* fix: use fresh browser context for selected tabs on each message
Previously, session.browserContext (set on the first message) always
took precedence via the nullish coalescing operator. On subsequent
messages with different tab selections, the new selectedTabs from the
request were silently ignored.
Now normal messages always use request.browserContext so freshly
selected tabs are included. Scheduled tasks still use the stored
session context to preserve the hidden window's pageId/windowId.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use singleton transport for MCP route
MCP SDK 1.26.0 added a strict guard in Protocol.connect() that throws
"Already connected to a transport" if called when already connected.
The previous code created a new transport per request and called
connect() each time, causing every request after the first to fail
with -32603 Internal server error.
Move transport creation outside the request handler and add
isConnected() check per @hono/mcp docs pattern.
* fix: per-request MCP server+transport for SDK 1.26.0 compat
MCP SDK 1.26.0 patched a security vulnerability (GHSA-345p-7cg4-v4c7)
where sharing a singleton McpServer across requests could leak
cross-client response data via message ID collisions.
Create fresh McpServer + StreamableHTTPTransport per request:
no shared state, no race conditions, no ID collisions.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The agent had no knowledge of its working directory, so it couldn't
reference created files by absolute path or help users locate them.
Pass sessionExecutionDir into buildSystemPrompt for both AiSdkAgent
and GeminiAgent so the prompt includes a <workspace> section with
the resolved directory path.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Previously, session.browserContext (set on the first message) always
took precedence via the nullish coalescing operator. On subsequent
messages with different tab selections, the new selectedTabs from the
request were silently ignored.
Now normal messages always use request.browserContext so freshly
selected tabs are included. Scheduled tasks still use the stored
session context to preserve the hidden window's pageId/windowId.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: new onboarding flow
* feat: co-ordinate the sign in and import hints
* fix: ux on step one
* fix: make custom option friendlier
* feat: added required fields
* feat: setup step two redirection
* fix: remove copy url button
* feat: store profile info from onboarding
* feat: sync onboarding profile to api
* feat: show confetti when the onboarding completes
* fix: change the options in onboarding demo
* feat: setup missing analytics events
* fix: lint issues
* ci: fix typescript error
* fix: sign in hint
* fix: restore glow overlay for CDP-based tools
After migrating to CDP tools, glow broke because the hook looked for
input.tabId (controller tools) while CDP tools use input.page (pageId).
- Server: add getTabIdForPage() to Browser, include tabId in tool output
- Client: extract tabId from output, fall back to active Chrome tab
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: use ToolResultMetadata for tabId resolution
Move tabId resolution from tool-adapter into the framework layer:
- response.ts: add ToolResultMetadata interface with tabId field
- framework.ts: auto-resolve pageId→tabId after tool execution
- tool-adapter.ts: just forward metadata (no domain logic)
This makes metadata available to all ToolResult consumers, not just
the AI SDK adapter, and the metadata bag is extensible for future fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add todo
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>