@danypops/jittor 0.14.0 → 0.16.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.
Files changed (59) hide show
  1. package/package.json +4 -3
  2. package/src/adapters/artificial-analysis-direct-source.ts +42 -11
  3. package/src/adapters/lmarena-hf-source.ts +37 -15
  4. package/src/adapters/metric-benchmark-store.ts +29 -18
  5. package/src/adapters/openrouter-benchmark-source.ts +75 -19
  6. package/src/adapters/openrouter-design-arena-source.ts +36 -19
  7. package/src/adapters/sqlite-metric-store.ts +48 -25
  8. package/src/adapters/sqlite-session-identity-store.ts +13 -7
  9. package/src/cli-commands/benchmarks.ts +87 -22
  10. package/src/cli-commands/compaction.ts +7 -2
  11. package/src/cli-commands/context.ts +10 -2
  12. package/src/cli-commands/metrics.ts +128 -31
  13. package/src/cli-commands/op.ts +6 -1
  14. package/src/cli-commands/route-args.ts +5 -1
  15. package/src/cli-commands/router.ts +61 -18
  16. package/src/cli-commands/service-daemon.ts +31 -13
  17. package/src/cli-commands/session.ts +15 -4
  18. package/src/cli-commands/support.ts +1 -1
  19. package/src/cli.ts +30 -23
  20. package/src/client.ts +1 -1
  21. package/src/constants.ts +1 -1
  22. package/src/daemon.ts +44 -24
  23. package/src/domain/benchmark.ts +72 -40
  24. package/src/domain/codex-recovery.ts +34 -25
  25. package/src/domain/context-hub.ts +35 -26
  26. package/src/domain/context-telemetry.ts +106 -35
  27. package/src/domain/metric.ts +11 -11
  28. package/src/domain/model-observation.ts +139 -55
  29. package/src/domain/model-ranking-service.ts +13 -3
  30. package/src/domain/model-ranking.ts +126 -60
  31. package/src/domain/task-cost.ts +52 -11
  32. package/src/domain/task-focus.ts +11 -8
  33. package/src/domain/usage.ts +2 -2
  34. package/src/index.ts +69 -69
  35. package/src/log.ts +7 -2
  36. package/src/operations/benchmark-operations.ts +1 -1
  37. package/src/operations/context-operations.ts +15 -6
  38. package/src/operations/metrics-operations.ts +63 -28
  39. package/src/operations/model-ranking-operations.ts +9 -2
  40. package/src/operations/router-operations.ts +8 -4
  41. package/src/operations/session-identity-operations.ts +1 -1
  42. package/src/operations/session-scope.ts +5 -3
  43. package/src/policy.ts +22 -17
  44. package/src/ports/benchmark-controller.ts +1 -5
  45. package/src/ports/metric-store.ts +1 -1
  46. package/src/providers/anthropic-contracts.ts +13 -3
  47. package/src/providers/codex-contracts.ts +60 -52
  48. package/src/providers/codex.ts +16 -19
  49. package/src/providers/google-vertex-budget-contracts.ts +24 -14
  50. package/src/providers/google-vertex-budget.ts +15 -13
  51. package/src/providers/google-vertex-contracts.ts +36 -24
  52. package/src/providers/openrouter-contracts.ts +49 -51
  53. package/src/providers/openrouter.ts +21 -15
  54. package/src/providers/telemetry-sources.ts +13 -10
  55. package/src/router.ts +92 -43
  56. package/src/service.ts +93 -32
  57. package/src/session-identity-service.ts +10 -2
  58. package/src/state.ts +4 -10
  59. package/src/vehicle-registration.ts +154 -0
