@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.
- package/package.json +4 -3
- package/src/adapters/artificial-analysis-direct-source.ts +42 -11
- package/src/adapters/lmarena-hf-source.ts +37 -15
- package/src/adapters/metric-benchmark-store.ts +29 -18
- package/src/adapters/openrouter-benchmark-source.ts +75 -19
- package/src/adapters/openrouter-design-arena-source.ts +36 -19
- package/src/adapters/sqlite-metric-store.ts +48 -25
- package/src/adapters/sqlite-session-identity-store.ts +13 -7
- package/src/cli-commands/benchmarks.ts +87 -22
- package/src/cli-commands/compaction.ts +7 -2
- package/src/cli-commands/context.ts +10 -2
- package/src/cli-commands/metrics.ts +128 -31
- package/src/cli-commands/op.ts +6 -1
- package/src/cli-commands/route-args.ts +5 -1
- package/src/cli-commands/router.ts +61 -18
- package/src/cli-commands/service-daemon.ts +31 -13
- package/src/cli-commands/session.ts +15 -4
- package/src/cli-commands/support.ts +1 -1
- package/src/cli.ts +30 -23
- package/src/client.ts +1 -1
- package/src/constants.ts +1 -1
- package/src/daemon.ts +44 -24
- package/src/domain/benchmark.ts +72 -40
- package/src/domain/codex-recovery.ts +34 -25
- package/src/domain/context-hub.ts +35 -26
- package/src/domain/context-telemetry.ts +106 -35
- package/src/domain/metric.ts +11 -11
- package/src/domain/model-observation.ts +139 -55
- package/src/domain/model-ranking-service.ts +13 -3
- package/src/domain/model-ranking.ts +126 -60
- package/src/domain/task-cost.ts +52 -11
- package/src/domain/task-focus.ts +11 -8
- package/src/domain/usage.ts +2 -2
- package/src/index.ts +69 -69
- package/src/log.ts +7 -2
- package/src/operations/benchmark-operations.ts +1 -1
- package/src/operations/context-operations.ts +15 -6
- package/src/operations/metrics-operations.ts +63 -28
- package/src/operations/model-ranking-operations.ts +9 -2
- package/src/operations/router-operations.ts +8 -4
- package/src/operations/session-identity-operations.ts +1 -1
- package/src/operations/session-scope.ts +5 -3
- package/src/policy.ts +22 -17
- package/src/ports/benchmark-controller.ts +1 -5
- package/src/ports/metric-store.ts +1 -1
- package/src/providers/anthropic-contracts.ts +13 -3
- package/src/providers/codex-contracts.ts +60 -52
- package/src/providers/codex.ts +16 -19
- package/src/providers/google-vertex-budget-contracts.ts +24 -14
- package/src/providers/google-vertex-budget.ts +15 -13
- package/src/providers/google-vertex-contracts.ts +36 -24
- package/src/providers/openrouter-contracts.ts +49 -51
- package/src/providers/openrouter.ts +21 -15
- package/src/providers/telemetry-sources.ts +13 -10
- package/src/router.ts +92 -43
- package/src/service.ts +93 -32
- package/src/session-identity-service.ts +10 -2
- package/src/state.ts +4 -10
- package/src/vehicle-registration.ts +154 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { BudgetWindow } from "../policy.ts";
|
|
2
|
-
import type { MetricObservation } from "../domain/metric.ts";
|
|
3
|
-
import type { GoogleVertexMetricSource } from "./google-vertex-contracts.ts";
|
|
4
1
|
import {
|
|
5
2
|
GOOGLE_VERTEX_BUDGET_CONFIDENCE,
|
|
6
3
|
GOOGLE_VERTEX_BUDGET_DISPLAY_NAME_MAX_CHARACTERS,
|
|
7
4
|
MILLISECONDS_PER_SECOND,
|
|
8
5
|
} from "../constants.ts";
|
|
6
|
+
import type { MetricObservation } from "../domain/metric.ts";
|
|
7
|
+
import type { BudgetWindow } from "../policy.ts";
|
|
8
|
+
import type { GoogleVertexMetricSource } from "./google-vertex-contracts.ts";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Cloud Billing's programmatic budget notification schema (Pub/Sub attributes + base64 JSON data
|
|
@@ -61,7 +61,8 @@ function requiredTimestamp(value: unknown, name: string): number {
|
|
|
61
61
|
|
|
62
62
|
function optionalFraction(value: unknown, name: string): number | undefined {
|
|
63
63
|
if (value === undefined) return undefined;
|
|
64
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
|
|
64
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
|
|
65
|
+
throw new Error(`Google Vertex budget notification schema changed: ${name}`);
|
|
65
66
|
return value;
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -77,11 +78,12 @@ export function parseGoogleVertexBudgetNotification(
|
|
|
77
78
|
attributes: { billingAccountId?: unknown; budgetId?: unknown; schemaVersion?: unknown },
|
|
78
79
|
publishedAt: number,
|
|
79
80
|
): GoogleVertexBudgetNotification {
|
|
80
|
-
if (typeof data !== "object" || data === null || Array.isArray(data))
|
|
81
|
+
if (typeof data !== "object" || data === null || Array.isArray(data))
|
|
82
|
+
throw new Error("Google Vertex budget notification schema changed: data");
|
|
81
83
|
const input = data as Record<string, unknown>;
|
|
82
84
|
if (!Number.isFinite(publishedAt) || publishedAt < 0) throw new Error("Google Vertex budget notification schema changed: publishTime");
|
|
83
85
|
|
|
84
|
-
const budgetAmountType = requiredString(input
|
|
86
|
+
const budgetAmountType = requiredString(input.budgetAmountType, "budgetAmountType");
|
|
85
87
|
if (!BUDGET_AMOUNT_TYPES.includes(budgetAmountType as GoogleVertexBudgetAmountType)) {
|
|
86
88
|
throw new Error("Google Vertex budget notification schema changed: budgetAmountType");
|
|
87
89
|
}
|
|
@@ -90,14 +92,14 @@ export function parseGoogleVertexBudgetNotification(
|
|
|
90
92
|
billingAccountId: requiredString(attributes.billingAccountId, "billingAccountId"),
|
|
91
93
|
budgetId: requiredString(attributes.budgetId, "budgetId"),
|
|
92
94
|
schemaVersion: requiredString(attributes.schemaVersion, "schemaVersion"),
|
|
93
|
-
budgetDisplayName: requiredString(input
|
|
94
|
-
costAmount: requiredFiniteNumber(input
|
|
95
|
-
costIntervalStart: requiredTimestamp(input
|
|
96
|
-
budgetAmount: requiredFiniteNumber(input
|
|
95
|
+
budgetDisplayName: requiredString(input.budgetDisplayName, "budgetDisplayName", GOOGLE_VERTEX_BUDGET_DISPLAY_NAME_MAX_CHARACTERS),
|
|
96
|
+
costAmount: requiredFiniteNumber(input.costAmount, "costAmount"),
|
|
97
|
+
costIntervalStart: requiredTimestamp(input.costIntervalStart, "costIntervalStart"),
|
|
98
|
+
budgetAmount: requiredFiniteNumber(input.budgetAmount, "budgetAmount"),
|
|
97
99
|
budgetAmountType: budgetAmountType as GoogleVertexBudgetAmountType,
|
|
98
|
-
currencyCode: requiredString(input
|
|
99
|
-
alertThresholdExceeded: optionalFraction(input
|
|
100
|
-
forecastThresholdExceeded: optionalFraction(input
|
|
100
|
+
currencyCode: requiredString(input.currencyCode, "currencyCode", 8),
|
|
101
|
+
alertThresholdExceeded: optionalFraction(input.alertThresholdExceeded, "alertThresholdExceeded"),
|
|
102
|
+
forecastThresholdExceeded: optionalFraction(input.forecastThresholdExceeded, "forecastThresholdExceeded"),
|
|
101
103
|
publishedAt,
|
|
102
104
|
};
|
|
103
105
|
}
|
|
@@ -127,7 +129,15 @@ export function googleVertexBudgetMetrics(
|
|
|
127
129
|
{ source, scope: "budget", metric: "cap", value: notification.budgetAmount, unit: "usd", observedAt, attributes },
|
|
128
130
|
];
|
|
129
131
|
if (notification.budgetAmount > 0) {
|
|
130
|
-
metrics.push({
|
|
132
|
+
metrics.push({
|
|
133
|
+
source,
|
|
134
|
+
scope: "budget",
|
|
135
|
+
metric: "spend-fraction",
|
|
136
|
+
value: notification.costAmount / notification.budgetAmount,
|
|
137
|
+
unit: "ratio",
|
|
138
|
+
observedAt,
|
|
139
|
+
attributes,
|
|
140
|
+
});
|
|
131
141
|
}
|
|
132
142
|
return metrics;
|
|
133
143
|
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { GOOGLE_VERTEX_BUDGET_MAX_MESSAGES_PER_PULL } from "../constants.ts";
|
|
2
2
|
import type { MetricObservation } from "../domain/metric.ts";
|
|
3
|
+
import type { BudgetWindow } from "../policy.ts";
|
|
4
|
+
import type { GoogleAdcTokenProvider } from "./google-adc-auth.ts";
|
|
3
5
|
import {
|
|
6
|
+
type GoogleVertexBudgetNotification,
|
|
4
7
|
googleVertexBudgetMetrics,
|
|
5
8
|
googleVertexBudgetWindow,
|
|
6
9
|
parseGoogleVertexBudgetNotification,
|
|
7
|
-
type GoogleVertexBudgetNotification,
|
|
8
10
|
} from "./google-vertex-budget-contracts.ts";
|
|
9
11
|
import type { GoogleVertexMetricSource } from "./google-vertex-contracts.ts";
|
|
10
|
-
import type { GoogleAdcTokenProvider } from "./google-adc-auth.ts";
|
|
11
|
-
import { GOOGLE_VERTEX_BUDGET_MAX_MESSAGES_PER_PULL } from "../constants.ts";
|
|
12
12
|
|
|
13
13
|
export {
|
|
14
|
+
type GoogleVertexBudgetAmountType,
|
|
15
|
+
type GoogleVertexBudgetNotification,
|
|
14
16
|
googleVertexBudgetMetrics,
|
|
15
17
|
googleVertexBudgetWindow,
|
|
16
18
|
parseGoogleVertexBudgetNotification,
|
|
17
|
-
type GoogleVertexBudgetAmountType,
|
|
18
|
-
type GoogleVertexBudgetNotification,
|
|
19
19
|
} from "./google-vertex-budget-contracts.ts";
|
|
20
20
|
|
|
21
21
|
const PUBSUB_BASE_URL = "https://pubsub.googleapis.com/v1";
|
|
@@ -67,7 +67,7 @@ export class GoogleVertexBudgetTelemetryAdapter {
|
|
|
67
67
|
async pull(observedAt = Date.now()): Promise<GoogleVertexBudgetSnapshot | null> {
|
|
68
68
|
const token = await this.tokenProvider();
|
|
69
69
|
const pullResponse = await this.request(":pull", token, { maxMessages: GOOGLE_VERTEX_BUDGET_MAX_MESSAGES_PER_PULL });
|
|
70
|
-
const body = await pullResponse.json() as { receivedMessages?: RawPubSubMessage[] };
|
|
70
|
+
const body = (await pullResponse.json()) as { receivedMessages?: RawPubSubMessage[] };
|
|
71
71
|
const received = Array.isArray(body.receivedMessages) ? body.receivedMessages : [];
|
|
72
72
|
if (received.length === 0) return null;
|
|
73
73
|
|
|
@@ -85,7 +85,7 @@ export class GoogleVertexBudgetTelemetryAdapter {
|
|
|
85
85
|
if (parseFailure) throw parseFailure;
|
|
86
86
|
if (parsed.length === 0) return null;
|
|
87
87
|
|
|
88
|
-
const freshest = parsed.reduce((latest, candidate) => candidate.publishedAt > latest.publishedAt ? candidate : latest);
|
|
88
|
+
const freshest = parsed.reduce((latest, candidate) => (candidate.publishedAt > latest.publishedAt ? candidate : latest));
|
|
89
89
|
return {
|
|
90
90
|
notification: freshest,
|
|
91
91
|
metrics: googleVertexBudgetMetrics(freshest, observedAt, this.source),
|
|
@@ -116,11 +116,13 @@ export class GoogleVertexBudgetTelemetryAdapter {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
private async request(action: ":pull" | ":acknowledge", token: string, body: Record<string, unknown>): Promise<Response> {
|
|
119
|
-
const response = await this.transport(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
const response = await this.transport(
|
|
120
|
+
new Request(`${PUBSUB_BASE_URL}/${this.subscription}${action}`, {
|
|
121
|
+
method: "POST",
|
|
122
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
123
|
+
body: JSON.stringify(body),
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
124
126
|
if (!response.ok) throw new Error(`Google Cloud Pub/Sub ${action.slice(1)} failed with HTTP ${response.status}`);
|
|
125
127
|
return response;
|
|
126
128
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { MetricObservation } from "../domain/metric.ts";
|
|
2
1
|
import { MILLISECONDS_PER_MINUTE, MILLISECONDS_PER_SECOND } from "../constants.ts";
|
|
2
|
+
import type { MetricObservation } from "../domain/metric.ts";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Google Vertex AI has no documented per-response rate-limit or remaining-quota header, and no
|
|
@@ -15,13 +15,7 @@ import { MILLISECONDS_PER_MINUTE, MILLISECONDS_PER_SECOND } from "../constants.t
|
|
|
15
15
|
* `errorMessage` string Pi already exposes for every provider (see classifyCodexFailure for the
|
|
16
16
|
* established pattern this mirrors).
|
|
17
17
|
*/
|
|
18
|
-
export type GoogleVertexFailureKind =
|
|
19
|
-
| "quota"
|
|
20
|
-
| "authentication"
|
|
21
|
-
| "invalid-request"
|
|
22
|
-
| "overload"
|
|
23
|
-
| "transport"
|
|
24
|
-
| "unknown";
|
|
18
|
+
export type GoogleVertexFailureKind = "quota" | "authentication" | "invalid-request" | "overload" | "transport" | "unknown";
|
|
25
19
|
|
|
26
20
|
export interface GoogleVertexFailure {
|
|
27
21
|
kind: GoogleVertexFailureKind;
|
|
@@ -72,12 +66,24 @@ export function classifyGoogleVertexFailure(value: unknown, metadata: GoogleVert
|
|
|
72
66
|
return { kind: "quota", transient: true, status: "RESOURCE_EXHAUSTED", ...base };
|
|
73
67
|
}
|
|
74
68
|
if (matches(evidence, ["unauthenticated", "permission_denied"]) || metadata.status === 401 || metadata.status === 403) {
|
|
75
|
-
return {
|
|
69
|
+
return {
|
|
70
|
+
kind: "authentication",
|
|
71
|
+
transient: false,
|
|
72
|
+
status: matches(evidence, ["unauthenticated"]) ? "UNAUTHENTICATED" : "PERMISSION_DENIED",
|
|
73
|
+
...base,
|
|
74
|
+
};
|
|
76
75
|
}
|
|
77
|
-
if (
|
|
76
|
+
if (
|
|
77
|
+
matches(evidence, ["invalid_argument", "failed_precondition", "out_of_range"]) ||
|
|
78
|
+
metadata.status === 400 ||
|
|
79
|
+
metadata.status === 422
|
|
80
|
+
) {
|
|
78
81
|
return { kind: "invalid-request", transient: false, status: "INVALID_ARGUMENT", ...base };
|
|
79
82
|
}
|
|
80
|
-
if (
|
|
83
|
+
if (
|
|
84
|
+
matches(evidence, ["unavailable", "internal", "aborted"]) ||
|
|
85
|
+
(metadata.status !== undefined && metadata.status >= 500 && metadata.status <= 599)
|
|
86
|
+
) {
|
|
81
87
|
return { kind: "overload", transient: true, status: "UNAVAILABLE", ...base };
|
|
82
88
|
}
|
|
83
89
|
if (matches(evidence, ["deadline_exceeded", "timeout", "timed out", "network", "connection", "fetch failed", "cancelled"])) {
|
|
@@ -99,18 +105,24 @@ export function classifyGoogleVertexFailure(value: unknown, metadata: GoogleVert
|
|
|
99
105
|
export type GoogleVertexMetricSource = "google-vertex" | "anthropic-vertex";
|
|
100
106
|
|
|
101
107
|
/** A bounded failure-count observation; never a fabricated remaining-budget fraction. */
|
|
102
|
-
export function googleVertexFailureMetrics(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
export function googleVertexFailureMetrics(
|
|
109
|
+
failure: GoogleVertexFailure,
|
|
110
|
+
observedAt: number,
|
|
111
|
+
source: GoogleVertexMetricSource = "google-vertex",
|
|
112
|
+
): MetricObservation[] {
|
|
113
|
+
return [
|
|
114
|
+
{
|
|
115
|
+
source,
|
|
116
|
+
scope: "failure",
|
|
117
|
+
metric: failure.kind,
|
|
118
|
+
value: 1,
|
|
119
|
+
unit: "count",
|
|
120
|
+
observedAt,
|
|
121
|
+
attributes: {
|
|
122
|
+
transient: failure.transient,
|
|
123
|
+
...(failure.status ? { status: failure.status } : {}),
|
|
124
|
+
...(failure.code !== undefined ? { code: failure.code } : {}),
|
|
125
|
+
},
|
|
114
126
|
},
|
|
115
|
-
|
|
127
|
+
];
|
|
116
128
|
}
|
|
@@ -99,21 +99,18 @@ function metric(
|
|
|
99
99
|
|
|
100
100
|
export function parseOpenRouterUsage(value: unknown): OpenRouterUsage {
|
|
101
101
|
const usage = contractRecord(value, "usage");
|
|
102
|
-
const promptDetails =
|
|
103
|
-
? {}
|
|
104
|
-
|
|
105
|
-
const costDetails = usage["cost_details"] === undefined
|
|
106
|
-
? {}
|
|
107
|
-
: contractRecord(usage["cost_details"], "cost details");
|
|
102
|
+
const promptDetails =
|
|
103
|
+
usage.prompt_tokens_details === undefined ? {} : contractRecord(usage.prompt_tokens_details, "prompt token details");
|
|
104
|
+
const costDetails = usage.cost_details === undefined ? {} : contractRecord(usage.cost_details, "cost details");
|
|
108
105
|
return {
|
|
109
|
-
promptTokens: finite(usage
|
|
110
|
-
completionTokens: finite(usage
|
|
111
|
-
totalTokens: finite(usage
|
|
112
|
-
reasoningTokens: optionalFinite(usage
|
|
113
|
-
cachedReadTokens: optionalFinite(promptDetails
|
|
114
|
-
cachedWriteTokens: optionalFinite(promptDetails
|
|
115
|
-
cost: finite(usage
|
|
116
|
-
upstreamCost: optionalFinite(costDetails
|
|
106
|
+
promptTokens: finite(usage.prompt_tokens, "prompt tokens"),
|
|
107
|
+
completionTokens: finite(usage.completion_tokens, "completion tokens"),
|
|
108
|
+
totalTokens: finite(usage.total_tokens, "total tokens"),
|
|
109
|
+
reasoningTokens: optionalFinite(usage.reasoning_tokens, "reasoning tokens") ?? 0,
|
|
110
|
+
cachedReadTokens: optionalFinite(promptDetails.cached_tokens, "cached tokens") ?? 0,
|
|
111
|
+
cachedWriteTokens: optionalFinite(promptDetails.cache_write_tokens, "cache write tokens") ?? 0,
|
|
112
|
+
cost: finite(usage.cost, "cost"),
|
|
113
|
+
upstreamCost: optionalFinite(costDetails.upstream_inference_cost, "upstream inference cost") ?? 0,
|
|
117
114
|
};
|
|
118
115
|
}
|
|
119
116
|
|
|
@@ -134,23 +131,23 @@ export function openRouterUsageMetrics(usage: OpenRouterUsage, context: OpenRout
|
|
|
134
131
|
|
|
135
132
|
export function parseOpenRouterKey(rootValue: unknown, observedAt: number): OpenRouterKeySnapshot {
|
|
136
133
|
const root = contractRecord(rootValue, "key response");
|
|
137
|
-
const data = contractRecord(root
|
|
138
|
-
const label = optionalText(data
|
|
139
|
-
const limit = optionalFinite(data
|
|
140
|
-
const remaining = optionalFinite(data
|
|
141
|
-
const usage = finite(data
|
|
134
|
+
const data = contractRecord(root.data, "key data");
|
|
135
|
+
const label = optionalText(data.label, "key label");
|
|
136
|
+
const limit = optionalFinite(data.limit, "key limit");
|
|
137
|
+
const remaining = optionalFinite(data.limit_remaining, "key limit remaining");
|
|
138
|
+
const usage = finite(data.usage, "key usage");
|
|
142
139
|
const snapshot: OpenRouterKeySnapshot = {
|
|
143
140
|
label,
|
|
144
141
|
limit,
|
|
145
142
|
remaining,
|
|
146
|
-
reset: optionalText(data
|
|
143
|
+
reset: optionalText(data.limit_reset, "key limit reset"),
|
|
147
144
|
usage,
|
|
148
|
-
usageDaily: optionalFinite(data
|
|
149
|
-
usageWeekly: optionalFinite(data
|
|
150
|
-
usageMonthly: optionalFinite(data
|
|
151
|
-
management: data
|
|
152
|
-
provisioning: data
|
|
153
|
-
rateLimit: data
|
|
145
|
+
usageDaily: optionalFinite(data.usage_daily, "daily usage"),
|
|
146
|
+
usageWeekly: optionalFinite(data.usage_weekly, "weekly usage"),
|
|
147
|
+
usageMonthly: optionalFinite(data.usage_monthly, "monthly usage"),
|
|
148
|
+
management: data.is_management_key === true,
|
|
149
|
+
provisioning: data.is_provisioning_key === true,
|
|
150
|
+
rateLimit: data.rate_limit === undefined || data.rate_limit === null ? null : contractRecord(data.rate_limit, "rate limit"),
|
|
154
151
|
observedAt,
|
|
155
152
|
metrics: [],
|
|
156
153
|
};
|
|
@@ -166,7 +163,8 @@ export function parseOpenRouterKey(rootValue: unknown, observedAt: number): Open
|
|
|
166
163
|
add("limit-remaining", remaining);
|
|
167
164
|
if (limit !== null && limit > 0 && remaining !== null) {
|
|
168
165
|
const remainingFraction = remaining / limit;
|
|
169
|
-
if (remainingFraction < 0 || remainingFraction > 1)
|
|
166
|
+
if (remainingFraction < 0 || remainingFraction > 1)
|
|
167
|
+
throw new Error("OpenRouter key remaining fraction is outside its configured limit");
|
|
170
168
|
const attributes = { limit, remaining, reset: snapshot.reset };
|
|
171
169
|
snapshot.metrics.push(metric(scope, "remaining-fraction", remainingFraction, "ratio", observedAt, attributes));
|
|
172
170
|
snapshot.metrics.push(metric(scope, "used-fraction", 1 - remainingFraction, "ratio", observedAt, attributes));
|
|
@@ -176,49 +174,49 @@ export function parseOpenRouterKey(rootValue: unknown, observedAt: number): Open
|
|
|
176
174
|
|
|
177
175
|
export function parseOpenRouterModels(rootValue: unknown): OpenRouterModel[] {
|
|
178
176
|
const root = contractRecord(rootValue, "models response");
|
|
179
|
-
if (!Array.isArray(root
|
|
180
|
-
return root
|
|
177
|
+
if (!Array.isArray(root.data)) throw new Error("OpenRouter models schema changed");
|
|
178
|
+
return root.data.map((value) => {
|
|
181
179
|
const model = contractRecord(value, "model");
|
|
182
|
-
const pricing = contractRecord(model
|
|
183
|
-
const provider = contractRecord(model
|
|
184
|
-
if (!Array.isArray(model
|
|
180
|
+
const pricing = contractRecord(model.pricing, "model pricing");
|
|
181
|
+
const provider = contractRecord(model.top_provider, "top provider");
|
|
182
|
+
if (!Array.isArray(model.supported_parameters) || !model.supported_parameters.every((parameter) => typeof parameter === "string")) {
|
|
185
183
|
throw new Error("OpenRouter supported parameters schema changed");
|
|
186
184
|
}
|
|
187
185
|
return {
|
|
188
|
-
id: text(model
|
|
189
|
-
canonicalSlug: text(model
|
|
190
|
-
name: text(model
|
|
191
|
-
contextLength: finite(model
|
|
186
|
+
id: text(model.id, "model id"),
|
|
187
|
+
canonicalSlug: text(model.canonical_slug, "canonical slug"),
|
|
188
|
+
name: text(model.name, "model name"),
|
|
189
|
+
contextLength: finite(model.context_length, "context length"),
|
|
192
190
|
pricing: {
|
|
193
|
-
prompt: price(pricing
|
|
194
|
-
completion: price(pricing
|
|
195
|
-
request: price(pricing
|
|
191
|
+
prompt: price(pricing.prompt, "prompt pricing"),
|
|
192
|
+
completion: price(pricing.completion, "completion pricing"),
|
|
193
|
+
request: price(pricing.request, "request pricing"),
|
|
196
194
|
},
|
|
197
|
-
supportedParameters: model
|
|
198
|
-
maxCompletionTokens: optionalFinite(provider
|
|
199
|
-
expiresAt: optionalText(model
|
|
195
|
+
supportedParameters: model.supported_parameters as string[],
|
|
196
|
+
maxCompletionTokens: optionalFinite(provider.max_completion_tokens, "max completion tokens"),
|
|
197
|
+
expiresAt: optionalText(model.expiration_date, "expiration date"),
|
|
200
198
|
};
|
|
201
199
|
});
|
|
202
200
|
}
|
|
203
201
|
|
|
204
202
|
export function parseOpenRouterGeneration(rootValue: unknown): OpenRouterGeneration {
|
|
205
203
|
const root = contractRecord(rootValue, "generation response");
|
|
206
|
-
const data = contractRecord(root
|
|
204
|
+
const data = contractRecord(root.data, "generation data");
|
|
207
205
|
return {
|
|
208
|
-
id: text(data
|
|
209
|
-
totalCost: finite(data
|
|
210
|
-
promptTokens: finite(data
|
|
211
|
-
completionTokens: finite(data
|
|
206
|
+
id: text(data.id, "generation id"),
|
|
207
|
+
totalCost: finite(data.total_cost, "generation cost"),
|
|
208
|
+
promptTokens: finite(data.tokens_prompt, "generation prompt tokens"),
|
|
209
|
+
completionTokens: finite(data.tokens_completion, "generation completion tokens"),
|
|
212
210
|
raw: data,
|
|
213
211
|
};
|
|
214
212
|
}
|
|
215
213
|
|
|
216
214
|
export function parseOpenRouterAnalytics(rootValue: unknown): OpenRouterAnalyticsResult {
|
|
217
215
|
const root = contractRecord(rootValue, "analytics response");
|
|
218
|
-
if (!Array.isArray(root
|
|
216
|
+
if (!Array.isArray(root.data) || !root.data.every((row) => typeof row === "object" && row !== null && !Array.isArray(row))) {
|
|
219
217
|
throw new Error("OpenRouter analytics data schema changed");
|
|
220
218
|
}
|
|
221
|
-
const metadata = contractRecord(root
|
|
222
|
-
if (typeof metadata
|
|
223
|
-
return { data: root
|
|
219
|
+
const metadata = contractRecord(root.metadata, "analytics metadata");
|
|
220
|
+
if (typeof metadata.truncated !== "boolean") throw new Error("OpenRouter analytics metadata schema changed");
|
|
221
|
+
return { data: root.data as Array<Record<string, unknown>>, metadata: metadata as OpenRouterAnalyticsResult["metadata"] };
|
|
224
222
|
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
-
parseOpenRouterAnalytics,
|
|
3
|
-
parseOpenRouterGeneration,
|
|
4
|
-
parseOpenRouterKey,
|
|
5
|
-
parseOpenRouterModels,
|
|
6
2
|
type OpenRouterAnalyticsResult,
|
|
7
3
|
type OpenRouterGeneration,
|
|
8
4
|
type OpenRouterKeySnapshot,
|
|
9
5
|
type OpenRouterModel,
|
|
6
|
+
parseOpenRouterAnalytics,
|
|
7
|
+
parseOpenRouterGeneration,
|
|
8
|
+
parseOpenRouterKey,
|
|
9
|
+
parseOpenRouterModels,
|
|
10
10
|
} from "./openrouter-contracts.ts";
|
|
11
11
|
|
|
12
12
|
export {
|
|
13
|
-
openRouterUsageMetrics,
|
|
14
|
-
parseOpenRouterUsage,
|
|
15
13
|
type OpenRouterAnalyticsResult,
|
|
16
14
|
type OpenRouterGeneration,
|
|
17
15
|
type OpenRouterKeySnapshot,
|
|
18
16
|
type OpenRouterModel,
|
|
19
17
|
type OpenRouterUsage,
|
|
20
18
|
type OpenRouterUsageContext,
|
|
19
|
+
openRouterUsageMetrics,
|
|
20
|
+
parseOpenRouterUsage,
|
|
21
21
|
} from "./openrouter-contracts.ts";
|
|
22
22
|
|
|
23
23
|
const OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
@@ -51,20 +51,26 @@ export class OpenRouterTelemetryAdapter {
|
|
|
51
51
|
|
|
52
52
|
async queryAnalytics(query: Record<string, unknown>): Promise<OpenRouterAnalyticsResult> {
|
|
53
53
|
if (this.managementCapability !== true) throw new Error("OpenRouter analytics requires a detected management key");
|
|
54
|
-
return parseOpenRouterAnalytics(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
return parseOpenRouterAnalytics(
|
|
55
|
+
await this.request("/analytics/query", {
|
|
56
|
+
method: "POST",
|
|
57
|
+
body: JSON.stringify(query),
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
private async request(path: string, init: RequestInit = {}): Promise<unknown> {
|
|
61
|
-
const response = await this.transport(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
const response = await this.transport(
|
|
64
|
+
new Request(`${this.baseUrl}${path}`, {
|
|
65
|
+
...init,
|
|
66
|
+
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json", ...init.headers },
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
65
69
|
if (!response.ok) {
|
|
66
70
|
const retryAfter = response.headers.get("retry-after");
|
|
67
|
-
throw new Error(
|
|
71
|
+
throw new Error(
|
|
72
|
+
`OpenRouter ${path.split("?")[0]} failed with HTTP ${response.status}${retryAfter ? `; retry after ${retryAfter}` : ""}`,
|
|
73
|
+
);
|
|
68
74
|
}
|
|
69
75
|
return response.json();
|
|
70
76
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import type { BudgetWindow } from "../policy.ts";
|
|
2
2
|
import type { TelemetryBatch, TelemetrySource } from "../ports/telemetry-source.ts";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
type CodexRateLimitSnapshot,
|
|
5
|
+
CodexSubscriptionTelemetryAdapter,
|
|
6
|
+
type CodexTransport,
|
|
7
|
+
type CodexWindow,
|
|
8
|
+
loadCodexFileCredentials,
|
|
9
|
+
} from "./codex.ts";
|
|
10
|
+
import type { GoogleAdcTokenProvider } from "./google-adc-auth.ts";
|
|
5
11
|
import { GoogleVertexBudgetTelemetryAdapter, type GoogleVertexBudgetTransport } from "./google-vertex-budget.ts";
|
|
6
12
|
import type { GoogleVertexMetricSource } from "./google-vertex-contracts.ts";
|
|
7
|
-
import type
|
|
13
|
+
import { OpenRouterTelemetryAdapter, type OpenRouterTransport } from "./openrouter.ts";
|
|
8
14
|
|
|
9
|
-
function budgetWindow(
|
|
10
|
-
limit: CodexRateLimitSnapshot,
|
|
11
|
-
name: "primary" | "secondary",
|
|
12
|
-
window: CodexWindow | null,
|
|
13
|
-
): BudgetWindow | null {
|
|
15
|
+
function budgetWindow(limit: CodexRateLimitSnapshot, name: "primary" | "secondary", window: CodexWindow | null): BudgetWindow | null {
|
|
14
16
|
if (!window || window.windowSeconds === null || window.resetsAt === null) return null;
|
|
15
17
|
return {
|
|
16
18
|
id: `${limit.limitId}:${name}@${limit.observedAt}`,
|
|
@@ -26,8 +28,9 @@ function budgetWindow(
|
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
function windowsFromLimit(limit: CodexRateLimitSnapshot): BudgetWindow[] {
|
|
29
|
-
return [budgetWindow(limit, "primary", limit.primary), budgetWindow(limit, "secondary", limit.secondary)]
|
|
30
|
-
|
|
31
|
+
return [budgetWindow(limit, "primary", limit.primary), budgetWindow(limit, "secondary", limit.secondary)].filter(
|
|
32
|
+
(window): window is BudgetWindow => window !== null,
|
|
33
|
+
);
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
export class CodexTelemetrySource implements TelemetrySource {
|