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.
Files changed (310) hide show
  1. package/.pi/extensions/smart-router/command-formatters.ts +167 -0
  2. package/.pi/extensions/smart-router/commands.ts +242 -0
  3. package/.pi/extensions/smart-router/dataset-export.ts +142 -0
  4. package/.pi/extensions/smart-router/delegate-stream.ts +105 -0
  5. package/.pi/extensions/smart-router/delegation-runtime.ts +355 -0
  6. package/.pi/extensions/smart-router/extension-setup.ts +115 -0
  7. package/.pi/extensions/smart-router/fleet-bootstrap.ts +244 -0
  8. package/.pi/extensions/smart-router/index.ts +115 -0
  9. package/.pi/extensions/smart-router/package.json +3 -0
  10. package/.pi/extensions/smart-router/pi-model-scope.ts +55 -0
  11. package/.pi/extensions/smart-router/pricing-lifecycle.ts +43 -0
  12. package/.pi/extensions/smart-router/route-and-delegate.ts +562 -0
  13. package/.pi/extensions/smart-router/routing-context.ts +171 -0
  14. package/.pi/extensions/smart-router/routing-outcomes.ts +44 -0
  15. package/.pi/extensions/smart-router/session-lifecycle.ts +140 -0
  16. package/.pi/extensions/smart-router/stream-delegation.ts +75 -0
  17. package/.pi/extensions/smart-router/types.ts +90 -0
  18. package/.pi/extensions/smart-router/utils.ts +58 -0
  19. package/README.md +593 -0
  20. package/bin/pi-smart-router.mjs +79 -0
  21. package/config/.gitkeep +0 -0
  22. package/config/hydra-projection-weights.json.example +1169 -0
  23. package/config/models.yaml.example +58 -0
  24. package/config/p-success-weights.json.example +19 -0
  25. package/config/routing-calibration.json.example +1605 -0
  26. package/config/routing-centroids.json.example +1570 -0
  27. package/config/routing-clusters.yaml.example +41 -0
  28. package/data/contrib/example.json +25 -0
  29. package/dist/api/explain/router-explain.d.ts +47 -0
  30. package/dist/api/explain/router-explain.d.ts.map +1 -0
  31. package/dist/api/explain/router-explain.js +101 -0
  32. package/dist/api/explain/router-explain.js.map +1 -0
  33. package/dist/api/middleware/pi-router-middleware.d.ts +86 -0
  34. package/dist/api/middleware/pi-router-middleware.d.ts.map +1 -0
  35. package/dist/api/middleware/pi-router-middleware.js +83 -0
  36. package/dist/api/middleware/pi-router-middleware.js.map +1 -0
  37. package/dist/cli/smart-router-cli.d.ts +85 -0
  38. package/dist/cli/smart-router-cli.d.ts.map +1 -0
  39. package/dist/cli/smart-router-cli.js +293 -0
  40. package/dist/cli/smart-router-cli.js.map +1 -0
  41. package/dist/config/defaults.d.ts +7 -0
  42. package/dist/config/defaults.d.ts.map +1 -0
  43. package/dist/config/defaults.js +33 -0
  44. package/dist/config/defaults.js.map +1 -0
  45. package/dist/config/models-loader.d.ts +22 -0
  46. package/dist/config/models-loader.d.ts.map +1 -0
  47. package/dist/config/models-loader.js +51 -0
  48. package/dist/config/models-loader.js.map +1 -0
  49. package/dist/config/pi-model-mapper.d.ts +40 -0
  50. package/dist/config/pi-model-mapper.d.ts.map +1 -0
  51. package/dist/config/pi-model-mapper.js +216 -0
  52. package/dist/config/pi-model-mapper.js.map +1 -0
  53. package/dist/config/routing-clusters-loader.d.ts +35 -0
  54. package/dist/config/routing-clusters-loader.d.ts.map +1 -0
  55. package/dist/config/routing-clusters-loader.js +100 -0
  56. package/dist/config/routing-clusters-loader.js.map +1 -0
  57. package/dist/domain/delegation/delegation-context.d.ts +23 -0
  58. package/dist/domain/delegation/delegation-context.d.ts.map +1 -0
  59. package/dist/domain/delegation/delegation-context.js +73 -0
  60. package/dist/domain/delegation/delegation-context.js.map +1 -0
  61. package/dist/domain/delegation/execution-ledger.d.ts +19 -0
  62. package/dist/domain/delegation/execution-ledger.d.ts.map +1 -0
  63. package/dist/domain/delegation/execution-ledger.js +23 -0
  64. package/dist/domain/delegation/execution-ledger.js.map +1 -0
  65. package/dist/domain/delegation/output-headroom.d.ts +39 -0
  66. package/dist/domain/delegation/output-headroom.d.ts.map +1 -0
  67. package/dist/domain/delegation/output-headroom.js +78 -0
  68. package/dist/domain/delegation/output-headroom.js.map +1 -0
  69. package/dist/domain/matching/cluster-matcher.d.ts +69 -0
  70. package/dist/domain/matching/cluster-matcher.d.ts.map +1 -0
  71. package/dist/domain/matching/cluster-matcher.js +294 -0
  72. package/dist/domain/matching/cluster-matcher.js.map +1 -0
  73. package/dist/domain/matching/embedding-provider.d.ts +21 -0
  74. package/dist/domain/matching/embedding-provider.d.ts.map +1 -0
  75. package/dist/domain/matching/embedding-provider.js +42 -0
  76. package/dist/domain/matching/embedding-provider.js.map +1 -0
  77. package/dist/domain/matching/hydra-input.d.ts +18 -0
  78. package/dist/domain/matching/hydra-input.d.ts.map +1 -0
  79. package/dist/domain/matching/hydra-input.js +40 -0
  80. package/dist/domain/matching/hydra-input.js.map +1 -0
  81. package/dist/domain/matching/hydra-matcher.d.ts +103 -0
  82. package/dist/domain/matching/hydra-matcher.d.ts.map +1 -0
  83. package/dist/domain/matching/hydra-matcher.js +275 -0
  84. package/dist/domain/matching/hydra-matcher.js.map +1 -0
  85. package/dist/domain/pinning/cache-economics.d.ts +53 -0
  86. package/dist/domain/pinning/cache-economics.d.ts.map +1 -0
  87. package/dist/domain/pinning/cache-economics.js +72 -0
  88. package/dist/domain/pinning/cache-economics.js.map +1 -0
  89. package/dist/domain/pinning/loop-escalation.d.ts +41 -0
  90. package/dist/domain/pinning/loop-escalation.d.ts.map +1 -0
  91. package/dist/domain/pinning/loop-escalation.js +137 -0
  92. package/dist/domain/pinning/loop-escalation.js.map +1 -0
  93. package/dist/domain/pinning/session-pinner.d.ts +81 -0
  94. package/dist/domain/pinning/session-pinner.d.ts.map +1 -0
  95. package/dist/domain/pinning/session-pinner.js +237 -0
  96. package/dist/domain/pinning/session-pinner.js.map +1 -0
  97. package/dist/domain/pinning/sub-route-policy.d.ts +41 -0
  98. package/dist/domain/pinning/sub-route-policy.d.ts.map +1 -0
  99. package/dist/domain/pinning/sub-route-policy.js +72 -0
  100. package/dist/domain/pinning/sub-route-policy.js.map +1 -0
  101. package/dist/domain/pipeline/router-pipeline.d.ts +180 -0
  102. package/dist/domain/pipeline/router-pipeline.d.ts.map +1 -0
  103. package/dist/domain/pipeline/router-pipeline.js +807 -0
  104. package/dist/domain/pipeline/router-pipeline.js.map +1 -0
  105. package/dist/domain/pipeline/safe-default.d.ts +25 -0
  106. package/dist/domain/pipeline/safe-default.d.ts.map +1 -0
  107. package/dist/domain/pipeline/safe-default.js +41 -0
  108. package/dist/domain/pipeline/safe-default.js.map +1 -0
  109. package/dist/domain/refactor-guardrails.d.ts +48 -0
  110. package/dist/domain/refactor-guardrails.d.ts.map +1 -0
  111. package/dist/domain/refactor-guardrails.js +129 -0
  112. package/dist/domain/refactor-guardrails.js.map +1 -0
  113. package/dist/domain/routing/context-fit.d.ts +53 -0
  114. package/dist/domain/routing/context-fit.d.ts.map +1 -0
  115. package/dist/domain/routing/context-fit.js +142 -0
  116. package/dist/domain/routing/context-fit.js.map +1 -0
  117. package/dist/domain/routing/expected-cost.d.ts +63 -0
  118. package/dist/domain/routing/expected-cost.d.ts.map +1 -0
  119. package/dist/domain/routing/expected-cost.js +177 -0
  120. package/dist/domain/routing/expected-cost.js.map +1 -0
  121. package/dist/domain/routing/p-success-classifier.d.ts +130 -0
  122. package/dist/domain/routing/p-success-classifier.d.ts.map +1 -0
  123. package/dist/domain/routing/p-success-classifier.js +350 -0
  124. package/dist/domain/routing/p-success-classifier.js.map +1 -0
  125. package/dist/domain/routing/tier-features.d.ts +70 -0
  126. package/dist/domain/routing/tier-features.d.ts.map +1 -0
  127. package/dist/domain/routing/tier-features.js +174 -0
  128. package/dist/domain/routing/tier-features.js.map +1 -0
  129. package/dist/domain/routing/tool-history-guard.d.ts +32 -0
  130. package/dist/domain/routing/tool-history-guard.d.ts.map +1 -0
  131. package/dist/domain/routing/tool-history-guard.js +110 -0
  132. package/dist/domain/routing/tool-history-guard.js.map +1 -0
  133. package/dist/domain/scoring/multi-objective.d.ts +48 -0
  134. package/dist/domain/scoring/multi-objective.d.ts.map +1 -0
  135. package/dist/domain/scoring/multi-objective.js +116 -0
  136. package/dist/domain/scoring/multi-objective.js.map +1 -0
  137. package/dist/domain/triage/triage-engine.d.ts +43 -0
  138. package/dist/domain/triage/triage-engine.d.ts.map +1 -0
  139. package/dist/domain/triage/triage-engine.js +317 -0
  140. package/dist/domain/triage/triage-engine.js.map +1 -0
  141. package/dist/domain/triage/turn-envelope.d.ts +17 -0
  142. package/dist/domain/triage/turn-envelope.d.ts.map +1 -0
  143. package/dist/domain/triage/turn-envelope.js +81 -0
  144. package/dist/domain/triage/turn-envelope.js.map +1 -0
  145. package/dist/domain/types/entities.d.ts +303 -0
  146. package/dist/domain/types/entities.d.ts.map +1 -0
  147. package/dist/domain/types/entities.js +6 -0
  148. package/dist/domain/types/entities.js.map +1 -0
  149. package/dist/domain/types/index.d.ts +4 -0
  150. package/dist/domain/types/index.d.ts.map +1 -0
  151. package/dist/domain/types/index.js +2 -0
  152. package/dist/domain/types/index.js.map +1 -0
  153. package/dist/domain/types/schemas.d.ts +346 -0
  154. package/dist/domain/types/schemas.d.ts.map +1 -0
  155. package/dist/domain/types/schemas.js +241 -0
  156. package/dist/domain/types/schemas.js.map +1 -0
  157. package/dist/domain/types/store-port.d.ts +44 -0
  158. package/dist/domain/types/store-port.d.ts.map +1 -0
  159. package/dist/domain/types/store-port.js +6 -0
  160. package/dist/domain/types/store-port.js.map +1 -0
  161. package/dist/index.d.ts +39 -0
  162. package/dist/index.d.ts.map +1 -0
  163. package/dist/index.js +36 -0
  164. package/dist/index.js.map +1 -0
  165. package/dist/infra/gemini-provider.d.ts +28 -0
  166. package/dist/infra/gemini-provider.d.ts.map +1 -0
  167. package/dist/infra/gemini-provider.js +112 -0
  168. package/dist/infra/gemini-provider.js.map +1 -0
  169. package/dist/infra/telemetry.d.ts +51 -0
  170. package/dist/infra/telemetry.d.ts.map +1 -0
  171. package/dist/infra/telemetry.js +100 -0
  172. package/dist/infra/telemetry.js.map +1 -0
  173. package/dist/infrastructure/delegation/provider-error.d.ts +44 -0
  174. package/dist/infrastructure/delegation/provider-error.d.ts.map +1 -0
  175. package/dist/infrastructure/delegation/provider-error.js +179 -0
  176. package/dist/infrastructure/delegation/provider-error.js.map +1 -0
  177. package/dist/infrastructure/gateway/circuit-breaker.d.ts +68 -0
  178. package/dist/infrastructure/gateway/circuit-breaker.d.ts.map +1 -0
  179. package/dist/infrastructure/gateway/circuit-breaker.js +150 -0
  180. package/dist/infrastructure/gateway/circuit-breaker.js.map +1 -0
  181. package/dist/infrastructure/gateway/gateway-dispatch.d.ts +138 -0
  182. package/dist/infrastructure/gateway/gateway-dispatch.d.ts.map +1 -0
  183. package/dist/infrastructure/gateway/gateway-dispatch.js +308 -0
  184. package/dist/infrastructure/gateway/gateway-dispatch.js.map +1 -0
  185. package/dist/infrastructure/hardware/hardware-probe.d.ts +32 -0
  186. package/dist/infrastructure/hardware/hardware-probe.d.ts.map +1 -0
  187. package/dist/infrastructure/hardware/hardware-probe.js +199 -0
  188. package/dist/infrastructure/hardware/hardware-probe.js.map +1 -0
  189. package/dist/infrastructure/local/local-zero-tier.d.ts +47 -0
  190. package/dist/infrastructure/local/local-zero-tier.d.ts.map +1 -0
  191. package/dist/infrastructure/local/local-zero-tier.js +92 -0
  192. package/dist/infrastructure/local/local-zero-tier.js.map +1 -0
  193. package/dist/infrastructure/persistence/memory-store.d.ts +31 -0
  194. package/dist/infrastructure/persistence/memory-store.d.ts.map +1 -0
  195. package/dist/infrastructure/persistence/memory-store.js +87 -0
  196. package/dist/infrastructure/persistence/memory-store.js.map +1 -0
  197. package/dist/infrastructure/persistence/sqlite-store.d.ts +81 -0
  198. package/dist/infrastructure/persistence/sqlite-store.d.ts.map +1 -0
  199. package/dist/infrastructure/persistence/sqlite-store.js +658 -0
  200. package/dist/infrastructure/persistence/sqlite-store.js.map +1 -0
  201. package/dist/infrastructure/pricing/litellm-fetch.d.ts +46 -0
  202. package/dist/infrastructure/pricing/litellm-fetch.d.ts.map +1 -0
  203. package/dist/infrastructure/pricing/litellm-fetch.js +145 -0
  204. package/dist/infrastructure/pricing/litellm-fetch.js.map +1 -0
  205. package/dist/infrastructure/pricing/price-broker.d.ts +56 -0
  206. package/dist/infrastructure/pricing/price-broker.d.ts.map +1 -0
  207. package/dist/infrastructure/pricing/price-broker.js +133 -0
  208. package/dist/infrastructure/pricing/price-broker.js.map +1 -0
  209. package/dist/infrastructure/pricing/pricing-monitor.d.ts +27 -0
  210. package/dist/infrastructure/pricing/pricing-monitor.d.ts.map +1 -0
  211. package/dist/infrastructure/pricing/pricing-monitor.js +46 -0
  212. package/dist/infrastructure/pricing/pricing-monitor.js.map +1 -0
  213. package/dist/infrastructure/telemetry/dataset-limits.d.ts +13 -0
  214. package/dist/infrastructure/telemetry/dataset-limits.d.ts.map +1 -0
  215. package/dist/infrastructure/telemetry/dataset-limits.js +28 -0
  216. package/dist/infrastructure/telemetry/dataset-limits.js.map +1 -0
  217. package/dist/infrastructure/telemetry/dataset-recorder.d.ts +48 -0
  218. package/dist/infrastructure/telemetry/dataset-recorder.d.ts.map +1 -0
  219. package/dist/infrastructure/telemetry/dataset-recorder.js +154 -0
  220. package/dist/infrastructure/telemetry/dataset-recorder.js.map +1 -0
  221. package/dist/infrastructure/telemetry/outcome-limits.d.ts +12 -0
  222. package/dist/infrastructure/telemetry/outcome-limits.d.ts.map +1 -0
  223. package/dist/infrastructure/telemetry/outcome-limits.js +28 -0
  224. package/dist/infrastructure/telemetry/outcome-limits.js.map +1 -0
  225. package/dist/infrastructure/telemetry/outcome-recorder.d.ts +29 -0
  226. package/dist/infrastructure/telemetry/outcome-recorder.d.ts.map +1 -0
  227. package/dist/infrastructure/telemetry/outcome-recorder.js +49 -0
  228. package/dist/infrastructure/telemetry/outcome-recorder.js.map +1 -0
  229. package/dist/infrastructure/telemetry/routing-telemetry.d.ts +115 -0
  230. package/dist/infrastructure/telemetry/routing-telemetry.d.ts.map +1 -0
  231. package/dist/infrastructure/telemetry/routing-telemetry.js +529 -0
  232. package/dist/infrastructure/telemetry/routing-telemetry.js.map +1 -0
  233. package/dist/infrastructure/telemetry/telemetry-limits.d.ts +16 -0
  234. package/dist/infrastructure/telemetry/telemetry-limits.d.ts.map +1 -0
  235. package/dist/infrastructure/telemetry/telemetry-limits.js +35 -0
  236. package/dist/infrastructure/telemetry/telemetry-limits.js.map +1 -0
  237. package/package.json +110 -0
  238. package/skills/router-backlog-orchestrator/SKILL.md +183 -0
  239. package/skills/router-backlog-orchestrator/references/github-router-issue-template.md +78 -0
  240. package/skills/router-backlog-orchestrator/references/packet-from-issue.md +99 -0
  241. package/skills/router-backlog-orchestrator/references/prioritization-rubric.md +65 -0
  242. package/skills/router-backlog-orchestrator/scripts/collect-backlog.sh +44 -0
  243. package/specs/001-build-smart-router/contracts/telemetry-contrib.schema.json +151 -0
  244. package/src/api/explain/.gitkeep +0 -0
  245. package/src/api/explain/router-explain.ts +146 -0
  246. package/src/api/middleware/.gitkeep +0 -0
  247. package/src/api/middleware/pi-router-middleware.ts +169 -0
  248. package/src/cli/smart-router-cli.ts +436 -0
  249. package/src/config/.gitkeep +0 -0
  250. package/src/config/defaults.ts +35 -0
  251. package/src/config/models-loader.ts +68 -0
  252. package/src/config/pi-model-mapper.ts +285 -0
  253. package/src/config/routing-clusters-loader.ts +148 -0
  254. package/src/domain/delegation/delegation-context.ts +111 -0
  255. package/src/domain/delegation/execution-ledger.ts +34 -0
  256. package/src/domain/delegation/output-headroom.ts +131 -0
  257. package/src/domain/matching/.gitkeep +0 -0
  258. package/src/domain/matching/cluster-matcher.ts +474 -0
  259. package/src/domain/matching/embedding-provider.ts +79 -0
  260. package/src/domain/matching/hydra-input.ts +53 -0
  261. package/src/domain/matching/hydra-matcher.ts +454 -0
  262. package/src/domain/pinning/.gitkeep +0 -0
  263. package/src/domain/pinning/cache-economics.ts +128 -0
  264. package/src/domain/pinning/loop-escalation.ts +181 -0
  265. package/src/domain/pinning/session-pinner.ts +388 -0
  266. package/src/domain/pinning/sub-route-policy.ts +119 -0
  267. package/src/domain/pipeline/.gitkeep +0 -0
  268. package/src/domain/pipeline/router-pipeline.ts +1139 -0
  269. package/src/domain/pipeline/safe-default.ts +70 -0
  270. package/src/domain/refactor-guardrails.ts +202 -0
  271. package/src/domain/routing/context-fit.ts +221 -0
  272. package/src/domain/routing/expected-cost.ts +320 -0
  273. package/src/domain/routing/p-success-classifier.ts +511 -0
  274. package/src/domain/routing/tier-features.ts +290 -0
  275. package/src/domain/routing/tool-history-guard.ts +159 -0
  276. package/src/domain/scoring/.gitkeep +0 -0
  277. package/src/domain/scoring/multi-objective.ts +175 -0
  278. package/src/domain/triage/.gitkeep +0 -0
  279. package/src/domain/triage/triage-engine.ts +373 -0
  280. package/src/domain/triage/turn-envelope.ts +104 -0
  281. package/src/domain/types/.gitkeep +0 -0
  282. package/src/domain/types/entities.ts +384 -0
  283. package/src/domain/types/index.ts +41 -0
  284. package/src/domain/types/schemas.ts +289 -0
  285. package/src/domain/types/store-port.ts +59 -0
  286. package/src/index.ts +103 -0
  287. package/src/infra/gemini-provider.ts +142 -0
  288. package/src/infra/telemetry.ts +169 -0
  289. package/src/infrastructure/delegation/provider-error.ts +251 -0
  290. package/src/infrastructure/gateway/.gitkeep +0 -0
  291. package/src/infrastructure/gateway/circuit-breaker.ts +196 -0
  292. package/src/infrastructure/gateway/gateway-dispatch.ts +444 -0
  293. package/src/infrastructure/hardware/.gitkeep +0 -0
  294. package/src/infrastructure/hardware/hardware-probe.ts +276 -0
  295. package/src/infrastructure/local/.gitkeep +0 -0
  296. package/src/infrastructure/local/local-zero-tier.ts +151 -0
  297. package/src/infrastructure/persistence/.gitkeep +0 -0
  298. package/src/infrastructure/persistence/memory-store.ts +122 -0
  299. package/src/infrastructure/persistence/sqlite-store.ts +900 -0
  300. package/src/infrastructure/pricing/.gitkeep +0 -0
  301. package/src/infrastructure/pricing/litellm-fetch.ts +215 -0
  302. package/src/infrastructure/pricing/price-broker.ts +183 -0
  303. package/src/infrastructure/pricing/pricing-monitor.ts +65 -0
  304. package/src/infrastructure/telemetry/.gitkeep +0 -0
  305. package/src/infrastructure/telemetry/dataset-limits.ts +39 -0
  306. package/src/infrastructure/telemetry/dataset-recorder.ts +215 -0
  307. package/src/infrastructure/telemetry/outcome-limits.ts +42 -0
  308. package/src/infrastructure/telemetry/outcome-recorder.ts +118 -0
  309. package/src/infrastructure/telemetry/routing-telemetry.ts +824 -0
  310. package/src/infrastructure/telemetry/telemetry-limits.ts +50 -0
