Commit graph

696 commits

Author SHA1 Message Date
iamtoruk
df05d7792e perf: web dashboard period prefetch + menubar serve client
Two more surfaces adopt the resident-serve pattern the desktop app got:

- Web dashboard: every period tab is prefetched sequentially right after
  startup, so the first click on 7d/30d/Month answers from the payload
  cache instead of paying a full parse; stale-while-revalidate rebuilds
  behind a served payload past 75% of the TTL so expiry never lands its
  multi-second parse on a user's click. Lifetime prefetches last.
- Menubar: ServeConnection (Swift actor) holds one codeburn serve --stdio
  child; status payload fetches route through it once warm, with the same
  contract as the app client — cold start and every failure keep the
  spawn path, three child deaths disable serve for the run, requests
  time out by killing the child, app termination shuts it down, and a
  pre-serve CLI (0.9.19) simply dies into permanent spawn fallback, so
  mixed-version installs degrade gracefully.

swift build clean, swift test 156/156, CLI tsc clean; verified live with
both the Electron app's and the menubar's serve children resident and
answering.
2026-08-10 11:17:59 -07:00
iamtoruk
cecb6239c6 fix(serve): close the resident-process staleness and growth holes
Adversarial review of the serve design surfaced three weaknesses a
one-shot CLI never had, because it never lived long enough:

- Pricing-affecting config (model aliases, price overrides, local-model
  savings) now participates in the parse memo key. Config reloads fresh
  per request (the preAction hook), but a memoized or burst-reused parse
  embedded costs priced under the OLD config; the widened key makes any
  such change an automatic memo miss. New alias-hash helper + tests.
- Memory guard: past 3GB RSS the serve loop drops its in-memory memos
  (session cache + parse entries) and the next request re-parses once.
  The child never exits for this, so the client's death budget is
  untouched.
- codeburn serve typed in an interactive terminal now explains itself on
  stderr instead of hanging silently on stdin.
2026-08-10 10:03:33 -07:00
iamtoruk
d78ab77d96 perf: resident serve process for the desktop app — panel fetches in milliseconds
Every CLI spawn on a large corpus pays seconds of fixed cost before any
query work: node boot, a 100MB+ session-cache JSON.parse, the discovery +
fingerprint sweep, and serve-time classification. The desktop app spawns
one CLI per panel fetch, so it pays that cost per panel.

codeburn serve --stdio is the same CLI kept warm: the app holds one child,
sends {id, args} per line, and gets the command's stdout back. Three layers
make it fast, each disabled outside serve so one-shot runs stay byte-exact:

- loadCache memo (session-cache.ts): the parsed cache object is reused
  while a stat() shows the file unchanged; saveCache updates it
  write-through. A rewrite by another process still forces a fresh read.
- burst reuse (parser.ts, CODEBURN_PARSE_BURST_MS, serve sets 10s): panel
  bursts anchor their range ends at their own new Date(), so the exact-key
  memo never hits in real traffic; within the window a re-anchored range is
  served by trimming the previous parse instead of re-running discovery.
- fresh commander program per request (main.ts buildProgram factory),
  because commander option state is sticky across parses.

The server allows only the app's read queries (status/overview/models/
sessions/compare/yield/spend/optimize/audit), refuses everything else
(client falls back to a spawn), serializes requests, and converts
process.exit into a caught signal. The app starts the child once at
startup; requests route through it only when warm, cold-start keeps the
spawn path with its progress events, any serve failure falls back to a
spawn, and three child deaths disable serve for the app run.

