modelrig 0.0.1 → 0.2.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 (420) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE +201 -0
  3. package/README.md +145 -8
  4. package/data/PROVENANCE.md +19 -0
  5. package/data/pricing-manual.json +22 -0
  6. package/data/pricing-map.json +46362 -0
  7. package/data/pricing-overlay.json +419 -0
  8. package/dist/adapters/anthropic.d.ts +90 -0
  9. package/dist/adapters/anthropic.d.ts.map +1 -0
  10. package/dist/adapters/anthropic.js +296 -0
  11. package/dist/adapters/build-adapters.d.ts +11 -0
  12. package/dist/adapters/build-adapters.d.ts.map +1 -0
  13. package/dist/adapters/build-adapters.js +45 -0
  14. package/dist/adapters/deepseek.d.ts +47 -0
  15. package/dist/adapters/deepseek.d.ts.map +1 -0
  16. package/dist/adapters/deepseek.js +216 -0
  17. package/dist/adapters/gemini.d.ts +44 -0
  18. package/dist/adapters/gemini.d.ts.map +1 -0
  19. package/dist/adapters/gemini.js +262 -0
  20. package/dist/adapters/grok.d.ts +53 -0
  21. package/dist/adapters/grok.d.ts.map +1 -0
  22. package/dist/adapters/grok.js +232 -0
  23. package/dist/adapters/openai-compat.d.ts +80 -0
  24. package/dist/adapters/openai-compat.d.ts.map +1 -0
  25. package/dist/adapters/openai-compat.js +244 -0
  26. package/dist/adapters/openai-stream.d.ts +58 -0
  27. package/dist/adapters/openai-stream.d.ts.map +1 -0
  28. package/dist/adapters/openai-stream.js +120 -0
  29. package/dist/adapters/openai.d.ts +55 -0
  30. package/dist/adapters/openai.d.ts.map +1 -0
  31. package/dist/adapters/openai.js +281 -0
  32. package/dist/adapters/sampling.d.ts +28 -0
  33. package/dist/adapters/sampling.d.ts.map +1 -0
  34. package/dist/adapters/sampling.js +34 -0
  35. package/dist/adapters/tool-mapping.d.ts +92 -0
  36. package/dist/adapters/tool-mapping.d.ts.map +1 -0
  37. package/dist/adapters/tool-mapping.js +143 -0
  38. package/dist/artifacts/artifact.d.ts +137 -0
  39. package/dist/artifacts/artifact.d.ts.map +1 -0
  40. package/dist/artifacts/artifact.js +377 -0
  41. package/dist/artifacts/content-uploader.d.ts +87 -0
  42. package/dist/artifacts/content-uploader.d.ts.map +1 -0
  43. package/dist/artifacts/content-uploader.js +124 -0
  44. package/dist/artifacts/index.d.ts +63 -0
  45. package/dist/artifacts/index.d.ts.map +1 -0
  46. package/dist/artifacts/index.js +80 -0
  47. package/dist/artifacts/run-context.d.ts +129 -0
  48. package/dist/artifacts/run-context.d.ts.map +1 -0
  49. package/dist/artifacts/run-context.js +208 -0
  50. package/dist/artifacts/scrub.d.ts +60 -0
  51. package/dist/artifacts/scrub.d.ts.map +1 -0
  52. package/dist/artifacts/scrub.js +139 -0
  53. package/dist/artifacts/step.d.ts +26 -0
  54. package/dist/artifacts/step.d.ts.map +1 -0
  55. package/dist/artifacts/step.js +37 -0
  56. package/dist/artifacts/taint.d.ts +63 -0
  57. package/dist/artifacts/taint.d.ts.map +1 -0
  58. package/dist/artifacts/taint.js +76 -0
  59. package/dist/bakeoff/cache-sim.d.ts +99 -0
  60. package/dist/bakeoff/cache-sim.d.ts.map +1 -0
  61. package/dist/bakeoff/cache-sim.js +126 -0
  62. package/dist/bakeoff/engine.d.ts +52 -0
  63. package/dist/bakeoff/engine.d.ts.map +1 -0
  64. package/dist/bakeoff/engine.js +163 -0
  65. package/dist/bakeoff/eval-cases.d.ts +96 -0
  66. package/dist/bakeoff/eval-cases.d.ts.map +1 -0
  67. package/dist/bakeoff/eval-cases.js +105 -0
  68. package/dist/bakeoff/replay.d.ts +52 -0
  69. package/dist/bakeoff/replay.d.ts.map +1 -0
  70. package/dist/bakeoff/replay.js +94 -0
  71. package/dist/bakeoff/report.d.ts +41 -0
  72. package/dist/bakeoff/report.d.ts.map +1 -0
  73. package/dist/bakeoff/report.js +142 -0
  74. package/dist/bakeoff/samples.d.ts +77 -0
  75. package/dist/bakeoff/samples.d.ts.map +1 -0
  76. package/dist/bakeoff/samples.js +148 -0
  77. package/dist/bakeoff/stats.d.ts +13 -0
  78. package/dist/bakeoff/stats.d.ts.map +1 -0
  79. package/dist/bakeoff/stats.js +48 -0
  80. package/dist/bakeoff/types.d.ts +37 -0
  81. package/dist/bakeoff/types.d.ts.map +1 -0
  82. package/dist/bakeoff/types.js +10 -0
  83. package/dist/cli.d.ts +25 -0
  84. package/dist/cli.d.ts.map +1 -0
  85. package/dist/cli.js +590 -0
  86. package/dist/config.d.ts +204 -0
  87. package/dist/config.d.ts.map +1 -0
  88. package/dist/config.js +252 -0
  89. package/dist/deprecations.d.ts +32 -0
  90. package/dist/deprecations.d.ts.map +1 -0
  91. package/dist/deprecations.js +59 -0
  92. package/dist/feedback/coverage.d.ts +32 -0
  93. package/dist/feedback/coverage.d.ts.map +1 -0
  94. package/dist/feedback/coverage.js +95 -0
  95. package/dist/feedback/feedback.d.ts +35 -0
  96. package/dist/feedback/feedback.d.ts.map +1 -0
  97. package/dist/feedback/feedback.js +39 -0
  98. package/dist/gateway/http-protocol.d.ts +175 -0
  99. package/dist/gateway/http-protocol.d.ts.map +1 -0
  100. package/dist/gateway/http-protocol.js +105 -0
  101. package/dist/index.d.ts +242 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +576 -0
  104. package/dist/init/finder.d.ts +94 -0
  105. package/dist/init/finder.d.ts.map +1 -0
  106. package/dist/init/finder.js +343 -0
  107. package/dist/init/init-cli.d.ts +10 -0
  108. package/dist/init/init-cli.d.ts.map +1 -0
  109. package/dist/init/init-cli.js +86 -0
  110. package/dist/init/observe-cli.d.ts +19 -0
  111. package/dist/init/observe-cli.d.ts.map +1 -0
  112. package/dist/init/observe-cli.js +73 -0
  113. package/dist/init/observe.d.ts +81 -0
  114. package/dist/init/observe.d.ts.map +1 -0
  115. package/dist/init/observe.js +245 -0
  116. package/dist/init/run.d.ts +99 -0
  117. package/dist/init/run.d.ts.map +1 -0
  118. package/dist/init/run.js +281 -0
  119. package/dist/init/signatures.d.ts +39 -0
  120. package/dist/init/signatures.d.ts.map +1 -0
  121. package/dist/init/signatures.js +116 -0
  122. package/dist/matrix/aggregate.d.ts +89 -0
  123. package/dist/matrix/aggregate.d.ts.map +1 -0
  124. package/dist/matrix/aggregate.js +186 -0
  125. package/dist/query/grammar.d.ts +35 -0
  126. package/dist/query/grammar.d.ts.map +1 -0
  127. package/dist/query/grammar.js +279 -0
  128. package/dist/query/run.d.ts +8 -0
  129. package/dist/query/run.d.ts.map +1 -0
  130. package/dist/query/run.js +21 -0
  131. package/dist/registry/build.d.ts +219 -0
  132. package/dist/registry/build.d.ts.map +1 -0
  133. package/dist/registry/build.js +313 -0
  134. package/dist/registry/cache-policy.d.ts +94 -0
  135. package/dist/registry/cache-policy.d.ts.map +1 -0
  136. package/dist/registry/cache-policy.js +238 -0
  137. package/dist/registry/call-notes.d.ts +11 -0
  138. package/dist/registry/call-notes.d.ts.map +1 -0
  139. package/dist/registry/call-notes.js +110 -0
  140. package/dist/registry/claims.d.ts +63 -0
  141. package/dist/registry/claims.d.ts.map +1 -0
  142. package/dist/registry/claims.js +107 -0
  143. package/dist/registry/effective-rate.d.ts +151 -0
  144. package/dist/registry/effective-rate.d.ts.map +1 -0
  145. package/dist/registry/effective-rate.js +156 -0
  146. package/dist/registry/facts.d.ts +32 -0
  147. package/dist/registry/facts.d.ts.map +1 -0
  148. package/dist/registry/facts.js +136 -0
  149. package/dist/registry/fingerprint.d.ts +20 -0
  150. package/dist/registry/fingerprint.d.ts.map +1 -0
  151. package/dist/registry/fingerprint.js +150 -0
  152. package/dist/registry/parity.d.ts +52 -0
  153. package/dist/registry/parity.d.ts.map +1 -0
  154. package/dist/registry/parity.js +82 -0
  155. package/dist/registry/pricing-shape.d.ts +113 -0
  156. package/dist/registry/pricing-shape.d.ts.map +1 -0
  157. package/dist/registry/pricing-shape.js +123 -0
  158. package/dist/registry/pricing.d.ts +43 -0
  159. package/dist/registry/pricing.d.ts.map +1 -0
  160. package/dist/registry/pricing.js +127 -0
  161. package/dist/registry/rows.d.ts +16 -0
  162. package/dist/registry/rows.d.ts.map +1 -0
  163. package/dist/registry/rows.js +57 -0
  164. package/dist/registry/seed.d.ts +43 -0
  165. package/dist/registry/seed.d.ts.map +1 -0
  166. package/dist/registry/seed.js +97 -0
  167. package/dist/registry/select.d.ts +68 -0
  168. package/dist/registry/select.d.ts.map +1 -0
  169. package/dist/registry/select.js +141 -0
  170. package/dist/registry/staleness.d.ts +18 -0
  171. package/dist/registry/staleness.d.ts.map +1 -0
  172. package/dist/registry/staleness.js +39 -0
  173. package/dist/rigindex/bootstrap.d.ts +36 -0
  174. package/dist/rigindex/bootstrap.d.ts.map +1 -0
  175. package/dist/rigindex/bootstrap.js +97 -0
  176. package/dist/rigindex/fit.d.ts +24 -0
  177. package/dist/rigindex/fit.d.ts.map +1 -0
  178. package/dist/rigindex/fit.js +76 -0
  179. package/dist/rigindex/gates.d.ts +52 -0
  180. package/dist/rigindex/gates.d.ts.map +1 -0
  181. package/dist/rigindex/gates.js +109 -0
  182. package/dist/rigindex/graph.d.ts +31 -0
  183. package/dist/rigindex/graph.d.ts.map +1 -0
  184. package/dist/rigindex/graph.js +120 -0
  185. package/dist/rigindex/index.d.ts +23 -0
  186. package/dist/rigindex/index.d.ts.map +1 -0
  187. package/dist/rigindex/index.js +112 -0
  188. package/dist/rigindex/types.d.ts +76 -0
  189. package/dist/rigindex/types.d.ts.map +1 -0
  190. package/dist/rigindex/types.js +8 -0
  191. package/dist/routes/cache-lint.d.ts +41 -0
  192. package/dist/routes/cache-lint.d.ts.map +1 -0
  193. package/dist/routes/cache-lint.js +81 -0
  194. package/dist/routes/draft.d.ts +83 -0
  195. package/dist/routes/draft.d.ts.map +1 -0
  196. package/dist/routes/draft.js +135 -0
  197. package/dist/routes/loader.d.ts +63 -0
  198. package/dist/routes/loader.d.ts.map +1 -0
  199. package/dist/routes/loader.js +574 -0
  200. package/dist/routes/manifest.d.ts +24 -0
  201. package/dist/routes/manifest.d.ts.map +1 -0
  202. package/dist/routes/manifest.js +118 -0
  203. package/dist/routes/resolved-bundle.d.ts +79 -0
  204. package/dist/routes/resolved-bundle.d.ts.map +1 -0
  205. package/dist/routes/resolved-bundle.js +148 -0
  206. package/dist/routes/sampling-config.d.ts +32 -0
  207. package/dist/routes/sampling-config.d.ts.map +1 -0
  208. package/dist/routes/sampling-config.js +91 -0
  209. package/dist/routes/serveability.d.ts +52 -0
  210. package/dist/routes/serveability.d.ts.map +1 -0
  211. package/dist/routes/serveability.js +73 -0
  212. package/dist/routes/template.d.ts +18 -0
  213. package/dist/routes/template.d.ts.map +1 -0
  214. package/dist/routes/template.js +94 -0
  215. package/dist/run/ajv.d.ts +22 -0
  216. package/dist/run/ajv.d.ts.map +1 -0
  217. package/dist/run/ajv.js +32 -0
  218. package/dist/run/cache-handle.d.ts +58 -0
  219. package/dist/run/cache-handle.d.ts.map +1 -0
  220. package/dist/run/cache-handle.js +54 -0
  221. package/dist/run/cache-stamp.d.ts +65 -0
  222. package/dist/run/cache-stamp.d.ts.map +1 -0
  223. package/dist/run/cache-stamp.js +0 -0
  224. package/dist/run/capture-write.d.ts +33 -0
  225. package/dist/run/capture-write.d.ts.map +1 -0
  226. package/dist/run/capture-write.js +55 -0
  227. package/dist/run/cost.d.ts +26 -0
  228. package/dist/run/cost.d.ts.map +1 -0
  229. package/dist/run/cost.js +41 -0
  230. package/dist/run/dispatch.d.ts +99 -0
  231. package/dist/run/dispatch.d.ts.map +1 -0
  232. package/dist/run/dispatch.js +191 -0
  233. package/dist/run/envelope.d.ts +21 -0
  234. package/dist/run/envelope.d.ts.map +1 -0
  235. package/dist/run/envelope.js +45 -0
  236. package/dist/run/grounding.d.ts +56 -0
  237. package/dist/run/grounding.d.ts.map +1 -0
  238. package/dist/run/grounding.js +89 -0
  239. package/dist/run/raw.d.ts +88 -0
  240. package/dist/run/raw.d.ts.map +1 -0
  241. package/dist/run/raw.js +286 -0
  242. package/dist/run/record-attempt.d.ts +40 -0
  243. package/dist/run/record-attempt.d.ts.map +1 -0
  244. package/dist/run/record-attempt.js +99 -0
  245. package/dist/run/repair.d.ts +36 -0
  246. package/dist/run/repair.d.ts.map +1 -0
  247. package/dist/run/repair.js +61 -0
  248. package/dist/run/resolve.d.ts +99 -0
  249. package/dist/run/resolve.d.ts.map +1 -0
  250. package/dist/run/resolve.js +203 -0
  251. package/dist/run/retry.d.ts +19 -0
  252. package/dist/run/retry.d.ts.map +1 -0
  253. package/dist/run/retry.js +50 -0
  254. package/dist/run/run.d.ts +55 -0
  255. package/dist/run/run.d.ts.map +1 -0
  256. package/dist/run/run.js +540 -0
  257. package/dist/run/stream.d.ts +49 -0
  258. package/dist/run/stream.d.ts.map +1 -0
  259. package/dist/run/stream.js +87 -0
  260. package/dist/run/validate.d.ts +15 -0
  261. package/dist/run/validate.d.ts.map +1 -0
  262. package/dist/run/validate.js +55 -0
  263. package/dist/savings/cache-ledger.d.ts +108 -0
  264. package/dist/savings/cache-ledger.d.ts.map +1 -0
  265. package/dist/savings/cache-ledger.js +174 -0
  266. package/dist/savings/cache-reconcile.d.ts +64 -0
  267. package/dist/savings/cache-reconcile.d.ts.map +1 -0
  268. package/dist/savings/cache-reconcile.js +59 -0
  269. package/dist/savings/cache-stats.d.ts +63 -0
  270. package/dist/savings/cache-stats.d.ts.map +1 -0
  271. package/dist/savings/cache-stats.js +108 -0
  272. package/dist/savings/emit.d.ts +38 -0
  273. package/dist/savings/emit.d.ts.map +1 -0
  274. package/dist/savings/emit.js +100 -0
  275. package/dist/savings/odometer.d.ts +32 -0
  276. package/dist/savings/odometer.d.ts.map +1 -0
  277. package/dist/savings/odometer.js +70 -0
  278. package/dist/savings/swap-execute.d.ts +58 -0
  279. package/dist/savings/swap-execute.d.ts.map +1 -0
  280. package/dist/savings/swap-execute.js +130 -0
  281. package/dist/savings/swaps-client.d.ts +55 -0
  282. package/dist/savings/swaps-client.d.ts.map +1 -0
  283. package/dist/savings/swaps-client.js +95 -0
  284. package/dist/settings/api-fetcher.d.ts +39 -0
  285. package/dist/settings/api-fetcher.d.ts.map +1 -0
  286. package/dist/settings/api-fetcher.js +92 -0
  287. package/dist/settings/index.d.ts +10 -0
  288. package/dist/settings/index.d.ts.map +1 -0
  289. package/dist/settings/index.js +15 -0
  290. package/dist/settings/task-settings.d.ts +91 -0
  291. package/dist/settings/task-settings.d.ts.map +1 -0
  292. package/dist/settings/task-settings.js +116 -0
  293. package/dist/status.d.ts +77 -0
  294. package/dist/status.d.ts.map +1 -0
  295. package/dist/status.js +113 -0
  296. package/dist/telemetry/artifact-store.d.ts +48 -0
  297. package/dist/telemetry/artifact-store.d.ts.map +1 -0
  298. package/dist/telemetry/artifact-store.js +189 -0
  299. package/dist/telemetry/cache-miss-streak.d.ts +79 -0
  300. package/dist/telemetry/cache-miss-streak.d.ts.map +1 -0
  301. package/dist/telemetry/cache-miss-streak.js +99 -0
  302. package/dist/telemetry/capture.d.ts +31 -0
  303. package/dist/telemetry/capture.d.ts.map +1 -0
  304. package/dist/telemetry/capture.js +81 -0
  305. package/dist/telemetry/exporter-setup.d.ts +28 -0
  306. package/dist/telemetry/exporter-setup.d.ts.map +1 -0
  307. package/dist/telemetry/exporter-setup.js +34 -0
  308. package/dist/telemetry/exporter.d.ts +137 -0
  309. package/dist/telemetry/exporter.d.ts.map +1 -0
  310. package/dist/telemetry/exporter.js +510 -0
  311. package/dist/telemetry/health.d.ts +76 -0
  312. package/dist/telemetry/health.d.ts.map +1 -0
  313. package/dist/telemetry/health.js +92 -0
  314. package/dist/telemetry/ingest-protocol.d.ts +310 -0
  315. package/dist/telemetry/ingest-protocol.d.ts.map +1 -0
  316. package/dist/telemetry/ingest-protocol.js +363 -0
  317. package/dist/telemetry/load-error-report.d.ts +24 -0
  318. package/dist/telemetry/load-error-report.d.ts.map +1 -0
  319. package/dist/telemetry/load-error-report.js +50 -0
  320. package/dist/telemetry/otel-map.d.ts +121 -0
  321. package/dist/telemetry/otel-map.d.ts.map +1 -0
  322. package/dist/telemetry/otel-map.js +224 -0
  323. package/dist/telemetry/otel-normalize.d.ts +104 -0
  324. package/dist/telemetry/otel-normalize.d.ts.map +1 -0
  325. package/dist/telemetry/otel-normalize.js +530 -0
  326. package/dist/telemetry/otlp-emitter.d.ts +52 -0
  327. package/dist/telemetry/otlp-emitter.d.ts.map +1 -0
  328. package/dist/telemetry/otlp-emitter.js +144 -0
  329. package/dist/telemetry/otlp-proto.d.ts +29 -0
  330. package/dist/telemetry/otlp-proto.d.ts.map +1 -0
  331. package/dist/telemetry/otlp-proto.js +266 -0
  332. package/dist/telemetry/sinks.d.ts +90 -0
  333. package/dist/telemetry/sinks.d.ts.map +1 -0
  334. package/dist/telemetry/sinks.js +180 -0
  335. package/dist/telemetry/store.d.ts +65 -0
  336. package/dist/telemetry/store.d.ts.map +1 -0
  337. package/dist/telemetry/store.js +547 -0
  338. package/dist/tenancy/api-key-format.d.ts +77 -0
  339. package/dist/tenancy/api-key-format.d.ts.map +1 -0
  340. package/dist/tenancy/api-key-format.js +110 -0
  341. package/dist/tenancy/constants.d.ts +23 -0
  342. package/dist/tenancy/constants.d.ts.map +1 -0
  343. package/dist/tenancy/constants.js +25 -0
  344. package/dist/tenancy/scrub.d.ts +47 -0
  345. package/dist/tenancy/scrub.d.ts.map +1 -0
  346. package/dist/tenancy/scrub.js +85 -0
  347. package/dist/types/config-teaching.d.ts +62 -0
  348. package/dist/types/config-teaching.d.ts.map +1 -0
  349. package/dist/types/config-teaching.js +183 -0
  350. package/dist/types/failures-teaching.d.ts +56 -0
  351. package/dist/types/failures-teaching.d.ts.map +1 -0
  352. package/dist/types/failures-teaching.js +177 -0
  353. package/dist/types/failures.d.ts +27 -0
  354. package/dist/types/failures.d.ts.map +1 -0
  355. package/dist/types/failures.js +41 -0
  356. package/dist/types/provider.d.ts +200 -0
  357. package/dist/types/provider.d.ts.map +1 -0
  358. package/dist/types/provider.js +40 -0
  359. package/dist/types/route.d.ts +205 -0
  360. package/dist/types/route.d.ts.map +1 -0
  361. package/dist/types/route.js +6 -0
  362. package/dist/types/telemetry.d.ts +206 -0
  363. package/dist/types/telemetry.d.ts.map +1 -0
  364. package/dist/types/telemetry.js +6 -0
  365. package/dist/validate-cli.d.ts +12 -0
  366. package/dist/validate-cli.d.ts.map +1 -0
  367. package/dist/validate-cli.js +57 -0
  368. package/dist/verify/capture.d.ts +66 -0
  369. package/dist/verify/capture.d.ts.map +1 -0
  370. package/dist/verify/capture.js +180 -0
  371. package/dist/verify/cli-run.d.ts +23 -0
  372. package/dist/verify/cli-run.d.ts.map +1 -0
  373. package/dist/verify/cli-run.js +57 -0
  374. package/dist/verify/diff.d.ts +48 -0
  375. package/dist/verify/diff.d.ts.map +1 -0
  376. package/dist/verify/diff.js +157 -0
  377. package/dist/verify/index.d.ts +17 -0
  378. package/dist/verify/index.d.ts.map +1 -0
  379. package/dist/verify/index.js +24 -0
  380. package/dist/verify/report.d.ts +14 -0
  381. package/dist/verify/report.d.ts.map +1 -0
  382. package/dist/verify/report.js +88 -0
  383. package/dist/verify/types.d.ts +101 -0
  384. package/dist/verify/types.d.ts.map +1 -0
  385. package/dist/verify/types.js +17 -0
  386. package/dist/verify/verify.d.ts +29 -0
  387. package/dist/verify/verify.d.ts.map +1 -0
  388. package/dist/verify/verify.js +148 -0
  389. package/dist/watch/budget.d.ts +19 -0
  390. package/dist/watch/budget.d.ts.map +1 -0
  391. package/dist/watch/budget.js +35 -0
  392. package/dist/watch/evaluate.d.ts +225 -0
  393. package/dist/watch/evaluate.d.ts.map +1 -0
  394. package/dist/watch/evaluate.js +155 -0
  395. package/dist/watch/monitor.d.ts +116 -0
  396. package/dist/watch/monitor.d.ts.map +1 -0
  397. package/dist/watch/monitor.js +199 -0
  398. package/dist/watch/proposals.d.ts +89 -0
  399. package/dist/watch/proposals.d.ts.map +1 -0
  400. package/dist/watch/proposals.js +197 -0
  401. package/dist/watch/run-record.d.ts +64 -0
  402. package/dist/watch/run-record.d.ts.map +1 -0
  403. package/dist/watch/run-record.js +86 -0
  404. package/dist/watch/run-reported.d.ts +20 -0
  405. package/dist/watch/run-reported.d.ts.map +1 -0
  406. package/dist/watch/run-reported.js +53 -0
  407. package/dist/watch/run.d.ts +73 -0
  408. package/dist/watch/run.d.ts.map +1 -0
  409. package/dist/watch/run.js +83 -0
  410. package/dist/watch/state-store.d.ts +48 -0
  411. package/dist/watch/state-store.d.ts.map +1 -0
  412. package/dist/watch/state-store.js +86 -0
  413. package/dist/watch/state.d.ts +21 -0
  414. package/dist/watch/state.d.ts.map +1 -0
  415. package/dist/watch/state.js +93 -0
  416. package/package.json +56 -14
  417. package/registry/LICENSE +20 -0
  418. package/registry/leaderboard.json +3639 -0
  419. package/registry/registry.json +7263 -0
  420. package/index.js +0 -3
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ /**
3
+ * Streaming surface on the run path — G-1/G-5 Phase A (http-gateway spec §4.3).
4
+ *
5
+ * `runStream` wraps the existing `run()` loop with a delta side-channel: as the
6
+ * serving adapter streams, raw text tokens are emitted as `delta` events; when
7
+ * the run resolves, its terminal `RunResult` is emitted as the `final` event.
8
+ * Crucially the SAME pipeline (resolve → dispatch → validate → repair →
9
+ * telemetry) drives both streamed and buffered runs — streaming is purely a
10
+ * side-channel, so validation, repair, ZDR (G-3) and routing controls (G-2)
11
+ * all apply unchanged. `rig.run()` is left exactly as it was.
12
+ *
13
+ * The structured-route caveat (spec §4.3): streamed `delta` bytes are the
14
+ * model's RAW pre-validation output. The `final` event is authoritative — it
15
+ * carries the schema-validated (and, if repair fired, repaired) object plus
16
+ * `meta.validated` / `meta.repairedBy`. Callers wanting validated-only output
17
+ * pass `buffered: true` (no deltas, just the final) — the SDK mirror of the
18
+ * endpoint's `x-modelrig-stream: buffered`.
19
+ *
20
+ * ModelRig never executes a tool (spec §4.4); a tool-call turn surfaces on the
21
+ * final event's `meta.toolCalls` exactly as it does through `run()`.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.runStream = runStream;
25
+ const run_1 = require("./run");
26
+ /**
27
+ * Drive a route with token streaming. Returns an async-iterable of events plus
28
+ * a `result` promise for callers that only want the terminal value.
29
+ */
30
+ function runStream(deps, routeName, opts) {
31
+ const queue = [];
32
+ let wake = null;
33
+ let done = false;
34
+ let failure = null;
35
+ const emit = (ev) => {
36
+ queue.push(ev);
37
+ if (wake !== null) {
38
+ wake();
39
+ wake = null;
40
+ }
41
+ };
42
+ const finish = () => {
43
+ done = true;
44
+ if (wake !== null) {
45
+ wake();
46
+ wake = null;
47
+ }
48
+ };
49
+ // Buffered mode omits the delta sink entirely — the loop then dispatches via
50
+ // the adapter's buffered call() (no true streaming), exactly as before.
51
+ const streamDeps = opts.buffered === true
52
+ ? deps
53
+ : { ...deps, onStreamDelta: ({ text }) => emit({ type: "delta", text }) };
54
+ const result = (0, run_1.run)(streamDeps, routeName, opts)
55
+ .then((r) => {
56
+ emit({ type: "final", result: r });
57
+ return r;
58
+ })
59
+ .catch((e) => {
60
+ failure = e;
61
+ throw e;
62
+ })
63
+ .finally(finish);
64
+ // A caller may consume only `events`; keep the promise from becoming an
65
+ // unhandled rejection (the error still surfaces through the iterator).
66
+ result.catch(() => undefined);
67
+ const events = {
68
+ async *[Symbol.asyncIterator]() {
69
+ for (;;) {
70
+ while (queue.length > 0) {
71
+ const ev = queue.shift();
72
+ if (ev !== undefined)
73
+ yield ev;
74
+ }
75
+ if (done) {
76
+ if (failure !== null)
77
+ throw failure;
78
+ return;
79
+ }
80
+ await new Promise((res) => {
81
+ wake = res;
82
+ });
83
+ }
84
+ },
85
+ };
86
+ return { events, result };
87
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Output validation — plan §4. Ajv compiled once per (route, version), cached.
3
+ * Phase 1 checks schema conformance; value-accuracy gates arrive with the
4
+ * bake-off in Phase 3.
5
+ */
6
+ import type { RouteBundle } from "../types/route";
7
+ export interface ValidationOutcome {
8
+ readonly valid: boolean;
9
+ /** ajv error summaries, capped, human- and agent-readable. */
10
+ readonly errors: readonly string[];
11
+ /** Parsed output when text was JSON-parseable (even if schema-invalid). */
12
+ readonly parsed: unknown;
13
+ }
14
+ export declare function validateOutput(route: RouteBundle, text: string): ValidationOutcome;
15
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/run/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAwBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA6BlF"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ /**
3
+ * Output validation — plan §4. Ajv compiled once per (route, version), cached.
4
+ * Phase 1 checks schema conformance; value-accuracy gates arrive with the
5
+ * bake-off in Phase 3.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.validateOutput = validateOutput;
9
+ const ajv_1 = require("./ajv");
10
+ // Mirrors the production probe harness (packages/modelrig-probes/src/harness.ts):
11
+ // an Ajv-2020 instance with the draft-07 meta added for back-compat — the two
12
+ // must enforce identically, or a fixture would score differently than it serves.
13
+ // Schemas trip ajv strict-mode warnings by design (strict:false).
14
+ const ajv = (0, ajv_1.createModelrigAjv)();
15
+ const MAX_ERRORS = 12;
16
+ /** Compiled validators cached per (route, version) — recompiling a 300-line
17
+ * schema per attempt is measurable. */
18
+ const validatorCache = new Map();
19
+ function validatorFor(route) {
20
+ const key = `${route.route}@${route.version}`;
21
+ let compiled = validatorCache.get(key);
22
+ if (compiled === undefined) {
23
+ compiled = ajv.compile(route.outputSchema);
24
+ validatorCache.set(key, compiled);
25
+ }
26
+ return compiled;
27
+ }
28
+ function validateOutput(route, text) {
29
+ let parsed;
30
+ try {
31
+ parsed = JSON.parse(text);
32
+ }
33
+ catch (err) {
34
+ return {
35
+ valid: false,
36
+ errors: [`output is not valid JSON: ${err.message}`],
37
+ parsed: undefined,
38
+ };
39
+ }
40
+ if (route.outputSchema === null) {
41
+ return { valid: true, errors: [], parsed };
42
+ }
43
+ const validate = validatorFor(route);
44
+ if (validate(parsed)) {
45
+ return { valid: true, errors: [], parsed };
46
+ }
47
+ const all = validate.errors ?? [];
48
+ const errors = all
49
+ .slice(0, MAX_ERRORS)
50
+ .map((e) => `${e.instancePath || "/"} ${e.message ?? "invalid"}${e.keyword === "enum" ? ` (${JSON.stringify(e.params)})` : ""}`);
51
+ if (all.length > MAX_ERRORS) {
52
+ errors.push(`… ${all.length - MAX_ERRORS} more errors`);
53
+ }
54
+ return { valid: false, errors, parsed };
55
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Cache Ledger — DERIVED in v1 (cache-aware-routing spec §5.2, [Briefing §8]).
3
+ *
4
+ * The Briefing's Cache Ledger is a first-class fast-state store; v1 does NOT
5
+ * build one. It DERIVES warm-set state from telemetry rows at decision time —
6
+ * ZERO new tables (spec schema budget). The `CacheLedgerEntry` TYPE ships now so
7
+ * that when the conversational-gateway phase needs a dedicated store (per-message
8
+ * traffic makes per-call derivation too hot), it is a swap of BACKING, not of
9
+ * SHAPE. Nothing here persists anything.
10
+ *
11
+ * This answers the Briefing's first-milestone question — "which candidate routes
12
+ * appear warm, by how much, at what confidence" [§41] — with a 4-value status:
13
+ *
14
+ * observed_hot — the most recent use within the TTL window actually READ
15
+ * cache (tokensCached>0): the cache is demonstrably warm.
16
+ * probably_hot — last use within the TTL window but no read observed on it:
17
+ * warmth is INFERRED from recency, not seen.
18
+ * probably_expired— last use past the TTL but within a bounded grace: likely
19
+ * cold, yet recent enough that a switch-back could still hit
20
+ * (LiteLLM: 99.3% of switch-backs land within TTL, [§6]).
21
+ * cold — no recent use, well past any grace, or the provider does
22
+ * not cache on our path (fail-closed).
23
+ *
24
+ * ── CONSERVATISM (spec §10 cache-state overconfidence) ────────────────────
25
+ * The TTL comes from the POLICY REGISTRY only. When a provider publishes no TTL
26
+ * (deepseek "hours-to-days", gemini/fireworks best-effort → `default_ttl_seconds:
27
+ * null`), we do NOT invent a warm window: the entry can reach `observed_hot`
28
+ * only via a demonstrated read within a short fallback recency, and otherwise is
29
+ * `cold`. Under-claiming warmth never over-predicts a hit.
30
+ */
31
+ import type { CachePolicy } from "../registry/cache-policy";
32
+ import type { ProviderId } from "../types/provider";
33
+ import type { TelemetryRow } from "../types/telemetry";
34
+ export type WarmStatus = "observed_hot" | "probably_hot" | "probably_expired" | "cold";
35
+ /**
36
+ * One derived warm-set entry: a (route, candidate, prefix_fingerprint, cache_key)
37
+ * group's current cache standing. The shape is the phase-2 storage seam —
38
+ * everything a dedicated ledger row would carry is here, derived.
39
+ */
40
+ export interface CacheLedgerEntry {
41
+ readonly route: string;
42
+ readonly provider: string;
43
+ readonly model: string;
44
+ /** The cacheable-prefix identity (WS-C fills it; null in WS-A telemetry). */
45
+ readonly prefixFingerprint: string | null;
46
+ /** The provider cache key sent, if any (WS-C fills it; null otherwise). */
47
+ readonly cacheKey: string | null;
48
+ readonly status: WarmStatus;
49
+ /** Most recent use of this group (ISO). */
50
+ readonly lastSeenAt: string;
51
+ /** Seconds since `lastSeenAt` relative to the injected `now`. */
52
+ readonly ageSeconds: number;
53
+ /** Best estimate of the warm prefix size, tokens ("by how much" [§41]): the
54
+ * largest observed cache-READ on the group, or — when no read was observed —
55
+ * the mean input tokens as an upper bound of what COULD be cached. */
56
+ readonly warmTokens: number;
57
+ /** Largest observed cache-read on the group (0 ⇒ warmth is inferred, not seen). */
58
+ readonly observedReadTokens: number;
59
+ /** The policy TTL used to classify (seconds), or null when undocumented. */
60
+ readonly ttlSeconds: number | null;
61
+ /** Workflow identity (spec §9): run-loop = route; E2 runs carry episode_id.
62
+ * v1 normalizes to the route handle — the field exists so the ledger type is
63
+ * stable when episode-keyed workflows arrive. */
64
+ readonly workflowId: string;
65
+ }
66
+ export interface CacheLedgerOptions {
67
+ /** Reference "now" (epoch ms) — injected for deterministic derivation/tests. */
68
+ readonly now: number;
69
+ /** Policy lookup — injected for tests; defaults to the live registry. */
70
+ readonly policyFor?: (provider: ProviderId) => CachePolicy;
71
+ /** Only rows at/after this window start (epoch ms) are considered. Older rows
72
+ * cannot be warm and are skipped. Defaults to 24h before `now` — well past any
73
+ * seeded TTL, so no genuinely-warm group is dropped. */
74
+ readonly windowStartMs?: number;
75
+ }
76
+ /**
77
+ * Fallback recency window (seconds) for the `observed_hot` decision when a
78
+ * provider publishes NO TTL. NOT a claimed provider TTL — a conservative display
79
+ * bound so an ancient demonstrated read is not still called "hot". 5 minutes is
80
+ * the shortest real cache TTL in the registry (Anthropic 5m), so it never
81
+ * over-claims relative to any documented policy.
82
+ */
83
+ export declare const NULL_TTL_OBSERVED_HOT_SECONDS = 300;
84
+ /**
85
+ * Grace multiplier past the TTL for `probably_expired` before an entry is called
86
+ * `cold`. Beyond `ttl × this`, a switch-back is very unlikely to still hit.
87
+ */
88
+ export declare const PROBABLY_EXPIRED_TTL_MULTIPLE = 3;
89
+ /**
90
+ * Classify a group's warm status from its policy TTL, age, and whether the most
91
+ * recent use read cache. Pure and total; the boundary rules are the architect
92
+ * math-review surface, so they are spelled out rather than folded together.
93
+ */
94
+ export declare function classifyWarmStatus(policy: CachePolicy, ageSeconds: number, lastUseReadCache: boolean): WarmStatus;
95
+ /**
96
+ * Derive the warm-set ledger from telemetry rows (spec §5.2). Groups production
97
+ * rows by (route, provider, model, prefix_fingerprint, cache_key), takes each
98
+ * group's most-recent use to classify warmth via the policy TTL, and estimates
99
+ * the warm prefix size. Replay rows are excluded (odometer parity). Output is
100
+ * sorted for deterministic rendering. Nothing is stored.
101
+ */
102
+ export declare function deriveCacheLedger(rows: readonly TelemetryRow[], opts: CacheLedgerOptions): CacheLedgerEntry[];
103
+ /** The warm candidates for a route — `observed_hot` or `probably_hot` — as the
104
+ * warmth input for shadow-mode ordering (WS-B step 8) and the console warm-set
105
+ * chips (WS-D). `probably_expired`/`cold` are excluded: warmth we would ACT on
106
+ * must be current, not merely recent. */
107
+ export declare function warmEntries(ledger: readonly CacheLedgerEntry[]): CacheLedgerEntry[];
108
+ //# sourceMappingURL=cache-ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-ledger.d.ts","sourceRoot":"","sources":["../../src/savings/cache-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,cAAc,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAEvF;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;0EAEsE;IACtE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;qDAEiD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,WAAW,CAAC;IAC3D;;4DAEwD;IACxD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAa/C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,OAAO,GACxB,UAAU,CAkBZ;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,YAAY,EAAE,EAC7B,IAAI,EAAE,kBAAkB,GACvB,gBAAgB,EAAE,CA6FpB;AAED;;;yCAGyC;AACzC,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAEnF"}
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ /**
3
+ * Cache Ledger — DERIVED in v1 (cache-aware-routing spec §5.2, [Briefing §8]).
4
+ *
5
+ * The Briefing's Cache Ledger is a first-class fast-state store; v1 does NOT
6
+ * build one. It DERIVES warm-set state from telemetry rows at decision time —
7
+ * ZERO new tables (spec schema budget). The `CacheLedgerEntry` TYPE ships now so
8
+ * that when the conversational-gateway phase needs a dedicated store (per-message
9
+ * traffic makes per-call derivation too hot), it is a swap of BACKING, not of
10
+ * SHAPE. Nothing here persists anything.
11
+ *
12
+ * This answers the Briefing's first-milestone question — "which candidate routes
13
+ * appear warm, by how much, at what confidence" [§41] — with a 4-value status:
14
+ *
15
+ * observed_hot — the most recent use within the TTL window actually READ
16
+ * cache (tokensCached>0): the cache is demonstrably warm.
17
+ * probably_hot — last use within the TTL window but no read observed on it:
18
+ * warmth is INFERRED from recency, not seen.
19
+ * probably_expired— last use past the TTL but within a bounded grace: likely
20
+ * cold, yet recent enough that a switch-back could still hit
21
+ * (LiteLLM: 99.3% of switch-backs land within TTL, [§6]).
22
+ * cold — no recent use, well past any grace, or the provider does
23
+ * not cache on our path (fail-closed).
24
+ *
25
+ * ── CONSERVATISM (spec §10 cache-state overconfidence) ────────────────────
26
+ * The TTL comes from the POLICY REGISTRY only. When a provider publishes no TTL
27
+ * (deepseek "hours-to-days", gemini/fireworks best-effort → `default_ttl_seconds:
28
+ * null`), we do NOT invent a warm window: the entry can reach `observed_hot`
29
+ * only via a demonstrated read within a short fallback recency, and otherwise is
30
+ * `cold`. Under-claiming warmth never over-predicts a hit.
31
+ */
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.PROBABLY_EXPIRED_TTL_MULTIPLE = exports.NULL_TTL_OBSERVED_HOT_SECONDS = void 0;
34
+ exports.classifyWarmStatus = classifyWarmStatus;
35
+ exports.deriveCacheLedger = deriveCacheLedger;
36
+ exports.warmEntries = warmEntries;
37
+ const cache_policy_1 = require("../registry/cache-policy");
38
+ /**
39
+ * Fallback recency window (seconds) for the `observed_hot` decision when a
40
+ * provider publishes NO TTL. NOT a claimed provider TTL — a conservative display
41
+ * bound so an ancient demonstrated read is not still called "hot". 5 minutes is
42
+ * the shortest real cache TTL in the registry (Anthropic 5m), so it never
43
+ * over-claims relative to any documented policy.
44
+ */
45
+ exports.NULL_TTL_OBSERVED_HOT_SECONDS = 300;
46
+ /**
47
+ * Grace multiplier past the TTL for `probably_expired` before an entry is called
48
+ * `cold`. Beyond `ttl × this`, a switch-back is very unlikely to still hit.
49
+ */
50
+ exports.PROBABLY_EXPIRED_TTL_MULTIPLE = 3;
51
+ // Grouping key — none of the components contains a newline.
52
+ const KEY_SEP = "\n";
53
+ function isProductionRow(row) {
54
+ try {
55
+ return JSON.parse(row.tagsJson).replay === undefined;
56
+ }
57
+ catch {
58
+ return true;
59
+ }
60
+ }
61
+ /**
62
+ * Classify a group's warm status from its policy TTL, age, and whether the most
63
+ * recent use read cache. Pure and total; the boundary rules are the architect
64
+ * math-review surface, so they are spelled out rather than folded together.
65
+ */
66
+ function classifyWarmStatus(policy, ageSeconds, lastUseReadCache) {
67
+ if (!policy.cache_supported)
68
+ return "cold";
69
+ const ttl = policy.default_ttl_seconds;
70
+ if (ttl === null) {
71
+ // No documented TTL: only a demonstrated, recent read earns "hot". We never
72
+ // INFER warmth here (no probably_hot) — that would be the overconfidence the
73
+ // spec §10 warns against.
74
+ return lastUseReadCache && ageSeconds <= exports.NULL_TTL_OBSERVED_HOT_SECONDS ? "observed_hot" : "cold";
75
+ }
76
+ if (ageSeconds <= ttl) {
77
+ return lastUseReadCache ? "observed_hot" : "probably_hot";
78
+ }
79
+ if (ageSeconds <= ttl * exports.PROBABLY_EXPIRED_TTL_MULTIPLE) {
80
+ return "probably_expired";
81
+ }
82
+ return "cold";
83
+ }
84
+ /**
85
+ * Derive the warm-set ledger from telemetry rows (spec §5.2). Groups production
86
+ * rows by (route, provider, model, prefix_fingerprint, cache_key), takes each
87
+ * group's most-recent use to classify warmth via the policy TTL, and estimates
88
+ * the warm prefix size. Replay rows are excluded (odometer parity). Output is
89
+ * sorted for deterministic rendering. Nothing is stored.
90
+ */
91
+ function deriveCacheLedger(rows, opts) {
92
+ const policyFor = opts.policyFor ?? ((p) => (0, cache_policy_1.getCachePolicy)(p));
93
+ const windowStartMs = opts.windowStartMs ?? opts.now - 86400000;
94
+ const byKey = new Map();
95
+ for (const row of rows) {
96
+ if (!isProductionRow(row))
97
+ continue;
98
+ const t = Date.parse(row.ts);
99
+ if (Number.isNaN(t) || t < windowStartMs || t > opts.now)
100
+ continue;
101
+ const fp = row.prefixFingerprint ?? null;
102
+ const ck = row.cacheKey ?? null;
103
+ const key = [row.route, row.provider, row.model, fp ?? "", ck ?? ""].join(KEY_SEP);
104
+ let acc = byKey.get(key);
105
+ if (acc === undefined) {
106
+ acc = {
107
+ route: row.route,
108
+ provider: row.provider,
109
+ model: row.model,
110
+ prefixFingerprint: fp,
111
+ cacheKey: ck,
112
+ lastSeenAtMs: -1,
113
+ lastSeenAt: row.ts,
114
+ lastUseReadCache: false,
115
+ maxReadTokens: 0,
116
+ tokensInSum: 0,
117
+ n: 0,
118
+ };
119
+ byKey.set(key, acc);
120
+ }
121
+ acc.n += 1;
122
+ acc.tokensInSum += Math.max(row.tokensIn, 0);
123
+ acc.maxReadTokens = Math.max(acc.maxReadTokens, Math.max(row.tokensCached, 0));
124
+ if (t > acc.lastSeenAtMs) {
125
+ acc.lastSeenAtMs = t;
126
+ acc.lastSeenAt = row.ts;
127
+ acc.lastUseReadCache = row.tokensCached > 0;
128
+ }
129
+ else if (t === acc.lastSeenAtMs && row.tokensCached > 0) {
130
+ // Same-ms tie: a DEMONSTRATED read at the newest timestamp wins,
131
+ // regardless of row order in the (unsorted) feed. Without this the
132
+ // observed_hot/probably_hot status would depend on array order — a
133
+ // reordered feed of the same rows could flip the status. Preferring the
134
+ // read is the truer signal (the cache WAS warm at that instant).
135
+ acc.lastUseReadCache = true;
136
+ }
137
+ }
138
+ const out = [];
139
+ for (const acc of byKey.values()) {
140
+ const ageSeconds = Math.max(0, (opts.now - acc.lastSeenAtMs) / 1000);
141
+ const policy = policyFor(acc.provider);
142
+ const status = classifyWarmStatus(policy, ageSeconds, acc.lastUseReadCache);
143
+ const meanIn = acc.n > 0 ? acc.tokensInSum / acc.n : 0;
144
+ const warmTokens = acc.maxReadTokens > 0 ? acc.maxReadTokens : meanIn;
145
+ out.push({
146
+ route: acc.route,
147
+ provider: acc.provider,
148
+ model: acc.model,
149
+ prefixFingerprint: acc.prefixFingerprint,
150
+ cacheKey: acc.cacheKey,
151
+ status,
152
+ lastSeenAt: acc.lastSeenAt,
153
+ ageSeconds,
154
+ warmTokens,
155
+ observedReadTokens: acc.maxReadTokens,
156
+ ttlSeconds: policy.cache_supported ? policy.default_ttl_seconds : null,
157
+ workflowId: acc.route,
158
+ });
159
+ }
160
+ return out.sort((a, b) => a.route !== b.route
161
+ ? a.route.localeCompare(b.route)
162
+ : a.provider !== b.provider
163
+ ? a.provider.localeCompare(b.provider)
164
+ : a.model !== b.model
165
+ ? a.model.localeCompare(b.model)
166
+ : (a.prefixFingerprint ?? "").localeCompare(b.prefixFingerprint ?? ""));
167
+ }
168
+ /** The warm candidates for a route — `observed_hot` or `probably_hot` — as the
169
+ * warmth input for shadow-mode ordering (WS-B step 8) and the console warm-set
170
+ * chips (WS-D). `probably_expired`/`cold` are excluded: warmth we would ACT on
171
+ * must be current, not merely recent. */
172
+ function warmEntries(ledger) {
173
+ return ledger.filter((e) => e.status === "observed_hot" || e.status === "probably_hot");
174
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Cache prediction reconciliation — cache-aware-routing spec §5.2 (the
3
+ * [Briefing §8] feedback loop, v1-deterministic). PURE: no store/clock/network.
4
+ *
5
+ * "Predict → route → observe → reconcile" (spec §1.2): the derived ledger + the
6
+ * simulator PREDICT cache reads; provider-reported usage is GROUND TRUTH. When
7
+ * the two diverge beyond tolerance, the estimate is systematically off — a
8
+ * provider rule changed, a fingerprint is unstable, an endpoint lost affinity —
9
+ * and a `cache_prediction_drift` health event fires so the discrepancy is
10
+ * surfaced rather than silently trusted.
11
+ *
12
+ * G-4 PATTERN (telemetry/health.ts): this is a pure aggregation that RETURNS
13
+ * event objects — it never persists. A min-sample gate protects against calling
14
+ * two noisy calls a "drift". WS-D renders the events (console badge); no DDL and
15
+ * no new table are involved (spec schema budget).
16
+ */
17
+ /** A predicted-vs-observed pair for one (route, candidate) over the window. */
18
+ export interface CachePredictionSample {
19
+ readonly route: string;
20
+ readonly provider: string;
21
+ readonly model: string;
22
+ /** Cache-READ tokens the ledger/simulator predicted over the window. */
23
+ readonly predictedReadTokens: number;
24
+ /** Cache-READ tokens the provider actually reported (Σ tokensCached). */
25
+ readonly observedReadTokens: number;
26
+ /** Total input tokens over the window — the base the drift is normalized by,
27
+ * and the min-sample gate. */
28
+ readonly windowInputTokens: number;
29
+ /** Production rows the pair aggregates (for the gate + the surfaced evidence). */
30
+ readonly sampleN: number;
31
+ }
32
+ /** A fired drift event (G-4 shape). Never persisted; rendered by WS-D. */
33
+ export interface CachePredictionDrift {
34
+ readonly route: string;
35
+ readonly provider: string;
36
+ readonly model: string;
37
+ readonly predictedReadTokens: number;
38
+ readonly observedReadTokens: number;
39
+ /** |predicted − observed| / windowInputTokens — the normalized gap. */
40
+ readonly driftFraction: number;
41
+ /** Signed hit-rate error (predicted_h − observed_h): positive ⇒ we OVER-predicted
42
+ * warmth (the more dangerous direction — over-optimistic routing). */
43
+ readonly signedHitRateError: number;
44
+ readonly sampleN: number;
45
+ }
46
+ export interface ReconcileOptions {
47
+ /** Drift tolerance as a FRACTION of window input tokens (default 0.15 — the
48
+ * estimate must be within 15% of ground truth before it is "off"). */
49
+ readonly toleranceFraction?: number;
50
+ /** Minimum production rows before a pair is judged (default 20 — matches the
51
+ * observed-health min-n; below it the gap is too noisy to trust). */
52
+ readonly minN?: number;
53
+ }
54
+ export declare const DEFAULT_DRIFT_TOLERANCE_FRACTION = 0.15;
55
+ export declare const DEFAULT_DRIFT_MIN_N = 20;
56
+ /**
57
+ * Compare predicted vs observed cache reads per (route, candidate) and emit a
58
+ * drift event for each pair whose normalized gap exceeds tolerance AND clears
59
+ * the min-sample gate. Pure and total; output sorted for deterministic
60
+ * rendering. An empty result means every prediction tracked ground truth (or
61
+ * nothing had enough data) — the healthy case.
62
+ */
63
+ export declare function reconcileCacheDrift(samples: readonly CachePredictionSample[], opts?: ReconcileOptions): CachePredictionDrift[];
64
+ //# sourceMappingURL=cache-reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-reconcile.d.ts","sourceRoot":"","sources":["../../src/savings/cache-reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC;kCAC8B;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,kFAAkF;IAClF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,uEAAuE;IACvE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;0EACsE;IACtE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B;0EACsE;IACtE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC;yEACqE;IACrE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,gCAAgC,OAAO,CAAC;AACrD,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,IAAI,GAAE,gBAAqB,GAC1B,oBAAoB,EAAE,CA+BxB"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /**
3
+ * Cache prediction reconciliation — cache-aware-routing spec §5.2 (the
4
+ * [Briefing §8] feedback loop, v1-deterministic). PURE: no store/clock/network.
5
+ *
6
+ * "Predict → route → observe → reconcile" (spec §1.2): the derived ledger + the
7
+ * simulator PREDICT cache reads; provider-reported usage is GROUND TRUTH. When
8
+ * the two diverge beyond tolerance, the estimate is systematically off — a
9
+ * provider rule changed, a fingerprint is unstable, an endpoint lost affinity —
10
+ * and a `cache_prediction_drift` health event fires so the discrepancy is
11
+ * surfaced rather than silently trusted.
12
+ *
13
+ * G-4 PATTERN (telemetry/health.ts): this is a pure aggregation that RETURNS
14
+ * event objects — it never persists. A min-sample gate protects against calling
15
+ * two noisy calls a "drift". WS-D renders the events (console badge); no DDL and
16
+ * no new table are involved (spec schema budget).
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.DEFAULT_DRIFT_MIN_N = exports.DEFAULT_DRIFT_TOLERANCE_FRACTION = void 0;
20
+ exports.reconcileCacheDrift = reconcileCacheDrift;
21
+ exports.DEFAULT_DRIFT_TOLERANCE_FRACTION = 0.15;
22
+ exports.DEFAULT_DRIFT_MIN_N = 20;
23
+ /**
24
+ * Compare predicted vs observed cache reads per (route, candidate) and emit a
25
+ * drift event for each pair whose normalized gap exceeds tolerance AND clears
26
+ * the min-sample gate. Pure and total; output sorted for deterministic
27
+ * rendering. An empty result means every prediction tracked ground truth (or
28
+ * nothing had enough data) — the healthy case.
29
+ */
30
+ function reconcileCacheDrift(samples, opts = {}) {
31
+ const tolerance = opts.toleranceFraction ?? exports.DEFAULT_DRIFT_TOLERANCE_FRACTION;
32
+ const minN = opts.minN ?? exports.DEFAULT_DRIFT_MIN_N;
33
+ const out = [];
34
+ for (const s of samples) {
35
+ if (s.sampleN < minN || s.windowInputTokens <= 0)
36
+ continue; // thin data → no judgment
37
+ const gap = Math.abs(s.predictedReadTokens - s.observedReadTokens);
38
+ const driftFraction = gap / s.windowInputTokens;
39
+ if (driftFraction <= tolerance)
40
+ continue;
41
+ const predictedH = s.predictedReadTokens / s.windowInputTokens;
42
+ const observedH = s.observedReadTokens / s.windowInputTokens;
43
+ out.push({
44
+ route: s.route,
45
+ provider: s.provider,
46
+ model: s.model,
47
+ predictedReadTokens: s.predictedReadTokens,
48
+ observedReadTokens: s.observedReadTokens,
49
+ driftFraction,
50
+ signedHitRateError: predictedH - observedH,
51
+ sampleN: s.sampleN,
52
+ });
53
+ }
54
+ return out.sort((a, b) => a.route !== b.route
55
+ ? a.route.localeCompare(b.route)
56
+ : a.provider !== b.provider
57
+ ? a.provider.localeCompare(b.provider)
58
+ : a.model.localeCompare(b.model));
59
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Cache-hit-rate rollup — cache-aware-routing spec §5.1, WS-B. PURE: a function
3
+ * over telemetry rows, no store/clock/network (an injected `now` bounds the
4
+ * window). Feeds the effective-rate blend (§4.2), the derived ledger (§5.2), and
5
+ * the console (WS-D).
6
+ *
7
+ * ── THE ODOMETER RULE (replay exclusion) ──────────────────────────────────
8
+ * Trailing-window measurements count PRODUCTION serving only: a bake-off replay
9
+ * pass runs real (billed) calls tagged `replay`, and those must NEVER inflate a
10
+ * route's measured hit rate any more than they inflate measured savings. This is
11
+ * the SAME 5-line filter the savings odometer uses — see
12
+ * `savings/odometer.ts` (`JSON.parse(r.tagsJson).replay !== undefined`). It is
13
+ * duplicated (not imported) deliberately: the two live in different modules with
14
+ * different row shapes, and a shared 5-line helper would couple them for no real
15
+ * gain. If the replay tag convention ever changes, change BOTH.
16
+ *
17
+ * ── UNPRICED ROWS ARE KEPT ────────────────────────────────────────────────
18
+ * Unlike the odometer (which drops `pricingMissing` rows so a $0 cannot inflate
19
+ * dollar savings), the hit-rate rollup is a TOKEN measurement, not a dollar one:
20
+ * an unpriced row still carries honest token counts, so it counts toward h/w.
21
+ * Pricing enters later, in the effective-rate blend, where a missing rate
22
+ * fail-closes on its own.
23
+ */
24
+ import type { TelemetryRow } from "../types/telemetry";
25
+ /** Trailing window for the rollup — 7 days by default (spec §5.1). */
26
+ export declare const DEFAULT_CACHE_WINDOW_DAYS = 7;
27
+ /** Observed cache activity for one (route, provider, model) over the window. */
28
+ export interface CacheStatsRollup {
29
+ readonly route: string;
30
+ readonly provider: string;
31
+ readonly model: string;
32
+ /** Production rows in the window (replay excluded). */
33
+ readonly sampleN: number;
34
+ /** Σ input tokens (the denominator of h and w). */
35
+ readonly tokensIn: number;
36
+ /** Σ cache-READ tokens. */
37
+ readonly tokensCached: number;
38
+ /** Σ cache-WRITE (creation) tokens. */
39
+ readonly tokensCacheWrite: number;
40
+ /** Observed hit rate `h = Σcached/Σin` (0 when `tokensIn` is 0). */
41
+ readonly h: number;
42
+ /** Observed write rate `w = Σwrite/Σin` (0 when `tokensIn` is 0). */
43
+ readonly w: number;
44
+ /** Most recent row ts in the window (ISO), or null when none. */
45
+ readonly lastSeenAt: string | null;
46
+ /** Distinct non-null prefix fingerprints seen — the cacheable prefixes this
47
+ * route×candidate exercised (WS-C fills them; empty in WS-A-only telemetry). */
48
+ readonly prefixFingerprints: readonly string[];
49
+ }
50
+ export interface CacheStatsOptions {
51
+ /** Reference "now" (epoch ms) — injected for deterministic windowing/tests. */
52
+ readonly now: number;
53
+ /** Window width in days (default 7). */
54
+ readonly windowDays?: number;
55
+ }
56
+ /**
57
+ * Roll telemetry rows up into per-(route, provider, model) cache stats over the
58
+ * trailing window. Rows outside `[now − windowDays, now]`, with an unparseable
59
+ * ts, or tagged `replay` are excluded. Output is sorted (route, provider, model)
60
+ * for deterministic downstream rendering and stable snapshots.
61
+ */
62
+ export declare function rollupCacheStats(rows: readonly TelemetryRow[], opts: CacheStatsOptions): CacheStatsRollup[];
63
+ //# sourceMappingURL=cache-stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-stats.d.ts","sourceRoot":"","sources":["../../src/savings/cache-stats.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,sEAAsE;AACtE,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2BAA2B;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,oEAAoE;IACpE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;oFACgF;IAChF,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,iBAAiB;IAChC,+EAA+E;IAC/E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAiBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,SAAS,YAAY,EAAE,EAC7B,IAAI,EAAE,iBAAiB,GACtB,gBAAgB,EAAE,CAwEpB"}