ccc-notifier 0.7.0 → 0.8.0

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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  formatJPY,
4
4
  formatUSD
5
- } from "./chunk-XG73C6CC.js";
5
+ } from "./chunk-XOGYLFX3.js";
6
6
  import {
7
7
  currentMonthTotals,
8
8
  paths,
@@ -12,7 +12,7 @@ import {
12
12
  setCountedCalls,
13
13
  splitIntoCodexTurnDrafts,
14
14
  surfaceForClaudePath
15
- } from "./chunk-OCKZZVOG.js";
15
+ } from "./chunk-GAOGTALW.js";
16
16
  import {
17
17
  codexHome,
18
18
  computeCost,
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-Q45AAPJY.js";
21
21
  import {
22
22
  writeDashboardHtml
23
- } from "./chunk-O2E4VTDR.js";
23
+ } from "./chunk-DSTGXYSY.js";
24
24
  import {
25
25
  invalidateCanonicalDashboards,
26
26
  makeFullDashboardState,
@@ -33,7 +33,7 @@ import {
33
33
  formatJPY,
34
34
  formatUSD,
35
35
  modelDisplayName
36
- } from "./chunk-XG73C6CC.js";
36
+ } from "./chunk-XOGYLFX3.js";
37
37
  import {
38
38
  appendTurn,
39
39
  loadCursor,
@@ -590,6 +590,41 @@ function codexDraftToRecord(draft, ts, table, fx) {
590
590
  setCountedCalls(rec, draft.agg.codexEventKeys ?? []);
591
591
  return rec;
592
592
  }
593
+ function codexChildDraftToRecord(draft, ts, table, fx, ingest) {
594
+ const main = draft.agg.main;
595
+ const breakdown = computeCost(main, {}, table);
596
+ const rec = {
597
+ schemaVersion: 1,
598
+ ts,
599
+ sessionId: draft.agg.sessionId,
600
+ project: draft.agg.cwd ?? "",
601
+ gitBranch: null,
602
+ models: collectModels(main, {}),
603
+ tokens: emptyBuckets2(),
604
+ sidechainTokens: null,
605
+ apiCalls: 0,
606
+ costUSD: 0,
607
+ costByModel: {},
608
+ costJPY: 0,
609
+ fxRate: fx.rate,
610
+ fxSource: fx.source,
611
+ prompt: "",
612
+ ingest,
613
+ source: "codex",
614
+ surface: normalizeCodexOriginator(draft.agg.originator),
615
+ subagents: {
616
+ costUSD: breakdown.usd,
617
+ costByModel: { ...breakdown.byModel },
618
+ tokens: sumBuckets(main),
619
+ apiCalls: draft.agg.apiCalls,
620
+ agentFiles: 1
621
+ }
622
+ };
623
+ if (typeof draft.agg.originator === "string") rec.originator = draft.agg.originator;
624
+ if (breakdown.unknownModels.length > 0) rec.unknownModels = breakdown.unknownModels;
625
+ setCountedCalls(rec, draft.agg.codexEventKeys ?? []);
626
+ return rec;
627
+ }
593
628
  async function processCodexRolloutLocked(rolloutPath, table, fx, daysCutoff, dryRun, summary, opts = {}) {
594
629
  if (opts.strictRead) {
595
630
  const file = await fsp.open(rolloutPath, "r");
@@ -598,21 +633,27 @@ async function processCodexRolloutLocked(rolloutPath, table, fx, daysCutoff, dry
598
633
  const cursor = opts.ignoreCursors ? null : sanitizeCursor(loadCursor(rolloutPath));
599
634
  const drafts = await splitIntoCodexTurnDrafts(rolloutPath, cursor);
600
635
  if (drafts === null || drafts.length === 0) return;
601
- if (drafts[0].isSubagentRollout) return;
636
+ const isChild = drafts[0].isSubagentRollout;
637
+ const isForkedChild = isChild && drafts[0].isForkedRollout;
602
638
  const records = [];
603
- for (const draft of drafts) {
604
- const ts = draft.endTs ?? (/* @__PURE__ */ new Date()).toISOString();
605
- if (daysCutoff !== null) {
606
- const tsMs = Date.parse(ts);
607
- if (!Number.isFinite(tsMs) || tsMs < daysCutoff) continue;
639
+ if (!isForkedChild) {
640
+ for (const draft of drafts) {
641
+ const ts = draft.endTs ?? (/* @__PURE__ */ new Date()).toISOString();
642
+ if (daysCutoff !== null) {
643
+ const tsMs = Date.parse(ts);
644
+ if (!Number.isFinite(tsMs) || tsMs < daysCutoff) continue;
645
+ }
646
+ records.push(
647
+ isChild ? codexChildDraftToRecord(draft, ts, table, fx, "sweep") : codexDraftToRecord(draft, ts, table, fx)
648
+ );
608
649
  }
609
- records.push(codexDraftToRecord(draft, ts, table, fx));
610
650
  }
611
651
  for (const rec of records) {
612
652
  summary.newRecords += 1;
613
653
  summary.totalUSD += rec.costUSD;
614
654
  summary.codexRecords += 1;
615
655
  summary.codexUSD += rec.costUSD;
656
+ summary.subagentsUSD += rec.subagents?.costUSD ?? 0;
616
657
  if (rec.costByModel) {
617
658
  for (const [m, c] of Object.entries(rec.costByModel)) {
618
659
  summary.byModel[m] = (summary.byModel[m] ?? 0) + c;
@@ -953,5 +994,6 @@ export {
953
994
  collectSubagentUsage,
954
995
  splitIntoTurnDrafts,
955
996
  attachSubagentGroups,
997
+ codexChildDraftToRecord,
956
998
  runSweep
957
999
  };
@@ -18,7 +18,7 @@ import {
18
18
  formatTokens,
19
19
  formatUSD,
20
20
  modelDisplayName
21
- } from "./chunk-XG73C6CC.js";
21
+ } from "./chunk-XOGYLFX3.js";
22
22
  import {
23
23
  paths,
24
24
  readConfig,
@@ -225,7 +225,7 @@ function buildTurnEmbed(rec, map) {
225
225
  const primary = rec.models[0] ?? "unknown";
226
226
  const extra = rec.models.length > 1 ? ` +${rec.models.length - 1}` : "";
227
227
  const saMark = rec.subagents ? " +SA" : "";
228
- const codexActivityMark = rec.source === "codex" && rec.subagentActivity ? " +SA(\u672A\u96C6\u8A08)" : "";
228
+ const codexActivityMark = rec.source === "codex" && rec.subagentActivity ? " +SA(\u691C\u51FA)" : "";
229
229
  let sa = null;
230
230
  if (rec.subagents) {
231
231
  const saModels = Object.keys(rec.subagents.costByModel).map((m) => modelDisplayName(m));
@@ -235,6 +235,12 @@ function buildTurnEmbed(rec, map) {
235
235
  models: saModels.join(", "),
236
236
  apiCalls: rec.subagents.apiCalls
237
237
  };
238
+ const b = rec.subagents.tokens;
239
+ const cache = b.cacheRead + b.cacheWrite5m + b.cacheWrite1h;
240
+ const total = b.input + b.output + cache;
241
+ if (total > 0) {
242
+ sa.tok = `\u8A08 ${formatTokens(total)} tokens(cache ${Math.round(cache / total * 100)}%)`;
243
+ }
238
244
  }
239
245
  const ms = Date.parse(rec.ts);
240
246
  const out = {
@@ -974,12 +980,12 @@ var APP_JS = `<script>
974
980
  dtd.appendChild(meta);
975
981
  if(t.sa){
976
982
  var saLine = document.createElement('div'); saLine.className = 'detail-meta';
977
- saLine.textContent = '\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8: ' + (t.sa.usd||'') + '(' + (t.sa.jpy||'') + ')\xB7 ' + (t.sa.models||'') + ' \xB7 API\u30B3\u30FC\u30EB ' + (t.sa.apiCalls||0);
983
+ saLine.textContent = '\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8: ' + (t.sa.usd||'') + '(' + (t.sa.jpy||'') + ')\xB7 ' + (t.sa.models||'') + ' \xB7 API\u30B3\u30FC\u30EB ' + (t.sa.apiCalls||0) + (t.sa.tok ? ' \xB7 ' + t.sa.tok : '');
978
984
  dtd.appendChild(saLine);
979
985
  }
980
986
  if(t.ca){
981
987
  var caLine = document.createElement('div'); caLine.className = 'detail-meta';
982
- caLine.textContent = 'Codex\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8: \u5229\u7528\u3042\u308A\u30FB\u6599\u91D1\u672A\u96C6\u8A08 \xB7 \u958B\u59CB ' +
988
+ caLine.textContent = 'Codex\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8: \u5229\u7528\u3042\u308A(\u6599\u91D1\u306F\u3053\u306E\u30BF\u30FC\u30F3\u306B\u542B\u3081\u306A\u3044)\xB7 \u958B\u59CB ' +
983
989
  (t.ca.started||0) + ' \xB7 \u7D42\u4E86 ' + (t.ca.stopped||0) + ' \xB7 \u7A2E\u5225 ' + ((t.ca.agentTypes||[]).join(', ')||'unknown');
984
990
  dtd.appendChild(caLine);
985
991
  }
@@ -356,7 +356,8 @@ function readSessionMetaSeed(buffer) {
356
356
  sessionId: strOrNull(payload.id) ?? strOrNull(payload.session_id),
357
357
  cwd: strOrNull(payload.cwd),
358
358
  originator: strOrNull(payload.originator),
359
- isSubagentRollout: isRecord(source) && Object.hasOwn(source, "subagent")
359
+ isSubagentRollout: isRecord(source) && Object.hasOwn(source, "subagent"),
360
+ isForkedRollout: strOrNull(payload.forked_from_id) !== null
360
361
  };
361
362
  }
362
363
  function newSegmentBuf() {
@@ -395,6 +396,7 @@ async function scanWindow(rolloutPath, cursor, opts = {}) {
395
396
  let sessionMetaCwd = null;
396
397
  let sessionMetaSid = null;
397
398
  let isSubagentRollout = false;
399
+ let isForkedRollout = false;
398
400
  let originator = cursor?.codexOriginator ?? null;
399
401
  if (startOffset > 0) {
400
402
  const seed = readSessionMetaSeed(buffer);
@@ -403,6 +405,7 @@ async function scanWindow(rolloutPath, cursor, opts = {}) {
403
405
  sessionMetaCwd = seed.cwd;
404
406
  if (seed.originator !== null) originator = seed.originator;
405
407
  isSubagentRollout = seed.isSubagentRollout;
408
+ isForkedRollout = seed.isForkedRollout;
406
409
  }
407
410
  }
408
411
  let firstTs = null;
@@ -454,6 +457,7 @@ async function scanWindow(rolloutPath, cursor, opts = {}) {
454
457
  if (c !== null) sessionMetaCwd = c;
455
458
  const source = payload.source;
456
459
  if (isRecord(source) && Object.hasOwn(source, "subagent")) isSubagentRollout = true;
460
+ if (strOrNull(payload.forked_from_id) !== null) isForkedRollout = true;
457
461
  const orig = strOrNull(payload.originator);
458
462
  if (orig !== null) originator = orig;
459
463
  return;
@@ -532,6 +536,7 @@ async function scanWindow(rolloutPath, cursor, opts = {}) {
532
536
  sessionId: rolloutId(),
533
537
  eventKeys: windowEventKeys,
534
538
  isSubagentRollout,
539
+ isForkedRollout,
535
540
  originator,
536
541
  firstTs,
537
542
  lastTs,
@@ -569,6 +574,7 @@ async function aggregateCodexTurn(rolloutPath, cursor, opts = {}) {
569
574
  newCursor: windowCursor(scan),
570
575
  originator: scan.originator,
571
576
  isSubagentRollout: scan.isSubagentRollout,
577
+ isForkedRollout: scan.isForkedRollout,
572
578
  codexEventKeys: scan.eventKeys
573
579
  };
574
580
  }
@@ -640,6 +646,7 @@ function draftsFromScan(scan) {
640
646
  const lastIndex = picked.length - 1;
641
647
  return picked.map((s, i) => ({
642
648
  isSubagentRollout: scan.isSubagentRollout,
649
+ isForkedRollout: scan.isForkedRollout,
643
650
  agg: {
644
651
  sessionId: scan.sessionId,
645
652
  // session_meta はファイル先頭にしか無いので全ドラフト共通
@@ -652,6 +659,7 @@ function draftsFromScan(scan) {
652
659
  originator: scan.originator,
653
660
  // session_meta はファイル先頭にしか無いので全ドラフト共通
654
661
  isSubagentRollout: scan.isSubagentRollout,
662
+ isForkedRollout: scan.isForkedRollout,
655
663
  codexEventKeys: s.eventKeys,
656
664
  firstTs: s.firstTs,
657
665
  lastTs: s.endTs,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  notifyOS,
4
4
  notifySlack
5
- } from "./chunk-JLDI4D5E.js";
5
+ } from "./chunk-TTD3BGOL.js";
6
6
  import {
7
7
  codexHome,
8
8
  detectCodex,
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-DGXUSPS4.js";
5
5
  import {
6
6
  formatSummary
7
- } from "./chunk-XG73C6CC.js";
7
+ } from "./chunk-XOGYLFX3.js";
8
8
 
9
9
  // src/notify/os.ts
10
10
  import { spawn } from "child_process";
@@ -84,7 +84,9 @@ function formatIngestSummary(input, cfg) {
84
84
  const label = cfg.costLabel === "api_equivalent" ? "API\u63DB\u7B97 " : "";
85
85
  const title = `\u{1F4B0} ${label}${formatUSD(input.totalUSD)}(${formatJPY(input.totalJPY)})| hook\u975E\u4F9D\u5B58\u306E\u53D6\u308A\u8FBC\u307F ${input.recordCount}\u4EF6`;
86
86
  const bySurfaceLine = Object.entries(input.bySurface).sort((a, b) => b[1].usd - a[1].usd).map(([surface, v]) => `${surface}: ${v.turns}\u4EF6 ${formatUSD(v.usd)}`).join(" / ");
87
- const body = `${bySurfaceLine}
87
+ const cachePct = input.totalTokens > 0 ? Math.round(input.cacheTokens / input.totalTokens * 100) : 0;
88
+ const tokensPart = input.totalTokens > 0 ? ` \xB7 \u8A08 ${formatTokens(input.totalTokens)} tokens(cache ${cachePct}%)` : "";
89
+ const body = `${bySurfaceLine}${tokensPart}
88
90
  hook \u975E\u4F9D\u5B58\u306E\u5897\u5206\u53D6\u308A\u8FBC\u307F(scan)\u306B\u3088\u308B\u65B0\u898F\u5206\u3067\u3059`;
89
91
  return { title, body };
90
92
  }
@@ -2,13 +2,14 @@
2
2
  import {
3
3
  notifyOS,
4
4
  notifySlack
5
- } from "./chunk-JLDI4D5E.js";
5
+ } from "./chunk-TTD3BGOL.js";
6
6
  import {
7
7
  attachSubagentGroups,
8
+ codexChildDraftToRecord,
8
9
  collectSubagentUsage,
9
10
  normalizeCodexOriginator,
10
11
  splitIntoTurnDrafts
11
- } from "./chunk-6BXD6HU5.js";
12
+ } from "./chunk-C7QOYVGT.js";
12
13
  import {
13
14
  anyOf,
14
15
  callFingerprints,
@@ -20,7 +21,7 @@ import {
20
21
  scanCodexTurns,
21
22
  setCountedCalls,
22
23
  surfaceForClaudePath
23
- } from "./chunk-OCKZZVOG.js";
24
+ } from "./chunk-GAOGTALW.js";
24
25
  import {
25
26
  codexHome,
26
27
  computeCost,
@@ -31,7 +32,7 @@ import {
31
32
  } from "./chunk-PXMXEFM7.js";
32
33
  import {
33
34
  formatIngestSummary
34
- } from "./chunk-XG73C6CC.js";
35
+ } from "./chunk-XOGYLFX3.js";
35
36
  import {
36
37
  appendTurn,
37
38
  floorKey,
@@ -240,17 +241,33 @@ function emptyResult(dryRun, fx, lockAcquired) {
240
241
  failures: 0,
241
242
  totalUSD: 0,
242
243
  totalJPY: 0,
244
+ totalTokens: 0,
245
+ cacheTokens: 0,
243
246
  fxRate: fx.rate,
244
247
  fxSource: fx.source,
245
248
  bySurface: {}
246
249
  };
247
250
  }
251
+ function recordTokenTotals(rec) {
252
+ let total = 0;
253
+ let cache = 0;
254
+ for (const b of [rec.tokens, rec.sidechainTokens, rec.subagents?.tokens]) {
255
+ if (!b) continue;
256
+ const cached = b.cacheRead + b.cacheWrite5m + b.cacheWrite1h;
257
+ total += b.input + b.output + cached;
258
+ cache += cached;
259
+ }
260
+ return { total, cache };
261
+ }
248
262
  function addRecord(result, rec) {
249
263
  const usd = rec.costUSD + (rec.subagents?.costUSD ?? 0);
250
264
  const jpy = rec.costJPY + (rec.subagents?.costUSD ?? 0) * rec.fxRate;
265
+ const tokens = recordTokenTotals(rec);
251
266
  result.records.push(rec);
252
267
  result.totalUSD += usd;
253
268
  result.totalJPY += jpy;
269
+ result.totalTokens += tokens.total;
270
+ result.cacheTokens += tokens.cache;
254
271
  const surface = rec.surface ?? "cli";
255
272
  const cur = result.bySurface[surface] ?? { turns: 0, usd: 0 };
256
273
  cur.turns += 1;
@@ -365,17 +382,18 @@ async function processFiles(claudeFiles, codexFiles, claudeRoots, table, fx, dry
365
382
  return;
366
383
  }
367
384
  const windowCursor = scan.newCursor;
368
- if (drafts[0].isSubagentRollout) {
385
+ if (drafts[0].isSubagentRollout && drafts[0].isForkedRollout) {
369
386
  commit(filePath, [], windowCursor);
370
387
  return;
371
388
  }
389
+ const build = drafts[0].isSubagentRollout ? (draft) => codexChildDraftToRecord(draft, draft.endTs ?? (/* @__PURE__ */ new Date()).toISOString(), table, fx, "scan") : (draft) => buildCodexRecord(draft.agg, table, fx);
372
390
  if (cursor !== null) {
373
- commit(filePath, drafts.map((draft) => buildCodexRecord(draft.agg, table, fx)), windowCursor);
391
+ commit(filePath, drafts.map(build), windowCursor);
374
392
  return;
375
393
  }
376
394
  const floor = recordedFloor("codex", drafts[0].agg.sessionId);
377
395
  const target = floor === null ? drafts : (await scanCodexTurns(filePath, await codexResumePointAtTs(filePath, floor), scanOpts))?.drafts ?? [];
378
- commit(filePath, target.map((draft) => buildCodexRecord(draft.agg, table, fx)), windowCursor);
396
+ commit(filePath, target.map(build), windowCursor);
379
397
  };
380
398
  const runOver = async (files, context, handle, signature = fileMtimeMs) => {
381
399
  for (const filePath of files) {
@@ -423,7 +441,14 @@ async function notifyIngestSummary(result, cfg) {
423
441
  if (v) bySurface[surface] = v;
424
442
  }
425
443
  const summary = formatIngestSummary(
426
- { recordCount: result.records.length, totalUSD: result.totalUSD, totalJPY: result.totalJPY, bySurface },
444
+ {
445
+ recordCount: result.records.length,
446
+ totalUSD: result.totalUSD,
447
+ totalJPY: result.totalJPY,
448
+ totalTokens: result.totalTokens,
449
+ cacheTokens: result.cacheTokens,
450
+ bySurface
451
+ },
427
452
  cfg
428
453
  );
429
454
  const record = {
package/dist/cli.js CHANGED
@@ -7,12 +7,12 @@ import {
7
7
  CODEX_HOOK_TIMEOUT_SECONDS,
8
8
  matchesMarker,
9
9
  parseConfiguredOwnedCodexHookCommand
10
- } from "./chunk-X7U63BZG.js";
10
+ } from "./chunk-RE72XBXB.js";
11
11
  import {
12
12
  notifyOS,
13
13
  notifySlack,
14
14
  selectNotifyBackend
15
- } from "./chunk-JLDI4D5E.js";
15
+ } from "./chunk-TTD3BGOL.js";
16
16
  import {
17
17
  aggregateNewTurn,
18
18
  claudeTranscriptRoots,
@@ -21,7 +21,7 @@ import {
21
21
  listCodexRollouts,
22
22
  rootForClaudePath,
23
23
  splitIntoCodexTurnDrafts
24
- } from "./chunk-OCKZZVOG.js";
24
+ } from "./chunk-GAOGTALW.js";
25
25
  import {
26
26
  codexHome,
27
27
  computeCost,
@@ -39,7 +39,7 @@ import {
39
39
  formatJPY,
40
40
  formatTokens,
41
41
  formatUSD
42
- } from "./chunk-XG73C6CC.js";
42
+ } from "./chunk-XOGYLFX3.js";
43
43
  import {
44
44
  cursorPaths,
45
45
  hasUnresolvedPendingMarker,
@@ -1044,7 +1044,7 @@ function printTable(result, days) {
1044
1044
  if (result.total.codexSubagentActivity) {
1045
1045
  const activity = result.total.codexSubagentActivity;
1046
1046
  console.log(
1047
- `(Codex\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u5229\u7528\u3042\u308A\u30FB\u6599\u91D1\u672A\u96C6\u8A08: ${activity.turns}\u30BF\u30FC\u30F3 / \u958B\u59CB${activity.started}\u30FB\u7D42\u4E86${activity.stopped})`
1047
+ `(Codex\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u5229\u7528\u3042\u308A(\u6599\u91D1\u306F\u89AA\u30BF\u30FC\u30F3\u306B\u542B\u3081\u306A\u3044): ${activity.turns}\u30BF\u30FC\u30F3 / \u958B\u59CB${activity.started}\u30FB\u7D42\u4E86${activity.stopped})`
1048
1048
  );
1049
1049
  }
1050
1050
  console.log("");
@@ -1157,7 +1157,7 @@ function isCodexPassiveEvent(value) {
1157
1157
  async function runCodexPassiveHook(event, text) {
1158
1158
  try {
1159
1159
  if (event === "Stop") {
1160
- const trackMod = await import("./track-P6A5WDJZ.js");
1160
+ const trackMod = await import("./track-TIINM4ZR.js");
1161
1161
  await trackMod.runTrack(text, { codex: true });
1162
1162
  } else if (event === "UserPromptSubmit") {
1163
1163
  const activity = await import("./subagent-store-USG3WJEB.js");
@@ -1242,18 +1242,18 @@ async function main(argv) {
1242
1242
  const text = await readStdin();
1243
1243
  const codex = rest.includes("--codex");
1244
1244
  try {
1245
- const trackMod = await import("./track-P6A5WDJZ.js");
1245
+ const trackMod = await import("./track-TIINM4ZR.js");
1246
1246
  await trackMod.runTrack(text, { codex });
1247
1247
  } catch {
1248
1248
  }
1249
1249
  return 0;
1250
1250
  }
1251
1251
  case "init": {
1252
- const { runInit } = await import("./setup-VLMW433R.js");
1252
+ const { runInit } = await import("./setup-2QDA3OWE.js");
1253
1253
  return await runInit(rest);
1254
1254
  }
1255
1255
  case "uninstall": {
1256
- const { runUninstall } = await import("./setup-VLMW433R.js");
1256
+ const { runUninstall } = await import("./setup-2QDA3OWE.js");
1257
1257
  return await runUninstall(rest);
1258
1258
  }
1259
1259
  case "doctor":
@@ -1261,19 +1261,19 @@ async function main(argv) {
1261
1261
  case "report":
1262
1262
  return await runReport(rest);
1263
1263
  case "dashboard": {
1264
- const { runDashboard } = await import("./dashboard-64XHDUVT.js");
1264
+ const { runDashboard } = await import("./dashboard-YG4H3GLA.js");
1265
1265
  return await runDashboard(rest);
1266
1266
  }
1267
1267
  case "sweep": {
1268
- const { runSweep } = await import("./sweep-DVOV4XIZ.js");
1268
+ const { runSweep } = await import("./sweep-OLI2LIXJ.js");
1269
1269
  return await runSweep(rest);
1270
1270
  }
1271
1271
  case "scan": {
1272
- const { runScan } = await import("./scan-UB6ORRZK.js");
1272
+ const { runScan } = await import("./scan-QB2N2O4Q.js");
1273
1273
  return await runScan(rest);
1274
1274
  }
1275
1275
  case "reset-cursors": {
1276
- const { runResetCursors } = await import("./reset-cursors-5CCM6MQL.js");
1276
+ const { runResetCursors } = await import("./reset-cursors-UVQXFN5Y.js");
1277
1277
  return await runResetCursors(rest);
1278
1278
  }
1279
1279
  case "history": {
@@ -1281,7 +1281,7 @@ async function main(argv) {
1281
1281
  return await runHistory(rest);
1282
1282
  }
1283
1283
  case "budget": {
1284
- const { runBudget } = await import("./budget-O4VAP6RB.js");
1284
+ const { runBudget } = await import("./budget-U37CCG4Y.js");
1285
1285
  return runBudget(rest);
1286
1286
  }
1287
1287
  case "mute": {
@@ -3,12 +3,12 @@ import {
3
3
  browserOpenPlan,
4
4
  runDashboard,
5
5
  writeDashboardHtml
6
- } from "./chunk-O2E4VTDR.js";
6
+ } from "./chunk-DSTGXYSY.js";
7
7
  import "./chunk-3M5UQK76.js";
8
8
  import "./chunk-PXMXEFM7.js";
9
9
  import "./chunk-6IVSZ3S4.js";
10
10
  import "./chunk-DGXUSPS4.js";
11
- import "./chunk-XG73C6CC.js";
11
+ import "./chunk-XOGYLFX3.js";
12
12
  import "./chunk-WONMZ466.js";
13
13
  export {
14
14
  browserOpenPlan,
@@ -34,6 +34,9 @@ async function runResetCursors(argv) {
34
34
  console.log("\u53D6\u308A\u8FBC\u307F\u4F4D\u7F6E(cursors.json)\u3068\u4FDD\u7559\u30DE\u30FC\u30AB\u30FC\u3092\u7834\u68C4\u3057\u307E\u3057\u305F\u3002");
35
35
  console.log("\u5C65\u6B74(history.jsonl)\u30FB\u8A2D\u5B9A\u30FB\u901A\u77E5\u5148\u306F\u305D\u306E\u307E\u307E\u3067\u3059\u3002\u4E8C\u91CD\u8A08\u4E0A\u306F\u5C65\u6B74\u5074\u306E\u6307\u7D0B\u3067\u9632\u304E\u307E\u3059\u3002");
36
36
  console.log("\u6B21\u56DE\u306E\u53D6\u308A\u8FBC\u307F\u306F\u5168 transcript / rollout \u3092\u8AAD\u307F\u76F4\u3059\u305F\u3081\u3001\u4E00\u5EA6\u3060\u3051\u6642\u9593\u304C\u304B\u304B\u308A\u307E\u3059\u3002");
37
+ console.log(
38
+ "\u6CE8\u610F: \u904E\u53BB\u306B\u672A\u8A08\u4E0A\u3060\u3063\u305F\u5206(\u4F8B: \u65E7\u30D0\u30FC\u30B8\u30E7\u30F3\u3067\u8A08\u4E0A\u3057\u3066\u3044\u306A\u304B\u3063\u305F Codex \u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u5206)\u3082\u65B0\u898F\u306B\u53D6\u308A\u8FBC\u307E\u308C\u308B\u305F\u3081\u3001\u5C65\u6B74\u7DCF\u984D\u30FB\u6708\u4E88\u7B97\u306E\u6D88\u5316\u304C\u5897\u3048\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002"
39
+ );
37
40
  return 0;
38
41
  }
39
42
  export {
@@ -2,20 +2,21 @@
2
2
  import {
3
3
  notifyIngestSummary,
4
4
  runIngest
5
- } from "./chunk-V4IS4FXH.js";
6
- import "./chunk-JLDI4D5E.js";
7
- import "./chunk-6BXD6HU5.js";
8
- import "./chunk-OCKZZVOG.js";
5
+ } from "./chunk-YH45W7TA.js";
6
+ import "./chunk-TTD3BGOL.js";
7
+ import "./chunk-C7QOYVGT.js";
8
+ import "./chunk-GAOGTALW.js";
9
9
  import "./chunk-Q45AAPJY.js";
10
- import "./chunk-O2E4VTDR.js";
10
+ import "./chunk-DSTGXYSY.js";
11
11
  import "./chunk-3M5UQK76.js";
12
12
  import "./chunk-PXMXEFM7.js";
13
13
  import "./chunk-6IVSZ3S4.js";
14
14
  import "./chunk-DGXUSPS4.js";
15
15
  import {
16
16
  formatJPY,
17
+ formatTokens,
17
18
  formatUSD
18
- } from "./chunk-XG73C6CC.js";
19
+ } from "./chunk-XOGYLFX3.js";
19
20
  import {
20
21
  readConfig
21
22
  } from "./chunk-WONMZ466.js";
@@ -58,6 +59,8 @@ async function runScan(argv) {
58
59
  failures: result.failures,
59
60
  totalUSD: result.totalUSD,
60
61
  totalJPY: result.totalJPY,
62
+ totalTokens: result.totalTokens,
63
+ cacheTokens: result.cacheTokens,
61
64
  bySurface: result.bySurface
62
65
  },
63
66
  null,
@@ -73,7 +76,11 @@ async function runScan(argv) {
73
76
  if (result.records.length === 0) {
74
77
  console.log("\u65B0\u898F\u53D6\u308A\u8FBC\u307F\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F");
75
78
  } else {
76
- console.log(`\u53D6\u308A\u8FBC\u307F: ${result.records.length} \u30BF\u30FC\u30F3\u3001\u5408\u8A08 ${formatUSD(result.totalUSD)}(${formatJPY(result.totalJPY)})`);
79
+ const cachePct = result.totalTokens > 0 ? Math.round(result.cacheTokens / result.totalTokens * 100) : 0;
80
+ const tokensPart = result.totalTokens > 0 ? `\u3001\u8A08 ${formatTokens(result.totalTokens)} tokens(cache ${cachePct}%)` : "";
81
+ console.log(
82
+ `\u53D6\u308A\u8FBC\u307F: ${result.records.length} \u30BF\u30FC\u30F3\u3001\u5408\u8A08 ${formatUSD(result.totalUSD)}(${formatJPY(result.totalJPY)})${tokensPart}`
83
+ );
77
84
  const bySurface = Object.entries(result.bySurface).sort((a, b) => (b[1]?.usd ?? 0) - (a[1]?.usd ?? 0));
78
85
  for (const [surface, v] of bySurface) {
79
86
  if (!v) continue;
@@ -4,11 +4,11 @@ import {
4
4
  matchesMarker,
5
5
  runInit,
6
6
  runUninstall
7
- } from "./chunk-X7U63BZG.js";
8
- import "./chunk-JLDI4D5E.js";
7
+ } from "./chunk-RE72XBXB.js";
8
+ import "./chunk-TTD3BGOL.js";
9
9
  import "./chunk-Q45AAPJY.js";
10
10
  import "./chunk-DGXUSPS4.js";
11
- import "./chunk-XG73C6CC.js";
11
+ import "./chunk-XOGYLFX3.js";
12
12
  import "./chunk-WONMZ466.js";
13
13
  export {
14
14
  maskWebhookUrl,
@@ -1,20 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  attachSubagentGroups,
4
+ codexChildDraftToRecord,
4
5
  runSweep,
5
6
  splitIntoTurnDrafts
6
- } from "./chunk-6BXD6HU5.js";
7
- import "./chunk-OCKZZVOG.js";
7
+ } from "./chunk-C7QOYVGT.js";
8
+ import "./chunk-GAOGTALW.js";
8
9
  import "./chunk-Q45AAPJY.js";
9
- import "./chunk-O2E4VTDR.js";
10
+ import "./chunk-DSTGXYSY.js";
10
11
  import "./chunk-3M5UQK76.js";
11
12
  import "./chunk-PXMXEFM7.js";
12
13
  import "./chunk-6IVSZ3S4.js";
13
14
  import "./chunk-DGXUSPS4.js";
14
- import "./chunk-XG73C6CC.js";
15
+ import "./chunk-XOGYLFX3.js";
15
16
  import "./chunk-WONMZ466.js";
16
17
  export {
17
18
  attachSubagentGroups,
19
+ codexChildDraftToRecord,
18
20
  runSweep,
19
21
  splitIntoTurnDrafts
20
22
  };
@@ -2,15 +2,15 @@
2
2
  import {
3
3
  notifyIngestSummary,
4
4
  runIngest
5
- } from "./chunk-V4IS4FXH.js";
5
+ } from "./chunk-YH45W7TA.js";
6
6
  import {
7
7
  notifyOS,
8
8
  notifySlack
9
- } from "./chunk-JLDI4D5E.js";
9
+ } from "./chunk-TTD3BGOL.js";
10
10
  import {
11
11
  collectSubagentUsage,
12
12
  normalizeCodexOriginator
13
- } from "./chunk-6BXD6HU5.js";
13
+ } from "./chunk-C7QOYVGT.js";
14
14
  import {
15
15
  aggregateCodexTurn,
16
16
  aggregateNewTurn,
@@ -22,14 +22,14 @@ import {
22
22
  getUsdJpy,
23
23
  messageKeyFilterOf,
24
24
  setCountedCalls
25
- } from "./chunk-OCKZZVOG.js";
25
+ } from "./chunk-GAOGTALW.js";
26
26
  import {
27
27
  computeCost,
28
28
  loadPriceTable
29
29
  } from "./chunk-Q45AAPJY.js";
30
30
  import {
31
31
  writeDashboardHtml
32
- } from "./chunk-O2E4VTDR.js";
32
+ } from "./chunk-DSTGXYSY.js";
33
33
  import {
34
34
  isFullDashboardDue,
35
35
  makeFullDashboardState,
@@ -40,7 +40,7 @@ import {
40
40
  } from "./chunk-PXMXEFM7.js";
41
41
  import "./chunk-6IVSZ3S4.js";
42
42
  import "./chunk-DGXUSPS4.js";
43
- import "./chunk-XG73C6CC.js";
43
+ import "./chunk-XOGYLFX3.js";
44
44
  import {
45
45
  appendTurn,
46
46
  clearPendingAppend,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccc-notifier",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Claude Code Cost notifier (now also covers Codex CLI): per-prompt cost notifications (USD/JPY) with local history and HTML dashboard",
5
5
  "keywords": [
6
6
  "claude",