Skip to content

fix(ai): retry pre-output stream failures - #421

Merged
code-yeongyu merged 2 commits into
mainfrom
fix/digitalocean-stream-retry
Jul 28, 2026
Merged

fix(ai): retry pre-output stream failures#421
code-yeongyu merged 2 commits into
mainfrom
fix/digitalocean-stream-retry

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • retry OpenAI-compatible stream failures that occur before the first wire chunk using the existing bounded, abortable provider retry policy
  • recognize the exact property-less DigitalOcean gateway error while leaving arbitrary property-less errors non-retryable
  • stop retrying after any chunk has been received, preventing duplicate assistant text or tool effects
  • preserve underlying async-iterator cleanup when a consumer exits early
  • add deterministic unit coverage and an isolated real-CLI mock-loop scenario

Verification

  • RED -> GREEN: npx vitest run test/openai-completions-retry.test.ts
    • exact DigitalOcean error recovers with one retry
    • retry exhaustion is bounded
    • status 400 is not retried
    • failure after the first content chunk is not retried
  • Reviewer blocker RED -> GREEN: npx vitest run test/provider-retry.test.ts
    • early consumer cancellation now forwards to the provider iterator's return()
  • Focused suite: npx vitest run test/provider-retry.test.ts test/openai-completions-retry.test.ts (13/13)
  • Static validation: npm run check
  • Real CLI: node .agents/skills/senpi-qa/scripts/mock-loop-stream-retry.mjs
    • exact SSE error on request 1
    • successful response on request 2
    • exactly one final marker
    • isolated sandbox and real-auth integrity checks
  • Standard real CLI regression: node .agents/skills/senpi-qa/scripts/mock-loop.mjs --self-test --api openai-completions (20/20)
  • HEAVY reviewer: unconditional APPROVE after the iterator-cancellation blocker was fixed and revalidated

Summary by cubic

Fixes OpenAI-compatible streaming by retrying failures before the first SSE chunk and ensuring onResponse fires once in the right order. Handles DigitalOcean’s “stream failed” error, avoids duplicate output, and preserves iterator cleanup.

  • Bug Fixes
    • Added retryProviderStreamRequest to prefetch the first chunk under the existing bounded, abortable provider retry policy.
    • Treated the exact DigitalOcean error “Upstream error from DigitalOcean: stream failed” as retryable; other property-less errors remain non-retryable.
    • Switched openai-completions to the new stream retry wrapper; onResponse now fires only after a successful prefetch and before start, preserving callback ordering.
    • Disabled retries once the first chunk is seen to prevent duplicate assistant text or tool effects.
    • Forwarded early consumer cancellation to the provider stream’s return() for proper cleanup.
    • Added targeted tests and a mock CLI loop to validate recovery, bounds, and non-retryable cases.

Written for commit 6012db5. Summary will update on new commits.

Review in cubic

@code-yeongyu
code-yeongyu enabled auto-merge July 28, 2026 08:00
@code-yeongyu
code-yeongyu merged commit fabdaf7 into main Jul 28, 2026
11 checks passed
@code-yeongyu
code-yeongyu deleted the fix/digitalocean-stream-retry branch July 28, 2026 08:40
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