@@ -6,20 +6,24 @@ export class SQLiteSessionIdentityStore implements SessionIdentityStore {
6
6
  constructor(private readonly db: Database) {}
7
7
 
8
8
  find(sessionId: string): SessionIdentityRecord | undefined {
9
- const row = this.db.query("SELECT session_id, secret_hash, registered_at, last_seen_at FROM session_identities WHERE session_id = ?").get(sessionId) as
10
- | { session_id: string; secret_hash: string; registered_at: string; last_seen_at: string }
11
- | null;
12
- return row ? { sessionId: row.session_id, secretHash: row.secret_hash, registeredAt: row.registered_at, lastSeenAt: row.last_seen_at } : undefined;
9
+ const row = this.db
10
+ .query("SELECT session_id, secret_hash, registered_at, last_seen_at FROM session_identities WHERE session_id = ?")
11
+ .get(sessionId) as { session_id: string; secret_hash: string; registered_at: string; last_seen_at: string } | null;
12
+ return row
13
+ ? { sessionId: row.session_id, secretHash: row.secret_hash, registeredAt: row.registered_at, lastSeenAt: row.last_seen_at }
14
+ : undefined;
13
15
  }
14
16
 
15
17
  upsert(record: SessionIdentityRecord): void {
16
18
  this.db.transaction(() => {
17
19
  this.evictOldestBeyondCap(record.sessionId);
18
- this.db.query(`
20
+ this.db
21
+ .query(`
19
22
  INSERT INTO session_identities (session_id, secret_hash, registered_at, last_seen_at)
20
23
  VALUES (?, ?, ?, ?)
21
24
  ON CONFLICT(session_id) DO UPDATE SET secret_hash = excluded.secret_hash, registered_at = excluded.registered_at, last_seen_at = excluded.last_seen_at
22
- `).run(record.sessionId, record.secretHash, record.registeredAt, record.lastSeenAt);
25
+ `)
26
+ .run(record.sessionId, record.secretHash, record.registeredAt, record.lastSeenAt);
23
27
  })();
24
28
  }
25
29
 
@@ -40,6 +44,8 @@ export class SQLiteSessionIdentityStore implements SessionIdentityStore {
40
44
  const exists = this.db.query("SELECT 1 FROM session_identities WHERE session_id = ?").get(sessionId);
41
45
  if (exists) return;
42
46
  if (this.count() < SESSION_IDENTITY_MAX_ROWS) return;
43
- this.db.exec("DELETE FROM session_identities WHERE session_id = (SELECT session_id FROM session_identities ORDER BY last_seen_at ASC LIMIT 1)");
47
+ this.db.exec(
48
+ "DELETE FROM session_identities WHERE session_id = (SELECT session_id FROM session_identities ORDER BY last_seen_at ASC LIMIT 1)",
49
+ );
44
50
  }
45
51
  }
@@ -8,11 +8,11 @@ import {
8
8
  MODEL_RANKING_MAX_SOURCES,
9
9
  } from "../constants.ts";
10
10
  import type { BenchmarkQuery, BenchmarkQueryResult, BenchmarkRefreshResult } from "../domain/benchmark.ts";
11
- import type { ModelRecommendationInput } from "../domain/model-ranking-service.ts";
11
+ import { type ModelTaskDomain, type ModelTaskType, TASK_DOMAINS, TASK_TYPES } from "../domain/model-observation.ts";
12
12
  import type { ModelCandidate, ModelRankingResult, ScopeAuthority, UtilityWeights } from "../domain/model-ranking.ts";
13
- import { TASK_DOMAINS, TASK_TYPES, type ModelTaskDomain, type ModelTaskType } from "../domain/model-observation.ts";
14
- import { humanField, type CliDependencies } from "./support.ts";
13
+ import type { ModelRecommendationInput } from "../domain/model-ranking-service.ts";
15
14
  import { parseCandidate } from "./route-args.ts";
15
+ import { type CliDependencies, humanField } from "./support.ts";
16
16
 
17
17
  export const BENCHMARKS_USAGE_LINES = [" benchmarks <status|refresh|list|rank> [options] [--json]"];
18
18
 
@@ -38,16 +38,42 @@ function parseBenchmarkArgs(action: string | undefined, args: string[]): Benchma
38
38
  let sessionId: string | undefined;
39
39
  let sessionSecret: string | undefined;
40
40
  const weights: UtilityWeights = {
41
- quality: MODEL_RANKING_DEFAULT_QUALITY_WEIGHT, cost: MODEL_RANKING_DEFAULT_COST_WEIGHT,
42
- latency: MODEL_RANKING_DEFAULT_LATENCY_WEIGHT, context: MODEL_RANKING_DEFAULT_CONTEXT_WEIGHT,
41
+ quality: MODEL_RANKING_DEFAULT_QUALITY_WEIGHT,
42
+ cost: MODEL_RANKING_DEFAULT_COST_WEIGHT,
43
+ latency: MODEL_RANKING_DEFAULT_LATENCY_WEIGHT,
44
+ context: MODEL_RANKING_DEFAULT_CONTEXT_WEIGHT,
43
45
  reliability: MODEL_RANKING_DEFAULT_RELIABILITY_WEIGHT,
44
46
  };
