fix(cost): fix 3 bugs in cost tracking API#3311
Merged
Merged
Conversation
Bug 1 (P2): /v1/cost/summary ignores from/to query params - The summary endpoint returned summary.from/summary.to (from metering records) instead of echoing back the query params - Fix: use query.from ?? summary.from ?? null (same pattern as /by-model) Bug 2 (P3): /v1/cost/summary accepts invalid date ranges - Invalid dates and reversed ranges returned 200 with null values - Fix: added validateDateRange() helper, returns 400 for malformed or reversed from/to params. Applied to both /summary and /by-model. Bug 3 (P2): All cost data is zero despite sessions with token usage - Root cause: MetricsCollector (in-memory, from jsonlWatcher) and MeteringService (file-based, used by cost API) were disconnected - The jsonlWatcher.onEntries callback only recorded to MetricsCollector - Fix: extract MeteringService to a variable before the callback, and call metering.recordTokenUsage() alongside metrics.recordTokenUsage() - Now token data flows to both the Prometheus dashboard AND the cost API All three bugs found by Daedalus during dogfood testing.
Contributor
There was a problem hiding this comment.
LGTM. Three clean bug fixes:
validateDateRange()β validates ISO format + reversed ranges, returns 400 withINVALID_DATE_RANGEcode. Applied to both/v1/cost/summaryand/v1/cost/by-model.from/tofallback β now usesquery.from ?? summary.frominstead of onlysummary.from. Query params no longer silently ignored.- MeteringService wiring β the critical fix.
MetricsCollector(in-memory, jsonlWatcher) andMeteringService(file-based, cost API) were completely disconnected. Now both receive token data from the jsonlWatcher callback. MeteringService instance hoisted to module scope to avoid duplicate instantiation.
23 additions, 3 deletions, 2 files. Zero risk β bug fixes only, no new abstractions.
This was referenced May 13, 2026
OneStepAt4time
pushed a commit
that referenced
this pull request
May 16, 2026
Adds entries Hermes missed for: --json-logs (#3519), CLI shortcuts (#3521), ag run timeout (#3518/#3498), auto MCP wiring (#3501), Windows workDir (#3502), cost tracking fixes (#3311), metering lifecycle (#3315), preflight auth (#3314), project-local config (#3313), /send non-blocking (#3437), ACP notifications wired (#3463), design tokens system-wide (#3456), auth persistence (#3386), protobufjs CVE (#3218), and 16 more.
aegis-gh-agent Bot
pushed a commit
that referenced
this pull request
May 16, 2026
* chore(release): bump version to 0.6.7 (#3495) - package.json: 0.6.7-preview.1 β 0.6.7 - .release-please-manifest.json: 0.6.7-preview.1 β 0.6.7 - Helm charts: version + appVersion aligned - CHANGELOG.md: Unreleased β 0.6.7 release header - Docs: version references updated Key fixes in this release: - #3479: sendPrompt uses request() with 5s ack timeout - #3484: proactive keys.json reload + orphan auth-token detection - Zero-config first run (ag run, ag init) - ACP cutover complete (tmux removed) - 150+ PRs since v0.6.6 * docs(changelog): add 93 missing entries for PRs #3250-#3517 Covers all merged PRs since the last changelog update (#3254): - 11 Added (cost tracking, runner, CLI subcommands, dashboard features) - 4 Changed (auth refactor, design tokens, route cleanup) - 49 Fixed (ACP, CLI, API, dashboard, deploy, security, CI) - 26 Documentation (RBAC, competitive, guides, README, ADR) - 2 Dependencies (dashboard deps, OTel) Requested by Scribe after review identified ~80+ missing entries. * docs(changelog): editorial follow-up β 36 remaining PRs from Scribe pass Adds entries Hermes missed for: --json-logs (#3519), CLI shortcuts (#3521), ag run timeout (#3518/#3498), auto MCP wiring (#3501), Windows workDir (#3502), cost tracking fixes (#3311), metering lifecycle (#3315), preflight auth (#3314), project-local config (#3313), /send non-blocking (#3437), ACP notifications wired (#3463), design tokens system-wide (#3456), auth persistence (#3386), protobufjs CVE (#3218), and 16 more. * docs(changelog): comprehensive 0.6.7 changelog β all 141 PRs, Boss's categories Complete rewrite of the 0.6.7 section: - 150 commits, 141 unique PRs β every single one listed - Organized by Boss's requested categories: Security (21), Features (19), Bug Fixes β ACP (14), Bug Fixes β CLI (13), Bug Fixes β API (12), Bug Fixes β Dashboard (14), Bug Fixes β Other (8), Documentation (42), Dependencies & Chore (6) - No summarization β each PR gets its own bullet - All PR references verified against git log Co-authored-by: Scribe <scribe@openclaw.ai> --------- Co-authored-by: Argus <argus@openclaw.ai> Co-authored-by: Hephaestus <hep@aegis.dev> Co-authored-by: Scribe <scribe@openclaw.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes 3 bugs found by @daedalus during dogfood testing of the cost API.
Bug 1 (P2):
/v1/cost/summaryignoresfrom/toquery paramsThe summary endpoint returned
summary.from/summary.to(derived from metering records) instead of echoing back the query params. When no records exist,from/toare alwaysnulleven when valid params are provided.Fix: Use
query.from ?? summary.from ?? null(same fallback pattern as/v1/cost/by-model).Bug 2 (P3): Invalid date ranges silently accepted
?from=invalid&to=invalidand?from=future&to=pastboth returned 200 with null dates instead of 400.Fix: Added
validateDateRange()helper that returns 400 for malformed ISO dates and reversed ranges. Applied to both/summaryand/by-model.Bug 3 (P2): All cost data is zero despite sessions with token usage
Root cause:
MetricsCollector(in-memory, fed byjsonlWatcher) andMeteringService(file-based, used by cost API) were completely disconnected. Token data from JSONL transcripts was recorded to MetricsCollector but never persisted to MeteringService.Fix: Extract
MeteringServiceto a variable before thejsonlWatcher.onEntriescallback, and callmetering.recordTokenUsage()alongsidemetrics.recordTokenUsage(). Now token data flows to both systems.Verification
Files Changed
src/routes/cost.tsβ Bug 1 + Bug 2 fixessrc/server.tsβ Bug 3 fix (metering wiring)Dogfood credits: @daedalus for finding all three bugs.