Skip to content

refactor: yobrowser tools#1357

Merged
zerob13 merged 4 commits intodevfrom
refactor/yobrowser-tools
Mar 17, 2026
Merged

refactor: yobrowser tools#1357
zerob13 merged 4 commits intodevfrom
refactor/yobrowser-tools

Conversation

@zerob13
Copy link
Copy Markdown
Collaborator

@zerob13 zerob13 commented Mar 17, 2026

Summary by CodeRabbit

  • New Features

    • Per-conversation session browser in the side panel with independent lifecycle.
    • New, simplified agent tools: load_url, get_browser_status, cdp_send (cdp_send requires an initialized session).
  • Bug Fixes

    • Improved offload filename sanitization for Windows paths.
    • More stable floating-button drag/layout behavior during animations.
  • Refactor

    • Consolidated browser UI into session sidepanel; standalone in-app browser removed.
    • Tool routing and presenter flows migrated to session-aware model.
  • Documentation

    • Updated architecture and spec docs for session-based browser behavior.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 17, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eaa00a15-910b-49ec-ac49-145ca1858259

📥 Commits

Reviewing files that changed from the base of the PR and between 4afc874 and c1e10f6.

📒 Files selected for processing (3)
  • src/main/lib/agentRuntime/sessionPaths.ts
  • test/main/lib/agentRuntime/sessionPaths.test.ts
  • test/main/presenter/floatingButtonPresenter/index.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/main/presenter/floatingButtonPresenter/index.test.ts

📝 Walkthrough

Walkthrough

The PR converts YoBrowser from a multi-window model to a session-scoped single-instance sidepanel, reduces tools to load_url, get_browser_status, and cdp_send, removes the standalone browser renderer, and introduces session-based presenter APIs and session-aware renderer plumbing.

Changes

