feat(ai): track real usage for BYOK provider calls - #3382
Conversation
callAiProvider never read the usage field from Anthropic/OpenAI's raw response body, so BYOK calls populated no provider/token/cost data in ai_usage_events even though the maintainer bills these to their own account. Normalize both providers' native usage envelopes into the same shape the free/self-host path already produces, and price tokens against a static per-model USD table (absent model -> costUsd stays undefined, never fabricated).
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3382 +/- ##
=======================================
Coverage 93.46% 93.46%
=======================================
Files 287 287
Lines 30763 30781 +18
Branches 11210 11219 +9
=======================================
+ Hits 28752 28770 +18
Misses 1355 1355
Partials 656 656
🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-05 05:50:37 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 4 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
…dency (#3421) Address gittensory-orb review nits on #3382: note the pricing table's source/verification date, cross-reference coerceByokUsage's indirect dependent in ai-slop.ts, and add a test forcing the totalTokens fallback through OpenAI's field names specifically (previously only exercised via Anthropic's).
Summary
callAiProviderinsrc/services/ai-review.tsis the shared HTTP helper for every BYOK (bring-your-own-key) AI call — used by ai-review.ts's BYOK advisory write-up and ai-slop.ts's BYOK slop-advisory path. It POSTs directly tohttps://api.anthropic.com/v1/messagesorhttps://api.openai.com/v1/chat/completionsbut only ever returned{ text }, discarding the response body'susagefield. That meant BYOK calls never populatedprovider/effort/input_tokens/output_tokens/total_tokens/cost_usdinai_usage_events(migration 0109's columns), even though the maintainer is billing these calls to their own Anthropic/OpenAI account in real dollars.This PR:
callAiProvider's return type with an optionalusagefield.coerceByokUsage()to normalize Anthropic'susage: {input_tokens, output_tokens}and OpenAI'susage: {prompt_tokens, completion_tokens, total_tokens}— both snake_case, provider-specific — into the sameAiReviewActualUsageshapecoerceAiUsagealready produces for the free/self-host path.BYOK_MODEL_PRICING_USD_PER_MTOK) to computecostUsd, since neither provider's API reports a dollar figure directly. A model absent from the table leavescostUsdundefined rather than fabricated.usagefield throughrunProviderReview's diagnostic in ai-review.ts (flows automatically into the existingaggregateActualUsage/record()/recordAiUsageEventplumbing — no other changes needed there) and into ai-slop.ts's BYOK branch.Not in scope (flagged for a possible follow-up, not a defect in this PR): Anthropic's
usageobject can carrycache_creation_input_tokens/cache_read_input_tokensat different price multipliers when prompt caching is active.callAiProvidernever sends acache_controlmarker on its request body, so Anthropic never populates those fields on this path today — documented inline so a future reader doesn't need to rediscover this.Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally — 100% branch/line coverage on every changed line, verified via lcov diff-mapping against the exact hunks in this diff.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderate— 0 vulnerabilities.ai-review.test.ts/ai-slop.test.tscovering both providers, priced/unpriced models, partial usage fields, and malformed response bodies.Safety
UI Evidencesection below with screenshots. (N/A — no visible UI changes; backend-only.)Notes