pi-smart-router 0.1.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/.pi/extensions/smart-router/command-formatters.ts +167 -0
- package/.pi/extensions/smart-router/commands.ts +242 -0
- package/.pi/extensions/smart-router/dataset-export.ts +142 -0
- package/.pi/extensions/smart-router/delegate-stream.ts +105 -0
- package/.pi/extensions/smart-router/delegation-runtime.ts +355 -0
- package/.pi/extensions/smart-router/extension-setup.ts +115 -0
- package/.pi/extensions/smart-router/fleet-bootstrap.ts +244 -0
- package/.pi/extensions/smart-router/index.ts +115 -0
- package/.pi/extensions/smart-router/package.json +3 -0
- package/.pi/extensions/smart-router/pi-model-scope.ts +55 -0
- package/.pi/extensions/smart-router/pricing-lifecycle.ts +43 -0
- package/.pi/extensions/smart-router/route-and-delegate.ts +562 -0
- package/.pi/extensions/smart-router/routing-context.ts +171 -0
- package/.pi/extensions/smart-router/routing-outcomes.ts +44 -0
- package/.pi/extensions/smart-router/session-lifecycle.ts +140 -0
- package/.pi/extensions/smart-router/stream-delegation.ts +75 -0
- package/.pi/extensions/smart-router/types.ts +90 -0
- package/.pi/extensions/smart-router/utils.ts +58 -0
- package/README.md +593 -0
- package/bin/pi-smart-router.mjs +79 -0
- package/config/.gitkeep +0 -0
- package/config/hydra-projection-weights.json.example +1169 -0
- package/config/models.yaml.example +58 -0
- package/config/p-success-weights.json.example +19 -0
- package/config/routing-calibration.json.example +1605 -0
- package/config/routing-centroids.json.example +1570 -0
- package/config/routing-clusters.yaml.example +41 -0
- package/data/contrib/example.json +25 -0
- package/dist/api/explain/router-explain.d.ts +47 -0
- package/dist/api/explain/router-explain.d.ts.map +1 -0
- package/dist/api/explain/router-explain.js +101 -0
- package/dist/api/explain/router-explain.js.map +1 -0
- package/dist/api/middleware/pi-router-middleware.d.ts +86 -0
- package/dist/api/middleware/pi-router-middleware.d.ts.map +1 -0
- package/dist/api/middleware/pi-router-middleware.js +83 -0
- package/dist/api/middleware/pi-router-middleware.js.map +1 -0
- package/dist/cli/smart-router-cli.d.ts +85 -0
- package/dist/cli/smart-router-cli.d.ts.map +1 -0
- package/dist/cli/smart-router-cli.js +293 -0
- package/dist/cli/smart-router-cli.js.map +1 -0
- package/dist/config/defaults.d.ts +7 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +33 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/models-loader.d.ts +22 -0
- package/dist/config/models-loader.d.ts.map +1 -0
- package/dist/config/models-loader.js +51 -0
- package/dist/config/models-loader.js.map +1 -0
- package/dist/config/pi-model-mapper.d.ts +40 -0
- package/dist/config/pi-model-mapper.d.ts.map +1 -0
- package/dist/config/pi-model-mapper.js +216 -0
- package/dist/config/pi-model-mapper.js.map +1 -0
- package/dist/config/routing-clusters-loader.d.ts +35 -0
- package/dist/config/routing-clusters-loader.d.ts.map +1 -0
- package/dist/config/routing-clusters-loader.js +100 -0
- package/dist/config/routing-clusters-loader.js.map +1 -0
- package/dist/domain/delegation/delegation-context.d.ts +23 -0
- package/dist/domain/delegation/delegation-context.d.ts.map +1 -0
- package/dist/domain/delegation/delegation-context.js +73 -0
- package/dist/domain/delegation/delegation-context.js.map +1 -0
- package/dist/domain/delegation/execution-ledger.d.ts +19 -0
- package/dist/domain/delegation/execution-ledger.d.ts.map +1 -0
- package/dist/domain/delegation/execution-ledger.js +23 -0
- package/dist/domain/delegation/execution-ledger.js.map +1 -0
- package/dist/domain/delegation/output-headroom.d.ts +39 -0
- package/dist/domain/delegation/output-headroom.d.ts.map +1 -0
- package/dist/domain/delegation/output-headroom.js +78 -0
- package/dist/domain/delegation/output-headroom.js.map +1 -0
- package/dist/domain/matching/cluster-matcher.d.ts +69 -0
- package/dist/domain/matching/cluster-matcher.d.ts.map +1 -0
- package/dist/domain/matching/cluster-matcher.js +294 -0
- package/dist/domain/matching/cluster-matcher.js.map +1 -0
- package/dist/domain/matching/embedding-provider.d.ts +21 -0
- package/dist/domain/matching/embedding-provider.d.ts.map +1 -0
- package/dist/domain/matching/embedding-provider.js +42 -0
- package/dist/domain/matching/embedding-provider.js.map +1 -0
- package/dist/domain/matching/hydra-input.d.ts +18 -0
- package/dist/domain/matching/hydra-input.d.ts.map +1 -0
- package/dist/domain/matching/hydra-input.js +40 -0
- package/dist/domain/matching/hydra-input.js.map +1 -0
- package/dist/domain/matching/hydra-matcher.d.ts +103 -0
- package/dist/domain/matching/hydra-matcher.d.ts.map +1 -0
- package/dist/domain/matching/hydra-matcher.js +275 -0
- package/dist/domain/matching/hydra-matcher.js.map +1 -0
- package/dist/domain/pinning/cache-economics.d.ts +53 -0
- package/dist/domain/pinning/cache-economics.d.ts.map +1 -0
- package/dist/domain/pinning/cache-economics.js +72 -0
- package/dist/domain/pinning/cache-economics.js.map +1 -0
- package/dist/domain/pinning/loop-escalation.d.ts +41 -0
- package/dist/domain/pinning/loop-escalation.d.ts.map +1 -0
- package/dist/domain/pinning/loop-escalation.js +137 -0
- package/dist/domain/pinning/loop-escalation.js.map +1 -0
- package/dist/domain/pinning/session-pinner.d.ts +81 -0
- package/dist/domain/pinning/session-pinner.d.ts.map +1 -0
- package/dist/domain/pinning/session-pinner.js +237 -0
- package/dist/domain/pinning/session-pinner.js.map +1 -0
- package/dist/domain/pinning/sub-route-policy.d.ts +41 -0
- package/dist/domain/pinning/sub-route-policy.d.ts.map +1 -0
- package/dist/domain/pinning/sub-route-policy.js +72 -0
- package/dist/domain/pinning/sub-route-policy.js.map +1 -0
- package/dist/domain/pipeline/router-pipeline.d.ts +180 -0
- package/dist/domain/pipeline/router-pipeline.d.ts.map +1 -0
- package/dist/domain/pipeline/router-pipeline.js +807 -0
- package/dist/domain/pipeline/router-pipeline.js.map +1 -0
- package/dist/domain/pipeline/safe-default.d.ts +25 -0
- package/dist/domain/pipeline/safe-default.d.ts.map +1 -0
- package/dist/domain/pipeline/safe-default.js +41 -0
- package/dist/domain/pipeline/safe-default.js.map +1 -0
- package/dist/domain/refactor-guardrails.d.ts +48 -0
- package/dist/domain/refactor-guardrails.d.ts.map +1 -0
- package/dist/domain/refactor-guardrails.js +129 -0
- package/dist/domain/refactor-guardrails.js.map +1 -0
- package/dist/domain/routing/context-fit.d.ts +53 -0
- package/dist/domain/routing/context-fit.d.ts.map +1 -0
- package/dist/domain/routing/context-fit.js +142 -0
- package/dist/domain/routing/context-fit.js.map +1 -0
- package/dist/domain/routing/expected-cost.d.ts +63 -0
- package/dist/domain/routing/expected-cost.d.ts.map +1 -0
- package/dist/domain/routing/expected-cost.js +177 -0
- package/dist/domain/routing/expected-cost.js.map +1 -0
- package/dist/domain/routing/p-success-classifier.d.ts +130 -0
- package/dist/domain/routing/p-success-classifier.d.ts.map +1 -0
- package/dist/domain/routing/p-success-classifier.js +350 -0
- package/dist/domain/routing/p-success-classifier.js.map +1 -0
- package/dist/domain/routing/tier-features.d.ts +70 -0
- package/dist/domain/routing/tier-features.d.ts.map +1 -0
- package/dist/domain/routing/tier-features.js +174 -0
- package/dist/domain/routing/tier-features.js.map +1 -0
- package/dist/domain/routing/tool-history-guard.d.ts +32 -0
- package/dist/domain/routing/tool-history-guard.d.ts.map +1 -0
- package/dist/domain/routing/tool-history-guard.js +110 -0
- package/dist/domain/routing/tool-history-guard.js.map +1 -0
- package/dist/domain/scoring/multi-objective.d.ts +48 -0
- package/dist/domain/scoring/multi-objective.d.ts.map +1 -0
- package/dist/domain/scoring/multi-objective.js +116 -0
- package/dist/domain/scoring/multi-objective.js.map +1 -0
- package/dist/domain/triage/triage-engine.d.ts +43 -0
- package/dist/domain/triage/triage-engine.d.ts.map +1 -0
- package/dist/domain/triage/triage-engine.js +317 -0
- package/dist/domain/triage/triage-engine.js.map +1 -0
- package/dist/domain/triage/turn-envelope.d.ts +17 -0
- package/dist/domain/triage/turn-envelope.d.ts.map +1 -0
- package/dist/domain/triage/turn-envelope.js +81 -0
- package/dist/domain/triage/turn-envelope.js.map +1 -0
- package/dist/domain/types/entities.d.ts +303 -0
- package/dist/domain/types/entities.d.ts.map +1 -0
- package/dist/domain/types/entities.js +6 -0
- package/dist/domain/types/entities.js.map +1 -0
- package/dist/domain/types/index.d.ts +4 -0
- package/dist/domain/types/index.d.ts.map +1 -0
- package/dist/domain/types/index.js +2 -0
- package/dist/domain/types/index.js.map +1 -0
- package/dist/domain/types/schemas.d.ts +346 -0
- package/dist/domain/types/schemas.d.ts.map +1 -0
- package/dist/domain/types/schemas.js +241 -0
- package/dist/domain/types/schemas.js.map +1 -0
- package/dist/domain/types/store-port.d.ts +44 -0
- package/dist/domain/types/store-port.d.ts.map +1 -0
- package/dist/domain/types/store-port.js +6 -0
- package/dist/domain/types/store-port.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/infra/gemini-provider.d.ts +28 -0
- package/dist/infra/gemini-provider.d.ts.map +1 -0
- package/dist/infra/gemini-provider.js +112 -0
- package/dist/infra/gemini-provider.js.map +1 -0
- package/dist/infra/telemetry.d.ts +51 -0
- package/dist/infra/telemetry.d.ts.map +1 -0
- package/dist/infra/telemetry.js +100 -0
- package/dist/infra/telemetry.js.map +1 -0
- package/dist/infrastructure/delegation/provider-error.d.ts +44 -0
- package/dist/infrastructure/delegation/provider-error.d.ts.map +1 -0
- package/dist/infrastructure/delegation/provider-error.js +179 -0
- package/dist/infrastructure/delegation/provider-error.js.map +1 -0
- package/dist/infrastructure/gateway/circuit-breaker.d.ts +68 -0
- package/dist/infrastructure/gateway/circuit-breaker.d.ts.map +1 -0
- package/dist/infrastructure/gateway/circuit-breaker.js +150 -0
- package/dist/infrastructure/gateway/circuit-breaker.js.map +1 -0
- package/dist/infrastructure/gateway/gateway-dispatch.d.ts +138 -0
- package/dist/infrastructure/gateway/gateway-dispatch.d.ts.map +1 -0
- package/dist/infrastructure/gateway/gateway-dispatch.js +308 -0
- package/dist/infrastructure/gateway/gateway-dispatch.js.map +1 -0
- package/dist/infrastructure/hardware/hardware-probe.d.ts +32 -0
- package/dist/infrastructure/hardware/hardware-probe.d.ts.map +1 -0
- package/dist/infrastructure/hardware/hardware-probe.js +199 -0
- package/dist/infrastructure/hardware/hardware-probe.js.map +1 -0
- package/dist/infrastructure/local/local-zero-tier.d.ts +47 -0
- package/dist/infrastructure/local/local-zero-tier.d.ts.map +1 -0
- package/dist/infrastructure/local/local-zero-tier.js +92 -0
- package/dist/infrastructure/local/local-zero-tier.js.map +1 -0
- package/dist/infrastructure/persistence/memory-store.d.ts +31 -0
- package/dist/infrastructure/persistence/memory-store.d.ts.map +1 -0
- package/dist/infrastructure/persistence/memory-store.js +87 -0
- package/dist/infrastructure/persistence/memory-store.js.map +1 -0
- package/dist/infrastructure/persistence/sqlite-store.d.ts +81 -0
- package/dist/infrastructure/persistence/sqlite-store.d.ts.map +1 -0
- package/dist/infrastructure/persistence/sqlite-store.js +658 -0
- package/dist/infrastructure/persistence/sqlite-store.js.map +1 -0
- package/dist/infrastructure/pricing/litellm-fetch.d.ts +46 -0
- package/dist/infrastructure/pricing/litellm-fetch.d.ts.map +1 -0
- package/dist/infrastructure/pricing/litellm-fetch.js +145 -0
- package/dist/infrastructure/pricing/litellm-fetch.js.map +1 -0
- package/dist/infrastructure/pricing/price-broker.d.ts +56 -0
- package/dist/infrastructure/pricing/price-broker.d.ts.map +1 -0
- package/dist/infrastructure/pricing/price-broker.js +133 -0
- package/dist/infrastructure/pricing/price-broker.js.map +1 -0
- package/dist/infrastructure/pricing/pricing-monitor.d.ts +27 -0
- package/dist/infrastructure/pricing/pricing-monitor.d.ts.map +1 -0
- package/dist/infrastructure/pricing/pricing-monitor.js +46 -0
- package/dist/infrastructure/pricing/pricing-monitor.js.map +1 -0
- package/dist/infrastructure/telemetry/dataset-limits.d.ts +13 -0
- package/dist/infrastructure/telemetry/dataset-limits.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/dataset-limits.js +28 -0
- package/dist/infrastructure/telemetry/dataset-limits.js.map +1 -0
- package/dist/infrastructure/telemetry/dataset-recorder.d.ts +48 -0
- package/dist/infrastructure/telemetry/dataset-recorder.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/dataset-recorder.js +154 -0
- package/dist/infrastructure/telemetry/dataset-recorder.js.map +1 -0
- package/dist/infrastructure/telemetry/outcome-limits.d.ts +12 -0
- package/dist/infrastructure/telemetry/outcome-limits.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/outcome-limits.js +28 -0
- package/dist/infrastructure/telemetry/outcome-limits.js.map +1 -0
- package/dist/infrastructure/telemetry/outcome-recorder.d.ts +29 -0
- package/dist/infrastructure/telemetry/outcome-recorder.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/outcome-recorder.js +49 -0
- package/dist/infrastructure/telemetry/outcome-recorder.js.map +1 -0
- package/dist/infrastructure/telemetry/routing-telemetry.d.ts +115 -0
- package/dist/infrastructure/telemetry/routing-telemetry.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/routing-telemetry.js +529 -0
- package/dist/infrastructure/telemetry/routing-telemetry.js.map +1 -0
- package/dist/infrastructure/telemetry/telemetry-limits.d.ts +16 -0
- package/dist/infrastructure/telemetry/telemetry-limits.d.ts.map +1 -0
- package/dist/infrastructure/telemetry/telemetry-limits.js +35 -0
- package/dist/infrastructure/telemetry/telemetry-limits.js.map +1 -0
- package/package.json +110 -0
- package/skills/router-backlog-orchestrator/SKILL.md +183 -0
- package/skills/router-backlog-orchestrator/references/github-router-issue-template.md +78 -0
- package/skills/router-backlog-orchestrator/references/packet-from-issue.md +99 -0
- package/skills/router-backlog-orchestrator/references/prioritization-rubric.md +65 -0
- package/skills/router-backlog-orchestrator/scripts/collect-backlog.sh +44 -0
- package/specs/001-build-smart-router/contracts/telemetry-contrib.schema.json +151 -0
- package/src/api/explain/.gitkeep +0 -0
- package/src/api/explain/router-explain.ts +146 -0
- package/src/api/middleware/.gitkeep +0 -0
- package/src/api/middleware/pi-router-middleware.ts +169 -0
- package/src/cli/smart-router-cli.ts +436 -0
- package/src/config/.gitkeep +0 -0
- package/src/config/defaults.ts +35 -0
- package/src/config/models-loader.ts +68 -0
- package/src/config/pi-model-mapper.ts +285 -0
- package/src/config/routing-clusters-loader.ts +148 -0
- package/src/domain/delegation/delegation-context.ts +111 -0
- package/src/domain/delegation/execution-ledger.ts +34 -0
- package/src/domain/delegation/output-headroom.ts +131 -0
- package/src/domain/matching/.gitkeep +0 -0
- package/src/domain/matching/cluster-matcher.ts +474 -0
- package/src/domain/matching/embedding-provider.ts +79 -0
- package/src/domain/matching/hydra-input.ts +53 -0
- package/src/domain/matching/hydra-matcher.ts +454 -0
- package/src/domain/pinning/.gitkeep +0 -0
- package/src/domain/pinning/cache-economics.ts +128 -0
- package/src/domain/pinning/loop-escalation.ts +181 -0
- package/src/domain/pinning/session-pinner.ts +388 -0
- package/src/domain/pinning/sub-route-policy.ts +119 -0
- package/src/domain/pipeline/.gitkeep +0 -0
- package/src/domain/pipeline/router-pipeline.ts +1139 -0
- package/src/domain/pipeline/safe-default.ts +70 -0
- package/src/domain/refactor-guardrails.ts +202 -0
- package/src/domain/routing/context-fit.ts +221 -0
- package/src/domain/routing/expected-cost.ts +320 -0
- package/src/domain/routing/p-success-classifier.ts +511 -0
- package/src/domain/routing/tier-features.ts +290 -0
- package/src/domain/routing/tool-history-guard.ts +159 -0
- package/src/domain/scoring/.gitkeep +0 -0
- package/src/domain/scoring/multi-objective.ts +175 -0
- package/src/domain/triage/.gitkeep +0 -0
- package/src/domain/triage/triage-engine.ts +373 -0
- package/src/domain/triage/turn-envelope.ts +104 -0
- package/src/domain/types/.gitkeep +0 -0
- package/src/domain/types/entities.ts +384 -0
- package/src/domain/types/index.ts +41 -0
- package/src/domain/types/schemas.ts +289 -0
- package/src/domain/types/store-port.ts +59 -0
- package/src/index.ts +103 -0
- package/src/infra/gemini-provider.ts +142 -0
- package/src/infra/telemetry.ts +169 -0
- package/src/infrastructure/delegation/provider-error.ts +251 -0
- package/src/infrastructure/gateway/.gitkeep +0 -0
- package/src/infrastructure/gateway/circuit-breaker.ts +196 -0
- package/src/infrastructure/gateway/gateway-dispatch.ts +444 -0
- package/src/infrastructure/hardware/.gitkeep +0 -0
- package/src/infrastructure/hardware/hardware-probe.ts +276 -0
- package/src/infrastructure/local/.gitkeep +0 -0
- package/src/infrastructure/local/local-zero-tier.ts +151 -0
- package/src/infrastructure/persistence/.gitkeep +0 -0
- package/src/infrastructure/persistence/memory-store.ts +122 -0
- package/src/infrastructure/persistence/sqlite-store.ts +900 -0
- package/src/infrastructure/pricing/.gitkeep +0 -0
- package/src/infrastructure/pricing/litellm-fetch.ts +215 -0
- package/src/infrastructure/pricing/price-broker.ts +183 -0
- package/src/infrastructure/pricing/pricing-monitor.ts +65 -0
- package/src/infrastructure/telemetry/.gitkeep +0 -0
- package/src/infrastructure/telemetry/dataset-limits.ts +39 -0
- package/src/infrastructure/telemetry/dataset-recorder.ts +215 -0
- package/src/infrastructure/telemetry/outcome-limits.ts +42 -0
- package/src/infrastructure/telemetry/outcome-recorder.ts +118 -0
- package/src/infrastructure/telemetry/routing-telemetry.ts +824 -0
- package/src/infrastructure/telemetry/telemetry-limits.ts +50 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local zero-tier readiness pings — T045, FR-012, FR-013.
|
|
3
|
+
*
|
|
4
|
+
* Pings LM Studio and Ollama HTTP endpoints in parallel to determine
|
|
5
|
+
* whether a local model is loaded and ready. Combined latency target <15ms.
|
|
6
|
+
*
|
|
7
|
+
* Never throws — unreachable services return `available: false`.
|
|
8
|
+
* Port-based HTTP for testability; default uses Node.js global fetch.
|
|
9
|
+
*/
|
|
10
|
+
// ─── Defaults ────────────────────────────────────────────────────────────────
|
|
11
|
+
export const DEFAULT_LOCAL_CONFIG = {
|
|
12
|
+
lmStudioBaseUrl: 'http://127.0.0.1:1234',
|
|
13
|
+
ollamaBaseUrl: 'http://127.0.0.1:11434',
|
|
14
|
+
pingTimeoutMs: 500,
|
|
15
|
+
};
|
|
16
|
+
const UNAVAILABLE = {
|
|
17
|
+
available: false,
|
|
18
|
+
hasLoadedModel: false,
|
|
19
|
+
latencyMs: 0,
|
|
20
|
+
};
|
|
21
|
+
async function pingLmStudio(baseUrl, signal, httpFetch) {
|
|
22
|
+
const start = performance.now();
|
|
23
|
+
try {
|
|
24
|
+
const res = await httpFetch.fetch(`${baseUrl}/v1/models`, { signal });
|
|
25
|
+
const latencyMs = performance.now() - start;
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
return { available: true, hasLoadedModel: false, latencyMs };
|
|
28
|
+
}
|
|
29
|
+
const body = (await res.json());
|
|
30
|
+
const hasLoadedModel = Array.isArray(body.data) && body.data.length > 0;
|
|
31
|
+
return { available: true, hasLoadedModel, latencyMs };
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { ...UNAVAILABLE, latencyMs: performance.now() - start };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function pingOllama(baseUrl, signal, httpFetch) {
|
|
38
|
+
const start = performance.now();
|
|
39
|
+
try {
|
|
40
|
+
const res = await httpFetch.fetch(`${baseUrl}/api/tags`, { signal });
|
|
41
|
+
const latencyMs = performance.now() - start;
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
return { available: true, hasLoadedModel: false, latencyMs };
|
|
44
|
+
}
|
|
45
|
+
const body = (await res.json());
|
|
46
|
+
const hasLoadedModel = Array.isArray(body.models) && body.models.length > 0;
|
|
47
|
+
return { available: true, hasLoadedModel, latencyMs };
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return { ...UNAVAILABLE, latencyMs: performance.now() - start };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
54
|
+
/**
|
|
55
|
+
* Default HTTP fetch port using Node.js global fetch.
|
|
56
|
+
*/
|
|
57
|
+
export const defaultHttpFetch = {
|
|
58
|
+
fetch: (url, init) => globalThis.fetch(url, init),
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Ping LM Studio and Ollama in parallel. Returns readiness state for each
|
|
62
|
+
* service and whether any local model is loaded and ready for inference.
|
|
63
|
+
*
|
|
64
|
+
* Combined latency target: <15ms on a healthy system.
|
|
65
|
+
*/
|
|
66
|
+
export async function pingLocalServices(config = DEFAULT_LOCAL_CONFIG, httpFetch = defaultHttpFetch) {
|
|
67
|
+
const overallStart = performance.now();
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
const timeout = setTimeout(() => controller.abort(), config.pingTimeoutMs);
|
|
70
|
+
try {
|
|
71
|
+
const [lmStudio, ollama] = await Promise.all([
|
|
72
|
+
pingLmStudio(config.lmStudioBaseUrl, controller.signal, httpFetch),
|
|
73
|
+
pingOllama(config.ollamaBaseUrl, controller.signal, httpFetch),
|
|
74
|
+
]);
|
|
75
|
+
const combinedLatencyMs = performance.now() - overallStart;
|
|
76
|
+
const anyModelReady = lmStudio.hasLoadedModel || ollama.hasLoadedModel;
|
|
77
|
+
return { lmStudio, ollama, anyModelReady, combinedLatencyMs };
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// FR-022: never crash — return both unavailable on unexpected error
|
|
81
|
+
return {
|
|
82
|
+
lmStudio: UNAVAILABLE,
|
|
83
|
+
ollama: UNAVAILABLE,
|
|
84
|
+
anyModelReady: false,
|
|
85
|
+
combinedLatencyMs: performance.now() - overallStart,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
clearTimeout(timeout);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=local-zero-tier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-zero-tier.js","sourceRoot":"","sources":["../../../src/infrastructure/local/local-zero-tier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory persistence store — fallback when SQLite is unavailable.
|
|
3
|
+
*
|
|
4
|
+
* Implements StorePort for process-local state. Data does not survive
|
|
5
|
+
* process restart. Used as a safety net per FR-025: when the SQLite
|
|
6
|
+
* state store is unavailable, degrade to in-memory rather than crash.
|
|
7
|
+
*/
|
|
8
|
+
import type { ModelProfile, PriceCatalog, RoutingDatasetRecord, RoutingOutcomeRecord, RoutingTelemetry, SessionPin } from '../../domain/types/entities.js';
|
|
9
|
+
import type { ListDatasetOptions, ListOutcomeOptions, ListTelemetryOptions, StorePort } from '../../domain/types/store-port.js';
|
|
10
|
+
export declare class MemoryStore implements StorePort {
|
|
11
|
+
private readonly pins;
|
|
12
|
+
private readonly models;
|
|
13
|
+
private priceCatalog;
|
|
14
|
+
private readonly telemetry;
|
|
15
|
+
private readonly dataset;
|
|
16
|
+
private readonly outcomes;
|
|
17
|
+
constructor(models?: readonly ModelProfile[]);
|
|
18
|
+
getSessionPin(sessionId: string): Promise<SessionPin | null>;
|
|
19
|
+
putSessionPin(pin: SessionPin): Promise<void>;
|
|
20
|
+
deleteSessionPin(sessionId: string): Promise<void>;
|
|
21
|
+
getModelProfiles(): Promise<readonly ModelProfile[]>;
|
|
22
|
+
getPriceCatalog(): Promise<PriceCatalog | null>;
|
|
23
|
+
putPriceCatalog(catalog: PriceCatalog): Promise<void>;
|
|
24
|
+
appendTelemetry(entry: RoutingTelemetry): void;
|
|
25
|
+
listTelemetry(options?: ListTelemetryOptions): Promise<readonly RoutingTelemetry[]>;
|
|
26
|
+
appendDatasetRecord(entry: RoutingDatasetRecord): void;
|
|
27
|
+
listDatasetRecords(options?: ListDatasetOptions): Promise<readonly RoutingDatasetRecord[]>;
|
|
28
|
+
appendOutcomeRecord(entry: RoutingOutcomeRecord): void;
|
|
29
|
+
listOutcomeRecords(options?: ListOutcomeOptions): Promise<readonly RoutingOutcomeRecord[]>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=memory-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/persistence/memory-store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC3J,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAchI,qBAAa,WAAY,YAAW,SAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;gBAE3C,MAAM,GAAE,SAAS,YAAY,EAAO;IAI1C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI5D,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,gBAAgB,IAAI,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;IAIpD,eAAe,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAI/C,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAKxC,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC;IAazF,mBAAmB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAKhD,kBAAkB,CACtB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC;IAQ3C,mBAAmB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAKhD,kBAAkB,CACtB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC;CAe5C"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory persistence store — fallback when SQLite is unavailable.
|
|
3
|
+
*
|
|
4
|
+
* Implements StorePort for process-local state. Data does not survive
|
|
5
|
+
* process restart. Used as a safety net per FR-025: when the SQLite
|
|
6
|
+
* state store is unavailable, degrade to in-memory rather than crash.
|
|
7
|
+
*/
|
|
8
|
+
import { DEFAULT_HISTORY_LIMIT, MAX_HISTORY_LIMIT, TELEMETRY_MAX_ENTRIES, makeTelemetryRoom, } from '../telemetry/telemetry-limits.js';
|
|
9
|
+
import { makeDatasetRoom, } from '../telemetry/dataset-limits.js';
|
|
10
|
+
import { makeOutcomeRoom, } from '../telemetry/outcome-limits.js';
|
|
11
|
+
export class MemoryStore {
|
|
12
|
+
pins = new Map();
|
|
13
|
+
models;
|
|
14
|
+
priceCatalog = null;
|
|
15
|
+
telemetry = [];
|
|
16
|
+
dataset = [];
|
|
17
|
+
outcomes = [];
|
|
18
|
+
constructor(models = []) {
|
|
19
|
+
this.models = models;
|
|
20
|
+
}
|
|
21
|
+
async getSessionPin(sessionId) {
|
|
22
|
+
return this.pins.get(sessionId) ?? null;
|
|
23
|
+
}
|
|
24
|
+
async putSessionPin(pin) {
|
|
25
|
+
this.pins.set(pin.session_id, pin);
|
|
26
|
+
}
|
|
27
|
+
async deleteSessionPin(sessionId) {
|
|
28
|
+
this.pins.delete(sessionId);
|
|
29
|
+
}
|
|
30
|
+
async getModelProfiles() {
|
|
31
|
+
return this.models;
|
|
32
|
+
}
|
|
33
|
+
async getPriceCatalog() {
|
|
34
|
+
return this.priceCatalog;
|
|
35
|
+
}
|
|
36
|
+
async putPriceCatalog(catalog) {
|
|
37
|
+
this.priceCatalog = catalog;
|
|
38
|
+
}
|
|
39
|
+
appendTelemetry(entry) {
|
|
40
|
+
makeTelemetryRoom(this.telemetry, TELEMETRY_MAX_ENTRIES);
|
|
41
|
+
this.telemetry.push(entry);
|
|
42
|
+
}
|
|
43
|
+
async listTelemetry(options) {
|
|
44
|
+
const limit = clampHistoryLimit(options?.limit);
|
|
45
|
+
const sessionId = options?.sessionId;
|
|
46
|
+
const filtered = sessionId
|
|
47
|
+
? this.telemetry.filter((entry) => entry.session_id === sessionId)
|
|
48
|
+
: this.telemetry;
|
|
49
|
+
return [...filtered]
|
|
50
|
+
.reverse()
|
|
51
|
+
.slice(0, limit);
|
|
52
|
+
}
|
|
53
|
+
appendDatasetRecord(entry) {
|
|
54
|
+
makeDatasetRoom(this.dataset);
|
|
55
|
+
this.dataset.push(entry);
|
|
56
|
+
}
|
|
57
|
+
async listDatasetRecords(options) {
|
|
58
|
+
const limit = clampHistoryLimit(options?.limit);
|
|
59
|
+
return [...this.dataset]
|
|
60
|
+
.reverse()
|
|
61
|
+
.slice(0, limit);
|
|
62
|
+
}
|
|
63
|
+
appendOutcomeRecord(entry) {
|
|
64
|
+
makeOutcomeRoom(this.outcomes);
|
|
65
|
+
this.outcomes.push(entry);
|
|
66
|
+
}
|
|
67
|
+
async listOutcomeRecords(options) {
|
|
68
|
+
const limit = clampHistoryLimit(options?.limit);
|
|
69
|
+
const requestId = options?.requestId;
|
|
70
|
+
const sessionId = options?.sessionId;
|
|
71
|
+
const filtered = requestId
|
|
72
|
+
? this.outcomes.filter((entry) => entry.request_id === requestId)
|
|
73
|
+
: sessionId
|
|
74
|
+
? this.outcomes.filter((entry) => entry.session_id === sessionId)
|
|
75
|
+
: this.outcomes;
|
|
76
|
+
return [...filtered]
|
|
77
|
+
.reverse()
|
|
78
|
+
.slice(0, limit);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function clampHistoryLimit(limit) {
|
|
82
|
+
if (limit === undefined) {
|
|
83
|
+
return DEFAULT_HISTORY_LIMIT;
|
|
84
|
+
}
|
|
85
|
+
return Math.min(Math.max(1, Math.floor(limit)), MAX_HISTORY_LIMIT);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=memory-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-store.js","sourceRoot":"","sources":["../../../src/infrastructure/persistence/memory-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite-backed persistence store for routing state.
|
|
3
|
+
*
|
|
4
|
+
* Implements StorePort from domain types, plus token-bucket rate limiting.
|
|
5
|
+
* Uses WAL journal mode for concurrent reads and BEGIN IMMEDIATE for
|
|
6
|
+
* atomic token-bucket operations (prevents TOCTOU on rate_limits table).
|
|
7
|
+
*
|
|
8
|
+
* Maps to T013 in the routing pipeline spec.
|
|
9
|
+
*/
|
|
10
|
+
import type { ModelProfile, PriceCatalog, RoutingDatasetRecord, RoutingOutcomeRecord, RoutingTelemetry, SessionPin } from '../../domain/types/entities.js';
|
|
11
|
+
import type { ListDatasetOptions, ListOutcomeOptions, ListTelemetryOptions, StorePort } from '../../domain/types/store-port.js';
|
|
12
|
+
export interface TokenBucketResult {
|
|
13
|
+
readonly allowed: boolean;
|
|
14
|
+
readonly remaining: number;
|
|
15
|
+
readonly retryAfterSeconds: number | null;
|
|
16
|
+
}
|
|
17
|
+
export interface SqliteStoreOptions {
|
|
18
|
+
/** Path to SQLite database file, or ':memory:' for tests. */
|
|
19
|
+
readonly dbPath: string;
|
|
20
|
+
/** Fleet catalog (loaded from YAML config, not persisted in SQLite). */
|
|
21
|
+
readonly models: readonly ModelProfile[];
|
|
22
|
+
}
|
|
23
|
+
export interface CreateStoreResult {
|
|
24
|
+
readonly store: StorePort;
|
|
25
|
+
readonly degraded: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a persistence store with corrupt-DB recovery.
|
|
29
|
+
*
|
|
30
|
+
* Strategy:
|
|
31
|
+
* 1. Attempt to open the SQLite DB and run migrations.
|
|
32
|
+
* 2. On failure (corrupt/locked): rename the file, try fresh creation.
|
|
33
|
+
* 3. If recreation also fails: fall back to MemoryStore.
|
|
34
|
+
*
|
|
35
|
+
* Never throws — the host agent must not crash due to persistence issues.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createResilientStore(options: SqliteStoreOptions): CreateStoreResult;
|
|
38
|
+
export declare class SqliteStore implements StorePort {
|
|
39
|
+
private readonly db;
|
|
40
|
+
private readonly models;
|
|
41
|
+
private readonly consumeTokenTx;
|
|
42
|
+
constructor(options: SqliteStoreOptions);
|
|
43
|
+
getSessionPin(sessionId: string): Promise<SessionPin | null>;
|
|
44
|
+
putSessionPin(pin: SessionPin): Promise<void>;
|
|
45
|
+
deleteSessionPin(sessionId: string): Promise<void>;
|
|
46
|
+
getModelProfiles(): Promise<readonly ModelProfile[]>;
|
|
47
|
+
getPriceCatalog(): Promise<PriceCatalog | null>;
|
|
48
|
+
putPriceCatalog(catalog: PriceCatalog): Promise<void>;
|
|
49
|
+
appendTelemetry(entry: RoutingTelemetry): void;
|
|
50
|
+
listTelemetry(options?: ListTelemetryOptions): Promise<readonly RoutingTelemetry[]>;
|
|
51
|
+
private evictTelemetryRows;
|
|
52
|
+
appendDatasetRecord(entry: RoutingDatasetRecord): void;
|
|
53
|
+
listDatasetRecords(options?: ListDatasetOptions): Promise<readonly RoutingDatasetRecord[]>;
|
|
54
|
+
private evictDatasetRows;
|
|
55
|
+
appendOutcomeRecord(entry: RoutingOutcomeRecord): void;
|
|
56
|
+
listOutcomeRecords(options?: ListOutcomeOptions): Promise<readonly RoutingOutcomeRecord[]>;
|
|
57
|
+
private evictOutcomeRows;
|
|
58
|
+
/**
|
|
59
|
+
* Initialize a token bucket. Idempotent — existing buckets are unchanged.
|
|
60
|
+
*/
|
|
61
|
+
initBucket(key: string, maxTokens: number, refillRate: number): void;
|
|
62
|
+
/**
|
|
63
|
+
* Atomically attempt to consume tokens from a bucket.
|
|
64
|
+
*
|
|
65
|
+
* Uses BEGIN IMMEDIATE to acquire a reserved lock before reading,
|
|
66
|
+
* preventing TOCTOU races between concurrent consumers.
|
|
67
|
+
*/
|
|
68
|
+
consumeToken(key: string, cost?: number): TokenBucketResult;
|
|
69
|
+
/** Run PRAGMA integrity_check. Returns true if the database is healthy. */
|
|
70
|
+
checkHealth(): boolean;
|
|
71
|
+
/** Close the database connection. */
|
|
72
|
+
close(): void;
|
|
73
|
+
private initialize;
|
|
74
|
+
private runMigrations;
|
|
75
|
+
private buildConsumeTokenTx;
|
|
76
|
+
}
|
|
77
|
+
export declare class SqliteStoreError extends Error {
|
|
78
|
+
readonly name = "SqliteStoreError";
|
|
79
|
+
constructor(message: string, options?: ErrorOptions);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=sqlite-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/persistence/sqlite-store.ts"],"names":[],"mappings":"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"}
|