tines 0.0.186 → 0.0.187
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 +174 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4139,7 +4139,10 @@ function createApiClient(options) {
|
|
|
4139
4139
|
appendRunLog: (runId, body) => request("POST", `/api/v1/runs/${runId}/logs`, body),
|
|
4140
4140
|
finishRun: (runId, body) => request("POST", `/api/v1/runs/${runId}/finish`, body),
|
|
4141
4141
|
// Agent runs
|
|
4142
|
-
listRuns: (filters = {}) => get(
|
|
4142
|
+
listRuns: (filters = {}) => get(
|
|
4143
|
+
`/api/v1/runs${query(filters)}`
|
|
4144
|
+
),
|
|
4145
|
+
getUsage: (filters = {}) => get(`/api/v1/usage${query(filters)}`),
|
|
4143
4146
|
getRun: (id2) => get(`/api/v1/runs/${id2}`),
|
|
4144
4147
|
/**
|
|
4145
4148
|
* The run's complete log (not the 256 KB tail `getRun` returns) as a
|
|
@@ -4540,6 +4543,20 @@ var schedule = shape({
|
|
|
4540
4543
|
// ../shared/src/library/choices.ts
|
|
4541
4544
|
var PACKAGE_CHOICES_MAX_BYTES = 512 * 1024;
|
|
4542
4545
|
|
|
4546
|
+
// ../shared/src/usage.ts
|
|
4547
|
+
function usageCostLabel(cost, finalized = 1) {
|
|
4548
|
+
if (finalized === 0) return "No runs";
|
|
4549
|
+
if (cost === null) return "Unknown";
|
|
4550
|
+
if (cost === 0) return "$0";
|
|
4551
|
+
if (cost < 0.01) return "<$0.01";
|
|
4552
|
+
return cost.toLocaleString("en-US", {
|
|
4553
|
+
style: "currency",
|
|
4554
|
+
currency: "USD",
|
|
4555
|
+
minimumFractionDigits: 2,
|
|
4556
|
+
maximumFractionDigits: 2
|
|
4557
|
+
});
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4543
4560
|
// src/format.ts
|
|
4544
4561
|
function timestamp(ms) {
|
|
4545
4562
|
return new Date(ms).toISOString().replace("T", " ").slice(0, 19);
|
|
@@ -9641,22 +9658,71 @@ function register8(program3) {
|
|
|
9641
9658
|
});
|
|
9642
9659
|
const runsCmd = program3.command("runs").description("Agent runs: attempts at issues by runners");
|
|
9643
9660
|
withList(
|
|
9644
|
-
runsCmd.command("list").description("List runs, newest first").option("-i, --issue <ref>", "filter to one issue (<project>/<number>)").option("-r, --runner <name>", "filter by runner name").option("--active", "only runs holding a claim (assigned/launching/running)")
|
|
9661
|
+
runsCmd.command("list").description("List runs, newest first").option("-i, --issue <ref>", "filter to one issue (<project>/<number>)").option("-r, --runner <name>", "filter by runner name").option("--active", "only runs holding a claim (assigned/launching/running)").addOption(
|
|
9662
|
+
new Option("--population <mode>", "period evidence population").choices([
|
|
9663
|
+
"finalized",
|
|
9664
|
+
"pending"
|
|
9665
|
+
])
|
|
9666
|
+
).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(
|
|
9667
|
+
new Option("--outcome <outcome>", "recorded outcome").choices([
|
|
9668
|
+
"advanced",
|
|
9669
|
+
"stalled",
|
|
9670
|
+
"interrupted",
|
|
9671
|
+
"unknown"
|
|
9672
|
+
])
|
|
9673
|
+
).addOption(
|
|
9674
|
+
new Option("--accounting-status <status>", "usage accounting status").choices([
|
|
9675
|
+
"priced",
|
|
9676
|
+
"unpriced",
|
|
9677
|
+
"unreported"
|
|
9678
|
+
])
|
|
9679
|
+
)
|
|
9645
9680
|
).action(async (opts) => {
|
|
9646
9681
|
const api = client(opts);
|
|
9682
|
+
const evidence = opts;
|
|
9683
|
+
if (evidence.from === void 0 !== (evidence.to === void 0))
|
|
9684
|
+
die("--from and --to are required together");
|
|
9685
|
+
if ((evidence.from || evidence.to) && !evidence.population)
|
|
9686
|
+
die("period filters require --population");
|
|
9647
9687
|
const issueId = opts.issue ? (await resolveIssue(api, opts.issue)).id : void 0;
|
|
9648
9688
|
const runnerId = opts.runner ? (await resolveRunner(api, opts.runner)).id : void 0;
|
|
9689
|
+
const projectId = evidence.project ? (await resolveProject(api, evidence.project)).id : void 0;
|
|
9690
|
+
const workflowId = evidence.workflow ? (await resolveWorkflow(api, evidence.workflow)).id : void 0;
|
|
9649
9691
|
const res = await fetchList(
|
|
9650
9692
|
opts,
|
|
9651
9693
|
(page) => api.listRuns({
|
|
9652
9694
|
issue: issueId,
|
|
9653
9695
|
runner: runnerId,
|
|
9654
9696
|
active: opts.active ? true : void 0,
|
|
9697
|
+
population: evidence.population,
|
|
9698
|
+
from: evidence.from,
|
|
9699
|
+
to: evidence.to,
|
|
9700
|
+
project: projectId,
|
|
9701
|
+
workflow: workflowId,
|
|
9702
|
+
state: evidence.state,
|
|
9703
|
+
tier: evidence.tier,
|
|
9704
|
+
outcome: evidence.outcome,
|
|
9705
|
+
accounting_status: evidence.accountingStatus,
|
|
9655
9706
|
...page
|
|
9656
9707
|
})
|
|
9657
9708
|
);
|
|
9658
9709
|
printList(res, opts, (items) => {
|
|
9659
9710
|
if (items.length === 0) return console.log(opts.active ? "no active runs" : "no runs");
|
|
9711
|
+
if (evidence.population === "pending") {
|
|
9712
|
+
table([
|
|
9713
|
+
["ID", "ISSUE", "RUNNER", "TIER", "STATUS", "COST", "CREATED"],
|
|
9714
|
+
...items.map((run) => [
|
|
9715
|
+
run.id,
|
|
9716
|
+
run.issue_ref ? `${run.issue_ref.project_name}/${run.issue_ref.number}` : run.issue_id,
|
|
9717
|
+
run.runner_name,
|
|
9718
|
+
run.tier,
|
|
9719
|
+
"Pending at cutoff",
|
|
9720
|
+
"\u2014",
|
|
9721
|
+
timestamp(run.created_at)
|
|
9722
|
+
])
|
|
9723
|
+
]);
|
|
9724
|
+
return;
|
|
9725
|
+
}
|
|
9660
9726
|
table([
|
|
9661
9727
|
["ID", "ISSUE", "RUNNER", "TIER", "STATUS", "DURATION", "COST", "CREATED"],
|
|
9662
9728
|
...items.map(runRow)
|
|
@@ -10442,6 +10508,111 @@ see \`tines workflows create --help\` for the expected shape`
|
|
|
10442
10508
|
});
|
|
10443
10509
|
}
|
|
10444
10510
|
|
|
10511
|
+
// src/commands/usage.ts
|
|
10512
|
+
var money = (value) => usageCostLabel(value);
|
|
10513
|
+
function printReport(report) {
|
|
10514
|
+
console.log(`Usage \xB7 ${report.filters.project ?? "All projects"} \xB7 ${report.by}`);
|
|
10515
|
+
console.log(
|
|
10516
|
+
`${new Date(report.from).toISOString()} \u2014 ${new Date(report.to).toISOString()} \xB7 ${report.timezone} (${report.timezone_source.replace("_", " ")})`
|
|
10517
|
+
);
|
|
10518
|
+
console.log(
|
|
10519
|
+
`generated ${new Date(report.generated_at).toISOString()} \xB7 ${report.accounting_basis}`
|
|
10520
|
+
);
|
|
10521
|
+
const scope = report.scope_total;
|
|
10522
|
+
console.log(
|
|
10523
|
+
`Scope total: ${money(scope.cost_usd)} \xB7 ${scope.coverage} \xB7 ${scope.finalized_run_count} finalized \xB7 ${scope.priced_run_count} priced \xB7 ${scope.unpriced_run_count + scope.unreported_run_count} without price`
|
|
10524
|
+
);
|
|
10525
|
+
if (JSON.stringify(report.filters) !== JSON.stringify({ ...report.filters.project ? { project: report.filters.project } : {} })) {
|
|
10526
|
+
const matching = report.matching_total;
|
|
10527
|
+
console.log(
|
|
10528
|
+
`Matching subtotal: ${money(matching.cost_usd)} \xB7 ${matching.coverage} \xB7 ${matching.finalized_run_count} finalized`
|
|
10529
|
+
);
|
|
10530
|
+
}
|
|
10531
|
+
const total = report.matching_total;
|
|
10532
|
+
console.log(
|
|
10533
|
+
`Pending at cutoff: ${report.pending.matching_count}${report.pending.unapplied_filters.length ? ` (before ${report.pending.unapplied_filters.join("/")} filters)` : ""}`
|
|
10534
|
+
);
|
|
10535
|
+
if (report.groups.length === 0) return console.log("no finalized runs");
|
|
10536
|
+
table([
|
|
10537
|
+
["GROUP", "SPEND", "COVERAGE", "FINAL", "PRICED", "MISSING", "MEDIAN", "P95", "MAX", "MEAN"],
|
|
10538
|
+
...report.groups.map(({ dimension, aggregate: a }) => [
|
|
10539
|
+
dimension.name,
|
|
10540
|
+
money(a.cost_usd),
|
|
10541
|
+
a.coverage,
|
|
10542
|
+
String(a.finalized_run_count),
|
|
10543
|
+
String(a.priced_run_count),
|
|
10544
|
+
String(a.unpriced_run_count + a.unreported_run_count),
|
|
10545
|
+
money(a.distribution.median_cost_usd),
|
|
10546
|
+
money(a.distribution.p95_cost_usd),
|
|
10547
|
+
money(a.distribution.max_cost_usd),
|
|
10548
|
+
money(a.distribution.mean_cost_usd)
|
|
10549
|
+
])
|
|
10550
|
+
]);
|
|
10551
|
+
console.log("Per-run cost \xB7 priced subset; p95 uses nearest rank.");
|
|
10552
|
+
if (report.groups.some((g) => g.aggregate.distribution.low_sample))
|
|
10553
|
+
console.log("Small samples (under 20): p95 equals maximum.");
|
|
10554
|
+
console.log(
|
|
10555
|
+
`Matching tokens: ${Object.entries(total.tokens).map(
|
|
10556
|
+
([name2, t]) => `${name2} ${t.value ?? "unknown"} (${t.reported_runs}/${total.finalized_run_count} runs)`
|
|
10557
|
+
).join(" \xB7 ")}`
|
|
10558
|
+
);
|
|
10559
|
+
console.log(
|
|
10560
|
+
`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}`
|
|
10561
|
+
);
|
|
10562
|
+
for (const portion of total.rate_portions) {
|
|
10563
|
+
const basis = portion.basis;
|
|
10564
|
+
console.log(
|
|
10565
|
+
basis ? `Rate: ${basis.rate_id} v${basis.rate_version} \xB7 ${basis.model} \xB7 ${basis.source_url}` : `Rate: historical calculated amount \xB7 basis unavailable`
|
|
10566
|
+
);
|
|
10567
|
+
}
|
|
10568
|
+
}
|
|
10569
|
+
function register12(program3) {
|
|
10570
|
+
withCommon(
|
|
10571
|
+
program3.command("usage").description("Compare finalized run spend for a period").addOption(
|
|
10572
|
+
new Option("--window <window>", "today, 7d, or 30d").choices(["today", "7d", "30d"])
|
|
10573
|
+
).option("--from <bound>", "custom inclusive start (date or offset timestamp)").option("--to <bound>", "custom exclusive end (date or offset timestamp)").option("--project <name-or-id>", "project scope (including archived), or unknown").option("--workflow <name-or-id>", "workflow filter, or unknown").option("--state <id>", "starting state id (requires --workflow)").option("--runner <name-or-id>", "runner filter, or unknown").option("--tier <tier>", "tier filter").addOption(
|
|
10574
|
+
new Option("--outcome <outcome>", "recorded outcome").choices([
|
|
10575
|
+
"advanced",
|
|
10576
|
+
"stalled",
|
|
10577
|
+
"interrupted",
|
|
10578
|
+
"unknown"
|
|
10579
|
+
])
|
|
10580
|
+
).addOption(
|
|
10581
|
+
new Option("--accounting-status <status>", "price coverage").choices([
|
|
10582
|
+
"priced",
|
|
10583
|
+
"unpriced",
|
|
10584
|
+
"unreported"
|
|
10585
|
+
])
|
|
10586
|
+
).addOption(
|
|
10587
|
+
new Option("--by <dimension>", "group dimension").choices(["project", "workflow", "state", "outcome", "runner", "tier"]).default("workflow")
|
|
10588
|
+
)
|
|
10589
|
+
).action(async (opts) => {
|
|
10590
|
+
if (opts.from === void 0 !== (opts.to === void 0))
|
|
10591
|
+
throw new Error("--from and --to are required together");
|
|
10592
|
+
if (opts.window && opts.from) throw new Error("--window cannot be combined with --from/--to");
|
|
10593
|
+
if (opts.state && !opts.workflow) throw new Error("--state requires --workflow");
|
|
10594
|
+
const api = client(opts);
|
|
10595
|
+
const project = opts.project && opts.project !== "unknown" ? (await resolveProject(api, opts.project)).id : opts.project;
|
|
10596
|
+
const workflow = opts.workflow && opts.workflow !== "unknown" ? (await resolveWorkflow(api, opts.workflow)).id : opts.workflow;
|
|
10597
|
+
const runner = opts.runner && opts.runner !== "unknown" ? (await resolveRunner(api, opts.runner)).id : opts.runner;
|
|
10598
|
+
const report = await api.getUsage({
|
|
10599
|
+
window: opts.window,
|
|
10600
|
+
from: opts.from,
|
|
10601
|
+
to: opts.to,
|
|
10602
|
+
project,
|
|
10603
|
+
workflow,
|
|
10604
|
+
state: opts.state,
|
|
10605
|
+
runner,
|
|
10606
|
+
tier: opts.tier,
|
|
10607
|
+
outcome: opts.outcome,
|
|
10608
|
+
accounting_status: opts.accountingStatus,
|
|
10609
|
+
by: opts.by
|
|
10610
|
+
});
|
|
10611
|
+
if (opts.json) return printJson(report);
|
|
10612
|
+
printReport(report);
|
|
10613
|
+
});
|
|
10614
|
+
}
|
|
10615
|
+
|
|
10445
10616
|
// src/program.ts
|
|
10446
10617
|
var program2 = new Command();
|
|
10447
10618
|
program2.name("tines").description("CLI for Tines").version(cliVersion()).enablePositionalOptions();
|
|
@@ -10457,6 +10628,7 @@ register9(program2);
|
|
|
10457
10628
|
register8(program2);
|
|
10458
10629
|
register7(program2);
|
|
10459
10630
|
register10(program2);
|
|
10631
|
+
register12(program2);
|
|
10460
10632
|
registerEvents(program2);
|
|
10461
10633
|
|
|
10462
10634
|
// src/index.ts
|