Commit graph

65 commits

Author SHA1 Message Date
AgentSeal
5e095bf86e chore: polish Pi provider integration
- Add Pi entry to PROVIDER_COLORS (pink) and PROVIDER_DISPLAY_NAMES.
- Update README with Pi in supported providers, requirements,
  command examples, and the data-format section.
2026-04-16 02:11:48 -07:00
AgentSeal
1a101b586c chore: map Pi dispatch_agent to Agent for activity classification
dispatch_agent is Pi's delegation tool. Mapping it to Agent makes
the classifier route those turns into the Delegation category
instead of Conversation, matching the existing semantics for the
task tool.
2026-04-16 02:08:07 -07:00
AgentSeal
97c0869763 chore: hoist Pi model sort + cover bash-utils edge cases
- Move modelDisplayEntries sort to module scope so it runs once
  instead of on every modelDisplayName call.
- Add bash-utils tests for the env var prefix and true/false
  skip behaviors that came in with the Pi commit.

Verified Pi token semantics against real session data:
input + cacheRead + cacheWrite + output equals totalTokens
exactly, confirming Anthropic-style accounting (cached tokens
disjoint from input). No double-counting.
2026-04-16 02:02:32 -07:00
AgentSeal
d92d5b3f26 chore: normalize Pi tool names via toolNameMap
Maps Pi's lowercase tool names (bash, read, edit, write...) to
the capitalized form used by every other provider, so the
dashboard shows consistent tool names across providers and the
activity classifier works without extra lowercase entries.

Reverts the lowercase additions to classifier.ts since the
provider now normalizes tool names at the source.
2026-04-16 01:57:39 -07:00
Damian Jackson
7ac512a7e4 feat: add Pi provider for tracking Pi agent sessions
- Adds support for Pi (pi.ai) as a new session provider.
- Pi sessions are stored as JSONL files under `~/.pi/agent/sessions/<project-dir>/` and use OpenAI-compatible model IDs (gpt-5, gpt-5.4, gpt-4o, etc.).

- `src/providers/pi.ts` (new): Pi provider - discovers JSONL session files, parses assistant turns, extracts token counts, tool calls, and bash commands, deduplicates via response ID with line-index fallback
- `src/providers/types.ts`: added bashCommands field to `ParsedProviderCall` so all providers carry extracted bash command lists
- `src/providers/index.ts`: registered Pi as a core provider alongside Claude and Codex
- `src/providers/codex.ts`, `cursor.ts`: added `bashCommands: []` to satisfy the new required field on `ParsedProviderCall`
- `src/parser.ts`: fixed bug where `providerCallToTurn` always emitted an empty bashCommands array instead of passing through the parsed commands
- `src/classifier.ts`: added lowercase tool name variants (bash, edit, read, write) to match Pi's tool naming convention in JSONL output
- `src/bash-utils.ts`: exclude `true`, `false`, and shell variable assignments from extracted commands; scan past leading `NAME=val` tokens so `FOO=bar ls` correctly records `ls` rather than being dropped
- `package.json`: added pi to keywords
- `tests/providers/pi.test.ts` (new): 16 unit tests covering session discovery, multi-turn parsing, tool/bash extraction, deduplication, zero-token filtering, and display name mapping
- `tests/provider-registry.test.ts`: updated core provider list to include pi

- [X] Unit tests pass (`npx vitest run`, 56 tests across 6 files);
- [X] Manually verified via `npx tsx src/cli.ts` report and showing Pi sessions alongside Claude and Codex in the dashboard.
2026-04-16 01:54:42 -07:00
AgentSeal
45572e43f2 feat: cache hit % per model + correct calculation
Adds a cache hit percentage column to the By Model panel and
fixes the cache hit math in the Overview panel. Both were
treating cache_creation tokens as cache hits, when they are
actually cache misses being written to cache for future use.

The corrected formula counts both fresh input and cache writes
in the denominator, so a heavy Claude Code session now shows
~97% cache hit instead of the misleading 100%.

