From 1a5ffe7e4cde26ac61e23ce24fa21c9123d49e61 Mon Sep 17 00:00:00 2001 From: MagMueller Date: Sun, 2 Aug 2026 19:25:14 -0700 Subject: [PATCH 1/2] docs(browser): clarify timed-out invocation --- packages/bcode-browser/skills/browser-execute/SKILL.md | 2 +- packages/bcode-browser/src/browser-execute.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bcode-browser/skills/browser-execute/SKILL.md b/packages/bcode-browser/skills/browser-execute/SKILL.md index fc11f6738..79ad61baf 100644 --- a/packages/bcode-browser/skills/browser-execute/SKILL.md +++ b/packages/bcode-browser/skills/browser-execute/SKILL.md @@ -202,7 +202,7 @@ console.log(JSON.stringify(titles)) ## Guardrails - Top-level `import` statements inside the snippet body are not allowed. Use `await import(...)` instead. - No CPU-bound infinite loops without `await` — they ignore the timeout. Insert `await new Promise(r => setTimeout(r, 0))` to yield. -- `browser_execute` defaults to 60s; longer timeouts delay your next turn. A timeout does not close CDP, though its last command may still run. `Target.getTargets` succeeding means CDP is live; `session.connect()` is then a no-op, and reattaching the same target does not restart its renderer. +- `browser_execute` defaults to 60s; longer timeouts delay your next turn. A timeout ends that call's CDP access without closing the connection, though its last command may still run. `Target.getTargets` succeeding means CDP is live; `session.connect()` is then a no-op, and reattaching the same target does not restart its renderer. ## Console - `console.log`, `console.error`, `console.warn`, `console.info`, `console.debug` are all captured and streamed to the user. Treat them as your stdout. Other `console.*` methods write to bcode's stderr without being captured into the tool result. diff --git a/packages/bcode-browser/src/browser-execute.ts b/packages/bcode-browser/src/browser-execute.ts index 7f8375f93..2ba6fb38b 100644 --- a/packages/bcode-browser/src/browser-execute.ts +++ b/packages/bcode-browser/src/browser-execute.ts @@ -262,7 +262,7 @@ export const make = Effect.fn("BrowserExecute.make")(function* (dataDir: string) const output = timeoutOutput(captured.output) const error = new Error( [ - `browser_execute timed out after ${timeout} ms; the timeout did not close the CDP session`, + `browser_execute timed out after ${timeout} ms; this invocation can no longer issue CDP commands, but the timeout did not close the CDP session`, output.trim() ? `Partial console output before timeout:\n${output.trimEnd()}` : "", ] .filter(Boolean) From c015c79c5fb314e9f1ed2fe04b57c612bc8391fb Mon Sep 17 00:00:00 2001 From: MagMueller Date: Sun, 2 Aug 2026 19:30:49 -0700 Subject: [PATCH 2/2] docs(browser): distinguish follow-up calls --- packages/bcode-browser/skills/browser-execute/SKILL.md | 2 +- packages/bcode-browser/src/browser-execute.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bcode-browser/skills/browser-execute/SKILL.md b/packages/bcode-browser/skills/browser-execute/SKILL.md index 79ad61baf..581e92540 100644 --- a/packages/bcode-browser/skills/browser-execute/SKILL.md +++ b/packages/bcode-browser/skills/browser-execute/SKILL.md @@ -202,7 +202,7 @@ console.log(JSON.stringify(titles)) ## Guardrails - Top-level `import` statements inside the snippet body are not allowed. Use `await import(...)` instead. - No CPU-bound infinite loops without `await` — they ignore the timeout. Insert `await new Promise(r => setTimeout(r, 0))` to yield. -- `browser_execute` defaults to 60s; longer timeouts delay your next turn. A timeout ends that call's CDP access without closing the connection, though its last command may still run. `Target.getTargets` succeeding means CDP is live; `session.connect()` is then a no-op, and reattaching the same target does not restart its renderer. +- `browser_execute` defaults to 60s; longer timeouts delay your next turn. After a timeout, only that call loses CDP access; the next call can continue on the same connection and target. The last command sent by the timed-out call may still finish. `Target.getTargets` succeeding means CDP is live; `session.connect()` is then a no-op, and reattaching the same target does not restart its renderer. ## Console - `console.log`, `console.error`, `console.warn`, `console.info`, `console.debug` are all captured and streamed to the user. Treat them as your stdout. Other `console.*` methods write to bcode's stderr without being captured into the tool result. diff --git a/packages/bcode-browser/src/browser-execute.ts b/packages/bcode-browser/src/browser-execute.ts index 2ba6fb38b..3ee2ba0ee 100644 --- a/packages/bcode-browser/src/browser-execute.ts +++ b/packages/bcode-browser/src/browser-execute.ts @@ -262,7 +262,7 @@ export const make = Effect.fn("BrowserExecute.make")(function* (dataDir: string) const output = timeoutOutput(captured.output) const error = new Error( [ - `browser_execute timed out after ${timeout} ms; this invocation can no longer issue CDP commands, but the timeout did not close the CDP session`, + `browser_execute timed out after ${timeout} ms; this call can no longer issue CDP commands, but the next browser_execute call receives the unchanged CDP session`, output.trim() ? `Partial console output before timeout:\n${output.trimEnd()}` : "", ] .filter(Boolean)