@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.
- package/README.md +38 -13
- package/docs/COMPACTION_EFFECTIVENESS.md +34 -0
- package/docs/CONTEXT_SNAPSHOTS.md +53 -0
- package/docs/MODEL_CATALOG.md +43 -0
- package/docs/OTLP_EXPORT.md +63 -0
- package/docs/PROVIDER_RESEARCH.md +1 -1
- package/docs/TOKEN_MEASUREMENT.md +53 -0
- package/docs/USAGE_BACKFILL.md +35 -0
- package/package.json +5 -4
- package/src/{providers/anthropic-contracts.ts → anthropic/rate-limits.ts} +1 -1
- package/src/{adapters/artificial-analysis-direct-source.ts → artificial-analysis/benchmark-source.ts} +3 -3
- package/src/cli-commands/backfill.ts +51 -0
- package/src/cli-commands/benchmarks.ts +4 -4
- package/src/cli-commands/cache.ts +120 -0
- package/src/cli-commands/catalog.ts +123 -0
- package/src/cli-commands/compaction.ts +1 -1
- package/src/cli-commands/context.ts +77 -4
- package/src/cli-commands/export.ts +30 -0
- package/src/cli-commands/metrics.ts +8 -2
- package/src/cli-commands/op.ts +1 -1
- package/src/cli-commands/route-args.ts +2 -2
- package/src/cli-commands/router.ts +2 -2
- package/src/cli-commands/support.ts +2 -2
- package/src/cli.ts +59 -21
- package/src/{providers/codex-contracts.ts → codex/contracts.ts} +1 -1
- package/src/codex/source.ts +53 -0
- package/src/{providers/codex.ts → codex/telemetry.ts} +2 -2
- package/src/constants.ts +31 -0
- package/src/daemon.ts +53 -23
- package/src/{providers/google-vertex-budget-contracts.ts → google-vertex/budget-contracts.ts} +3 -3
- package/src/{providers/google-vertex-budget.ts → google-vertex/budget-telemetry.ts} +6 -6
- package/src/{providers/google-vertex-contracts.ts → google-vertex/failures.ts} +1 -1
- package/src/google-vertex/source.ts +35 -0
- package/src/index.ts +149 -55
- package/src/{adapters/lmarena-hf-source.ts → lmarena/benchmark-source.ts} +3 -3
- package/src/observability/budget.ts +14 -0
- package/src/observability/cache-economics.ts +623 -0
- package/src/observability/context-delta.ts +309 -0
- package/src/{domain → observability}/context-hub.ts +19 -2
- package/src/observability/context-snapshot-history.ts +281 -0
- package/src/{domain → observability}/context-telemetry.ts +232 -4
- package/src/observability/model-identity.ts +42 -0
- package/src/{domain → observability}/model-observation.ts +26 -11
- package/src/{ports/metric-store.ts → observability/store.ts} +2 -2
- package/src/{ports → observability}/telemetry-source.ts +2 -2
- package/src/observability/token-measurement.ts +194 -0
- package/src/observability/usage-import.ts +122 -0
- package/src/openai/token-counter.ts +63 -0
- package/src/{adapters/openrouter-benchmark-source.ts → openrouter/benchmark-source.ts} +3 -3
- package/src/{providers/openrouter-contracts.ts → openrouter/contracts.ts} +1 -1
- package/src/{adapters/openrouter-design-arena-source.ts → openrouter/design-arena-source.ts} +4 -4
- package/src/openrouter/source.ts +20 -0
- package/src/{providers/openrouter.ts → openrouter/telemetry.ts} +2 -2
- package/src/{domain → optimization/model-selection}/benchmark.ts +9 -27
- package/src/optimization/model-selection/catalog-store.ts +97 -0
- package/src/optimization/model-selection/catalog.ts +478 -0
- package/src/{ports/benchmark-controller.ts → optimization/model-selection/controller.ts} +1 -1
- package/src/{adapters/metric-benchmark-store.ts → optimization/model-selection/observation-store.ts} +5 -5
- package/src/{domain/model-ranking-service.ts → optimization/model-selection/ranker.ts} +6 -12
- package/src/{domain/model-ranking.ts → optimization/model-selection/ranking.ts} +8 -2
- package/src/{ports/benchmark-source.ts → optimization/model-selection/source.ts} +1 -1
- package/src/{ports/benchmark-store.ts → optimization/model-selection/store.ts} +1 -1
- package/src/{domain/codex-recovery.ts → optimization/recovery/codex.ts} +1 -1
- package/src/{ports/router-controller.ts → optimization/routing/controller.ts} +1 -1
- package/src/{policy.ts → optimization/routing/policy.ts} +4 -14
- package/src/{router.ts → optimization/routing/router.ts} +4 -10
- package/src/otlp/exporter.ts +354 -0
- package/src/pi/session-usage-source.ts +203 -0
- package/src/{session-identity-service.ts → sessions/identity.ts} +2 -2
- package/src/{operations/session-scope.ts → sessions/router-authorization.ts} +1 -1
- package/src/{db.ts → sqlite/database.ts} +14 -1
- package/src/{adapters/sqlite-metric-store.ts → sqlite/metric-store.ts} +4 -4
- package/src/{adapters/sqlite-session-identity-store.ts → sqlite/session-store.ts} +1 -1
- package/src/sqlite/usage-import-store.ts +133 -0
- package/src/telemetry-export/exporter.ts +84 -0
- package/src/{operations → vehicle}/benchmark-operations.ts +3 -3
- package/src/vehicle/cache-operations.ts +95 -0
- package/src/vehicle/catalog-operations.ts +10 -0
- package/src/{client.ts → vehicle/client.ts} +1 -1
- package/src/{operations → vehicle}/context-operations.ts +13 -5
- package/src/vehicle/export-operations.ts +12 -0
- package/src/{operations/metrics-operations.ts → vehicle/metric-operations.ts} +4 -4
- package/src/{operations → vehicle}/model-ranking-operations.ts +3 -3
- package/src/{vehicle-registration.ts → vehicle/registration.ts} +21 -4
- package/src/{operations/router-operations.ts → vehicle/routing-operations.ts} +4 -4
- package/src/{service.ts → vehicle/service.ts} +114 -26
- package/src/{operations/session-identity-operations.ts → vehicle/session-operations.ts} +3 -3
- package/src/vehicle/usage-import-operations.ts +10 -0
- package/src/providers/telemetry-sources.ts +0 -108
- /package/src/{providers/google-adc-auth.ts → google-vertex/auth.ts} +0 -0
- /package/src/{domain → observability}/metric.ts +0 -0
- /package/src/{domain → observability}/task-cost.ts +0 -0
- /package/src/{domain → observability}/task-focus.ts +0 -0
- /package/src/{domain → observability}/usage.ts +0 -0
- /package/src/{config.ts → optimization/routing/config.ts} +0 -0
- /package/src/{ports/session-identity-store.ts → sessions/store.ts} +0 -0
- /package/src/{operations/types.ts → vehicle/operation-types.ts} +0 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import type { MetricObservation } from "../observability/metric.ts";
|
|
3
|
+
import { validateMetricObservation } from "../observability/metric.ts";
|
|
4
|
+
import type { HistoricalUsageRecord, UsageImportResult, UsageImportStatus, UsageImportStore } from "../observability/usage-import.ts";
|
|
5
|
+
|
|
6
|
+
function validateRecord(record: HistoricalUsageRecord): HistoricalUsageRecord {
|
|
7
|
+
if (!/^[a-f0-9]{64}$/.test(record.identity)) throw new Error("usage import identity is invalid");
|
|
8
|
+
if (!Number.isSafeInteger(record.observedAt) || record.observedAt < 0) throw new Error("usage import timestamp is invalid");
|
|
9
|
+
return record;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function observations(record: HistoricalUsageRecord): MetricObservation[] {
|
|
13
|
+
const attributes = {
|
|
14
|
+
provider: record.provider,
|
|
15
|
+
model: record.model,
|
|
16
|
+
...(record.thinking ? { thinking: record.thinking } : {}),
|
|
17
|
+
imported: true,
|
|
18
|
+
importIdentity: record.identity,
|
|
19
|
+
};
|
|
20
|
+
const token = (metric: string, value: number, scope: "request-input" | "response-output" | "cache-read" | "cache-write") => ({
|
|
21
|
+
source: "pi",
|
|
22
|
+
scope: `${record.provider}:${record.model}`,
|
|
23
|
+
metric,
|
|
24
|
+
value,
|
|
25
|
+
unit: "tokens" as const,
|
|
26
|
+
observedAt: record.observedAt,
|
|
27
|
+
attributes: {
|
|
28
|
+
...attributes,
|
|
29
|
+
tokenMeasurement: {
|
|
30
|
+
tokens: value,
|
|
31
|
+
scope,
|
|
32
|
+
provenance: "provider-reported",
|
|
33
|
+
method: "pi-assistant-usage",
|
|
34
|
+
provider: record.provider,
|
|
35
|
+
model: record.model,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
return [
|
|
40
|
+
token("input-tokens", record.inputTokens, "request-input"),
|
|
41
|
+
token("output-tokens", record.outputTokens, "response-output"),
|
|
42
|
+
token("cache-read-tokens", record.cacheReadTokens, "cache-read"),
|
|
43
|
+
token("cache-write-tokens", record.cacheWriteTokens, "cache-write"),
|
|
44
|
+
{
|
|
45
|
+
source: "pi",
|
|
46
|
+
scope: `${record.provider}:${record.model}`,
|
|
47
|
+
metric: "cost",
|
|
48
|
+
value: record.costUsd,
|
|
49
|
+
unit: "usd",
|
|
50
|
+
observedAt: record.observedAt,
|
|
51
|
+
attributes,
|
|
52
|
+
},
|
|
53
|
+
].map(validateMetricObservation);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class SQLiteUsageImportStore implements UsageImportStore {
|
|
57
|
+
constructor(private readonly db: Database) {}
|
|
58
|
+
|
|
59
|
+
import(input: HistoricalUsageRecord[]): { imported: number; duplicates: number } {
|
|
60
|
+
const records = input.map(validateRecord);
|
|
61
|
+
const claim = this.db.prepare("INSERT OR IGNORE INTO usage_import_identities(identity, imported_at) VALUES (?, ?)");
|
|
62
|
+
const matchingLive = this.db.prepare(
|
|
63
|
+
"SELECT COUNT(DISTINCT metric) AS matched FROM metric_observations WHERE source = 'pi' AND scope = ? AND observed_at = ? AND ((metric = 'input-tokens' AND value = ?) OR (metric = 'output-tokens' AND value = ?) OR (metric = 'cache-read-tokens' AND value = ?) OR (metric = 'cache-write-tokens' AND value = ?) OR (metric = 'cost' AND value = ?))",
|
|
64
|
+
);
|
|
65
|
+
const insert = this.db.prepare(
|
|
66
|
+
"INSERT INTO metric_observations(source, scope, metric, value, unit, observed_at, attributes) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
67
|
+
);
|
|
68
|
+
let imported = 0;
|
|
69
|
+
let duplicates = 0;
|
|
70
|
+
this.db.transaction(() => {
|
|
71
|
+
for (const record of records) {
|
|
72
|
+
const scope = `${record.provider}:${record.model}`;
|
|
73
|
+
const live = matchingLive.get(
|
|
74
|
+
scope,
|
|
75
|
+
record.observedAt,
|
|
76
|
+
record.inputTokens,
|
|
77
|
+
record.outputTokens,
|
|
78
|
+
record.cacheReadTokens,
|
|
79
|
+
record.cacheWriteTokens,
|
|
80
|
+
record.costUsd,
|
|
81
|
+
) as { matched: number };
|
|
82
|
+
const result = claim.run(record.identity, Date.now());
|
|
83
|
+
if (result.changes === 0 || live.matched === 5) {
|
|
84
|
+
duplicates += 1;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
for (const observation of observations(record)) {
|
|
88
|
+
insert.run(
|
|
89
|
+
observation.source,
|
|
90
|
+
observation.scope,
|
|
91
|
+
observation.metric,
|
|
92
|
+
observation.value,
|
|
93
|
+
observation.unit,
|
|
94
|
+
observation.observedAt,
|
|
95
|
+
JSON.stringify(observation.attributes ?? {}),
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
imported += 1;
|
|
99
|
+
}
|
|
100
|
+
})();
|
|
101
|
+
return { imported, duplicates };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
preview(records: HistoricalUsageRecord[]): { duplicates: number } {
|
|
105
|
+
const exists = this.db.prepare("SELECT 1 AS found FROM usage_import_identities WHERE identity = ? LIMIT 1");
|
|
106
|
+
return { duplicates: records.map(validateRecord).filter((record) => exists.get(record.identity) !== null).length };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
status(): UsageImportStatus {
|
|
110
|
+
const row = this.db.query<{ status: string }, []>("SELECT status FROM usage_import_state WHERE id = 1").get();
|
|
111
|
+
if (!row) return { running: false, cancelRequested: false, lastResult: null };
|
|
112
|
+
try {
|
|
113
|
+
const parsed = JSON.parse(row.status) as { lastResult?: unknown };
|
|
114
|
+
const lastResult = parsed.lastResult;
|
|
115
|
+
return {
|
|
116
|
+
running: false,
|
|
117
|
+
cancelRequested: false,
|
|
118
|
+
lastResult:
|
|
119
|
+
typeof lastResult === "object" && lastResult !== null && !Array.isArray(lastResult) ? (lastResult as UsageImportResult) : null,
|
|
120
|
+
};
|
|
121
|
+
} catch {
|
|
122
|
+
return { running: false, cancelRequested: false, lastResult: null };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
saveStatus(status: UsageImportStatus): void {
|
|
127
|
+
this.db
|
|
128
|
+
.prepare(
|
|
129
|
+
"INSERT INTO usage_import_state(id, status, updated_at) VALUES (1, ?, ?) ON CONFLICT(id) DO UPDATE SET status = excluded.status, updated_at = excluded.updated_at",
|
|
130
|
+
)
|
|
131
|
+
.run(JSON.stringify(status), Date.now());
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { MetricObservation, MetricQuery, StoredMetricObservation } from "../observability/metric.ts";
|
|
2
|
+
import type { DistinctScopesFilter, MetricStore, UsageAggregateFilter } from "../observability/store.ts";
|
|
3
|
+
import type { UsageAggregateRow } from "../observability/usage.ts";
|
|
4
|
+
|
|
5
|
+
export interface ObservationExportStatus {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
semanticConventions: string;
|
|
8
|
+
queued: number;
|
|
9
|
+
dropped: number;
|
|
10
|
+
exported: number;
|
|
11
|
+
failures: number;
|
|
12
|
+
lastSuccessAt: number | null;
|
|
13
|
+
lastFailureAt: number | null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ObservationExporter {
|
|
17
|
+
enqueue(observation: MetricObservation): void;
|
|
18
|
+
flush(): Promise<void>;
|
|
19
|
+
shutdown(): Promise<void>;
|
|
20
|
+
status(): ObservationExportStatus;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class DisabledObservationExporter implements ObservationExporter {
|
|
24
|
+
enqueue(): void {}
|
|
25
|
+
async flush(): Promise<void> {}
|
|
26
|
+
async shutdown(): Promise<void> {}
|
|
27
|
+
status(): ObservationExportStatus {
|
|
28
|
+
return {
|
|
29
|
+
enabled: false,
|
|
30
|
+
semanticConventions: "none",
|
|
31
|
+
queued: 0,
|
|
32
|
+
dropped: 0,
|
|
33
|
+
exported: 0,
|
|
34
|
+
failures: 0,
|
|
35
|
+
lastSuccessAt: null,
|
|
36
|
+
lastFailureAt: null,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Local persistence completes first; exporter enqueue is best-effort and can never alter that result. */
|
|
42
|
+
export class ExportingMetricStore implements MetricStore {
|
|
43
|
+
constructor(
|
|
44
|
+
private readonly local: MetricStore,
|
|
45
|
+
private readonly exporter: ObservationExporter,
|
|
46
|
+
) {}
|
|
47
|
+
|
|
48
|
+
record(observation: MetricObservation): StoredMetricObservation {
|
|
49
|
+
const stored = this.local.record(observation);
|
|
50
|
+
try {
|
|
51
|
+
this.exporter.enqueue(observation);
|
|
52
|
+
} catch {}
|
|
53
|
+
return stored;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
recordBatch(observations: MetricObservation[]): StoredMetricObservation[] {
|
|
57
|
+
const stored = this.local.recordBatch(observations);
|
|
58
|
+
for (const observation of observations) {
|
|
59
|
+
try {
|
|
60
|
+
this.exporter.enqueue(observation);
|
|
61
|
+
} catch {}
|
|
62
|
+
}
|
|
63
|
+
return stored;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
query(filter?: MetricQuery): StoredMetricObservation[] {
|
|
67
|
+
return this.local.query(filter);
|
|
68
|
+
}
|
|
69
|
+
distinctScopes(filter: DistinctScopesFilter): string[] {
|
|
70
|
+
return this.local.distinctScopes(filter);
|
|
71
|
+
}
|
|
72
|
+
aggregateUsage(filter: UsageAggregateFilter): UsageAggregateRow[] {
|
|
73
|
+
return this.local.aggregateUsage(filter);
|
|
74
|
+
}
|
|
75
|
+
pruneBefore(cutoff: number): number {
|
|
76
|
+
return this.local.pruneBefore(cutoff);
|
|
77
|
+
}
|
|
78
|
+
checkpoint(): void {
|
|
79
|
+
this.local.checkpoint();
|
|
80
|
+
}
|
|
81
|
+
close(): void {
|
|
82
|
+
this.local.close();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { BenchmarkQuery } from "../
|
|
2
|
-
import type { BenchmarkController } from "../
|
|
3
|
-
import type { OperationHandlerMap } from "./types.ts";
|
|
1
|
+
import type { BenchmarkQuery } from "../optimization/model-selection/benchmark.ts";
|
|
2
|
+
import type { BenchmarkController } from "../optimization/model-selection/controller.ts";
|
|
3
|
+
import type { OperationHandlerMap } from "./operation-types.ts";
|
|
4
4
|
|
|
5
5
|
/** benchmark.* -- every operation whose only collaborator is the benchmark-controller port. */
|
|
6
6
|
export function benchmarkOperations(benchmarks: BenchmarkController): OperationHandlerMap {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { CACHE_ECONOMICS_QUERY_LIMIT, CATALOG_LONG_CONTEXT_THRESHOLD_TOKENS } from "../constants.ts";
|
|
2
|
+
import {
|
|
3
|
+
buildCacheEconomicsSummary,
|
|
4
|
+
type CacheEconomicsPricing,
|
|
5
|
+
type CacheEconomicsPricingLookup,
|
|
6
|
+
} from "../observability/cache-economics.ts";
|
|
7
|
+
import type { MetricStore } from "../observability/store.ts";
|
|
8
|
+
import type { ModelCatalogController, ModelCatalogPriceTier, ModelCatalogPricing } from "../optimization/model-selection/catalog.ts";
|
|
9
|
+
import type { OperationHandlerMap } from "./operation-types.ts";
|
|
10
|
+
|
|
11
|
+
function mergeWithBase(
|
|
12
|
+
base: ModelCatalogPricing,
|
|
13
|
+
override: Partial<Pick<ModelCatalogPricing, "input" | "cacheRead" | "cacheWrite">>,
|
|
14
|
+
): CacheEconomicsPricing {
|
|
15
|
+
return {
|
|
16
|
+
input: override.input ?? base.input,
|
|
17
|
+
cacheRead: override.cacheRead ?? base.cacheRead,
|
|
18
|
+
cacheWrite: override.cacheWrite ?? base.cacheWrite,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Resolves one flat price for one real request size, honoring models.dev's own long-context and
|
|
24
|
+
* tiered pricing shapes -- the only place tiering can be resolved honestly, since it needs a
|
|
25
|
+
* single request's real context size (see cache-economics.ts's per-run pricing).
|
|
26
|
+
*
|
|
27
|
+
* `contextOver200k` takes priority over `tiers` when both are present (mirrors models.dev's own
|
|
28
|
+
* convention: it is a distinct override for the specific >200k-token case, not one more tier).
|
|
29
|
+
* A field a tier/override omits falls back to the base flat price, never to `undefined`-as-unknown
|
|
30
|
+
* silently -- a tier that only republishes input/output pricing still inherits the model's real
|
|
31
|
+
* cache prices instead of losing them.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveTieredCatalogPrice(pricing: ModelCatalogPricing, contextSizeTokens: number): CacheEconomicsPricing {
|
|
34
|
+
if (pricing.contextOver200k && contextSizeTokens > CATALOG_LONG_CONTEXT_THRESHOLD_TOKENS) {
|
|
35
|
+
return mergeWithBase(pricing, pricing.contextOver200k);
|
|
36
|
+
}
|
|
37
|
+
if (pricing.tiers && pricing.tiers.length > 0) {
|
|
38
|
+
const ascending = [...pricing.tiers].sort((left, right) => left.contextSize - right.contextSize);
|
|
39
|
+
const tier: ModelCatalogPriceTier = ascending.find((candidate) => candidate.contextSize >= contextSizeTokens) ?? ascending.at(-1)!;
|
|
40
|
+
return mergeWithBase(pricing, tier);
|
|
41
|
+
}
|
|
42
|
+
return { input: pricing.input, cacheRead: pricing.cacheRead, cacheWrite: pricing.cacheWrite };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Best-effort catalog-backed pricing lookup: an unconfigured/unavailable catalog, or a model the
|
|
47
|
+
* catalog doesn't carry, returns null rather than throwing -- cache economics degrades that
|
|
48
|
+
* model's pricing to "unknown" instead of failing the whole query.
|
|
49
|
+
*/
|
|
50
|
+
class CatalogCacheEconomicsPricing implements CacheEconomicsPricingLookup {
|
|
51
|
+
constructor(private readonly catalog: ModelCatalogController) {}
|
|
52
|
+
|
|
53
|
+
priceFor(provider: string, model: string, contextSizeTokens: number): CacheEconomicsPricing | null {
|
|
54
|
+
try {
|
|
55
|
+
const result = this.catalog.query({ provider, model, limit: 1 });
|
|
56
|
+
const entry = result.entries[0];
|
|
57
|
+
if (!entry?.pricing) return null;
|
|
58
|
+
return { ...resolveTieredCatalogPrice(entry.pricing, contextSizeTokens), freshness: result.freshness };
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** cache.economics -- the only operation that combines the metric store's "pi"/"pi-context-snapshot" rows with catalog pricing. */
|
|
66
|
+
export function cacheEconomicsOperations(metrics: MetricStore, catalog: ModelCatalogController): OperationHandlerMap {
|
|
67
|
+
const pricing = new CatalogCacheEconomicsPricing(catalog);
|
|
68
|
+
return {
|
|
69
|
+
"cache.economics": (input) => {
|
|
70
|
+
const since = input.since;
|
|
71
|
+
const until = input.until;
|
|
72
|
+
if (!Number.isSafeInteger(since) || !Number.isSafeInteger(until) || (since as number) < 0 || (until as number) < (since as number)) {
|
|
73
|
+
throw new Error("cache economics requires non-negative ordered integer bounds");
|
|
74
|
+
}
|
|
75
|
+
const usageRows = metrics.query({
|
|
76
|
+
source: "pi",
|
|
77
|
+
since: since as number,
|
|
78
|
+
until: until as number,
|
|
79
|
+
order: "desc",
|
|
80
|
+
limit: CACHE_ECONOMICS_QUERY_LIMIT,
|
|
81
|
+
});
|
|
82
|
+
const snapshotRows = metrics.query({
|
|
83
|
+
source: "pi-context-snapshot",
|
|
84
|
+
metric: "snapshot",
|
|
85
|
+
since: since as number,
|
|
86
|
+
until: until as number,
|
|
87
|
+
order: "desc",
|
|
88
|
+
limit: CACHE_ECONOMICS_QUERY_LIMIT,
|
|
89
|
+
});
|
|
90
|
+
const summary = buildCacheEconomicsSummary(usageRows, snapshotRows, pricing, { since: since as number, until: until as number });
|
|
91
|
+
const rowsTruncated = usageRows.length >= CACHE_ECONOMICS_QUERY_LIMIT || snapshotRows.length >= CACHE_ECONOMICS_QUERY_LIMIT;
|
|
92
|
+
return { ...summary, truncated: summary.truncated || rowsTruncated };
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ModelCatalogController, ModelCatalogQuery } from "../optimization/model-selection/catalog.ts";
|
|
2
|
+
import type { OperationHandlerMap } from "./operation-types.ts";
|
|
3
|
+
|
|
4
|
+
export function catalogOperations(catalog: ModelCatalogController): OperationHandlerMap {
|
|
5
|
+
return {
|
|
6
|
+
"catalog.refresh": (input) => catalog.refresh(input.force === true),
|
|
7
|
+
"catalog.status": () => catalog.status(),
|
|
8
|
+
"catalog.query": (input) => catalog.query(input as unknown as ModelCatalogQuery),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AuthenticatedRpcClient, type FetchTransport } from "@danypops/vehicle-client/rpc-client";
|
|
2
|
+
import { ensureAuthToken, type JittorPaths, readDaemonHandle, resolveJittorPaths } from "../state.ts";
|
|
2
3
|
import type { OperationInputs, OperationName, OperationOutputs } from "./service.ts";
|
|
3
|
-
import { ensureAuthToken, type JittorPaths, readDaemonHandle, resolveJittorPaths } from "./state.ts";
|
|
4
4
|
|
|
5
5
|
export type { FetchTransport };
|
|
6
6
|
|
|
@@ -3,12 +3,14 @@ import {
|
|
|
3
3
|
CONTEXT_ASSESSMENT_DEFAULT_WINDOW_MS,
|
|
4
4
|
CONTEXT_ASSESSMENT_QUERY_LIMIT,
|
|
5
5
|
} from "../constants.ts";
|
|
6
|
-
import {
|
|
7
|
-
import type {
|
|
8
|
-
import
|
|
6
|
+
import type { ContextSnapshot } from "../observability/context-delta.ts";
|
|
7
|
+
import type { ContextSnapshotHistory } from "../observability/context-snapshot-history.ts";
|
|
8
|
+
import { assessContextTelemetry, estimateCompactionDuration } from "../observability/context-telemetry.ts";
|
|
9
|
+
import type { MetricStore } from "../observability/store.ts";
|
|
10
|
+
import type { OperationHandlerMap } from "../vehicle/operation-types.ts";
|
|
9
11
|
|
|
10
|
-
/**
|
|
11
|
-
export function contextOperations(metrics: MetricStore): OperationHandlerMap {
|
|
12
|
+
/** Context assessment, content-free snapshots/deltas, and compaction estimates. */
|
|
13
|
+
export function contextOperations(metrics: MetricStore, snapshots: ContextSnapshotHistory): OperationHandlerMap {
|
|
12
14
|
return {
|
|
13
15
|
"context.assess": (input) => {
|
|
14
16
|
const until = input.until === undefined ? Date.now() : input.until;
|
|
@@ -25,6 +27,12 @@ export function contextOperations(metrics: MetricStore): OperationHandlerMap {
|
|
|
25
27
|
truncated: injections.length >= CONTEXT_ASSESSMENT_QUERY_LIMIT || compactions.length >= CONTEXT_ASSESSMENT_QUERY_LIMIT,
|
|
26
28
|
});
|
|
27
29
|
},
|
|
30
|
+
"context.snapshot": (input) => snapshots.record(input as unknown as ContextSnapshot),
|
|
31
|
+
"context.delta": (input) => {
|
|
32
|
+
if (typeof input.session_id !== "string" || !/^[A-Za-z0-9_-]{32,64}$/.test(input.session_id))
|
|
33
|
+
throw new Error("context delta requires an opaque session_id fingerprint");
|
|
34
|
+
return snapshots.latestDelta(input.session_id);
|
|
35
|
+
},
|
|
28
36
|
"compaction.estimate": () => {
|
|
29
37
|
const rows = metrics.query({
|
|
30
38
|
source: "pi-context",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ObservationExporter } from "../telemetry-export/exporter.ts";
|
|
2
|
+
import type { OperationHandlerMap } from "./operation-types.ts";
|
|
3
|
+
|
|
4
|
+
export function exportOperations(exporter: ObservationExporter): OperationHandlerMap {
|
|
5
|
+
return {
|
|
6
|
+
"export.status": () => exporter.status(),
|
|
7
|
+
"export.flush": async () => {
|
|
8
|
+
await exporter.flush();
|
|
9
|
+
return exporter.status();
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
TASK_COST_QUERY_LIMIT,
|
|
6
6
|
USAGE_MAX_DISTINCT_SCOPES,
|
|
7
7
|
} from "../constants.ts";
|
|
8
|
-
import { type MetricQuery, validateMetricObservation } from "../
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import type { OperationHandlerMap } from "
|
|
8
|
+
import { type MetricQuery, validateMetricObservation } from "../observability/metric.ts";
|
|
9
|
+
import type { MetricStore } from "../observability/store.ts";
|
|
10
|
+
import { buildTaskCostSummary } from "../observability/task-cost.ts";
|
|
11
|
+
import type { OperationHandlerMap } from "../vehicle/operation-types.ts";
|
|
12
12
|
|
|
13
13
|
/** metrics.* and service.checkpoint -- every operation whose only collaborator is the metric-store port. */
|
|
14
14
|
export function metricsOperations(metrics: MetricStore): OperationHandlerMap {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ModelRanker, ModelRecommendationInput } from "../
|
|
2
|
-
import type { RouterController } from "../
|
|
3
|
-
import type { OperationHandlerMap } from "./types.ts";
|
|
1
|
+
import type { ModelRanker, ModelRecommendationInput } from "../optimization/model-selection/ranker.ts";
|
|
2
|
+
import type { RouterController } from "../optimization/routing/controller.ts";
|
|
3
|
+
import type { OperationHandlerMap } from "./operation-types.ts";
|
|
4
4
|
|
|
5
5
|
/** models.rank -- scores candidates via the model ranker, then, only for an automatic selection, applies it as a router mutation (so it shares the same session-identity authorization as every other router mutation). */
|
|
6
6
|
export function modelRankingOperations(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* jittor's
|
|
2
|
+
* jittor's operation surface projected onto the real Vehicle protocol.
|
|
3
3
|
* Every operation delegates to the exact same handler function service.ts's
|
|
4
4
|
* hand-rolled dispatch already calls (one implementation, two projections --
|
|
5
5
|
* the same shape every other Vehicle-migrated daemon in this ecosystem
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* alongside (not replacing) the existing /api/v1/ops route.
|
|
8
8
|
*
|
|
9
9
|
* Every jittor operation already validates its own loosely-typed
|
|
10
|
-
* Record<string, unknown> input internally (see
|
|
10
|
+
* Record<string, unknown> input internally (see each feature's operation module) -- there
|
|
11
11
|
* is no separate Vehicle-side schema to duplicate that logic, so both input
|
|
12
12
|
* and output use passthroughVehicleSchema and let the real handler's own
|
|
13
13
|
* validation (already covered by service.test.ts) be the single source of
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
import type { VehicleEffect, VehicleIdempotency } from "@danypops/vehicle-core";
|
|
26
26
|
import { bindVehicleOperation, defineErrorMapping, defineVehicleOperation, passthroughVehicleSchema } from "@danypops/vehicle-core";
|
|
27
27
|
import type { VehicleRegistry } from "@danypops/vehicle-server";
|
|
28
|
-
import
|
|
28
|
+
import { InvalidSessionSecretError } from "../sessions/identity.ts";
|
|
29
|
+
import type { OperationHandlerMap } from "./operation-types.ts";
|
|
29
30
|
import type { OperationName } from "./service.ts";
|
|
30
|
-
import { InvalidSessionSecretError } from "./session-identity-service.ts";
|
|
31
31
|
|
|
32
32
|
/** Preserves the legacy route's 403 for invalid session credentials; every other rejection remains validation. */
|
|
33
33
|
const withJittorErrorParity = defineErrorMapping([
|
|
@@ -73,6 +73,8 @@ const WRITE: VehicleIdempotency = { mode: "unsafe" };
|
|
|
73
73
|
* available_routes: local-write (every one is a real router.set (or
|
|
74
74
|
* pause/resume) call, despite router.current_route's read-sounding name
|
|
75
75
|
* -- confirmed directly against router-operations.ts).
|
|
76
|
+
* - cache.economics: read (a pure projection over already-recorded metric
|
|
77
|
+
* rows plus catalog pricing; never mutates anything).
|
|
76
78
|
*/
|
|
77
79
|
const OPERATION_META: Record<OperationName, OperationMeta> = {
|
|
78
80
|
"metrics.record": { description: "Records one metric observation.", effect: "local-write" },
|
|
@@ -85,6 +87,14 @@ const OPERATION_META: Record<OperationName, OperationMeta> = {
|
|
|
85
87
|
"benchmark.refresh": { description: "Refreshes model benchmark evidence from external sources.", effect: "external-write" },
|
|
86
88
|
"benchmark.status": { description: "Reports the last benchmark refresh's own status.", effect: "read" },
|
|
87
89
|
"benchmark.query": { description: "Queries cached benchmark evidence.", effect: "read" },
|
|
90
|
+
"catalog.refresh": { description: "Refreshes the opt-in models.dev metadata snapshot.", effect: "external-write" },
|
|
91
|
+
"catalog.status": { description: "Reports model-catalog configuration and last-good snapshot status.", effect: "read" },
|
|
92
|
+
"catalog.query": { description: "Queries bounded provenance-bearing model metadata.", effect: "read" },
|
|
93
|
+
"usage.import": { description: "Imports bounded content-free usage from persisted Pi sessions.", effect: "local-write" },
|
|
94
|
+
"usage.import_status": { description: "Reports durable historical usage import progress.", effect: "read" },
|
|
95
|
+
"usage.import_cancel": { description: "Requests cancellation of active historical usage imports.", effect: "local-write" },
|
|
96
|
+
"export.status": { description: "Reports credential-safe OTLP exporter health and queue status.", effect: "read" },
|
|
97
|
+
"export.flush": { description: "Flushes the bounded OTLP export queue.", effect: "external-write" },
|
|
88
98
|
"session.register": { description: "Registers a Pi session identity, issuing a session secret.", effect: "local-write" },
|
|
89
99
|
"session.release": { description: "Releases a registered Pi session identity.", effect: "local-write" },
|
|
90
100
|
"models.rank": {
|
|
@@ -92,6 +102,8 @@ const OPERATION_META: Record<OperationName, OperationMeta> = {
|
|
|
92
102
|
effect: "local-write",
|
|
93
103
|
},
|
|
94
104
|
"context.assess": { description: "Assesses context-injection/compaction health within a bounded time window.", effect: "read" },
|
|
105
|
+
"context.delta": { description: "Returns the latest bounded content-free context delta for one opaque session.", effect: "read" },
|
|
106
|
+
"context.snapshot": { description: "Records one bounded content-free context snapshot and computes its delta.", effect: "local-write" },
|
|
95
107
|
"compaction.estimate": { description: "Estimates compaction duration from recorded samples.", effect: "read" },
|
|
96
108
|
"service.checkpoint": { description: "Flushes the metric store's write-ahead log.", effect: "local-write" },
|
|
97
109
|
"telemetry.poll": { description: "Polls external telemetry provider status.", effect: "read" },
|
|
@@ -103,6 +115,11 @@ const OPERATION_META: Record<OperationName, OperationMeta> = {
|
|
|
103
115
|
"router.clear_override": { description: "Clears a manual route override.", effect: "local-write" },
|
|
104
116
|
"router.current_route": { description: "Sets the router's currently-active route.", effect: "local-write" },
|
|
105
117
|
"router.available_routes": { description: "Sets the router's currently-available routes.", effect: "local-write" },
|
|
118
|
+
"cache.economics": {
|
|
119
|
+
description:
|
|
120
|
+
"Reports prompt-cache economics (read/write cost, savings, break-even) and candidate missed-cache opportunities within a bounded time window.",
|
|
121
|
+
effect: "read",
|
|
122
|
+
},
|
|
106
123
|
};
|
|
107
124
|
|
|
108
125
|
/** Read effects need only jittor:read; every other effect needs both (writes commonly also read first). */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import { routerSessionId } from "
|
|
4
|
-
import type { OperationHandlerMap } from "./types.ts";
|
|
1
|
+
import type { RouteOverride, RouterController } from "../optimization/routing/controller.ts";
|
|
2
|
+
import type { Route } from "../optimization/routing/policy.ts";
|
|
3
|
+
import { routerSessionId } from "../sessions/router-authorization.ts";
|
|
4
|
+
import type { OperationHandlerMap } from "./operation-types.ts";
|
|
5
5
|
|
|
6
6
|
/** telemetry.poll and every router.* operation -- reads pass a bare session_id through; mutations run authorize first, matching the opt-in session-identity armor. */
|
|
7
7
|
export function routerOperations(
|