Skip to content

feat(vscode): add integrated browser editor tab - #14836

Merged
marius-kilocode merged 2 commits into
mainfrom
ritzy-spectacles
Oct 6, 2026
Merged

marius-kilocode merged 2 commits into
mainfrom
ritzy-spectacles

Conversation

@marius-kilocode

Copy link
Copy Markdown
Collaborator

What Problem This Solves

The Integrated Browser only worked inside Agent Manager. A session in the sidebar or a Kilo editor tab could call browser_open, but had no way to see the page it opened.

Why This Change Was Made

The Agent Manager browser already has a broker, a screencast stream, and a full panel UI. This change reuses that implementation for a new editor-tab browser instead of building a second one:

  • Extracted host command handling into a shared browser-control.ts, used by both Agent Manager and the editor tab.
  • Extended BrowserBroker route ownership to multiple owners, disambiguated by project id, so sidebar sessions and Agent Manager sessions can coexist.
  • Added BrowserTabProvider (one webview panel per session) plus a browserTab.* message contract and a webview adapter over the shared BrowserPanel.
  • Added the Kilo Code: Open Integrated Browser command. The browser_open tool also reveals the tab automatically.
  • Left Agent Manager unchanged: its navigation approvals stay scoped to its own surface and its browser entries are not closed when an editor-tab browser closes.

User Impact

  • Any session can preview a local application or public HTTPS page in an editor tab.
  • Each session gets its own browser tab. Switching sidebar sessions keeps an open tab live.
  • The feature is gated behind the existing kilo-code.new.experimental.browserAutomation setting.

Evidence

Integrated Browser editor tab rendering a local page, next to the Kilo sidebar

Integrated Browser panel with back, forward, refresh, address, inspect, and devtools controls

Automated checks:

  • bun run check-types and check-types:webview: 0 errors.
  • bun run lint, bun run knip, bun run bundle: clean.
  • Unit suite: 6704 pass, 0 fail (includes a new broker test for project-scoped close).

Manual verification in an isolated VS Code instance:

  • Kilo Code: Open Integrated Browser opens the tab and renders a local page.
  • The browser_open tool auto-reveals the tab without opening Agent Manager.
  • Two sessions produce two independent browser tabs.
  • Switching the sidebar to another session keeps the previous session's open tab usable.

Notes

  • packages/kilo-docs/source-links.md is regenerated because the tab's download button references the Chrome URL.

Comment thread packages/kilo-vscode/src/extension.ts Resolved
@kilo-code-bot

kilo-code-bot Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/src/services/browser-automation/browser-broker.ts 717 closeOwned scans only entries, so an open still in pending is not stopped and can leave a live browser after closeAll() (onWorkspaceChanged, refreshBrowserAutomation).
packages/kilo-vscode/src/extension.ts 236 isActive(route.sessionId) keys ownership to the currently displayed session, not to whether Agent Manager owns a browser for it, so a shared root session can get both AM and tab entries and ambiguous require/get lookups.

SUGGESTION

File Line Issue
packages/kilo-vscode/src/services/browser-automation/browser-control.ts 54 { kind, ...fields } lets a top-level kind on the incoming message override the caller-supplied kind; { ...fields, kind } restores the previous guarantee.
Files Reviewed (2 files)
  • packages/kilo-vscode/src/extension.ts - 1 issue
  • packages/kilo-vscode/src/services/browser-automation/browser-broker.ts - 1 issue
  • packages/kilo-vscode/src/services/browser-automation/browser-control.ts - 1 issue
  • packages/kilo-vscode/src/services/browser-automation/index.ts - no issues
  • packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts - no issues
  • packages/kilo-vscode/src/agent-manager/am-visible-presence.ts - no issues
  • packages/kilo-vscode/src/agent-manager/browser-lifecycle.ts - no issues
  • packages/kilo-vscode/src/agent-manager/browser-message.ts - no issues
  • packages/kilo-vscode/src/browser-tab/BrowserTabProvider.ts - no issues
  • packages/kilo-vscode/tests/unit/browser-broker.test.ts - no issues
  • packages/kilo-vscode/webview-ui/agent-manager/BrowserPanel.tsx - no issues
  • packages/kilo-vscode/webview-ui/browser-tab/BrowserTabApp.tsx - no issues
  • packages/kilo-vscode/webview-ui/browser-tab/messages.ts - no issues
  • packages/kilo-vscode/webview-ui/browser/adapter.ts - no issues
  • packages/kilo-vscode/webview-ui/browser/index.ts - no issues

Fix these issues in Kilo Cloud

Previous Review Summary (commit 760048d)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 760048d)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/src/extension.ts 236 agentManager.isActive() early return disables editor-tab browser resolution for all sessions, not just shared Agent Manager sessions. The Open Integrated Browser command and browser_open from sidebar sessions fail while Agent Manager is the active editor, and an open tab's stream/viewport/input freeze even when visible in a split.

SUGGESTION

