pi-smart-router 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/.pi/extensions/smart-router/command-formatters.ts +167 -0
  2. package/.pi/extensions/smart-router/commands.ts +242 -0
  3. package/.pi/extensions/smart-router/dataset-export.ts +142 -0
  4. package/.pi/extensions/smart-router/delegate-stream.ts +105 -0
  5. package/.pi/extensions/smart-router/delegation-runtime.ts +355 -0
  6. package/.pi/extensions/smart-router/extension-setup.ts +115 -0
  7. package/.pi/extensions/smart-router/fleet-bootstrap.ts +244 -0
  8. package/.pi/extensions/smart-router/index.ts +115 -0
  9. package/.pi/extensions/smart-router/package.json +3 -0
  10. package/.pi/extensions/smart-router/pi-model-scope.ts +55 -0
  11. package/.pi/extensions/smart-router/pricing-lifecycle.ts +43 -0
  12. package/.pi/extensions/smart-router/route-and-delegate.ts +562 -0
  13. package/.pi/extensions/smart-router/routing-context.ts +171 -0
  14. package/.pi/extensions/smart-router/routing-outcomes.ts +44 -0
  15. package/.pi/extensions/smart-router/session-lifecycle.ts +140 -0
  16. package/.pi/extensions/smart-router/stream-delegation.ts +75 -0
  17. package/.pi/extensions/smart-router/types.ts +90 -0
  18. package/.pi/extensions/smart-router/utils.ts +58 -0
  19. package/README.md +593 -0
  20. package/bin/pi-smart-router.mjs +79 -0
  21. package/config/.gitkeep +0 -0
  22. package/config/hydra-projection-weights.json.example +1169 -0
  23. package/config/models.yaml.example +58 -0
  24. package/config/p-success-weights.json.example +19 -0
  25. package/config/routing-calibration.json.example +1605 -0
  26. package/config/routing-centroids.json.example +1570 -0
  27. package/config/routing-clusters.yaml.example +41 -0
  28. package/data/contrib/example.json +25 -0
  29. package/dist/api/explain/router-explain.d.ts +47 -0
  30. package/dist/api/explain/router-explain.d.ts.map +1 -0
  31. package/dist/api/explain/router-explain.js +101 -0
  32. package/dist/api/explain/router-explain.js.map +1 -0
  33. package/dist/api/middleware/pi-router-middleware.d.ts +86 -0
  34. package/dist/api/middleware/pi-router-middleware.d.ts.map +1 -0
  35. package/dist/api/middleware/pi-router-middleware.js +83 -0
  36. package/dist/api/middleware/pi-router-middleware.js.map +1 -0
  37. package/dist/cli/smart-router-cli.d.ts +85 -0
  38. package/dist/cli/smart-router-cli.d.ts.map +1 -0
  39. package/dist/cli/smart-router-cli.js +293 -0
  40. package/dist/cli/smart-router-cli.js.map +1 -0
  41. package/dist/config/defaults.d.ts +7 -0
  42. package/dist/config/defaults.d.ts.map +1 -0
  43. package/dist/config/defaults.js +33 -0
  44. package/dist/config/defaults.js.map +1 -0
  45. package/dist/config/models-loader.d.ts +22 -0
  46. package/dist/config/models-loader.d.ts.map +1 -0
  47. package/dist/config/models-loader.js +51 -0
  48. package/dist/config/models-loader.js.map +1 -0
  49. package/dist/config/pi-model-mapper.d.ts +40 -0
  50. package/dist/config/pi-model-mapper.d.ts.map +1 -0
  51. package/dist/config/pi-model-mapper.js +216 -0
  52. package/dist/config/pi-model-mapper.js.map +1 -0
  53. package/dist/config/routing-clusters-loader.d.ts +35 -0
  54. package/dist/config/routing-clusters-loader.d.ts.map +1 -0
  55. package/dist/config/routing-clusters-loader.js +100 -0
  56. package/dist/config/routing-clusters-loader.js.map +1 -0
  57. package/dist/domain/delegation/delegation-context.d.ts +23 -0
  58. package/dist/domain/delegation/delegation-context.d.ts.map +1 -0
  59. package/dist/domain/delegation/delegation-context.js +73 -0
  60. package/dist/domain/delegation/delegation-context.js.map +1 -0
  61. package/dist/domain/delegation/execution-ledger.d.ts +19 -0
  62. package/dist/domain/delegation/execution-ledger.d.ts.map +1 -0
  63. package/dist/domain/delegation/execution-ledger.js +23 -0
  64. package/dist/domain/delegation/execution-ledger.js.map +1 -0
  65. package/dist/domain/delegation/output-headroom.d.ts +39 -0
  66. package/dist/domain/delegation/output-headroom.d.ts.map +1 -0
  67. package/dist/domain/delegation/output-headroom.js +78 -0
  68. package/dist/domain/delegation/output-headroom.js.map +1 -0
  69. package/dist/domain/matching/cluster-matcher.d.ts +69 -0
  70. package/dist/domain/matching/cluster-matcher.d.ts.map +1 -0
  71. package/dist/domain/matching/cluster-matcher.js +294 -0
  72. package/dist/domain/matching/cluster-matcher.js.map +1 -0
  73. package/dist/domain/matching/embedding-provider.d.ts +21 -0
  74. package/dist/domain/matching/embedding-provider.d.ts.map +1 -0
  75. package/dist/domain/matching/embedding-provider.js +42 -0
  76. package/dist/domain/matching/embedding-provider.js.map +1 -0
  77. package/dist/domain/matching/hydra-input.d.ts +18 -0
  78. package/dist/domain/matching/hydra-input.d.ts.map +1 -0
  79. package/dist/domain/matching/hydra-input.js +40 -0
  80. package/dist/domain/matching/hydra-input.js.map +1 -0
  81. package/dist/domain/matching/hydra-matcher.d.ts +103 -0
  82. package/dist/domain/matching/hydra-matcher.d.ts.map +1 -0
  83. package/dist/domain/matching/hydra-matcher.js +275 -0
  84. package/dist/domain/matching/hydra-matcher.js.map +1 -0
  85. package/dist/domain/pinning/cache-economics.d.ts +53 -0
  86. package/dist/domain/pinning/cache-economics.d.ts.map +1 -0
  87. package/dist/domain/pinning/cache-economics.js +72 -0
  88. package/dist/domain/pinning/cache-economics.js.map +1 -0
  89. package/dist/domain/pinning/loop-escalation.d.ts +41 -0
  90. package/dist/domain/pinning/loop-escalation.d.ts.map +1 -0
  91. package/dist/domain/pinning/loop-escalation.js +137 -0
  92. package/dist/domain/pinning/loop-escalation.js.map +1 -0
  93. package/dist/domain/pinning/session-pinner.d.ts +81 -0
  94. package/dist/domain/pinning/session-pinner.d.ts.map +1 -0
  95. package/dist/domain/pinning/session-pinner.js +237 -0
  96. package/dist/domain/pinning/session-pinner.js.map +1 -0
  97. package/dist/domain/pinning/sub-route-policy.d.ts +41 -0
  98. package/dist/domain/pinning/sub-route-policy.d.ts.map +1 -0
  99. package/dist/domain/pinning/sub-route-policy.js +72 -0
  100. package/dist/domain/pinning/sub-route-policy.js.map +1 -0
  101. package/dist/domain/pipeline/router-pipeline.d.ts +180 -0
  102. package/dist/domain/pipeline/router-pipeline.d.ts.map +1 -0
  103. package/dist/domain/pipeline/router-pipeline.js +807 -0
  104. package/dist/domain/pipeline/router-pipeline.js.map +1 -0
  105. package/dist/domain/pipeline/safe-default.d.ts +25 -0
  106. package/dist/domain/pipeline/safe-default.d.ts.map +1 -0
  107. package/dist/domain/pipeline/safe-default.js +41 -0
  108. package/dist/domain/pipeline/safe-default.js.map +1 -0
  109. package/dist/domain/refactor-guardrails.d.ts +48 -0
  110. package/dist/domain/refactor-guardrails.d.ts.map +1 -0
  111. package/dist/domain/refactor-guardrails.js +129 -0
  112. package/dist/domain/refactor-guardrails.js.map +1 -0
  113. package/dist/domain/routing/context-fit.d.ts +53 -0
  114. package/dist/domain/routing/context-fit.d.ts.map +1 -0
  115. package/dist/domain/routing/context-fit.js +142 -0
  116. package/dist/domain/routing/context-fit.js.map +1 -0
  117. package/dist/domain/routing/expected-cost.d.ts +63 -0
  118. package/dist/domain/routing/expected-cost.d.ts.map +1 -0
  119. package/dist/domain/routing/expected-cost.js +177 -0
  120. package/dist/domain/routing/expected-cost.js.map +1 -0
  121. package/dist/domain/routing/p-success-classifier.d.ts +130 -0
  122. package/dist/domain/routing/p-success-classifier.d.ts.map +1 -0
  123. package/dist/domain/routing/p-success-classifier.js +350 -0
  124. package/dist/domain/routing/p-success-classifier.js.map +1 -0
  125. package/dist/domain/routing/tier-features.d.ts +70 -0
  126. package/dist/domain/routing/tier-features.d.ts.map +1 -0
  127. package/dist/domain/routing/tier-features.js +174 -0
  128. package/dist/domain/routing/tier-features.js.map +1 -0
  129. package/dist/domain/routing/tool-history-guard.d.ts +32 -0
  130. package/dist/domain/routing/tool-history-guard.d.ts.map +1 -0
  131. package/dist/domain/routing/tool-history-guard.js +110 -0
  132. package/dist/domain/routing/tool-history-guard.js.map +1 -0
  133. package/dist/domain/scoring/multi-objective.d.ts +48 -0
  134. package/dist/domain/scoring/multi-objective.d.ts.map +1 -0
  135. package/dist/domain/scoring/multi-objective.js +116 -0
  136. package/dist/domain/scoring/multi-objective.js.map +1 -0
  137. package/dist/domain/triage/triage-engine.d.ts +43 -0
  138. package/dist/domain/triage/triage-engine.d.ts.map +1 -0
  139. package/dist/domain/triage/triage-engine.js +317 -0
  140. package/dist/domain/triage/triage-engine.js.map +1 -0
  141. package/dist/domain/triage/turn-envelope.d.ts +17 -0
  142. package/dist/domain/triage/turn-envelope.d.ts.map +1 -0
  143. package/dist/domain/triage/turn-envelope.js +81 -0
  144. package/dist/domain/triage/turn-envelope.js.map +1 -0
  145. package/dist/domain/types/entities.d.ts +303 -0
  146. package/dist/domain/types/entities.d.ts.map +1 -0
  147. package/dist/domain/types/entities.js +6 -0
  148. package/dist/domain/types/entities.js.map +1 -0
  149. package/dist/domain/types/index.d.ts +4 -0
  150. package/dist/domain/types/index.d.ts.map +1 -0
  151. package/dist/domain/types/index.js +2 -0
  152. package/dist/domain/types/index.js.map +1 -0
  153. package/dist/domain/types/schemas.d.ts +346 -0
  154. package/dist/domain/types/schemas.d.ts.map +1 -0
  155. package/dist/domain/types/schemas.js +241 -0
  156. package/dist/domain/types/schemas.js.map +1 -0
  157. package/dist/domain/types/store-port.d.ts +44 -0
  158. package/dist/domain/types/store-port.d.ts.map +1 -0
  159. package/dist/domain/types/store-port.js +6 -0
  160. package/dist/domain/types/store-port.js.map +1 -0
  161. package/dist/index.d.ts +39 -0
  162. package/dist/index.d.ts.map +1 -0
  163. package/dist/index.js +36 -0
  164. package/dist/index.js.map +1 -0
  165. package/dist/infra/gemini-provider.d.ts +28 -0
  166. package/dist/infra/gemini-provider.d.ts.map +1 -0
  167. package/dist/infra/gemini-provider.js +112 -0
  168. package/dist/infra/gemini-provider.js.map +1 -0
  169. package/dist/infra/telemetry.d.ts +51 -0
  170. package/dist/infra/telemetry.d.ts.map +1 -0
  171. package/dist/infra/telemetry.js +100 -0
  172. package/dist/infra/telemetry.js.map +1 -0
  173. package/dist/infrastructure/delegation/provider-error.d.ts +44 -0
  174. package/dist/infrastructure/delegation/provider-error.d.ts.map +1 -0
  175. package/dist/infrastructure/delegation/provider-error.js +179 -0
  176. package/dist/infrastructure/delegation/provider-error.js.map +1 -0
  177. package/dist/infrastructure/gateway/circuit-breaker.d.ts +68 -0
  178. package/dist/infrastructure/gateway/circuit-breaker.d.ts.map +1 -0
  179. package/dist/infrastructure/gateway/circuit-breaker.js +150 -0
  180. package/dist/infrastructure/gateway/circuit-breaker.js.map +1 -0
  181. package/dist/infrastructure/gateway/gateway-dispatch.d.ts +138 -0
  182. package/dist/infrastructure/gateway/gateway-dispatch.d.ts.map +1 -0
  183. package/dist/infrastructure/gateway/gateway-dispatch.js +308 -0
  184. package/dist/infrastructure/gateway/gateway-dispatch.js.map +1 -0
  185. package/dist/infrastructure/hardware/hardware-probe.d.ts +32 -0
  186. package/dist/infrastructure/hardware/hardware-probe.d.ts.map +1 -0
  187. package/dist/infrastructure/hardware/hardware-probe.js +199 -0
  188. package/dist/infrastructure/hardware/hardware-probe.js.map +1 -0
  189. package/dist/infrastructure/local/local-zero-tier.d.ts +47 -0
  190. package/dist/infrastructure/local/local-zero-tier.d.ts.map +1 -0
  191. package/dist/infrastructure/local/local-zero-tier.js +92 -0
  192. package/dist/infrastructure/local/local-zero-tier.js.map +1 -0
  193. package/dist/infrastructure/persistence/memory-store.d.ts +31 -0
  194. package/dist/infrastructure/persistence/memory-store.d.ts.map +1 -0
  195. package/dist/infrastructure/persistence/memory-store.js +87 -0
  196. package/dist/infrastructure/persistence/memory-store.js.map +1 -0
  197. package/dist/infrastructure/persistence/sqlite-store.d.ts +81 -0
  198. package/dist/infrastructure/persistence/sqlite-store.d.ts.map +1 -0
  199. package/dist/infrastructure/persistence/sqlite-store.js +658 -0
  200. package/dist/infrastructure/persistence/sqlite-store.js.map +1 -0
  201. package/dist/infrastructure/pricing/litellm-fetch.d.ts +46 -0
  202. package/dist/infrastructure/pricing/litellm-fetch.d.ts.map +1 -0
  203. package/dist/infrastructure/pricing/litellm-fetch.js +145 -0
  204. package/dist/infrastructure/pricing/litellm-fetch.js.map +1 -0
  205. package/dist/infrastructure/pricing/price-broker.d.ts +56 -0
  206. package/dist/infrastructure/pricing/price-broker.d.ts.map +1 -0
  207. package/dist/infrastructure/pricing/price-broker.js +133 -0
  208. package/dist/infrastructure/pricing/price-broker.js.map +1 -0
  209. package/dist/infrastructure/pricing/pricing-monitor.d.ts +27 -0
  210. package/dist/infrastructure/pricing/pricing-monitor.d.ts.map +1 -0
  211. package/dist/infrastructure/pricing/pricing-monitor.js +46 -0
  212. package/dist/infrastructure/pricing/pricing-monitor.js.map +1 -0
  213. package/dist/infrastructure/telemetry/dataset-limits.d.ts +13 -0
  214. package/dist/infrastructure/telemetry/dataset-limits.d.ts.map +1 -0
  215. package/dist/infrastructure/telemetry/dataset-limits.js +28 -0
  216. package/dist/infrastructure/telemetry/dataset-limits.js.map +1 -0
  217. package/dist/infrastructure/telemetry/dataset-recorder.d.ts +48 -0
  218. package/dist/infrastructure/telemetry/dataset-recorder.d.ts.map +1 -0
  219. package/dist/infrastructure/telemetry/dataset-recorder.js +154 -0
  220. package/dist/infrastructure/telemetry/dataset-recorder.js.map +1 -0
  221. package/dist/infrastructure/telemetry/outcome-limits.d.ts +12 -0
  222. package/dist/infrastructure/telemetry/outcome-limits.d.ts.map +1 -0
  223. package/dist/infrastructure/telemetry/outcome-limits.js +28 -0
  224. package/dist/infrastructure/telemetry/outcome-limits.js.map +1 -0
  225. package/dist/infrastructure/telemetry/outcome-recorder.d.ts +29 -0
  226. package/dist/infrastructure/telemetry/outcome-recorder.d.ts.map +1 -0
  227. package/dist/infrastructure/telemetry/outcome-recorder.js +49 -0
  228. package/dist/infrastructure/telemetry/outcome-recorder.js.map +1 -0
  229. package/dist/infrastructure/telemetry/routing-telemetry.d.ts +115 -0
  230. package/dist/infrastructure/telemetry/routing-telemetry.d.ts.map +1 -0
  231. package/dist/infrastructure/telemetry/routing-telemetry.js +529 -0
  232. package/dist/infrastructure/telemetry/routing-telemetry.js.map +1 -0
  233. package/dist/infrastructure/telemetry/telemetry-limits.d.ts +16 -0
  234. package/dist/infrastructure/telemetry/telemetry-limits.d.ts.map +1 -0
  235. package/dist/infrastructure/telemetry/telemetry-limits.js +35 -0
  236. package/dist/infrastructure/telemetry/telemetry-limits.js.map +1 -0
  237. package/package.json +110 -0
  238. package/skills/router-backlog-orchestrator/SKILL.md +183 -0
  239. package/skills/router-backlog-orchestrator/references/github-router-issue-template.md +78 -0
  240. package/skills/router-backlog-orchestrator/references/packet-from-issue.md +99 -0
  241. package/skills/router-backlog-orchestrator/references/prioritization-rubric.md +65 -0
  242. package/skills/router-backlog-orchestrator/scripts/collect-backlog.sh +44 -0
  243. package/specs/001-build-smart-router/contracts/telemetry-contrib.schema.json +151 -0
  244. package/src/api/explain/.gitkeep +0 -0
  245. package/src/api/explain/router-explain.ts +146 -0
  246. package/src/api/middleware/.gitkeep +0 -0
  247. package/src/api/middleware/pi-router-middleware.ts +169 -0
  248. package/src/cli/smart-router-cli.ts +436 -0
  249. package/src/config/.gitkeep +0 -0
  250. package/src/config/defaults.ts +35 -0
  251. package/src/config/models-loader.ts +68 -0
  252. package/src/config/pi-model-mapper.ts +285 -0
  253. package/src/config/routing-clusters-loader.ts +148 -0
  254. package/src/domain/delegation/delegation-context.ts +111 -0
  255. package/src/domain/delegation/execution-ledger.ts +34 -0
  256. package/src/domain/delegation/output-headroom.ts +131 -0
  257. package/src/domain/matching/.gitkeep +0 -0
  258. package/src/domain/matching/cluster-matcher.ts +474 -0
  259. package/src/domain/matching/embedding-provider.ts +79 -0
  260. package/src/domain/matching/hydra-input.ts +53 -0
  261. package/src/domain/matching/hydra-matcher.ts +454 -0
  262. package/src/domain/pinning/.gitkeep +0 -0
  263. package/src/domain/pinning/cache-economics.ts +128 -0
  264. package/src/domain/pinning/loop-escalation.ts +181 -0
  265. package/src/domain/pinning/session-pinner.ts +388 -0
  266. package/src/domain/pinning/sub-route-policy.ts +119 -0
  267. package/src/domain/pipeline/.gitkeep +0 -0
  268. package/src/domain/pipeline/router-pipeline.ts +1139 -0
  269. package/src/domain/pipeline/safe-default.ts +70 -0
  270. package/src/domain/refactor-guardrails.ts +202 -0
  271. package/src/domain/routing/context-fit.ts +221 -0
  272. package/src/domain/routing/expected-cost.ts +320 -0
  273. package/src/domain/routing/p-success-classifier.ts +511 -0
  274. package/src/domain/routing/tier-features.ts +290 -0
  275. package/src/domain/routing/tool-history-guard.ts +159 -0
  276. package/src/domain/scoring/.gitkeep +0 -0
  277. package/src/domain/scoring/multi-objective.ts +175 -0
  278. package/src/domain/triage/.gitkeep +0 -0
  279. package/src/domain/triage/triage-engine.ts +373 -0
  280. package/src/domain/triage/turn-envelope.ts +104 -0
  281. package/src/domain/types/.gitkeep +0 -0
  282. package/src/domain/types/entities.ts +384 -0
  283. package/src/domain/types/index.ts +41 -0
  284. package/src/domain/types/schemas.ts +289 -0
  285. package/src/domain/types/store-port.ts +59 -0
  286. package/src/index.ts +103 -0
  287. package/src/infra/gemini-provider.ts +142 -0
  288. package/src/infra/telemetry.ts +169 -0
  289. package/src/infrastructure/delegation/provider-error.ts +251 -0
  290. package/src/infrastructure/gateway/.gitkeep +0 -0
  291. package/src/infrastructure/gateway/circuit-breaker.ts +196 -0
  292. package/src/infrastructure/gateway/gateway-dispatch.ts +444 -0
  293. package/src/infrastructure/hardware/.gitkeep +0 -0
  294. package/src/infrastructure/hardware/hardware-probe.ts +276 -0
  295. package/src/infrastructure/local/.gitkeep +0 -0
  296. package/src/infrastructure/local/local-zero-tier.ts +151 -0
  297. package/src/infrastructure/persistence/.gitkeep +0 -0
  298. package/src/infrastructure/persistence/memory-store.ts +122 -0
  299. package/src/infrastructure/persistence/sqlite-store.ts +900 -0
  300. package/src/infrastructure/pricing/.gitkeep +0 -0
  301. package/src/infrastructure/pricing/litellm-fetch.ts +215 -0
  302. package/src/infrastructure/pricing/price-broker.ts +183 -0
  303. package/src/infrastructure/pricing/pricing-monitor.ts +65 -0
  304. package/src/infrastructure/telemetry/.gitkeep +0 -0
  305. package/src/infrastructure/telemetry/dataset-limits.ts +39 -0
  306. package/src/infrastructure/telemetry/dataset-recorder.ts +215 -0
  307. package/src/infrastructure/telemetry/outcome-limits.ts +42 -0
  308. package/src/infrastructure/telemetry/outcome-recorder.ts +118 -0
  309. package/src/infrastructure/telemetry/routing-telemetry.ts +824 -0
  310. package/src/infrastructure/telemetry/telemetry-limits.ts +50 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-headroom.js","sourceRoot":"","sources":["../../../src/domain/delegation/output-headroom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Semantic cluster matcher — SP-101, GitHub #56.
