* feat(cli): filter usage by billing route and mode
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.
* feat(opencode): preserve OpenRouter route provenance
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.
* feat(opencode): classify Amazon Bedrock route
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.
* docs(opencode): document billing route provenance
---------
Co-authored-by: ozymandiashh <234437643+ozymandiashh@users.noreply.github.com>
When none of a session's messages produce a priced call, the SQLite
parser falls back to the totals on OpenCode's session row. That path
passed tokens_output alone to calculateCost and dropped
tokens_reasoning, while still reporting reasoningTokens, so thinking
tokens were shown but never charged. OpenCode bills reasoning at the
output rate and the per-message path already did the same.
Route both the fallback and buildAssistantCall through
billableOutputTokens so they share one rule with the cache-rehydration
path. The per-message change is behaviour-neutral for opencode and
kilo-code; it only removes the hand-rolled sum that let the fallback
drift.
Refs #1334
The Skills & Agents panel was always empty for OpenCode sessions even
when skills and subagents were used. buildAssistantCall (shared by the
OpenCode SQLite and file-based parsers, and Kilo Code) counted the
skill/task tool invocations but never read the skill name or subagent
type from the tool-call input, so the dedicated breakdowns had no names
to aggregate.
In OpenCode's part files the identifier lives in state.input: the skill
tool carries input.name and the task tool carries input.subagent_type.
Extract both in buildAssistantCall and surface them on
ParsedProviderCall.skills / .subagentTypes, then stop hard-coding
skills: [] in providerCallToTurn and providerCallToCachedCall so the
classifier's subCategory and the subagent breakdown receive the data.
Verified against real OpenCode data: the previously empty skills[] and
subagents[] now populate (pipeline-investigation, plan-spec, splunk, ...
and explore/general subagents).
Fixes#556
Co-authored-by: Kevin Addison <kevin.addison3@tesco.com>
OpenCode 1.1+ stores sessions as file-based JSON under
storage/{session,message,part}/ instead of a SQLite DB, so the
SQLite-only provider discovered zero sessions on current installs and
reported no usage at all.
Add a file-based discovery and parser path, preferred when present and
falling back to the SQLite DB for pre-migration installs. Extract the
shared message-to-call logic (token extraction, tool and bash parsing,
cost) into session-message.ts so the file path, the SQLite path, and
Kilo Code stay identical.