Commit graph

570 commits

Author SHA1 Message Date
Resham Joshi
06f69484f3
Fix one-shot rate detection for all non-Claude providers (#355)
Some checks are pending
CI / semgrep (push) Waiting to run
* Add CodeBurn Pro Mac App Store app

SwiftUI MenuBarExtra with litellm-snapshot pricing, Claude/Codex/Copilot
parsers, session discovery, auto-refresh timer, and dashboard UI matching
the real menubar design.

* Add appstore/ to .gitignore

Private Mac App Store build, not for the public repo.

* Fix one-shot rate detection for Gemini, Vibe, Kiro, and Goose

Gemini and Mistral Vibe now emit per-assistant-message calls grouped
by user turn via turnId, so the classifier sees Edit->Bash->Edit as
retries instead of independent one-shot turns. Kiro and Goose record
per-message tool ordering via toolSequence for the same effect on
aggregated sessions.

Vibe now prefers meta.json.stats.session_cost over price-derived
estimates. Session cache bumped to v2. Insight pill switcher scrolls
horizontally instead of wrapping.

Closes #351.

* Remove dead geminiOrdinal variable and add toolSequence cache validation

* Restore geminiOrdinal for idx fallback dedup key
2026-05-18 15:56:14 -07:00
Resham Joshi
7cea9efb31
Add Optimize tab, token display modes, daily budget alerts, and project drill-down (#349)
* Add CodeBurn Pro Mac App Store app

SwiftUI MenuBarExtra with litellm-snapshot pricing, Claude/Codex/Copilot
parsers, session discovery, auto-refresh timer, and dashboard UI matching
the real menubar design.

* Add appstore/ to .gitignore

Private Mac App Store build, not for the public repo.

* Add Optimize tab, token display modes, daily budget alerts, and project drill-down

- New Optimize insight tab with Retry Tax and Routing Waste computations
  (pure math from session data, no LLM required)
- Retry tax: shows money wasted on failed edit retries, per-model breakdown
- Routing waste: counterfactual savings vs cheapest reliable model, per-model
- Token display modes: Cost ($), Tokens (up/down split), Total Tokens
- Daily budget alert: configurable threshold, flame turns yellow when exceeded
- Project drill-down: click project rows to see per-session cost, tokens, models
- Period-aware top sessions: 30-day view now shows 30-day costliest sessions
- Friendly project names: show directory name instead of full path, Home for ~
- Session cache TTL bumped to 180s to prevent re-parsing on non-today periods
- Audit fixes: array mutation, percentage rounding, ForEach ID collision,
  baseline minimum threshold, editTurns scoping, first-of-month edge case

* Fix model badge ForEach ID collision and budget warning provider filter

- SessionDetailsList model badges used id: \.name which silently drops
  duplicate model entries. Switched to enumerated offset-based ID.
- Hero budget warning compared against provider-filtered payload instead
  of todayPayload (all providers). Now matches the menubar flame tint.
2026-05-18 14:51:15 -07:00
ozymandiashh
5a837c94e9
Track OpenCode child sessions (#343)
Some checks are pending
CI / semgrep (push) Waiting to run
2026-05-18 05:51:08 -07:00
ozymandiashh
2013ecbfd9
Track agent calls across providers (#340) 2026-05-18 05:51:01 -07:00
Resham Joshi
303c9458cb
Fix OpenCode/Goose returning 0 sessions on fresh install (#347)
* Add CodeBurn Pro Mac App Store app

SwiftUI MenuBarExtra with litellm-snapshot pricing, Claude/Codex/Copilot
parsers, session discovery, auto-refresh timer, and dashboard UI matching
the real menubar design.

* Add appstore/ to .gitignore

Private Mac App Store build, not for the public repo.

* Fix OpenCode/Goose returning 0 sessions on fresh install

SQLite-based providers use compound paths (db.path:sessionId) which
caused fingerprintFile to fail stat() and silently skip all sessions.
Fall back to stat on the DB file when the full compound path fails.

Fixes #346
2026-05-18 05:45:20 -07:00
iamtoruk
1317af2acf Bump to 0.9.10, fix per-provider chart history for today period
Some checks are pending
CI / semgrep (push) Waiting to run
The fallback daily history path (used when rangeStartStr = todayStr)
was missing cache-based historical data, showing only today's bar in
the trend chart. Now includes allCacheDays filtered by provider.
2026-05-17 14:06:13 -07:00
Resham Joshi
58ccf84f02
Fix menubar per-provider performance (24s → 2s) and session cache safety (#344)
Some checks are pending
CI / semgrep (push) Waiting to run
Per-provider menubar calls now use loadDailyCache() instead of hydrateCache(),
splitting history into cache-based and fallback paths. Fixes session cache wipe
when scanProjectDirs/parseProviderSources receive empty dirs. Strips _dirty flag
before session cache serialization to prevent unnecessary 132MB rewrites. Removes
dead keychain code from both credential stores.
2026-05-17 13:54:38 -07:00
iamtoruk
b0131f698c Store credential cache in file instead of keychain, use cache for per-provider menubar
Credential cache: switched from keychain to file-based storage under
Application Support. Ad-hoc signed builds invalidate keychain ACLs on
every rebuild, causing repeated macOS password prompts. Existing
keychain entries are migrated to file on first read, then deleted.

Per-provider menubar: the Codex/Claude/etc tabs previously re-parsed
all sessions from scratch (22s). Now parses only today with the
provider filter and uses the daily cache for historical days, matching
the fast path the All tab already uses.

Daily cache bumped to v7 to force a clean rebuild after pricing and
provider changes since v6.
2026-05-17 07:18:58 -07:00
iamtoruk
9ad137f2b8 Fix dormant activation to bootstrap instead of refresh
When the user clicks Load Quota from dormant state after a clean
reinstall, the cached keychain item may not exist. Using the refresh
path triggered a macOS keychain prompt because it assumed the cache
was present. Now calls bootstrapSubscription/bootstrapCodex which
properly re-reads credentials from source.
2026-05-17 05:27:49 -07:00
Resham Joshi
7e0c1de086
Merge pull request #338 from getagentseal/fix/dormant-keychain-prompt
Some checks are pending
CI / semgrep (push) Waiting to run
Defer keychain access until user clicks Connect on plan tab
2026-05-17 00:31:52 -07:00
iamtoruk
bf0c7cc993 Defer keychain access until user explicitly connects on plan tab
Adds a `dormant` state to SubscriptionLoadState so the menubar never
prompts for keychain permission on launch. Users must navigate to the
plan tab and click "Load Quota" / "Connect" to trigger credential access.

Also fixes a flaky TZ-boundary test (cli-status-menubar) by widening the
time offset to avoid generating timestamps in the future at UTC hour 0.
2026-05-17 00:31:33 -07:00
iamtoruk
dcbf6dcfbf Merge pull request #300: Track multiple provider plans
Some checks are pending
CI / semgrep (push) Waiting to run
# Conflicts:
#	CHANGELOG.md
#	src/main.ts
2026-05-16 10:49:05 -07:00
iamtoruk
257e8924dd Merge main into feat/multi-provider-plans, remove dead tautology 2026-05-16 10:42:03 -07:00
iamtoruk
e3a0593ed8 Fix menubar PATH discovery for nvm/volta/asdf/npm-global installs
GUI-launched apps inherit a minimal PATH that misses user-managed Node
directories. Scan ~/.volta/bin, ~/.npm-global/bin, ~/.asdf/shims, and
the newest nvm Node version at launch. All candidates pass isSafe()
validation. Closes #331.
2026-05-16 08:54:45 -07:00
Resham Joshi
a00b0ebce0
Merge pull request #124 from anandghegde/feat/codebuff-provider
feat(providers): add Codebuff provider
2026-05-16 08:02:38 -07:00
iamtoruk
06c90d0293 Merge main into feat/codebuff-provider to resolve conflicts 2026-05-16 08:02:27 -07:00
Resham Joshi
7777bf80bf
Merge pull request #301 from ozymandiashh/feat/mistral-vibe-provider
Support Mistral Vibe sessions
2026-05-16 07:35:32 -07:00
iamtoruk
adfbd0bd04 Merge main into feat/mistral-vibe-provider, add malformed input tests 2026-05-16 07:35:22 -07:00
Resham Joshi
c455203b0d
Merge pull request #306 from ozymandiashh/feat/kimi-code-provider
Support Kimi Code CLI sessions
2026-05-16 07:25:23 -07:00
iamtoruk
5696a74571 Merge main into feat/kimi-code-provider to resolve conflicts 2026-05-16 07:25:12 -07:00
Resham Joshi
a45ee7aca2
Merge pull request #312 from ozymandiashh/feat/cline-provider
Add Cline provider
2026-05-16 05:58:22 -07:00
iamtoruk
59a4d95b18 Merge main into feat/cline-provider to resolve conflicts 2026-05-16 05:58:10 -07:00
Resham Joshi
37fb7f9c3e
Merge pull request #252 from brunoleemann-code/fix/windows-test-home-dir
Fix cli-plan test failing on Windows
2026-05-16 05:18:35 -07:00
Resham Joshi
c56f7ea7db
Merge pull request #324 from ozymandiashh/fix/antigravity-windows-discovery
Fix Antigravity Windows discovery
2026-05-16 05:16:05 -07:00
Resham Joshi
95884c01f3
Merge pull request #334 from vaibhavarora14/fix/provider-strip-scroll
fix(menubar): make provider strip reachable and mouse-wheel scrollable
2026-05-16 05:02:59 -07:00
iamtoruk
bd41fa3962 Add persistent disk cache for parsed session data
Some checks are pending
CI / semgrep (push) Waiting to run
Cache normalized turns/calls to ~/.cache/codeburn/session-cache.json so
the CLI skips re-parsing unchanged JSONL files on subsequent runs.
File reconciliation uses dev+ino+mtime+size fingerprinting; cost,
classification, and summaries are recomputed at query time. Atomic
writes via temp+fsync+rename, deep structural validation on load,
per-provider env fingerprinting, and best-effort save so cache failures
never break the CLI. ~6x speedup on warm cache.
2026-05-16 01:04:13 -07:00
iamtoruk
d568c8c103 Add src/summit.ts to gitignore 2026-05-15 23:17:20 -07:00
iamtoruk
2fb078bdfb Fix V8 OOM crash on 30-day period with Buffer-based line reader and large-line parser
Three-layer fix for V8 heap exhaustion when parsing heavy session data:

1. Buffer-based readSessionLines (fs-utils.ts): Replace readline with raw
   Buffer streaming using Buffer.indexOf(0x0a). Eliminates ConsString trees
   that caused OOM when regex-flattening 100MB+ lines. Two-state machine
   (ACCUMULATING/SCANNING) skips old lines at ~2KB cost instead of 200MB.

2. Large-line streaming parser (parser.ts): Hand-written JSON scanner for
   lines >32KB extracts only cost/token/tool fields without JSON.parse,
   avoiding full object graph allocation. Dual string/Buffer paths.

3. Dashboard memory management (dashboard.tsx): Disable auto-refresh for
   heavy periods (30d/month/all), clear old dataset before reload via
   nextTick to allow GC, prevent overlapping reloads with mutex, lazy
   optimize scanning on keypress instead of useEffect.

Also fixes three race conditions in dashboard reload deduplication:
- Early return after nextTick bypassing finally block (permanent mutex lock)
- A->B->A period switching dropping final reload (stale pending)
- Stale pendingReloadRef not cleared when in-flight matches request
2026-05-15 23:15:26 -07:00
iamtoruk
36e94169fb Fix changelog: command count, issue refs, Node guard, menubar section
- "Nine commands" → "Eight commands" (report has 2 call sites, 1 command)
- "Closes #196" → "Closes #320" (#196 was closed in 0.9.8)
- Add Node version guard entry (closes #319)
- Add Fixed (macOS menubar) section covering 8 commits since 0.9.8
2026-05-15 20:04:49 -07:00
iamtoruk
6a12d818d9 Sync package-lock.json to 0.9.9 and fix flaky menubar test
package-lock.json was stale at 0.9.7 with engines >=22; now matches
package.json 0.9.9 / >=22.13.0.

The menubar-json CLI test used hardcoded 10:00/11:00 UTC timestamps
which fall in the "future" when the test runs before those hours,
causing the menubar's todayRange (start..now) to exclude them.
Use timestamps relative to now instead.
2026-05-15 20:03:44 -07:00
iamtoruk
54e3123cc0 Fold Unreleased entries into 0.9.9 and add hydrateCache removal note
All Unreleased items (IBM Bob, cache write pricing, OpenCode MCP,
project names, Cursor bubbles) are already on main, so they belong
under 0.9.9. Replaced the narrow status-only hydrateCache bullet
with the broader 9-command removal.
2026-05-15 14:23:47 -07:00
iamtoruk
57e48e6e55 Stop eager daily-cache hydration on CLI commands that never consume it
Only `status --format menubar-json` uses getDaysInRange from the hydrated
cache. The other 9 call sites (report, today, month, export, optimize,
compare, models, yield) parse their own date ranges directly via
parseAllSessions. Removing hydrateCache from these paths avoids a 365-day
backfill parse that was the primary OOM multiplier on large session dirs.
2026-05-15 14:23:20 -07:00
Resham Joshi
041d9338c2
Merge pull request #335 from getagentseal/fix/oom-compact-entries
Some checks are pending
CI / semgrep (push) Waiting to run
Reduce Claude parser OOM risk (0.9.9)
2026-05-15 13:22:18 -07:00
iamtoruk
a7bb780618 Reduce Claude parser OOM risk via entry compaction (0.9.9)
Strip heavy fields from JournalEntry immediately after JSON.parse in the
JSONL hot loop. Keeps only what downstream consumers need: type, timestamp,
sessionId, cwd, compacted user text (2000 char total cap), assistant
model/usage/id, tool_use names with Skill and Bash inputs, and MCP
inventory attachments. Text, thinking, and tool_result blocks are dropped.

Also removes redundant hydrateCache() from status --format json and
terminal status paths, and clears the session cache between period
parses to avoid pinning both today and month result sets.

This is a mitigation, not a full fix. Very large month ranges still
materialize full ProjectSummary.turns arrays. The real fix is the
streaming single-pass parser refactor.
2026-05-15 13:20:50 -07:00
Resham Joshi
1f0aa7dce8
Merge pull request #328 from getagentseal/fix/menubar-tab-refresh-recovery
Some checks are pending
CI / semgrep (push) Waiting to run
Harden menubar refresh and release path
2026-05-15 10:10:05 -07:00
Vaibhav Arora
8f35dcd128 fix(menubar): make provider strip reachable and mouse-wheel scrollable
Two related bugs in the macOS menubar `AgentTabStrip`:

1. With more detected providers than fit at the default 360pt popover
   width (~7+), the off-screen provider chips were unreachable. SwiftUI's
   horizontal `ScrollView` does not scroll from click-drag, and there
   was no other affordance to reveal the hidden tabs.

2. Independent mouse wheels could not scroll the horizontal strip.
   Standard wheels emit only vertical `deltaY` with
   `hasPreciseScrollingDeltas == false`, and a horizontal SwiftUI
   `ScrollView` ignores vertical-only deltas. Trackpads (which emit
   horizontal deltas natively) already worked.

Fix:

- Wrap the strip in `ScrollViewReader` and add overflow-aware
  left/right chevron buttons that programmatically scroll to the
  next/previous visible provider via `proxy.scrollTo(_, anchor: .center)`.
  Buttons only appear when `stripContentWidth > stripViewportWidth - 30`
  and disable at the ends.
- Install an `NSEvent.addLocalMonitorForEvents(matching: .scrollWheel)`
  in `.onAppear` (removed in `.onDisappear`). When the cursor is over
  the strip and the event is non-precise (`!hasPreciseScrollingDeltas`)
  with `deltaX≈0` and `deltaY≠0`, copy the `CGEvent` and transpose
  `scrollWheelEventDeltaAxis1` / `PointDeltaAxis1` / `FixedPtDeltaAxis1`
  onto axis 2 so the underlying NSScrollView receives a real horizontal
  delta.
- Track strip hover via a `@MainActor` singleton
  `AgentTabStripScrollState` so the local-monitor closure can read the
  latest hover status without capturing stale SwiftUI state.

Trackpad events are passed through untouched, so vertical scrolling
elsewhere in the popover is unaffected.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-15 19:52:57 +05:30
iamtoruk
d342f2205b Fix menubar all-provider refresh OOM 2026-05-14 21:57:51 -07:00
iamtoruk
909efcf989 Harden menubar refresh and installer 2026-05-14 18:32:15 -07:00
iamtoruk
478131d5b7 Harden menubar status refresh timer 2026-05-14 17:57:36 -07:00
iamtoruk
00c55873a4 Fix menubar tab refresh recovery 2026-05-14 11:26:15 -07:00
Resham Joshi
2ca92a97cf
Merge pull request #315 from getagentseal/fix/menubar-version-prefix
Some checks failed
CI / semgrep (push) Has been cancelled
Harden menubar refresh recovery
2026-05-13 20:33:42 -07:00
iamtoruk
403efd4727 Merge remote-tracking branch 'origin/main' into fix/menubar-version-prefix
# Conflicts:
#	package.json
#	src/parser.ts
2026-05-13 20:32:22 -07:00
iamtoruk
c626fc4a45 Fix menubar stale cache recovery 2026-05-13 20:22:15 -07:00
iamtoruk
aa946d0965 Keep CLI executable after build 2026-05-12 19:13:40 -07:00
ozymandiashh
929c66e7d1 Fix Antigravity Windows discovery 2026-05-13 00:51:39 +03:00
Resham Joshi
151d24fb26
Drop Z suffix from day-aggregator test timestamps for timezone stability (#322)
Some checks failed
CI / semgrep (push) Has been cancelled
Timestamps with Z are interpreted as UTC, causing date bucketing tests
to fail in non-UTC timezones (e.g. UTC+12 shifts Apr 9 10:00Z to Apr 8).
Local timestamps without Z are interpreted in the runtime timezone,
matching how the aggregator actually buckets dates.

Based on #112 by @lfl1337, extended to cover all affected timestamps.
2026-05-11 22:25:32 -07:00
iamtoruk
f9a5d2c8e6 Add changelog entries for project path fix and Cursor undated bubbles 2026-05-11 22:19:15 -07:00
Resham Joshi
fe2e622038
Skip Cursor bubble rows that lack a createdAt timestamp (#321)
Bubble rows without createdAt were defaulting to new Date(), which
misattributed historical or undated usage to Today and inflated the
daily chart. Now filtered at the SQL level and skipped in application
code.

Based on the bubble-side fix from #262 by @darthrevanyunka.
2026-05-11 22:16:00 -07:00
Resham Joshi
3b71650f24
Fix mangled project paths in dashboard (#320)
* Fix mangled project paths in By Project and Top Sessions panels

shortProject() decoded Claude Code slugs by splitting on '-', which
broke directory names containing dashes ('foo-bar' became 'foo/bar').
Switch the dashboard to consume ProjectSummary.projectPath (the
canonical cwd already extracted by parser.ts) and rewrite shortProject
to operate on a real absolute path.

* shortProject: cache homedir, normalize Windows backslashes, fix stale test helper

---------

Co-authored-by: Abdallah Meghraoui <abdallah.meghraoui@outlook.com>
2026-05-11 22:02:38 -07:00
Resham Joshi
38e41e93c3
Add Node version guard for unsupported runtimes (#319)
Split CLI into a tiny launcher (src/cli.ts) that checks for Node >= 22.13.0
before dynamically importing the full CLI (src/main.ts). Users on Node 18
now get a clear upgrade message instead of a cryptic regex parse error from
string-width. Closes #232.
2026-05-11 21:50:17 -07:00