Skip to content

fix(session): bound retry loop, fix doom-loop guard, treat abort as clean stop#124

Merged
Aayam Bansal (aayambansal) merged 1 commit into
mainfrom
fix/session-spend-safety
Jul 7, 2026
Merged

fix(session): bound retry loop, fix doom-loop guard, treat abort as clean stop#124
Aayam Bansal (aayambansal) merged 1 commit into
mainfrom
fix/session-spend-safety

Conversation

@aayambansal

Copy link
Copy Markdown
Member

Three spend/reliability-safety fixes in the session processor (from the audit):

  • chore(deps): bump the production-dependencies group with 65 updates #7 (High) — the while(true) retry loop was unbounded, and retry.ts classifies any JSON body carrying an error field as retryable (Provider Server Error), so a persistently-failing provider — or a permanent error (bad request, context-length) that arrives as JSON — retried forever. Cap at MAX_RETRY_ATTEMPTS = 10 per message generation (the counter is per-process, so this is per-message, not per-session), after which the error is terminal.
  • fix(managed): point the managed API base at the real backend; launcher install fallback #10 (High) — the doom-loop guard required the last 3 raw parts to be identical tool parts, but reasoning models emit a reasoning part before every tool call, so 3 consecutive tool parts never appeared and the guard never fired against a genuinely looping tool. Now scans the last N tool parts (extracted isDoomLoop, unit-tested).
  • Spend toggle rewrites openscience.json with resolved secrets in plaintext #51 (Low) — a user-initiated abort no longer fires Session.Event.Error: it's a clean cancellation, so it's recorded on the message (the turn still stops) but not rendered as an error state.

Tests

test/session/doom-loop.test.ts covers interleaved reasoning/text, differing inputs, below-threshold, a broken streak, and pending calls. Full session suite (83) green.

…ort as a clean stop

- Cap transient-error retries at MAX_RETRY_ATTEMPTS (10) per message
  generation. The while(true) retry loop was unbounded, and retry.ts marks
  any JSON body with an 'error' field as retryable, so a persistently-failing
  provider (or a permanent error arriving as JSON) retried forever. (#7)
- Doom-loop detection now scans the last N *tool* parts (isDoomLoop helper)
  instead of the last N raw parts. Reasoning models emit a reasoning part
  before each tool call, so the last 3 raw parts were never 3 identical tool
  parts and the guard never fired against a genuinely looping tool. (#10)
- A user-initiated abort no longer fires the session Error event: it's a clean
  cancellation, so record it on the message (turn still stops) but don't
  surface it as an error state in the UI. (#51)
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openscience Ready Ready Preview, Comment Jul 7, 2026 3:46am

Request Review

@aayambansal Aayam Bansal (aayambansal) merged commit c9e0d76 into main Jul 7, 2026
11 checks passed
@aayambansal Aayam Bansal (aayambansal) deleted the fix/session-spend-safety branch July 7, 2026 03:47
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.

1 participant