Conversation
Carry provider-observed billing provenance through Hermes and the session cache, register the real OpenRouter route, and add call-level route/billing filters to models, sessions, export, and audit. Keep unknown billing unclassified, preserve existing pricing, and repair legacy included Hermes ledger baselines without rewriting genuine multi-observation history.
Carry OpenCode providerID through legacy SQLite, v2, file, and session-rollup paths so OpenRouter calls remain distinct from direct traffic. Invalidate OpenCode and KiloCode caches and cover strict route matching.
ozymandiashh
left a comment
There was a problem hiding this comment.
Reviewed the full diff plus the follow-up OpenCode provenance commit. Approving from my side — the PR is merge-ready whenever you flip it out of draft.
What I verified against the corpus conventions:
- Every claim in the body maps to code: billing provenance plumbed ParsedProviderCall → ParsedApiCall → CachedCall → turns;
--route/--billingon models/sessions/export/audit with theassertRoute/assertBillingmirroring ofassertProvider; call-level slicing with rebuilt totals; the Hermes v3 ledger repair. Deferrals are stated and genuinely absent, not half-done. - The route registration stays exact-literal through
routeFromProviderField— the negative tests ('OpenRouter', ' openrouter ', model-id prefixes) hold, and the new OpenCodeproviderID→ route passthrough uses the same helper rather than a second mapping, so no alias-without-evidence creeps in. - Warm-cache invalidation is the intended mechanism (
PROVIDER_PARSE_VERSIONSbump) and upgrade-path CI confirms it; the unfiltered path returns the input by identity, new payload fields are additive, and the one visible output change — a separate(OpenRouter)row for Hermes OpenRouter sessions — is the feature per #1448's row-key design.
One non-blocking note I'd keep in mind: carryLinkageFields now also carries agentName/agentStartedAt, which slightly widens that function beyond the PR's stated scope (benign — fields previously dropped are now preserved — but worth a line in the body if you get a chance).
Relative to #1451 this lands the call-level CLI slice (4 of 6 commands, openrouter registration, billing-mode provenance); the payload/tab-strip half stays open as you scoped it.
Map OpenCode's exact amazon-bedrock providerID to the existing metered Bedrock route, including model families that cannot rely on Anthropic/OpenAI ID shapes. Invalidate OpenCode and KiloCode caches across the route expansion.
|
@ozymandiashh Thanks for the review. I addressed the non-blocking scope note by stating explicitly in the PR summary that filtered rebuilds preserve the existing Since your review at Current verification: 4,324 local tests plus 36 serial lock tests passed; build and upgrade verification passed; the final GitHub run has 19 successful checks, one expected skipped release-asset check, and no failures or pending jobs. Independent reviews of the post-review OpenCode and Amazon Bedrock deltas found no remaining issues. The PR body now says |
ozymandiashh
left a comment
There was a problem hiding this comment.
Re-reviewed the two commits pushed after my earlier approval (dismissed as stale): the amazon-bedrock registration follows the same exact-literal discipline as openrouter — evidence-backed spelling, no invented aliases, case/whitespace normalization kept only for Hermes' shipped bedrock — and the billing-routes-v2 parse-version bump invalidates both the shared OpenCode/Kilo cache and pre-merge builds of this PR, which is the right warm-cache treatment. Docs and the route/cache-invalidation tests cover it. Still approving; from my side this is merge-ready whenever you are.
getagentseal#1491 moved the models command's floor and --top slice from aggregateModels to the call site (unfiltered fetch + local floor + the unpriced disclosure line). This merge keeps that fetch and applies the PR's own rule at the floor: --route/--billing is an explicit request for those rows, so the noise floor lifts for them too, and the disclosure line only prints when a floor actually dropped something.
ozymandiashh
left a comment
There was a problem hiding this comment.
Merge-conflict resolution reviewed: keeps #1491's unfiltered fetch, local floor, slice and disclosure line, and lifts the floor for --route/--billing exactly as this PR intended. 147 tests green locally across this PR's suites (billing-route e2e, opencode routes, cache invalidation) plus the #1420 suite. Approving again after the push.
Summary
Part of #1451. Builds on #1448, which resolved #1450. This PR is the first call-level CLI slice; it does not close #1451.
billing: 'metered' | 'subscription'provenance on provider, parsed, and cached calls. Hermesincludedis subscription-covered,actual(including explicit $0) is metered, registered routes supply a default only when the provider recorded no billing fact, and everything else stays unknown.openrouteras the OpenRouter metered route and OpenCode'samazon-bedrockas the Bedrock metered route. Preserve them from Hermesbilling_providerand OpenCodeproviderIDacross legacy SQLite, v2session_message, file storage, and session-rollup fallbacks, with no speculative aliases. Bedrock remains the only id-shape route.--route direct|bedrock|openrouterand--billing metered|subscriptionfilters tomodels,sessions,export, andaudit. Mixed sessions contribute only matching calls; rebuilt totals retain session linkage plus existingagentName/agentStartedAtmetadata.$0route/subscription rows remain visible by default; an explicit--min-coststill wins.directis documented as direct-or-unknown, and unknown billing matches neither billing filter.actual, without relabeling genuine multi-observation histories.Still open in #1451:
today/report/status,compare, menubar payload fields, daily-cache v34, and native/web UI. Those need durable structured route/billing aggregates.sessions --by-work-unitwith either new filter is rejected before parsing rather than inferring filtered-out roots.Testing / Verification
npm testpassesnpm run buildsucceedsExact base/branch comparison on Node 22:
0f5a3345: 4,278 passed / 5 skipped / 0 failed.7d6f573e: 4,324 passed / 5 skipped / 0 failed — 46 added tests, zero new failures.npm run test:locks: 36 passed on base and branch.npx tsc --noEmit: clean.npm run build: CLI and dashboard built.npm run verify:upgrade: passed (1 warm-run observation skipped by the harness).src/providers/andsrc/parser.ts: 0 findings / 0 errors.Real data, this machine:
The first two OpenRouter rows come from two fresh Hermes sessions against
https://openrouter.ai/api/v1: oneopenrouter/freecoding task that readsrc/models.ts(4 upstream calls, 107,456 input / 668 output tokens) and one explicitcohere/north-mini-code:freerequest (15,001 input / 69 output tokens). Both were zero-cost.OpenCode 1.18.31 was then run independently with
openrouter/cohere/north-mini-code:freeagainst this PR'ssrc/models.ts. Its on-disk messages recordedproviderID=openrouter,modelID=cohere/north-mini-code:free, three assistant calls, and zero reported cost. Before the extension CodeBurn parsed those calls asroute=null; after it, fresh isolated cold and warm caches both returnroute=openrouter,--route directexcludes them, and--billing meteredincludes them.Two OpenCode Amazon Bedrock sessions were also run through the AWS SDK credential chain in
us-east-1.amazon-bedrock/openai.gpt-5.6-solrecordedproviderID=amazon-bedrock,modelID=openai.gpt-5.6-sol, one call, and $0.1261678; CodeBurn classified it as Bedrock by both provider evidence and the existing model shape.amazon-bedrock/amazon.nova-2-lite-v1:0recorded the same provider field with a Nova id that the model-shape detector deliberately does not recognise; this proves the new provider-field path itself. Cold and warm caches classify both asroute=bedrock/billing=metered, and--route directexcludes both.The regression suite covers exact
openrouterandamazon-bedrockroute detection with negative aliases, OpenCode legacy SQLite/v2/file/session-rollup storage, OpenCode and KiloCode cache invalidation across both route additions, fallback model normalization, billing precedence, Hermes cost-basis transitions and vanished sources, session-cache validation/round trips, mixed-call totals and metadata, midnight re-anchoring, all four CLI surfaces, validation-before-export, resident serve allowlists, and the legacy v3 included-baseline repair.For new providers only:
Not applicable: this adds billing-route provenance to existing Hermes and OpenCode providers; it does not register a new coding-harness provider.
Affiliation: none. I use Bedrock and OpenRouter alongside fixed-fee coding subscriptions and need their billing paths to remain distinct.