@trazum/cli 1.28.0 → 1.29.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.
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ const VALUE_FLAGS = new Set([
44
44
  'max-growth-usd',
45
45
  'max-cache-loss-usd',
46
46
  'max-day-usd',
47
+ 'max-session-usd',
47
48
  'csv-out',
48
49
  'csv-shape',
49
50
  'what-if',
@@ -258,7 +259,7 @@ const COMMAND_FLAGS = {
258
259
  ],
259
260
  check: ['max-tokens', 'level', 'exact-tokens', 'markdown-out', 'baseline'],
260
261
  baseline: ['model', 'calls', 'output-tokens', 'cache-hit-rate', 'batch', 'exact-tokens', 'out', 'o'],
261
- profile: ['json', 'pricing', 'pricing-live', 'against', 'what-if', 'markdown-out', 'csv-out', 'csv-shape', 'max-usd', 'max-growth-usd', 'max-cache-loss-usd', 'max-day-usd', 'label', 'since', 'until'],
262
+ profile: ['json', 'pricing', 'pricing-live', 'against', 'what-if', 'markdown-out', 'csv-out', 'csv-shape', 'max-usd', 'max-growth-usd', 'max-cache-loss-usd', 'max-day-usd', 'max-session-usd', 'label', 'since', 'until'],
262
263
  route: ['prompt-file', 'cases', 'label', 'concurrency', 'json', 'yes', 'pricing', 'pricing-live'],
263
264
  eval: ['cases', 'level', 'concurrency', 'export', 'out', 'o', 'model'],
264
265
  prune: ['cases', 'concurrency', 'json', 'yes'],
@@ -1730,6 +1731,7 @@ async function commandProfile(args, config, pricing, t) {
1730
1731
  typeof args.flags.get('max-growth-usd') === 'string' ||
1731
1732
  typeof args.flags.get('max-cache-loss-usd') === 'string' ||
1732
1733
  typeof args.flags.get('max-day-usd') === 'string' ||
1734
+ typeof args.flags.get('max-session-usd') === 'string' ||
1733
1735
  config.spend !== undefined;
1734
1736
  if (anyGate) {
1735
1737
  const reasons = [];
@@ -1871,6 +1873,35 @@ async function commandProfile(args, config, pricing, t) {
1871
1873
  }
1872
1874
  }
1873
1875
  }
1876
+ /**
1877
+ * The per-conversation gate — the unit an agent product actually blows
1878
+ * up in. A month's budget and a day's budget both pass while one
1879
+ * conversation loops its way through $400; the single most expensive
1880
+ * conversation is the number a per-conversation policy has to judge,
1881
+ * and the log already carries it.
1882
+ *
1883
+ * The refusals it inherits: a log with **no sessions** fails rather
1884
+ * than passes ("not measured" is not "under budget"), and a
1885
+ * conversation that started before this log is counted only for the
1886
+ * turns recorded here — so a pass is a floor, and the pass message says
1887
+ * so. The session key itself is never printed, here or anywhere.
1888
+ */
1889
+ if (typeof args.flags.get('max-session-usd') === 'string' || config.spend?.maxSessionUsd !== undefined) {
1890
+ const maxSession = typeof args.flags.get('max-session-usd') === 'string'
1891
+ ? numberFlag(args, 'max-session-usd', 0, t)
1892
+ : config.spend.maxSessionUsd;
1893
+ if (report.sessionSpend === null) {
1894
+ console.error(c.red(t.profile.maxSessionNoSessions()));
1895
+ process.exitCode = 1;
1896
+ }
1897
+ else if (report.sessionSpend.maxUsd > maxSession) {
1898
+ console.error(c.red(t.profile.maxSessionFailed(formatUsd(report.sessionSpend.maxUsd), formatUsd(maxSession), n(report.sessionSpend.sessions))));
1899
+ process.exitCode = 1;
1900
+ }
1901
+ else {
1902
+ console.error(c.dim(t.profile.maxSessionOk(formatUsd(report.sessionSpend.maxUsd), formatUsd(maxSession), n(report.sessionSpend.sessions))));
1903
+ }
1904
+ }
1874
1905
  };
1875
1906
  /**
1876
1907
  * The side files the caller asked for. Written on **both** output paths:
@@ -2463,6 +2494,17 @@ async function commandProfile(args, config, pricing, t) {
2463
2494
  console.log(` ${c.yellow('!')} ${c.dim(wrap(t.profile.sessionCostTail((shape.p95Usd / shape.medianUsd).toFixed(0)), 74, ' '))}`);
2464
2495
  }
2465
2496
  }
2497
+ /**
2498
+ * The figure that survives a small log. `sessionCosts` refuses slices too
2499
+ * thin for a percentile, and rightly — but a log of four conversations
2500
+ * still has a most expensive one, and that maximum is a fact at any count.
2501
+ * It is also exactly the number `--max-session-usd` judges, so the report
2502
+ * states it rather than going silent where the gate would speak.
2503
+ */
2504
+ if (report.sessionCosts.length === 0 && report.sessionSpend !== null) {
2505
+ console.log();
2506
+ console.log(` ${c.dim(wrap(t.profile.sessionSpendOnly(n(report.sessionSpend.sessions), formatUsd(report.sessionSpend.maxUsd)), 74, ' '))}`);
2507
+ }
2466
2508
  /**
2467
2509
  * A total that assumed a cache-write rate is a floor, and says so.
2468
2510
  *