parseChatFile estimated input tokens from pendingUserMessage - the last
human turn sliced to 500 chars - while output summed every bot char, so a
multi-turn session or any prompt over 500 chars undercounted input tokens
and therefore costUSD severalfold. Accumulate every human turn's full
length (inputChars), matching the modern-execution path; keep the 500
slice for the display userMessage only. Mutation-checked: a 2400-char
prompt reports 125 tokens before, 600 after.
v1 modern execution files carry the same metered credits as v2
(usageSummary[].usage, unit "credit" — the predecessor of v2's
promptTurnSummaries), but the parser only harvested usedTools from
that array and priced executions from estimated tokens. Since v2 only
ships in brand-new IDE builds, v1 is the format nearly all Kiro IDE
users are on today. Sum usage across usageSummary entries and price at
the public overage rate.
Align all three credit parsers (CLI, v1, v2) on one fallback contract —
gate on summed credits > 0 and fall back to token-estimated pricing
with costIsEstimated: true:
- CLI turns without metering_usage were priced at a frozen $0
- CLI turns with an EMPTY metering_usage array (75 of 10,105 real turn
metadatas — meta written before metering lands) passed the truthy
presence check and froze $0 marked as real cost
- legacy .chat calls now carry costIsEstimated: true, which was always
the reality but never stated
Validated against a real machine: 221 of 277 v1/legacy calls now carry
metered cost ($20.11) instead of token estimates that had overstated
them ~5x; verified usageSummary values are per-turn amounts, not
cumulative counters (sequences fluctuate). Call counts unchanged before
and after — nothing gained, lost, or double-counted.
Also document the companion-file fingerprint blind spot at
fingerprintFile: kiro CLI credits and v2 modelId live in companion
files the single-file fingerprint never sees, so a parse racing the
companion write can cache fallback values that only self-heal while
the transcript keeps changing.
AI-Origin: ai-generated
AI-Tool: kiro
Kiro's new IDE builds write sessions to ~/.kiro/sessions/<hash>/sess_<id>/
(session.json + messages.jsonl event log) instead of globalStorage. Add a
v2 parser and discovery, plus fixes surfaced while validating against a
real upgraded machine:
- Parse v2 event-sourced turns (user/turn_start/assistant/tool_call/
tool_result/usage_summary/turn_end) with per-execution dedup keys
(kiro-v2:<session>:<execId>) and defensive flushes for out-of-order
events and in-progress sessions
- Price turns from real metered credits at the public overage rate
(USD_PER_KIRO_CREDIT = $0.04/credit, individual plan: $20/mo for
1,000 credits), falling back to token estimation only when a turn has
no usage_summary (aborted/in-flight); costIsEstimated distinguishes
the two
- Fix pre-existing CLI parser bug: metering_usage values are credits,
not dollars — costs were overstated 25x at the real rate
- Count v2 tool_result content as input context (matching the CLI
parser's ToolResults treatment); previously only the user prompt was
counted, undercounting input ~25x on agentic turns
- Keep reasoningTokens disjoint from outputTokens: downstream
aggregation (models-report, audit-report, parser) sums the two
fields, so folding reasoning into output would double-count. Combine
them only for the token-pricing fallback, matching codex/gemini
- Take the real modelId from session.json, so v2 sessions are not
mislabeled kiro-auto
- Extract parseWorkspaceSession from the inline createParser block for
parity with the other four format parsers
- Add v2SessionsRootOverride and stop deriving the v2 scan root from
the cliDir parent when only agentDirOverride is set (tests were
scanning the system tmpdir)
- Tests: v2 parsing/discovery/dedup/routing, credit vs fallback
pricing, tool_result turn scoping, reasoning disjointness, cli-dir
skip guard, and a mixed-format coexistence suite (legacy .chat + v1
executions + workspace-sessions + CLI + v2 on one machine) asserting
exact aggregate counts and no double counting
- Docs: v2 store layout, credit pricing, dedup namespaces, and the
disjoint-store verification (v1->v2 is a clean cutover, no
migration/dual-write observed)
AI-Origin: human
Four fixes for the Kiro IDE provider:
1. Add 'entries' to extractText() key list — Kiro IDE stores message
content in context.messages[].entries (not .content), causing the
parser to extract 0 chars from every execution file.
2. Check data.context[key] for conversation arrays in parseModernExecution
— current Kiro builds store messages at data.context.messages, not at
the top-level data.messages path the parser was checking.
3. Scan both ~/.kiro-server/data/... AND ~/.config/Kiro/... on Linux —
remote dev boxes use .kiro-server while local installs use .config/Kiro.
Both can have data simultaneously; the old code short-circuited on the
first path found.
4. Discover and parse workspace-sessions/<base64>/*.json files — newer
Kiro builds write session state here with history[].message format.
Skips stub entries (executionId refs + 'On it.' only) to avoid
double-counting with execution files parsed separately.
5. Add kiro: 'ide-parsing-v1' to PROVIDER_PARSE_VERSIONS for automatic
cache invalidation — users upgrading from the broken parser will get
a fresh re-parse without manually clearing session-cache.json.
Bonus: Extract tool names from usageSummary[].usedTools, add chatSessionId
to session ID resolution, add Kiro-specific tool name mappings.
AI-Origin: human
The Kiro provider previously only detected sessions from the Kiro IDE
(VS Code-based) stored in globalStorage. This adds support for Kiro CLI
(`kiro-cli chat`) sessions stored in ~/.kiro/sessions/cli/.
CLI sessions use a different format:
- .jsonl files with Prompt/AssistantMessage/ToolResults entries
- Companion .json files with session metadata, model info, and
per-turn metering usage (credits)
Changes:
- Add CLI session discovery (scans ~/.kiro/sessions/cli/ for .jsonl)
- Add CLI JSONL parser that extracts turns, tools, and cost from
metering_usage credits
- Add CLI tool name mappings (read, write, shell, grep, glob)
- Make CLI sessions dir configurable via third param to
createKiroProvider for testability
- Add unit tests for CLI session discovery and parsing
Adds extensionless session index and nested execution file discovery
while preserving legacy .chat support. Modern execution JSON is parsed
for identifiers, timestamps, model IDs, conversation text, structured
tools, and token estimates. Also fixes dedup key poisoning on invalid
timestamps in the legacy parser.
* Add Kiro provider and transparent auto-model naming
- Add Kiro IDE provider: parses .chat JSON files, estimates tokens,
normalizes dot-versioned model IDs for cost lookup
- Show "Cursor (auto)", "Copilot (auto)", "Kiro (auto)" in CLI
dashboard instead of pretending to know which model was used
- Route auto model names through BUILTIN_ALIASES for cost estimation
* Fix menubar tabs: add missing providers, show period-scoped costs
- Add Kiro, OMP to ProviderFilter enum so installed providers appear as tabs
- Merge Cursor + Cursor Agent into single Cursor tab
- Tab costs now reflect the selected period (7d/30d/month/all) instead
of always showing today
- Tab visibility still uses today's provider list so tabs don't
disappear when switching to periods with no data
* Add accent color picker to menubar with Apple system presets
- 9 presets using Apple's exact macOS dark-mode accent colors
(Ember, Blue, Purple, Pink, Red, Orange, Yellow, Green, Graphite)
- Color picker in header, persisted via UserDefaults
- "Burn" text stays fixed ember regardless of accent
- ThemeState is MainActor-isolated for thread safety
- Picker state lifted to AppStore so it survives .id() tree rebuild
- Accessibility labels on all color swatches
- Renamed brandAccentDark/brandEmberDeep/brandEmberGlow to match
their actual light/deep/glow semantics
* Fix review findings: case-sensitive cost lookup, Kiro timestamp guard, cache versioning
- Normalize provider dictionary keys to lowercase in tab cost lookup
so "Cursor Agent" (title-case from CLI) matches providerKeys
- Guard against missing/invalid/epoch startTime in Kiro parser to
prevent RangeError crash or 1970-01-01 ghost entries
- Bump DAILY_CACHE_VERSION to 4 so upgraded users get a clean
recompute with the new auto-model naming (cursor-auto vs default)
- Add version field to cursor-results.json cache to invalidate stale
entries that still use the old 'default' model name