Skip to content

feat(core): capture provider-reported cost in OpenAI-compatible streaming - #2243

Open
tripplen23 wants to merge 2 commits into
0xPlaygrounds:mainfrom
tripplen23:feat/streaming-cost
Open

feat(core): capture provider-reported cost in OpenAI-compatible streaming#2243
tripplen23 wants to merge 2 commits into
0xPlaygrounds:mainfrom
tripplen23:feat/streaming-cost

Conversation

@tripplen23

Copy link
Copy Markdown

Fixes #2242

Summary

OpenAI-compatible gateways such as OpenCode Go report per-request monetary cost in the chat-completions stream, but rig drops it. OpenCode Go emits a dedicated inference-cost SSE chunk after the usage chunk:

{choices: [], x-opencode-type: inference-cost, cost: 0.00006972, normalizedUsage: {...}}

(cost arrives as a string; some gateways send a number.) Without this change, callers must re-derive cost from token counts using per-model price tables that drift over time.

Changes

  • Capture: StreamingCompletionChunk parses the top-level cost field (string or number).
  • Thread: cost flows through CompatibleChunk → the streaming loop → build_final_response, mirroring how usage already flows. The last chunk carrying a cost wins.
  • Surface: StreamingCompletionResponse::cost and, via token_usage(), completion::Usage::cost — agent runs and telemetry see it without extra plumbing.
  • Usage::cost defaults to None; Eq is now implemented manually since the new field is Option<f64> (providers report finite decimals only).

Tests

  • test_streaming_captures_provider_reported_cost: full stream with an inference-cost chunk, asserts response cost + token_usage().cost.
  • test_streaming_chunk_parses_cost_string_or_number: string, number, and absent cost.

cargo test -p rig-core (1023 tests) and strict clippy pass locally.

…ming

OpenCode Go and other OpenAI-compatible gateways report per-request cost in
the chat-completions stream (OpenCode Go emits a dedicated `inference-cost`
chunk with a string `cost` field; some gateways send a number). The value was
silently dropped because StreamingCompletionChunk ignores unknown fields, so
callers could not report real spend without maintaining per-model price
tables.

Parse the top-level `cost` field (string or number) and thread it through
CompatibleChunk and the streaming loop, mirroring how `usage` flows, then
surface it on StreamingCompletionResponse::cost and propagate it into
completion::Usage::cost via token_usage() so agent runs and telemetry see it.

Adds `Usage::cost` (defaults to None; `Eq` now implemented manually since
f64 is not Eq). No breaking changes to deserialization.
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.

feat: capture provider-reported cost from OpenAI-compatible streaming responses

1 participant