@cookielab.io/oopst 0.6.0 → 0.6.2

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/dist/index.js CHANGED
@@ -266,7 +266,10 @@ import { fileURLToPath } from "url";
266
266
  import { NodeFileSystem, NodeServices } from "@effect/platform-node";
267
267
  import { Context, Effect as Effect2, FileSystem as FileSystem2, Layer, Stream } from "effect";
268
268
  import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
269
- var PACKAGE_JSON_PATH = fileURLToPath(new URL("../../package.json", import.meta.url));
269
+ var PACKAGE_JSON_PATHS = [
270
+ fileURLToPath(new URL("../package.json", import.meta.url)),
271
+ fileURLToPath(new URL("../../package.json", import.meta.url))
272
+ ];
270
273
  var CliConsole = class extends Context.Service()("@oopst/cli/CliConsole") {
271
274
  };
272
275
  var CliProcess = class extends Context.Service()("@oopst/cli/CliProcess") {
@@ -306,7 +309,7 @@ function parsePackageMetadata(raw) {
306
309
  }
307
310
  var readPackageMetadata = Effect2.fn("CliPackageMetadata.readPackageMetadata")(function* () {
308
311
  const fs = yield* FileSystem2.FileSystem;
309
- const raw = yield* fs.readFileString(PACKAGE_JSON_PATH, "utf8");
312
+ const raw = yield* Effect2.firstSuccessOf(PACKAGE_JSON_PATHS.map((path) => fs.readFileString(path, "utf8")));
310
313
  return parsePackageMetadata(raw);
311
314
  });
312
315
  function makeCliConsole(options) {
@@ -2516,7 +2519,7 @@ function isObject(value) {
2516
2519
  function isFiniteNumber(value) {
2517
2520
  return typeof value === "number" && Number.isFinite(value);
2518
2521
  }
2519
- function isCodexUsageDelta(value) {
2522
+ function isCodexUsageCounters(value) {
2520
2523
  if (!isObject(value)) {
2521
2524
  return false;
2522
2525
  }
@@ -2554,10 +2557,10 @@ function isCodexTokenCountEvent(value) {
2554
2557
  if (info["model"] !== void 0 && typeof info["model"] !== "string") {
2555
2558
  return false;
2556
2559
  }
2557
- if (info["last_token_usage"] !== void 0 && !isCodexUsageDelta(info["last_token_usage"])) {
2560
+ if (info["last_token_usage"] !== void 0 && !isCodexUsageCounters(info["last_token_usage"])) {
2558
2561
  return false;
2559
2562
  }
2560
- if (info["total_token_usage"] !== void 0 && !isCodexUsageDelta(info["total_token_usage"])) {
2563
+ if (info["total_token_usage"] !== void 0 && !isCodexUsageCounters(info["total_token_usage"])) {
2561
2564
  return false;
2562
2565
  }
2563
2566
  }
@@ -2619,8 +2622,11 @@ function isCodexSessionMetaEvent(value) {
2619
2622
  }
2620
2623
  return true;
2621
2624
  }
2622
- function pickCodexDelta(event) {
2623
- return event.payload.info?.last_token_usage ?? event.payload.info?.total_token_usage;
2625
+ function extractCodexUsageSnapshot(event) {
2626
+ return {
2627
+ last: event.payload.info?.last_token_usage,
2628
+ total: event.payload.info?.total_token_usage
2629
+ };
2624
2630
  }
2625
2631
  function pickCodexEventModel(event) {
2626
2632
  return event.payload.info?.model ?? event.payload.model ?? event.model;
@@ -2643,6 +2649,8 @@ function makeCodexFileAccumulator() {
2643
2649
  excluded: false,
2644
2650
  lineNo: 0,
2645
2651
  sawTurnContext: false,
2652
+ previousTotalUsage: void 0,
2653
+ pendingUsage: [],
2646
2654
  sessionLastSeenAt: void 0,
2647
2655
  sessionStartedAt: void 0
2648
2656
  };
@@ -2691,10 +2699,47 @@ function lineStreamFromFile(path) {
2691
2699
  )
2692
2700
  );
2693
2701
  }
2702
+ function normalizeUsage(usage) {
2703
+ return {
2704
+ inputTokens: Math.max(0, usage.input_tokens ?? 0),
2705
+ outputTokens: Math.max(0, usage.output_tokens ?? 0),
2706
+ cacheReadTokens: Math.max(0, usage.cached_input_tokens ?? usage.cache_read_input_tokens ?? 0)
2707
+ };
2708
+ }
2709
+ function sameUsage(a, b) {
2710
+ return a.inputTokens === b.inputTokens && a.outputTokens === b.outputTokens && a.cacheReadTokens === b.cacheReadTokens;
2711
+ }
2712
+ function positiveUsage(usage) {
2713
+ return usage.inputTokens > 0 || usage.outputTokens > 0 || usage.cacheReadTokens > 0;
2714
+ }
2715
+ function cumulativeDelta(current, previous) {
2716
+ if (previous === void 0) {
2717
+ return current;
2718
+ }
2719
+ return {
2720
+ inputTokens: current.inputTokens < previous.inputTokens ? current.inputTokens : current.inputTokens - previous.inputTokens,
2721
+ outputTokens: current.outputTokens < previous.outputTokens ? current.outputTokens : current.outputTokens - previous.outputTokens,
2722
+ cacheReadTokens: current.cacheReadTokens < previous.cacheReadTokens ? current.cacheReadTokens : current.cacheReadTokens - previous.cacheReadTokens
2723
+ };
2724
+ }
2725
+ function usageIncrement(acc, last, total) {
2726
+ const normalizedTotal = total === void 0 ? void 0 : normalizeUsage(total);
2727
+ if (normalizedTotal !== void 0) {
2728
+ if (acc.previousTotalUsage !== void 0 && sameUsage(acc.previousTotalUsage, normalizedTotal)) {
2729
+ return void 0;
2730
+ }
2731
+ const increment2 = last === void 0 ? cumulativeDelta(normalizedTotal, acc.previousTotalUsage) : normalizeUsage(last);
2732
+ acc.previousTotalUsage = normalizedTotal;
2733
+ return positiveUsage(increment2) ? increment2 : void 0;
2734
+ }
2735
+ if (last === void 0) {
2736
+ return void 0;
2737
+ }
2738
+ const increment = normalizeUsage(last);
2739
+ return positiveUsage(increment) ? increment : void 0;
2740
+ }
2694
2741
  function addToBucket(acc, hourUtc, model, delta) {
2695
- const inputTokens = Math.max(0, delta.input_tokens ?? 0);
2696
- const outputTokens = Math.max(0, delta.output_tokens ?? 0);
2697
- const cacheReadTokens = Math.max(0, delta.cached_input_tokens ?? delta.cache_read_input_tokens ?? 0);
2742
+ const { inputTokens, outputTokens, cacheReadTokens } = delta;
2698
2743
  if (inputTokens === 0 && outputTokens === 0 && cacheReadTokens === 0) {
2699
2744
  return false;
2700
2745
  }
@@ -2716,6 +2761,14 @@ function addToBucket(acc, hourUtc, model, delta) {
2716
2761
  existing.cacheReadTokens += cacheReadTokens;
2717
2762
  return true;
2718
2763
  }
2764
+ function flushPendingUsage(acc, model) {
2765
+ for (const pending of acc.pendingUsage) {
2766
+ if (addToBucket(acc, startOfUtcHour(pending.eventAt), model, pending.usage)) {
2767
+ markSessionSeen(acc, pending.eventAt);
2768
+ }
2769
+ }
2770
+ acc.pendingUsage = [];
2771
+ }
2719
2772
  function markSessionSeen(acc, eventAt) {
2720
2773
  if (acc.sessionStartedAt === void 0 || eventAt.getTime() < acc.sessionStartedAt.getTime()) {
2721
2774
  acc.sessionStartedAt = eventAt;
@@ -2745,6 +2798,7 @@ function accumulateCodexLine(context, acc, raw) {
2745
2798
  if (shouldExcludePath(parsed.payload.cwd, options.excludePath)) {
2746
2799
  acc.excluded = true;
2747
2800
  acc.buckets.clear();
2801
+ acc.pendingUsage = [];
2748
2802
  }
2749
2803
  return acc;
2750
2804
  }
@@ -2752,12 +2806,14 @@ function accumulateCodexLine(context, acc, raw) {
2752
2806
  if (shouldExcludePath(parsed.payload.cwd, options.excludePath)) {
2753
2807
  acc.excluded = true;
2754
2808
  acc.buckets.clear();
2809
+ acc.pendingUsage = [];
2755
2810
  return acc;
2756
2811
  }
2757
2812
  const model2 = parsed.payload.model ?? parsed.payload.info?.model;
2758
2813
  if (model2 !== void 0) {
2759
2814
  acc.currentModel = model2;
2760
2815
  acc.sawTurnContext = true;
2816
+ flushPendingUsage(acc, model2);
2761
2817
  }
2762
2818
  return acc;
2763
2819
  }
@@ -2768,16 +2824,18 @@ function accumulateCodexLine(context, acc, raw) {
2768
2824
  if (!Number.isFinite(tsMs)) {
2769
2825
  return acc;
2770
2826
  }
2827
+ const snapshot = extractCodexUsageSnapshot(parsed);
2828
+ const delta = usageIncrement(acc, snapshot.last, snapshot.total);
2829
+ if (delta === void 0) {
2830
+ return acc;
2831
+ }
2832
+ const eventAt = new Date(tsMs);
2771
2833
  const eventModel = pickCodexEventModel(parsed);
2772
2834
  const model = acc.sawTurnContext ? acc.currentModel ?? eventModel : eventModel ?? acc.currentModel;
2773
2835
  if (model === void 0) {
2836
+ acc.pendingUsage.push({ eventAt, usage: delta });
2774
2837
  return acc;
2775
2838
  }
2776
- const delta = pickCodexDelta(parsed);
2777
- if (delta === void 0) {
2778
- return acc;
2779
- }
2780
- const eventAt = new Date(tsMs);
2781
2839
  if (addToBucket(acc, startOfUtcHour(eventAt), model, delta)) {
2782
2840
  markSessionSeen(acc, eventAt);
2783
2841
  }