modelrig 0.1.0 → 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 (309) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +41 -11
  3. package/data/PROVENANCE.md +19 -0
  4. package/data/pricing-manual.json +22 -0
  5. package/data/pricing-map.json +46362 -0
  6. package/data/pricing-overlay.json +419 -0
  7. package/dist/adapters/anthropic.d.ts +50 -6
  8. package/dist/adapters/anthropic.d.ts.map +1 -1
  9. package/dist/adapters/anthropic.js +123 -29
  10. package/dist/adapters/build-adapters.d.ts +11 -0
  11. package/dist/adapters/build-adapters.d.ts.map +1 -0
  12. package/dist/adapters/build-adapters.js +45 -0
  13. package/dist/adapters/deepseek.d.ts +6 -0
  14. package/dist/adapters/deepseek.d.ts.map +1 -1
  15. package/dist/adapters/deepseek.js +54 -1
  16. package/dist/adapters/gemini.d.ts.map +1 -1
  17. package/dist/adapters/gemini.js +46 -6
  18. package/dist/adapters/grok.d.ts +9 -0
  19. package/dist/adapters/grok.d.ts.map +1 -1
  20. package/dist/adapters/grok.js +67 -3
  21. package/dist/adapters/openai-compat.d.ts +6 -0
  22. package/dist/adapters/openai-compat.d.ts.map +1 -1
  23. package/dist/adapters/openai-compat.js +58 -1
  24. package/dist/adapters/openai-stream.d.ts +58 -0
  25. package/dist/adapters/openai-stream.d.ts.map +1 -0
  26. package/dist/adapters/openai-stream.js +120 -0
  27. package/dist/adapters/openai.d.ts +6 -0
  28. package/dist/adapters/openai.d.ts.map +1 -1
  29. package/dist/adapters/openai.js +60 -1
  30. package/dist/adapters/sampling.d.ts +28 -0
  31. package/dist/adapters/sampling.d.ts.map +1 -0
  32. package/dist/adapters/sampling.js +34 -0
  33. package/dist/adapters/tool-mapping.d.ts +92 -0
  34. package/dist/adapters/tool-mapping.d.ts.map +1 -0
  35. package/dist/adapters/tool-mapping.js +143 -0
  36. package/dist/artifacts/artifact.d.ts +137 -0
  37. package/dist/artifacts/artifact.d.ts.map +1 -0
  38. package/dist/artifacts/artifact.js +377 -0
  39. package/dist/artifacts/content-uploader.d.ts +87 -0
  40. package/dist/artifacts/content-uploader.d.ts.map +1 -0
  41. package/dist/artifacts/content-uploader.js +124 -0
  42. package/dist/artifacts/index.d.ts +63 -0
  43. package/dist/artifacts/index.d.ts.map +1 -0
  44. package/dist/artifacts/index.js +80 -0
  45. package/dist/artifacts/run-context.d.ts +129 -0
  46. package/dist/artifacts/run-context.d.ts.map +1 -0
  47. package/dist/artifacts/run-context.js +208 -0
  48. package/dist/artifacts/scrub.d.ts +60 -0
  49. package/dist/artifacts/scrub.d.ts.map +1 -0
  50. package/dist/artifacts/scrub.js +139 -0
  51. package/dist/artifacts/step.d.ts +26 -0
  52. package/dist/artifacts/step.d.ts.map +1 -0
  53. package/dist/artifacts/step.js +37 -0
  54. package/dist/artifacts/taint.d.ts +63 -0
  55. package/dist/artifacts/taint.d.ts.map +1 -0
  56. package/dist/artifacts/taint.js +76 -0
  57. package/dist/bakeoff/cache-sim.d.ts +99 -0
  58. package/dist/bakeoff/cache-sim.d.ts.map +1 -0
  59. package/dist/bakeoff/cache-sim.js +126 -0
  60. package/dist/bakeoff/eval-cases.d.ts +96 -0
  61. package/dist/bakeoff/eval-cases.d.ts.map +1 -0
  62. package/dist/bakeoff/eval-cases.js +105 -0
  63. package/dist/bakeoff/report.d.ts +41 -0
  64. package/dist/bakeoff/report.d.ts.map +1 -0
  65. package/dist/bakeoff/report.js +142 -0
  66. package/dist/bakeoff/samples.d.ts +15 -0
  67. package/dist/bakeoff/samples.d.ts.map +1 -1
  68. package/dist/bakeoff/samples.js +20 -0
  69. package/dist/cli.d.ts +1 -3
  70. package/dist/cli.d.ts.map +1 -1
  71. package/dist/cli.js +134 -116
  72. package/dist/config.d.ts +100 -0
  73. package/dist/config.d.ts.map +1 -1
  74. package/dist/config.js +104 -0
  75. package/dist/deprecations.d.ts +32 -0
  76. package/dist/deprecations.d.ts.map +1 -0
  77. package/dist/deprecations.js +59 -0
  78. package/dist/gateway/http-protocol.d.ts +175 -0
  79. package/dist/gateway/http-protocol.d.ts.map +1 -0
  80. package/dist/gateway/http-protocol.js +105 -0
  81. package/dist/index.d.ts +105 -18
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +266 -138
  84. package/dist/init/finder.d.ts +15 -0
  85. package/dist/init/finder.d.ts.map +1 -1
  86. package/dist/init/finder.js +46 -0
  87. package/dist/init/init-cli.d.ts +10 -0
  88. package/dist/init/init-cli.d.ts.map +1 -0
  89. package/dist/init/init-cli.js +86 -0
  90. package/dist/init/observe-cli.d.ts +19 -0
  91. package/dist/init/observe-cli.d.ts.map +1 -0
  92. package/dist/init/observe-cli.js +73 -0
  93. package/dist/init/observe.d.ts +81 -0
  94. package/dist/init/observe.d.ts.map +1 -0
  95. package/dist/init/observe.js +245 -0
  96. package/dist/registry/build.d.ts +94 -1
  97. package/dist/registry/build.d.ts.map +1 -1
  98. package/dist/registry/build.js +125 -4
  99. package/dist/registry/cache-policy.d.ts +94 -0
  100. package/dist/registry/cache-policy.d.ts.map +1 -0
  101. package/dist/registry/cache-policy.js +238 -0
  102. package/dist/registry/call-notes.d.ts.map +1 -1
  103. package/dist/registry/call-notes.js +40 -2
  104. package/dist/registry/effective-rate.d.ts +151 -0
  105. package/dist/registry/effective-rate.d.ts.map +1 -0
  106. package/dist/registry/effective-rate.js +156 -0
  107. package/dist/registry/facts.d.ts.map +1 -1
  108. package/dist/registry/facts.js +16 -0
  109. package/dist/registry/parity.d.ts +26 -0
  110. package/dist/registry/parity.d.ts.map +1 -1
  111. package/dist/registry/parity.js +43 -2
  112. package/dist/registry/pricing-shape.d.ts +113 -0
  113. package/dist/registry/pricing-shape.d.ts.map +1 -0
  114. package/dist/registry/pricing-shape.js +123 -0
  115. package/dist/registry/pricing.d.ts +25 -1
  116. package/dist/registry/pricing.d.ts.map +1 -1
  117. package/dist/registry/pricing.js +64 -6
  118. package/dist/rigindex/bootstrap.d.ts +36 -0
  119. package/dist/rigindex/bootstrap.d.ts.map +1 -0
  120. package/dist/rigindex/bootstrap.js +97 -0
  121. package/dist/rigindex/fit.d.ts +24 -0
  122. package/dist/rigindex/fit.d.ts.map +1 -0
  123. package/dist/rigindex/fit.js +76 -0
  124. package/dist/rigindex/gates.d.ts +52 -0
  125. package/dist/rigindex/gates.d.ts.map +1 -0
  126. package/dist/rigindex/gates.js +109 -0
  127. package/dist/rigindex/graph.d.ts +31 -0
  128. package/dist/rigindex/graph.d.ts.map +1 -0
  129. package/dist/rigindex/graph.js +120 -0
  130. package/dist/rigindex/index.d.ts +23 -0
  131. package/dist/rigindex/index.d.ts.map +1 -0
  132. package/dist/rigindex/index.js +112 -0
  133. package/dist/rigindex/types.d.ts +76 -0
  134. package/dist/rigindex/types.d.ts.map +1 -0
  135. package/dist/rigindex/types.js +8 -0
  136. package/dist/routes/cache-lint.d.ts +41 -0
  137. package/dist/routes/cache-lint.d.ts.map +1 -0
  138. package/dist/routes/cache-lint.js +81 -0
  139. package/dist/routes/loader.d.ts +37 -0
  140. package/dist/routes/loader.d.ts.map +1 -1
  141. package/dist/routes/loader.js +138 -0
  142. package/dist/routes/resolved-bundle.d.ts +79 -0
  143. package/dist/routes/resolved-bundle.d.ts.map +1 -0
  144. package/dist/routes/resolved-bundle.js +148 -0
  145. package/dist/routes/sampling-config.d.ts +32 -0
  146. package/dist/routes/sampling-config.d.ts.map +1 -0
  147. package/dist/routes/sampling-config.js +91 -0
  148. package/dist/run/ajv.d.ts +22 -0
  149. package/dist/run/ajv.d.ts.map +1 -0
  150. package/dist/run/ajv.js +32 -0
  151. package/dist/run/cache-handle.d.ts +58 -0
  152. package/dist/run/cache-handle.d.ts.map +1 -0
  153. package/dist/run/cache-handle.js +54 -0
  154. package/dist/run/cache-stamp.d.ts +65 -0
  155. package/dist/run/cache-stamp.d.ts.map +1 -0
  156. package/dist/run/cache-stamp.js +0 -0
  157. package/dist/run/capture-write.d.ts +33 -0
  158. package/dist/run/capture-write.d.ts.map +1 -0
  159. package/dist/run/capture-write.js +55 -0
  160. package/dist/run/cost.d.ts.map +1 -1
  161. package/dist/run/cost.js +1 -1
  162. package/dist/run/dispatch.d.ts +99 -0
  163. package/dist/run/dispatch.d.ts.map +1 -0
  164. package/dist/run/dispatch.js +191 -0
  165. package/dist/run/raw.d.ts +88 -0
  166. package/dist/run/raw.d.ts.map +1 -0
  167. package/dist/run/raw.js +286 -0
  168. package/dist/run/record-attempt.d.ts +40 -0
  169. package/dist/run/record-attempt.d.ts.map +1 -0
  170. package/dist/run/record-attempt.js +99 -0
  171. package/dist/run/resolve.d.ts +75 -2
  172. package/dist/run/resolve.d.ts.map +1 -1
  173. package/dist/run/resolve.js +126 -4
  174. package/dist/run/run.d.ts +14 -0
  175. package/dist/run/run.d.ts.map +1 -1
  176. package/dist/run/run.js +0 -0
  177. package/dist/run/stream.d.ts +49 -0
  178. package/dist/run/stream.d.ts.map +1 -0
  179. package/dist/run/stream.js +87 -0
  180. package/dist/run/validate.d.ts.map +1 -1
  181. package/dist/run/validate.js +6 -7
  182. package/dist/savings/cache-ledger.d.ts +108 -0
  183. package/dist/savings/cache-ledger.d.ts.map +1 -0
  184. package/dist/savings/cache-ledger.js +174 -0
  185. package/dist/savings/cache-reconcile.d.ts +64 -0
  186. package/dist/savings/cache-reconcile.d.ts.map +1 -0
  187. package/dist/savings/cache-reconcile.js +59 -0
  188. package/dist/savings/cache-stats.d.ts +63 -0
  189. package/dist/savings/cache-stats.d.ts.map +1 -0
  190. package/dist/savings/cache-stats.js +108 -0
  191. package/dist/savings/emit.d.ts +13 -0
  192. package/dist/savings/emit.d.ts.map +1 -1
  193. package/dist/savings/emit.js +25 -0
  194. package/dist/savings/swap-execute.d.ts +14 -0
  195. package/dist/savings/swap-execute.d.ts.map +1 -1
  196. package/dist/savings/swap-execute.js +44 -1
  197. package/dist/savings/swaps-client.d.ts +14 -0
  198. package/dist/savings/swaps-client.d.ts.map +1 -1
  199. package/dist/savings/swaps-client.js +16 -2
  200. package/dist/settings/api-fetcher.d.ts +39 -0
  201. package/dist/settings/api-fetcher.d.ts.map +1 -0
  202. package/dist/settings/api-fetcher.js +92 -0
  203. package/dist/settings/index.d.ts +10 -0
  204. package/dist/settings/index.d.ts.map +1 -0
  205. package/dist/settings/index.js +15 -0
  206. package/dist/settings/task-settings.d.ts +91 -0
  207. package/dist/settings/task-settings.d.ts.map +1 -0
  208. package/dist/settings/task-settings.js +116 -0
  209. package/dist/status.d.ts +77 -0
  210. package/dist/status.d.ts.map +1 -0
  211. package/dist/status.js +113 -0
  212. package/dist/telemetry/artifact-store.d.ts +48 -0
  213. package/dist/telemetry/artifact-store.d.ts.map +1 -0
  214. package/dist/telemetry/artifact-store.js +189 -0
  215. package/dist/telemetry/cache-miss-streak.d.ts +79 -0
  216. package/dist/telemetry/cache-miss-streak.d.ts.map +1 -0
  217. package/dist/telemetry/cache-miss-streak.js +99 -0
  218. package/dist/telemetry/capture.d.ts +3 -0
  219. package/dist/telemetry/capture.d.ts.map +1 -1
  220. package/dist/telemetry/capture.js +15 -8
  221. package/dist/telemetry/exporter-setup.d.ts +28 -0
  222. package/dist/telemetry/exporter-setup.d.ts.map +1 -0
  223. package/dist/telemetry/exporter-setup.js +34 -0
  224. package/dist/telemetry/exporter.d.ts +75 -0
  225. package/dist/telemetry/exporter.d.ts.map +1 -1
  226. package/dist/telemetry/exporter.js +324 -47
  227. package/dist/telemetry/health.d.ts +76 -0
  228. package/dist/telemetry/health.d.ts.map +1 -0
  229. package/dist/telemetry/health.js +92 -0
  230. package/dist/telemetry/ingest-protocol.d.ts +152 -3
  231. package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
  232. package/dist/telemetry/ingest-protocol.js +204 -4
  233. package/dist/telemetry/load-error-report.d.ts +24 -0
  234. package/dist/telemetry/load-error-report.d.ts.map +1 -0
  235. package/dist/telemetry/load-error-report.js +50 -0
  236. package/dist/telemetry/otel-map.d.ts +121 -0
  237. package/dist/telemetry/otel-map.d.ts.map +1 -0
  238. package/dist/telemetry/otel-map.js +224 -0
  239. package/dist/telemetry/otel-normalize.d.ts +104 -0
  240. package/dist/telemetry/otel-normalize.d.ts.map +1 -0
  241. package/dist/telemetry/otel-normalize.js +530 -0
  242. package/dist/telemetry/otlp-emitter.d.ts +52 -0
  243. package/dist/telemetry/otlp-emitter.d.ts.map +1 -0
  244. package/dist/telemetry/otlp-emitter.js +144 -0
  245. package/dist/telemetry/otlp-proto.d.ts +29 -0
  246. package/dist/telemetry/otlp-proto.d.ts.map +1 -0
  247. package/dist/telemetry/otlp-proto.js +266 -0
  248. package/dist/telemetry/sinks.d.ts +37 -1
  249. package/dist/telemetry/sinks.d.ts.map +1 -1
  250. package/dist/telemetry/sinks.js +121 -30
  251. package/dist/telemetry/store.d.ts +28 -1
  252. package/dist/telemetry/store.d.ts.map +1 -1
  253. package/dist/telemetry/store.js +218 -3
  254. package/dist/tenancy/api-key-format.d.ts +15 -5
  255. package/dist/tenancy/api-key-format.d.ts.map +1 -1
  256. package/dist/tenancy/api-key-format.js +24 -5
  257. package/dist/types/config-teaching.d.ts +62 -0
  258. package/dist/types/config-teaching.d.ts.map +1 -0
  259. package/dist/types/config-teaching.js +183 -0
  260. package/dist/types/provider.d.ts +122 -1
  261. package/dist/types/provider.d.ts.map +1 -1
  262. package/dist/types/provider.js +21 -1
  263. package/dist/types/route.d.ts +79 -1
  264. package/dist/types/route.d.ts.map +1 -1
  265. package/dist/types/telemetry.d.ts +117 -0
  266. package/dist/types/telemetry.d.ts.map +1 -1
  267. package/dist/validate-cli.d.ts +12 -0
  268. package/dist/validate-cli.d.ts.map +1 -0
  269. package/dist/validate-cli.js +57 -0
  270. package/dist/verify/capture.d.ts +66 -0
  271. package/dist/verify/capture.d.ts.map +1 -0
  272. package/dist/verify/capture.js +180 -0
  273. package/dist/verify/cli-run.d.ts +23 -0
  274. package/dist/verify/cli-run.d.ts.map +1 -0
  275. package/dist/verify/cli-run.js +57 -0
  276. package/dist/verify/diff.d.ts +48 -0
  277. package/dist/verify/diff.d.ts.map +1 -0
  278. package/dist/verify/diff.js +157 -0
  279. package/dist/verify/index.d.ts +17 -0
  280. package/dist/verify/index.d.ts.map +1 -0
  281. package/dist/verify/index.js +24 -0
  282. package/dist/verify/report.d.ts +14 -0
  283. package/dist/verify/report.d.ts.map +1 -0
  284. package/dist/verify/report.js +88 -0
  285. package/dist/verify/types.d.ts +101 -0
  286. package/dist/verify/types.d.ts.map +1 -0
  287. package/dist/verify/types.js +17 -0
  288. package/dist/verify/verify.d.ts +29 -0
  289. package/dist/verify/verify.d.ts.map +1 -0
  290. package/dist/verify/verify.js +148 -0
  291. package/dist/watch/evaluate.d.ts +162 -3
  292. package/dist/watch/evaluate.d.ts.map +1 -1
  293. package/dist/watch/evaluate.js +61 -0
  294. package/dist/watch/monitor.d.ts +116 -0
  295. package/dist/watch/monitor.d.ts.map +1 -0
  296. package/dist/watch/monitor.js +199 -0
  297. package/dist/watch/proposals.d.ts +20 -4
  298. package/dist/watch/proposals.d.ts.map +1 -1
  299. package/dist/watch/proposals.js +31 -3
  300. package/dist/watch/run.d.ts +33 -0
  301. package/dist/watch/run.d.ts.map +1 -1
  302. package/dist/watch/run.js +39 -0
  303. package/package.json +7 -1
  304. package/registry/LICENSE +20 -0
  305. package/registry/leaderboard.json +3639 -0
  306. package/registry/registry.json +7263 -0
  307. package/dist/telemetry/supabase-exporter.d.ts +0 -64
  308. package/dist/telemetry/supabase-exporter.d.ts.map +0 -1
  309. package/dist/telemetry/supabase-exporter.js +0 -211
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Prompt-stability lint — cache-aware-routing WS-C step 4 (spec §5.3,
3
+ * [Briefing §10]). A prefix cache only pays off when the CACHED PREFIX is
4
+ * stable across calls. A route template that interpolates a volatile value
5
+ * (a timestamp, a run id, a random nonce) high in the prompt shifts the prefix
6
+ * on every call, so the provider caches something that never recurs — the route
7
+ * pays the write premium forever and never reads a hit ("paying full price and
8
+ * don't know it", the §5.6 smell, caught statically here instead of after the money).
9
+ *
10
+ * v1 is a pure, conservative NAME heuristic over the declared `{{variable}}`
11
+ * references (the run-loop's stable prefix IS the route template — spec §5.3).
12
+ * It flags variables whose NAME reads volatile AND that appear before the
13
+ * template's stable tail. It does NOT inspect rendered values (it can't — the
14
+ * lint runs at load, before any input) and it never fails the load: a false
15
+ * positive must not block a legitimate route, so this warns. The prompt compiler
16
+ * + Prefix Stability Score (real per-token volatility telemetry) is the deferred
17
+ * successor ([Briefing Phase 5]); this is the cheap static precursor.
18
+ */
19
+ export interface CacheLintWarning {
20
+ /** The offending variable name. */
21
+ readonly variable: string;
22
+ /** Character offset of the reference in the raw template. */
23
+ readonly index: number;
24
+ /** Human-readable, teach-not-scold message. */
25
+ readonly message: string;
26
+ }
27
+ /**
28
+ * Lint a route's raw system template for cache-hostile volatile interpolations.
29
+ * Pure and total. Returns one warning per volatile-named reference that sits
30
+ * before the stable tail; `[]` for a clean template.
31
+ *
32
+ * "Before the stable tail" (v1 approximation): a volatile reference in the first
33
+ * `headFraction` of the template shifts the cacheable prefix; one at the very
34
+ * end (after the bulk of the stable instructions) shifts only the tail and is
35
+ * harmless for prefix caching. We warn only on head references to keep the
36
+ * signal high — a `{{now}}` in a trailing "as of {{now}}" line is fine.
37
+ */
38
+ export declare function lintCacheTemplate(template: string, opts?: {
39
+ readonly headFraction?: number;
40
+ }): CacheLintWarning[];
41
+ //# sourceMappingURL=cache-lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-lint.d.ts","sourceRoot":"","sources":["../../src/routes/cache-lint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAmCH,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5C,gBAAgB,EAAE,CAmBpB"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * Prompt-stability lint — cache-aware-routing WS-C step 4 (spec §5.3,
4
+ * [Briefing §10]). A prefix cache only pays off when the CACHED PREFIX is
5
+ * stable across calls. A route template that interpolates a volatile value
6
+ * (a timestamp, a run id, a random nonce) high in the prompt shifts the prefix
7
+ * on every call, so the provider caches something that never recurs — the route
8
+ * pays the write premium forever and never reads a hit ("paying full price and
9
+ * don't know it", the §5.6 smell, caught statically here instead of after the money).
10
+ *
11
+ * v1 is a pure, conservative NAME heuristic over the declared `{{variable}}`
12
+ * references (the run-loop's stable prefix IS the route template — spec §5.3).
13
+ * It flags variables whose NAME reads volatile AND that appear before the
14
+ * template's stable tail. It does NOT inspect rendered values (it can't — the
15
+ * lint runs at load, before any input) and it never fails the load: a false
16
+ * positive must not block a legitimate route, so this warns. The prompt compiler
17
+ * + Prefix Stability Score (real per-token volatility telemetry) is the deferred
18
+ * successor ([Briefing Phase 5]); this is the cheap static precursor.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.lintCacheTemplate = lintCacheTemplate;
22
+ /** Variable names that read as per-call-volatile. Deliberately broad on the
23
+ * volatile side (a warning is cheap; a silently un-cached route is not) but
24
+ * anchored to whole \b tokens so `updated_at_note` matches yet `runtime` does
25
+ * not falsely trip on "run". */
26
+ const VOLATILE_NAME = new RegExp([
27
+ "\\btime(stamp)?\\b",
28
+ "\\bnow\\b",
29
+ "\\bdate(time)?\\b",
30
+ "run[_-]?id",
31
+ "request[_-]?id",
32
+ "trace[_-]?id",
33
+ "session[_-]?id",
34
+ "correlation[_-]?id",
35
+ "\\buuid\\b",
36
+ "\\bguid\\b",
37
+ "\\bnonce\\b",
38
+ "\\brandom\\b",
39
+ "\\brand\\b",
40
+ "\\bepoch\\b",
41
+ "\\bcurrent[_-]",
42
+ "generated[_-]?at",
43
+ "created[_-]?at",
44
+ "updated[_-]?at",
45
+ ].join("|"), "i");
46
+ /** The `{{var}}` scanner from template.ts, duplicated as a global-match here so
47
+ * the lint can read each reference's POSITION (scanTemplateVariables dedupes to
48
+ * names only). Kept in sync with template.ts's VAR_TAG. */
49
+ const VAR_TAG = /\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
50
+ /**
51
+ * Lint a route's raw system template for cache-hostile volatile interpolations.
52
+ * Pure and total. Returns one warning per volatile-named reference that sits
53
+ * before the stable tail; `[]` for a clean template.
54
+ *
55
+ * "Before the stable tail" (v1 approximation): a volatile reference in the first
56
+ * `headFraction` of the template shifts the cacheable prefix; one at the very
57
+ * end (after the bulk of the stable instructions) shifts only the tail and is
58
+ * harmless for prefix caching. We warn only on head references to keep the
59
+ * signal high — a `{{now}}` in a trailing "as of {{now}}" line is fine.
60
+ */
61
+ function lintCacheTemplate(template, opts = {}) {
62
+ const headFraction = opts.headFraction ?? 0.75;
63
+ const headCutoff = Math.floor(template.length * headFraction);
64
+ const warnings = [];
65
+ for (const m of template.matchAll(VAR_TAG)) {
66
+ const name = m[1];
67
+ const index = m.index;
68
+ if (index >= headCutoff)
69
+ continue; // in the stable tail — harmless
70
+ if (!VOLATILE_NAME.test(name))
71
+ continue;
72
+ warnings.push({
73
+ variable: name,
74
+ index,
75
+ message: `route template interpolates \`{{${name}}}\` before the stable prompt tail — a per-call ` +
76
+ `value here shifts the cacheable prefix and defeats prompt caching (the route would pay ` +
77
+ `full price every call). Move volatile values to the end of the prompt, or drop them.`,
78
+ });
79
+ }
80
+ return warnings;
81
+ }
@@ -22,5 +22,42 @@ export interface LoadedRoutes {
22
22
  get(route: string): RouteBundle;
23
23
  list(): readonly RouteBundle[];
24
24
  }
25
+ /**
26
+ * Merge two loaded route sets into one store — a UNION, collision is a loud
27
+ * error. Used to fold a deployment's bundled INTERNAL infra routes (e.g. the
28
+ * server's run-judge@v1 / analyst-summarize@v1) into the operator's configured
29
+ * routes without replacing them (index.ts createRig, extraRoutesDir). The
30
+ * reserved `@v<n>` infra namespace never collides with customer/demo routes;
31
+ * if it ever did, failing at boot is correct.
32
+ */
33
+ /**
34
+ * Load a routes directory and OPTIONALLY union a second (deployment-bundled
35
+ * infra) directory into it — the one call createRig makes so the extra-routes
36
+ * merge does not grow index.ts. `extraDir` absent/empty ⇒ exactly loadRoutes.
37
+ */
38
+ export declare function loadRoutesWithExtra(routesDir: string, extraDir?: string): LoadedRoutes;
39
+ export declare function mergeLoadedRoutes(primary: LoadedRoutes, extra: LoadedRoutes): LoadedRoutes;
40
+ /** One route file's structural-validation outcome (CE-6, spec §1 / walkthrough
41
+ * §8.7a). `route` is the parsed handle, or null when the bundle failed before a
42
+ * name could be read. */
43
+ export interface RouteValidation {
44
+ readonly file: string;
45
+ readonly route: string | null;
46
+ readonly ok: boolean;
47
+ readonly problems: readonly string[];
48
+ }
49
+ /**
50
+ * Structurally validate every route bundle in a directory WITHOUT requiring any
51
+ * provider key (CE-6 `modelrig validate`). Unlike {@link loadRoutes}, one bad
52
+ * bundle does NOT abort the rest — each file is loaded independently and its
53
+ * outcome collected, so a newbie sees every problem in one pass. Duplicate route
54
+ * handles across files are reported per the later file. This deliberately does
55
+ * NOT run the serveable-candidate gate (serveability.ts) — that needs keys and
56
+ * stays fail-closed for SERVING; validation only checks authoring.
57
+ *
58
+ * A missing directory is still a hard error (nothing to validate) — it throws
59
+ * the same teaching RouteConfigError as loadRoutes.
60
+ */
61
+ export declare function validateRoutesDir(routesDir: string): RouteValidation[];
25
62
  export declare function loadRoutes(routesDir: string): LoadedRoutes;
26
63
  //# sourceMappingURL=loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAKV,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AAIxB;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;CAOxF;AAiCD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,IAAI,IAAI,SAAS,WAAW,EAAE,CAAC;CAChC;AAkXD,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA2C1D"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/routes/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAKV,WAAW,EAGZ,MAAM,gBAAgB,CAAC;AAMxB;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;gBAEzB,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO;CAOxF;AAiCD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,IAAI,IAAI,SAAS,WAAW,EAAE,CAAC;CAChC;AAqZD;;;;;;;GAOG;AACH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAItF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,YAAY,CAyB1F;AAED;;yBAEyB;AACzB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CA6CtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CA2C1D"}
@@ -6,6 +6,9 @@
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.RouteConfigError = void 0;
9
+ exports.loadRoutesWithExtra = loadRoutesWithExtra;
10
+ exports.mergeLoadedRoutes = mergeLoadedRoutes;
11
+ exports.validateRoutesDir = validateRoutesDir;
9
12
  exports.loadRoutes = loadRoutes;
10
13
  const node_fs_1 = require("node:fs");
11
14
  const node_path_1 = require("node:path");
@@ -13,6 +16,8 @@ const yaml_1 = require("yaml");
13
16
  const failures_1 = require("../types/failures");
14
17
  const fingerprint_1 = require("../registry/fingerprint");
15
18
  const template_1 = require("./template");
19
+ const cache_lint_1 = require("./cache-lint");
20
+ const sampling_config_1 = require("./sampling-config");
16
21
  /**
17
22
  * Structured config error thrown for any invalid bundle (never a raw Error).
18
23
  * Load-time problems are deliberately NOT RigFailures — the failure taxonomy
@@ -136,6 +141,7 @@ function parsePolicy(raw, problems) {
136
141
  if (typeof json !== "string" || !JSON_MODES.has(json)) {
137
142
  problems.push(`policy.json "${String(json)}" is not one of [native, json_mode]`);
138
143
  }
144
+ const sampling = (0, sampling_config_1.parseSampling)(raw.sampling, "policy.sampling", problems);
139
145
  if (problems.length > 0)
140
146
  return fallback;
141
147
  return Object.freeze({
@@ -143,6 +149,7 @@ function parsePolicy(raw, problems) {
143
149
  timeoutMs: timeoutMs,
144
150
  tier: tier,
145
151
  json: json,
152
+ ...(sampling !== undefined ? { sampling } : {}),
146
153
  });
147
154
  }
148
155
  /** "provider/model" string or {provider, model} mapping → CandidateSpec. */
@@ -328,6 +335,21 @@ function loadBundleFile(filePath) {
328
335
  if (typeof capture !== "boolean") {
329
336
  problems.push("capture must be a boolean");
330
337
  }
338
+ // Request-path caching opt-in (cache-aware-routing WS-C). Exactly one value
339
+ // is supported in v1 — `cache: auto`. Anything else is a config error (a typo
340
+ // must not silently ship an un-cached route). Gemini is NOT excluded here: a
341
+ // mixed-provider route may opt in, and the run-loop's policy gate skips
342
+ // gemini's request path (cache-stamp.ts) while its implicit hit rate still
343
+ // arrives passively — the exclusion is code-enforced, not author-policed.
344
+ let cache = false;
345
+ if (doc.cache !== undefined && doc.cache !== null) {
346
+ if (doc.cache === "auto") {
347
+ cache = true;
348
+ }
349
+ else {
350
+ problems.push(`cache "${String(doc.cache)}" is not supported — use "cache: auto" or omit it`);
351
+ }
352
+ }
331
353
  let groundingQuery;
332
354
  if (doc.grounding !== undefined) {
333
355
  if (!isRecord(doc.grounding) || typeof doc.grounding.query !== "string" || doc.grounding.query === "") {
@@ -377,6 +399,22 @@ function loadBundleFile(filePath) {
377
399
  if (problems.length > 0) {
378
400
  throw new RouteConfigError("invalid route bundle", { file: filePath, problems });
379
401
  }
402
+ // Prompt-stability lint (WS-C step 4, spec §5.3): a non-fatal warning — a
403
+ // volatile interpolation before the stable tail defeats prompt caching. Only
404
+ // meaningful once the route opted into `cache: auto`, so scoped to it to keep
405
+ // the signal high (same console-warn posture as manifest dimension warnings).
406
+ if (cache) {
407
+ for (const w of (0, cache_lint_1.lintCacheTemplate)(systemTemplate)) {
408
+ console.warn(`modelrig: route "${String(route)}" (${filePath}): ${w.message}`);
409
+ }
410
+ }
411
+ // CE-6 sampling advisory: a sub-1.0 temperature on a Gemini-3 candidate loads
412
+ // and is sent as declared, but Google recommends 1.0 for the family — warn so
413
+ // the choice is deliberate, never silent (spec §3/§6).
414
+ const geminiTempWarning = (0, sampling_config_1.gemini3LowTemperatureWarning)(route, policy, candidates);
415
+ if (geminiTempWarning !== null) {
416
+ console.warn(`modelrig: ${geminiTempWarning}`);
417
+ }
380
418
  return Object.freeze({
381
419
  route: route,
382
420
  version: version,
@@ -390,12 +428,112 @@ function loadBundleFile(filePath) {
390
428
  ...(repair !== undefined ? { repair } : {}),
391
429
  variants: Object.freeze(variants),
392
430
  capture: capture === true,
431
+ cache,
393
432
  ...(groundingQuery !== undefined ? { groundingQuery } : {}),
394
433
  // Network-effect instrumentation (spec WS6): computed once at load,
395
434
  // stamped on every telemetry row for this route.
396
435
  fingerprintCell: (0, fingerprint_1.fingerprintSchema)(outputSchema)?.cellKey ?? null,
397
436
  });
398
437
  }
438
+ /**
439
+ * Merge two loaded route sets into one store — a UNION, collision is a loud
440
+ * error. Used to fold a deployment's bundled INTERNAL infra routes (e.g. the
441
+ * server's run-judge@v1 / analyst-summarize@v1) into the operator's configured
442
+ * routes without replacing them (index.ts createRig, extraRoutesDir). The
443
+ * reserved `@v<n>` infra namespace never collides with customer/demo routes;
444
+ * if it ever did, failing at boot is correct.
445
+ */
446
+ /**
447
+ * Load a routes directory and OPTIONALLY union a second (deployment-bundled
448
+ * infra) directory into it — the one call createRig makes so the extra-routes
449
+ * merge does not grow index.ts. `extraDir` absent/empty ⇒ exactly loadRoutes.
450
+ */
451
+ function loadRoutesWithExtra(routesDir, extraDir) {
452
+ const base = loadRoutes(routesDir);
453
+ if (extraDir === undefined || extraDir === "")
454
+ return base;
455
+ return mergeLoadedRoutes(base, loadRoutes(extraDir));
456
+ }
457
+ function mergeLoadedRoutes(primary, extra) {
458
+ const byName = new Map();
459
+ for (const b of primary.list())
460
+ byName.set(b.route, b);
461
+ for (const b of extra.list()) {
462
+ if (byName.has(b.route)) {
463
+ throw new RouteConfigError(`duplicate route "${b.route}" — an internal infra route collides with a configured route`);
464
+ }
465
+ byName.set(b.route, b);
466
+ }
467
+ return {
468
+ get(route) {
469
+ const bundle = byName.get(route);
470
+ if (!bundle) {
471
+ throw new RouteConfigError(`unknown route "${route}" — known routes: [${[...byName.keys()].join(", ")}]`);
472
+ }
473
+ return bundle;
474
+ },
475
+ list() {
476
+ return Object.freeze([...byName.values()]);
477
+ },
478
+ };
479
+ }
480
+ /**
481
+ * Structurally validate every route bundle in a directory WITHOUT requiring any
482
+ * provider key (CE-6 `modelrig validate`). Unlike {@link loadRoutes}, one bad
483
+ * bundle does NOT abort the rest — each file is loaded independently and its
484
+ * outcome collected, so a newbie sees every problem in one pass. Duplicate route
485
+ * handles across files are reported per the later file. This deliberately does
486
+ * NOT run the serveable-candidate gate (serveability.ts) — that needs keys and
487
+ * stays fail-closed for SERVING; validation only checks authoring.
488
+ *
489
+ * A missing directory is still a hard error (nothing to validate) — it throws
490
+ * the same teaching RouteConfigError as loadRoutes.
491
+ */
492
+ function validateRoutesDir(routesDir) {
493
+ if (!(0, node_fs_1.existsSync)(routesDir)) {
494
+ throw new RouteConfigError(`routes directory not found: ${routesDir}\n\n` +
495
+ "There are no route bundles to validate here. Create your first with\n" +
496
+ " modelrig init . draft routes from the provider calls in this repo\n" +
497
+ "or point elsewhere with MODELRIG_ROUTES_DIR. Docs: https://modelrig.dev/quickstart.html");
498
+ }
499
+ const files = (0, node_fs_1.readdirSync)(routesDir)
500
+ .filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"))
501
+ .sort()
502
+ .map((f) => (0, node_path_1.join)(routesDir, f));
503
+ const results = [];
504
+ const seen = new Map();
505
+ for (const file of files) {
506
+ try {
507
+ const bundle = loadBundleFile(file);
508
+ const prior = seen.get(bundle.route);
509
+ if (prior !== undefined) {
510
+ results.push({
511
+ file,
512
+ route: bundle.route,
513
+ ok: false,
514
+ problems: [`duplicate route "${bundle.route}" — already declared in ${prior}`],
515
+ });
516
+ continue;
517
+ }
518
+ seen.set(bundle.route, file);
519
+ results.push({ file, route: bundle.route, ok: true, problems: [] });
520
+ }
521
+ catch (err) {
522
+ if (err instanceof RouteConfigError) {
523
+ results.push({
524
+ file,
525
+ route: null,
526
+ ok: false,
527
+ problems: err.problems.length > 0 ? err.problems : [err.message],
528
+ });
529
+ }
530
+ else {
531
+ results.push({ file, route: null, ok: false, problems: [err.message] });
532
+ }
533
+ }
534
+ }
535
+ return results;
536
+ }
399
537
  function loadRoutes(routesDir) {
400
538
  if (!(0, node_fs_1.existsSync)(routesDir)) {
401
539
  // First-run moment (Phase 5 WS4): this is the most likely error a new
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The RESOLVED route bundle — http-gateway spec §13 (Phase D).
3
+ *
4
+ * A `RouteBundle` in memory already has its file references FOLLOWED and
5
+ * INLINED: `loader.ts` reads the schema file into `outputSchema` (a parsed JSON
6
+ * object) and the prompt file into `systemTemplate` (a string), and a MISSING
7
+ * file fails there with a teaching `RouteConfigError` — at deploy, where the
8
+ * developer is, never at request where the customer is (§13.1 rule 6). So the
9
+ * "resolved bundle" the exporter mirrors is a pure, serialisable PROJECTION of
10
+ * an already-loaded bundle; this module is the ONE definition of that shape and
11
+ * of the round-trip both sides use.
12
+ *
13
+ * exporter (SDK) resolveRouteBundle(bundle) → ResolvedRouteBundle + sha
14
+ * → mirrored onto public.routes.bundle / bundle_sha
15
+ * gateway (server) bundleFromResolved(mirrored) → RouteBundle
16
+ * → rig.runBundle(bundle, opts) → the SAME verified pipeline
17
+ *
18
+ * `bundle_sha` is the content hash of the CANONICAL serialisation (keys sorted
19
+ * recursively, array order preserved), so the same bundle always hashes the
20
+ * same and the console can flag a mirror that no longer matches git (§13.1
21
+ * rule 5). The hash is computed once, at sync time, from the resolved bundle.
22
+ *
23
+ * `fingerprintCell` is NOT carried on the wire: it is derived from
24
+ * `outputSchema` and recomputed on rebuild, so it can never drift from the
25
+ * schema it fingerprints.
26
+ */
27
+ import type { LoadedRoutes } from "./loader";
28
+ import type { CandidateSpec, Preference, RepairPolicy, Requirement, RouteBundle, RoutePolicy, RouteVariant } from "../types/route";
29
+ /**
30
+ * The canonical, JSON-serialisable form of a resolved route bundle. Every field
31
+ * here defines how the route BEHAVES — the gateway needs all of them to drive
32
+ * the verified pipeline without the customer's filesystem. `fingerprintCell` is
33
+ * deliberately absent (derived from `outputSchema`, recomputed on rebuild).
34
+ */
35
+ export interface ResolvedRouteBundle {
36
+ readonly route: string;
37
+ readonly version: number;
38
+ /** Resolved, parsed JSON Schema (null = unstructured route). Inlined at sync. */
39
+ readonly outputSchema: object | null;
40
+ readonly candidates: readonly CandidateSpec[];
41
+ readonly require: readonly Requirement[];
42
+ readonly prefer: readonly Preference[];
43
+ /** Raw template text — the prompt FILE, inlined at sync. */
44
+ readonly systemTemplate: string;
45
+ readonly variables: readonly string[];
46
+ readonly policy: RoutePolicy;
47
+ readonly repair?: RepairPolicy;
48
+ readonly variants: readonly RouteVariant[];
49
+ readonly capture: boolean;
50
+ readonly groundingQuery?: string;
51
+ }
52
+ /** Project an already-loaded (resolved) bundle to its serialisable form. Pure —
53
+ * no filesystem; the loader already followed every file reference. */
54
+ export declare function resolveRouteBundle(bundle: RouteBundle): ResolvedRouteBundle;
55
+ /** The canonical serialisation whose hash becomes `bundle_sha`. */
56
+ export declare function canonicalBundleJson(bundle: ResolvedRouteBundle): string;
57
+ /** Content hash of the canonical bundle — `sha256:<hex>`. Self-describing so a
58
+ * future algorithm change is visible in the stored value rather than silent. */
59
+ export declare function hashResolvedBundle(bundle: ResolvedRouteBundle): string;
60
+ /**
61
+ * Rebuild a runnable `RouteBundle` from a mirrored resolved bundle. Recomputes
62
+ * `fingerprintCell` from `outputSchema` (never trusted from the wire) and
63
+ * freezes to match loader output. Throws `RouteConfigError` — the loader's own
64
+ * teaching class — if the mirrored payload is structurally unusable, so a
65
+ * corrupt mirror row surfaces as a teaching error, not a downstream crash.
66
+ */
67
+ export declare function bundleFromResolved(raw: unknown): RouteBundle;
68
+ /**
69
+ * A `LoadedRoutes` holding exactly ONE bundle — the seam that lets the verified
70
+ * pipeline run over a mirrored bundle without a local routes directory.
71
+ *
72
+ * `run()`/`runStream()` resolve a route only through `deps.routes.get(name)`, so
73
+ * swapping in this store (and nothing else) runs the WHOLE existing pipeline —
74
+ * validate, repair, envelope, telemetry, ZDR (G-3), routing controls (G-2) —
75
+ * over the provided bundle. Asking for any other name is a teaching error, so a
76
+ * mismatched slug can never silently resolve to the wrong route.
77
+ */
78
+ export declare function singleRouteStore(bundle: RouteBundle): LoadedRoutes;
79
+ //# sourceMappingURL=resolved-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolved-bundle.d.ts","sourceRoot":"","sources":["../../src/routes/resolved-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;sEACsE;AACtE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,CAgB3E;AAiBD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEvE;AAED;gFACgF;AAChF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAsC5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAclE"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ /**
3
+ * The RESOLVED route bundle — http-gateway spec §13 (Phase D).
4
+ *
5
+ * A `RouteBundle` in memory already has its file references FOLLOWED and
6
+ * INLINED: `loader.ts` reads the schema file into `outputSchema` (a parsed JSON
7
+ * object) and the prompt file into `systemTemplate` (a string), and a MISSING
8
+ * file fails there with a teaching `RouteConfigError` — at deploy, where the
9
+ * developer is, never at request where the customer is (§13.1 rule 6). So the
10
+ * "resolved bundle" the exporter mirrors is a pure, serialisable PROJECTION of
11
+ * an already-loaded bundle; this module is the ONE definition of that shape and
12
+ * of the round-trip both sides use.
13
+ *
14
+ * exporter (SDK) resolveRouteBundle(bundle) → ResolvedRouteBundle + sha
15
+ * → mirrored onto public.routes.bundle / bundle_sha
16
+ * gateway (server) bundleFromResolved(mirrored) → RouteBundle
17
+ * → rig.runBundle(bundle, opts) → the SAME verified pipeline
18
+ *
19
+ * `bundle_sha` is the content hash of the CANONICAL serialisation (keys sorted
20
+ * recursively, array order preserved), so the same bundle always hashes the
21
+ * same and the console can flag a mirror that no longer matches git (§13.1
22
+ * rule 5). The hash is computed once, at sync time, from the resolved bundle.
23
+ *
24
+ * `fingerprintCell` is NOT carried on the wire: it is derived from
25
+ * `outputSchema` and recomputed on rebuild, so it can never drift from the
26
+ * schema it fingerprints.
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.resolveRouteBundle = resolveRouteBundle;
30
+ exports.canonicalBundleJson = canonicalBundleJson;
31
+ exports.hashResolvedBundle = hashResolvedBundle;
32
+ exports.bundleFromResolved = bundleFromResolved;
33
+ exports.singleRouteStore = singleRouteStore;
34
+ const node_crypto_1 = require("node:crypto");
35
+ const fingerprint_1 = require("../registry/fingerprint");
36
+ const loader_1 = require("./loader");
37
+ /** Project an already-loaded (resolved) bundle to its serialisable form. Pure —
38
+ * no filesystem; the loader already followed every file reference. */
39
+ function resolveRouteBundle(bundle) {
40
+ return {
41
+ route: bundle.route,
42
+ version: bundle.version,
43
+ outputSchema: bundle.outputSchema,
44
+ candidates: bundle.candidates,
45
+ require: bundle.require,
46
+ prefer: bundle.prefer,
47
+ systemTemplate: bundle.systemTemplate,
48
+ variables: bundle.variables,
49
+ policy: bundle.policy,
50
+ ...(bundle.repair !== undefined ? { repair: bundle.repair } : {}),
51
+ variants: bundle.variants,
52
+ capture: bundle.capture,
53
+ ...(bundle.groundingQuery !== undefined ? { groundingQuery: bundle.groundingQuery } : {}),
54
+ };
55
+ }
56
+ /** Deterministic JSON: object keys sorted recursively, array order preserved.
57
+ * The whole point is that the SAME bundle always produces the SAME bytes, so
58
+ * the content hash is stable across processes and machines. */
59
+ function canonicalize(value) {
60
+ if (Array.isArray(value))
61
+ return value.map(canonicalize);
62
+ if (value !== null && typeof value === "object") {
63
+ const out = {};
64
+ for (const key of Object.keys(value).sort()) {
65
+ out[key] = canonicalize(value[key]);
66
+ }
67
+ return out;
68
+ }
69
+ return value;
70
+ }
71
+ /** The canonical serialisation whose hash becomes `bundle_sha`. */
72
+ function canonicalBundleJson(bundle) {
73
+ return JSON.stringify(canonicalize(bundle));
74
+ }
75
+ /** Content hash of the canonical bundle — `sha256:<hex>`. Self-describing so a
76
+ * future algorithm change is visible in the stored value rather than silent. */
77
+ function hashResolvedBundle(bundle) {
78
+ return `sha256:${(0, node_crypto_1.createHash)("sha256").update(canonicalBundleJson(bundle)).digest("hex")}`;
79
+ }
80
+ /**
81
+ * Rebuild a runnable `RouteBundle` from a mirrored resolved bundle. Recomputes
82
+ * `fingerprintCell` from `outputSchema` (never trusted from the wire) and
83
+ * freezes to match loader output. Throws `RouteConfigError` — the loader's own
84
+ * teaching class — if the mirrored payload is structurally unusable, so a
85
+ * corrupt mirror row surfaces as a teaching error, not a downstream crash.
86
+ */
87
+ function bundleFromResolved(raw) {
88
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
89
+ throw new loader_1.RouteConfigError("mirrored route bundle is not an object");
90
+ }
91
+ const b = raw;
92
+ if (typeof b.route !== "string" || b.route === "") {
93
+ throw new loader_1.RouteConfigError("mirrored route bundle is missing `route`");
94
+ }
95
+ if (typeof b.version !== "number" || !Number.isInteger(b.version)) {
96
+ throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" is missing a valid \`version\``);
97
+ }
98
+ if (!Array.isArray(b.candidates) || b.candidates.length === 0) {
99
+ throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" has no candidates`);
100
+ }
101
+ if (typeof b.systemTemplate !== "string") {
102
+ throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" is missing \`systemTemplate\``);
103
+ }
104
+ if (b.policy === undefined || b.policy === null) {
105
+ throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" is missing \`policy\``);
106
+ }
107
+ const outputSchema = b.outputSchema ?? null;
108
+ return Object.freeze({
109
+ route: b.route,
110
+ version: b.version,
111
+ outputSchema: outputSchema === null ? null : Object.freeze(outputSchema),
112
+ candidates: Object.freeze([...b.candidates]),
113
+ require: Object.freeze([...(b.require ?? [])]),
114
+ prefer: Object.freeze([...(b.prefer ?? [])]),
115
+ systemTemplate: b.systemTemplate,
116
+ variables: Object.freeze([...(b.variables ?? [])]),
117
+ policy: b.policy,
118
+ ...(b.repair !== undefined ? { repair: b.repair } : {}),
119
+ variants: Object.freeze([...(b.variants ?? [])]),
120
+ capture: b.capture === true,
121
+ ...(b.groundingQuery !== undefined ? { groundingQuery: b.groundingQuery } : {}),
122
+ // Recomputed, never trusted from the wire — cannot drift from the schema.
123
+ fingerprintCell: (0, fingerprint_1.fingerprintSchema)(outputSchema)?.cellKey ?? null,
124
+ });
125
+ }
126
+ /**
127
+ * A `LoadedRoutes` holding exactly ONE bundle — the seam that lets the verified
128
+ * pipeline run over a mirrored bundle without a local routes directory.
129
+ *
130
+ * `run()`/`runStream()` resolve a route only through `deps.routes.get(name)`, so
131
+ * swapping in this store (and nothing else) runs the WHOLE existing pipeline —
132
+ * validate, repair, envelope, telemetry, ZDR (G-3), routing controls (G-2) —
133
+ * over the provided bundle. Asking for any other name is a teaching error, so a
134
+ * mismatched slug can never silently resolve to the wrong route.
135
+ */
136
+ function singleRouteStore(bundle) {
137
+ return {
138
+ get(route) {
139
+ if (route !== bundle.route) {
140
+ throw new loader_1.RouteConfigError(`route "${route}" is not the mirrored bundle "${bundle.route}"`);
141
+ }
142
+ return bundle;
143
+ },
144
+ list() {
145
+ return Object.freeze([bundle]);
146
+ },
147
+ };
148
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Route-bundle sampling config (CE-6, spec §2/§3) — extracted from loader.ts to
3
+ * keep it under the 700-LOC cap. Pure parsing + the Gemini-3 advisory; the
4
+ * loader calls both and owns the fail-loud aggregation.
5
+ */
6
+ import type { SamplingParams } from "../types/provider";
7
+ import type { CandidateSpec, RoutePolicy } from "../types/route";
8
+ /**
9
+ * Parse + validate `policy.sampling`. YAML is snake_case (`temperature` /
10
+ * `top_p` / `max_output_tokens`); the parsed block is camelCase
11
+ * (`SamplingParams`). Ranges are the permissive provider envelope — a value the
12
+ * provider then rejects surfaces through the run loop's failure ladder, never a
13
+ * silent clamp here (spec §3/§6). Every violation is a config error at load
14
+ * (fail-loud). Returns undefined when the block is absent OR empty ⇒ every
15
+ * adapter behaves exactly as pre-CE-6.
16
+ */
17
+ export declare function parseSampling(raw: unknown, field: string, problems: string[]): SamplingParams | undefined;
18
+ /** A Gemini-3.x model id (gemini-3.0-*, gemini-3.1-*, gemini-3-*). Google
19
+ * recommends temperature=1.0 for the whole Gemini-3 family (CE-6 §3). */
20
+ export declare function isGemini3Model(model: string): boolean;
21
+ /**
22
+ * CE-6 §3/§6: warn (non-fatal) when a route declares a sub-1.0 temperature on a
23
+ * Gemini-3 candidate. Google STRONGLY recommends temperature=1.0 for Gemini 3
24
+ * and warns sub-1.0 values can loop / degrade on complex reasoning tasks
25
+ * (classification/extraction are typically fine — which is why the source
26
+ * pipeline ran gemini-3.1-pro at 0.1 for classification without looping). The
27
+ * route still LOADS and the request is still sent AS DECLARED — the honest
28
+ * middle: the customer asked, we told them, the request goes as asked. Returns
29
+ * the warning line, or null when no advisory applies.
30
+ */
31
+ export declare function gemini3LowTemperatureWarning(route: string, policy: RoutePolicy, candidates: readonly CandidateSpec[]): string | null;
32
+ //# sourceMappingURL=sampling-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampling-config.d.ts","sourceRoot":"","sources":["../../src/routes/sampling-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMjE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,cAAc,GAAG,SAAS,CAmC5B;AAED;yEACyE;AACzE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,SAAS,aAAa,EAAE,GACnC,MAAM,GAAG,IAAI,CAaf"}