tines 0.0.207 → 0.0.209
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 +161 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4153,6 +4153,9 @@ function createApiClient(options) {
|
|
|
4153
4153
|
`/api/v1/runs${query(filters)}`
|
|
4154
4154
|
),
|
|
4155
4155
|
getUsage: (filters = {}) => get(`/api/v1/usage${query(filters)}`),
|
|
4156
|
+
getIssueUsage: (issue) => get(`/api/v1/usage${query({ mode: "issue", issue })}`),
|
|
4157
|
+
getUsageScope: (scope) => get(`/api/v1/usage${query({ scope })}`),
|
|
4158
|
+
getUsageEvidence: (filters) => get(`/api/v1/usage/evidence${query(filters)}`),
|
|
4156
4159
|
getRun: (id2) => get(`/api/v1/runs/${id2}`),
|
|
4157
4160
|
/**
|
|
4158
4161
|
* The run's complete log (not the 256 KB tail `getRun` returns) as a
|
|
@@ -11009,9 +11012,11 @@ function usageAggregateLines(label, aggregate) {
|
|
|
11009
11012
|
function usageEvidenceLines(id2, dimensions, accounting) {
|
|
11010
11013
|
const dims = ["project", "workflow", "state", "outcome", "runner", "tier"].map((name2) => `${name2}=${dimensions[name2].name} [${dimensions[name2].id ?? "unknown"}]`).join(" \xB7 ");
|
|
11011
11014
|
const diagnostics = Object.entries(accounting.diagnostics).filter(([, count]) => count > 0).map(([name2, count]) => `${name2}=${count}`).join(" \xB7 ");
|
|
11015
|
+
const tokens = ["input_tokens", "output_tokens", "cache_read_tokens", "cache_write_tokens"].map((name2) => `${name2}=${present(accounting.tokens[name2])}`).join(" \xB7 ");
|
|
11012
11016
|
return [
|
|
11013
11017
|
`Evidence ${id2}: ${dims}`,
|
|
11014
11018
|
`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}` : ""}`,
|
|
11019
|
+
`Tokens ${id2}: ${tokens} \xB7 invalid_tokens=${accounting.invalid_tokens.length ? accounting.invalid_tokens.join(",") : "none"}`,
|
|
11015
11020
|
...accounting.source === "calculated" ? [`Rate ${id2}: ${basisLine(accounting.basis)}`] : []
|
|
11016
11021
|
];
|
|
11017
11022
|
}
|
|
@@ -12740,6 +12745,62 @@ function normalizeUrl(value) {
|
|
|
12740
12745
|
}
|
|
12741
12746
|
|
|
12742
12747
|
// src/commands/usage.ts
|
|
12748
|
+
function printEvidence(page) {
|
|
12749
|
+
console.log(
|
|
12750
|
+
`Usage evidence \xB7 ${page.kind} \xB7 ${page.population} \xB7 ${page.total_count} total \xB7 ${page.sort} ${page.direction}`
|
|
12751
|
+
);
|
|
12752
|
+
if (page.kind === "issues")
|
|
12753
|
+
table([
|
|
12754
|
+
["ISSUE", "SPEND", "COVERAGE", "RUNS"],
|
|
12755
|
+
...page.items.map((item) => [
|
|
12756
|
+
item.issue_ref ? `${item.issue_ref.project_name}/${item.issue_ref.number} ${item.issue_ref.title}` : item.issue_id ? `Unavailable issue (${item.issue_id})` : "Unknown issue",
|
|
12757
|
+
money(item.aggregate.cost_usd),
|
|
12758
|
+
item.aggregate.coverage,
|
|
12759
|
+
String(item.attempt_count)
|
|
12760
|
+
])
|
|
12761
|
+
]);
|
|
12762
|
+
else
|
|
12763
|
+
table([
|
|
12764
|
+
["RUN", "ISSUE", "SPEND", "AT"],
|
|
12765
|
+
...page.items.map((item) => {
|
|
12766
|
+
const run2 = item;
|
|
12767
|
+
return [
|
|
12768
|
+
run2.id,
|
|
12769
|
+
run2.issue_id,
|
|
12770
|
+
page.population === "pending" ? "Pending" : money(run2.usage_accounting?.cost ?? null),
|
|
12771
|
+
new Date(run2.ended_at ?? run2.created_at).toISOString()
|
|
12772
|
+
];
|
|
12773
|
+
})
|
|
12774
|
+
]);
|
|
12775
|
+
if (page.kind === "runs" && page.population === "finalized")
|
|
12776
|
+
for (const item of page.items) {
|
|
12777
|
+
if ("id" in item && "usage_accounting" in item && item.usage_dimensions)
|
|
12778
|
+
for (const line of usageEvidenceLines(
|
|
12779
|
+
item.id,
|
|
12780
|
+
item.usage_dimensions,
|
|
12781
|
+
item.usage_accounting
|
|
12782
|
+
))
|
|
12783
|
+
console.log(line);
|
|
12784
|
+
}
|
|
12785
|
+
console.log(
|
|
12786
|
+
`Matching total: ${money(page.matching_total.cost_usd)} \xB7 ${page.attempt_count} attempts \xB7 ${page.pending_count} pending`
|
|
12787
|
+
);
|
|
12788
|
+
if (page.next_cursor) console.log(`Next cursor: ${page.next_cursor}`);
|
|
12789
|
+
}
|
|
12790
|
+
function printIssueReport(report) {
|
|
12791
|
+
const { issue } = report;
|
|
12792
|
+
console.log(
|
|
12793
|
+
`Usage \xB7 ${issue.issue_ref ? `${issue.issue_ref.project_name}/${issue.issue_ref.number}` : issue.issue_id} \xB7 Lifetime through now`
|
|
12794
|
+
);
|
|
12795
|
+
console.log(`as of ${new Date(report.cutoff).toISOString()} \xB7 direct retained attempts`);
|
|
12796
|
+
if (issue.attempt_count === 0) console.log("No agent runs");
|
|
12797
|
+
else {
|
|
12798
|
+
console.log(
|
|
12799
|
+
`${money(issue.aggregate.cost_usd)} \xB7 ${issue.aggregate.coverage} \xB7 ${issue.aggregate.finalized_run_count} finalized \xB7 ${issue.pending_count} pending at cutoff`
|
|
12800
|
+
);
|
|
12801
|
+
for (const line of usageAggregateLines("Lifetime", issue.aggregate)) console.log(line);
|
|
12802
|
+
}
|
|
12803
|
+
}
|
|
12743
12804
|
var money = (value) => usageCostLabel(value);
|
|
12744
12805
|
function printReport(report) {
|
|
12745
12806
|
console.log(`Usage \xB7 ${report.filters.project ?? "All projects"} \xB7 ${report.by}`);
|
|
@@ -12798,7 +12859,12 @@ function register12(program3) {
|
|
|
12798
12859
|
withCommon(
|
|
12799
12860
|
program3.command("usage").description("Compare finalized run spend for a period").addOption(
|
|
12800
12861
|
new Option("--window <window>", "today, 7d, or 30d").choices(["today", "7d", "30d"])
|
|
12801
|
-
).option("--from <bound>", "custom inclusive start (date or offset timestamp)").option("--to <bound>", "custom exclusive end (date or offset timestamp)").option("--
|
|
12862
|
+
).option("--from <bound>", "custom inclusive start (date or offset timestamp)").option("--to <bound>", "custom exclusive end (date or offset timestamp)").option("--issue <ref>", "direct issue lifetime through now").option("--scope <token>", "replay a frozen usage scope").addOption(new Option("--evidence <kind>", "list evidence").choices(["issues", "runs"])).option("--member <issue-id>", "narrow run evidence to one contributing issue").addOption(
|
|
12863
|
+
new Option("--population <population>", "finalized or pending").choices([
|
|
12864
|
+
"finalized",
|
|
12865
|
+
"pending"
|
|
12866
|
+
])
|
|
12867
|
+
).addOption(new Option("--sort <sort>", "evidence sort").choices(["cost", "time"])).addOption(new Option("--direction <direction>", "sort direction").choices(["asc", "desc"])).option("--cursor <token>", "evidence page cursor").option("--limit <count>", "evidence page size (1-100)").option("--all-pages", "fetch every evidence page").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(
|
|
12802
12868
|
new Option("--outcome <outcome>", "recorded outcome").choices([
|
|
12803
12869
|
"advanced",
|
|
12804
12870
|
"stalled",
|
|
@@ -12814,7 +12880,100 @@ function register12(program3) {
|
|
|
12814
12880
|
).addOption(
|
|
12815
12881
|
new Option("--by <dimension>", "group dimension").choices(["project", "workflow", "state", "outcome", "runner", "tier"]).default("workflow")
|
|
12816
12882
|
)
|
|
12817
|
-
).action(async (opts) => {
|
|
12883
|
+
).action(async (opts, command) => {
|
|
12884
|
+
const evidenceOnly = [
|
|
12885
|
+
opts.member,
|
|
12886
|
+
opts.population,
|
|
12887
|
+
opts.sort,
|
|
12888
|
+
opts.direction,
|
|
12889
|
+
opts.cursor,
|
|
12890
|
+
opts.limit,
|
|
12891
|
+
opts.allPages
|
|
12892
|
+
];
|
|
12893
|
+
if (evidenceOnly.some((value) => value !== void 0) && !opts.evidence)
|
|
12894
|
+
throw new Error(
|
|
12895
|
+
"--member/--population/--sort/--direction/--cursor/--limit/--all-pages require --evidence"
|
|
12896
|
+
);
|
|
12897
|
+
if (opts.evidence && !opts.scope) throw new Error("--evidence requires --scope");
|
|
12898
|
+
if (opts.scope) {
|
|
12899
|
+
const reportFlags = [
|
|
12900
|
+
opts.issue,
|
|
12901
|
+
opts.window,
|
|
12902
|
+
opts.from,
|
|
12903
|
+
opts.to,
|
|
12904
|
+
opts.project,
|
|
12905
|
+
opts.workflow,
|
|
12906
|
+
opts.state,
|
|
12907
|
+
opts.runner,
|
|
12908
|
+
opts.tier,
|
|
12909
|
+
opts.outcome,
|
|
12910
|
+
opts.accountingStatus
|
|
12911
|
+
];
|
|
12912
|
+
if (command.getOptionValueSource("by") === "cli") reportFlags.push(opts.by);
|
|
12913
|
+
if (reportFlags.some((value) => value !== void 0))
|
|
12914
|
+
throw new Error("--scope cannot be combined with report options");
|
|
12915
|
+
const api2 = client(opts);
|
|
12916
|
+
if (!opts.evidence) {
|
|
12917
|
+
const report2 = await api2.getUsageScope(opts.scope);
|
|
12918
|
+
if (opts.json) return printJson(report2);
|
|
12919
|
+
if (report2.mode === "issue") printIssueReport(report2);
|
|
12920
|
+
else printReport(report2);
|
|
12921
|
+
return;
|
|
12922
|
+
}
|
|
12923
|
+
let cursor = opts.cursor;
|
|
12924
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
12925
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
12926
|
+
let combined = null;
|
|
12927
|
+
do {
|
|
12928
|
+
if (cursor && seenCursors.has(cursor))
|
|
12929
|
+
throw new Error("Evidence pagination repeated a cursor");
|
|
12930
|
+
if (cursor) seenCursors.add(cursor);
|
|
12931
|
+
const page = await api2.getUsageEvidence({
|
|
12932
|
+
scope: opts.scope,
|
|
12933
|
+
kind: opts.evidence,
|
|
12934
|
+
population: opts.population,
|
|
12935
|
+
member: opts.member,
|
|
12936
|
+
sort: opts.sort,
|
|
12937
|
+
direction: opts.direction,
|
|
12938
|
+
limit: opts.limit ? Number(opts.limit) : void 0,
|
|
12939
|
+
cursor
|
|
12940
|
+
});
|
|
12941
|
+
for (const item of page.items) {
|
|
12942
|
+
const id2 = "id" in item ? item.id : item.issue_id ?? "unknown";
|
|
12943
|
+
if (seenIds.has(id2)) throw new Error(`Evidence pagination repeated ${id2}`);
|
|
12944
|
+
seenIds.add(id2);
|
|
12945
|
+
}
|
|
12946
|
+
combined = combined ? { ...page, items: [...combined.items, ...page.items], previous_cursor: null } : page;
|
|
12947
|
+
cursor = page.next_cursor ?? void 0;
|
|
12948
|
+
} while (opts.allPages && cursor);
|
|
12949
|
+
if (!combined) throw new Error("Evidence response was empty");
|
|
12950
|
+
if (opts.json) return printJson(combined);
|
|
12951
|
+
printEvidence(combined);
|
|
12952
|
+
return;
|
|
12953
|
+
}
|
|
12954
|
+
if (opts.issue) {
|
|
12955
|
+
const contradictions = [
|
|
12956
|
+
opts.window,
|
|
12957
|
+
opts.from,
|
|
12958
|
+
opts.to,
|
|
12959
|
+
opts.project,
|
|
12960
|
+
opts.workflow,
|
|
12961
|
+
opts.state,
|
|
12962
|
+
opts.runner,
|
|
12963
|
+
opts.tier,
|
|
12964
|
+
opts.outcome,
|
|
12965
|
+
opts.accountingStatus
|
|
12966
|
+
];
|
|
12967
|
+
if (command.getOptionValueSource("by") === "cli") contradictions.push(opts.by);
|
|
12968
|
+
if (contradictions.some((value) => value !== void 0))
|
|
12969
|
+
throw new Error("--issue cannot be combined with period or filter options");
|
|
12970
|
+
const api2 = client(opts);
|
|
12971
|
+
const issueId = isUsageIdentity(opts.issue, "iss") ? opts.issue : (await resolveIssue(api2, opts.issue)).id;
|
|
12972
|
+
const report2 = await api2.getIssueUsage(issueId);
|
|
12973
|
+
if (opts.json) return printJson(report2);
|
|
12974
|
+
printIssueReport(report2);
|
|
12975
|
+
return;
|
|
12976
|
+
}
|
|
12818
12977
|
if (opts.from === void 0 !== (opts.to === void 0))
|
|
12819
12978
|
throw new Error("--from and --to are required together");
|
|
12820
12979
|
if (opts.window && opts.from) throw new Error("--window cannot be combined with --from/--to");
|