@danypops/jittor 0.16.3 → 0.18.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 (97) hide show
  1. package/README.md +38 -13
  2. package/docs/COMPACTION_EFFECTIVENESS.md +34 -0
  3. package/docs/CONTEXT_SNAPSHOTS.md +53 -0
  4. package/docs/MODEL_CATALOG.md +43 -0
  5. package/docs/OTLP_EXPORT.md +63 -0
  6. package/docs/PROVIDER_RESEARCH.md +1 -1
  7. package/docs/TOKEN_MEASUREMENT.md +53 -0
  8. package/docs/USAGE_BACKFILL.md +35 -0
  9. package/package.json +5 -4
  10. package/src/{providers/anthropic-contracts.ts → anthropic/rate-limits.ts} +1 -1
  11. package/src/{adapters/artificial-analysis-direct-source.ts → artificial-analysis/benchmark-source.ts} +3 -3
  12. package/src/cli-commands/backfill.ts +51 -0
  13. package/src/cli-commands/benchmarks.ts +4 -4
  14. package/src/cli-commands/cache.ts +120 -0
  15. package/src/cli-commands/catalog.ts +123 -0
  16. package/src/cli-commands/compaction.ts +1 -1
  17. package/src/cli-commands/context.ts +77 -4
  18. package/src/cli-commands/export.ts +30 -0
  19. package/src/cli-commands/metrics.ts +8 -2
  20. package/src/cli-commands/op.ts +1 -1
  21. package/src/cli-commands/route-args.ts +2 -2
  22. package/src/cli-commands/router.ts +2 -2
  23. package/src/cli-commands/support.ts +2 -2
  24. package/src/cli.ts +59 -21
  25. package/src/{providers/codex-contracts.ts → codex/contracts.ts} +1 -1
  26. package/src/codex/source.ts +53 -0
  27. package/src/{providers/codex.ts → codex/telemetry.ts} +2 -2
  28. package/src/constants.ts +31 -0
  29. package/src/daemon.ts +53 -23
  30. package/src/{providers/google-vertex-budget-contracts.ts → google-vertex/budget-contracts.ts} +3 -3
  31. package/src/{providers/google-vertex-budget.ts → google-vertex/budget-telemetry.ts} +6 -6
  32. package/src/{providers/google-vertex-contracts.ts → google-vertex/failures.ts} +1 -1
  33. package/src/google-vertex/source.ts +35 -0
  34. package/src/index.ts +149 -55
  35. package/src/{adapters/lmarena-hf-source.ts → lmarena/benchmark-source.ts} +3 -3
  36. package/src/observability/budget.ts +14 -0
  37. package/src/observability/cache-economics.ts +623 -0
  38. package/src/observability/context-delta.ts +309 -0
  39. package/src/{domain → observability}/context-hub.ts +19 -2
  40. package/src/observability/context-snapshot-history.ts +281 -0
  41. package/src/{domain → observability}/context-telemetry.ts +232 -4
  42. package/src/observability/model-identity.ts +42 -0
  43. package/src/{domain → observability}/model-observation.ts +26 -11
  44. package/src/{ports/metric-store.ts → observability/store.ts} +2 -2
  45. package/src/{ports → observability}/telemetry-source.ts +2 -2
  46. package/src/observability/token-measurement.ts +194 -0
  47. package/src/observability/usage-import.ts +122 -0
  48. package/src/openai/token-counter.ts +63 -0
  49. package/src/{adapters/openrouter-benchmark-source.ts → openrouter/benchmark-source.ts} +3 -3
  50. package/src/{providers/openrouter-contracts.ts → openrouter/contracts.ts} +1 -1
  51. package/src/{adapters/openrouter-design-arena-source.ts → openrouter/design-arena-source.ts} +4 -4
  52. package/src/openrouter/source.ts +20 -0
  53. package/src/{providers/openrouter.ts → openrouter/telemetry.ts} +2 -2
  54. package/src/{domain → optimization/model-selection}/benchmark.ts +9 -27
  55. package/src/optimization/model-selection/catalog-store.ts +97 -0
  56. package/src/optimization/model-selection/catalog.ts +478 -0
  57. package/src/{ports/benchmark-controller.ts → optimization/model-selection/controller.ts} +1 -1
  58. package/src/{adapters/metric-benchmark-store.ts → optimization/model-selection/observation-store.ts} +5 -5
  59. package/src/{domain/model-ranking-service.ts → optimization/model-selection/ranker.ts} +6 -12
  60. package/src/{domain/model-ranking.ts → optimization/model-selection/ranking.ts} +8 -2
  61. package/src/{ports/benchmark-source.ts → optimization/model-selection/source.ts} +1 -1
  62. package/src/{ports/benchmark-store.ts → optimization/model-selection/store.ts} +1 -1
  63. package/src/{domain/codex-recovery.ts → optimization/recovery/codex.ts} +1 -1
  64. package/src/{ports/router-controller.ts → optimization/routing/controller.ts} +1 -1
  65. package/src/{policy.ts → optimization/routing/policy.ts} +4 -14
  66. package/src/{router.ts → optimization/routing/router.ts} +4 -10
  67. package/src/otlp/exporter.ts +354 -0
  68. package/src/pi/session-usage-source.ts +203 -0
  69. package/src/{session-identity-service.ts → sessions/identity.ts} +2 -2
  70. package/src/{operations/session-scope.ts → sessions/router-authorization.ts} +1 -1
  71. package/src/{db.ts → sqlite/database.ts} +14 -1
  72. package/src/{adapters/sqlite-metric-store.ts → sqlite/metric-store.ts} +4 -4
  73. package/src/{adapters/sqlite-session-identity-store.ts → sqlite/session-store.ts} +1 -1
  74. package/src/sqlite/usage-import-store.ts +133 -0
  75. package/src/telemetry-export/exporter.ts +84 -0
  76. package/src/{operations → vehicle}/benchmark-operations.ts +3 -3
  77. package/src/vehicle/cache-operations.ts +95 -0
  78. package/src/vehicle/catalog-operations.ts +10 -0
  79. package/src/{client.ts → vehicle/client.ts} +1 -1
  80. package/src/{operations → vehicle}/context-operations.ts +13 -5
  81. package/src/vehicle/export-operations.ts +12 -0
  82. package/src/{operations/metrics-operations.ts → vehicle/metric-operations.ts} +4 -4
  83. package/src/{operations → vehicle}/model-ranking-operations.ts +3 -3
  84. package/src/{vehicle-registration.ts → vehicle/registration.ts} +21 -4
  85. package/src/{operations/router-operations.ts → vehicle/routing-operations.ts} +4 -4
  86. package/src/{service.ts → vehicle/service.ts} +114 -26
  87. package/src/{operations/session-identity-operations.ts → vehicle/session-operations.ts} +3 -3
  88. package/src/vehicle/usage-import-operations.ts +10 -0
  89. package/src/providers/telemetry-sources.ts +0 -108
  90. /package/src/{providers/google-adc-auth.ts → google-vertex/auth.ts} +0 -0
  91. /package/src/{domain → observability}/metric.ts +0 -0
  92. /package/src/{domain → observability}/task-cost.ts +0 -0
  93. /package/src/{domain → observability}/task-focus.ts +0 -0
  94. /package/src/{domain → observability}/usage.ts +0 -0
  95. /package/src/{config.ts → optimization/routing/config.ts} +0 -0
  96. /package/src/{ports/session-identity-store.ts → sessions/store.ts} +0 -0
  97. /package/src/{operations/types.ts → vehicle/operation-types.ts} +0 -0
