feat: back the per-chat cost endpoint with AI Gateway data - #27328
Conversation
Docs previewCheck off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 955196e618
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5aae0e1845
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65369cd937
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 961d7d0a57
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fdcfe50486
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f427c6f957
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c0b3da4b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c0b3da4b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
1 similar comment
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
0afa840 to
5468559
Compare
|
@codex review |
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
5468559 to
0389c65
Compare
This stack of pull requests is managed by Graphite. Learn more about stacking. |
0389c65 to
3885435
Compare
GetAIBridgeChatCost now aggregates token usage per interception in a CTE instead of relying on COUNT(DISTINCT) over the joined rows. The reported counts are unchanged, but a request that records several provider responses is now visibly aggregated once, and the unpriced flag reads as 'this request had usage we could not price'. Correct the SDK doc and the sidebar copy to match: a partially priced request still contributes its priced usage to the total, so the note now says the total excludes unpriced usage rather than whole requests. Add coverage for a partially priced request, a request priced at zero, a sibling root chat tree, and a member reading the cost of a chat they own.
…rol experiment gate The ai-gateway-cost-control experiment was removed upstream, so gate the per-chat cost row on the aibridge feature alone.
cc9086e to
e7a7fba
Compare
|
Force-pushed after rebasing the stack onto Upstream #27579 removed the Change here: the per-chat cost row is gated on the Validated per branch:
|
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e7a7fbad85
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e7a7fbad85
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
johnstcn
left a comment
There was a problem hiding this comment.
Backend looks good to me, just one test coverage gap I see. Deferring explicit approval to Susana and Danielle.
A request that fails upstream still ends but records no token usage, so the inner join dropped it from request_count. Left-join eligible usage instead, and guard the unpriced check on the usage row existing so a request with no usage is not reported as unpriced.
DanielleMaywood
left a comment
There was a problem hiding this comment.
Leaving Approval to Susana but otherwise the frontend is fine
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e225bccacf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The cost endpoint only totals retained AI Gateway records, so state the retention caveat where the endpoint is introduced rather than later in the stack. Also assert UnpricedRequestCount in the root-resolve test and inline the single-use story parameters constant.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6a706b5753
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
chats.parent_chat_id and chats.root_chat_id are both ON DELETE SET NULL, so deleting a root leaves descendants with only a parent. Resolve the cost tree with the same COALESCE(root_chat_id, parent_chat_id) precedence the chat queries use, on both the endpoint and the frontend cache key.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 432b4b16b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…t tree The cost cache key and the watch-event invalidation key resolved the tree differently, so an event on a chat whose root was deleted left a mounted cost stale. Both now use one getChatCostTreeID helper, which also trims blank IDs that a nullish check would accept.
|
@codex review |
|
Codex Review: Didn't find any major issues. Delightful! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |

Stack Context
This stack removes native chat cost tracking and native chat usage limits, making the AI Gateway the single source of AI spend data and budget enforcement.
What?
GET /api/experimental/chats/{chat}/costsummedchat_messages.total_cost_micros, which native chat cost tracking maintained. It now aggregates AI Gateway interception data instead, and has no native fallback.GetAIBridgeChatCostquery, authorized through the root chat so members can read their own chat's cost without gaining access to raw interception rows.priced_message_count->request_count,unpriced_messages_having_usage_count->unpriced_request_count.GetChatModelUsageCostByChatIDand the rest of native cost tracking are untouched here; PR 3 removes them.Why?
Native cost tracking duplicates what the AI Gateway already records, and the two disagree. Repointing the endpoint first means the cost UI keeps working while the native implementation is deleted later in the stack.
Two behaviour changes follow from gateway semantics and are intentional:
Attribution and counting semantics
The aggregate groups token usage per interception before counting, so the reported numbers are per request even though a request records one usage row per provider response:
RequestCountcounts finishedCoder Agentsinterceptions in the tree, including unpriced ones.UnpricedRequestCountcounts requests with at least one usage row the gateway could not price. It is a subset ofRequestCount.TotalCostMicrosomits only unpriced usage, so a partially priced request still contributes its priced portion. The sidebar therefore saysExcludes unpriced usage from N request(s)rather than claiming whole requests were dropped.A recorded cost of zero is a free request, not an unpriced one. Usage without an effective group is excluded, matching what never reached
ai_user_daily_spend.Authorization
Reads go through
ExtractChatParamplusResourceChat, with no cost-specific RBAC widening.TestGetChatCost/MemberCanReadOwnChatcovers a scopedagents-accessmember reading their own chat's cost, andMemberCannotReadOtherUsersChatstill asserts 404 for a non-owner. Plain members withoutagents-accesscannot create or read chats at all, so they never reach this endpoint.Known limitation
AI Gateway data has its own retention period, 60 days by default and configured independently of chat retention, so spend for requests older than that is no longer reported. A chat whose gateway records have all been purged reports zero cost, which is indistinguishable from genuinely free usage under this contract. The endpoint documents the caveat; #27330 documents it on the Spend Management page.
In-flight interceptions are excluded, since cost is only known once the response is recorded. A chat's cost therefore lags the active turn by one request.
Rebase note
Rebased onto
mainafter #27579 removed theai-gateway-cost-controlexperiment. The per-chat cost row is now gated on theaibridgefeature alone, matching how #27579 degated the other cost-control surfaces.