Skip to content

fix(browser): apply core's timeout rules to tool calls - #95

Merged
frontegg-david merged 2 commits into
fix/browser-sanitize-resultsfrom
fix/browser-timeout-tool-calls
Oct 4, 2026
Merged

frontegg-david merged 2 commits into
fix/browser-sanitize-resultsfrom
fix/browser-timeout-tool-calls

Conversation

@frontegg-david

@frontegg-david frontegg-david commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Stack 4/10: main ← #92 ← #93 ← #94 ← this ← #96 ← #98 ← #99 ← #100 ← #101 ← #102

Fixes #90.

Validation

Reproduced: with timeout: 1000 and a tool that takes 2.5 s, core returns "done" and the browser fails at 1.0 s with EXECUTION_TIMEOUT.

The issue says core's timer doesn't count time spent in tool calls. Not quite: core's timer does run during a tool call; it just never cuts off a call in progress. When it fires, core only sets aborted, which the next callTool() checks. Measured on core with timeout: 1000 and a 2.5 s tool:

Script core
one callTool succeeds after 2.5 s with "done"
two callTools in sequence fails after 2.5 s: Execution aborted (the second call is refused)

The browser had two wall-clock timers (outer iframe at timeout, host at timeout + parentTimeoutBuffer), and both kept running while a tool call waited for toolHandler.

Fix

The browser now follows core's rules exactly, instead of only leaving tool time out of the timer:

  • The outer iframe's timeout and the host's backup timeout pause while a tool call is waiting for the host (new PausableTimer on the host side; counters in the outer iframe). A tool call in progress is never cut off.
  • The inner iframe refuses a tool call once timeout ms of wall-clock time have passed since the start: Execution aborted, as in core. The clock is captured before user code runs.
  • The script's own running time stays bounded by timeout (a test covers a script that sleeps after a tool call).

Docs: the timeout JSDoc in both packages, the configuration tables and the overview's "Browser vs Node.js" table now describe these rules. That includes the one caveat the two packages share: a toolHandler that never settles keeps run() waiting, so bound slow tools in the handler.

Red → green

Suite Before After
libs/browser/e2e/timeout.spec.ts (+4 tests) 3 failed: slow tool, parallel slow tools, next call refused after the deadline. The 4th (the timeout still bounds the script after a tool call) is a guard. 8 passed
libs/core/src/__tests__/enclave.timeout-tool-calls.spec.ts (new, 2 tests) passes; pins core's rules so the two packages can't drift passes

Review follow-ups (f8b7c6a)

  • Timeout accounting used Date.now() (Copilot, 3 comments), so a system clock change moved the budget. The inner deadline (captured before STRICT removes performance), the outer iframe's pause accounting and the host's PausableTimer now use performance.now(); Date.now() is kept for the reported stats. New e2e test: the page's Date.now() jumps an hour ahead between two tool calls. Before, the host timer fired at once (EXECUTION_TIMEOUT); now the run completes (10/10 with --repeat-each 10).

Verification

  • browser: nx run browser:test-e2e: 83 passed
  • core: 64 suites pass
  • lint, build, prettier: pass

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

Next included review available in 19 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 3 included reviews currently available. Your 43 included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: agentfront/enclave/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 3c912b08-edf8-4316-b8fc-5385447f8a4b
📥 Commits

Reviewing files that changed from the base of the PR and between 08a240a and f8b7c6a.

📒 Files selected for processing (11)
  • docs/enclave/core-libraries/enclave-browser/configuration.mdx
  • docs/enclave/core-libraries/enclave-browser/overview.mdx
  • docs/enclave/core-libraries/enclave-vm/configuration.mdx
  • libs/browser/e2e/timeout.spec.ts
  • libs/browser/src/adapters/iframe-adapter.ts
  • libs/browser/src/adapters/inner-iframe-bootstrap.ts
  • libs/browser/src/adapters/outer-iframe-bootstrap.ts
  • libs/browser/src/adapters/pausable-timer.ts
  • libs/browser/src/types.ts
  • libs/core/src/__tests__/enclave.timeout-tool-calls.spec.ts
  • libs/core/src/types.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Timeout state is not propagated to all runtime gates, and adjustable wall clocks make the new deadline accounting unreliable.

Review effort: Balanced
Findings: 3 Medium severity

Open (3)
What changed in this PR

Aligns browser tool-call timeout behavior with core while preserving execution-time limits.

Changes:

  • Adds pausable browser timeout handling for active tool calls.
  • Adds core and browser regression tests.
  • Documents shared timeout semantics.
File Description
libs/​core/​src/​types.ts Documents core timeout semantics.
libs/​core/​src/​__tests__/​enclave.timeout-tool-calls.spec.ts Tests core behavior with slow tools.
libs/​browser/​src/​types.ts Documents browser timeout semantics.
libs/​browser/​src/​adapters/​pausable-timer.ts Adds a pausable timer utility.
libs/​browser/​src/​adapters/​outer-iframe-bootstrap.ts Pauses outer-frame timeout during tool calls.
libs/​browser/​src/​adapters/​inner-iframe-bootstrap.ts Rejects post-deadline tool calls.
libs/​browser/​src/​adapters/​iframe-adapter.ts Pauses the host backup timeout.
libs/​browser/​e2e/​timeout.spec.ts Covers slow, parallel, and sequential calls.
docs/​enclave/​core-libraries/​enclave-vm/​configuration.mdx Updates core configuration documentation.
docs/​enclave/​core-libraries/​enclave-browser/​overview.mdx Adds timeout parity information.
docs/​enclave/​core-libraries/​enclave-browser/​configuration.mdx Updates browser timeout documentation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread libs/browser/src/adapters/inner-iframe-bootstrap.ts Outdated
Comment thread libs/browser/src/adapters/outer-iframe-bootstrap.ts
Comment thread libs/browser/src/adapters/pausable-timer.ts
frontegg-david and others added 2 commits October 4, 2026 03:20
BrowserEnclave's timeout was a wall-clock timer that also ran while a
tool call waited for toolHandler, so a script with a slow tool timed
out in the browser and succeeded on @enclave-vm/core.

Core's rules: a tool call in progress when the timeout passes is not
cut off and its result is delivered; the script's next tool call then
fails with "Execution aborted". The browser now does the same: the
outer iframe's and the host's hard timeouts pause while a tool call is
waiting for the host (a new PausableTimer on the host side), and the
inner iframe refuses a tool call once the timeout has passed since the
start. The script's own running time stays bounded by the timeout.

A core spec pins the same rules, and the timeout docs of both packages
describe them, including that a handler that never settles keeps run()
waiting.

Fixes #90

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-up. The inner iframe's deadline, the outer iframe's pause
accounting and the host's PausableTimer measured elapsed time with
Date.now(), so a system clock change during a run moved the budget: a
jump forward expired the host timer at once (the new test fails with
EXECUTION_TIMEOUT before this change), a jump back stretched it.

All three now use performance.now(); the inner iframe captures it
before STRICT removes performance. Date.now() is kept only for the
reported timestamps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@frontegg-david
frontegg-david force-pushed the fix/browser-timeout-tool-calls branch from 484ece7 to f8b7c6a Compare October 4, 2026 00:21
@frontegg-david
frontegg-david merged commit 78650e3 into main Oct 4, 2026
8 checks passed
@frontegg-david
frontegg-david deleted the fix/browser-timeout-tool-calls branch October 4, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@enclave-vm/browser: timeout counts time spent waiting for tool calls; core's doesn't

3 participants