@@ -1,29 +1,44 @@
1
1
  import { VehicleRegistry } from "@danypops/vehicle-server";
2
2
  import { createVehicleHttpApp } from "@danypops/vehicle-server/http";
3
3
  import { errorResponse, healthResponse, readyResponse, requireBearerToken } from "@danypops/vehicle-server/rpc-http";
4
- import { SERVICE_MAX_BODY_BYTES, SERVICE_MAX_RESPONSE_BYTES } from "./constants.ts";
5
- import type { BenchmarkQuery, BenchmarkQueryResult, BenchmarkRefreshResult } from "./domain/benchmark.ts";
6
- import type { CompactionDurationEstimate, ContextAssessment } from "./domain/context-telemetry.ts";
7
- import type { MetricObservation, MetricQuery, StoredMetricObservation } from "./domain/metric.ts";
8
- import type { ModelRankingResult } from "./domain/model-ranking.ts";
9
- import type { ModelRanker, ModelRecommendationInput } from "./domain/model-ranking-service.ts";
10
- import type { TaskCostSummary } from "./domain/task-cost.ts";
11
- import type { UsageAggregateRow } from "./domain/usage.ts";
12
- import { benchmarkOperations } from "./operations/benchmark-operations.ts";
13
- import { contextOperations } from "./operations/context-operations.ts";
14
- import { metricsOperations } from "./operations/metrics-operations.ts";
15
- import { modelRankingOperations } from "./operations/model-ranking-operations.ts";
16
- import { routerOperations } from "./operations/router-operations.ts";
17
- import { sessionIdentityOperations } from "./operations/session-identity-operations.ts";
18
- import { routerMutationAuthorizer } from "./operations/session-scope.ts";
19
- import type { OperationHandlerMap } from "./operations/types.ts";
20
- import type { PolicyDecision, Route } from "./policy.ts";
21
- import type { BenchmarkController } from "./ports/benchmark-controller.ts";
22
- import type { MetricStore } from "./ports/metric-store.ts";
23
- import type { RouteOverride, RouterController, RouterStatus, TelemetryPollResult } from "./ports/router-controller.ts";
24
- import { InvalidSessionSecretError, type RegisterSessionIdentityResult, type SessionIdentity } from "./session-identity-service.ts";
25
- import { registerJittorVehicleOperations } from "./vehicle-registration.ts";
26
- import { VERSION } from "./version.ts";
4
+ import { SERVICE_MAX_BODY_BYTES, SERVICE_MAX_RESPONSE_BYTES } from "../constants.ts";
5
+ import type { CacheEconomicsSummary } from "../observability/cache-economics.ts";
6
+ import type { ContextDelta, ContextSnapshot } from "../observability/context-delta.ts";
7
+ import { type ContextSnapshotHistory, MetricContextSnapshotHistory } from "../observability/context-snapshot-history.ts";
8
+ import type { CompactionDurationEstimate, ContextAssessment } from "../observability/context-telemetry.ts";
9
+ import type { MetricObservation, MetricQuery, StoredMetricObservation } from "../observability/metric.ts";
10
+ import type { MetricStore } from "../observability/store.ts";
11
+ import type { TaskCostSummary } from "../observability/task-cost.ts";
12
+ import type { UsageAggregateRow } from "../observability/usage.ts";
13
+ import type { UsageImportController, UsageImportResult, UsageImportStatus } from "../observability/usage-import.ts";
14
+ import type { BenchmarkQuery, BenchmarkQueryResult, BenchmarkRefreshResult } from "../optimization/model-selection/benchmark.ts";
15
+ import type {
16
+ ModelCatalogController,
17
+ ModelCatalogQuery,
18
+ ModelCatalogQueryResult,
19
+ ModelCatalogStatus,
20
+ } from "../optimization/model-selection/catalog.ts";
21
+ import type { BenchmarkController } from "../optimization/model-selection/controller.ts";
22
+ import type { ModelRanker, ModelRecommendationInput } from "../optimization/model-selection/ranker.ts";
23
+ import type { ModelRankingResult } from "../optimization/model-selection/ranking.ts";
24
+ import type { RouteOverride, RouterController, RouterStatus, TelemetryPollResult } from "../optimization/routing/controller.ts";
25
+ import type { PolicyDecision, Route } from "../optimization/routing/policy.ts";
26
+ import { InvalidSessionSecretError, type RegisterSessionIdentityResult, type SessionIdentity } from "../sessions/identity.ts";
27
+ import { routerMutationAuthorizer } from "../sessions/router-authorization.ts";
28
+ import { DisabledObservationExporter, type ObservationExporter, type ObservationExportStatus } from "../telemetry-export/exporter.ts";
29
+ import { VERSION } from "../version.ts";
30
+ import { benchmarkOperations } from "./benchmark-operations.ts";
31
+ import { cacheEconomicsOperations } from "./cache-operations.ts";
32
+ import { catalogOperations } from "./catalog-operations.ts";
33
+ import { contextOperations } from "./context-operations.ts";
34
+ import { exportOperations } from "./export-operations.ts";
35
+ import { metricsOperations } from "./metric-operations.ts";
36
+ import { modelRankingOperations } from "./model-ranking-operations.ts";
37
+ import type { OperationHandlerMap } from "./operation-types.ts";
38
+ import { registerJittorVehicleOperations } from "./registration.ts";
39
+ import { routerOperations } from "./routing-operations.ts";
40
+ import { sessionIdentityOperations } from "./session-operations.ts";
41
+ import { usageImportOperations } from "./usage-import-operations.ts";
27
42
 
