Skip to content

fix: stabilize browser extension tab group recovery#51

Open
1923213756 wants to merge 2 commits into
contrueCT:mainfrom
1923213756:private/fix-browser-tab-group-stability
Open

fix: stabilize browser extension tab group recovery#51
1923213756 wants to merge 2 commits into
contrueCT:mainfrom
1923213756:private/fix-browser-tab-group-stability

Conversation

@1923213756
Copy link
Copy Markdown
Collaborator

@1923213756 1923213756 commented May 12, 2026

描述 / Summary

修复浏览器扩展在 Nine1Bot 标签组场景下的稳定性问题,重点解决“标签组仍存在,但 runtime/bridge 识别不到标签页”的问题。
这次改动把标签组绑定从全局单例改成按窗口恢复,补上扩展侧 target/session 的权威重同步,以及 server 侧基于权威扫描结果的自愈与诊断信息,降低 sidepanel 重开、扩展重连、service worker 重启后的失联概率。

类型 / Type of change

  • Bug 修复 (bugfix)
  • 重构 (refactor)

关联的 issue(如果有)/ Related issues

/ 暂无 /

变更点 / What changed

  • 将浏览器扩展的活跃标签组绑定从单一 activeNine1TabGroupId 升级为按 windowId 存储的 activeNine1TabGroups,并保留旧存储键迁移逻辑。
  • 新增标签组恢复策略:优先使用有效存储绑定;若失效则扫描当前窗口 Nine1Bot* 标签组,并优先选择当前活动 tab 所在组,其次单一匹配组。
  • sidepanel 初始化不再每次无条件重绑标签组,只在当前窗口缺少有效绑定时才 ensure。
  • 扩展 relay sessionId 改为稳定值 tab_<tabId>,避免断连/重连后 target 身份漂移。
  • 新增扩展侧权威 resync 机制,按窗口对 managed tabs 执行 attach / detach / targetInfoChanged,同步替代原先全量 detach 再重建的粗暴逻辑。
  • 在 relay 连接成功、group 激活、tab 创建/关闭、group 变化、URL/标题变化、debugger detach 等场景触发重同步。
  • tabs_context_mcp 增强返回结果,补充 tabScanStatus、group diagnostics、reason code,显式区分 no_active_groupgroup_binding_staleno_automatable_tabs 等状态。
  • bridge/server 侧 browser_status 优先使用扩展权威扫描结果;当 relay cache 为空但权威 tab 列表可用时,自动重建 targets。
  • 仅在权威扫描失败时才回退 relay cache,并通过 runtime.issues 暴露 tab_scan_failed / relay_cache_fallback 等诊断码。
  • BrowserStatus.user 新增 tabListSource,模型侧 browser_status 输出会显示 tab 列表来源。
  • 改善 server 启动失败提示:端口占用时给出更明确的错误信息,并在主服务启动失败时清理已初始化的 browser bridge。
  • 新增回归测试,覆盖标签组恢复、旧存储迁移、稳定 session、自愈重建与 fallback 行为。

如何测试 / How to test

  1. 运行定向测试:
    bun test opencode/packages/opencode/test/server/listen-errors.test.ts packages/browser-extension/test/tab-group-manager.test.ts packages/browser-mcp-server/test/bridge-server.test.ts packages/browser-mcp-server/test/relay-routes.test.ts packages/browser-extension/test/server-config.test.ts
  2. 运行类型检查:
    cd packages/browser-extension && bun run typecheck
    cd packages/browser-mcp-server && bun run typecheck
  3. 手动验证浏览器扩展场景:
    打开带有 Nine1Bot 标签组的窗口,反复打开 sidepanel、重连扩展或触发 service worker 恢复,确认 browser_status 仍能识别已有 tabs,且不会因为 sidepanel 重开丢失当前窗口绑定。
  4. 预期结果:
    browser_status 能稳定返回用户浏览器 tabs;group 存在时可自动恢复;无有效 group / 无可自动化 tab 时返回明确诊断;端口占用时启动报错更明确。

截图(UI 变更时提供)/ Screenshots for UI changed

无重大 UI 改动。

Checklist(合并前请确认) / Checklist

  • 本地已通过测试