Cohort / File(s) Summary
Docs & Specs
docs/architecture/tool-system.md, docs/specs/yobrowser-optimization/plan.md, docs/specs/yobrowser-optimization/spec.md, docs/specs/yobrowser-optimization/tasks.md
Added session-single-instance design, tooling (load_url/get_browser_status/cdp_send), lifecycle rules, tasks, and acceptance criteria.
Core Presenter & Tools
src/main/presenter/browser/YoBrowserPresenter.ts, src/main/presenter/browser/YoBrowserToolDefinitions.ts, src/main/presenter/browser/YoBrowserToolHandler.ts, src/main/presenter/browser/BrowserContextBuilder.ts
Replaced window-centric model with SessionBrowserState; introduced session APIs (loadUrl, getBrowserStatus, attach/detach/update/destroy session browser); reduced tool set and exported YO_BROWSER_TOOL_NAMES.
Agent/Tool Routing & Offload
src/main/presenter/agentPresenter/acp/agentToolManager.ts, src/main/presenter/agentPresenter/loop/toolCallProcessor.ts, src/main/presenter/deepchatAgentPresenter/toolOutputGuard.ts, src/main/presenter/toolPresenter/index.ts
Switched routing from yo_browser_* prefix to explicit YO_BROWSER_TOOL_NAMES set; renamed offload whitelist to include cdp_send; filter MCP tools that conflict with reserved YoBrowser names.
Shared Types & Presenter Interfaces
src/shared/types/browser.ts, src/shared/types/presenters/legacy.presenters.d.ts
Introduced YoBrowserStatus, removed legacy BrowserWindow/Tab/Context types, and updated presenter interface methods to be session-scoped (sessionId parameters) and to accept an optional conversationId on tool calls.
Renderer Consolidation
src/renderer/browser/*, src/renderer/browser/stores/window.ts, src/renderer/browser/lib/events.ts, src/renderer/browser/index.html, electron.vite.config.ts
Removed standalone browser renderer, components, store, and events; removed @browser alias and separate browser build entry, consolidating UI into sidepanel.
Sidepanel Integration
src/renderer/src/components/sidepanel/BrowserPanel.vue, src/renderer/src/components/sidepanel/ChatSidePanel.vue, src/renderer/src/components/sidepanel/BrowserPlaceholder.vue
Made BrowserPanel session-aware (added sessionId prop), switched to session presenter calls, added pending-destroy/session cleanup logic, and tightened open-request validation by sessionId.
Window/Tab Presenter Changes
src/main/presenter/windowPresenter/index.ts, src/main/presenter/tabPresenter.ts, src/main/presenter/newAgentPresenter/index.ts
Stop creating standalone browser windows (use chat shell), removed TabPresenter.setTabBrowserId, added legacy tool name mapping for disabled-agent-tool normalization.
Floating Widget
src/main/presenter/floatingButtonPresenter/index.ts
Added drag stabilization: snapshot bounds, width/height in drag state, isDragging flag, and pending layout sync to defer layout changes during drag.
Offload Path Sanitization & Tests
src/main/lib/agentRuntime/sessionPaths.ts, test/main/lib/agentRuntime/sessionPaths.test.ts
Added sanitizeToolCallIdForOffload with Windows-invalid-char handling and fingerprinting for offload filenames; tests added for sanitization behavior.
Tests Updated
various test/* files (YoBrowserPresenter, YoBrowserToolHandler, deepchat/newAgent/toolPresenter, renderer BrowserPanel/McpIndicator/NewThreadPage, floatingButtonPresenter tests, etc.)
Updated tests to session-based API and new tool names (load_url, get_browser_status, cdp_send); added/updated tests for handler behaviors and drag layout; adjusted offload id expectations.

Sequence Diagram

sequenceDiagram
    participant Agent as Agent/Tool Loop
    participant Manager as AgentToolManager
    participant Handler as YoBrowserToolHandler
    participant Presenter as YoBrowserPresenter
    participant State as SessionBrowserState
    participant Renderer as BrowserPanel

    Agent->>Manager: callTool(toolName, args, conversationId)
    Manager->>Manager: is toolName in YO_BROWSER_TOOL_NAMES?
    Manager->>Handler: route to YoBrowserToolHandler
    Handler->>Presenter: derive sessionId from conversationId
    alt load_url
        Handler->>Presenter: loadUrl(sessionId, url)
        Presenter->>State: ensureSessionBrowserState(sessionId)
        Presenter->>State: create/attach view, await host readiness
        Presenter->>State: navigate to URL
        Presenter-->>Handler: YoBrowserStatus
    else get_browser_status
        Handler->>Presenter: getBrowserStatus(sessionId)
        Presenter-->>Handler: YoBrowserStatus
    else cdp_send
        Handler->>Presenter: getBrowserPage(sessionId)
        Presenter->>State: return page
        Handler->>Presenter: sendCdpCommand(sessionId, method, params)
        Presenter-->>Handler: CDP response
    end
    Handler-->>Agent: return stringified result
    Presenter->>Renderer: emit WINDOW_CREATED / WINDOW_UPDATED with sessionId
    Renderer->>Renderer: update UI for provided sessionId
Loading

Estimated Code Review Effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly Related PRs

Poem

🐰 I hopped through sessions, one by one,

One sidepanel browser, the job well done.
load_url, status, cdp in a line,
No extra windows — the state’s now fine.
A tidy burrow for code to run!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'refactor: yobrowser tools' accurately describes the main change—a comprehensive refactoring of YoBrowser tools from legacy names (yo_browser_*) to new simplified names (load_url, get_browser_status, cdp_send), with accompanying session-based architecture updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/yobrowser-tools
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 4afc8747c7

ℹ️ 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".

throw new Error('url is required')
}

const hostWindowId = this.resolveHostWindowId()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Resolve host window from session before load_url

loadUrl picks the host via resolveHostWindowId() (focused/first window) instead of the window bound to sessionId. In multi-window usage, if session A is executing while window B is focused, the open event is emitted with B’s windowId; ChatSidePanel.handleBrowserOpenRequested requires both sessionId and windowId to match, so neither window attaches the browser and waitForSessionHostReady times out. This makes load_url (and subsequent cdp_send) fail for background sessions even though the session is valid.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (5)
src/main/presenter/windowPresenter/index.ts (1)

521-527: createBrowserWindow now behaves like chat-window creation; consider deprecating this API name.

This now always creates a chat shell, so the method name can mislead callers and future maintenance. A deprecation annotation (or redirect to createAppWindow) would make intent explicit.

♻️ Minimal clarity refactor
+  /**
+   * `@deprecated` Standalone browser shell was removed. Use createAppWindow().
+   */
   public async createBrowserWindow(options?: { x?: number; y?: number }): Promise<number | null> {
-    return await this.createManagedWindow({
-      windowType: 'chat',
-      x: options?.x,
-      y: options?.y
-    })
+    return await this.createAppWindow({
+      initialRoute: 'chat',
+      x: options?.x,
+      y: options?.y
+    })
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/presenter/windowPresenter/index.ts` around lines 521 - 527, The
public method createBrowserWindow currently always delegates to
createManagedWindow with windowType:'chat', which makes the name misleading;
mark createBrowserWindow as deprecated and either redirect callers to
createAppWindow or change createBrowserWindow to call createAppWindow (or proxy
to it) and add a JSDoc `@deprecated` note plus console/process deprecation
warning; update callers to use createAppWindow and keep createBrowserWindow as a
thin shim that forwards to createAppWindow (or to createManagedWindow with
explicit comment) so intent is explicit.
test/main/presenter/newAgentPresenter/newAgentPresenter.test.ts (1)

1004-1045: Add one regression test for legacy disabled-tool IDs.

These assertions cover canonical cdp_send, but not the new yo_browser_cdp_send -> cdp_send normalization path. A focused case would lock migration safety.

Proposed test addition
+  it('normalizes legacy YoBrowser disabled tool ids', async () => {
+    sqlitePresenter.newSessionsTable.get.mockReturnValue({
+      id: 's1',
+      agent_id: 'deepchat',
+      title: 'Test',
+      project_dir: null,
+      is_pinned: 0,
+      created_at: 1000,
+      updated_at: 1000
+    })
+
+    const disabledTools = await presenter.updateSessionDisabledAgentTools('s1', [
+      'yo_browser_cdp_send',
+      'exec'
+    ])
+
+    expect(disabledTools).toEqual(['cdp_send', 'exec'])
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/main/presenter/newAgentPresenter/newAgentPresenter.test.ts` around lines
1004 - 1045, Add a regression test that verifies legacy tool IDs are normalized
to the canonical ID (yo_browser_cdp_send -> cdp_send) when updating or reading
disabled agent tools: in the existing test block for disabled agent tools, mock
sqlitePresenter.newSessionsTable.get to return the session and then call
presenter.updateSessionDisabledAgentTools with an array containing the legacy ID
"yo_browser_cdp_send" (and possibly duplicates), assert the returned disabled
list contains "cdp_send" (not the legacy ID) and that
sqlitePresenter.newSessionsTable.updateDisabledAgentTools was called with the
normalized array; also add a complementary call to
presenter.getSessionDisabledAgentTools (or mock getDisabledAgentTools to include
legacy IDs) to assert that getSessionDisabledAgentTools performs the same
normalization path.
src/main/presenter/browser/YoBrowserPresenter.ts (1)

540-564: Consider cleaning up host window listeners when no sessions are attached.

detachOtherSessionBrowsers and detachFromWindow properly detach sessions from windows, but detachHostWindowListeners is only called in the closed listener callback. If all sessions are detached from a window (but the window remains open), the listeners persist.

This is likely acceptable since the listeners are lightweight and will be cleaned up when the window closes, but for completeness:

♻️ Optional cleanup enhancement
 private detachFromWindow(state: SessionBrowserState, hostWindowId: number): void {
   const window = BrowserWindow.fromId(hostWindowId)
   if (window && !window.isDestroyed()) {
     try {
       window.contentView.removeChildView(state.view)
     } catch {
       // Ignore already detached view.
     }
   }
   state.attachedWindowId = null
+
+  // Clean up listeners if no sessions remain attached to this window
+  if (!this.findAttachedStateByWindowId(hostWindowId)) {
+    this.detachHostWindowListeners(hostWindowId)
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/presenter/browser/YoBrowserPresenter.ts` around lines 540 - 564, The
detach methods remove session views but never remove the host window's event
listeners unless the window is closed; update detachFromWindow (and/or
detachOtherSessionBrowsers) to detect when no more SessionBrowserState entries
have attachedWindowId === hostWindowId after setting state.attachedWindowId =
null and then call detachHostWindowListeners(hostWindowId) to remove listeners
for that window; use the existing functions detachFromWindow,
detachOtherSessionBrowsers, and detachHostWindowListeners identifiers to locate
where to add the check so listeners are cleaned up when the last session
detaches while the window remains open.
src/renderer/src/components/sidepanel/BrowserPanel.vue (1)

514-522: Consider using a more explicit watch source for session status changes.

The current approach creates a dependency string by joining session IDs and statuses. While functional, this pattern recalculates on every sessionStore change even if unrelated properties change.

A more explicit approach would be to watch the specific data needed:

♻️ Alternative approach
 watch(
-  () => sessionStore.sessions.map((session) => `${session.id}:${session.status}`).join('|'),
+  () => sessionStore.sessions.map((session) => ({ id: session.id, status: session.status })),
   () => {
     void flushPendingSessionDestroys()
     if (currentSessionId.value) {
       void loadState(currentSessionId.value)
     }
-  }
+  },
+  { deep: true }
 )

This is a minor stylistic preference - the current implementation works correctly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/src/components/sidepanel/BrowserPanel.vue` around lines 514 -
522, Replace the synthetic dependency string in the watch with an explicit
watcher over the exact values you care about: instead of () =>
sessionStore.sessions.map(...).join('|'), watch a function that returns the
array of tuples or objects containing only id and status (e.g.,
sessionStore.sessions.map(s => [s.id, s.status]) or map to {id,status}) so the
watcher only reacts to id/status changes; keep the body calling
flushPendingSessionDestroys(), and when currentSessionId.value is set call
loadState(currentSessionId.value) as before (refer to watch,
sessionStore.sessions, flushPendingSessionDestroys, currentSessionId, and
loadState).
src/main/presenter/browser/YoBrowserToolHandler.ts (1)

43-64: Potential redundant check and inconsistent error handling in cdp_send.

The getBrowserPage check (lines 43-46) verifies session initialization, but sendCdpCommand (line 50) will also throw if the session doesn't exist. This creates two potential issues:

  1. The error message "not initialized" at line 45 may be misleading if the session was destroyed between calls.
  2. The page object retrieved at line 43 is only used for logging metadata (lines 58-60) but not for the actual CDP command execution.

Consider consolidating the validation into sendCdpCommand and catching the specific error for logging:

♻️ Suggested refactor
       case 'cdp_send': {
         const method = typeof args.method === 'string' ? args.method : ''
         if (!method) {
           throw new Error('CDP method is required')
         }

-        const page = await this.presenter.getBrowserPage(sessionId)
-        if (!page) {
-          throw new Error(`Session browser for ${sessionId} is not initialized`)
-        }
-
         try {
           const params = this.normalizeCdpParams(args.params)
           const response = await this.presenter.sendCdpCommand(sessionId, method, params)
           return JSON.stringify(response ?? {})
         } catch (error) {
           if (error instanceof Error && error.name === 'YoBrowserNotReadyError') {
+            const page = await this.presenter.getBrowserPage(sessionId)
             logger.warn('[YoBrowser] tool blocked:not-ready', {
               toolName: 'cdp_send',
               sessionId,
               method,
-              pageId: page.id,
-              url: page.url,
-              status: page.status
+              pageId: page?.id,
+              url: page?.url,
+              status: page?.status
             })
           }
           throw error
         }
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/presenter/browser/YoBrowserToolHandler.ts` around lines 43 - 64,
Remove the initial getBrowserPage() null-check and let sendCdpCommand(sessionId,
method, params) perform session validation; call
this.presenter.sendCdpCommand(...) directly after normalizing params. In the
catch block, specifically handle Error with name 'YoBrowserNotReadyError' by
then calling this.presenter.getBrowserPage(sessionId) to retrieve page metadata
for logging (guarding for null and only including page.id/url/status when
available) instead of relying on the earlier page variable; keep throwing the
original error after logging. Ensure references: normalizeCdpParams,
sendCdpCommand, getBrowserPage, YoBrowserNotReadyError, and the page fields (id,
url, status) are used as described.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/architecture/tool-system.md`:
- Line 636: Update the docs line that currently references
BrowserTab.ensureSession(): replace that stale implementation pointer with a
reference to the session-scoped CDP guard used in the presenter/tool handler
path (i.e., point readers to the presenter/tool handler CDP guard instead of
BrowserTab.ensureSession()). Locate the old mention of
BrowserTab.ensureSession() in the sentence and change it to explicitly reference
the presenter/tool-handler session guard (the guard implemented in the
presenter/tool handler path) so the doc points to the current code location.

In `@src/main/lib/agentRuntime/sessionPaths.ts`:
- Around line 48-60: The sanitizeToolCallIdForOffload function currently
collates multiple disallowed characters into '_' causing distinct toolCallId
values (e.g., "tool:1" vs "tool/1") to collide; update
sanitizeToolCallIdForOffload to append a short deterministic fingerprint of the
original toolCallId (for example a truncated hex of a hash like SHA-1/MD5/CRC32)
to the sanitized name so that different inputs that sanitize to the same
characters still produce unique filenames, while continuing to replace invalid
chars and trim trailing invalid characters; ensure the appended fingerprint only
contains filesystem-safe characters and fall back to 'tool_call' if the final
result would be empty.

In `@test/main/presenter/floatingButtonPresenter/index.test.ts`:
- Around line 71-100: The inline class declaration for BrowserWindow inside the
vi.mock('electron', ...) object causes a Biome parse error; extract the class
declaration to module scope (e.g., declare class BrowserWindow {} above the
vi.mock call) and then reference that class name in the mock object instead of
declaring it inline, ensuring the mock still exports BrowserWindow, ipcMain,
screen, Menu, and app as before (update any type annotations or imports if
needed to use the new BrowserWindow symbol).

---

Nitpick comments:
In `@src/main/presenter/browser/YoBrowserPresenter.ts`:
- Around line 540-564: The detach methods remove session views but never remove
the host window's event listeners unless the window is closed; update
detachFromWindow (and/or detachOtherSessionBrowsers) to detect when no more
SessionBrowserState entries have attachedWindowId === hostWindowId after setting
state.attachedWindowId = null and then call
detachHostWindowListeners(hostWindowId) to remove listeners for that window; use
the existing functions detachFromWindow, detachOtherSessionBrowsers, and
detachHostWindowListeners identifiers to locate where to add the check so
listeners are cleaned up when the last session detaches while the window remains
open.

In `@src/main/presenter/browser/YoBrowserToolHandler.ts`:
- Around line 43-64: Remove the initial getBrowserPage() null-check and let
sendCdpCommand(sessionId, method, params) perform session validation; call
this.presenter.sendCdpCommand(...) directly after normalizing params. In the
catch block, specifically handle Error with name 'YoBrowserNotReadyError' by
then calling this.presenter.getBrowserPage(sessionId) to retrieve page metadata
for logging (guarding for null and only including page.id/url/status when
available) instead of relying on the earlier page variable; keep throwing the
original error after logging. Ensure references: normalizeCdpParams,
sendCdpCommand, getBrowserPage, YoBrowserNotReadyError, and the page fields (id,
url, status) are used as described.

In `@src/main/presenter/windowPresenter/index.ts`:
- Around line 521-527: The public method createBrowserWindow currently always
delegates to createManagedWindow with windowType:'chat', which makes the name
misleading; mark createBrowserWindow as deprecated and either redirect callers
to createAppWindow or change createBrowserWindow to call createAppWindow (or
proxy to it) and add a JSDoc `@deprecated` note plus console/process deprecation
warning; update callers to use createAppWindow and keep createBrowserWindow as a
thin shim that forwards to createAppWindow (or to createManagedWindow with
explicit comment) so intent is explicit.

In `@src/renderer/src/components/sidepanel/BrowserPanel.vue`:
- Around line 514-522: Replace the synthetic dependency string in the watch with
an explicit watcher over the exact values you care about: instead of () =>
sessionStore.sessions.map(...).join('|'), watch a function that returns the
array of tuples or objects containing only id and status (e.g.,
sessionStore.sessions.map(s => [s.id, s.status]) or map to {id,status}) so the
watcher only reacts to id/status changes; keep the body calling
flushPendingSessionDestroys(), and when currentSessionId.value is set call
loadState(currentSessionId.value) as before (refer to watch,
sessionStore.sessions, flushPendingSessionDestroys, currentSessionId, and
loadState).

In `@test/main/presenter/newAgentPresenter/newAgentPresenter.test.ts`:
- Around line 1004-1045: Add a regression test that verifies legacy tool IDs are
normalized to the canonical ID (yo_browser_cdp_send -> cdp_send) when updating
or reading disabled agent tools: in the existing test block for disabled agent
tools, mock sqlitePresenter.newSessionsTable.get to return the session and then
call presenter.updateSessionDisabledAgentTools with an array containing the
legacy ID "yo_browser_cdp_send" (and possibly duplicates), assert the returned
disabled list contains "cdp_send" (not the legacy ID) and that
sqlitePresenter.newSessionsTable.updateDisabledAgentTools was called with the
normalized array; also add a complementary call to
presenter.getSessionDisabledAgentTools (or mock getDisabledAgentTools to include
legacy IDs) to assert that getSessionDisabledAgentTools performs the same
normalization path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1dfcc6cc-f984-4740-9937-20999e22279e

📥 Commits

Reviewing files that changed from the base of the PR and between 79b08f5 and 4afc874.

📒 Files selected for processing (47)
  • docs/architecture/tool-system.md
  • docs/specs/yobrowser-optimization/plan.md
  • docs/specs/yobrowser-optimization/spec.md
  • docs/specs/yobrowser-optimization/tasks.md
  • electron.vite.config.ts
  • src/main/lib/agentRuntime/sessionPaths.ts
  • src/main/presenter/agentPresenter/acp/agentToolManager.ts
  • src/main/presenter/agentPresenter/loop/toolCallProcessor.ts
  • src/main/presenter/browser/BrowserContextBuilder.ts
  • src/main/presenter/browser/YoBrowserPresenter.ts
  • src/main/presenter/browser/YoBrowserToolDefinitions.ts
  • src/main/presenter/browser/YoBrowserToolHandler.ts
  • src/main/presenter/deepchatAgentPresenter/toolOutputGuard.ts
  • src/main/presenter/floatingButtonPresenter/index.ts
  • src/main/presenter/newAgentPresenter/index.ts
  • src/main/presenter/tabPresenter.ts
  • src/main/presenter/toolPresenter/index.ts
  • src/main/presenter/windowPresenter/index.ts
  • src/renderer/browser/App.vue
  • src/renderer/browser/components/AppBar.vue
  • src/renderer/browser/components/BrowserToolbar.vue
  • src/renderer/browser/components/icons/CloseIcon.vue
  • src/renderer/browser/components/icons/MaximizeIcon.vue
  • src/renderer/browser/components/icons/MinimizeIcon.vue
  • src/renderer/browser/components/icons/RestoreIcon.vue
  • src/renderer/browser/index.html
  • src/renderer/browser/lib/events.ts
  • src/renderer/browser/main.ts
  • src/renderer/browser/stores/window.ts
  • src/renderer/src/components/sidepanel/BrowserPanel.vue
  • src/renderer/src/components/sidepanel/BrowserPlaceholder.vue
  • src/renderer/src/components/sidepanel/ChatSidePanel.vue
  • src/shared/types/browser.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • test/main/lib/agentRuntime/sessionPaths.test.ts
  • test/main/presenter/YoBrowserPresenter.test.ts
  • test/main/presenter/agentPresenter/loop/toolCallProcessor.test.ts
  • test/main/presenter/browser/YoBrowserToolHandler.test.ts
  • test/main/presenter/deepchatAgentPresenter/deepchatAgentPresenter.test.ts
  • test/main/presenter/deepchatAgentPresenter/dispatch.test.ts
  • test/main/presenter/deepchatAgentPresenter/process.test.ts
  • test/main/presenter/floatingButtonPresenter/index.test.ts
  • test/main/presenter/newAgentPresenter/newAgentPresenter.test.ts
  • test/main/presenter/toolPresenter/toolPresenter.test.ts
  • test/renderer/components/BrowserPanel.test.ts
  • test/renderer/components/McpIndicator.test.ts
  • test/renderer/components/NewThreadPage.test.ts
💤 Files with no reviewable changes (13)
  • electron.vite.config.ts
  • src/main/presenter/tabPresenter.ts
  • src/renderer/browser/lib/events.ts
  • src/renderer/browser/components/icons/RestoreIcon.vue
  • src/renderer/browser/index.html
  • src/renderer/browser/components/BrowserToolbar.vue
  • src/renderer/browser/App.vue
  • src/renderer/browser/stores/window.ts
  • src/renderer/browser/components/icons/CloseIcon.vue
  • src/renderer/browser/components/icons/MinimizeIcon.vue
  • src/renderer/browser/main.ts
  • src/renderer/browser/components/icons/MaximizeIcon.vue
  • src/renderer/browser/components/AppBar.vue

**安全约束**:
**约束**:
- `cdp_send` 不会自动创建 browser;必须先调用 `load_url`
- `local://` URL 禁止 CDP attach(在 `BrowserTab.ensureSession()` 中检查)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update the stale implementation reference for the local:// CDP guard.

The mention of BrowserTab.ensureSession() looks outdated for the new session-scoped architecture; point this line to the current guard location used in the presenter/tool handler path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/architecture/tool-system.md` at line 636, Update the docs line that
currently references BrowserTab.ensureSession(): replace that stale
implementation pointer with a reference to the session-scoped CDP guard used in
the presenter/tool handler path (i.e., point readers to the presenter/tool
handler CDP guard instead of BrowserTab.ensureSession()). Locate the old mention
of BrowserTab.ensureSession() in the sentence and change it to explicitly
reference the presenter/tool-handler session guard (the guard implemented in the
presenter/tool handler path) so the doc points to the current code location.

@zerob13 zerob13 merged commit f294d8e into dev Mar 17, 2026
1 of 2 checks passed
This was referenced Mar 23, 2026
@zerob13 zerob13 deleted the refactor/yobrowser-tools branch March 29, 2026 05:41
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.

1 participant