Skip to content

fix: partially settle chat completions aborts - #11455

Merged
lalalune merged 1 commit into
developfrom
fix/11169-completions-abort-settle
Jul 2, 2026
Merged

lalalune merged 1 commit into
developfrom
fix/11169-completions-abort-settle

Conversation

@lalalune

@lalalune lalalune commented Jul 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Partially settle /api/v1/chat/completions streaming reservations on client abort instead of refunding the full hold with settleReservation(0) after text deltas were already sent.
  • Track successfully enqueued text deltas and price abort settlement from the existing prompt estimate plus delivered output-token estimate; finished-step usage is used when the AI SDK provides it.
  • Preserve provider-error behavior: provider 400/429/503 and fullStream provider errors still release the hold to 0.

Refs #11169. This targets part 4 only; the part 3 durable stranded-reservation sweep remains separate money-infra work.

Evidence

Artifact: .github/issue-evidence/11169-completions-abort-partial-settle.md

Verified after rebasing onto latest origin/develop:

  • ELIZA_SKIP_ARTIFACT_SYNC=1 bun install
  • bun test --conditions eliza-source --pass-with-no-tests __tests__/chat-completions-streaming-credit-leak.test.ts — 7 pass
  • bun test --conditions eliza-source --pass-with-no-tests __tests__/chat-stream-credit-leak.test.ts — 6 pass
  • bun test --conditions eliza-source --pass-with-no-tests __tests__/chat-completions-optimistic-billing.test.ts — 5 pass
  • bun test --conditions eliza-source --pass-with-no-tests __tests__/chat-completions-tool-choice.test.ts — 18 pass
  • bun run --cwd packages/cloud/api typecheck — pass
  • bun run --cwd packages/cloud/api build — pass
  • bunx @biomejs/biome check packages/cloud/api/v1/chat/completions/route.ts packages/cloud/api/__tests__/chat-completions-streaming-credit-leak.test.ts — pass
  • git diff --check HEAD — pass
  • bun run verify — pass

N/A: UI screenshots/video and native capture; backend billing/stream settlement route only.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7b7dd0d8-7ce8-4dc6-9b28-e3da7284dba5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/11169-completions-abort-settle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@lalalune
lalalune merged commit f0cb8d3 into develop Jul 2, 2026
38 of 43 checks passed
@lalalune
lalalune deleted the fix/11169-completions-abort-settle branch July 2, 2026 12:55
lalalune pushed a commit that referenced this pull request Jul 2, 2026
…ll-refund (#11513)

A client abort on a streaming /api/v1/messages request settled the credit
reservation to 0 (full refund) in both onAbort and the stream-catch backstop,
even though the platform had already paid the upstream provider for the prompt
and every token delivered before the disconnect — an uncollected-revenue leak.
/v1/chat/completions was fixed for this in #11455/#11472; this ports the same
mechanism to /v1/messages:

- accumulate delivered text-delta output during the stream
- on abort (onAbort AND the catch path when the request signal is aborted),
  bill max(estimated input, finished-step input) + max(estimateTokens of
  delivered text, finished-step output) and settle the reservation to that
  partial cost, recording the usage as client_aborted_stream
- single-flight the terminal settlement across onFinish/onAbort/onError/catch
  so racing abort paths cannot double-bill (mirrors #11472)
- provider errors (onError / catch without an aborted signal) still refund in
  full; a failed partial billing falls back to a full refund via the
  first-call-wins idempotent settler

Regression test drives the REAL createCreditReservationSettler against a
ledger-backed reservation through the exported handleStream seam: red on the
old route (abort settled $0, billed nothing), green with the fix.

Closes #11513

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
NubsCarson added a commit that referenced this pull request Jul 2, 2026
…ll-refund (#11513) (#11556)

A client abort on a streaming /api/v1/messages request settled the credit
reservation to 0 (full refund) in both onAbort and the stream-catch backstop,
even though the platform had already paid the upstream provider for the prompt
and every token delivered before the disconnect — an uncollected-revenue leak.
/v1/chat/completions was fixed for this in #11455/#11472; this ports the same
mechanism to /v1/messages:

- accumulate delivered text-delta output during the stream
- on abort (onAbort AND the catch path when the request signal is aborted),
  bill max(estimated input, finished-step input) + max(estimateTokens of
  delivered text, finished-step output) and settle the reservation to that
  partial cost, recording the usage as client_aborted_stream
- single-flight the terminal settlement across onFinish/onAbort/onError/catch
  so racing abort paths cannot double-bill (mirrors #11472)
- provider errors (onError / catch without an aborted signal) still refund in
  full; a failed partial billing falls back to a full refund via the
  first-call-wins idempotent settler

Regression test drives the REAL createCreditReservationSettler against a
ledger-backed reservation through the exported handleStream seam: red on the
old route (abort settled $0, billed nothing), green with the fix.

Closes #11513

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error —— View job


I'll analyze this and get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant