claude-discover 1.10.11 → 1.10.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,7 +34,7 @@ claude-discover
34
34
  Your Claude sessions laid out on a daily, weekly, or monthly timeline. One glance tells you where your tokens went; the second finds the session that quietly spawned 100+ agents.
35
35
 
36
36
  - **Sessions list**\
37
- Filter and sort every session in the selected period. Warning badges flag the expensive habits: oversized context, extended 1h cache, fast mode, marathon sessions - and more to come.
37
+ Filter and sort every session in the selected period. Warning badges flag the expensive habits: oversized context, a cache TTL (5m or 1h) that would have cost less, fast mode, marathon sessions - and more to come.
38
38
 
39
39
  - **Session preview**
40
40
  - **Conversation view**\
package/bin/proxy.mjs CHANGED
@@ -192,10 +192,11 @@ export function dedupeRequest(body, seen = new Set()) {
192
192
  // Inside a newly-seen value, array elements (content blocks, tool schemas, …) are deduped
193
193
  // individually too, at any depth — one injected/updated element (e.g. a system-reminder)
194
194
  // must not re-log its siblings. Primitive elements stay inline: a $ref would outweigh them.
195
- const deep = v =>
196
- Array.isArray(v) ? v.map(el => el && typeof el === 'object' ? dedupe(el) : el)
197
- : v && typeof v === 'object' ? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, deep(x)]))
198
- : v
195
+ const deep = v => {
196
+ return Array.isArray(v) ? v.map(el => el && typeof el === 'object' ? dedupe(el) : el)
197
+ : v && typeof v === 'object' ? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, deep(x)]))
198
+ : v
199
+ }
199
200
  const out = { ...body }
200
201
  if (out.system != null) out.system = dedupe(out.system)
201
202
  if (out.tools != null) out.tools = dedupe(out.tools)
