Skip to content

Architecture ko

Hermes Agent edited this page Oct 1, 2026 · 1 revision

아키텍처

English | 中文 | 日本語 | 한국어 | Español | Português | Русский

browsa는 사이드 패널 채팅 UI를 가진 Chrome MV3 확장 프로그램이다. 확장 소스 코드에는 빌드 단계가 없다 — Chrome이 모든 JS 파일을 직접 로드한다; 유일한 빌드(build/build.mjs)는 벤더 라이브러리를 esbuild로 번들한다.

한 메시지의 여정

page content scripts (MAIN-world interceptors / ISOLATED-world selection toolbar)
        │  chrome.runtime.sendMessage / port
        ▼
background.js (service worker, single message router)
        │  handle() switch — case bodies live in lib/handlers/*
        ▼
sidepanel.js (the UI orchestrator)
        ▲
        ├── browsa-nav      long-lived port: NAVIGATED / XHS pushes / SELECTION_ACTION
        ├── browsa-chat     fresh per turn: main chat stream (chunk protocol)
        └── browsa-subchat  fresh per send: detail-thread stream
  • background.js는 유일한 chrome.runtime.onMessage 라우터이다. 하나의 handle() 스위치가 테스트가 임포트하는 단일 익스포트 디스패처로 남는다; 가장 큰 케이스 본문들은 lib/handlers/에 산다 (chat / subchat / session / attach 계열 / mermaid-repair / provider-resolver / approval-relay / agent-stream-session / prompt-assembly / site-cache-store …).
  • 스트림 상태(streamPorts / streamState / chatControllers / 승인 대기 Map들 …)는 lib/state.js에 한 번만 살고, background.js가 이를 재익스포트한다 — ../background.js에서 임포트하는 테스트는 같은 Map 인스턴스를 얻는다.

포트 수명 주기: 상시 vs 턴 단위 (의도된 차이)

  • browsa-nav는 장수명이다: 패널 init에서 한 번 연결되고, SW 재시작 후에는 connectNavPort() 패턴으로 재연결된다(1초 백오프; 새 포트 객체에는 모든 onMessage 리스너를 다시 붙여야 한다). 이 포트는 "패널이 지켜보는 탭 무엇이든"을 의미한다 — NAV_FOLLOW로 새 tabId 아래 재등록하는 것이 정확히 이 포트의 의미론이다.
  • browsa-chat / browsa-subchat은 턴마다 / 전송마다 새로 연다: 한 턴 = 한 포트. SW가 잠들어 생긴 끊김은 자가 치유가 필요 없다 — 다음 전송이 새 포트를 열면 된다. 의도된 설계: 한 턴의 수명 주기가 다음 턴으로 새어 나가지 않는다.

응답 엔벨로프 (역사적 버그 계열 — 어느 층을 읽고 있는지 확인하라)

  • 대부분의 핸들러: 성공 { ok: true, data } / 던진 에러 { ok: false, error, code, hint }.
  • 일부(APPROVAL_RESPOND / CLARIFY_RESPOND …)는 중계 실패를 내부에서 잡아 data 안에 내부 { ok, ... }를 반환한다.
  • 가정하기 전에 실제 케이스를 읽어라. 엔벨로프를 잘못 읽는 것은 2026-08 전 저장소 스윕에서 발견된 실제 버그의 한 계열 전체다 (예: LOAD_SESSION은 미스 시 -1을 반환한다 — 0은 합법적인 빈 세션이다; 내부 res.data.ok가 진짜 성공 플래그다).

세션 전환 시 백그라운드 스트림 (2026-09-24)

대화를 전환해도 실행 중인 턴은 취소되지 않는다. 한 줄 라우팅 규칙: 패널이 스트림을 지켜보는 동안 턴은 LIVE 히스토리에 쓰고(bg === false), 백그라운드로 가면 ORIGIN 세션의 스냅숏에 쓴다. persistTurnEntry가 단일 기록자다; REASSIGN_STREAM_SESSION(전환-이탈 시 자동 저장)과 STREAM_PEEK(복귀 시 재부착)만이 bg를 바꾸는 두 메시지다. 스트리밍 텍스트가 있는 중단 턴은 origin에 { interrupted: true }로 구제된다(Esc / 유휴 타임아웃 / 네트워크 끊김); 명시적 히스토리 파괴는 salvage: false를 쓴다.

MV3 서비스 워커 함정 (SW 측 코드를 쓰기 전에 읽어라)

  • SW는 ~30초 유휴 후 잠든다. 모듈 수준 Map은 재시작마다 리셋된다 — 영속 상태를 거기에 저장하지 마라.
  • SW 안의 setTimeout은 메시지 처리가 반환된 후에는 신뢰할 수 없다 — chrome.alarms나 chrome.storage.session을 써라.
  • 온디맨드 리스너 등록이 하우스 스타일이다: 세 개의 chrome.webNavigation 리스너는 navPort가 존재하는 동안에만 등록되고, tabs.onRemoved는 필요할 때 등록되며, 스트림-GC 알람은 streamState가 비어 있지 않은 동안에만 존재한다 — 그렇지 않으면 모든 내비게이션/탭 닫기가 no-op 하나 하려고 SW를 콜드 스타트한다(644KB 모듈 파싱).
  • chrome.storage.session은 브라우저 세션 안에서 SW 재시작을 넘어 살아남는다(사이트 캐시 복원, 대기 중인 SELECTION_ACTION …).

탭 전환

chrome.tabs.onActivated는 DOM을 건드려서는 안 된다 — Chrome은 탭 전환 전체에 걸쳐 사이드 패널 문서를 살아 있게 유지한다. currentTabId와 페이지-메타 텍스트를 갱신하고 NAV_FOLLOW를 보내라. 스트림 중단은 스트림 자신의 탭(streamTabIdOf())을 겨냥한다, 패널의 현재 탭이 아니다.

모듈 지도

경로 책임
background.js SW; handle() 디스패치 + 인라인 소형 케이스(ATTACH_PAGE …)
lib/handlers/* 큰 케이스 본문: chat / subchat / session / attach-* / approval-relay / provider-resolver / stream-dispatch / agent-stream-session / site-cache-store / attach-store / attach-modes
lib/state.js 스트림 상태 Map + pushChunk 프로토콜 + 터미널 톰스톤
lib/llm-client.js 와이어 프로토콜 층: 하나의 openSseStream() 골격 위의 네 스트림
lib/message-builder.js 프로바이더별 요청 형태 + ageStaleAttachments
lib/agent-turn.js / lib/image-budget.js 공유 에이전트-턴 층(텍스트/이미지 예산/백필)
lib/prompt-assembly.js CAPABILITY_HINTS_ENTRIES — 단일 렌더-계약 텍스트 소스
lib/storage.js chrome.storage.local 래퍼; 전역 히스토리 + 분할 세션 키
lib/sidepanel/* 26개 UI 측 모듈(렌더 파이프라인, 세션 드로어, 디테일 스레드, 타임라인 …)
lib/content-scripts/* MAIN 월드 사이트 인터셉터 + ISOLATED 선택 툴바; 사이트별 지식은 SITES.md
lib/page-extractor.js … 첨부/추출 층(reader/dom/full/auto 캐스케이드 + 사이트 빠른 경로 + PDF/Office/ASR 핸드오프)

원본 출처: AGENTS.md "Message flow", "Port lifecycle", "MV3 service worker gotchas", "Background streams across session switches" 절; CONTEXT.md 용어집. 권위판: Architecture(영어) / Architecture-zh(중국어) — AI 초벌 번역 스냅숏, 동기화 2026-10-01.

Clone this wiki locally