@tokz/cli 0.2.15 → 0.2.17

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.
@@ -766,9 +766,6 @@ function parseLine(raw) {
766
766
  obj: o
767
767
  };
768
768
  }
769
- function tokenCountInfo(p) {
770
- return p.type === "event_msg" && p.payload?.type === "token_count" ? asDict(p.payload.info) : void 0;
771
- }
772
769
  function headlessUsage(o) {
773
770
  const usage = rawUsage(asDict(o.usage)) ?? rawUsage(asDict(asDict(o.data)?.usage)) ?? rawUsage(asDict(asDict(o.result)?.usage)) ?? rawUsage(asDict(asDict(o.response)?.usage));
774
771
  if (!usage) return void 0;
@@ -784,6 +781,29 @@ function headlessTimestamp(o, pick) {
784
781
  const fromFields = (f) => f ? pick(f.timestamp) ?? pick(f.created_at) ?? pick(f.createdAt) : void 0;
785
782
  return fromFields(o) ?? fromFields(asDict(o.data)) ?? fromFields(asDict(o.result)) ?? fromFields(asDict(o.response));
786
783
  }
784
+ function detectReplaySecond(content, lines) {
785
+ const head = content.slice(0, 16384);
786
+ if (!head.includes("thread_spawn") && !head.includes("forked_from_id")) return void 0;
787
+ let firstSecond;
788
+ for (const p of lines) {
789
+ if (p.type !== "event_msg" || p.payload?.type !== "token_count") continue;
790
+ const info = p.payload.info;
791
+ if (!info) continue;
792
+ if (!asDict(info.last_token_usage) && !asDict(info.total_token_usage)) continue;
793
+ const ts = p.timestamp;
794
+ if (!ts || typeof ts !== "string" || ts.length < 19) continue;
795
+ const sec = ts.slice(0, 19);
796
+ if (firstSecond === void 0) {
797
+ firstSecond = sec;
798
+ } else {
799
+ if (firstSecond === sec) {
800
+ return sec;
801
+ }
802
+ return void 0;
803
+ }
804
+ }
805
+ return void 0;
806
+ }
787
807
  async function parseCodexRollout(file, seen = /* @__PURE__ */ new Set()) {
788
808
  const stats = { file, usageByModel: {}, toolCalls: {}, toolCostUsd: {}, dailyUsage: {} };
789
809
  const content = await readFile4(file, "utf8").catch(() => "");
@@ -793,6 +813,8 @@ async function parseCodexRollout(file, seen = /* @__PURE__ */ new Set()) {
793
813
  const parsed = parseLine(raw);
794
814
  if (parsed) lines.push(parsed);
795
815
  }
816
+ const replaySecond = detectReplaySecond(content, lines);
817
+ let skipReplay = replaySecond !== void 0;
796
818
  const modelState = { currentIsFallback: false };
797
819
  let prev;
798
820
  let turnTools = [];
@@ -812,7 +834,6 @@ async function parseCodexRollout(file, seen = /* @__PURE__ */ new Set()) {
812
834
  }
813
835
  seen.add(dedupKey);
814
836
  const delta = {
815
- // Codex's input_tokens INCLUDES cached tokens; split them out.
816
837
  inputTokens: Math.max(0, usage.input - cached),
817
838
  cacheReadTokens: cached,
818
839
  cacheCreationTokens: 0,
@@ -862,21 +883,34 @@ async function parseCodexRollout(file, seen = /* @__PURE__ */ new Set()) {
862
883
  }
863
884
  continue;
864
885
  }
865
- const info = tokenCountInfo(parsed);
866
- if (info) {
867
- const totals = rawUsage(info.total_token_usage);
868
- const last = rawUsage(info.last_token_usage);
869
- if (!last && !totals) continue;
870
- const usage2 = last ?? subtractUsage(totals, prev);
871
- if (totals) prev = totals;
872
- if (usage2.input === 0 && usage2.cached === 0 && usage2.output === 0 && usage2.reasoning === 0) {
886
+ if (type === "event_msg" && payload2?.type === "token_count") {
887
+ const info = asDict(payload2.info);
888
+ if (replaySecond !== void 0 && skipReplay) {
889
+ const ts = timestamp ?? parsed.obj.timestamp;
890
+ const matchesReplay = typeof ts === "string" && ts.length >= 19 && ts.slice(0, 19) === replaySecond;
891
+ if (matchesReplay) {
892
+ const totals = rawUsage(info?.total_token_usage);
893
+ if (totals) prev = totals;
894
+ turnTools = [];
895
+ continue;
896
+ }
897
+ skipReplay = false;
898
+ }
899
+ if (info) {
900
+ const totals = rawUsage(info.total_token_usage);
901
+ const last = rawUsage(info.last_token_usage);
902
+ if (!last && !totals) continue;
903
+ const usage2 = last ?? subtractUsage(totals, prev);
904
+ if (totals) prev = totals;
905
+ if (usage2.input === 0 && usage2.cached === 0 && usage2.output === 0 && usage2.reasoning === 0) {
906
+ continue;
907
+ }
908
+ const ts = nonEmpty(timestamp) ?? normalizeTimestamp(parsed.obj.timestamp);
909
+ const parsedModel = modelFromParts(payload2) ?? modelFromParts(info);
910
+ const model2 = resolveModel(parsedModel, ts ?? "", modelState);
911
+ accumulate(usage2, model2, ts);
873
912
  continue;
874
913
  }
875
- const ts = nonEmpty(timestamp) ?? normalizeTimestamp(parsed.obj.timestamp);
876
- const parsedModel = modelFromParts(payload2) ?? modelFromParts(info);
877
- const model2 = resolveModel(parsedModel, ts ?? "", modelState);
878
- accumulate(usage2, model2, ts);
879
- continue;
880
914
  }
881
915
  if (type === "event_msg" || payload2?.type === "turn_context") continue;
882
916
  const usage = headlessUsage(parsed.obj);
package/dist/cli.js CHANGED
@@ -276,7 +276,7 @@ program.action(async () => {
276
276
  const [{ render }, React, { Root }, { Fullscreen }] = await Promise.all([
277
277
  import("ink"),
278
278
  import("react"),
279
- import("./Root-ZXWUSTBH.js"),
279
+ import("./Root-K4HFMFGA.js"),
280
280
  import("./Fullscreen-GK2ZYXHV.js")
281
281
  ]);
282
282
  render(React.createElement(Fullscreen, null, React.createElement(Root)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokz/cli",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
4
4
  "description": "See where your coding agents' tokens and dollars actually go.",
5
5
  "keywords": [
6
6
  "claude",