45
47
  for (let index = 0; index < args.length; index += 1) {
46
48
  const argument = args[index];
47
- if (argument === "--json") { json = true; continue; }
48
- if (argument === "--force" && action === "refresh") { force = true; continue; }
49
- const allowed = action === "list" ? ["--source", "--model", "--dimension", "--limit"]
50
- : action === "rank" ? ["--candidate", "--source", "--domain", "--type", "--scope", "--budget", "--weight-quality", "--weight-cost", "--weight-latency", "--weight-context", "--weight-reliability", "--session-id", "--session-secret"] : [];
49
+ if (argument === "--json") {
50
+ json = true;
51
+ continue;
52
+ }
53
+ if (argument === "--force" && action === "refresh") {
54
+ force = true;
55
+ continue;
56
+ }
57
+ const allowed =
58
+ action === "list"
59
+ ? ["--source", "--model", "--dimension", "--limit"]
60
+ : action === "rank"
61
+ ? [
62
+ "--candidate",
63
+ "--source",
64
+ "--domain",
65
+ "--type",
66
+ "--scope",
67
+ "--budget",
68
+ "--weight-quality",
69
+ "--weight-cost",
70
+ "--weight-latency",
71
+ "--weight-context",
72
+ "--weight-reliability",
73
+ "--session-id",
74
+ "--session-secret",
75
+ ]
76
+ : [];
51
77
  if (!allowed.includes(argument ?? "")) return null;
52
78
  const raw = args[++index];
53
79
  if (raw === undefined || raw.length === 0) return null;
@@ -85,38 +111,76 @@ function parseBenchmarkArgs(action: string | undefined, args: string[]): Benchma
85
111
  }
86
112
  }
87
113
  if (action === "list" && query.sourceId === undefined) return null;
88
- if (action === "rank" && (candidates.length === 0 || sourceIds.length > MODEL_RANKING_MAX_SOURCES || !Number.isFinite(budgetPressure) || budgetPressure < 0 || budgetPressure > 2)) return null;
114
+ if (
115
+ action === "rank" &&
116
+ (candidates.length === 0 ||
117
+ sourceIds.length > MODEL_RANKING_MAX_SOURCES ||
118
+ !Number.isFinite(budgetPressure) ||
119
+ budgetPressure < 0 ||
120
+ budgetPressure > 2)
121
+ )
122
+ return null;
89
123
  return {
90
- action, json, force,
124
+ action,
125
+ json,
126
+ force,
91
127
  ...(action === "list" ? { query: query as BenchmarkQuery } : {}),
92
- ...(action === "rank" ? { recommendation: { candidates, sourceIds: [...new Set(sourceIds)], scopeAuthority, domain, type, budgetPressure, weights, ...(sessionId ? { session_id: sessionId } : {}), ...(sessionSecret ? { session_secret: sessionSecret } : {}) } } : {}),
128
+ ...(action === "rank"
129
+ ? {
130
+ recommendation: {
131
+ candidates,
132
+ sourceIds: [...new Set(sourceIds)],
133
+ scopeAuthority,
134
+ domain,
135
+ type,
136
+ budgetPressure,
137
+ weights,
138
+ ...(sessionId ? { session_id: sessionId } : {}),
139
+ ...(sessionSecret ? { session_secret: sessionSecret } : {}),
140
+ },
141
+ }
142
+ : {}),
93
143
  };
94
144
  }
95
145
 
96
146
  export function formatBenchmarkStatus(result: BenchmarkRefreshResult): string {
97
147
  if (result.sources.length === 0) return "Benchmark sources: none configured";
98
- return ["Benchmark sources:", ...result.sources.map((source) => {
99
- const state = source.ok === null ? "not refreshed" : source.ok ? "ready" : "refresh failed";
100
- return `- ${source.id}: ${state} · ${source.observations.toLocaleString()} observations · ${source.hasEvidence ? "evidence retained" : "no evidence"}`;
101
- })].join("\n");
148
+ return [
149
+ "Benchmark sources:",
150
+ ...result.sources.map((source) => {
151
+ const state = source.ok === null ? "not refreshed" : source.ok ? "ready" : "refresh failed";
152
+ return `- ${source.id}: ${state} · ${source.observations.toLocaleString()} observations · ${source.hasEvidence ? "evidence retained" : "no evidence"}`;
153
+ }),
154
+ ].join("\n");
102
155
  }
103
156
 
104
157
  export function formatBenchmarkQuery(result: BenchmarkQueryResult): string {
105
158
  return [
106
159
  `Benchmark evidence: ${humanField(result.sourceId)} · ${result.completeness} · ${result.freshness} · ${result.observations.length.toLocaleString()} observations`,
107
- ...result.observations.map((observation) => `- ${humanField(observation.model.canonical)} · ${humanField(observation.dimension)} ${observation.value.toLocaleString()} ${observation.unit} · ${humanField(observation.provenance.publisher)} · confidence ${(observation.provenance.confidence * 100).toFixed(0)}%`),
160
+ ...result.observations.map(
161
+ (observation) =>
162
+ `- ${humanField(observation.model.canonical)} · ${humanField(observation.dimension)} ${observation.value.toLocaleString()} ${observation.unit} · ${humanField(observation.provenance.publisher)} · confidence ${(observation.provenance.confidence * 100).toFixed(0)}%`,
163
+ ),
108
164
  ].join("\n");
109
165
  }
110
166
 
