Maintenance notice: Browser Brain Loop vNext has passed the repo-side Level 2 cutover gate and is now the accepted replacement candidate for this old extension mainline. Start new replacement/cutover work from
catoncat/Snowyanddocs/vnext-cutover-record-2026-05-27.md; use this repository for maintenance, reference, and rollback archaeology unless a task explicitly targets old-mainline behavior.
这是一个可运行的 MVP:
- 浏览器侧(MV3 Extension)做 Planner + Loop Engine
- Service Worker 做 CDP Gateway + WS Client
- 本地 Bridge(Bun)提供
read/write/edit/bash - 支持
sessionId / parentSessionId / agentId,可并行子 agents
架构铁律:
- 大脑永远在浏览器侧(SidePanel + ServiceWorker + 浏览器内记忆)
- 本地 WS 只做执行代理(read/write/edit/bash),不做任务决策
文档入口:
- 总索引:
docs/README.md - vNext 切换记录:
docs/vnext-cutover-record-2026-05-27.md - 当前实现基线(必读):
docs/kernel-alignment-2026-02-25.md - 非 UI 架构蓝图:
docs/non-ui-architecture-blueprint.md - pi-mono runtime 对比:
docs/pi-mono-runtime-comparison.md - BDD 总览:
bdd/README.md
browser-brain-loop/
├── bridge/ # Bun 本地服务(ws://127.0.0.1:8787)
├── extension/ # MV3 扩展(SidePanel + Service Worker)
├── bdd/ # BDD 契约/特性/映射/门禁配置
└── tools/ # bdd:validate / bdd:gate 等脚本
首次环境准备(必做):
bun install
cd bridge && bun install
cd extension && bun install && bun run build- 一条命令启动(推荐)
在仓库根目录执行:
BRIDGE_TOKEN="replace-me" bun run brain:dev它会同时启动 bridge + extension watcher。
若检测到已有 bridge,会自动复用并继续启动 watcher。
- 启动 bridge(手动模式)
cd bridge
bun install
BRIDGE_TOKEN="replace-me" bun run start- 加载扩展
- 打开
chrome://extensions - 开启开发者模式
- 选择“加载已解压的扩展程序”
- 目录选
extension
- 在 SidePanel 填配置
Bridge URL:ws://127.0.0.1:8787/wsBridge Token: 与环境变量一致- 必填 LLM(当前缺配置会直接
failed_execute):LLM Base:https://ai.chen.rs/v1LLM Key:<your-api-key>Model:gpt-5.3-codex
- 启动扩展自动热重载(可选,开发推荐)
BRIDGE_TOKEN="replace-me" bun run brain:ext:watch当 extension/ 文件变化时,会自动 bump bridge 版本号,扩展检测到版本变化后自动 chrome.runtime.reload()。
当前 watcher 流程为:检测变更 -> 自动执行 extension build -> bump version -> reload。
为避免循环触发,watcher 默认忽略 extension/dist/** 与 extension/node_modules/**。
当前仓库已启用 BDD 分层门禁:契约先行 + 证据校验(all/ux/protocol/storage)。
会话中断续跑说明见:bdd/SESSION-HANDOFF.md
BDD 索引说明见:bdd/README.md
目录约定:
bdd/
├── schemas/behavior-contract.schema.json # 契约 schema
├── contracts/ # Canonical behavior contracts
├── mappings/contract-categories.json # 契约分类(ux/protocol/storage)
├── features/business/ # 业务语义 feature(ux)
├── features/technical/ # 技术语义 feature(protocol/storage)
└── mappings/contract-to-tests.json # 契约到证明层映射
关键规则:
- 每个行为契约 ID 必须唯一,格式:
BHV-... - 每个契约必须至少被一个
.feature的@contract(...)引用 - 每个契约必须在
contract-categories.json有且仅有一个分类(ux|protocol|storage) - 每个契约必须在
contract-to-tests.json有映射,且满足proof_requirements.required_layers/min_layers - gate 采用严格失败策略:任何契约缺失/映射不完整/目标路径不存在都会失败
- 对
bdd/evidence/*.json的e2e证明层,gate 会检查passed=true,并支持path::selector命中校验
命令:
bun run brain:e2e
bun run brain:e2e:live # 真实 LLM 冒烟(默认读取 .env.live.local)
bun run bdd:lint:features
bun run bdd:validate
bun run bdd:gate
bun run bdd:gate:ux
bun run bdd:gate:protocol
bun run bdd:gate:storage
bun run bdd:gate:live # 检查 live profile 契约brain:e2e 会启动临时 bridge + 临时 Chrome(加载当前 extension),并分两组执行:
- Service-worker API 组:
cdp.snapshot/cdp.action/lease.*/cdp.verify - Sidepanel loop 组:
MAX_STEPS/MAX_WALL_MS护栏 - Live LLM 组(开启
BRAIN_E2E_ENABLE_LIVE_LLM=true时):真实模型能力冒烟(按成功率阈值判定)
关键断言:
snapshot(mode=interactive|full)必须返回可引用 A11y 节点:nodes[*].ref/role/name/depth(可兼容nodeId/backendNodeId句柄)snapshot(format=compact, maxTokens=...)必须返回低噪紧凑文本,并提供truncated状态cdp.action所有写动作都走lease.acquire(owner) -> cdp.action(owner) -> lease.release(owner)cdp.verify支持urlChanged/urlContains/titleContains/textIncludes/selectorExistsref行为分两类验证:- ref 存在但句柄过期:应可 fallback
- ref 不存在:按现状返回
ref ... not found
- sidepanel 在
stopped状态下优先返回状态文案,不应回显大段 snapshot JSON - sidepanel 的 LLM 能力门禁:
- LLM 可用时可完成
tool_call -> tool_result -> done闭环 - 缺少 LLM 配置时应返回
failed_execute(reason=missing_llm_config) - LLM HTTP 失败按 retryable 语义重试;超限或不可重试时返回
failed_execute - 不再以规则 planner 作为“成功降级”路径
- LLM 可用时可完成
- sidepanel 的真实 LLM 能力冒烟(live suite):
- 在浏览器任务上进行多次尝试并用
cdp.verify断言结果 - 通过阈值:
passedAttempts >= minPass(默认ceil(attempts*0.67))
- 在浏览器任务上进行多次尝试并用
运行后会产出证据文件:
bdd/evidence/brain-e2e.latest.json
bdd:gate 会根据 bdd/mappings/contract-to-tests.json 对所有声明了 e2e 证明层的契约校验 passed=true(以及可选 selector 命中)。
bdd:gate:live 还会额外检查 BHV-LLM-LIVE-CAPABILITY,读取 bdd/evidence/brain-e2e-live.latest.json。
运行 live 套件示例:
# .env.live.local 示例
# BRAIN_E2E_LIVE_LLM_BASE="https://ai.chen.rs/v1"
# BRAIN_E2E_LIVE_LLM_KEY="<key>"
# BRAIN_E2E_LIVE_LLM_MODEL="gpt-5.3-codex"
bun run brain:e2e:live
bun run bdd:gate:live注意:品牌版 Google Chrome 会忽略
--load-extension/--disable-extensions-except。
默认建议使用Chrome for Testing或Chromium。必要时可手动指定:CHROME_BIN="/path/to/chrome-for-testing" bun run brain:e2e
vNext 已切到 sidepanel.html + service-worker.js 主路径:
- 旧入口已移除:
extension/harness.html、extension/sidepanel.js extension/service-worker.js已收口为 shim,运行逻辑在extension/src/sw/kernel/*(构建到extension/dist/service-worker.js)- 运行链路已支持:
brain.run.start -> LLM(tool_calls) -> executeBrainToolCall -> tool result 回灌 -> 下一轮 brain.step.execute已从占位实现改为真实执行(script/cdp/bridge+ verify)- 主 sidepanel 已重构为聊天产品界面(多会话、会话内连续发送、设置抽屉)
- 调试能力迁移到独立页面:
extension/debug.html(Live Events / Step Stream / Debug Dump) - LLM 请求前统一消息 transform(tool_call/tool_result 配对、tool_call_id 归一)
brain.step.stream/brain.debug.dump支持maxEvents/maxBytes限流并返回streamMetallm.response.raw已瘦身为bodyPreview/bodyLength/bodyTruncated,避免大 payload 进入 trace- e2e 已覆盖 sidepanel + debug 工作台,并断言
brain.runtime可观测性(llm.request/llm.response.raw/auto_retry_*)
当前校验方式:
bun run brain:ext:buildbun run brain:ext:testbun run brain:e2ebun run bdd:validate && bun run bdd:gatebun run bdd:gate:ux(UX 分层校验)bun run bdd:gate:protocol(协议分层校验)bun run bdd:gate:storage(存储分层校验)
统一 invoke:
{
"id": "u1",
"type": "invoke",
"tool": "read",
"args": { "path": "src/a.ts" },
"sessionId": "s-main",
"parentSessionId": "s-root",
"agentId": "child-1"
}成功:
{ "id": "u1", "ok": true, "data": { "content": "..." }, "sessionId": "s-main" }失败:
{ "id": "u1", "ok": false, "error": { "code": "E_PATH", "message": "denied" } }事件帧:
{ "type": "event", "event": "invoke.started", "id": "u1", "sessionId": "s-main", "ts": "..." }read(path, offset?, limit?, cwd?)write(path, content, mode=overwrite|append|create, cwd?)edit(path, edits, cwd?)bash(cmdId, args, cwd?, timeoutMs?)
bash 仅允许白名单 cmdId,映射见 bridge/src/cmd-registry.ts。
cmdId=bash.exec 默认开启(无限能力);如需临时收紧,可设置 BRIDGE_ENABLE_BASH_EXEC=false。
cdp.snapshot:A11y-first 分级观测,支持参数:mode:text|interactive|fullfilter:interactive|allformat:compact|jsondiff: 是否返回快照差异maxTokens/depth/selector/noAnimations- 返回:
snapshotId/ts/url/title/count/truncated/hash/diff/compact + nodes[*].ref/role/name/depth(兼容nodeId/backendNodeId)
cdp.action:支持ref或selector的页面动作(click/type/fill/press/scroll/select/navigate),ref优先,selector回退cdp.verify:对 URL/title/text/selector 断言,支持urlChanged(可传previousUrl)lease.acquire|heartbeat|release|status:tab 写操作租约(owner + ttl)
- LLM 工具入参不再直接喂原始大 snapshot JSON;优先使用
snapshot.compact + 关键元信息,避免二次硬截断导致关键信息丢失。 - 在 strict 策略下,
browser_action执行后默认必须通过验证(显式expect走cdp.verify,否则走前后观测推进校验)。 - 语义分层:
loop_done.status是终态域:done | failed_execute | failed_verify | progress_uncertain | max_steps | stopped | timeoutFailureReason是失败子域:failed_execute | failed_verify | progress_uncertainbrain.agent.end/handleAgentEnd()是决策域:continue | retry | donehandleAgentEnd(action=done)时,reason应直接复用 canonical terminal status / failure reason;continue仅用于compaction_overflow|compaction_threshold
- ownership 分层:
thresholdcompaction 由runtime-loop在发 LLM 前触发preSendCompactionCheck()overflowcompaction 由外部brain.agent.end输入上报,再由orchestrator.handleAgentEnd()触发
- 新增
no_progress检测:当 action 签名连续重复或 ABAB 往返(ping-pong)时提前终止本轮。 - auto-repair 仅在
failed_execute | failed_verify | progress_uncertain或显式loop_no_progress信号时触发;max_steps | stopped | timeout不自动开启下一轮。 - 回复策略中,
stopped/timeout/max_steps/failed_*状态文案优先于 memory 回填。
- 每个 loop 有独立
sessionId - 子 agent 运行时设置
parentSessionId=<父会话>+ 独立agentId - SidePanel 支持 JSON 数组批量派生子 agents,并可设置并发上限
即使是 god mode(无限能力)也保留:
MAX_STEPS/MAX_WALL_MSbash timeoutmaxConcurrency- 输出截断
- 全量审计(JSONL)
- SidePanel 支持
AUTO_REPAIR_ROUNDS+自动修复(on/off) - 仅在
failed_execute/failed_verify/progress_uncertain(或loop_no_progress)时会把失败摘要写入下一轮 goal 并尝试修复 max_steps/stopped/timeout默认不进入下一轮 repair- 对“提前 done”有拦截(无成功动作时不允许 done)
ssh -N -L 8787:127.0.0.1:8787 <host>然后扩展仍连接 ws://127.0.0.1:8787/ws。