Also extracts column widths into named constants per CLAUDE.md
no-magic-numbers rule, and tightens the model name column to a
fixed 14 chars so columns hug the name like the Activity panel.
2026-04-16 01:50:19 -07:00
AgentSeal
e12b8e31d7 fix: load all 2,659 LiteLLM models, not just 192
The pricing fetcher was filtering out every model name containing
'/' or '.', which discarded provider-prefixed entries like
'anthropic/claude-opus-4-6' and version-suffixed ones like
'gemini-2.0-flash-001'. That dropped 93% of LiteLLM's catalog
(2,467 of 2,659 models), leaving most non-Anthropic models
priced at $0.

Now we load every entry and additionally index each one under its
stripped name so 'claude-opus-4-6' resolves whether or not the
caller includes the provider prefix.
2026-04-16 01:25:15 -07:00
Christopher Sant
5cdcd2c2ee feat: add rolling 30-day window to menubar status
Add a '30 Days' section to the menubar format output, positioned between
'7 Days' and 'Month' to match the tab order in the interactive report.

The rolling 30-day date range logic already existed (used by report and
export commands) - this wires it into the status menubar renderer.

Both 30 Days (rolling window) and Month (calendar month) are shown,
giving useful context early in the month when the calendar month total
is nearly empty.
2026-04-15 21:48:20 -07:00
AgentSeal
475ab0da61 fix: case-insensitive Codex originator check
Codex Desktop on Windows uses "Codex Desktop" as the originator
string instead of "codex_cli" or "codex_vscode". The startsWith
check was case-sensitive, rejecting these sessions silently.

Fixes #1 (comment by @JiglioNero).
2026-04-15 16:06:28 -07:00
AgentSeal
2d114d9393 feat: add OpenCode provider
Reads session data from OpenCode's SQLite databases at
~/.local/share/opencode/. Reuses the existing better-sqlite3
adapter (same as Cursor), lazy-loaded so users without OpenCode
see no difference. Adds bashCommands to the provider interface
so shell command breakdowns work across all providers.

31 tests, schema validation, diagnostic stderr on failures.
Also fixes a pre-existing tsc error in currency.ts.
2026-04-15 14:24:37 -07:00
AgentSeal
2afab5f71a fix: final review cleanup
- Remove unused vi import from cursor test
- Move LANG_DISPLAY_NAMES to module scope (was re-created per render)
- Remove redundant 'script' regex (scrip?t already covers it)
- Unexport getDbFingerprint (internal to cache module)
- Move beforeEach inside describe block (only cursor tests need it)
2026-04-15 05:35:11 -07:00
AgentSeal
94762ca1f4 fix: address review findings before merge
- getProvider() now async, eliminates race condition with cursor loading
- cursor:edit pseudo-tool prevents inflating Claude's Edit count in --provider all
- Tightened SCRIPT_PATTERNS to avoid false positives (run requires file context)
- Removed duplicated LANG_NAMES from cursor.ts (dashboard handles display)
- Test no longer assumes cursor always loads (CI-safe)
- Removed unnecessary type assertion and setTimeout yield
2026-04-15 05:31:51 -07:00
AgentSeal
91edd6f14a chore: remove 120-day period, shrink Cursor lookback to 35 days
120 days was for testing. Max dashboard period is 30 days, so
Cursor SQL lookback is now 35 days (30 + margin for This Month).
Smaller scan window = faster cold starts, smaller cache file.
2026-04-15 05:24:34 -07:00
AgentSeal
3fabc105d8 perf: file-based result cache for Cursor DB
First run parses the 21GB DB (slow, ~40-80s). Writes parsed
results to ~/.cache/codeburn/cursor-results.json. Subsequent
runs check DB mtime+size -- if unchanged, load from cache
(instant). Cache auto-invalidates when Cursor modifies the DB.
2026-04-15 05:11:30 -07:00
AgentSeal
6ba3691d24 fix: broader activity classification for informal messages
- File extension patterns (.py, .json, .ts, etc.) trigger Coding
- Script/API keywords (run, script, api, query, etc.) trigger Coding
- URL patterns trigger Exploration
- HTTP status codes (404, 500) trigger Debugging
- "make a/me/the" and "write a/me/the" trigger Feature Dev
- Catches informal Cursor messages that missed strict patterns
2026-04-15 05:03:15 -07:00
AgentSeal
4597cbbd16 fix: combine user + assistant text for better activity classification 2026-04-15 05:00:39 -07:00
AgentSeal
effe5b2438 fix: map language IDs to readable names in Languages panel 2026-04-15 04:56:25 -07:00
AgentSeal
caa0464832 fix: strip lang: prefix in Languages panel display 2026-04-15 04:55:01 -07:00
AgentSeal
5c6c266c85 fix: improve Cursor activity classification and language panel
- Fetch actual user messages (type 1 bubbles) for keyword classification
  instead of using assistant response text