3
+ *
4
+ * Embeds request prompt text via shared TextEmbedder, scores cosine similarity
5
+ * against precomputed cluster centroids, and returns best match with confidence
6
+ * from per-cluster min_similarity and min_margin thresholds.
7
+ *
8
+ * Centroids load from `config/routing-centroids.json` at startup when present;
9
+ * otherwise they are computed inline from reference prompts (SP-114).
10
+ */
11
+ import { type TextEmbedder } from './embedding-provider.js';
12
+ import type { ClusterMatchTableEntry, LoadedRoutingCluster, RoutingCluster, RoutingClusterCatalog, RoutingRequest, Tier } from '../types/index.js';
13
+ export declare const DEFAULT_ROUTING_CENTROIDS_PATH = "config/routing-centroids.json";
14
+ export interface RoutingCentroidRecord {
15
+ readonly cluster_id: string;
16
+ readonly tier_bias: Tier;
17
+ readonly centroid: readonly number[];
18
+ readonly reference_count: number;
19
+ }
20
+ export interface RoutingCentroidsArtifact {
21
+ readonly version: number;
22
+ readonly embedding_dim: number;
23
+ readonly clusters: readonly RoutingCentroidRecord[];
24
+ }
25
+ export declare class RoutingCentroidsError extends Error {
26
+ readonly name = "RoutingCentroidsError";
27
+ constructor(message: string, options?: ErrorOptions);
28
+ }
29
+ export declare function computeCentroid(embeddings: readonly Float32Array[]): Float32Array;
30
+ export declare function loadRoutingCentroidsArtifact(filePath?: string): RoutingCentroidsArtifact;
31
+ export declare function validateCentroidClusterIds(catalogClusters: readonly RoutingCluster[], artifact: RoutingCentroidsArtifact): void;
32
+ export declare function applyPrecomputedCentroids(catalogClusters: readonly RoutingCluster[], artifact: RoutingCentroidsArtifact): readonly LoadedRoutingCluster[];
33
+ export declare function buildRoutingCentroidsArtifact(catalogClusters: readonly RoutingCluster[], embedder: TextEmbedder): Promise<RoutingCentroidsArtifact>;
34
+ export declare function serializeRoutingCentroidsArtifact(artifact: RoutingCentroidsArtifact): string;
35
+ export interface CreateClusterMatcherOptions {
36
+ readonly clustersFilePath?: string;
37
+ readonly centroidsFilePath?: string;
38
+ readonly embedder: TextEmbedder;
39
+ }
40
+ /**
41
+ * Load routing cluster catalog with precomputed centroids when the artifact exists.
42
+ * Falls back to inline centroid computation from reference prompts when missing.
43
+ */
44
+ export declare function loadClusterMatcherCatalog(options: CreateClusterMatcherOptions): Promise<RoutingClusterCatalog>;
45
+ export declare function createClusterMatcher(options: CreateClusterMatcherOptions): Promise<ClusterMatcher>;
46
+ export type ClusterMatchConfidence = 'high' | 'low' | 'none';
47
+ export interface ClusterMatchResult {
48
+ readonly clusterId: string;
49
+ readonly tierBias: Tier;
50
+ readonly similarity: number;
51
+ /** sim(best) - sim(second); 0 when only one cluster exists. */
52
+ readonly margin: number;
53
+ readonly confidence: ClusterMatchConfidence;
54
+ readonly elapsedMs: number;
55
+ }
56
+ export declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
57
+ export interface ClusterMatcherConfig {
58
+ readonly catalog: RoutingClusterCatalog;
59
+ readonly embedder: TextEmbedder;
60
+ }
61
+ export declare class ClusterMatcher {
62
+ private readonly clusters;
63
+ private readonly embedder;
64
+ constructor(config: ClusterMatcherConfig);
65
+ match(request: RoutingRequest): Promise<ClusterMatchResult>;
66
+ /** Score all cluster centroids for explain / telemetry tables (SP-113). */
67
+ matchTable(request: RoutingRequest): Promise<readonly ClusterMatchTableEntry[]>;
68
+ }
69
+ //# sourceMappingURL=cluster-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster-matcher.d.ts","sourceRoot":"","sources":["../../../src/domain/matching/cluster-matcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Semantic cluster matcher — SP-101, GitHub #56.
3
+ *
4
+ * Embeds request prompt text via shared TextEmbedder, scores cosine similarity
5
+ * against precomputed cluster centroids, and returns best match with confidence
6
+ * from per-cluster min_similarity and min_margin thresholds.
7
+ *
8
+ * Centroids load from `config/routing-centroids.json` at startup when present;
9
+ * otherwise they are computed inline from reference prompts (SP-114).
10
+ */
11
+ import { readFileSync } from 'node:fs';
12
+ import { resolve } from 'node:path';
13
+ import { loadRoutingClusters, parseRoutingClustersYaml, } from '../../config/routing-clusters-loader.js';
14
+ import { EMBEDDING_DIM } from './embedding-provider.js';
15
+ // ─── Precomputed centroid artifact (SP-114) ──────────────────────────────────
16
+ export const DEFAULT_ROUTING_CENTROIDS_PATH = 'config/routing-centroids.json';
17
+ export class RoutingCentroidsError extends Error {
18
+ name = 'RoutingCentroidsError';
19
+ constructor(message, options) {
20
+ super(message, options);
21
+ }
22
+ }
23
+ export function computeCentroid(embeddings) {
24
+ if (embeddings.length === 0) {
25
+ throw new RoutingCentroidsError('Cannot compute centroid from zero embeddings');
26
+ }
27
+ const dim = embeddings[0].length;
28
+ const centroid = new Float32Array(dim);
29
+ for (const embedding of embeddings) {
30
+ if (embedding.length !== dim) {
31
+ throw new RoutingCentroidsError(`Embedding shape mismatch: expected ${dim}, got ${embedding.length}`);
32
+ }
33
+ for (let i = 0; i < dim; i++) {
34
+ centroid[i] = (centroid[i] ?? 0) + (embedding[i] ?? 0);
35
+ }
36
+ }
37
+ for (let i = 0; i < dim; i++) {
38
+ centroid[i] = (centroid[i] ?? 0) / embeddings.length;
39
+ }
40
+ return centroid;
41
+ }
42
+ function parseRoutingCentroidsArtifact(parsed) {
43
+ if (typeof parsed !== 'object' || parsed === null) {
44
+ throw new RoutingCentroidsError('Invalid routing centroids artifact: expected object');
45
+ }
46
+ const record = parsed;
47
+ const version = record.version;
48
+ const embeddingDim = record.embedding_dim;
49
+ const clusters = record.clusters;
50
+ if (version !== 1) {
51
+ throw new RoutingCentroidsError(`Unsupported routing centroids version: ${String(version)}`);
52
+ }
53
+ if (embeddingDim !== EMBEDDING_DIM) {
54
+ throw new RoutingCentroidsError(`Invalid embedding_dim: expected ${EMBEDDING_DIM}, got ${String(embeddingDim)}`);
55
+ }
56
+ if (!Array.isArray(clusters) || clusters.length === 0) {
57
+ throw new RoutingCentroidsError('Invalid routing centroids artifact: clusters required');
58
+ }
59
+ const parsedClusters = [];
60
+ for (const entry of clusters) {
61
+ if (typeof entry !== 'object' || entry === null) {
62
+ throw new RoutingCentroidsError('Invalid cluster entry in routing centroids artifact');
63
+ }
64
+ const cluster = entry;
65
+ const clusterId = cluster.cluster_id;
66
+ const tierBias = cluster.tier_bias;
67
+ const centroid = cluster.centroid;
68
+ const referenceCount = cluster.reference_count;
69
+ if (typeof clusterId !== 'string' || clusterId.length === 0) {
70
+ throw new RoutingCentroidsError('Invalid cluster_id in routing centroids artifact');
71
+ }
72
+ if (tierBias !== 'zero-tier' &&
73
+ tierBias !== 'economical-cloud' &&
74
+ tierBias !== 'frontier-cloud') {
75
+ throw new RoutingCentroidsError(`Invalid tier_bias for cluster '${clusterId}': ${String(tierBias)}`);
76
+ }
77
+ if (!Array.isArray(centroid) || centroid.length !== EMBEDDING_DIM) {
78
+ throw new RoutingCentroidsError(`Invalid centroid for cluster '${clusterId}': expected ${EMBEDDING_DIM} dimensions`);
79
+ }
80
+ if (!centroid.every((value) => typeof value === 'number' && Number.isFinite(value))) {
81
+ throw new RoutingCentroidsError(`Invalid centroid values for cluster '${clusterId}': must be finite numbers`);
82
+ }
83
+ if (typeof referenceCount !== 'number' || !Number.isInteger(referenceCount) || referenceCount < 1) {
84
+ throw new RoutingCentroidsError(`Invalid reference_count for cluster '${clusterId}'`);
85
+ }
86
+ parsedClusters.push({
87
+ cluster_id: clusterId,
88
+ tier_bias: tierBias,
89
+ centroid,
90
+ reference_count: referenceCount,
91
+ });
92
+ }
93
+ return {
94
+ version: 1,
95
+ embedding_dim: EMBEDDING_DIM,
96
+ clusters: parsedClusters,
97
+ };
98
+ }
99
+ export function loadRoutingCentroidsArtifact(filePath = resolve(DEFAULT_ROUTING_CENTROIDS_PATH)) {
100
+ let raw;
101
+ try {
102
+ raw = readFileSync(filePath, 'utf8');
103
+ }
104
+ catch (err) {
105
+ const message = err instanceof Error ? err.message : String(err);
106
+ throw new RoutingCentroidsError(`Failed to read routing centroids file: ${message}`, { cause: err });
107
+ }
108
+ let parsed;
109
+ try {
110
+ parsed = JSON.parse(raw);
111
+ }
112
+ catch (err) {
113
+ const message = err instanceof Error ? err.message : String(err);
114
+ throw new RoutingCentroidsError(`Failed to parse routing centroids JSON: ${message}`, {
115
+ cause: err,
116
+ });
117
+ }
118
+ return parseRoutingCentroidsArtifact(parsed);
119
+ }
120
+ export function validateCentroidClusterIds(catalogClusters, artifact) {
121
+ const catalogIds = new Set(catalogClusters.map((cluster) => cluster.id));
122
+ const artifactIds = new Set(artifact.clusters.map((cluster) => cluster.cluster_id));
123
+ for (const id of catalogIds) {
124
+ if (!artifactIds.has(id)) {
125
+ throw new RoutingCentroidsError(`Routing centroids artifact missing cluster_id '${id}' from catalog`);
126
+ }
127
+ }
128
+ for (const id of artifactIds) {
129
+ if (!catalogIds.has(id)) {
130
+ throw new RoutingCentroidsError(`Routing centroids artifact has unknown cluster_id '${id}'`);
131
+ }
132
+ }
133
+ const catalogById = new Map(catalogClusters.map((cluster) => [cluster.id, cluster]));
134
+ for (const record of artifact.clusters) {
135
+ const catalogCluster = catalogById.get(record.cluster_id);
136
+ if (catalogCluster.tier_bias !== record.tier_bias) {
137
+ throw new RoutingCentroidsError(`tier_bias mismatch for cluster '${record.cluster_id}': catalog=${catalogCluster.tier_bias}, artifact=${record.tier_bias}`);
138
+ }
139
+ if (catalogCluster.reference_prompts.length !== record.reference_count) {
140
+ throw new RoutingCentroidsError(`reference_count mismatch for cluster '${record.cluster_id}': catalog=${catalogCluster.reference_prompts.length}, artifact=${record.reference_count}`);
141
+ }
142
+ }
143
+ }
144
+ export function applyPrecomputedCentroids(catalogClusters, artifact) {
145
+ validateCentroidClusterIds(catalogClusters, artifact);
146
+ const centroidById = new Map(artifact.clusters.map((record) => [
147
+ record.cluster_id,
148
+ new Float32Array(record.centroid),
149
+ ]));
150
+ return catalogClusters.map((cluster) => ({
151
+ ...cluster,
152
+ centroid: centroidById.get(cluster.id),
153
+ }));
154
+ }
155
+ export async function buildRoutingCentroidsArtifact(catalogClusters, embedder) {
156
+ const clusters = [];
157
+ for (const cluster of catalogClusters) {
158
+ const embeddings = [];
159
+ for (const prompt of cluster.reference_prompts) {
160
+ embeddings.push(await embedder.embed(prompt));
161
+ }
162
+ clusters.push({
163
+ cluster_id: cluster.id,
164
+ tier_bias: cluster.tier_bias,
165
+ centroid: Array.from(computeCentroid(embeddings)),
166
+ reference_count: cluster.reference_prompts.length,
167
+ });
168
+ }
169
+ return {
170
+ version: 1,
171
+ embedding_dim: EMBEDDING_DIM,
172
+ clusters,
173
+ };
174
+ }
175
+ export function serializeRoutingCentroidsArtifact(artifact) {
176
+ return `${JSON.stringify(artifact, null, 2)}\n`;
177
+ }
178
+ function isMissingCentroidsFileError(err) {
179
+ return (err instanceof RoutingCentroidsError &&
180
+ err.cause instanceof Error &&
181
+ 'code' in err.cause &&
182
+ err.cause.code === 'ENOENT');
183
+ }
184
+ /**
185
+ * Load routing cluster catalog with precomputed centroids when the artifact exists.
186
+ * Falls back to inline centroid computation from reference prompts when missing.
187
+ */
188
+ export async function loadClusterMatcherCatalog(options) {
189
+ const clustersFilePath = options.clustersFilePath ?? resolve('config', 'routing-clusters.yaml');
190
+ const centroidsFilePath = options.centroidsFilePath ?? resolve(DEFAULT_ROUTING_CENTROIDS_PATH);
191
+ const raw = readFileSync(clustersFilePath, 'utf8');
192
+ const catalogClusters = parseRoutingClustersYaml(raw);
193
+ try {
194
+ const artifact = loadRoutingCentroidsArtifact(centroidsFilePath);
195
+ return { clusters: applyPrecomputedCentroids(catalogClusters, artifact) };
196
+ }
197
+ catch (err) {
198
+ if (isMissingCentroidsFileError(err)) {
199
+ return loadRoutingClusters({
200
+ filePath: clustersFilePath,
201
+ embedder: options.embedder,
202
+ });
203
+ }
204
+ throw err;
205
+ }
206
+ }
207
+ export async function createClusterMatcher(options) {
208
+ const catalog = await loadClusterMatcherCatalog(options);
209
+ return new ClusterMatcher({ catalog, embedder: options.embedder });
210
+ }
211
+ export function cosineSimilarity(a, b) {
212
+ if (a.length !== b.length) {
213
+ throw new Error(`Embedding shape mismatch: expected ${a.length}, got ${b.length}`);
214
+ }
215
+ let dot = 0;
216
+ let magA = 0;
217
+ let magB = 0;
218
+ for (let i = 0; i < a.length; i++) {
219
+ const av = a[i] ?? 0;
220
+ const bv = b[i] ?? 0;
221
+ dot += av * bv;
222
+ magA += av * av;
223
+ magB += bv * bv;
224
+ }
225
+ if (magA === 0 || magB === 0) {
226
+ return 0;
227
+ }
228
+ return dot / (Math.sqrt(magA) * Math.sqrt(magB));
229
+ }
230
+ function rankClusters(embedding, clusters) {
231
+ return clusters
232
+ .map((cluster) => ({
233
+ cluster,
234
+ similarity: cosineSimilarity(embedding, cluster.centroid),
235
+ }))
236
+ .sort((a, b) => b.similarity - a.similarity);
237
+ }
238
+ function computeConfidence(similarity, margin, minSimilarity, minMargin) {
239
+ if (similarity >= minSimilarity && margin >= minMargin) {
240
+ return 'high';
241
+ }
242
+ // Issue #56: low-confidence matches defer — report none for routing.
243
+ return 'none';
244
+ }
245
+ export class ClusterMatcher {
246
+ clusters;
247
+ embedder;
248
+ constructor(config) {
249
+ if (config.catalog.clusters.length === 0) {
250
+ throw new Error('ClusterMatcher requires at least one loaded cluster');
251
+ }
252
+ this.clusters = config.catalog.clusters;
253
+ this.embedder = config.embedder;
254
+ }
255
+ async match(request) {
256
+ const start = performance.now();
257
+ const embedding = await this.embedder.embed(request.prompt_text);
258
+ const ranked = rankClusters(embedding, this.clusters);
259
+ const best = ranked[0];
260
+ const runnerUp = ranked[1];
261
+ const margin = runnerUp
262
+ ? best.similarity - runnerUp.similarity
263
+ : 0;
264
+ const confidence = computeConfidence(best.similarity, margin, best.cluster.min_similarity, best.cluster.min_margin);
265
+ return {
266
+ clusterId: best.cluster.id,
267
+ tierBias: best.cluster.tier_bias,
268
+ similarity: best.similarity,
269
+ margin,
270
+ confidence,
271
+ elapsedMs: performance.now() - start,
272
+ };
273
+ }
274
+ /** Score all cluster centroids for explain / telemetry tables (SP-113). */
275
+ async matchTable(request) {
276
+ const embedding = await this.embedder.embed(request.prompt_text);
277
+ const ranked = rankClusters(embedding, this.clusters);
278
+ const best = ranked[0];
279
+ return ranked.map((entry, index) => {
280
+ const runnerUp = ranked[index + 1];
281
+ const margin = runnerUp ? entry.similarity - runnerUp.similarity : null;
282
+ const confidence = computeConfidence(entry.similarity, index === 0 ? (margin ?? 0) : 0, entry.cluster.min_similarity, entry.cluster.min_margin);
283
+ return {
284
+ cluster_id: entry.cluster.id,
285
+ tier_bias: entry.cluster.tier_bias,
286
+ similarity: entry.similarity,
287
+ margin: index === 0 ? margin : null,
288
+ confidence: confidence === 'high' ? 'high' : 'none',
289
+ selected: entry === best,
290
+ };
291
+ });
292
+ }
293
+ }
294
+ //# sourceMappingURL=cluster-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cluster-matcher.js","sourceRoot":"","sources":["../../../src/domain/matching/cluster-matcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shared MiniLM ONNX text embedder — SP-100.
3
+ *
4
+ * Embeds prompt text via Xenova/all-MiniLM-L6-v2 (384-dim) for HyDRA requirement
5
+ * projection and semantic cluster matching. One ONNX session per instance; share
6
+ * across matchers via a single factory call and coordinated dispose().
7
+ */
8
+ export declare const EMBEDDING_DIM = 384;
9
+ export interface TextEmbedder {
10
+ embed(text: string): Promise<Float32Array>;
11
+ dispose(): Promise<void>;
12
+ }
13
+ /**
14
+ * Creates a TextEmbedder backed by @huggingface/transformers ONNX runtime.
15
+ * Model: Xenova/all-MiniLM-L6-v2 (384-dim).
16
+ *
17
+ * The package is loaded dynamically — not required at compile time.
18
+ * Install: `npm i @huggingface/transformers`
19
+ */
20
+ export declare function createOnnxTextEmbedder(artifactCachePath: string): Promise<TextEmbedder>;
21
+ //# sourceMappingURL=embedding-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-provider.d.ts","sourceRoot":"","sources":["../../../src/domain/matching/embedding-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAqBD;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,YAAY,CAAC,CAmCvB"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Shared MiniLM ONNX text embedder — SP-100.
3
+ *
4
+ * Embeds prompt text via Xenova/all-MiniLM-L6-v2 (384-dim) for HyDRA requirement
5
+ * projection and semantic cluster matching. One ONNX session per instance; share
6
+ * across matchers via a single factory call and coordinated dispose().
7
+ */
8
+ export const EMBEDDING_DIM = 384;
9
+ /**
10
+ * Creates a TextEmbedder backed by @huggingface/transformers ONNX runtime.
11
+ * Model: Xenova/all-MiniLM-L6-v2 (384-dim).
12
+ *
13
+ * The package is loaded dynamically — not required at compile time.
14
+ * Install: `npm i @huggingface/transformers`
15
+ */
16
+ export async function createOnnxTextEmbedder(artifactCachePath) {
17
+ const moduleName = '@huggingface/transformers';
18
+ let mod;
19
+ try {
20
+ mod = (await import(moduleName));
21
+ }
22
+ catch {
23
+ throw new Error(`ONNX embedding requires ${moduleName}. Install: npm i ${moduleName}`);
24
+ }
25
+ const extractor = await mod.pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2', { cache_dir: artifactCachePath });
26
+ return {
27
+ async embed(text) {
28
+ const output = await extractor(text, {
29
+ pooling: 'mean',
30
+ normalize: true,
31
+ });
32
+ if (output.data.length !== EMBEDDING_DIM) {
33
+ throw new Error(`Embedding shape mismatch: expected ${EMBEDDING_DIM}, got ${output.data.length}`);
34
+ }
35
+ return output.data;
36
+ },
37
+ async dispose() {
38
+ /* @huggingface/transformers pipelines have no explicit dispose */
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=embedding-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-provider.js","sourceRoot":"","sources":["../../../src/domain/matching/embedding-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AA0BjC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,iBAAyB;IAEzB,MAAM,UAAU,GAAG,2BAA2B,CAAC;IAC/C,IAAI,GAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAuB,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,2BAA2B,UAAU,oBAAoB,UAAU,EAAE,CACtE,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAoB,MAAM,GAAG,CAAC,QAAQ,CACnD,oBAAoB,EACpB,yBAAyB,EACzB,EAAE,SAAS,EAAE,iBAAiB,EAAE,CACjC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,IAAY;YACtB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE;gBACnC,OAAO,EAAE,MAAM;gBACf,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CACb,sCAAsC,aAAa,SAAS,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CACjF,CAAC;YACJ,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;QAED,KAAK,CAAC,OAAO;YACX,kEAAkE;QACpE,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * HyDRA embedding input builder — SP-112, GitHub #60.
3
+ *
4
+ * Prefixes prompt text with session metadata so requirement vectors reflect
5
+ * turn context, not only the latest user string.
6
+ */
7
+ import type { RoutingRequest } from '../types/index.js';
8
+ import type { TriageResult } from '../triage/triage-engine.js';
9
+ /**
10
+ * Build HyDRA encoder input: metadata prefix + prompt text.
11
+ *
12
+ * Format: `[turns:N|tools:0|tokens:N|type:...] {prompt_text}`
13
+ *
14
+ * Metadata affects capability prediction only; tier selection uses the
15
+ * cluster/feature gate (SP-103) separately.
16
+ */
17
+ export declare function buildHydraInput(request: RoutingRequest, triage?: TriageResult): string;
18
+ //# sourceMappingURL=hydra-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydra-input.d.ts","sourceRoot":"","sources":["../../../src/domain/matching/hydra-input.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAsB/D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,YAAY,GACpB,MAAM,CAWR"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * HyDRA embedding input builder — SP-112, GitHub #60.
3
+ *
4
+ * Prefixes prompt text with session metadata so requirement vectors reflect
5
+ * turn context, not only the latest user string.
6
+ */
7
+ function resolveMessageCount(request) {
8
+ return request.messages?.length ?? 0;
9
+ }
10
+ function resolveHasToolContext(request) {
11
+ if (request.turn_type === 'tool_result') {
12
+ return true;
13
+ }
14
+ return request.messages?.some((message) => message.role === 'tool') ?? false;
15
+ }
16
+ function resolveEstimatedInputTokens(request) {
17
+ return request.estimated_input_tokens ?? 0;
18
+ }
19
+ function resolveTurnType(request) {
20
+ return request.turn_type ?? 'unknown';
21
+ }
22
+ /**
23
+ * Build HyDRA encoder input: metadata prefix + prompt text.
24
+ *
25
+ * Format: `[turns:N|tools:0|tokens:N|type:...] {prompt_text}`
26
+ *
27
+ * Metadata affects capability prediction only; tier selection uses the
28
+ * cluster/feature gate (SP-103) separately.
29
+ */
30
+ export function buildHydraInput(request, triage) {
31
+ void triage;
32
+ const flags = [
33
+ `turns:${resolveMessageCount(request)}`,
34
+ `tools:${resolveHasToolContext(request) ? 1 : 0}`,
35
+ `tokens:${resolveEstimatedInputTokens(request)}`,
36
+ `type:${resolveTurnType(request)}`,
37
+ ].join('|');
38
+ return `[${flags}] ${request.prompt_text}`;
39
+ }
40
+ //# sourceMappingURL=hydra-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydra-input.js","sourceRoot":"","sources":["../../../src/domain/matching/hydra-input.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,SAAS,mBAAmB,CAAC,OAAuB;IAClD,OAAO,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAuB;IACpD,IAAI,OAAO,CAAC,SAAS,KAAK,aAAa,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC;AAC/E,CAAC;AAED,SAAS,2BAA2B,CAAC,OAAuB;IAC1D,OAAO,OAAO,CAAC,sBAAsB,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,OAAuB;IAC9C,OAAO,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAuB,EACvB,MAAqB;IAErB,KAAK,MAAM,CAAC;IAEZ,MAAM,KAAK,GAAG;QACZ,SAAS,mBAAmB,CAAC,OAAO,CAAC,EAAE;QACvC,SAAS,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;QACjD,UAAU,2BAA2B,CAAC,OAAO,CAAC,EAAE;QAChD,QAAQ,eAAe,CAAC,OAAO,CAAC,EAAE;KACnC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,OAAO,IAAI,KAAK,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * HyDRA embedding matcher — T048, FR-005.
3
+ *
4
+ * Embeds prompt text via ONNX (Xenova/all-MiniLM-L6-v2 384-dim),
5
+ * projects to requirement dimensions [reasoning, code_gen, tool_use],
6
+ * and scores fleet candidates with a shortfall gate.
7
+ *
8
+ * Shortfall gate (data-model §Validation): candidate excluded when
9
+ * any capability dimension shortfall > 0 (quality parity).
10
+ *
11
+ * Budget: 80–120 ms (configurable, default 100 ms).
12
+ */
13
+ import { z } from 'zod';
14
+ import { EMBEDDING_DIM, type TextEmbedder } from './embedding-provider.js';
15
+ import { type FrugalityWeights } from '../scoring/multi-objective.js';
16
+ import type { CandidateScore, ModelProfile, RoutingRequest } from '../types/index.js';
17
+ export interface RequirementVector {
18
+ readonly reasoning: number;
19
+ readonly code_gen: number;
20
+ readonly tool_use: number;
21
+ }
22
+ export interface EmbeddingProvider {
23
+ extractRequirements(text: string): Promise<RequirementVector>;
24
+ dispose(): Promise<void>;
25
+ }
26
+ export interface MatchResult {
27
+ readonly selected: CandidateScore | null;
28
+ readonly candidates: readonly CandidateScore[];
29
+ readonly requirements: RequirementVector;
30
+ readonly elapsedMs: number;
31
+ readonly budgetExceeded: boolean;
32
+ }
33
+ export interface HydraMatcherConfig {
34
+ readonly artifactCachePath: string;
35
+ readonly budgetMs?: number;
36
+ readonly frugality?: FrugalityWeights;
37
+ readonly projectionWeightsPath?: string;
38
+ }
39
+ export declare const DEFAULT_HYDRA_PROJECTION_WEIGHTS_PATH: string;
40
+ export declare const HYDRA_PROJECTION_OUTPUT_DIM = 3;
41
+ export declare const HydraProjectionWeightsSchema: z.ZodObject<{
42
+ version: z.ZodLiteral<1>;
43
+ embedding_dim: z.ZodLiteral<384>;
44
+ weights: z.ZodArray<z.ZodArray<z.ZodNumber>>;
45
+ bias: z.ZodArray<z.ZodNumber>;
46
+ }, z.core.$strip>;
47
+ export interface HydraProjectionWeights {
48
+ readonly version: 1;
49
+ readonly embedding_dim: typeof EMBEDDING_DIM;
50
+ readonly weights: readonly (readonly number[])[];
51
+ readonly bias: readonly number[];
52
+ }
53
+ export interface LoadHydraProjectionWeightsOptions {
54
+ readonly filePath?: string;
55
+ }
56
+ export declare class HydraProjectionWeightsLoaderError extends Error {
57
+ readonly name = "HydraProjectionWeightsLoaderError";
58
+ constructor(message: string, options?: {
59
+ cause?: unknown;
60
+ });
61
+ }
62
+ export declare function parseHydraProjectionWeightsJson(raw: string): HydraProjectionWeights;
63
+ /**
64
+ * Load HyDRA projection weights from disk. Returns null when the artifact is
65
+ * missing; throws only when the file exists but is invalid.
66
+ */
67
+ export declare function loadHydraProjectionWeights(options?: LoadHydraProjectionWeightsOptions): HydraProjectionWeights | null;
68
+ /** Resolve projection weights — missing artifacts fall back to placeholder projection. */
69
+ export declare function resolveHydraProjectionWeights(options?: LoadHydraProjectionWeightsOptions): HydraProjectionWeights | null;
70
+ /**
71
+ * Project a 384-dim embedding to 3 requirement dimensions.
72
+ *
73
+ * Uses learned linear projection (sigmoid(embedding @ W + b)) when weights are
74
+ * provided; otherwise falls back to deterministic mean-pooled-thirds placeholder.
75
+ */
76
+ export declare function projectToRequirements(embedding: Float32Array, weights?: HydraProjectionWeights | null): RequirementVector;
77
+ /**
78
+ * Adapts a shared TextEmbedder for HyDRA requirement extraction.
79
+ * dispose() delegates to the underlying embedder for shared lifecycle.
80
+ */
81
+ export declare function wrapHydraEmbeddingProvider(embedder: TextEmbedder, projectionWeights?: HydraProjectionWeights | null): EmbeddingProvider;
82
+ export declare class HydraMatcher {
83
+ private readonly provider;
84
+ private readonly budgetMs;
85
+ private readonly frugality;
86
+ private readonly projectionWeights;
87
+ constructor(provider: EmbeddingProvider, config: HydraMatcherConfig);
88
+ /** Whether learned projection weights were loaded at init. */
89
+ usesLearnedProjection(): boolean;
90
+ match(request: RoutingRequest, fleet: readonly ModelProfile[]): Promise<MatchResult>;
91
+ dispose(): Promise<void>;
92
+ private validateRequirements;
93
+ }
94
+ export interface CreateOnnxEmbeddingProviderOptions {
95
+ readonly projectionWeightsPath?: string;
96
+ }
97
+ /**
98
+ * Creates an EmbeddingProvider backed by the shared ONNX text embedder.
99
+ * For multi-matcher setups, create one TextEmbedder via createOnnxTextEmbedder
100
+ * and pass wrapHydraEmbeddingProvider(embedder) to HyDRA while sharing embed().
101
+ */
102
+ export declare function createOnnxEmbeddingProvider(artifactCachePath: string, options?: CreateOnnxEmbeddingProviderOptions): Promise<EmbeddingProvider>;
103
+ //# sourceMappingURL=hydra-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydra-matcher.d.ts","sourceRoot":"","sources":["../../../src/domain/matching/hydra-matcher.ts"],"names":[],"mappings":"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"}