Repository navigation
Conversation
◈ PR Lens
Architecture 10 components touched across 3 lanes. Play the interactive walkthrough Inside the changed components — 2 viewsComponent view — Browser Agent Bridge In-tab registry and RPC sync bridge forwarding page functions to Devframe Component view — Client Agent Manager Node session manager tracking tabs, focus state, and routing tool calls Data flow
Follow each request, response and payload The other flows — 1 sequence
View
Tip Click the link under each diagram to open it on a canvas you can zoom, pan and step through 🪧 More tips
Thanks for using PR Lens! It's built by Coldtea, free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
fc6a624 to
ff554f0
Compare
…per tab Forward agent-flagged in-page channel functions to the node MCP endpoint (ports the bridge from #376 onto 0.10), and make each connected browser tab visible and addressable: a built-in devframe:agent:list-clients tool, a reserved client_id argument on forwarded tools, and focus-aware default routing so an unaddressed call follows the tab the user looked at last. devframe connect nests the tab list under mcp.clients per instance. Closes #394
ff554f0 to
0077dd9
Compare
|
👁️🗨️ Review this pull request with grouped, summarized diffs at: raw result💭 analyzed by {
"headSha": "51cbf58d4e54a00cf2600f4adaa82af239da3cf8",
"result": {
"overallSummary": "Ports and extends the #376 in-page-tools bridge onto 0.10 so multiple open tabs of the same app are each individually addressable: every tab now syncs a manifest (id, URL, title, visible/focused) alongside its tools, the node dedupes `tools/list` by id while routing calls to a specific tab via a reserved `client_id` argument (or to the most-recently-focused visible tab by default), exposes a new `devframe:agent:list-clients` tool and `DF0082` error for unknown ids, and `devframe connect` surfaces the same tab list under `mcp.clients`.",
"groups": [
{
"key": "core-routing",
"label": "Per-tab client-agent routing",
"summary": "Core of the feature: each browser tab now reports an id/URL/title/visible/focused manifest over its RPC connection; the node keeps a per-tab registry, dedupes forwarded tools by id, injects a reserved `client_id` argument, routes unaddressed calls by focus/visibility/recency, and exposes `devframe:agent:list-clients` plus the new `DF0082` diagnostic for unknown client ids.",
"category": "core",
"filePaths": [
"packages/devframe/src/node/client-agent.ts",
"packages/devframe/src/node/diagnostics.ts",
"packages/devframe/src/node/rpc/agent-sync-client-tools.ts",
"packages/devframe/src/node/rpc/index.ts",
"packages/devframe/src/types/rpc-augments.ts",
"packages/devframe/src/client/browser-agent.ts",
"packages/devframe/src/client/browser-agent-rpc.ts",
"packages/devframe/src/internal/index.ts"
],
"critical": true,
"fileNotes": [
{
"path": "packages/devframe/src/node/client-agent.ts",
"text": "Core routing logic: `pickTarget` ranking (focused > visible > last-synced), tool-id dedup, and the `client_id` stripping/validation before forwarding to a tab's RPC session.",
"critical": true
},
{
"path": "packages/devframe/src/client/browser-agent-rpc.ts",
"text": "Adds focus/blur/visibilitychange listeners that re-sync the tab's manifest, so the node can track which tab the user last looked at."
}
]
},
{
"key": "connect-cli",
"label": "devframe connect client listing",
"summary": "`devframe connect`'s `list-instances` now also fetches and nests the connected browser tabs (`mcp.clients`) per instance via the new built-in list-clients tool, and `call-tool`'s description documents passing `client_id` through.",
"category": "api",
"filePaths": [
"packages/agentic/src/connect/index.ts"
],
"fileNotes": [
{
"path": "packages/agentic/src/connect/index.ts",
"text": "`indexInstanceMcp` makes an extra `callTool` round-trip to `list-clients` only when that tool is present, so devframes without browser-agent tools pay no extra cost."
}
]
},
{
"key": "tests",
"label": "Routing and integration tests",
"summary": "Unit tests cover every tab-routing rule (focus/visible/last-synced precedence, `client_id` targeting and stripping, unknown id, no re-publish on focus-only resync) and the new document-focus reporting; an integration test exercises two live WS tabs through a real MCP client and through `devframe connect`.",
"category": "tests",
"filePaths": [
"packages/devframe/src/node/__tests__/client-agent.test.ts",
"packages/devframe/src/client/browser-agent-rpc.test.ts",
"packages/agentic/src/mcp/__tests__/mcp-client-tools.test.ts"
]
},
{
"key": "docs",
"label": "Agent-native docs & error pages",
"summary": "Documents the new in-page-tools-over-MCP flow, `list-clients`/`client_id` routing, and the `DF0082` error page; the error index also reflects the already-landed `DF0080` renumbering.",
"category": "docs",
"filePaths": [
"docs/content/1.guide/12.in-page-channel.md",
"docs/content/1.guide/15.agent-native.md",
"docs/content/6.errors/DF0082.md",
"docs/content/6.errors/index.md"
]
},
{
"key": "generated-snapshots",
"label": "Generated API snapshots",
"summary": "Auto-generated public-API snapshots regenerated to reflect the new `ConnectedClient`/`BrowserAgentClientInfo` types, `LIST_CLIENTS_TOOL` export, and `DF0082` diagnostic.",
"category": "other",
"filePaths": [
"tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts",
"tests/__snapshots__/tsnapi/devframe/internal.snapshot.d.ts",
"tests/__snapshots__/tsnapi/devframe/internal.snapshot.js"
]
}
],
"schemaVersion": 1,
"source": "llm",
"generatedAt": "2026-10-28T03:13:10.993Z",
"model": "vercel-ai-gateway/anthropic/claude-sonnet-5",
"locale": "en"
}
} |
Each component of the tab listing/routing feature was disabled in turn; six survived the suite. Add tests so each one is now required: focus beats a later background sync, focus is remembered after the user leaves the browser, connectedAt survives re-syncs, the page reports its own tab info and re-syncs on focus/visibility, and devframe connect nests the tabs under mcp.clients.
Closes #394. MVP of the plan discussed there.
What changes
With several tabs of the same app open, the MCP surface behaved as if there were one client:
devframe connectlists instances per port, and in-page tools (from #376) were silently owned by whichever tab synced last.@devframes/agenticera):agent-flagged in-page channel functions register in a per-document browser-agent registry and sync to the node over the page's RPC connection; the node exposes them as MCP tools and relays calls back. Not yet on main, so it lands here as the foundation.sessionStorage-backed instance id, so it survives reloads), URL, title,visible,focused. Re-synced on connect, tool changes, andfocus/blur/visibilitychange.devframe:agent:list-clients(wiredevframe_agent_list-clients): built-in tool listing the connected tabs and the tool ids each exposes. Appears once a tab is connected, so a devframe with no agent surface of its own doesn't flip MCP auto-mount.tools/liststays deduped (one entry per tool id). Forwarded tools take a reservedclient_idargument; an unknown id fails with the newDF0081listing the live ids. Withoutclient_id, the call goes to the most recently focused visible tab, falling back to the last-synced one — which is what medula's vendored patch approximated with "last sync wins".devframe connect:list-instancesnestsmcp.clientsper instance (fetched in the same MCP session it already opens to list tools);call-toolpassesclient_idthrough.DF0080(the feat: eagerly expose in-page tools to browser agents #376jsonSerializableguard, renumbered sinceDF0078is taken on main) andDF0081pages.Verification
client_idtargeting/stripping, missing id, no re-publish on focus-only re-sync).tools/listdedup + injectedclient_idschema,list-clientsoutput, addressed/unaddressed/missing-id calls, focus follow.pnpm lint && pnpm knip && pnpm test && pnpm typecheck && pnpm buildgreen (knip's remaining items are the pre-existing unbuilt-starter hints).Known limits (MVP)
sessionStorage, so two tabs can briefly share an id; targeting then picks the better-ranked one.Supersedes the in-page-tools part of #376 (ported and extended here).
This PR was created with the help of an agent.