备注 / Notes for reviewers

建议重点看这几块:

  • packages/browser-extension/src/background/tab-group-manager.ts
    这里是标签组绑定模型和恢复策略的核心改动。
  • packages/browser-extension/src/background/relay-client.ts
    这里实现了稳定 sessionId 和权威 resync,是本次稳定性修复的关键路径。
  • packages/browser-mcp-server/src/bridge/server.ts
    这里补了 authoritative scan 优先、relay cache fallback、自愈重建和 runtime issue 输出。
  • packages/browser-mcp-server/src/bridge/relay-routes.ts
    这里补了 target 重建与 diagnostics 透传逻辑。

另外有一个和本次修复无关但在本地验证中暴露的问题:如果 127.0.0.1:4096 已被其他进程占用,dev:test 仍会启动失败;这次已把错误信息补得更明确,但没有改成自动切换端口策略。

fix issue:
[Bug] 浏览器插件页面识别不稳定问题 #50

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1efb3eed9b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/browser-extension/src/background/tab-group-manager.ts Outdated
Comment thread packages/browser-extension/src/background/tab-group-manager.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR stabilizes Nine1Bot browser extension tab-group recovery across reconnects/service worker restarts by making tab-group binding window-scoped, introducing authoritative resync/diagnostics from the extension, and improving server-side self-healing and startup error reporting.

Changes:

  • Browser extension: migrate active tab-group binding from a single global ID to per-window bindings with recovery heuristics + diagnostics payloads.
  • Relay/bridge server: prefer authoritative tabs_context_mcp scans, rebuild targets when relay cache is empty, expose tabListSource + runtime diagnostics/issues.
  • OpenCode server: improve listen/start failure messaging and add regression tests.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/nine1bot/src/launcher/server.ts Best-effort cleanup of browser bridge if main server fails to start.
packages/browser-mcp-server/test/bridge-server.test.ts Adds regression tests for authoritative target rebuild and relay-cache fallback.
packages/browser-mcp-server/src/core/types.ts Extends browser status/runtime types with tab list source + diagnostics payload.
packages/browser-mcp-server/src/bridge/server.ts Implements authoritative tab scan refresh, relay-cache fallback, and runtime issue propagation.
packages/browser-mcp-server/src/bridge/relay-routes.ts Adds stable session IDs + target upsert helper + exposes extension diagnostics via relay health.
packages/browser-extension/test/tab-group-manager.test.ts Adds recovery/migration regression tests for window-scoped bindings.
packages/browser-extension/src/tools/tabs.ts Enhances tabs_context_mcp output with scan status + diagnostics and clearer reason codes.
packages/browser-extension/src/sidepanel/index.ts Avoids unconditional re-binding; ensures group only if missing; reacts to new storage key.
packages/browser-extension/src/shared/tab-group.ts Introduces window-scoped binding types and diagnostics schemas.
packages/browser-extension/src/background/tab-group-manager.ts Core refactor: per-window bindings, recovery strategy, persistence + diagnostics APIs.
packages/browser-extension/src/background/relay-client.ts Stabilizes session IDs, adds authoritative resync mechanism + diagnostics emission.
packages/browser-extension/src/background/index.ts Propagates open nonce and supports “onlyIfMissing” tab-group ensure semantics.
opencode/packages/opencode/test/server/listen-errors.test.ts Adds regression tests for improved listen error formatting.
opencode/packages/opencode/src/tool/browser.ts Displays user tab list source in browser_status output.
opencode/packages/opencode/src/server/server.ts Adds formatListenError() and uses it when Bun serve fails.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/browser-mcp-server/src/bridge/server.ts
Comment thread packages/browser-mcp-server/src/bridge/relay-routes.ts
Comment thread packages/browser-extension/src/background/relay-client.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Comment on lines +223 to +227
for (const [windowKey, candidate] of Object.entries(value as Record<string, unknown>)) {
if (!candidate || typeof candidate !== 'object') continue
const record = candidate as Partial<ActiveNine1TabGroupBinding>
if (
typeof record.groupId !== 'number'
}

export function __resetTabGroupManagerStateForTests(): void {
cleanupInstalled = false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants