tines 0.0.205 → 0.0.207

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.
Files changed (2) hide show
  1. package/dist/index.js +99 -31
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5865,7 +5865,7 @@ function withList(cmd) {
5865
5865
  cmd.option(
5866
5866
  "--limit <n>",
5867
5867
  "maximum items to return (page size under --all-pages)",
5868
- (v) => Number.parseInt(v, 10)
5868
+ parsePositiveInteger
5869
5869
  ).option("--cursor <cursor>", "resume from the next_cursor of a previous page").addOption(
5870
5870
  new Option(
5871
5871
  "--all-pages",
@@ -5874,6 +5874,15 @@ function withList(cmd) {
5874
5874
  )
5875
5875
  );
5876
5876
  }
5877
+ function parsePositiveInteger(value) {
5878
+ if (!/^[1-9]\d*$/.test(value)) throw new Error("limit must be a positive integer");
5879
+ const result = Number(value);
5880
+ if (!Number.isSafeInteger(result)) throw new Error("limit must be a positive safe integer");
5881
+ return result;
5882
+ }
5883
+ function isUsageIdentity(value, prefix) {
5884
+ return value === "unknown" || new RegExp(`^${prefix}_[A-Za-z0-9]+$`).test(value);
5885
+ }
5877
5886
  function resolveUrlSetting(opts) {
5878
5887
  if (opts.url) return { value: opts.url, source: "flag" };
5879
5888
  if (process.env.TINES_API_URL) return { value: process.env.TINES_API_URL, source: "env" };
@@ -6271,7 +6280,7 @@ var CHANGE_LABEL = {
6271
6280
  function inspectableChanges(preview) {
6272
6281
  return preview.context.changes;
6273
6282
  }
6274
- var effectiveness = (present, effective) => !present ? "not present" : effective ? "effective" : "overridden candidate";
6283
+ var effectiveness = (present2, effective) => !present2 ? "not present" : effective ? "effective" : "overridden candidate";
6275
6284
  function repoLine(change) {
6276
6285
  if (change.kind !== "repo") return null;
6277
6286
  const before = change.repo_before;
@@ -10961,6 +10970,52 @@ stop it first \u2014 \`tines runners pause ${settings.name}\`, wait for 0 active
10961
10970
  });
10962
10971
  }
10963
10972
 
10973
+ // src/usage-format.ts
10974
+ var present = (value) => value === null || value === void 0 || value === "" ? "unavailable" : String(value);
10975
+ var instant = (value) => {
10976
+ if (typeof value !== "number") return present(value);
10977
+ const parsed = new Date(value);
10978
+ return Number.isFinite(parsed.getTime()) ? parsed.toISOString() : "unavailable";
10979
+ };
10980
+ function basisLine(basis, selection) {
10981
+ if (!basis) return "historical calculated amount \xB7 basis unavailable";
10982
+ const rates = basis.rates && typeof basis.rates === "object" ? basis.rates : {};
10983
+ return [
10984
+ `id ${present(basis.rate_id)}`,
10985
+ `version ${present(basis.rate_version)}`,
10986
+ `model ${present(basis.model)}`,
10987
+ `plan ${present(basis.plan)}`,
10988
+ `context ${present(basis.context_band)}`,
10989
+ `source ${present(basis.source_url)}`,
10990
+ `checked ${present(basis.source_checked_at)}`,
10991
+ `effective ${present(basis.source_effective_at)}`,
10992
+ `adopted ${instant(basis.rate_adopted_at)}`,
10993
+ `valid to ${instant(basis.rate_valid_to)}`,
10994
+ ...selection ? [`selected ${instant(selection.min)} \u2014 ${instant(selection.max)}`] : [`selected ${instant(basis.rate_selected_at)}`],
10995
+ `rates input=${present(rates.input_tokens)} cache-read=${present(rates.cache_read_tokens)} cache-write=${present(rates.cache_write_tokens)} output=${present(rates.output_tokens)} per ${present(basis.unit_tokens)} tokens`
10996
+ ].join(" \xB7 ");
10997
+ }
10998
+ function usageAggregateLines(label, aggregate) {
10999
+ const nonzero = (record) => Object.entries(record).filter(([, count]) => typeof count === "number" && count > 0).map(([name2, count]) => `${name2}=${count}`).join(" \xB7 ") || "none";
11000
+ return [
11001
+ `${label} sources: provider ${aggregate.portions.provider.cost_usd_exact} (${aggregate.portions.provider.priced_run_count}) \xB7 calculated ${aggregate.portions.calculated.cost_usd_exact} (${aggregate.portions.calculated.priced_run_count}) \xB7 unknown ${aggregate.portions.unknown_source.cost_usd_exact} (${aggregate.portions.unknown_source.priced_run_count})`,
11002
+ `${label} diagnostics: ${nonzero(aggregate.diagnostics)}`,
11003
+ `${label} pricing reasons: ${nonzero(aggregate.pricing_reasons)}`,
11004
+ ...aggregate.rate_portions.map(
11005
+ (portion) => `${label} rate (${portion.cost_usd_exact}; ${portion.priced_run_count} runs): ${basisLine(portion.basis, { min: portion.rate_selected_at_min, max: portion.rate_selected_at_max })}`
11006
+ )
11007
+ ];
11008
+ }
11009
+ function usageEvidenceLines(id2, dimensions, accounting) {
11010
+ const dims = ["project", "workflow", "state", "outcome", "runner", "tier"].map((name2) => `${name2}=${dimensions[name2].name} [${dimensions[name2].id ?? "unknown"}]`).join(" \xB7 ");
11011
+ const diagnostics = Object.entries(accounting.diagnostics).filter(([, count]) => count > 0).map(([name2, count]) => `${name2}=${count}`).join(" \xB7 ");
11012
+ return [
11013
+ `Evidence ${id2}: ${dims}`,
11014
+ `Accounting ${id2}: ${accounting.status} \xB7 source ${accounting.source ?? "unavailable"} \xB7 exact cost ${accounting.cost_exact ?? "unavailable"}${accounting.pricing_reason ? ` \xB7 reason ${accounting.pricing_reason}` : ""}${diagnostics ? ` \xB7 diagnostics ${diagnostics}` : ""}`,
11015
+ ...accounting.source === "calculated" ? [`Rate ${id2}: ${basisLine(accounting.basis)}`] : []
11016
+ ];
11017
+ }
11018
+
10964
11019
  // src/commands/runners.ts
10965
11020
  function parseBoolean(value) {
10966
11021
  if (value === "true") return true;
@@ -11326,7 +11381,7 @@ function register8(program3) {
11326
11381
  "finalized",
11327
11382
  "pending"
11328
11383
  ])
11329
- ).option("--from <timestamp>", "inclusive period start").option("--to <timestamp>", "exclusive period cutoff").option("--project <name-or-id>", "project, including archived").option("--workflow <name-or-id>", "workflow").option("--state <id>", "starting state id").option("--tier <tier>", "model tier").addOption(
11384
+ ).option("--from <timestamp>", "inclusive period start").option("--to <timestamp>", "exclusive period cutoff").option("--timezone <iana>", "period display timezone (with --timezone-source)").option("--timezone-source <source>", "supervisor_budget or utc_fallback").option("--project <name-or-id>", "project, including archived").option("--workflow <name-or-id>", "workflow").option("--state <id>", "starting state id").option("--tier <tier>", "model tier").addOption(
11330
11385
  new Option("--outcome <outcome>", "recorded outcome").choices([
11331
11386
  "advanced",
11332
11387
  "stalled",
@@ -11347,10 +11402,14 @@ function register8(program3) {
11347
11402
  die("--from and --to are required together");
11348
11403
  if ((evidence.from || evidence.to) && !evidence.population)
11349
11404
  die("period filters require --population");
11405
+ if (evidence.timezone === void 0 !== (evidence.timezoneSource === void 0))
11406
+ die("--timezone and --timezone-source are required together");
11407
+ if (evidence.population && opts.limit !== void 0 && opts.limit > 100)
11408
+ die("period evidence --limit must be at most 100");
11350
11409
  const issueId = opts.issue ? (await resolveIssue(api, opts.issue)).id : void 0;
11351
- const runnerId = opts.runner ? (await resolveRunner(api, opts.runner)).id : void 0;
11352
- const projectId = evidence.project ? (await resolveProject(api, evidence.project)).id : void 0;
11353
- const workflowId = evidence.workflow ? (await resolveWorkflow(api, evidence.workflow)).id : void 0;
11410
+ const runnerId = opts.runner ? evidence.population && isUsageIdentity(opts.runner, "rnr") ? opts.runner : (await resolveRunner(api, opts.runner)).id : void 0;
11411
+ const projectId = evidence.project ? evidence.population && isUsageIdentity(evidence.project, "prj") ? evidence.project : (await resolveProject(api, evidence.project)).id : void 0;
11412
+ const workflowId = evidence.workflow ? evidence.population && isUsageIdentity(evidence.workflow, "wf") ? evidence.workflow : (await resolveWorkflow(api, evidence.workflow)).id : void 0;
11354
11413
  const res = await fetchList(
11355
11414
  opts,
11356
11415
  (page) => api.listRuns({
@@ -11366,6 +11425,8 @@ function register8(program3) {
11366
11425
  tier: evidence.tier,
11367
11426
  outcome: evidence.outcome,
11368
11427
  accounting_status: evidence.accountingStatus,
11428
+ timezone: evidence.timezone,
11429
+ timezone_source: evidence.timezoneSource,
11369
11430
  ...page
11370
11431
  })
11371
11432
  );
@@ -11390,6 +11451,16 @@ function register8(program3) {
11390
11451
  ["ID", "ISSUE", "RUNNER", "TIER", "STATUS", "DURATION", "COST", "CREATED"],
11391
11452
  ...items.map(runRow)
11392
11453
  ]);
11454
+ if (evidence.population === "finalized") {
11455
+ for (const run2 of items)
11456
+ if (run2.usage_dimensions && run2.usage_accounting)
11457
+ for (const line of usageEvidenceLines(
11458
+ run2.id,
11459
+ run2.usage_dimensions,
11460
+ run2.usage_accounting
11461
+ ))
11462
+ console.log(line);
11463
+ }
11393
11464
  });
11394
11465
  });
11395
11466
  withCommon(
@@ -12692,22 +12763,23 @@ function printReport(report) {
12692
12763
  console.log(
12693
12764
  `Pending at cutoff: ${report.pending.matching_count}${report.pending.unapplied_filters.length ? ` (before ${report.pending.unapplied_filters.join("/")} filters)` : ""}`
12694
12765
  );
12695
- if (report.groups.length === 0) return console.log("no finalized runs");
12696
- table([
12697
- ["GROUP", "SPEND", "COVERAGE", "FINAL", "PRICED", "MISSING", "MEDIAN", "P95", "MAX", "MEAN"],
12698
- ...report.groups.map(({ dimension, aggregate: a }) => [
12699
- dimension.name,
12700
- money(a.cost_usd),
12701
- a.coverage,
12702
- String(a.finalized_run_count),
12703
- String(a.priced_run_count),
12704
- String(a.unpriced_run_count + a.unreported_run_count),
12705
- money(a.distribution.median_cost_usd),
12706
- money(a.distribution.p95_cost_usd),
12707
- money(a.distribution.max_cost_usd),
12708
- money(a.distribution.mean_cost_usd)
12709
- ])
12710
- ]);
12766
+ if (report.groups.length === 0) console.log("no finalized runs");
12767
+ else
12768
+ table([
12769
+ ["GROUP", "SPEND", "COVERAGE", "FINAL", "PRICED", "MISSING", "MEDIAN", "P95", "MAX", "MEAN"],
12770
+ ...report.groups.map(({ dimension, aggregate: a }) => [
12771
+ dimension.name,
12772
+ money(a.cost_usd),
12773
+ a.coverage,
12774
+ String(a.finalized_run_count),
12775
+ String(a.priced_run_count),
12776
+ String(a.unpriced_run_count + a.unreported_run_count),
12777
+ money(a.distribution.median_cost_usd),
12778
+ money(a.distribution.p95_cost_usd),
12779
+ money(a.distribution.max_cost_usd),
12780
+ money(a.distribution.mean_cost_usd)
12781
+ ])
12782
+ ]);
12711
12783
  console.log("Per-run cost \xB7 priced subset; p95 uses nearest rank.");
12712
12784
  if (report.groups.some((g) => g.aggregate.distribution.low_sample))
12713
12785
  console.log("Small samples (under 20): p95 equals maximum.");
@@ -12719,12 +12791,8 @@ function printReport(report) {
12719
12791
  console.log(
12720
12792
  `Matching sources: provider ${total.portions.provider.cost_usd_exact} \xB7 calculated ${total.portions.calculated.cost_usd_exact} \xB7 unknown ${total.portions.unknown_source.cost_usd_exact}`
12721
12793
  );
12722
- for (const portion of total.rate_portions) {
12723
- const basis = portion.basis;
12724
- console.log(
12725
- basis ? `Rate: ${basis.rate_id} v${basis.rate_version} \xB7 ${basis.model} \xB7 ${basis.source_url}` : `Rate: historical calculated amount \xB7 basis unavailable`
12726
- );
12727
- }
12794
+ for (const line of usageAggregateLines("Scope", scope)) console.log(line);
12795
+ for (const line of usageAggregateLines("Matching", total)) console.log(line);
12728
12796
  }
12729
12797
  function register12(program3) {
12730
12798
  withCommon(
@@ -12752,9 +12820,9 @@ function register12(program3) {
12752
12820
  if (opts.window && opts.from) throw new Error("--window cannot be combined with --from/--to");
12753
12821
  if (opts.state && !opts.workflow) throw new Error("--state requires --workflow");
12754
12822
  const api = client(opts);
12755
- const project = opts.project && opts.project !== "unknown" ? (await resolveProject(api, opts.project)).id : opts.project;
12756
- const workflow2 = opts.workflow && opts.workflow !== "unknown" ? (await resolveWorkflow(api, opts.workflow)).id : opts.workflow;
12757
- const runner = opts.runner && opts.runner !== "unknown" ? (await resolveRunner(api, opts.runner)).id : opts.runner;
12823
+ const project = opts.project && !isUsageIdentity(opts.project, "prj") ? (await resolveProject(api, opts.project)).id : opts.project;
12824
+ const workflow2 = opts.workflow && !isUsageIdentity(opts.workflow, "wf") ? (await resolveWorkflow(api, opts.workflow)).id : opts.workflow;
12825
+ const runner = opts.runner && !isUsageIdentity(opts.runner, "rnr") ? (await resolveRunner(api, opts.runner)).id : opts.runner;
12758
12826
  const report = await api.getUsage({
12759
12827
  window: opts.window,
12760
12828
  from: opts.from,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tines",
3
- "version": "0.0.205",
3
+ "version": "0.0.207",
4
4
  "description": "CLI for Tines, an orchestration layer for AI agents",
5
5
  "repository": {
6
6
  "type": "git",