28
43
  export const EXPECTED_OPERATION_NAMES = [
29
44
  "metrics.record",
@@ -36,10 +51,20 @@ export const EXPECTED_OPERATION_NAMES = [
36
51
  "benchmark.refresh",
37
52
  "benchmark.status",
38
53
  "benchmark.query",
54
+ "catalog.refresh",
55
+ "catalog.status",
56
+ "catalog.query",
57
+ "usage.import",
58
+ "usage.import_status",
59
+ "usage.import_cancel",
60
+ "export.status",
61
+ "export.flush",
39
62
  "session.register",
40
63
  "session.release",
41
64
  "models.rank",
42
65
  "context.assess",
66
+ "context.delta",
67
+ "context.snapshot",
43
68
  "compaction.estimate",
44
69
  "service.checkpoint",
45
70
  "telemetry.poll",
@@ -51,6 +76,7 @@ export const EXPECTED_OPERATION_NAMES = [
51
76
  "router.clear_override",
52
77
  "router.current_route",
53
78
  "router.available_routes",
79
+ "cache.economics",
54
80
  ] as const;
55
81
 
56
82
  export type OperationName = (typeof EXPECTED_OPERATION_NAMES)[number];
@@ -71,8 +97,18 @@ export interface OperationInputs {
71
97
  "benchmark.refresh": { force?: boolean };
72
98
  "benchmark.status": Record<string, never>;
73
99
  "benchmark.query": BenchmarkQuery;
100
+ "catalog.refresh": { force?: boolean };
101
+ "catalog.status": Record<string, never>;
102
+ "catalog.query": ModelCatalogQuery;
103
+ "usage.import": { dryRun?: boolean };
104
+ "usage.import_status": Record<string, never>;
105
+ "usage.import_cancel": Record<string, never>;
106
+ "export.status": Record<string, never>;
107
+ "export.flush": Record<string, never>;
74
108
  "models.rank": ModelRecommendationInput & RouterScopeInput;
75
109
  "context.assess": { since?: number; until?: number };
110
+ "context.delta": { session_id: string };
111
+ "context.snapshot": ContextSnapshot;
76
112
  "compaction.estimate": Record<string, never>;
77
113
  "service.checkpoint": Record<string, never>;
78
114
  "telemetry.poll": Record<string, never>;
@@ -84,6 +120,7 @@ export interface OperationInputs {
84
120
  "router.clear_override": RouterScopeInput;
85
121
  "router.current_route": Route & RouterScopeInput;
86
122
  "router.available_routes": { routes: Route[] } & RouterScopeInput;
123
+ "cache.economics": { since: number; until: number };
87
124
  }
88
125
  export interface OperationOutputs {
89
126
  "session.register": RegisterSessionIdentityResult;
@@ -98,8 +135,18 @@ export interface OperationOutputs {
98
135
  "benchmark.refresh": BenchmarkRefreshResult;
99
136
  "benchmark.status": BenchmarkRefreshResult;
100
137
  "benchmark.query": BenchmarkQueryResult;
138
+ "catalog.refresh": ModelCatalogStatus;
139
+ "catalog.status": ModelCatalogStatus;
140
+ "catalog.query": ModelCatalogQueryResult;
141
+ "usage.import": UsageImportResult;
142
+ "usage.import_status": UsageImportStatus;
143
+ "usage.import_cancel": UsageImportStatus;
144
+ "export.status": ObservationExportStatus;
145
+ "export.flush": ObservationExportStatus;
101
146
  "models.rank": ModelRankingResult;
102
147
  "context.assess": ContextAssessment;
148
+ "context.delta": ContextDelta | null;
149
+ "context.snapshot": ContextDelta;
103
150
  "compaction.estimate": CompactionDurationEstimate;
104
151
  "service.checkpoint": { ok: true };
105
152
  "telemetry.poll": TelemetryPollResult;
@@ -111,11 +158,44 @@ export interface OperationOutputs {
111
158
  "router.clear_override": RouterStatus;
112
159
  "router.current_route": RouterStatus;
113
160
  "router.available_routes": RouterStatus;
161
+ "cache.economics": CacheEconomicsSummary;
114
162
  }
115
163
 
116
164
  export class UnknownOperationError extends Error {}
117
165
  export { InvalidSessionSecretError };
118
166
 
167
+ class UnavailableUsageImporter implements UsageImportController {
168
+ async run(): Promise<UsageImportResult> {
169
+ throw new Error("historical usage import is not configured");
170
+ }
171
+ status(): UsageImportStatus {
172
+ return { running: false, cancelRequested: false, lastResult: null };
173
+ }
174
+ cancel(): UsageImportStatus {
175
+ return this.status();
176
+ }
177
+ }
178
+
179
+ class UnavailableModelCatalog implements ModelCatalogController {
180
+ async refresh(): Promise<ModelCatalogStatus> {
181
+ return this.status();
182
+ }
183
+ status(): ModelCatalogStatus {
184
+ return {
185
+ configured: false,
186
+ ok: null,
187
+ hasSnapshot: false,
188
+ lastAttemptAt: null,
189
+ lastSuccessAt: null,
190
+ entries: 0,
191
+ revision: null,
192
+ };
193
+ }
194
+ query(): ModelCatalogQueryResult {
195
+ throw new Error("model catalog is not configured");
196
+ }
197
+ }
198
+
119
199
  class UnavailableModelRanker implements ModelRanker {
120
200
  rank(): ModelRankingResult {
121
201
  throw new Error("model ranking is not configured");
@@ -191,6 +271,10 @@ export class JittorService {
191
271
  benchmarks: BenchmarkController = new UnavailableBenchmarkController(),
192
272
  modelRanker: ModelRanker = new UnavailableModelRanker(),
193
273
  sessionIdentity?: SessionIdentity,
274
+ contextSnapshots: ContextSnapshotHistory = new MetricContextSnapshotHistory(metrics),
275
+ catalog: ModelCatalogController = new UnavailableModelCatalog(),
276
+ usageImporter: UsageImportController = new UnavailableUsageImporter(),
277
+ exporter: ObservationExporter = new DisabledObservationExporter(),
194
278
  ) {
195
279
  this.router = router;
196
280
  const authorize = routerMutationAuthorizer(sessionIdentity);
@@ -200,15 +284,19 @@ export class JittorService {
200
284
  this.operations = {
201
285
  ...metricsOperations(metrics),
202
286
  ...benchmarkOperations(benchmarks),
203
- ...contextOperations(metrics),
287
+ ...catalogOperations(catalog),
288
+ ...usageImportOperations(usageImporter),
289
+ ...exportOperations(exporter),
290
+ ...contextOperations(metrics, contextSnapshots),
204
291
  ...routerOperations(router, authorize),
205
292
  ...modelRankingOperations(modelRanker, router, authorize),
206
293
  ...sessionIdentityOperations(sessionIdentity),
294
+ ...cacheEconomicsOperations(metrics, catalog),
207
295
  };
208
296
  this.vehicleRegistry = new VehicleRegistry({
209
297
  name: "jittor",
210
- packageJsonUrl: new URL("../package.json", import.meta.url),
211
- description: "Just-in-Time Token Optimizing Router for Pi -- metrics, benchmark evidence, model ranking, and router policy.",
298
+ packageJsonUrl: new URL("../../package.json", import.meta.url),
299
+ description: "Just-in-Time Token Optimization Router for Pi -- token and context observability with optimization policies.",
212
300
  });
213
301
  // withJittorErrorParity() already converts every real handler error into a well-formed
214
302
  // VehicleError, so this only affects a genuine registration/binding bug.
@@ -1,6 +1,6 @@
1
- import type { SessionIdentity } from "../session-identity-service.ts";
2
- import { requiredString, routerSessionSecret } from "./session-scope.ts";
3
- import type { OperationHandlerMap } from "./types.ts";
1
+ import type { SessionIdentity } from "../sessions/identity.ts";
2
+ import { requiredString, routerSessionSecret } from "../sessions/router-authorization.ts";
3
+ import type { OperationHandlerMap } from "../vehicle/operation-types.ts";
4
4
 
5
5
  /** session.register and session.release -- the only two operations that mutate SessionIdentity itself, distinct from the router mutations it later authorizes. */
6
6
  export function sessionIdentityOperations(sessionIdentity: SessionIdentity | undefined): OperationHandlerMap {
@@ -0,0 +1,10 @@
1
+ import type { UsageImportController } from "../observability/usage-import.ts";
2
+ import type { OperationHandlerMap } from "./operation-types.ts";
3
+
4
+ export function usageImportOperations(importer: UsageImportController): OperationHandlerMap {
5
+ return {
6
+ "usage.import": (input) => importer.run({ dryRun: input.dryRun === true }),
7
+ "usage.import_status": () => importer.status(),
8
+ "usage.import_cancel": () => importer.cancel(),
9
+ };
10
+ }
@@ -1,108 +0,0 @@
1
- import type { BudgetWindow } from "../policy.ts";
2
- import type { TelemetryBatch, TelemetrySource } from "../ports/telemetry-source.ts";
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";
11
- import { GoogleVertexBudgetTelemetryAdapter, type GoogleVertexBudgetTransport } from "./google-vertex-budget.ts";
12
- import type { GoogleVertexMetricSource } from "./google-vertex-contracts.ts";
13
- import { OpenRouterTelemetryAdapter, type OpenRouterTransport } from "./openrouter.ts";
14
-
15
- function budgetWindow(limit: CodexRateLimitSnapshot, name: "primary" | "secondary", window: CodexWindow | null): BudgetWindow | null {
16
- if (!window || window.windowSeconds === null || window.resetsAt === null) return null;
17
- return {
18
- id: `${limit.limitId}:${name}@${limit.observedAt}`,
19
- source: "codex-subscription",
20
- scope: limit.limitId === "codex" ? `codex:${name}` : `${limit.limitId}:${name}`,
21
- usedFraction: window.usedPercent / 100,
22
- windowSeconds: window.windowSeconds,
23
- resetsAt: window.resetsAt * 1_000,
24
- observedAt: limit.observedAt,
25
- freshness: "fresh",
26
- confidence: 0.8,
27
- };
28
- }
29
-
30
- function windowsFromLimit(limit: CodexRateLimitSnapshot): BudgetWindow[] {
31
- return [budgetWindow(limit, "primary", limit.primary), budgetWindow(limit, "secondary", limit.secondary)].filter(
32
- (window): window is BudgetWindow => window !== null,
33
- );
34
- }
35
-
36
- export class CodexTelemetrySource implements TelemetrySource {
37
- readonly id = "codex-subscription";
38
- readonly provider = "openai-codex";
39
- readonly required = true;
40
-
41
- constructor(
42
- private readonly authFile: string,
43
- private readonly transport: CodexTransport = fetch,
44
- private readonly clock: () => number = Date.now,
45
- ) {}
46
-
47
- async poll(): Promise<TelemetryBatch> {
48
- const observedAt = this.clock();
49
- const adapter = new CodexSubscriptionTelemetryAdapter(loadCodexFileCredentials(this.authFile), this.transport);
50
- const snapshot = await adapter.readUsage(observedAt);
51
- return {
52
- observedAt,
53
- metrics: snapshot.metrics,
54
- windows: [snapshot.defaultLimit, ...snapshot.additionalLimits].flatMap(windowsFromLimit),
55
- };
56
- }
57
- }
58
-
59
- export class OpenRouterTelemetrySource implements TelemetrySource {
60
- readonly id = "openrouter";
61
- readonly provider = "openrouter";
62
- readonly required = false;
63
-
64
- constructor(
65
- private readonly apiKey: string,
66
- private readonly transport: OpenRouterTransport = fetch,
67
- private readonly clock: () => number = Date.now,
68
- ) {}
69
-
70
- async poll(): Promise<TelemetryBatch> {
71
- const observedAt = this.clock();
72
- const snapshot = await new OpenRouterTelemetryAdapter(this.apiKey, this.transport).readKey(observedAt);
73
- return { observedAt, metrics: snapshot.metrics, windows: [] };
74
- }
75
- }
76
-
77
- /**
78
- * Optional (never `required`): the one-time GCP setup (Pub/Sub topic + pull subscription
79
- * connected to the individual project's budget) lives entirely outside Jittor, so a subscription
80
- * that doesn't exist yet, or a project not yet migrated onto the individual-project model, must
81
- * not block every other route the way a missing required source would.
82
- */
83
- export class GoogleVertexBudgetTelemetrySource implements TelemetrySource {
84
- readonly id: string;
85
- readonly provider: GoogleVertexMetricSource;
86
- readonly required = false;
87
-
88
- private readonly adapter: GoogleVertexBudgetTelemetryAdapter;
89
-
90
- constructor(
91
- subscription: string,
92
- tokenProvider: GoogleAdcTokenProvider,
93
- private readonly clock: () => number = Date.now,
94
- transport: GoogleVertexBudgetTransport = fetch,
95
- source: GoogleVertexMetricSource = "google-vertex",
96
- ) {
97
- this.id = `google-vertex-budget:${source}`;
98
- this.provider = source;
99
- this.adapter = new GoogleVertexBudgetTelemetryAdapter(subscription, tokenProvider, transport, source);
100
- }
101
-
102
- async poll(): Promise<TelemetryBatch> {
103
- const observedAt = this.clock();
104
- const snapshot = await this.adapter.pull(observedAt);
105
- if (!snapshot) return { observedAt, metrics: [], windows: [] };
106
- return { observedAt, metrics: snapshot.metrics, windows: snapshot.window ? [snapshot.window] : [] };
107
- }
108
- }
File without changes
File without changes
File without changes
File without changes