Commit graph

1192 commits

Author SHA1 Message Date
Vaibhav Arora
0ac09d8909 fix(menubar): reduce repeated status parsing
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 00:07:04 +05:30
Stephan Leicht Vogt
04f3fc1060
fix(menubar): support installer HTTP proxies (#475)
Some checks failed
CI / semgrep (push) Has been cancelled
Route the menubar installer's GitHub downloads through an undici ProxyAgent when HTTP(S)_PROXY is set, honoring NO_PROXY for bypass. Falls back to direct fetch when no proxy is configured. Closes #473.
2026-06-11 14:13:10 +02:00
theparlor
81fdeee5d6
fix(mac): restore right-click status-item menu on macOS 27 (#472)
Present the right-click menu from a global right-mouse-down monitor (hit-tested against the status-item window) via NSMenu.popUp, since macOS 27 no longer routes right-mouse events to the status-item action. Legacy action path retained for macOS <= 26, guarded by a debounce. Remove the global monitor on terminate.
2026-06-11 09:56:56 +02:00
steelp02
7d067e82b2
feat(providers): [copilot.ts]Add OTel cache token parsing including tests and regression checks.
Signed-off-by: steelp02 <pieter.steel@pfizer.com>
2026-06-10 22:58:12 +02:00
iamtoruk
f1bf7a197b feat(report): Claude-scoped agent-type breakdown
Some checks are pending
CI / semgrep (push) Waiting to run
Surfaces real subagent-transcript spend grouped by agentType
(workflow-subagent / Explore / general-purpose / …), read from each agent's
sibling .meta.json (cached on CachedFile; session cache bumped 3→4). This makes
ultra/workflow usage visible — the existing Task-input-based "subagents" section
never sees workflow agents. Shown in `report --format json` (claudeAgentTypes)
and a "Claude Agent Types" dashboard panel that renders only when Claude agent
transcripts exist, so it never appears for the other providers.
2026-06-10 11:45:28 +02:00
iamtoruk
aa07d5c939 fix(parser): count workflow/ultracode subagent usage (#470)
collectJsonlFiles only read agent transcripts directly under `subagents/`, but
the workflow feature nests them at `subagents/workflows/<wf>/agent-*.jsonl`, so
their tokens were dropped — undercounting whenever workflow/ultracode was on.
Walk the `subagents/` subtree recursively. Verified on real data: a workflow-
using project recovered ~16% of its cost, with no change to other projects.
2026-06-10 11:45:28 +02:00
iamtoruk
edc07c6149 chore(ci): bump GitHub Actions to Node 24 versions
Some checks are pending
CI / semgrep (push) Waiting to run
GitHub forces Node 20 actions to Node 24 on 2026-06-16. Bump to current
node24 runtimes (inputs verified unchanged):
- actions/checkout v4 -> v6
- actions/upload-artifact v4 -> v7
- softprops/action-gh-release v2 -> v3
2026-06-10 01:11:08 +02:00
iamtoruk
1e96a27df7 chore(release): 0.9.12
Changelog for 0.9.12, README node badge aligned to the real >=22 requirement
(node:sqlite for Cursor/OpenCode), and ws lockfile bumped to patched 8.21.0
(npm audit clean). No source changes.
2026-06-10 00:54:26 +02:00
iamtoruk
f0768d4c32 fix(parser): isolate Claude per-file parse failures
The per-file failure isolation #441 added to the provider path was missing on
the Claude path: a throw in groupIntoTurns/canonicalization propagated up and
emptied the whole daily-history backfill. Wrap the per-file parse in try/catch
+ a failed marker, mirroring the provider path; one bad file no longer wipes
the trend.
2026-06-10 00:09:31 +02:00
iamtoruk
e7c0e21846 fix(vercel-gateway): route network sources through aggregation
The synthetic source path has no on-disk file, so fingerprintFile returned
null and parseProviderSources dropped the source before parsing — the provider
always reported $0 even with a key set. Add a `network` provider flag; such
sources skip the fingerprint gate, re-fetch each run with a synthetic
fingerprint, and keep the gateway's reported cost (instead of recomputing from
tokens, which would be $0 for any model codeburn can't price). Adds an
end-to-end test through parseAllSessions.
2026-06-10 00:09:31 +02:00
iamtoruk
f4fd6a1640 fix(pricing): restore Mythos 5 pricing dropped by gap-fill cleanup
Mythos 5 ($10/$50) is not in LiteLLM or the models.dev/OpenRouter gap-fill
yet (Fable is), so dropping the manual patch left it priced at $0. Add it to
MANUAL_ENTRIES + the snapshot and map the "Mythos 5" display name.
2026-06-10 00:09:31 +02:00
Gaurav Sisodia
a2e18d79e7
fix(cursor): period-aligned lookback; add Vercel AI Gateway provider (#432)
Opt-in Vercel AI Gateway provider (AI_GATEWAY_API_KEY/VERCEL_OIDC_TOKEN), inert without a key. Cursor lookback now period-aligned with a 6-month floor. Gateway fetch hardened on merge with an 8s timeout and try/catch fallback.
2026-06-09 23:01:43 +02:00
KirDE
35a8518518
feat(antigravity-ide): added support for antigravity IDE (#418) 2026-06-09 22:12:01 +02:00
Tiago Santos
cf35854b09
feat: add devin provider (#444)
* feat: add devin provider

* feat: add devin to gnome extension and improve dev scripts

* fix: fix local installer

* chore: cleanup unecessary changes and address pr comments
2026-06-09 21:58:31 +02:00
Resham Joshi
02b16351be
fix(menubar-tests): add missing localModelSavings/savingsUSD args so swift tests compile (#465) 2026-06-09 21:56:13 +02:00
Resham Joshi
e83160f415
feat(pricing): proxy-aware cost attribution for subscription-backed Claude (#417) (#459)
Claude Code routed through a GitHub-Copilot-backed proxy (ANTHROPIC_BASE_URL
-> claude-code-over-github-copilot / claudegate) costs ~$0 marginal but was
priced at full Anthropic API rates, producing a misleading cost figure. The
JSONL records only the model name and no endpoint, so proxying cannot be
auto-detected; the user declares it.

Add a `proxyPaths` config (managed via a new `codeburn proxy-path` subcommand)
listing project directories served through a subscription proxy. Sessions whose
canonical path is under one keep their full API-rate totalCostUSD (the billable
would-be figure is never destroyed) and additionally report totalProxiedCostUSD,
so the JSON report overview exposes cost / proxiedCost / netCost
(netCost = cost - proxiedCost). With no proxyPaths configured the new fields are
0 and every existing consumer is unchanged.

Design: "full cost, flagged" was chosen over zeroing cost so a misconfigured or
since-changed path can never silently erase real Anthropic spend. Attribution is
project-level (one canonical path per project), computed in a single helper
(summarizeProject) that all ProjectSummary builders route through, including the
cross-provider merge in parseAllSessions (re-derived from the merged total so a
repo used with both Claude and Codex stays correct). The in-memory session-cache
key folds in a proxy-config hash so toggling proxyPaths in a long-lived process
cannot serve stale attribution. Path matching is segment-boundary anchored
(/foo does not match /foobar), trailing-slash and backslash tolerant, leading-
slash agnostic (so a non-Claude provider's slash-stripped path matches the same
way Claude's absolute path does), and case-folded only on case-insensitive
filesystems (macOS/Windows, not Linux). The proxy-path CLI sanitizes a
hand-edited config.json (non-array / non-string entries) rather than crashing.

Tested: isProxiedPath matching matrix (boundary, case, Windows, empty, root,
multi-path, leading-slash form); config-hash distinctness/order-independence;
end-to-end attribution through parseAllSessions incl. the critical negative
cases (real spend must not be zeroed); cross-provider Claude+Codex merge;
Codex-only project under a proxy path; date-range-filtered attribution;
cache-staleness after a config change; and the proxy-path CLI add/list/remove,
malformed-config robustness, and the report --format json overview.

Scope note: proxiedCost/netCost currently surface in `report --format json`
only; wiring them into the TUI dashboard and menubar payload is a follow-up.
2026-06-09 21:30:57 +02:00
Resham Joshi
f5d1a8513d
fix(menubar): await terminationHandler instead of blocking a queue thread; cap CLI spawns (#462)
The #426 fix moved waitUntilExit and its timeout onto the same global(qos:.utility)
queue. Under sustained load every utility worker blocked in waitUntilExit, so the
timeout could never be scheduled to kill them and the menubar wedged on Loading
forever (confirmed via sample after ~a week of soak). Await process.terminationHandler
(fires on a Foundation queue, blocks no worker) so the timeout always has a free
thread. Add an actor-based async semaphore capping concurrent CLI spawns at 6.
2026-06-09 21:27:32 +02:00
Resham Joshi
ad251cfa3d
chore(pricing): drop manual Fable/Mythos patch; fable now gap-filled from models.dev/OpenRouter; keep Fable 5 name (#464) 2026-06-09 21:22:38 +02:00
Resham Joshi
a385f65dee
feat(pricing): automatic gap-fill from models.dev and OpenRouter (#457)
Keep model pricing automatic instead of hand-coding new models. The bundler
now layers three sources in priority order: LiteLLM (broad list prices),
hand-curated MANUAL_ENTRIES overrides, then a separate last-resort fallback
file gap-filled from models.dev first-party makers (official direct prices)
and OpenRouter (resale backstop). New models such as MiniMax-M3 ($0.6/$2.4)
now price correctly with no per-model code.

The fallback is written to its own pricing-fallback.json and consulted only
case-insensitively as the final step in getModelCosts, so a reseller variant
name can never shadow a canonical or aliased match.

Fixes surfaced while building and verifying this:
- Alias precedence: LiteLLM ships snowflake/claude-4-opus ($5), which the
  bundler strips to a bare claude-4-opus key that shadowed the curated alias
  to claude-opus-4 ($15 official). An explicit alias for a bare name now wins
  over a coincidental stripped reseller key; the prefixed gateway price is
  still returned for the fully-qualified id.
- Zero-stub guard: LiteLLM [0,0] price stubs (e.g. GigaChat-2-Max) are
  excluded from the case-insensitive index so a case-mismatched query stays
  null and keeps firing the unknown-model warning instead of silently
  reporting $0.
- Negative-sentinel guard: OpenRouter returns -1 for variable/BYOK-priced
  models. The bundler now rejects any non-positive rate pair (and strips the
  sentinel from cache fields) so a negative per-token cost can never ship and
  subtract from spend totals.

Bundler hardening: bareKey strips @pin and date suffixes to match the runtime
canonical form, seen-set dedupes on both full and bare key shapes, and it logs
MANUAL_ENTRIES now covered upstream plus models.dev allowlist drift. Extracted
buildCosts so the cache-cost heuristics live in one place. Added a data-hygiene
test that fails CI if a rebundle reintroduces negative, free, or unreachable
fallback entries.
2026-06-09 21:17:23 +02:00
Resham Joshi
c36f3afa76
chore(pricing): temp Fable 5 + Mythos 5 launch pricing ($10/$50 per M) + names until LiteLLM indexes them (#463) 2026-06-09 20:51:51 +02:00
Resham Joshi
8e460096e3
fix(codex): content-address fork dedupe key to stop undercounting divergent events (#458)
Some checks failed
CI / semgrep (push) Has been cancelled
Forked Codex sessions copy the parent's entire token_count history
(re-timestamped), so those replays are keyed into the parent's namespace
(forkedFromId) and deduped to avoid double-counting the parent's spend. But the
key used cumulativeTotal alone, which is too coarse: a genuine post-divergence
fork event whose running total coincidentally equals some parent total collided
with it and was dropped, undercounting real spend.

Add the cumulative token breakdown (input, cached, output, reasoning) to the
dedupe key. A fork replays those cumulative figures verbatim, so a true replay
still collides and parent and fork are not double-counted, while genuinely
different work that happens to reach the same cumulative total stays distinct.

The breakdown must come from the CUMULATIVE totals, not the per-event deltas:
the deltas are computed against a running `prev` that the fork advances
differently once the 5s replay cutoff skips some events, so a delta-based key
would spuriously diverge on a replay and double-count it (in the total-only
fallback branch).

This is the correct fix for issue #413. The reported "undercount" is mostly
replayed parent history being correctly credited to the parent, not lost; the
issue's suggested change (key on the fork's own session id) would instead
re-double-count the entire replayed history. Three regression tests pin the
invariants: a replay past the 5s cutoff counts once, a divergent fork event
sharing a parent's cumulative total is kept, and a total-only fork whose replay
straddles the cutoff does not overcount.
2026-06-07 07:29:42 +02:00
Resham Joshi
0edc8644aa
test(copilot): add JetBrains coverage; fix Windows path inference (#433 follow-up) (#456)
Some checks are pending
CI / semgrep (push) Waiting to run
Follow-up to #433. Adds tests for the JetBrains format: discovery of a jb
chat.jsonl, parsing into a call with inferred model/tools/user message, the
isJetBrainsFormat routing guard (legacy user.message files must not route to
the JB parser), and the id-less dedup fallback.

Also fixes inferJBProjectFromContent: it split homedir() on the platform
separator but the recorded tool path on a fixed '/', so project inference
always fell back to the raw session id on Windows. Split both on either
separator.
2026-06-06 23:32:56 +02:00
Zuber Khan
e7920fc6aa
feat: add JetBrains (IntelliJ/DataGrip) session discovery and parsing (#433)
* feat(copilot): add JetBrains (IntelliJ/DataGrip) session discovery and parsing
The Copilot provider previously only discovered sessions from:
- ~/.copilot/session-state/ (legacy VS Code format)
- VS Code workspace storage directories
IntelliJ and other JetBrains IDEs store Copilot chat sessions in
~/.copilot/jb/<session-id>/partition-*.jsonl using a slightly different
event format. This commit adds:
- discoverJetBrainsSessions(): finds all .jsonl files under ~/.copilot/jb/
- isJetBrainsFormat(): detects JB event format (no session.start header)
- parseJetBrainsEvents(): parses JB events (assistant.message with text/
  thinking, tool.execution_start for tool names, tool call ID prefixes
  for model inference)
- inferJBProjectName(): extracts project name from tool execution paths
Closes #N/A

* fix: address PR review feedback for JetBrains Copilot support
- Add 'sep' to path import (fixes ReferenceError in project inference)
- Use incrementing index as dedup key fallback when messageId is absent
  to prevent undercounting tokens/cost
- Move project inference to parse time using already-loaded content
  (avoids bypassing readSessionFile's 128MB safety cap)
- Tighten isJetBrainsFormat to only match user.message_rendered and
  partition.created (avoids false-positive on legacy files starting
  with user.message)
- Add dedicated inferModelFromEvents for JB format that checks
  data.model (100x weight) and tool call ID prefixes on
  tool.execution_start/complete events
- Remove dead first-pass loop that was never read
- Add jbDirOverride param to createCopilotProvider for test fixtures
2026-06-06 23:28:42 +02:00
Resham Joshi
4a384cd31d
feat(menubar): add macOS app icon (#455)
Adds assets/menubar-logo.png and generates AppIcon.icns (all standard sizes
via sips + iconutil) in package-app.sh, so the menubar app ships with a real
icon instead of the generic one. Info.plist already referenced AppIcon.

Icon and bundler change from @tvcsantos's #439; the unrelated tsconfig.json
change in that PR was left out.
2026-06-06 23:16:03 +02:00
Resham Joshi
fda117face
Merge pull request #454 from getagentseal/integrate/local-model-savings
feat(cli): local-model cost savings, re-homed onto current main (#421)
2026-06-06 22:38:23 +02:00
AgentSeal
a318375c6e Only show the Saved column when local-model savings exist
Without a model-savings mapping the Saved column was an unlabeled column of
dashes between Cost and Calls (menubar) and a dim '-' column (CLI models
report). Show it only when at least one model has savingsUSD > 0, so users
with no mapping keep the plain Cost/Calls layout. The menubar Hero caption was
already conditional.
2026-06-06 22:26:29 +02:00
AgentSeal
5a41f39944 Merge PR #423 (local-model savings) onto main, re-homing payload savings into usage-aggregator
Resolves conflicts from the post-PR refactor that moved buildPeriodData,
hydrateCache, and the menubar payload builder out of main.ts into
usage-aggregator.ts. The PR's savings additions to those functions are
re-homed there; config.ts keeps both new fields; parser.ts keeps both imports;
redact.ts session details carry savingsUSD.
2026-06-06 22:14:13 +02:00
Resham Joshi
efa8593cc5
fix(parser): cache parse failures so broken files aren't re-read every run (#441 follow-up) (#453)
Some checks are pending
CI / semgrep (push) Waiting to run
Follow-up to #450. When a session file throws during parse it was excluded but
left uncached, so every refresh (~4x/min in the menubar) re-read and re-parsed
it, and only the first failing file per provider was ever surfaced.

- Add a negative-result marker: a failed file is cached as { fingerprint,
  turns: [], failed: true }. reconcileFile treats it as 'unchanged' at the same
  fingerprint, so it's skipped (no re-read) until the file changes. Empty turns
  => contributes no usage.
- Warn per offending file (with its path), capped at 5 per provider per run,
  instead of once-per-provider — so a systemic break surfaces more than one file
  without flooding. Cached markers keep it quiet across refreshes.

Tests: marker round-trips through save/load; reconcile stays 'unchanged' at the
same fingerprint and re-parses when the file changes.
2026-06-06 21:10:10 +02:00
Resham Joshi
e8009c4559
fix(parser): tolerate string message content; isolate per-file parse failures (#441) (#450)
Some checks are pending
CI / semgrep (push) Waiting to run
Some agents (Pi, and others for injected turns) write a message's `content`
as a string instead of an array of blocks. Parsers did `(content ?? []).filter`,
which throws on a string — and because the daily-cache backfill swallowed parse
errors, one bad session silently wiped the entire trend/history.

- Add normalizeContentBlocks(): string -> one text block, array -> as-is (by
  reference; drops null/undefined elements so the same crash can't happen one
  level down), else -> []. Applied across pi/codex/droid/cursor-agent and the
  Claude path in parser.ts.
- Isolate per-file parse failures in parseProviderSources: skip the offending
  file (warn once per provider) instead of re-throwing and aborting the whole
  backfill. The stale cache entry is already cleared, so the file is excluded.
- Surface backfill failures in hydrateCache via stderr instead of silently
  returning an empty cache.

Likely fixes #425 (previous-day always 0) for the throwing-file cause.
Tests: content-utils unit tests + a Pi string-content regression test.
2026-06-06 04:01:12 +02:00
Resham Joshi
f57ad64ce7
fix(network): add timeouts to critical-path fetches (#445) (#448)
The pricing fetch (loadPricing -> fetchAndCachePricing) runs on every CLI
invocation, and the macOS menubar shells out to the CLI and blocks on its
exit. fetch() had no timeout, so a half-open network after wake-from-sleep
made it hang forever once the 24h pricing cache expired — wedging the
menubar on its loading spinner until relaunch.

Add a shared fetchWithTimeout helper (8s default, AbortSignal.timeout) and
apply it to the two daily-critical-path fetches: pricing (models.ts) and
the currency rate (currency.ts). On timeout the existing catch falls back
to the bundled price snapshot / cached or USD rate.

Reproduced on main (stale cache + black-holed host -> hangs indefinitely);
with the timeout the same scenario aborts in 8s and renders via fallback.
2026-06-06 03:25:36 +02:00
Resham Joshi
77340e52b8
fix(models-report): stop double-counting cache reads (#447)
cacheReadInputTokens (Anthropic) and cachedInputTokens (OpenAI) name the
same tokens. ~11 providers populate both with the same value, so summing
them doubled the cache-read token figure in the models report. Take the
max instead. Cost is unaffected (calculateCost never used the sum).
2026-06-06 03:14:51 +02:00
Resham Joshi
cef1a6b669
refactor(mux): drop dead openai reasoning fallback (#446)
usage.reasoningTokens is the AI SDK v6 normalized field across all
provider families, so the providerMetadata.openai fallback never fired.
Removed it and the now-unused openai extraction.
2026-06-06 03:05:07 +02:00
Thomas Kosiewski
e0051fc403
feat(providers): add coder/mux as a datasource (#438)
* feat(providers): add coder/mux as a datasource

Reads coder/mux session data from ~/.mux/sessions/<workspaceId>/chat.jsonl and normalizes per-assistant-message token usage into ParsedProviderCall. Discovery resolves project names from config.json; the token decomposition matches mux's own inclusive input/output accounting, and cost is recomputed via LiteLLM. Includes unit tests and a provider doc.

Change-Id: Ie6ce9d41254d8bf05ff0965b443328dfa7b598de
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>

* fix(providers): discover mux sub-agent transcripts

discoverSessions only globbed sessions/<id>/chat.jsonl and skipped each
spawned sub-agent's transcript at
sessions/<id>/subagent-transcripts/<childTaskId>/chat.jsonl. Against a real
~/.mux (629 workspaces) those nested files are 5,889 sessions and ~51% of all
assistant messages, so sub-agent spend was silently dropped: total mux usage
went from $17,113 to $21,564 (+26%) once counted.

Walk the subagent-transcripts dir per workspace and attribute each child
session to the parent's project. Dedup is unaffected: the parser keys off the
<childTaskId> dir name, which is disjoint from every workspace id, so each call
is still counted once. Cross-checked parsed per-model token totals against
mux's sibling session-usage.json.

Also corrects the provider doc, which wrongly claimed sub-agents get their own
top-level sessions/<id>/chat.jsonl, and documents the Google reasoning>output
decomposition edge case.

Change-Id: I1d43f26eec7c9c6c523e5ea541e2ff8d0c3aa07e
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: Thomas Kosiewski <tk@coder.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 03:04:24 +02:00
Porun
42ef1ff97e
Add contribution heatmap insight (#437)
* Add contribution heatmap insight

* fix(menubar): heatmap layout polish — labels, spacing, pill order

---------

Co-authored-by: AgentSeal <hello@agentseal.org>
2026-06-06 02:49:08 +02:00
Resham Joshi
3cdd13881f
feat(menubar): configure CLAUDE_CONFIG_DIRS via Settings (#434) (#436)
Adds a "Config Directories" section under the Claude settings tab so users
can aggregate usage across multiple Claude config directories (work /
personal accounts) from the GUI. The menubar is an accessory app that
doesn't inherit the user's shell environment, so CLAUDE_CONFIG_DIRS was
previously unreachable from the app.

Rather than injecting the value as an env var into every spawned subprocess
(which would force arbitrary user paths through the shell/AppleScript
allowlist that deliberately excludes shell metacharacters), the list is
persisted to the shared ~/.config/codeburn/config.json. The CLI reads it
regardless of how it's launched, so both the menubar's data refresh and
terminal-launched `report`/`optimize` honor it consistently.

CLI: getClaudeConfigDirs() now reads a claudeConfigDirs array from config
as a fallback below the CLAUDE_CONFIG_DIRS / CLAUDE_CONFIG_DIR env vars
(env still wins for per-shell overrides), above the ~/.claude default.

Menubar: CLIClaudeConfig mirrors CLICurrencyConfig's flock-guarded write;
the Settings UI offers an add/remove list with a folder picker and forces
a refresh on edit.
2026-06-06 02:30:46 +02:00
Resham Joshi
14fbd4d6d1
fix(menubar): use SupportedCurrency enum in settings picker (#435)
Some checks failed
CI / semgrep (push) Has been cancelled
The currency picker hardcoded 8 currencies while the SupportedCurrency
enum defines 18. New currencies added to the enum (like CNY in #430)
required a separate SettingsView edit to appear in the picker.
2026-06-03 23:27:55 +02:00
Resham Joshi
a6601efc60
Merge pull request #430 from PorunC/feat/add-cny-currency
Add CNY currency support
2026-06-03 23:25:32 +02:00
AgentSeal
692bc09729 Merge feat/codeburn-mcp: MCP server for AI agent usage queries
Adds stdio-based MCP server (codeburn mcp) exposing get_usage and
get_savings tools. Includes pseudonymized project names with per-install
salt, session detail redaction, structured output schemas, and inflight
request coalescing.
2026-06-03 22:48:36 +02:00
Misaka
906c5338e4 Add CNY currency support 2026-06-03 10:45:39 +08:00
AgentSeal
f748d3463b fix(test): kilo-code tests fail on machines with KiloCode installed
Some checks are pending
CI / semgrep (push) Waiting to run
discoverSessions always checks the SQLite path at ~/.local/share/kilo
regardless of overrideDir, so the test found real sessions on the host.
Filter to override-dir sessions and avoid hardcoded /tmp paths.
2026-06-03 01:03:39 +02:00
AgentSeal
679f7ba5a6 fix(mcp): harden redaction, error responses, and pre-warm race
- Add per-install random salt to pseudonym hash to prevent rainbow table
  reversal of common project names
- Redact session details (dates, models) when project names are hashed
  to prevent re-identification via cost fingerprinting
- Return structuredContent in error responses to satisfy strict MCP
  clients that validate against declared outputSchema
- Remove pre-warm fire-and-forget that raced with the inflight map
- Fix empty markdown table producing malformed cells
- Add tests for session detail redaction and cross-field consistency
2026-06-03 00:56:30 +02:00
Resham Joshi
bec0491667
Merge pull request #426 from getagentseal/fix/menubar-dataclient-deadlock
fix(menubar): run CLI exit-wait and timeout off the cooperative pool
2026-06-02 15:56:11 -07:00
iamtoruk
94e6b77672 feat(mcp): add 'codeburn mcp' stdio command with stdout guard 2026-06-02 02:18:00 -07:00
iamtoruk
1e54967d97 feat(mcp): get_usage + get_savings tools with annotations, schemas, coalescing 2026-06-02 02:16:10 -07:00
iamtoruk
296085dff1 feat(mcp): markdown table renderers for usage and savings 2026-06-02 02:13:51 -07:00
iamtoruk
1e82a9cf21 feat(mcp): hash project names by default with opt-in reveal 2026-06-02 02:13:08 -07:00
iamtoruk
d5c8ad0bfd refactor: extract buildMenubarPayloadForRange for reuse by MCP 2026-06-02 02:12:27 -07:00
iamtoruk
2c46488f0f refactor: move buildPeriodData into usage-aggregator module 2026-06-02 02:01:45 -07:00
iamtoruk
4e61fd1369 build(mcp): add @modelcontextprotocol/sdk + zod, externalize in tsup 2026-06-02 01:38:45 -07:00
iamtoruk
0843efdecb docs(mcp): add implementation plan for codeburn MCP server 2026-06-02 01:33:08 -07:00