- Synthetic Edit tool when codeBlocks present so classifier detects coding
- Languages use lang: prefix to separate from tool classification
- Dashboard filters lang: entries for Languages panel, hides from Core Tools
2026-04-15 04:53:07 -07:00
AgentSeal
d6c6e827ea fix: clean language names, remove diagnostic scripts 2026-04-15 04:49:09 -07:00
AgentSeal
7b23fbb57b fix: pass provider to static dashboard for correct panel titles 2026-04-15 04:48:03 -07:00
AgentSeal
11cdcaa89d feat: activity classification + language breakdown for Cursor
- Extract user text from bubbles for activity classifier
- Extract codeBlocks languageId for programming language breakdown
- Show Languages panel instead of Core Tools/Shell/MCP for Cursor
- Adaptive dashboard layout based on active provider
- 120-day daily activity range for longer periods
2026-04-15 04:46:12 -07:00
AgentSeal
ea5fd90a68 fix: remove incremental cache, always read full lookback window
The incremental cache saved a timestamp watermark but not the parsed
data, so subsequent runs found no new entries and returned empty.
Removed the cache layer entirely -- the 120-day SQL time filter
already limits the scan sufficiently.
2026-04-15 04:34:06 -07:00
AgentSeal
c7195c4a17 fix: handle ISO string timestamps from Cursor database
Cursor stores createdAt as ISO strings ('2026-02-23T06:00:51.123Z'),
not numeric timestamps. Was comparing string against number, so all
rows were filtered out. Now uses ISO string comparison throughout.
2026-04-15 04:17:56 -07:00
AgentSeal
5da6e772e4 feat: change 90-day period to 120 days 2026-04-15 04:05:12 -07:00
AgentSeal
76c9edd811 feat: debounce arrow key period switching (600ms)
Arrow keys now wait 600ms before loading data, so quickly
scrolling through periods (7d -> 30d -> 90d) skips intermediate
loads. Number keys (1-5) still load immediately.
2026-04-15 04:04:23 -07:00
AgentSeal
5ead1e9c07 perf: yield to event loop before heavy SQLite query
Adds a setTimeout(0) before parseBubbles so Ink can render
the Loading state before the synchronous query blocks.
2026-04-15 04:01:17 -07:00
AgentSeal
b7b7b2c7d6 perf: lazy-load cursor provider to eliminate startup overhead
Cursor module (sqlite.ts, better-sqlite3) now only loads when
cursor provider is actually requested. Claude/Codex startup
is unaffected -- cursor import never happens unless needed.
2026-04-15 03:59:49 -07:00
AgentSeal
3c439cb28f perf: remove provider pre-fetch on dashboard startup
The dashboard was pre-loading data for ALL detected providers
on startup, causing unnecessary SQLite scans when Cursor was
detected. Now only loads data for the active provider.
2026-04-15 03:56:21 -07:00
AgentSeal
2871af10e8 feat: add 90-day period option for testing Cursor data
Adds 90 Days tab (key: 4), shifts Month to key 5.
Available via --period 90days and interactive dashboard.
2026-04-15 03:55:23 -07:00
AgentSeal
dacebd6d3c perf: add 90-day time floor to Cursor SQL query
Instead of scanning all 300K+ rows on every load, only query
entries from the last 90 days. Eliminates the full table scan
that caused slow provider switching on large databases.
2026-04-15 03:51:11 -07:00
AgentSeal
70931b7269 feat: add Cursor IDE provider with SQLite adapter
Reads token usage from Cursor's local state.vscdb database.
Supports per-request input/output tokens, model tracking,
and incremental caching for large databases.

