Repository navigation
Conversation
🦋 Changeset detectedLatest commit: 60471ee The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
🟢 agents import sizes: 1 entry point changed, no growth
Changed exports (1)
How this worksEach runtime export is bundled on its own, minified, and gzipped. Changes smaller than 100 B, or smaller than 1% and 1 KiB, are ignored. Growth over 10% or 5 KiB is marked 🔴. This report is informational and does not fail CI. The workflow artifact contains every measurement. Compared |
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
| description: core.description, | ||
| parameters: browserToolParameters, | ||
| // Calls share the active tab, so one round's calls must not interleave. | ||
| executionMode: "sequential", |
There was a problem hiding this comment.
🔴 Concurrent conversations lose their active tab
When separate conversations call browserTool concurrently, executionMode does not serialize them across conversations. Both save to the same browser's activeTargetId, so a later call can act on another conversation's tab.
Learn more
Pi runs different conversations concurrently; executionMode: "sequential" orders calls within a conversation's tool round, not calls from other conversations. BrowserSessionConnector saves the active target to a single browser record after each execution. The next execution resolves "active" from that shared record via activeTarget. Two conversations using one Browser can therefore switch one another's active tab even though each tool reports sequential execution.
Example: Conversation A creates tab A, and conversation B creates tab B before A's next call. B's pass saves tab B as active. A's Runtime.evaluate with sessionId: "active" now runs in tab B, not tab A.
Recommended fix: Decide whether the browser is intended to be shared between conversations. If not, assign a distinct named Browser to each conversation. If it is shared, track the active target per conversation and pass the conversation identity into the connector; a global execution lock alone cannot retain separate active tabs between turns.
Was this helpful? React with 👍 or 👎 to provide feedback.
Adds
browserToolto a newagents/browser/pientry point, so a pi-durable harness (agents/harness/pi) can drive the same persistentBrowseras the AI SDK and TanStack AI tools.It returns a pi
ToolRegistrationbuilt on the sharedcreateBrowserToolCore, so tabs, logins,sessionId: "active",newTabs, andrestarted: truework as they do in the other tools.What's different in pi
calls) plus an image part. pi-ai sends the image only to models that accept images.executionMode: "sequential": calls share the active tab, so they don't interleave.replay: "unsafe": the code may have clicked or submitted something, so after an eviction pi gives the model an interrupted result instead of running it again.ctxis passed explicitly when the host is a plain Durable Object, which is what the pi examples use.detailscarriesexecutionId,status,restarted, andnewTabsfor a UI.Known gap: codemode ignores pi's abort signal, so stopping a conversation doesn't cancel a browser call already running. The call finishes or hits
timeoutMs. The docs say so.Tests
browser-capability.test.ts: name, mode, replay, restart, image, oversized screenshot, error.PiHarnesswith pi's faux model (harness/pi/tests/browser.test.ts). It checks that pi accepts the schema, runs the call, and stores the image in the transcript.tests-d/browser-tool.test-d.ts.Docs: a pi paragraph in "Persistent browser" (
browse-the-web.md) and a Browser subsection inharnesses/pi.md. Changeset:agentsminor.The Pi example gets the tool in the PR stacked above this one.