@@ -0,0 +1,658 @@
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 { renameSync } from 'node:fs';
11
+ import Database from 'better-sqlite3';
12
+ import { MemoryStore } from './memory-store.js';
13
+ import { DEFAULT_HISTORY_LIMIT, MAX_HISTORY_LIMIT, TELEMETRY_MAX_ENTRIES, TELEMETRY_WINDOW_MS, } from '../telemetry/telemetry-limits.js';
14
+ import { DATASET_MAX_ENTRIES, DATASET_WINDOW_MS, } from '../telemetry/dataset-limits.js';
15
+ import { OUTCOME_MAX_ENTRIES, OUTCOME_WINDOW_MS, } from '../telemetry/outcome-limits.js';
16
+ // ─── Schema version & migrations ────────────────────────────────────────────
17
+ const CURRENT_SCHEMA_VERSION = 5;
18
+ const MIGRATION_V1 = `
19
+ CREATE TABLE IF NOT EXISTS pins (
20
+ session_id TEXT PRIMARY KEY,
21
+ pinned_model_id TEXT NOT NULL,
22
+ pin_reason TEXT NOT NULL CHECK (pin_reason IN ('initial','user_forced','loop_escalation','compaction','cache_economics','context_overflow')),
23
+ has_ever_switched INTEGER NOT NULL DEFAULT 0,
24
+ consecutive_upstream_errors INTEGER NOT NULL DEFAULT 0,
25
+ consecutive_tool_failures INTEGER NOT NULL DEFAULT 0,
26
+ last_tool_failure_signature TEXT,
27
+ created_at TEXT NOT NULL,
28
+ updated_at TEXT NOT NULL
29
+ );
30
+
31
+ CREATE TABLE IF NOT EXISTS rate_limits (
32
+ bucket_key TEXT PRIMARY KEY,
33
+ tokens REAL NOT NULL,
34
+ max_tokens REAL NOT NULL,
35
+ refill_rate REAL NOT NULL,
36
+ last_refill_at TEXT NOT NULL
37
+ );
38
+
39
+ CREATE TABLE IF NOT EXISTS price_cache (
40
+ id INTEGER PRIMARY KEY CHECK (id = 1),
41
+ registry_snapshot TEXT NOT NULL,
42
+ user_overrides TEXT NOT NULL,
43
+ last_updated TEXT NOT NULL,
44
+ source TEXT NOT NULL CHECK (source IN ('override','registry','yaml_fallback'))
45
+ );
46
+
47
+ CREATE TABLE IF NOT EXISTS telemetry (
48
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
49
+ timestamp TEXT NOT NULL,
50
+ session_id TEXT NOT NULL,
51
+ request_id TEXT NOT NULL,
52
+ turn_type TEXT NOT NULL,
53
+ stage TEXT NOT NULL,
54
+ reason_code TEXT NOT NULL,
55
+ selected_model_id TEXT NOT NULL,
56
+ estimated_cost_usd REAL NOT NULL,
57
+ routing_latency_ms REAL NOT NULL,
58
+ pin_reason TEXT
59
+ );
60
+
61
+ CREATE INDEX IF NOT EXISTS idx_telemetry_session ON telemetry(session_id);
62
+ CREATE INDEX IF NOT EXISTS idx_telemetry_timestamp ON telemetry(timestamp);
63
+ `;
64
+ const MIGRATION_V2 = `
65
+ CREATE TABLE IF NOT EXISTS dataset (
66
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ request_id TEXT NOT NULL,
68
+ timestamp TEXT NOT NULL,
69
+ turn_type TEXT NOT NULL,
70
+ stage TEXT NOT NULL,
71
+ reason_code TEXT NOT NULL,
72
+ selected_model_id TEXT NOT NULL,
73
+ tier TEXT NOT NULL,
74
+ candidates_json TEXT,
75
+ prompt_length_chars INTEGER NOT NULL,
76
+ estimated_input_tokens INTEGER,
77
+ message_count INTEGER NOT NULL,
78
+ has_tool_context INTEGER NOT NULL,
79
+ compaction_flag INTEGER NOT NULL,
80
+ triage_verdict TEXT,
81
+ triage_reason_code TEXT,
82
+ triage_cyclomatic_score REAL,
83
+ triage_trivial_hits INTEGER,
84
+ triage_complex_hits INTEGER,
85
+ triage_sanitized_length_delta INTEGER,
86
+ requirement_reasoning REAL,
87
+ requirement_code_gen REAL,
88
+ requirement_tool_use REAL,
89
+ routing_latency_ms REAL NOT NULL,
90
+ estimated_cost_usd REAL
91
+ );
92
+
93
+ CREATE INDEX IF NOT EXISTS idx_dataset_timestamp ON dataset(timestamp);
94
+ CREATE INDEX IF NOT EXISTS idx_dataset_request ON dataset(request_id);
95
+ `;
96
+ const MIGRATION_V3 = `
97
+ ALTER TABLE dataset ADD COLUMN prompt_fingerprint TEXT;
98
+ `;
99
+ const MIGRATION_V4 = `
100
+ CREATE TABLE IF NOT EXISTS outcomes (
101
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
102
+ request_id TEXT NOT NULL,
103
+ session_id TEXT NOT NULL,
104
+ timestamp TEXT NOT NULL,
105
+ signal_type TEXT NOT NULL CHECK (signal_type IN ('model_override','compaction_pin_break','feedback_good','feedback_bad')),
106
+ routed_model_id TEXT,
107
+ override_model_id TEXT
108
+ );
109
+
110
+ CREATE INDEX IF NOT EXISTS idx_outcomes_timestamp ON outcomes(timestamp);
111
+ CREATE INDEX IF NOT EXISTS idx_outcomes_request ON outcomes(request_id);
112
+ CREATE INDEX IF NOT EXISTS idx_outcomes_session ON outcomes(session_id);
113
+ `;
114
+ const MIGRATION_V5 = `
115
+ CREATE TABLE pins_v5 (
116
+ session_id TEXT PRIMARY KEY,
117
+ pinned_model_id TEXT NOT NULL,
118
+ pin_reason TEXT NOT NULL CHECK (pin_reason IN ('initial','user_forced','loop_escalation','compaction','cache_economics','context_overflow')),
119
+ has_ever_switched INTEGER NOT NULL DEFAULT 0,
120
+ consecutive_upstream_errors INTEGER NOT NULL DEFAULT 0,
121
+ consecutive_tool_failures INTEGER NOT NULL DEFAULT 0,
122
+ last_tool_failure_signature TEXT,
123
+ created_at TEXT NOT NULL,
124
+ updated_at TEXT NOT NULL
125
+ );
126
+
127
+ INSERT INTO pins_v5 (
128
+ session_id, pinned_model_id, pin_reason,
129
+ has_ever_switched, consecutive_upstream_errors,
130
+ consecutive_tool_failures, last_tool_failure_signature,
131
+ created_at, updated_at
132
+ )
133
+ SELECT
134
+ session_id, pinned_model_id, pin_reason,
135
+ has_ever_switched, consecutive_upstream_errors,
136
+ consecutive_tool_failures, last_tool_failure_signature,
137
+ created_at, updated_at
138
+ FROM pins;
139
+
140
+ DROP TABLE pins;
141
+ ALTER TABLE pins_v5 RENAME TO pins;
142
+ `;
143
+ /**
144
+ * Create a persistence store with corrupt-DB recovery.
145
+ *
146
+ * Strategy:
147
+ * 1. Attempt to open the SQLite DB and run migrations.
148
+ * 2. On failure (corrupt/locked): rename the file, try fresh creation.
149
+ * 3. If recreation also fails: fall back to MemoryStore.
150
+ *
151
+ * Never throws — the host agent must not crash due to persistence issues.
152
+ */
153
+ export function createResilientStore(options) {
154
+ if (options.dbPath === ':memory:') {
155
+ return { store: new SqliteStore(options), degraded: false };
156
+ }
157
+ try {
158
+ return { store: new SqliteStore(options), degraded: false };
159
+ }
160
+ catch (firstError) {
161
+ console.warn('SQLite store open failed; attempting corrupt-DB recovery', firstError);
162
+ try {
163
+ const corruptPath = `${options.dbPath}.corrupt.${Date.now()}`;
164
+ renameSync(options.dbPath, corruptPath);
165
+ }
166
+ catch {
167
+ // Rename may fail if the file doesn't exist or permissions issue — continue to recreate attempt
168
+ }
169
+ try {
170
+ return { store: new SqliteStore(options), degraded: false };
171
+ }
172
+ catch {
173
+ return { store: new MemoryStore(options.models), degraded: true };
174
+ }
175
+ }
176
+ }
177
+ // ─── SqliteStore ────────────────────────────────────────────────────────────
178
+ export class SqliteStore {
179
+ db;
180
+ models;
181
+ consumeTokenTx;
182
+ constructor(options) {
183
+ this.db = new Database(options.dbPath);
184
+ this.models = options.models;
185
+ this.initialize();
186
+ this.consumeTokenTx = this.buildConsumeTokenTx();
187
+ }
188
+ // ─── StorePort: SessionPin ──────────────────────────────────────────────
189
+ async getSessionPin(sessionId) {
190
+ const row = this.db
191
+ .prepare('SELECT * FROM pins WHERE session_id = ?')
192
+ .get(sessionId);
193
+ return row ? pinRowToEntity(row) : null;
194
+ }
195
+ async putSessionPin(pin) {
196
+ this.db
197
+ .prepare(`INSERT INTO pins (
198
+ session_id, pinned_model_id, pin_reason,
199
+ has_ever_switched, consecutive_upstream_errors,
200
+ consecutive_tool_failures, last_tool_failure_signature,
201
+ created_at, updated_at
202
+ ) VALUES (
203
+ @session_id, @pinned_model_id, @pin_reason,
204
+ @has_ever_switched, @consecutive_upstream_errors,
205
+ @consecutive_tool_failures, @last_tool_failure_signature,
206
+ @created_at, @updated_at
207
+ )
208
+ ON CONFLICT(session_id) DO UPDATE SET
209
+ pinned_model_id = excluded.pinned_model_id,
210
+ pin_reason = excluded.pin_reason,
211
+ has_ever_switched = excluded.has_ever_switched,
212
+ consecutive_upstream_errors = excluded.consecutive_upstream_errors,
213
+ consecutive_tool_failures = excluded.consecutive_tool_failures,
214
+ last_tool_failure_signature = excluded.last_tool_failure_signature,
215
+ updated_at = excluded.updated_at`)
216
+ .run({
217
+ session_id: pin.session_id,
218
+ pinned_model_id: pin.pinned_model_id,
219
+ pin_reason: pin.pin_reason,
220
+ has_ever_switched: pin.has_ever_switched ? 1 : 0,
221
+ consecutive_upstream_errors: pin.consecutive_upstream_errors,
222
+ consecutive_tool_failures: pin.consecutive_tool_failures,
223
+ last_tool_failure_signature: pin.last_tool_failure_signature,
224
+ created_at: pin.created_at,
225
+ updated_at: pin.updated_at,
226
+ });
227
+ }
228
+ async deleteSessionPin(sessionId) {
229
+ this.db.prepare('DELETE FROM pins WHERE session_id = ?').run(sessionId);
230
+ }
231
+ // ─── StorePort: ModelProfile (read-only, from fleet catalog) ────────────
232
+ async getModelProfiles() {
233
+ return this.models;
234
+ }
235
+ // ─── StorePort: PriceCatalog ────────────────────────────────────────────
236
+ async getPriceCatalog() {
237
+ const row = this.db
238
+ .prepare('SELECT * FROM price_cache WHERE id = 1')
239
+ .get();
240
+ if (!row)
241
+ return null;
242
+ return {
243
+ registry_snapshot: JSON.parse(row.registry_snapshot),
244
+ user_overrides: JSON.parse(row.user_overrides),
245
+ last_updated: row.last_updated,
246
+ source: row.source,
247
+ };
248
+ }
249
+ async putPriceCatalog(catalog) {
250
+ this.db
251
+ .prepare(`INSERT INTO price_cache (id, registry_snapshot, user_overrides, last_updated, source)
252
+ VALUES (1, @registry_snapshot, @user_overrides, @last_updated, @source)
253
+ ON CONFLICT(id) DO UPDATE SET
254
+ registry_snapshot = excluded.registry_snapshot,
255
+ user_overrides = excluded.user_overrides,
256
+ last_updated = excluded.last_updated,
257
+ source = excluded.source`)
258
+ .run({
259
+ registry_snapshot: JSON.stringify(catalog.registry_snapshot),
260
+ user_overrides: JSON.stringify(catalog.user_overrides),
261
+ last_updated: catalog.last_updated,
262
+ source: catalog.source,
263
+ });
264
+ }
265
+ // ─── Telemetry (append-only) ────────────────────────────────────────────
266
+ appendTelemetry(entry) {
267
+ this.db
268
+ .prepare(`INSERT INTO telemetry (
269
+ timestamp, session_id, request_id, turn_type,
270
+ stage, reason_code, selected_model_id,
271
+ estimated_cost_usd, routing_latency_ms, pin_reason
272
+ ) VALUES (
273
+ @timestamp, @session_id, @request_id, @turn_type,
274
+ @stage, @reason_code, @selected_model_id,
275
+ @estimated_cost_usd, @routing_latency_ms, @pin_reason
276
+ )`)
277
+ .run(entry);
278
+ this.evictTelemetryRows();
279
+ }
280
+ async listTelemetry(options) {
281
+ const limit = clampHistoryLimit(options?.limit);
282
+ const sessionId = options?.sessionId;
283
+ const rows = sessionId
284
+ ? this.db
285
+ .prepare(`SELECT * FROM telemetry
286
+ WHERE session_id = ?
287
+ ORDER BY id DESC
288
+ LIMIT ?`)
289
+ .all(sessionId, limit)
290
+ : this.db
291
+ .prepare(`SELECT * FROM telemetry
292
+ ORDER BY id DESC
293
+ LIMIT ?`)
294
+ .all(limit);
295
+ return rows.map(telemetryRowToEntity);
296
+ }
297
+ evictTelemetryRows() {
298
+ const cutoff = new Date(Date.now() - TELEMETRY_WINDOW_MS).toISOString();
299
+ this.db.prepare('DELETE FROM telemetry WHERE timestamp < ?').run(cutoff);
300
+ const countRow = this.db
301
+ .prepare('SELECT COUNT(*) AS count FROM telemetry')
302
+ .get();
303
+ const excess = countRow.count - TELEMETRY_MAX_ENTRIES;
304
+ if (excess <= 0) {
305
+ return;
306
+ }
307
+ this.db
308
+ .prepare(`DELETE FROM telemetry
309
+ WHERE id IN (
310
+ SELECT id FROM telemetry
311
+ ORDER BY id ASC
312
+ LIMIT ?
313
+ )`)
314
+ .run(excess);
315
+ }
316
+ // ─── Dataset (append-only, privacy-safe) ────────────────────────────────
317
+ appendDatasetRecord(entry) {
318
+ this.db
319
+ .prepare(`INSERT INTO dataset (
320
+ request_id, timestamp, turn_type, stage, reason_code,
321
+ selected_model_id, tier, candidates_json,
322
+ prompt_length_chars, estimated_input_tokens, message_count,
323
+ has_tool_context, compaction_flag,
324
+ triage_verdict, triage_reason_code, triage_cyclomatic_score,
325
+ triage_trivial_hits, triage_complex_hits, triage_sanitized_length_delta,
326
+ requirement_reasoning, requirement_code_gen, requirement_tool_use,
327
+ routing_latency_ms, estimated_cost_usd, prompt_fingerprint
328
+ ) VALUES (
329
+ @request_id, @timestamp, @turn_type, @stage, @reason_code,
330
+ @selected_model_id, @tier, @candidates_json,
331
+ @prompt_length_chars, @estimated_input_tokens, @message_count,
332
+ @has_tool_context, @compaction_flag,
333
+ @triage_verdict, @triage_reason_code, @triage_cyclomatic_score,
334
+ @triage_trivial_hits, @triage_complex_hits, @triage_sanitized_length_delta,
335
+ @requirement_reasoning, @requirement_code_gen, @requirement_tool_use,
336
+ @routing_latency_ms, @estimated_cost_usd, @prompt_fingerprint
337
+ )`)
338
+ .run({
339
+ request_id: entry.request_id,
340
+ timestamp: entry.timestamp,
341
+ turn_type: entry.turn_type,
342
+ stage: entry.stage,
343
+ reason_code: entry.reason_code,
344
+ selected_model_id: entry.selected_model_id,
345
+ tier: entry.tier,
346
+ candidates_json: entry.candidates_json,
347
+ prompt_length_chars: entry.prompt_length_chars,
348
+ estimated_input_tokens: entry.estimated_input_tokens,
349
+ message_count: entry.message_count,
350
+ has_tool_context: entry.has_tool_context ? 1 : 0,
351
+ compaction_flag: entry.compaction_flag ? 1 : 0,
352
+ triage_verdict: entry.triage_verdict,
353
+ triage_reason_code: entry.triage_reason_code,
354
+ triage_cyclomatic_score: entry.triage_cyclomatic_score,
355
+ triage_trivial_hits: entry.triage_trivial_hits,
356
+ triage_complex_hits: entry.triage_complex_hits,
357
+ triage_sanitized_length_delta: entry.triage_sanitized_length_delta,
358
+ requirement_reasoning: entry.requirement_reasoning,
359
+ requirement_code_gen: entry.requirement_code_gen,
360
+ requirement_tool_use: entry.requirement_tool_use,
361
+ routing_latency_ms: entry.routing_latency_ms,
362
+ estimated_cost_usd: entry.estimated_cost_usd,
363
+ prompt_fingerprint: entry.prompt_fingerprint,
364
+ });
365
+ this.evictDatasetRows();
366
+ }
367
+ async listDatasetRecords(options) {
368
+ const limit = clampHistoryLimit(options?.limit);
369
+ const rows = this.db
370
+ .prepare(`SELECT * FROM dataset
371
+ ORDER BY id DESC
372
+ LIMIT ?`)
373
+ .all(limit);
374
+ return rows.map(datasetRowToEntity);
375
+ }
376
+ evictDatasetRows() {
377
+ const cutoff = new Date(Date.now() - DATASET_WINDOW_MS).toISOString();
378
+ this.db.prepare('DELETE FROM dataset WHERE timestamp < ?').run(cutoff);
379
+ const countRow = this.db
380
+ .prepare('SELECT COUNT(*) AS count FROM dataset')
381
+ .get();
382
+ const excess = countRow.count - DATASET_MAX_ENTRIES;
383
+ if (excess <= 0) {
384
+ return;
385
+ }
386
+ this.db
387
+ .prepare(`DELETE FROM dataset
388
+ WHERE id IN (
389
+ SELECT id FROM dataset
390
+ ORDER BY id ASC
391
+ LIMIT ?
392
+ )`)
393
+ .run(excess);
394
+ }
395
+ // ─── Outcomes (append-only, privacy-safe) ───────────────────────────────
396
+ appendOutcomeRecord(entry) {
397
+ this.db
398
+ .prepare(`INSERT INTO outcomes (
399
+ request_id, session_id, timestamp, signal_type,
400
+ routed_model_id, override_model_id
401
+ ) VALUES (
402
+ @request_id, @session_id, @timestamp, @signal_type,
403
+ @routed_model_id, @override_model_id
404
+ )`)
405
+ .run({
406
+ request_id: entry.request_id,
407
+ session_id: entry.session_id,
408
+ timestamp: entry.timestamp,
409
+ signal_type: entry.signal_type,
410
+ routed_model_id: entry.routed_model_id,
411
+ override_model_id: entry.override_model_id,
412
+ });
413
+ this.evictOutcomeRows();
414
+ }
415
+ async listOutcomeRecords(options) {
416
+ const limit = clampHistoryLimit(options?.limit);
417
+ const requestId = options?.requestId;
418
+ const sessionId = options?.sessionId;
419
+ const rows = requestId
420
+ ? this.db
421
+ .prepare(`SELECT * FROM outcomes
422
+ WHERE request_id = ?
423
+ ORDER BY id DESC
424
+ LIMIT ?`)
425
+ .all(requestId, limit)
426
+ : sessionId
427
+ ? this.db
428
+ .prepare(`SELECT * FROM outcomes
429
+ WHERE session_id = ?
430
+ ORDER BY id DESC
431
+ LIMIT ?`)
432
+ .all(sessionId, limit)
433
+ : this.db
434
+ .prepare(`SELECT * FROM outcomes
435
+ ORDER BY id DESC
436
+ LIMIT ?`)
437
+ .all(limit);
438
+ return rows.map(outcomeRowToEntity);
439
+ }
440
+ evictOutcomeRows() {
441
+ const cutoff = new Date(Date.now() - OUTCOME_WINDOW_MS).toISOString();
442
+ this.db.prepare('DELETE FROM outcomes WHERE timestamp < ?').run(cutoff);
443
+ const countRow = this.db
444
+ .prepare('SELECT COUNT(*) AS count FROM outcomes')
445
+ .get();
446
+ const excess = countRow.count - OUTCOME_MAX_ENTRIES;
447
+ if (excess <= 0) {
448
+ return;
449
+ }
450
+ this.db
451
+ .prepare(`DELETE FROM outcomes
452
+ WHERE id IN (
453
+ SELECT id FROM outcomes
454
+ ORDER BY id ASC
455
+ LIMIT ?
456
+ )`)
457
+ .run(excess);
458
+ }
459
+ // ─── Token bucket (BEGIN IMMEDIATE) ─────────────────────────────────────
460
+ /**
461
+ * Initialize a token bucket. Idempotent — existing buckets are unchanged.
462
+ */
463
+ initBucket(key, maxTokens, refillRate) {
464
+ this.db
465
+ .prepare(`INSERT OR IGNORE INTO rate_limits (bucket_key, tokens, max_tokens, refill_rate, last_refill_at)
466
+ VALUES (?, ?, ?, ?, ?)`)
467
+ .run(key, maxTokens, maxTokens, refillRate, new Date().toISOString());
468
+ }
469
+ /**
470
+ * Atomically attempt to consume tokens from a bucket.
471
+ *
472
+ * Uses BEGIN IMMEDIATE to acquire a reserved lock before reading,
473
+ * preventing TOCTOU races between concurrent consumers.
474
+ */
475
+ consumeToken(key, cost = 1) {
476
+ return this.consumeTokenTx(key, cost);
477
+ }
478
+ /** Run PRAGMA integrity_check. Returns true if the database is healthy. */
479
+ checkHealth() {
480
+ try {
481
+ const result = this.db.pragma('integrity_check', { simple: true });
482
+ return result === 'ok';
483
+ }
484
+ catch {
485
+ return false;
486
+ }
487
+ }
488
+ /** Close the database connection. */
489
+ close() {
490
+ this.db.close();
491
+ }
492
+ // ─── Internals ──────────────────────────────────────────────────────────
493
+ initialize() {
494
+ this.db.pragma('journal_mode = WAL');
495
+ this.db.pragma('busy_timeout = 5000');
496
+ this.db.pragma('foreign_keys = ON');
497
+ this.runMigrations();
498
+ }
499
+ runMigrations() {
500
+ let version = this.db.pragma('user_version', { simple: true });
501
+ if (version < 1) {
502
+ this.db.exec(MIGRATION_V1);
503
+ version = 1;
504
+ this.db.pragma('user_version = 1');
505
+ }
506
+ if (version < 2) {
507
+ this.db.exec(MIGRATION_V2);
508
+ version = 2;
509
+ this.db.pragma('user_version = 2');
510
+ }
511
+ if (version < 3) {
512
+ this.db.exec(MIGRATION_V3);
513
+ version = 3;
514
+ this.db.pragma('user_version = 3');
515
+ }
516
+ if (version < 4) {
517
+ this.db.exec(MIGRATION_V4);
518
+ version = 4;
519
+ this.db.pragma('user_version = 4');
520
+ }
521
+ if (version < 5) {
522
+ this.db.exec(MIGRATION_V5);
523
+ this.db.pragma(`user_version = ${CURRENT_SCHEMA_VERSION}`);
524
+ }
525
+ }
526
+ buildConsumeTokenTx() {
527
+ const selectBucket = this.db.prepare('SELECT * FROM rate_limits WHERE bucket_key = ?');
528
+ const updateBucket = this.db.prepare('UPDATE rate_limits SET tokens = ?, last_refill_at = ? WHERE bucket_key = ?');
529
+ return this.db.transaction((key, cost) => {
530
+ const row = selectBucket.get(key);
531
+ if (!row) {
532
+ throw new SqliteStoreError(`Token bucket not found: ${key}`);
533
+ }
534
+ const now = Date.now();
535
+ const lastRefill = new Date(row.last_refill_at).getTime();
536
+ const elapsedSeconds = Math.max(0, (now - lastRefill) / 1000);
537
+ const refilled = Math.min(row.max_tokens, row.tokens + elapsedSeconds * row.refill_rate);
538
+ if (refilled >= cost) {
539
+ const remaining = refilled - cost;
540
+ updateBucket.run(remaining, new Date(now).toISOString(), key);
541
+ return { allowed: true, remaining, retryAfterSeconds: null };
542
+ }
543
+ updateBucket.run(refilled, new Date(now).toISOString(), key);
544
+ const deficit = cost - refilled;
545
+ const retryAfterSeconds = Math.ceil(deficit / row.refill_rate);
546
+ return { allowed: false, remaining: refilled, retryAfterSeconds };
547
+ }).immediate;
548
+ }
549
+ }
550
+ // ─── Error type ───────────────────────────────────────────────────────────
551
+ export class SqliteStoreError extends Error {
552
+ name = 'SqliteStoreError';
553
+ constructor(message, options) {
554
+ super(message, options);
555
+ }
556
+ }
557
+ // ─── Row mappers ──────────────────────────────────────────────────────────
558
+ function clampHistoryLimit(limit) {
559
+ if (limit === undefined) {
560
+ return DEFAULT_HISTORY_LIMIT;
561
+ }
562
+ return Math.min(Math.max(1, Math.floor(limit)), MAX_HISTORY_LIMIT);
563
+ }
564
+ function telemetryRowToEntity(row) {
565
+ return {
566
+ timestamp: row.timestamp,
567
+ session_id: row.session_id,
568
+ request_id: row.request_id,
569
+ turn_type: row.turn_type,
570
+ stage: row.stage,
571
+ reason_code: row.reason_code,
572
+ selected_model_id: row.selected_model_id,
573
+ estimated_cost_usd: row.estimated_cost_usd,
574
+ routing_latency_ms: row.routing_latency_ms,
575
+ pin_reason: row.pin_reason,
576
+ estimated_input_tokens: null,
577
+ context_fit_viable_count: null,
578
+ context_fit_rejected_json: null,
579
+ context_overflow_pin_break: false,
580
+ selected_model_max_input_tokens: null,
581
+ context_fit_reason_code: null,
582
+ cluster_id: null,
583
+ cluster_similarity: null,
584
+ cluster_margin: null,
585
+ low_intensity_score: null,
586
+ tier_hint: null,
587
+ p_success_cheap: null,
588
+ local_eligible_reason: null,
589
+ tier_selection_reason_code: null,
590
+ };
591
+ }
592
+ function datasetRowToEntity(row) {
593
+ return {
594
+ request_id: row.request_id,
595
+ timestamp: row.timestamp,
596
+ turn_type: row.turn_type,
597
+ stage: row.stage,
598
+ reason_code: row.reason_code,
599
+ selected_model_id: row.selected_model_id,
600
+ tier: row.tier,
601
+ candidates_json: row.candidates_json,
602
+ prompt_length_chars: row.prompt_length_chars,
603
+ estimated_input_tokens: row.estimated_input_tokens,
604
+ message_count: row.message_count,
605
+ has_tool_context: row.has_tool_context === 1,
606
+ compaction_flag: row.compaction_flag === 1,
607
+ triage_verdict: row.triage_verdict,
608
+ triage_reason_code: row.triage_reason_code,
609
+ triage_cyclomatic_score: row.triage_cyclomatic_score,
610
+ triage_trivial_hits: row.triage_trivial_hits,
611
+ triage_complex_hits: row.triage_complex_hits,
612
+ triage_sanitized_length_delta: row.triage_sanitized_length_delta,
613
+ requirement_reasoning: row.requirement_reasoning,
614
+ requirement_code_gen: row.requirement_code_gen,
615
+ requirement_tool_use: row.requirement_tool_use,
616
+ routing_latency_ms: row.routing_latency_ms,
617
+ estimated_cost_usd: row.estimated_cost_usd,
618
+ prompt_fingerprint: row.prompt_fingerprint,
619
+ estimated_input_tokens_gate: null,
620
+ context_fit_viable_count: null,
621
+ context_fit_rejected_json: null,
622
+ context_overflow_pin_break: false,
623
+ selected_model_max_input_tokens: null,
624
+ context_fit_reason_code: null,
625
+ cluster_id: null,
626
+ cluster_similarity: null,
627
+ cluster_margin: null,
628
+ low_intensity_score: null,
629
+ tier_hint: null,
630
+ p_success_cheap: null,
631
+ local_eligible_reason: null,
632
+ tier_selection_reason_code: null,
633
+ };
634
+ }
635
+ function outcomeRowToEntity(row) {
636
+ return {
637
+ request_id: row.request_id,
638
+ session_id: row.session_id,
639
+ timestamp: row.timestamp,
640
+ signal_type: row.signal_type,
641
+ routed_model_id: row.routed_model_id,
642
+ override_model_id: row.override_model_id,
643
+ };
644
+ }
645
+ function pinRowToEntity(row) {
646
+ return {
647
+ session_id: row.session_id,
648
+ pinned_model_id: row.pinned_model_id,
649
+ pin_reason: row.pin_reason,
650
+ has_ever_switched: row.has_ever_switched === 1,
651
+ consecutive_upstream_errors: row.consecutive_upstream_errors,
652
+ consecutive_tool_failures: row.consecutive_tool_failures,
653
+ last_tool_failure_signature: row.last_tool_failure_signature,
654
+ created_at: row.created_at,
655
+ updated_at: row.updated_at,
656
+ };
657
+ }
658
+ //# sourceMappingURL=sqlite-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-store.js","sourceRoot":"","sources":["../../../src/infrastructure/persistence/sqlite-store.ts"],"names":[],"mappings":"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"}