File Line Issue
packages/kilo-vscode/src/services/browser-automation/browser-broker.ts 697 closeScoped is scoped, but unscoped close/closeAll now reach tab entries; Agent Manager callers (onWorkspaceChanged, refreshBrowserAutomation) can tear down open editor-tab browsers.
packages/kilo-vscode/src/browser-tab/BrowserTabProvider.ts 75 Route owner registered via BrowserBroker.bind is never unregistered; dispose() cleans listeners but not the owner closure.
Files Reviewed (38 files)
  • .changeset/browser-editor-tab.md - no issues
  • packages/kilo-docs/source-links.md - no issues (CI-generated)
  • packages/kilo-vscode/esbuild.js - no issues
  • packages/kilo-vscode/knip.json - no issues
  • packages/kilo-vscode/package.json - no issues
  • packages/kilo-vscode/src/agent-manager/browser-lifecycle.ts - no issues
  • packages/kilo-vscode/src/agent-manager/browser-message.ts - no issues
  • packages/kilo-vscode/src/browser-tab/BrowserTabProvider.ts - 1 issue
  • packages/kilo-vscode/src/extension.ts - 1 issue
  • packages/kilo-vscode/src/services/browser-automation/browser-broker.ts - 1 issue
  • packages/kilo-vscode/src/services/browser-automation/browser-control.ts - no issues
  • packages/kilo-vscode/tests/unit/browser-broker.test.ts - no issues
  • packages/kilo-vscode/webview-ui/browser-tab/BrowserTabApp.tsx - no issues
  • packages/kilo-vscode/webview-ui/browser-tab/index.tsx - no issues
  • packages/kilo-vscode/webview-ui/browser-tab/messages.ts - no issues
  • packages/kilo-vscode/webview-ui/src/i18n/*.ts (21 files) - no issues
  • packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts - no issues
  • packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts - no issues

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash · Input: 130.4K · Output: 35.8K · Cached: 2.6M

Review guidance: REVIEW.md from base branch main

Extract shared webview browser adapter and host control mapping to remove
duplication flagged by the duplication check. Track broker owners so the
Agent Manager and browser tab close only their own entries, and guard the
Agent Manager route on the exact displayed session.
@marius-kilocode
marius-kilocode merged commit c5bd6cb into main Oct 6, 2026
29 checks passed
@marius-kilocode
marius-kilocode deleted the ritzy-spectacles branch October 6, 2026 11:50
/** Close every entry owned by one surface, leaving other owners' entries intact. */
closeOwned(owner: BrowserOwner): Promise<void> {
return Promise.all(
[...this.entries.values()]

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.

WARNING: closeOwned only scans this.entries, so it misses in-flight open operations that have not registered an entry yet, which makes it weaker than the previous closeAll.

The old closeAll enumerated entries + pending (via sessions()) and routed through close(), whose serial(key, ...) waits for a pending create and then retires the entry. closeOwned iterates [...this.entries.values()] only, so a browser open still awaiting ensureBrowser()/create() when closeAll() runs is never stopped; the create completes afterwards and leaves a live proxy/context until broker dispose. This can be reached from AgentManagerProvider.onWorkspaceChanged() (pinned-workspace sync) and refreshBrowserAutomation(). Consider tracking the owner for pending keys, or document that closeOwned cannot cancel in-flight opens.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

// While the Agent Manager panel is focused on this exact session, it
// owns the browser for that shared root session. Other sidebar and
// editor-tab sessions still resolve here.
if (agentManager?.isActive(route.sessionId)) return

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.

WARNING: Ownership is keyed to the session the Agent Manager is currently displayed on, not to whether it actually owns a browser for that session, so a shared root session can end up with two owners.

isActive(route.sessionId) is only true while visiblePresence.displayed() equals the route's session. The Agent Manager keeps a browser entry alive across session switches (it only closes on explicit close, project change, or dispose), and displayed() is null when the panel shows a terminal/review/history view. So when the Agent Manager has a live browser for shared root session X but currently displays Y (or a non-session view), the guard does not fire and the editor-tab resolver also claims X; the broker then holds both ${project}\0X (Agent Manager) and \0X (tab) entries. Session-scoped lookups become ambiguous: get(X) returns undefined when two entries match (browser-broker.ts:463), and tab refresh/back/forward/inspect throw Browser session identity is ambiguous from require (browser-broker.ts:1062). Deciding based on whether the Agent Manager owns an entry for route.sessionId, rather than on the displayed session, would express the intended ownership.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.


/** Builds a neutral control message from a surface message that shares these fields. */
export function browserControlMessage(kind: BrowserControlKind, fields: BrowserControlFields): BrowserControlMessage {
return { kind, ...fields }

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.

SUGGESTION: { kind, ...fields } places the spread after kind, so a kind property on the incoming surface message would silently override the caller-supplied control kind - a guarantee the previous explicit field list provided. No current caller sets a top-level kind, so this is latent; return { ...fields, kind } preserves the guarantee at no cost.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

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.

2 participants