Option A: cloud browser via snippet, drop browser_open_cloud tool#42
Closed
Alezander9 wants to merge 1 commit intofeat/phase-h-ts-harnessfrom
Closed
Option A: cloud browser via snippet, drop browser_open_cloud tool#42Alezander9 wants to merge 1 commit intofeat/phase-h-ts-harnessfrom
Alezander9 wants to merge 1 commit intofeat/phase-h-ts-harnessfrom
Conversation
The local-browser connect path is already snippet-side (the agent calls `await session.connect(...)` itself in a snippet, picks Way 1 / Way 2). `browser_open_cloud` was the only opaque path — it wrapped one HTTP call and hid the Browser Use API surface from the agent. That asymmetry was the root of the cubic P2 lifecycle finding (auto-stop wired but never invoked) and the broader "two patterns mixed" review feedback on PR #41. This commit makes cloud match local. The agent provisions, connects, stops, and swaps cloud browsers from inside `browser_execute` snippets using `fetch` against `https://api.browser-use.com/api/v3/browsers`. Removed: - packages/bcode-browser/src/cloud-browser.ts (-109) - packages/opencode/src/tool/browser-open-cloud.{ts,txt} (-47) - registry hookup for BrowserOpenCloudTool - SessionStore.onEvict + cleanup-callback machinery (~ -25 LOC, including the Entry wrapper type). evict() now just closes + deletes; kept because the test file uses it for cleanup between cases. Added: - packages/bcode-browser/skills/cloud-browser.md (~150 LOC). Way 3 documentation: provision/connect/stop/swap, plus a recommended reusable workspace helper (.bcode/agent-workspace/cloud.ts) for projects that use cloud browsers more than once. BU API auth via process.env.BROWSER_USE_API_KEY (stays as an env var; opencode's auth.json was considered and rejected — see decisions.md §3.10). Updated: - BROWSER.md restructured around Way 1 / Way 2 / Way 3 (real Chrome popup-gated / isolated debug-port / cloud). New "Switching browsers mid-session" section. Listability hint added (`read {{SKILLS_DIR}}/interaction-skills/` to enumerate without committing). Removed the misleading "first call connects automatically" line — agent always calls connect() explicitly, just sometimes with no args. - browser-execute.txt mentions cloud-browser.md and notes process.env is in snippet scope. - bcode-browser README + package.json + index.ts: cloud-browser.ts references removed; brief note that cloud is intentionally not its own Level-1 surface. - comments in browser-execute.ts: no more `browser_open_cloud` cross-references. Net LOC: -200 deletions vs +150 markdown additions = ~-50 net hand- written. Bigger win is one fewer tool surface (back to the original Phase H §3.2 single-tool target) and zero wrapper-PR treadmill as the BU API surface grows (profile sync, custom proxies, regional pools, recording, etc. all reachable from a snippet without bcode changes). Verification: - bun typecheck clean across all browsercode packages. - bun test from packages/bcode-browser/: 4 pass + 5 skip (chrome-gated). - embed-skills.ts now embeds 18 files (was 17, +1 for cloud-browser.md). Cubic P2 finding closed: no tool claims cloud auto-stop, so there is no false claim. Stop is the agent's responsibility, documented in cloud-browser.md "Stop". Stacked on feat/phase-h-ts-harness; PR-A (#41) lands first, then this rebases onto main and lands separately. v0.1.0 tag waits for both.
There was a problem hiding this comment.
3 issues found across 12 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/bcode-browser/skills/cloud-browser.md">
<violation number="1" location="packages/bcode-browser/skills/cloud-browser.md:54">
P2: Handle the case where no page target is found before calling `session.use` to avoid a runtime crash.</violation>
<violation number="2" location="packages/bcode-browser/skills/cloud-browser.md:64">
P2: Validate the stop API response (`r.ok`) so failed stop requests don't silently leave cloud browsers running.</violation>
</file>
<file name="packages/bcode-browser/skills/BROWSER.md">
<violation number="1" location="packages/bcode-browser/skills/BROWSER.md:50">
P2: The new cloud connect example only reads `cdp_url`, even though this doc says some regions return `cdpUrl`. The snippet should accept both so copy-paste usage does not fail.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
| When you're done, stop the browser. BU's quotas and idle reclaim will eventually clean it up if you forget, but explicit stop is faster and frees the slot: | ||
|
|
||
| ```js | ||
| await fetch(`https://api.browser-use.com/api/v3/browsers/${id}`, { |
There was a problem hiding this comment.
P2: Validate the stop API response (r.ok) so failed stop requests don't silently leave cloud browsers running.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/bcode-browser/skills/cloud-browser.md, line 64:
<comment>Validate the stop API response (`r.ok`) so failed stop requests don't silently leave cloud browsers running.</comment>
<file context>
@@ -0,0 +1,145 @@
+When you're done, stop the browser. BU's quotas and idle reclaim will eventually clean it up if you forget, but explicit stop is faster and frees the slot:
+
+```js
+await fetch(`https://api.browser-use.com/api/v3/browsers/${id}`, {
+ method: "PATCH",
+ headers: { "X-Browser-Use-API-Key": apiKey, "Content-Type": "application/json" },
</file context>
| await session.connect({ wsUrl: cdpUrl }) | ||
| const targets = (await session.Target.getTargets({})).targetInfos | ||
| const page = targets.find(t => t.type === "page") | ||
| await session.use(page.targetId) |
There was a problem hiding this comment.
P2: Handle the case where no page target is found before calling session.use to avoid a runtime crash.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/bcode-browser/skills/cloud-browser.md, line 54:
<comment>Handle the case where no page target is found before calling `session.use` to avoid a runtime crash.</comment>
<file context>
@@ -0,0 +1,145 @@
+await session.connect({ wsUrl: cdpUrl })
+const targets = (await session.Target.getTargets({})).targetInfos
+const page = targets.find(t => t.type === "page")
+await session.use(page.targetId)
+```
+
</file context>
Comment on lines
+50
to
+51
| const { id, cdp_url, live_url } = await r.json() | ||
| await session.connect({ wsUrl: cdp_url }) |
There was a problem hiding this comment.
P2: The new cloud connect example only reads cdp_url, even though this doc says some regions return cdpUrl. The snippet should accept both so copy-paste usage does not fail.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/bcode-browser/skills/BROWSER.md, line 50:
<comment>The new cloud connect example only reads `cdp_url`, even though this doc says some regions return `cdpUrl`. The snippet should accept both so copy-paste usage does not fail.</comment>
<file context>
@@ -1,28 +1,62 @@
+ headers: { "X-Browser-Use-API-Key": process.env.BROWSER_USE_API_KEY, "Content-Type": "application/json" },
+ body: "{}",
+})
+const { id, cdp_url, live_url } = await r.json()
+await session.connect({ wsUrl: cdp_url })
+console.log("liveUrl for the user to watch:", live_url)
</file context>
Suggested change
| const { id, cdp_url, live_url } = await r.json() | |
| await session.connect({ wsUrl: cdp_url }) | |
| const { cdp_url, cdpUrl, live_url } = await r.json() | |
| const wsUrl = cdp_url ?? cdpUrl | |
| if (!wsUrl) throw new Error("Browser Use response missing cdp_url/cdpUrl") | |
| await session.connect({ wsUrl }) |
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on top of #41 (
feat/phase-h-ts-harness). Implements Option A from the PR #41 review thread.Why
The local-browser connect path is already snippet-side (the agent calls
await session.connect(...)itself in abrowser_executesnippet — picks Way 1 or Way 2 from BROWSER.md).browser_open_cloudwas the only opaque path: it wrapped one HTTP call and hid the Browser Use API surface from the agent. That asymmetry was the root of:This commit makes cloud match local. Agent provisions / connects / stops / swaps cloud browsers from inside
browser_executesnippets usingfetchagainsthttps://api.browser-use.com/api/v3/browsers, exactly the same way it callsawait session.connect({ profileDir })for a local browser.Decision recorded as
decisions.md §3.10(Rev 7) on the agent side.What's removed
packages/bcode-browser/src/cloud-browser.tspackages/opencode/src/tool/browser-open-cloud.tspackages/opencode/src/tool/browser-open-cloud.txttool/registry.ts)SessionStore.onEvict+ cleanup-callback machinery +Entrytype wrapperSessionStore.evict(sessionID)is preserved (with simpler signature: justclose + delete) becausetest/browser-execute.test.tsuses it for between-case cleanup.What's added
packages/bcode-browser/skills/cloud-browser.md(~150 LOC). The Way 3 deep dive: provision (POST), connect, stop (PATCH), swap (stop + close + provision again). Recommends a reusable./.bcode/agent-workspace/cloud.tsworkspace helper for projects that use cloud browsers more than once. Documentsprocess.env.BROWSER_USE_API_KEYas the auth source — see "Auth shape" below.cloud-browser.mdflows frombrowser-execute.txt→BROWSER.md→cloud-browser.md(read on demand, exactly the pattern the user asked for in the previous review pass).What's updated
packages/bcode-browser/skills/BROWSER.mdrewritten around Way 1 / Way 2 / Way 3 (the user's running Chrome via popup-gated remote debugging / isolated debug-port Chrome / Browser Use cloud). New "Switching browsers mid-session" section documents theawait session.close(); await session.connect(...)pattern. New listability hint:read {{SKILLS_DIR}}/interaction-skills/to enumerate skills without committing to read.packages/opencode/src/tool/browser-execute.txtpoints atcloud-browser.mdfor cloud specifics and notesprocess.envis available in snippet scope.packages/bcode-browser/{README.md, package.json, src/index.ts}and a comment insrc/browser-execute.ts: cloud-browser.ts references removed; brief note that cloud is intentionally not its own Level-1 surface.Auth shape
BROWSER_USE_API_KEYstays as an environment variable. The agent reads it viaprocess.env.BROWSER_USE_API_KEYfrom inside a snippet.opencode's
auth.jsonprovider system was considered and rejected: it's plugin-driven and tied to the LLM-provider abstraction. Treating "browser-use" as a provider would force us into the plugin/provider system for one API key, drag a Yellow-zone modification intopackages/opencode/, and confuse the user about whether bcode is selecting Browser Use as a model. Env var matches the existing AWS Bedrock pattern in opencode and keeps everything in Green zone (additive inbcode-browser/).Net LOC
cloud-browser.md)The bigger win is conceptual:
browser_execute) — back to the original Phase H §3.2 single-tool target.cloud-browser.md's Stop section. Hard rule extension: the migration plan's "workspace as plain code, no privileged files" extends to "no privileged tools either."Verification
bun typecheckclean across all browsercode packages (@browser-use/{browsercode-core,bcode-browser,bcode-laminar},@opencode-ai/{core,plugin,sdk}) via the turbo-filtered root run.bun testfrompackages/bcode-browser/: 4 pass (workspace-import always-on), 5 skip (chrome-gated underBCODE_SMOKE_CHROME=1— same as PR phase-h: TS harness port (v0.1.0 cut) #41's smoke matrix).embed-skills.tsnow embeds 18 files (was 17 = BROWSER.md + 16 interactions; +1 forcloud-browser.md). Verified locally.Stacking
Branch is
feat/option-a-browser-toolbased onfeat/phase-h-ts-harness. PerAGENTS.mdstacked-PR policy: PR #41 merges tomainfirst; then this branch rebases ontomain; then this PR retargetsmainand lands separately. v0.1.0 tag waits until both have landed onmain.If you'd rather land this folded into PR #41 instead of stacked, I can
git rebase --onto feat/phase-h-ts-harnessand force-push #41's branch with this commit appended — your call.