Commit graph

545 commits

Author SHA1 Message Date
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
AgentSeal
a1b5e4bd00
Fix OpenCode MCP usage reporting (#318)
* Fix OpenCode MCP usage reporting

* Move OpenCode MCP changelog entry to Unreleased section

---------

Co-authored-by: ozymandiashh <234437643+ozymandiashh@users.noreply.github.com>
Co-authored-by: iamtoruk <hello@agentseal.org>
2026-05-11 21:30:27 -07:00
AgentSeal
c85beeaeae
Fix Claude 1-hour cache write pricing (#317)
Co-authored-by: ozymandiashh <234437643+ozymandiashh@users.noreply.github.com>
Co-authored-by: iamtoruk <hello@agentseal.org>
2026-05-11 21:23:04 -07:00
AgentSeal
03e22ecb80
Add IBM Bob provider with workspace extraction (#316)
Some checks are pending
CI / semgrep (push) Waiting to run
* Add IBM Bob provider

* Add workspace extraction for Cline-family providers

Extract project name from workspace directory in api_conversation_history.json
so sessions show actual folder names instead of the provider display name.
Thread projectPath through ParsedProviderCall to avoid unsanitizePath mangling
hyphenated folder names.

---------

Co-authored-by: ozymandiashh <234437643+ozymandiashh@users.noreply.github.com>
Co-authored-by: iamtoruk <hello@agentseal.org>
2026-05-11 20:54:13 -07:00
iamtoruk
b4b28becc8 Harden menubar refresh recovery 2026-05-11 20:44:06 -07:00
iamtoruk
4737bfb1fa Contribution rules: require real-data testing for new providers, one PR at a time 2026-05-11 20:04:18 -07:00
ozymandiashh
9187bc590a Add Cline provider 2026-05-12 00:31:41 +03:00
iamtoruk
f058f36dbd Normalize menubar version display 2026-05-11 11:21:39 -07:00
AgentSeal
cd8c646818
Merge pull request #311 from getagentseal/fix/menubar-manual-refresh-reset
Some checks are pending
CI / semgrep (push) Waiting to run
Make menubar Refresh Now reset stale state
2026-05-11 11:13:02 -07:00
iamtoruk
469d956312 Preserve menubar bundle seal during install 2026-05-11 11:11:37 -07:00
iamtoruk
33649e0a65 Refresh live quota progress from menubar 2026-05-11 11:09:20 -07:00
iamtoruk
ce0e1eb116 Make menubar refresh now reset stale state 2026-05-11 11:05:50 -07:00
AgentSeal
2301577e03
Merge pull request #310 from getagentseal/fix/menubar-wake-recovery
Fix menubar wake recovery and release asset selection
2026-05-11 10:58:33 -07:00
iamtoruk
1149ab6e43 Fix menubar wake recovery and release asset selection 2026-05-11 10:57:02 -07:00
iamtoruk
d9acd8c4cd Release 0.9.8
Some checks are pending
CI / semgrep (push) Waiting to run
2026-05-10 17:09:16 -07:00
Resham Joshi
02f4635cec
Fix node:sqlite V8 crash on invalid UTF-8 in text columns (#272)
node:sqlite calls v8::String::NewFromUtf8 with kAbort on TEXT columns.
Cursor chat blobs often contain truncated multi-byte chars from streaming
boundaries, which triggers a V8 CHECK abort (not a JS exception).

Select all text-content columns as CAST(col AS BLOB) so node:sqlite
returns Uint8Array instead. Decode in JS with TextDecoder fatal:false
which replaces bad bytes with U+FFFD. Covers all three SQLite providers
(Cursor, Goose, OpenCode).

Removes the version blocklist (MIN_NODE_22_PATCH) and lowers engines
requirement from >=22.20 to >=22 since the BLOB cast approach works
on all Node 22.x versions.

Closes #264
Closes #250
2026-05-10 17:05:08 -07:00
Resham Joshi
d142bd97ef
daily-cache: discard pre-v5 caches (fixes menubar providers regression) (#297)
PR #296 (Cursor per-project breakdown) bumped DAILY_CACHE_VERSION
from 4 to 5 but left MIN_SUPPORTED_VERSION at 2. The migration
path (isMigratableCache + migrateDays) only fills in missing
default fields; it does NOT recompute the providers / categories
/ models rollups from session data, because raw sessions are not
retained in the cache. So a v4 cache migrated to v5 carried
forward its old per-day provider totals (single 'cursor' bucket)
for the full retention window.

Effect on users post-#296: the macOS menubar's
`current.providers.cursor` would show the orphan-bucket subtotal
instead of the full Cursor cost for any historical day whose
daily entry was computed before #296 landed. Live-test on my
machine showed cursor=$3.78 against a migrated v4 cache vs
cursor=$4.08 (correct) after the daily cache was discarded — the
$0.30 gap was the workspace projects whose costs were no longer
aggregated under the 'cursor' label by the new code.

Fix: raise MIN_SUPPORTED_VERSION to 5 so any cache with
version < DAILY_CACHE_VERSION is renamed to `.bak` and the cache
is recomputed from scratch on next run. The recompute is the same
operation that backfills the cache for a new user, so the cost is
a one-time cold-path hit (~3s on the test machine).

Test for the migration case updated to assert the new
discard-and-bak behavior. Full suite: 46 files / 654 tests pass.
2026-05-10 16:05:59 -07:00
Resham Joshi
810b214476
Cursor: per-project breakdown by workspace (closes per-project half of #196) (#296)
Cursor's chat history showed as a single row labeled 'cursor' in
the dashboard because the global state.vscdb has no workspace
field on individual bubbles. The fix joins through Cursor's
per-workspace storage:

1. Walk ~/Library/Application Support/Cursor/User/workspaceStorage/*
2. For each hash dir, read workspace.json -> folder URI
3. Open that dir's state.vscdb, read
   ItemTable['composer.composerData'] -> allComposers list
4. Build Map<composerId, folder URI>
5. emit one SessionSource per workspace plus a catch-all 'cursor'
   source for composers that did not register against any
   workspace (multi-root workspaces, no-folder-open windows,
   deleted workspaces with surviving global rows)

The parser decodes source.path's #cursor-ws= tag, filters the
parsed bubbles to the composerIds that belong to this workspace,
and yields only those. The orphan-tag source negates the filter so
it captures every composer not in any workspace.

In passing, fix a real bug in the old code: parseBubbles set
`sessionId: row.conversation_id ?? 'unknown'`, but the JSON
`conversationId` field is empty in current Cursor builds, so every
call shipped with `sessionId: 'unknown'`. We now derive the
composer id from the row key (`bubbleId:<composerId>:<bubbleUuid>`)
which is what the workspace map joins on. The old behavior masked
the bug because every call went into a single 'cursor' project
anyway; with per-workspace bucketing the bug becomes load-bearing.
Cache version bumped 2 -> 3 to invalidate caches that still record
'unknown' as the session id.

Live-tested against my real 1.9 GB Cursor DB: the single 'cursor'
row with 1904 calls / $4.08 now breaks into 5 workspaces plus an
orphan bucket, totals reconcile exactly. 8 fixture-based tests
cover multi-workspace routing, orphan filtering, legacy bare DB
path backwards compat, multi-root workspace skip, vscode-remote
URI slugification, and total reconciliation across all sources.

Full suite: 46 files, 653 tests passing.
2026-05-10 15:35:57 -07:00
Resham Joshi
180e14da82
Merge pull request #293 from getagentseal/fix/menubar-loading-watchdog
Some checks are pending
CI / semgrep (push) Waiting to run
Fix menubar loading recovery deadlocks
2026-05-10 10:32:56 -07:00
Resham Joshi
3380517b24
README: drop Project Structure tree, add Sponsor section (#292)
The Project Structure tree was duplicating information that
docs/architecture.md already covers in better detail (and updates
faster). Removing it from the README keeps the marketing-facing
README scoped to "what is this and how do I install it" and
points contributors at the proper map.

In its place, a short Sponsor section pointing at
https://github.com/sponsors/iamtoruk so users who find the tool
useful know where to support development.
2026-05-10 03:35:16 -07:00
iamtoruk
d79deefaae Fix menubar refresh recovery deadlock 2026-05-10 03:30:56 -07:00