111
167
  export function formatModelRanking(result: ModelRankingResult): string {
112
168
  return [
113
169
  `Model ranking: ${result.completeness} · scope ${result.scopeAuthority}${result.scopeWarning ? " · advisory only" : ""}`,
114
- ...result.ranked.map((item, index) => `${index + 1}. ${humanField(item.identity)} · utility ${item.utility === null ? "unknown" : item.utility.toFixed(3)} · confidence ${(item.confidence * 100).toFixed(0)}%`),
170
+ ...result.ranked.map(
171
+ (item, index) =>
172
+ `${index + 1}. ${humanField(item.identity)} · utility ${item.utility === null ? "unknown" : item.utility.toFixed(3)} · confidence ${(item.confidence * 100).toFixed(0)}%`,
173
+ ),
115
174
  ...(result.scopeWarning ? [result.scopeWarning] : []),
116
175
  ].join("\n");
117
176
  }
118
177
 
119
- export async function runBenchmarksCommand(action: string | undefined, rest: string[], deps: CliDependencies, usage: () => number): Promise<number> {
178
+ export async function runBenchmarksCommand(
179
+ action: string | undefined,
180
+ rest: string[],
181
+ deps: CliDependencies,
182
+ usage: () => number,
183
+ ): Promise<number> {
120
184
  const parsed = parseBenchmarkArgs(action, rest);
121
185
  if (!parsed) return usage();
122
186
  try {
@@ -127,9 +191,10 @@ export async function runBenchmarksCommand(action: string | undefined, rest: str
127
191
  const result = await deps.client.call("models.rank", parsed.recommendation!);
128
192
  deps.stdout(parsed.json ? JSON.stringify(result) : formatModelRanking(result));
129
193
  } else {
130
- const result = parsed.action === "refresh"
131
- ? await deps.client.call("benchmark.refresh", { force: parsed.force })
132
- : await deps.client.call("benchmark.status", {});
194
+ const result =
195
+ parsed.action === "refresh"
196
+ ? await deps.client.call("benchmark.refresh", { force: parsed.force })
197
+ : await deps.client.call("benchmark.status", {});
133
198
  deps.stdout(parsed.json ? JSON.stringify(result) : formatBenchmarkStatus(result));
134
199
  }
135
200
  return 0;
@@ -1,6 +1,6 @@
1
1
  import type { CompactionDurationEstimate } from "../domain/context-telemetry.ts";
2
- import { callAndPrint, type CliDependencies } from "./support.ts";
3
2
  import { parseJsonOnlyArgs } from "./router.ts";
3
+ import { type CliDependencies, callAndPrint } from "./support.ts";
4
4
 
5
5
  export function formatCompactionEstimate(estimate: CompactionDurationEstimate): string {
6
6
  if (estimate.confidence === "cold-start" || estimate.ms === null) {
@@ -9,7 +9,12 @@ export function formatCompactionEstimate(estimate: CompactionDurationEstimate):
9
9
  return `Compaction duration: ~${estimate.ms.toLocaleString()}ms learned from ${estimate.sampleSize.toLocaleString()} sample(s)`;
10
10
  }
11
11
 
12
- export async function runCompactionCommand(action: string | undefined, rest: string[], deps: CliDependencies, usage: () => number): Promise<number> {
12
+ export async function runCompactionCommand(
13
+ action: string | undefined,
14
+ rest: string[],
15
+ deps: CliDependencies,
16
+ usage: () => number,
17
+ ): Promise<number> {
13
18
  if (action !== "estimate") return usage();
14
19
  const parsed = parseJsonOnlyArgs(rest);
15
20
  if (!parsed) return usage();
@@ -8,7 +8,10 @@ function parseContextArgs(args: string[]): { input: { since?: number; until?: nu
8
8
  let json = false;
9
9
  for (let index = 0; index < args.length; index += 1) {
10
10
  const argument = args[index];
11
- if (argument === "--json") { json = true; continue; }
11
+ if (argument === "--json") {
12
+ json = true;
13
+ continue;
14
+ }
12
15
  if (argument !== "--since" && argument !== "--until") return null;
13
16
  const raw = args[++index];
14
17
  const value = raw === undefined ? Number.NaN : Number(raw);
@@ -35,7 +38,12 @@ export function formatContextAssessment(summary: ContextAssessment): string {
35
38
  ].join("\n");
36
39
  }
37
40
 
38
- export async function runContextCommand(action: string | undefined, rest: string[], deps: CliDependencies, usage: () => number): Promise<number> {
41
+ export async function runContextCommand(
42
+ action: string | undefined,
43
+ rest: string[],
44
+ deps: CliDependencies,
45
+ usage: () => number,
46
+ ): Promise<number> {
39
47
  const parsed = parseContextArgs([...(action === undefined ? [] : [action]), ...rest]);
40
48
  if (!parsed) return usage();
41
49
  try {
@@ -1,7 +1,13 @@
1
- import { CLI_METRICS_HUMAN_MAX_ROWS, MAX_QUERY_LIMIT, MAX_USAGE_BUCKETS, METRIC_BATCH_MAX_OBSERVATIONS, USAGE_MAX_DISTINCT_SCOPES } from "../constants.ts";
1
+ import {
2
+ CLI_METRICS_HUMAN_MAX_ROWS,
3
+ MAX_QUERY_LIMIT,
4
+ MAX_USAGE_BUCKETS,
5
+ METRIC_BATCH_MAX_OBSERVATIONS,
6
+ USAGE_MAX_DISTINCT_SCOPES,
7
+ } from "../constants.ts";
2
8
  import { METRIC_UNITS, type MetricObservation, type MetricQuery, type MetricUnit, type StoredMetricObservation } from "../domain/metric.ts";
3
9
  import type { TaskCostSummary } from "../domain/task-cost.ts";
4
- import { callAndPrint, humanField, type CliDependencies } from "./support.ts";
10
+ import { type CliDependencies, callAndPrint, humanField } from "./support.ts";
5
11
 
6
12
  export const METRICS_USAGE_LINES = [
7
13
  " metrics record --source <s> --scope <s> --metric <s> --value <number|null> --unit <unit> [--observed-at <ms>] [--attributes <json>] [--json]",
@@ -13,7 +19,10 @@ export const METRICS_USAGE_LINES = [
13
19
  " metrics cost-by-task --since <ms> --until <ms> [--json]",
14
20
  ];
15
21
 
16
- interface MetricsRecordArgs { input: MetricObservation; json: boolean }
22
+ interface MetricsRecordArgs {
23
+ input: MetricObservation;
24
+ json: boolean;
25
+ }
17
26
 
18
27
  function parseMetricsRecordArgs(args: string[]): MetricsRecordArgs | null {
19
28
  let json = false;
@@ -26,7 +35,10 @@ function parseMetricsRecordArgs(args: string[]): MetricsRecordArgs | null {
26
35
  let attributes: Record<string, unknown> | undefined;
27
36
  for (let index = 0; index < args.length; index += 1) {
28
37
  const argument = args[index];
29
- if (argument === "--json") { json = true; continue; }
38
+ if (argument === "--json") {
39
+ json = true;
40
+ continue;
41
+ }
30
42
  if (!["--source", "--scope", "--metric", "--value", "--unit", "--observed-at", "--attributes"].includes(argument ?? "")) return null;
31
43
  const raw = args[++index];
32
44
  if (raw === undefined || raw.length === 0) return null;
@@ -61,21 +73,31 @@ function parseMetricsRecordArgs(args: string[]): MetricsRecordArgs | null {
61
73
  return {
62
74
  json,
63
75
  input: {
64
- source, scope, metric, value, unit,
76
+ source,
77
+ scope,
78
+ metric,
79
+ value,
80
+ unit,
65
81
  observedAt: observedAt ?? Date.now(),
66
82
  ...(attributes ? { attributes } : {}),
67
83
  },
68
84
  };
69
85
  }
70
86
 
71
- interface MetricsRecordBatchArgs { input: { observations: MetricObservation[] }; json: boolean }
87
+ interface MetricsRecordBatchArgs {
88
+ input: { observations: MetricObservation[] };
89
+ json: boolean;
90
+ }
72
91
 
73
92
  function parseMetricsRecordBatchArgs(args: string[]): MetricsRecordBatchArgs | null {
74
93
  let json = false;
75
94
  let observations: unknown;
76
95
  for (let index = 0; index < args.length; index += 1) {
77
96
  const argument = args[index];
78
- if (argument === "--json") { json = true; continue; }
97
+ if (argument === "--json") {
98
+ json = true;
99
+ continue;
100
+ }
79
101
  if (argument !== "--observations") return null;
80
102
  const raw = args[++index];
81
103
  if (raw === undefined || raw.length === 0) return null;
@@ -89,14 +111,20 @@ function parseMetricsRecordBatchArgs(args: string[]): MetricsRecordBatchArgs | n
89
111
  return { input: { observations: observations as MetricObservation[] }, json };
90
112
  }
91
113
 
92
- interface MetricsQueryArgs { input: MetricQuery; json: boolean }
114
+ interface MetricsQueryArgs {
115
+ input: MetricQuery;
116
+ json: boolean;
117
+ }
93
118
 
94
119
  function parseMetricsQueryArgs(args: string[]): MetricsQueryArgs | null {
95
120
  let json = false;
96
121
  const input: MetricQuery = {};
97
122
  for (let index = 0; index < args.length; index += 1) {
98
123
  const argument = args[index];
99
- if (argument === "--json") { json = true; continue; }
124
+ if (argument === "--json") {
125
+ json = true;
126
+ continue;
127
+ }
100
128
  if (!["--source", "--scope", "--metric", "--since", "--until", "--limit", "--order"].includes(argument ?? "")) return null;
101
129
  const raw = args[++index];
102
130
  if (raw === undefined || raw.length === 0) return null;
@@ -121,7 +149,10 @@ function parseMetricsQueryArgs(args: string[]): MetricsQueryArgs | null {
121
149
  return { input, json };
122
150
  }
123
151
 
124
- interface MetricsDistinctScopesArgs { input: { source: string; since: number; until: number; limit?: number }; json: boolean }
152
+ interface MetricsDistinctScopesArgs {
153
+ input: { source: string; since: number; until: number; limit?: number };
154
+ json: boolean;
155
+ }
125
156
 
126
157
  function parseMetricsDistinctScopesArgs(args: string[]): MetricsDistinctScopesArgs | null {
127
158
  let json = false;
@@ -131,11 +162,17 @@ function parseMetricsDistinctScopesArgs(args: string[]): MetricsDistinctScopesAr
131
162
  let limit: number | undefined;
132
163
  for (let index = 0; index < args.length; index += 1) {
133
164
  const argument = args[index];
134
- if (argument === "--json") { json = true; continue; }
165
+ if (argument === "--json") {
166
+ json = true;
167
+ continue;
168
+ }
135
169
  if (!["--source", "--since", "--until", "--limit"].includes(argument ?? "")) return null;
136
170
  const raw = args[++index];
137
171
  if (raw === undefined || raw.length === 0) return null;
138
- if (argument === "--source") { source = raw; continue; }
172
+ if (argument === "--source") {
173
+ source = raw;
174
+ continue;
175
+ }
139
176
  const parsed = Number(raw);
140
177
  if (!Number.isSafeInteger(parsed) || parsed < 0) return null;
141
178
  if (argument === "--since") since = parsed;
@@ -149,7 +186,10 @@ function parseMetricsDistinctScopesArgs(args: string[]): MetricsDistinctScopesAr
149
186
  return { input: { source, since, until, ...(limit === undefined ? {} : { limit }) }, json };
150
187
  }
151
188
 
152
- interface MetricsUsageSeriesArgs { input: { source: string; since: number; until: number; bucketSizeMs: number; bucketCount: number; scopeLimit?: number }; json: boolean }
189
+ interface MetricsUsageSeriesArgs {
190
+ input: { source: string; since: number; until: number; bucketSizeMs: number; bucketCount: number; scopeLimit?: number };
191
+ json: boolean;
192
+ }
153
193
 
154
194
  function parseMetricsUsageSeriesArgs(args: string[]): MetricsUsageSeriesArgs | null {
155
195
  let json = false;
@@ -161,24 +201,48 @@ function parseMetricsUsageSeriesArgs(args: string[]): MetricsUsageSeriesArgs | n
161
201
  let scopeLimit: number | undefined;
162
202
  for (let index = 0; index < args.length; index += 1) {
163
203
  const argument = args[index];
164
- if (argument === "--json") { json = true; continue; }
165
- if (!(["--source", "--since", "--until", "--bucket-size-ms", "--bucket-count", "--scope-limit"].includes(argument ?? ""))) return null;
204
+ if (argument === "--json") {
205
+ json = true;
206
+ continue;
207
+ }
208
+ if (!["--source", "--since", "--until", "--bucket-size-ms", "--bucket-count", "--scope-limit"].includes(argument ?? "")) return null;
166
209
  const raw = args[++index];
167
210
  if (raw === undefined || raw.length === 0) return null;
168
- if (argument === "--source") { source = raw; continue; }
211
+ if (argument === "--source") {
212
+ source = raw;
213
+ continue;
214
+ }
169
215
  const parsed = Number(raw);
170
216
  if (!Number.isSafeInteger(parsed) || parsed < 0) return null;
171
217
  if (argument === "--since") since = parsed;
172
218
  else if (argument === "--until") until = parsed;
173
- else if (argument === "--bucket-size-ms") { if (parsed < 1) return null; bucketSizeMs = parsed; }
174
- else if (argument === "--bucket-count") { if (parsed < 1 || parsed > MAX_USAGE_BUCKETS) return null; bucketCount = parsed; }
175
- else { if (parsed < 1 || parsed > USAGE_MAX_DISTINCT_SCOPES) return null; scopeLimit = parsed; }
219
+ else if (argument === "--bucket-size-ms") {
220
+ if (parsed < 1) return null;
221
+ bucketSizeMs = parsed;
222
+ } else if (argument === "--bucket-count") {
223
+ if (parsed < 1 || parsed > MAX_USAGE_BUCKETS) return null;
224
+ bucketCount = parsed;
225
+ } else {
226
+ if (parsed < 1 || parsed > USAGE_MAX_DISTINCT_SCOPES) return null;
227
+ scopeLimit = parsed;
228
+ }
176
229
  }
177
- if (source === undefined || since === undefined || until === undefined || until < since || bucketSizeMs === undefined || bucketCount === undefined) return null;
230
+ if (
231
+ source === undefined ||
232
+ since === undefined ||
233
+ until === undefined ||
234
+ until < since ||
235
+ bucketSizeMs === undefined ||
236
+ bucketCount === undefined
237
+ )
238
+ return null;
178
239
  return { input: { source, since, until, bucketSizeMs, bucketCount, ...(scopeLimit === undefined ? {} : { scopeLimit }) }, json };
179
240
  }
180
241
 
181
- interface CostByTaskArgs { input: { since: number; until: number }; json: boolean }
242
+ interface CostByTaskArgs {
243
+ input: { since: number; until: number };
244
+ json: boolean;
245
+ }
182
246
 
183
247
  function parseCostByTaskArgs(args: string[]): CostByTaskArgs | null {
184
248
  let json = false;
@@ -186,7 +250,10 @@ function parseCostByTaskArgs(args: string[]): CostByTaskArgs | null {
186
250
  let until: number | undefined;
187
251
  for (let index = 0; index < args.length; index += 1) {
188
252
  const argument = args[index];
189
- if (argument === "--json") { json = true; continue; }
253
+ if (argument === "--json") {
254
+ json = true;
255
+ continue;
256
+ }
190
257
  if (!["--since", "--until"].includes(argument ?? "")) return null;
191
258
  const raw = args[++index];
192
259
  const parsed = Number(raw);
@@ -198,7 +265,10 @@ function parseCostByTaskArgs(args: string[]): CostByTaskArgs | null {
198
265
  return { input: { since, until }, json };
199
266
  }
200
267
 
201
- interface MetricsPruneArgs { input: { before: number; force?: boolean }; json: boolean }
268
+ interface MetricsPruneArgs {
269
+ input: { before: number; force?: boolean };
270
+ json: boolean;
271
+ }
202
272
 
203
273
  function parseMetricsPruneArgs(args: string[]): MetricsPruneArgs | null {
204
274
  let json = false;
@@ -206,8 +276,14 @@ function parseMetricsPruneArgs(args: string[]): MetricsPruneArgs | null {
206
276
  let before: number | undefined;
207
277
  for (let index = 0; index < args.length; index += 1) {
208
278
  const argument = args[index];
209
- if (argument === "--json") { json = true; continue; }
210
- if (argument === "--force") { force = true; continue; }
279
+ if (argument === "--json") {
280
+ json = true;
281
+ continue;
282
+ }
283
+ if (argument === "--force") {
284
+ force = true;
285
+ continue;
286
+ }
211
287
  if (argument !== "--before") return null;
212
288
  const raw = args[++index];
213
289
  const parsed = Number(raw);
@@ -223,7 +299,10 @@ export function formatMetricsQuery(rows: StoredMetricObservation[]): string {
223
299
  const shown = rows.slice(0, CLI_METRICS_HUMAN_MAX_ROWS);
224
300
  const lines = [
225
301
  `Metrics: ${rows.length.toLocaleString()} observation(s)${rows.length > shown.length ? ` (showing first ${shown.length})` : ""}`,
226
- ...shown.map((row) => `- ${humanField(row.source)}/${humanField(row.scope)}/${humanField(row.metric)} = ${row.value === null ? "null" : row.value} ${row.unit} @ ${new Date(row.observedAt).toISOString()}`),
302
+ ...shown.map(
303
+ (row) =>
304
+ `- ${humanField(row.source)}/${humanField(row.scope)}/${humanField(row.metric)} = ${row.value === null ? "null" : row.value} ${row.unit} @ ${new Date(row.observedAt).toISOString()}`,
305
+ ),
227
306
  ];
228
307
  return lines.join("\n");
229
308
  }
@@ -233,10 +312,14 @@ export function formatMetricsDistinctScopes(scopes: string[]): string {
233
312
  return [`Scopes: ${scopes.length.toLocaleString()}`, ...scopes.map((scope) => `- ${humanField(scope)}`)].join("\n");
234
313
  }
235
314
 
236
- export function formatMetricsUsageSeries(result: { rows: Array<{ scope: string; metric: string; bucketIndex: number; sum: number }>; truncated: boolean }): string {
315
+ export function formatMetricsUsageSeries(result: {
316
+ rows: Array<{ scope: string; metric: string; bucketIndex: number; sum: number }>;
317
+ truncated: boolean;
318
+ }): string {
237
319
  if (result.rows.length === 0) return `Usage series: no data${result.truncated ? " (scope limit reached)" : ""}`;
238
320
  const lines = [`Usage series: ${result.rows.length.toLocaleString()} bucket(s)${result.truncated ? " (scope limit reached)" : ""}`];
239
- for (const row of result.rows) lines.push(`- ${humanField(row.scope)}/${humanField(row.metric)} bucket ${row.bucketIndex}: ${row.sum.toLocaleString()}`);
321
+ for (const row of result.rows)
322
+ lines.push(`- ${humanField(row.scope)}/${humanField(row.metric)} bucket ${row.bucketIndex}: ${row.sum.toLocaleString()}`);
240
323
  return lines.join("\n");
241
324
  }
242
325
 
@@ -249,14 +332,22 @@ export function formatCostByTask(summary: TaskCostSummary): string {
249
332
  `Cost by task: ${summary.entries.length.toLocaleString()} task(s)${summary.truncated ? " (query limit reached; totals are a lower bound)" : ""}`,
250
333
  ...summary.entries.flatMap((entry) => [
251
334
  `- ${humanField(entry.taskId)}: ${formatUsdAmount(entry.costUsd)} · ↑${entry.inputTokens.toLocaleString()} ↓${entry.outputTokens.toLocaleString()} R${entry.cacheReadTokens.toLocaleString()} W${entry.cacheWriteTokens.toLocaleString()}`,
252
- ...entry.byModel.map((model) => ` · ${humanField(model.provider)}/${humanField(model.model)} (${humanField(model.thinking)}): ${formatUsdAmount(model.costUsd)} · ↑${model.inputTokens.toLocaleString()} ↓${model.outputTokens.toLocaleString()} R${model.cacheReadTokens.toLocaleString()} W${model.cacheWriteTokens.toLocaleString()}`),
335
+ ...entry.byModel.map(
336
+ (model) =>
337
+ ` · ${humanField(model.provider)}/${humanField(model.model)} (${humanField(model.thinking)}): ${formatUsdAmount(model.costUsd)} · ↑${model.inputTokens.toLocaleString()} ↓${model.outputTokens.toLocaleString()} R${model.cacheReadTokens.toLocaleString()} W${model.cacheWriteTokens.toLocaleString()}`,
338
+ ),
253
339
  ]),
254
340
  `Unattributed spend (no task was focused): ${formatUsdAmount(summary.unattributedCostUsd)}`,
255
341
  ];
256
342
  return lines.join("\n");
257
343
  }
258
344
 
259
- export async function runMetricsCommand(action: string | undefined, rest: string[], deps: CliDependencies, usage: () => number): Promise<number> {
345
+ export async function runMetricsCommand(
346
+ action: string | undefined,
347
+ rest: string[],
348
+ deps: CliDependencies,
349
+ usage: () => number,
350
+ ): Promise<number> {
260
351
  if (action === "record") {
261
352
  const parsed = parseMetricsRecordArgs(rest);
262
353
  if (!parsed) return usage();
@@ -275,7 +366,13 @@ export async function runMetricsCommand(action: string | undefined, rest: string
275
366
  if (action === "prune") {
276
367
  const parsed = parseMetricsPruneArgs(rest);
277
368
  if (!parsed) return usage();
278
- return callAndPrint(deps, "metrics.prune", parsed.input, parsed.json, (result) => `Pruned ${result.deleted.toLocaleString()} observation(s)`);
369
+ return callAndPrint(
370
+ deps,
371
+ "metrics.prune",
372
+ parsed.input,
373
+ parsed.json,
374
+ (result) => `Pruned ${result.deleted.toLocaleString()} observation(s)`,
375
+ );
279
376
  }
280
377
  if (action === "distinct-scopes") {
281
378
  const parsed = parseMetricsDistinctScopesArgs(rest);
@@ -22,7 +22,12 @@ function parseOpArgs(args: string[]): { operation: OperationName; input: Record<
22
22
  return { operation: operation as OperationName, input };
23
23
  }
24
24
 
25
- export async function runOpCommand(action: string | undefined, rest: string[], deps: CliDependencies, usage: () => number): Promise<number> {
25
+ export async function runOpCommand(
26
+ action: string | undefined,
27
+ rest: string[],
28
+ deps: CliDependencies,
29
+ usage: () => number,
30
+ ): Promise<number> {
26
31
  const parsed = parseOpArgs(action === undefined ? [] : [action, ...rest]);
27
32
  if (!parsed) return usage();
28
33
  try {
@@ -6,7 +6,11 @@ export function parseCandidate(raw: string): ModelCandidate | null {
6
6
  const separator = raw.indexOf("/");
7
7
  const thinkingSeparator = raw.lastIndexOf("@");
8
8
  if (separator <= 0 || thinkingSeparator <= separator + 1 || thinkingSeparator === raw.length - 1) return null;
9
- return { provider: raw.slice(0, separator), model: raw.slice(separator + 1, thinkingSeparator), thinking: raw.slice(thinkingSeparator + 1) };
9
+ return {
10
+ provider: raw.slice(0, separator),
11
+ model: raw.slice(separator + 1, thinkingSeparator),
12
+ thinking: raw.slice(thinkingSeparator + 1),
13
+ };
10
14
  }
11
15
 
12
16
  export function parseRoute(raw: string | undefined): Route | null {