- better-sqlite3 as optionalDependency (lazy-loaded, no impact on Claude/Codex)
- Parameterized SQL queries, read-only mode, per-row error handling
- Schema detection with clear error on format changes
- Cache layer with timestamp watermark for incremental reads
- Provider colors and [p] key cycling in dashboard
- 39 tests passing, zero regressions
2026-04-15 03:44:43 -07:00
AgentSeal
b7b6c208bd fix: read version from package.json instead of hardcoding
Closes #35 (comment)
2026-04-15 02:26:17 -07:00
AgentSeal
d597d458f9 feat: auto-refresh dashboard, show 'home' for home dir sessions 2026-04-15 01:40:48 -07:00
AgentSeal
c6c4979c06 feat: readable project names — strip home dir prefix, show ~ for home sessions 2026-04-15 01:09:18 -07:00
AgentSeal
5c7639b2fb fix: stale comment referencing removed config currency subcommand 2026-04-15 00:32:51 -07:00
mukunda katta
ad733fe596 fix(menubar): invoke binary directly + correct currency subcommand (#32, #27)
The two menubar action items were built as `bash -c "cd ~/codeburn &&
npx tsx src/cli.ts ..."`, which:

1. assumes a `~/codeburn` source checkout that npm-installed users
   don't have, and
2. interacts badly with how SwiftBar serialises `param2=` on long
   quoted strings — only the `cd` half ends up reaching `bash -c`,
   so the `npx tsx` fallback runs from `$HOME` and fails with
   `ERR_MODULE_NOT_FOUND: /Users/<u>/src/cli.ts`.

Replace with the resolved `${bin}` plus separate `paramN=` args,
which SwiftBar/xbar deliver as discrete argv entries — no shell
quoting, no checkout assumption.

While here, fix the currency submenu the same way: the items were
emitting `${bin} config currency XXX`, but the real CLI subcommand
defined in `src/cli.ts` is `codeburn currency [code]` (with
`--reset` for USD). The previous form silently failed on click.
That's #27.

Closes #32
Closes #27

Verified by running `npm run build` (clean) + `npm test -- --run`
(28/28 pass), and inspecting the rendered output of `codeburn status
--format menubar` to confirm the action lines now look like:

  Open Full Report | terminal=true shell=<bin> param1=report
  Export CSV to Desktop | terminal=false shell=<bin> param1=export param2=-o param3=<HOME>/Desktop/codeburn-report.csv
  --US Dollar (USD) * | terminal=false refresh=true shell=<bin> param1=currency param2=--reset
  --British Pound (GBP) | terminal=false refresh=true shell=<bin> param1=currency param2=GBP
2026-04-14 23:11:32 -07:00
AgentSeal
51c56d0726 fix: include agent/subagent sessions, fix Codex cache hit and cost calculation
- Remove agent-*.jsonl exclusion filter that was dropping ~46% of API calls
- Scan subagents/ directories for subagent session files
- Normalize Codex token semantics: OpenAI includes cached tokens inside
  input_tokens, subtract them to match Anthropic's separate reporting
- Fixes cost double-counting and 100% cache hit display for Codex users
2026-04-14 10:18:14 -07:00
AgentSeal
ce2c1d2995 Merge branch 'fix/csv-formula-injection' 2026-04-14 09:39:03 -07:00
AgentSeal
16f39e264e feat: responsive dashboard — dynamic reflow, wider cap, half-width panels
- Use Ink's useWindowSize() hook for reactive terminal reflow (PR #18)
- Raise width cap from 104 to 160 columns for wide screens
- Move Activity panel from full-width to half-width row with Model panel
- Pair Tool + Bash panels, MCP goes full-width at bottom
- Addresses issue #23 (UI responsiveness)
2026-04-14 09:15:37 -07:00
AgentSeal
d2560d7ad8 bump to 0.4.1: multi-currency support, 30-day rolling window 2026-04-14 09:06:35 -07:00
AgentSeal
40d04261d6 cleanup: strip TUI picker, promote currency command, remove verbose comments
- Remove CurrencyPicker component and all related state from dashboard
- Promote 'codeburn config currency' to top-level 'codeburn currency'
- Strip JSDoc comments that explain WHAT not WHY
- Remove forceRender hack and unused imports
2026-04-14 08:47:45 -07:00
AgentSeal
9ab7f37f6f Fix CSV formula injection in exports 2026-04-14 11:04:10 -04:00
BlairWelsh
f08f97cd3d feat: add interactive currency picker to dashboard
Press c in the dashboard to open a searchable currency picker modal.
Type to filter, arrow keys to navigate, enter to select, escape to
cancel. Shows 24 common currencies with the active one marked, and
accepts any valid ISO 4217 code typed directly.

Session-only switch -- does not write to config, so users can quickly
compare costs in different currencies without changing their default.
2026-04-14 14:09:39 +01:00
BlairWelsh
df69c2aadf feat: add currency picker to menubar plugin
Adds a Currency submenu to the SwiftBar/xbar dropdown with 16 common
currencies. Clicking one runs codeburn config currency and refreshes
the plugin. Active currency is marked with *.

The full 162 ISO 4217 currencies are available via the CLI for any
not listed in the menubar.
2026-04-14 13:51:11 +01:00
BlairWelsh
85304dbe30 feat: add multi-currency support
Display costs in any of 162 ISO 4217 currencies. Exchange rates are
fetched from frankfurter.app (ECB-backed, free, no API key) and cached
for 24h alongside the existing LiteLLM pricing cache.

Currency symbols and decimal rules come from Node's built-in Intl API
rather than hardcoded tables.

New command: codeburn config currency <code>
Reset: codeburn config currency --reset

Config stored at ~/.config/codeburn/config.json.
All internal calculations remain in USD -- conversion is display-only.
2026-04-14 13:51:11 +01:00
AgentSeal
efab93e78e cleanup: use Period type instead of inline union in renderDashboard 2026-04-14 04:58:47 -07:00
Øystein Krog
f66afc893d feat: add 30-day rolling window period
Add a '30days' period that shows the last 30 days of usage data, distinct
from 'month' which shows the current calendar month.

- New period available via `--period 30days` and keyboard shortcut `3`
- Dashboard cycles: Today > 7 Days > 30 Days > This Month
- Fix export command to use actual 30-day range instead of calendar month
  for the '30 Days' export label
2026-04-14 13:51:06 +02:00
AgentSeal
25bd54404c bump to 0.4.0: multi-provider support (Codex, provider plugin system) 2026-04-14 04:35:51 -07:00
AgentSeal
391a235d1d feat: multi-provider support (Codex + provider plugin system)
Add Codex (OpenAI) as a second provider alongside Claude Code. Provider
plugin architecture makes adding future providers (Pi, OpenCode, Amp) a
single-file addition.

- Provider interface: types, session discovery, stateful JSONL parsing
- Codex parser: token_count dedup, tool normalization, model resolution
- TUI: press p to cycle All/Claude/Codex with 1-min cache for instant switching
- CLI: --provider flag on report, today, month, status, export commands
- Pricing: Codex model fallbacks, fixed fuzzy matching for gpt-5.4-mini
- Menubar: per-provider cost breakdown when multiple providers detected
- 27 tests (10 new: Codex parser, provider registry, tool/model mapping)
2026-04-14 04:32:09 -07:00