package/out/main/main.js CHANGED
@@ -1505,6 +1505,41 @@ var pickParts = (byModel, part) => Object.fromEntries(Object.entries(byModel).ma
1505
1505
  function addUsage(target, delta) {
1506
1506
  for (const k of TOKEN_FIELDS) target[k] += delta[k];
1507
1507
  }
1508
+ var CACHE_TTL_MS = {
1509
+ "5m": 3e5,
1510
+ "1h": 36e5
1511
+ };
1512
+ var writeTtl = (u) => u.cacheCreation1h ? CACHE_TTL_MS["1h"] : u.cacheCreation ? CACHE_TTL_MS["5m"] : null;
1513
+ function promptCosts(calls, pricing) {
1514
+ const costs = {
1515
+ "5m": 0,
1516
+ "1h": 0
1517
+ };
1518
+ const prevByModel = /* @__PURE__ */ new Map();
1519
+ let ttl = writeTtl(calls.find((c) => c.usage.cacheCreation)?.usage ?? {}) ?? CACHE_TTL_MS["5m"];
1520
+ for (const { ts, model, fast, usage: u } of calls) {
1521
+ const price = (bucket) => pricing.costForDelta(model, bucket, { fast }) || 0;
1522
+ const prefix = u.cacheRead + u.cacheCreation;
1523
+ const prev = prevByModel.get(model);
1524
+ const gap = prev ? ts - prev.ts : Infinity;
1525
+ for (const [policy, ms] of Object.entries(CACHE_TTL_MS)) {
1526
+ const warm = gap <= ms;
1527
+ const read = warm === gap <= ttl ? u.cacheRead : !warm ? 0 : prefix >= prev.prefix ? Math.max(u.cacheRead, prev.prefix) : u.cacheRead;
1528
+ costs[policy] += price({
1529
+ input: u.input,
1530
+ cacheRead: read,
1531
+ cacheCreation: prefix - read,
1532
+ [`cacheCreation${policy}`]: prefix - read
1533
+ });
1534
+ }
1535
+ ttl = writeTtl(u) ?? ttl;
1536
+ prevByModel.set(model, {
1537
+ ts,
1538
+ prefix
1539
+ });
1540
+ }
1541
+ return costs;
1542
+ }
1508
1543
  function extractText(content) {
1509
1544
  if (typeof content === "string") return content;
1510
1545
  if (!Array.isArray(content)) return "";
@@ -1601,6 +1636,7 @@ var SessionParser = class {
1601
1636
  this.seenUuids = /* @__PURE__ */ new Set();
1602
1637
  this.typedCommands = /* @__PURE__ */ new Map();
1603
1638
  this.appliedById = /* @__PURE__ */ new Map();
1639
+ this.calls = [];
1604
1640
  this.branchStarted = false;
1605
1641
  }
1606
1642
  feed(obj) {
@@ -1686,6 +1722,7 @@ var SessionParser = class {
1686
1722
  Object.assign(this.meta, freshMetrics());
1687
1723
  this.lastSeenTs = null;
1688
1724
  this.appliedById.clear();
1725
+ this.calls = [];
1689
1726
  }
1690
1727
  _feedUser(obj) {
1691
1728
  const meta = this.meta;
@@ -1743,6 +1780,13 @@ var SessionParser = class {
1743
1780
  if (this.excludeIds?.has(msgId)) return;
1744
1781
  const applied = this.appliedById.get(msgId);
1745
1782
  if (!applied) {
1783
+ const sentAt = this.prevMessage?.type === "user" ? Math.min(this.prevMessage._ts, obj._ts) : obj._ts;
1784
+ this.calls.push({
1785
+ ts: sentAt,
1786
+ model,
1787
+ fast,
1788
+ usage
1789
+ });
1746
1790
  meta.lastContextTokens = contextSize;
1747
1791
  if (u.service_tier) meta.serviceTier = u.service_tier;
1748
1792
  if (this.pricing && this.pricing.priceFor(model) == null) meta.priceUnknown = true;
@@ -1795,7 +1839,8 @@ var SessionParser = class {
1795
1839
  }) || 0);
1796
1840
  meta.cost = costOf({});
1797
1841
  meta.costByType = Object.fromEntries(Object.entries(COST_PARTS).map(([type, part]) => [type, costOf({}, part)]));
1798
- meta.savings = { using5mCache: meta.cost - costOf({ ignoreCache1hPremium: true }) };
1842
+ const prompt = this.pricing ? promptCosts(this.calls, this.pricing) : null;
1843
+ meta.cacheCosts = prompt && Object.fromEntries(Object.entries(prompt).map(([p, c]) => [p, meta.costByType.output + c]));
1799
1844
  return meta;
1800
1845
  }
1801
1846
  };
@@ -2342,11 +2387,11 @@ var Pricing = class extends EventEmitter {
2342
2387
  fastMultiplier(model) {
2343
2388
  return this.priceFor(model)?.fastModeMplr ?? null;
2344
2389
  }
2345
- costForDelta(model, bucket, { ignoreCache1hPremium = false, fast = false } = {}) {
2390
+ costForDelta(model, bucket, { fast = false } = {}) {
2346
2391
  const p = this.priceFor(model);
2347
2392
  if (!p || !bucket) return null;
2348
- const tokens5m = ignoreCache1hPremium ? 0 : bucket.cacheCreation5m || 0;
2349
- const tokens1h = ignoreCache1hPremium ? 0 : bucket.cacheCreation1h || 0;
2393
+ const tokens5m = bucket.cacheCreation5m || 0;
2394
+ const tokens1h = bucket.cacheCreation1h || 0;
2350
2395
  const tokensUnknown = (bucket.cacheCreation || 0) - tokens5m - tokens1h;
2351
2396
  const base = ((bucket.input || 0) * p.input + (bucket.output || 0) * p.output + (bucket.cacheRead || 0) * p.cacheRead + tokens5m * p.cacheWrite + tokens1h * (p.cacheWrite1h ?? p.cacheWrite) + tokensUnknown * p.cacheWrite) / MILLION;
2352
2397
  return fast ? base * (this.fastMultiplier(model) ?? 1) : base;
@@ -13675,7 +13720,7 @@ var MainWindow = class {
13675
13720
  // src/main/updater.js
13676
13721
  var updater = new NpmUpdater({
13677
13722
  name: "claude-discover",
13678
- version: "1.10.11",
13723
+ version: "1.10.12",
13679
13724
  bin: { "claude-discover": "bin/claude-discover.mjs" }
13680
13725
  }, { dev: false });
13681
13726
  // src/main/Application.js