Measured on a real 17B-token corpus: panel fetches drop from ~7.4s per
spawn to 5-900ms warm (sessions/spend 5ms, status 898ms). One-shot CLI
output verified byte-identical against the pre-branch baseline.
2026-08-10 09:43:44 -07:00
iamtoruk
1103ca77a5 fix(insights): count read-shaped shell commands as reads, not as verification (#941) 2026-08-10 06:07:27 -07:00
iamtoruk
44082c3d1f Merge remote-tracking branch 'origin/main' into feat/tui-workflow-titles
# Conflicts:
#	src/dashboard.tsx
2026-08-10 04:51:55 -07:00
Resham Joshi
e7a3313cb9
Merge pull request #951 from getagentseal/feat/tui-wheel-scroll
feat(tui): mouse-wheel scrolling for the dashboard viewport
2026-08-10 04:51:18 -07:00
iamtoruk
61f5e7c24f fix(tui): floor pricing coverage so 100% means genuinely complete 2026-08-10 04:46:39 -07:00
iamtoruk
420f1f051f fix(insights): stop counting prose 'wrong answer' as a user correction 2026-08-10 04:45:52 -07:00
iamtoruk
cf281a2fb1 feat(tui): mouse-wheel scrolling for the dashboard viewport via SGR mouse reporting 2026-08-10 04:41:34 -07:00
Resham Joshi
9df25fa066
Merge pull request #903 from ozymandiashh/feat/899-proberoots-tier1
feat(doctor): probeRoots for 12 more providers (#899 Tier 1)
2026-08-10 02:49:47 -07:00
iamtoruk
27eac2cca4 Merge main; declare openclaude in the env-declaration guard file map 2026-08-10 02:49:25 -07:00
Resham Joshi
5d66f073ad
Merge pull request #900 from ozymandiashh/fix/ink-win-strip-sync-escapes
fix(ink-win): strip synchronized-update escapes instead of exact-matching them
2026-08-10 02:48:17 -07:00
Resham Joshi
ad3b12bb4d
Merge pull request #908 from ozymandiashh/fix/swarm-robustness
fix(hardening): guard three malformed-input crashes (URL, timestamp, pricing entry)
2026-08-10 02:40:33 -07:00
Resham Joshi
c6548fc96f
Merge pull request #906 from ozymandiashh/fix/770-tz-carry-dedup
fix(daily-cache): surgical tz-migration de-dup for carried days (#770)
2026-08-10 02:30:12 -07:00
Resham Joshi
259c7b5708
Merge pull request #927 from ozymandiashh/fix/920-provider-env-fingerprints
fix(cache): declare the provider env overrides that must invalidate the cache
2026-08-10 02:30:08 -07:00
Matthew Kelch
3536a1d3ac
fix(copilot): classify CLI sessions by source provenance, not producer (#945)
Some checks failed
CI / semgrep (push) Has been cancelled
Tests / test (push) Has been cancelled
Fixes #944.
2026-08-09 04:51:44 +03:00
ihearttokyo
74e69ba2fd
Stabilize TUI refresh, scrolling, responsive layout, and dashboard data density (#863)
Improve dashboard refresh coordination, scrolling, responsive layout, and data-density behavior, including the Windows-safe resize correction validated on the final head.
2026-08-09 03:39:19 +03:00
Rick Culpepper
08e6c99d3b
feat(doctor): probeRoots for six fixed-location providers (#899 Tier 2, batch 1) (#938)
Add doctor probeRoots coverage for the remaining fixed-location providers while keeping discovery and diagnostics on the same shared root-resolution logic.
2026-08-09 03:38:35 +03:00
ozymandiashh
a67bd279a6 test(cache): make the round-2 review findings fail when broken
Round 2 of the independent review proved five things by mutation: it broke the
behavior and the tests stayed green. Every one is now pinned.

The most important invariant in this change was the least guarded. Copilot must
have NO entry in PROVIDER_ENV_VARS - declaring any of its nine reads moves its
fingerprint and re-opens the durable history-loss path - but only one of the
nine was covered, so declaring any of the other eight passed the whole suite.
Now the absence of the entry is asserted directly, and all nine vars are
table-tested for fingerprint stability.

Doctor stops blaming parse-only overrides for a failed discovery.
CODEBURN_CURSOR_MAX_BUBBLES caps how many bubbles Cursor parses and
KIMI_MODEL_NAME renames an attributed model; neither relocates anything, so
"NOTHING FOUND (override CODEBURN_CURSOR_MAX_BUBBLES set...)" pointed the user
at the wrong thing. Both join NON_DISCOVERY_ENV_VARS, which exists for exactly
this, and both still appear in Details - only the verdict's blame line changes.

The secret-redaction and ambient-suppression tests are table-driven over both
names each covers, since removing either second name (VERCEL_OIDC_TOKEN,
LOCALAPPDATA) previously leaked or surfaced it with every test still passing.

The changelog no longer claims a one-time re-parse for the Vercel gateway: it
is a network provider re-fetched on every writable run, so its declaration is a
read-only-path correction, not a migration. Fourteen file-backed providers
migrate once.
2026-08-05 05:58:17 +03:00
ozymandiashh
9c9a37d4bf fix(cache): act on the independent review of the env-fingerprint fix
Five findings from a cross-model review of the previous two commits, each
verified on the code before acting:

Copilot is no longer declared. Declaring anything for it changes its
fingerprint, and getOrCreateProviderSection keeps only cached entries whose
source path is gone - but OTel discovery returns one source per DB file
(copilot.ts:1935) and that DB keeps existing, so the entry would be dropped and
re-parsed, destroying conversations Copilot has since pruned from the DB that
only the cache still holds. Trading a staleness bug for a data-loss bug is a
bad trade; copilot waits for the durable carry-forward to merge instead of
drop, and its reads are allowlisted with that reason.

The Vercel gateway credentials ARE declared, reversing the previous commit's
reasoning, which was wrong: servedSources is seeded with every discovered
source (parser.ts:2875) before the network branch, and the network re-fetch
(parser.ts:2888) only runs when !readOnly, so a read-only refresh serves the
cached report and an undeclared credential keeps reporting the previous
account's usage after a swap. Doctor redacts credential values so a key can
never reach terminal output or the JSON report.

AMBIENT_ENV_VARS narrows to APPDATA and LOCALAPPDATA. Windows sets those for
every process so they carry no intent, but the XDG vars are opt-in and do:
suppressing them made doctor answer a deliberately relocated XDG_DATA_HOME with
"tool likely not installed", which is worse than the noise it avoided.

The guard's allowlist is keyed by file and var, not var alone - a var
allowlisted for one file silenced every other file's undeclared read of it.

Cursor drops its stale XDG_DATA_HOME declaration, which it never reads; its
fingerprint already changes here, so this costs no extra migration.
cursor-agent keeps its equally stale one, since removing it would force a
re-parse to fix nothing.
2026-08-05 05:22:50 +03:00
ozymandiashh
36004080a6 fix(cache): declare the provider env overrides that must invalidate the cache
Nine providers honor an env var that relocates where discovery looks, but the
var was never declared in PROVIDER_ENV_VARS, so computeEnvFingerprint() did not
hash it and the provider's cache section survived the change: sessions parsed
from the old root kept being reported and the new root was never read, with no
diagnostic anywhere (#920, same silent-wrong-numbers family as #874).

Declare every env var that changes what a provider discovers or how its
sessions parse, including the platform path vars that resolve a discovery root
on Windows and Linux, and the CodeBurn-side directory overrides.

Ambient platform vars (APPDATA, LOCALAPPDATA, XDG_CONFIG_HOME, XDG_DATA_HOME)
are set by the OS or the desktop session for everyone, so doctor must not name
them as a deliberate override: without the guard every Windows user would be
told Claude and Copilot discovery runs under an override. They stay in the
fingerprint - a change to them does move the discovery root - but doctor skips
them when collecting overrides, and the probed paths it already prints show
where CodeBurn looked.
2026-08-05 04:28:54 +03:00
ozymandiashh
b7235adb16 fix(parser): fold SQLite -wal siblings into source fingerprints
Hermes, Cursor, OpenCode and copilot OTel sources all live in SQLite
databases that their agents keep open in WAL mode for the life of the
process. Committed writes park in <db>-wal until a checkpoint, so the
main file's stat can sit hours or days behind the newest committed data.

fingerprintFile only statted the main file, which broke two ways:

- The date-range mtime pre-filter in parseProviderSources read the stale
  mtime as "nothing in range" and skipped the source entirely. Every
  Hermes session committed after the last checkpoint vanished from
  reports: the today-parse skipped the db (mtime < local midnight) while
  the backfill only keeps days through yesterday. Exactly the "17
  sessions in the DB, 14 reported, the 3 from today missing" report in
  issue #913.

- reconcileFile saw an unchanged fingerprint between checkpoints and kept
  serving stale cached turns for sessions that had since grown.

Fold the -wal sibling into the fingerprint: newest mtime wins and sizes
add, so both WAL growth and a checkpoint (db grows, wal truncates) move
the fingerprint. -shm is deliberately ignored (it mutates on reads).
Bare SQLite paths get the fold only when the extension says database, so
JSONL transcript fingerprints (offset-based append detection) are
untouched.

Refs #913
2026-08-04 14:38:43 +03:00
Resham Joshi
0ca1d1cbb1
Merge pull request #909 from ozymandiashh/fix/swarm-provider-accuracy
fix(kiro): estimate input tokens from the full prompt, not a 500-char slice
2026-08-04 03:28:18 -07:00
Resham Joshi
22e122f137
Merge pull request #910 from ozymandiashh/fix/swarm-cache-correctness
fix(optimize): strengthen the result-cache fingerprint against collisions
2026-08-04 03:24:38 -07:00
ozymandiashh
99bf24611e fix(context-budget): stop double-counting home skills and CLAUDE.md
When the project directory IS the home directory, countSkills pushed both
~/.claude/skills and <project>/.claude/skills - the same path - and counted
every skill twice, and scanMemoryFiles read ~/.claude/CLAUDE.md twice,
inflating the context-budget estimate. Dedupe both by resolved path.
Mutation-checked: a single home skill counts 2 before the fix, 1 after.
2026-08-04 06:32:58 +03:00
ozymandiashh
48fd0daa0c fix(providers): guard two malformed-input crashes in the parse path
- vscode-cline-parser: entry.ts was truthy-checked but not validity-checked,
  so a garbage timestamp made new Date(ts).toISOString() throw RangeError and
  abort the whole session parse. Validate the date, fall back to empty.
- models: parseLiteLLMEntry read fields off its argument with no null/type
  guard, so a null value in the remote LiteLLM pricing JSON threw and aborted
  the entire live pricing load. Return null for a null/non-object entry.

Both mutation-checked: the tests raise RangeError / TypeError before the fix.
2026-08-04 06:28:41 +03:00
ozymandiashh
75b7df6bdd fix(optimize): strengthen the result-cache fingerprint against collisions
cacheKey fingerprinted only project count + api-call sum, so two datasets
agreeing on those two numbers collided onto one cached OptimizeResult, and
a cost/token change that left call count unchanged (e.g. a re-price) served
stale findings within the 60s TTL - reachable in the long-lived menubar.
Fold total cost, savings and proxied cost (scaled to micro-dollars) into
the key. Exported cacheKey and mutation-checked: the old key collides two
same-shape datasets and a re-price; the new one separates both, while an
identical dataset still keys identically.
2026-08-04 06:01:07 +03:00
ozymandiashh
6c4645a8bc fix(kiro): estimate input tokens from the full prompt, not a 500-char slice
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.
2026-08-04 05:58:17 +03:00
ozymandiashh
2b49608fd2 fix(sharing): answer malformed request URLs instead of crashing the server
handle() is dispatched via `void`, so a throw before its try/catch is an
unhandled rejection on a LAN-facing server. A request target the HTTP
parser accepts but the WHATWG URL parser rejects (unterminated IPv6 host
like //[::1) threw at new URL() and hung/killed the process. Parse inside
a guard and answer 400. Mutation-checked: the test times out with an
unhandled error before the fix, passes after.
2026-08-04 05:56:18 +03:00
ozymandiashh
43f807769a fix(daily-cache): surgical tz-migration de-dup for carried days (#770)
On a tz-change full re-derive, mergeDayEntries carried a baseline slice
whenever the fresh day had no data slice for that (date, provider), so a
turn that re-bucketed across local midnight left its old day sliceless,
got carried there, AND counted again on its new day. This subtracts from
each carried baseline slice exactly what the fresh parse still attributes
to that (date, provider) under the OLD bucketing (dateKeyInTz): the
re-bucketed turns, nothing else. A sources-gone slice has no such content
and survives untouched; a fully-explained slice is dropped; residual
slices ADD their sessions instead of max-dedup, since the subtraction
already removed the placeholder's share.
2026-08-04 04:11:30 +03:00
ozymandiashh
718a2b3a08 feat(openclaude): OpenClaude CLI provider (#213)
OpenClaude is a Claude Code fork routing to any LLM; transcripts are
Claude-Code-schema JSONL under ~/.openclaude/projects/<slug>/<uuid>.jsonl
with replay.json siblings skipped. Only usage-bearing assistant lines
become calls; sidechain lines are counted as real spend; costs are always
computed (the transcript reports none) through the shared tables.

Real local testing: sessions generated with the actual CLI against
DeepSeek (deepseek-chat), parsed end to end.
2026-08-04 04:05:25 +03:00
ozymandiashh
800f650dbd feat(doctor): probeRoots for 12 more providers (#899 Tier 1)
Each implementation calls the exact resolution helpers its provider's
discovery uses (same env fallbacks, same OS branches, same closure
overrides), so doctor reports precisely where discovery looks and a
stale override or moved data dir stops being a silent $0.00.

lingtai-tui deliberately reports its candidates pre-existence-filter:
getLingTaiHomes drops non-existent dirs (right for discovery, wrong for
doctor, whose job is to show where it looked).

tests/provider-probe-roots.test.ts locks the mirroring: where a factory
takes an override, the same override must come back through probeRoots.
2026-08-04 03:28:59 +03:00
ozymandiashh
bff930e645 fix(ink-win): strip synchronized-update escapes instead of exact-matching them
The ConPTY guard swallowed a chunk only when it exactly equaled BSU or
ESU, so any write concatenating them with other output reached Windows
raw and hung ConPTY, which buffers the unimplemented 2026 sequence
indefinitely (#195; the class recurred in #863's resize path). Strip
every occurrence from string chunks instead: standalone escapes are
swallowed, concatenated ones lose only the escapes, and a swallowed
write now also honors its callback so callback-style writers cannot
wedge. Non-string chunks pass through untouched.
2026-08-04 03:06:47 +03:00
Resham Joshi
2c3319b286
Merge pull request #889 from ozymandiashh/fix/865-provider-list-project-filter
Some checks are pending
CI / semgrep (push) Waiting to run
fix(menubar): apply --project/--exclude to the provider list on carried days
2026-08-03 17:06:32 -07:00
AgentSeal
c642787113 fix(cline-cli): decline the rollup when per-message calls were all deduped
The rollup fallback was gated on the post-dedup emitted counter, so a session
whose per-message calls were all suppressed by the shared dedup (a duplicated
session directory reusing a session_id) fell through to the metadata.usage
rollup and double-counted its cost. Gate on a hadMetrics flag set before the
dedup check instead.
2026-08-04 01:57:27 +02:00
Resham Joshi
6ad42fa6c7
Merge pull request #891 from therickfactr/feat/cline-cli-sessions-provider
feat(providers): add cline-cli provider for Cline CLI sessions
2026-08-03 16:47:40 -07:00
ozymandiashh
7615e7a8dc
Merge pull request #893 from therickfactr/feat/short-names-clinepass-slugs
models: name GPT-5.6, Grok 4.5 and ClinePass slugs instead of showing raw ids
2026-08-04 02:47:38 +03:00
Rick Culpepper (claude)
448d470049 feat(providers): add cline-cli provider for Cline CLI sessions
The Cline CLI (npm `cline`, 3.x) stores sessions as
<sessions>/<id>/<id>.json + <id>.messages.json. The existing `cline`
provider only discovers tasks/<id>/ui_messages.json, so every CLI session
was silently reported as $0.00 — no warning, not even under --verbose.

Adds `cline-cli` as its own provider rather than a third root on `cline`,
leaving the shared Cline-family parser (Roo Code, KiloCode, IBM Bob)
untouched. It mirrors the CLI's own root resolution
(CLINE_SESSION_DATA_DIR -> CLINE_DATA_DIR -> CLINE_DIR -> ~/.cline),
implements probeRoots() so `doctor` can tell "not installed" from "wrong
override", emits one call per assistant message's `metrics` block, and
falls back to the session rollup when a session carries none. The
fallback reads `usage`, not `aggregateUsage`, which folds in spawned
subagents that are themselves separate session directories.

Two supporting changes, both required for CLI costs to report correctly:

- parser.ts re-priced cline-cli calls from tokens because the provider
  was not on the reported-cost allowlist, inflating a real 12-session
  local sample from $1.11 to $3.92.
- session-cache.ts gains the matching PROVIDER_ENV_VARS entry (so a
  changed override invalidates) and a `reported-cost-v1` parse version
  (so sessions cached before the allowlist fix re-parse once instead of
  being re-priced forever).

Cost is treated as metered only when actually present and non-negative,
so a metered $0 stays reported while a missing or negative cost falls
back to token pricing — applied identically on the per-message and
rollup paths. Timestamps promote a seconds-resolution value rather than
silently landing in 1970, matching the guard kiro.ts uses.

CLINE_DIR / CLINE_DATA_DIR / CLINE_SESSION_DATA_DIR are added to the test
env-isolation list so a developer's real sessions cannot bleed into
fixtures.

The VS Code variant discovery bug reported alongside this in #874 is
deliberately NOT fixed here — it shipped in #882.

Verified against 18 real local sessions: 142 calls, 4,934,762 input /
224,561 output tokens, and a cost matching the CLI's own metered total to
the cent. `codeburn doctor` reports "Cline CLI  OK".

Refs: #874
2026-08-04 02:45:16 +03:00
Rick Culpepper (claude)
572c992aea models: name GPT-5.6, Grok 4.5 and ClinePass slugs instead of showing raw ids
Several model ids price correctly but had no SHORT_NAMES entry, so the
By Model panel rendered the raw slug next to properly named siblings:
`gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `grok-4.5`,
`qwen3.7-max`, `minimax-m3` and `mimo-v2.5-pro`.

All display-only; no dollar amounts move.

Notes on the less obvious ones:

- The GPT-5.6 variants are listed individually rather than as a bare
  `gpt-5.6`. A base entry would swallow every future `gpt-5.6-*` through
  the prefix match and hide the variant behind a sibling's label, which
  is exactly what getShortModelName's version-boundary rule prevents. An
  unlisted variant still falls through to its raw id, and there is a test
  pinning that.
- `grok-4.5` is the model the Grok Build harness runs and reports as
  `current_model_id`, so it takes the model's own name. Ids that really
  are `grok-build*` keep the "Grok Build" label, also covered by a test.
- ClinePass routes models as `cline-pass/<slug>`. No new prefix handling
  was needed: getShortModelName's path fallback already strips the
  prefix and re-resolves the bare slug, the same way it handles
  `accounts/fireworks/models/<slug>`.
- MiniMax M3 is mapped under both the lowercase OpenRouter slug and the
  capitalized spelling sessions report, since SHORT_NAMES matching is
  case-sensitive (the case-insensitive index covers pricing only).

`mimo-v2.5-pro` remains unpriced upstream; this only gives it a name.
2026-08-04 02:45:16 +03:00
ozymandiashh
fe760f0e76
Merge pull request #862 from AVSRPA1KR/feat/defer-report-baselines
feat(act): measure realized savings for defer-* actions in act report
2026-08-04 02:34:44 +03:00
ozymandiashh
db018f755f fix(act): dedup defer baselines against MCP rows, report pending honestly
deferRow now sums only the servers no applied mcp-remove / mcp-project-scope
record already measures, so a defer row and an MCP row can never claim the
same server's schema tokens over the same post-apply sessions and
totalRealizedTokens stays a disjoint sum. Conservative by design: the defer
row drops a claimed server for its whole window, and when every server is
claimed it reports not measurable instead of guessing.

deferredSessions === 0 now reports the new 'pending' status instead of
asserting 'reverted': the note already said the cause was ambiguous, and
--json consumers could not tell a not-yet-restarted client from a genuine
revert. The table renders it as 'not yet in effect'.
2026-08-04 02:22:47 +03:00
ozymandiashh
f2b59f0eb8 fix(menubar): apply --project/--exclude to the provider list on carried days
The provider list rebuilt its own day set straight from the daily cache,
unioning unfiltered historical days with an already-filtered today. Per-provider
costs therefore counted every carried day whole while today honoured the name
filters, so the list could not be reconciled with the headline or the By Project
panel. #864 fixed the headline and left this deliberately untouched.

Reuse durable.days, which is the same union the headline is built from, already
narrowed by range, day selection and project filter. That is what the comment
above the buildDurablePeriod call already promised this section would do.

Providers whose entire spend is excluded do not vanish from the list: the
installed-but-zero backfill below still adds them at cost 0.
2026-08-04 02:09:03 +03:00
AgentSeal
a8a954fd78 fix(models): price codex Kimi rollouts recorded as kimi/k3[1m]
Codex driving a Kimi backend records the model as kimi/k3[1m] (provider prefix
plus a [1m] context tag). getCanonicalName stripped the prefix but not the tag,
so it matched no alias and priced to $0 - Kimi-via-codex spend was silently
reported as free, and the menubar showed no Codex segment. Strip a trailing
[...] context tag so kimi/k3[1m] -> k3 -> kimi-k3, repairing both cost and the
display name.
2026-08-04 00:38:40 +02:00
Resham Joshi
2c69516b02
Merge pull request #882 from ozymandiashh/fix/874-cline-vscode-variants
fix(cline): scan all VS Code variants for task storage
2026-08-03 15:33:23 -07:00
Resham Joshi
b42baa7a93
Merge pull request #885 from getagentseal/harden/codex-parse-field-guards
fix(codex): guard non-string timestamp and model on the parse path
2026-08-03 15:16:51 -07:00
Resham Joshi
2ae4cbc2c2
Merge pull request #884 from getagentseal/harden/menubar-download-retry
fix(menubar): retry mid-stream download drops and harden the retry budget
2026-08-03 15:16:27 -07:00
AgentSeal
4ff3497eb8 fix(codex): guard non-string timestamp and model on the parse path
Follow-up to #881. Structural discovery admits third-party rollouts whose
schema is unverified. Two unchecked JSON.parse fields still reached string ops
on the parse path: an unparseable timestamp threw RangeError out of the
fork-cutoff Date math, and a non-string model threw TypeError from calculateCost
(.replace). Either sank that session's usage to zero. Skip the fork cutoff for
an unparseable timestamp, and only adopt a string model (falling back to a real
model otherwise) so the session is counted instead of silently reading zero.
2026-08-04 00:14:28 +02:00
AgentSeal
c6c069ad92 fix(menubar): retry mid-stream download drops and harden the retry budget
Follow-up to #880. Make fetchReleaseAsset generic over a consume callback
that runs inside the retry loop, so a socket dropped mid-download is retried
and its partial file removed rather than aborting the install and leaving a
truncated zip. Clamp a non-finite attempt budget, drain non-ok bodies, and
carry the original error as cause. The checksum comparison stays outside the
retry, so an integrity mismatch still aborts immediately and never re-downloads.
2026-08-04 00:09:04 +02:00
Resham Joshi
733003df35
Merge pull request #881 from ozymandiashh/fix/873-codex-originator-structural
fix(codex): validate rollouts structurally instead of by originator
2026-08-03 15:08:00 -07:00
Resham Joshi
fd4ede2bb3
Merge pull request #880 from ozymandiashh/fix/876-menubar-download-retry
Some checks are pending
CI / semgrep (push) Waiting to run
fix(menubar): retry transient release-asset download failures
2026-08-03 14:26:03 -07:00