feat(providers): Codex/OpenCode local telemetry; stop showing unknown cost as $0 - #26
Merged
Merged
Conversation
…nown cost as $0
Codex and OpenCode now feed the same expanded telemetry card that pi and
Hermes use, and the cost pipeline stops turning missing data into $0.
Local harness telemetry:
- New providers/get-local-analytics reads usage metadata (never prompts or
responses) from Codex rollout sessions and the OpenCode SQLite store,
emitting the shared window shape in scripts/local-analytics.jq: 7-day
chart, top models, top projects, and per-window input/output/cache/
reasoning/session counters.
- Codex token_count events carry cumulative counters that are re-emitted
unchanged on turns adding no tokens, so only positive deltas are summed;
a counter reset restarts from zero instead of producing a negative row.
last_token_usage is deliberately unused, as it repeats too.
- opencode reports from the local database by default, so the card works
for the free and third-party models used through OpenCode without an
OpenCode Zen subscription; the Zen quota path is unchanged and still
used when no local database exists or OPENCODE_USAGE_SOURCE=api is set.
get-provider-health follows the same rule instead of always demanding
an API key.
- Both scans are cached for 120s like the pi and Hermes adapters: a Codex
scan spawns one jq per session file and took ~5s, far too much to repeat
on every widget poll. The cache records the source path it scanned, so a
snapshot is never replayed for a different CODEX_HOME/OPENCODE_DATA_DIR
and a vanished source errors instead of serving stale telemetry.
Cost honesty:
- Hermes rows with cost_status = 'unknown' were summed as if measured,
mixing placeholder estimates (one row alone claimed ~$180k) into the
displayed spend. providers/local-cost-common now centralizes the rule so
the summary and analytics adapters cannot drift: unknown makes the window
unknown, 'included' counts as a true 0, and a window totals only when
every row has a known cost. Ledgers predating cost_status fall back to
positive values only, since a default 0 cannot establish a free request.
- pi sessions reporting 0 cost alongside non-zero tokens (unpriced or
custom models) are treated as unknown rather than free.
- formatCost renders unknown as "—" and sub-cent amounts as "<$0.01", so
"no data" and "no charge" are visually distinct. The cards carry a note
that local costs may be estimates, and the 7-day chart scales by tokens
so it stays meaningful when costs are unknown.
Also: weekday labels came from jq's locale-dependent strftime("%a"), so
two cards could disagree on the same day ("qua" next to "Wed"); the widget
now derives them from the row's ISO date. package-release asserts the new
runtime files ship, since a release missing scripts/local-analytics.jq
would break only at runtime.
CI's "Confirm all scripts are executable" gate requires the mode bit on every tests/*.sh; the new suite was committed as 100644.
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
Codex and OpenCode now feed the same expanded telemetry card that pi and Hermes use, and the cost pipeline stops turning missing data into
$0.Local harness telemetry
providers/get-local-analyticsreads usage metadata (never prompts or responses) from Codex rollout sessions and the OpenCode SQLite store, emitting the shared window shape inscripts/local-analytics.jq: 7-day chart, top models, top projects, per-window input/output/cache/reasoning/session counters.token_countevents carry cumulative counters and are re-emitted unchanged on turns that add no tokens, so only positive deltas are summed; a counter reset restarts from zero instead of producing a negative row.last_token_usageis deliberately unused, as it repeats too.opencodereports from the local database by default, so the card works for free and third-party models used through OpenCode without an OpenCode Zen subscription. The Zen quota path is unchanged and still used when no local database exists orOPENCODE_USAGE_SOURCE=apiis set;get-provider-healthfollows the same rule instead of always demanding an API key.jqper session file and took ~5s, far too much per poll (now 16ms warm). The cache records the source path it scanned, so a snapshot is never replayed for a differentCODEX_HOME/OPENCODE_DATA_DIR, and a vanished source errors instead of serving stale telemetry.Cost honesty
cost_status = 'unknown'were summed as if measured, mixing placeholder estimates (one row alone claimed ~$180k) into displayed spend.providers/local-cost-commoncentralizes the rule so the summary and analytics adapters cannot drift:unknownmakes the window unknown,includedcounts as a true 0, and a window totals only when every row has a known cost. Ledgers predatingcost_statusfall back to positive values only, since a default 0 cannot establish that a request was free.formatCostrenders unknown as—and sub-cent amounts as<$0.01, so "no data" and "no charge" are visually distinct. Cards carry a note that local costs may be estimates, and the 7-day chart scales by tokens so it stays meaningful when costs are unknown.Before/after on a real environment — note the week is now honestly unknown rather than a partial sum presented as the total:
Also fixed
jq's locale-dependentstrftime("%a"), so two cards could disagree on the same day (quanext toWed); the widget now derives them from the row's ISO date.package-releaseasserts the new runtime files ship — a release missingscripts/local-analytics.jqwould break only at runtime.Testing
New
tests/test-local-analytics.shcovers cumulative deduplication, model/project attribution, unknown vs. recorded zero, cache TTL and cache-key-by-source, and the Hermes cost-status rules.Local gates all pass: fixture suites,
shellcheck -S warning,bash -n,qmllint, i18n key parity.