@planu/cli 0.28.0 → 0.30.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 (297) hide show
  1. package/dist/config/model-routing-rules.json +98 -0
  2. package/dist/engine/ai-cost-estimator/core.d.ts.map +1 -1
  3. package/dist/engine/ai-cost-estimator/core.js +2 -202
  4. package/dist/engine/ai-cost-estimator/core.js.map +1 -1
  5. package/dist/engine/ai-cost-estimator/recommender.d.ts +8 -0
  6. package/dist/engine/ai-cost-estimator/recommender.d.ts.map +1 -0
  7. package/dist/engine/ai-cost-estimator/recommender.js +94 -0
  8. package/dist/engine/ai-cost-estimator/recommender.js.map +1 -0
  9. package/dist/engine/ai-cost-estimator/spec-loader.d.ts +13 -0
  10. package/dist/engine/ai-cost-estimator/spec-loader.d.ts.map +1 -0
  11. package/dist/engine/ai-cost-estimator/spec-loader.js +102 -0
  12. package/dist/engine/ai-cost-estimator/spec-loader.js.map +1 -0
  13. package/dist/engine/ci-generator/planu-config.d.ts +7 -0
  14. package/dist/engine/ci-generator/planu-config.d.ts.map +1 -0
  15. package/dist/engine/ci-generator/planu-config.js +40 -0
  16. package/dist/engine/ci-generator/planu-config.js.map +1 -0
  17. package/dist/engine/ci-generator/planu-steps.d.ts +11 -0
  18. package/dist/engine/ci-generator/planu-steps.d.ts.map +1 -0
  19. package/dist/engine/ci-generator/planu-steps.js +292 -0
  20. package/dist/engine/ci-generator/planu-steps.js.map +1 -0
  21. package/dist/engine/code-transforms/transform-engine.d.ts +7 -0
  22. package/dist/engine/code-transforms/transform-engine.d.ts.map +1 -0
  23. package/dist/engine/code-transforms/transform-engine.js +67 -0
  24. package/dist/engine/code-transforms/transform-engine.js.map +1 -0
  25. package/dist/engine/code-transforms/typescript/add-error-handling.d.ts +6 -0
  26. package/dist/engine/code-transforms/typescript/add-error-handling.d.ts.map +1 -0
  27. package/dist/engine/code-transforms/typescript/add-error-handling.js +92 -0
  28. package/dist/engine/code-transforms/typescript/add-error-handling.js.map +1 -0
  29. package/dist/engine/code-transforms/typescript/add-jsdoc.d.ts +6 -0
  30. package/dist/engine/code-transforms/typescript/add-jsdoc.d.ts.map +1 -0
  31. package/dist/engine/code-transforms/typescript/add-jsdoc.js +83 -0
  32. package/dist/engine/code-transforms/typescript/add-jsdoc.js.map +1 -0
  33. package/dist/engine/code-transforms/typescript/add-types.d.ts +3 -0
  34. package/dist/engine/code-transforms/typescript/add-types.d.ts.map +1 -0
  35. package/dist/engine/code-transforms/typescript/add-types.js +182 -0
  36. package/dist/engine/code-transforms/typescript/add-types.js.map +1 -0
  37. package/dist/engine/code-transforms/typescript/ast-utils.d.ts +38 -0
  38. package/dist/engine/code-transforms/typescript/ast-utils.d.ts.map +1 -0
  39. package/dist/engine/code-transforms/typescript/ast-utils.js +90 -0
  40. package/dist/engine/code-transforms/typescript/ast-utils.js.map +1 -0
  41. package/dist/engine/code-transforms/typescript/extract-interface.d.ts +6 -0
  42. package/dist/engine/code-transforms/typescript/extract-interface.d.ts.map +1 -0
  43. package/dist/engine/code-transforms/typescript/extract-interface.js +103 -0
  44. package/dist/engine/code-transforms/typescript/extract-interface.js.map +1 -0
  45. package/dist/engine/code-transforms/typescript/modernize-syntax.d.ts +3 -0
  46. package/dist/engine/code-transforms/typescript/modernize-syntax.d.ts.map +1 -0
  47. package/dist/engine/code-transforms/typescript/modernize-syntax.js +213 -0
  48. package/dist/engine/code-transforms/typescript/modernize-syntax.js.map +1 -0
  49. package/dist/engine/code-transforms/typescript/rename-symbol.d.ts +8 -0
  50. package/dist/engine/code-transforms/typescript/rename-symbol.d.ts.map +1 -0
  51. package/dist/engine/code-transforms/typescript/rename-symbol.js +40 -0
  52. package/dist/engine/code-transforms/typescript/rename-symbol.js.map +1 -0
  53. package/dist/engine/mermaid/core.d.ts +18 -0
  54. package/dist/engine/mermaid/core.d.ts.map +1 -0
  55. package/dist/engine/mermaid/core.js +88 -0
  56. package/dist/engine/mermaid/core.js.map +1 -0
  57. package/dist/engine/mermaid/diagram-generators.d.ts +22 -0
  58. package/dist/engine/mermaid/diagram-generators.d.ts.map +1 -0
  59. package/dist/engine/mermaid/diagram-generators.js +139 -0
  60. package/dist/engine/mermaid/diagram-generators.js.map +1 -0
  61. package/dist/engine/mermaid/helpers.d.ts +8 -0
  62. package/dist/engine/mermaid/helpers.d.ts.map +1 -0
  63. package/dist/engine/mermaid/helpers.js +61 -0
  64. package/dist/engine/mermaid/helpers.js.map +1 -0
  65. package/dist/engine/mermaid-generator.d.ts +2 -37
  66. package/dist/engine/mermaid-generator.d.ts.map +1 -1
  67. package/dist/engine/mermaid-generator.js +4 -276
  68. package/dist/engine/mermaid-generator.js.map +1 -1
  69. package/dist/engine/model-router/complexity-analyzer.d.ts +26 -0
  70. package/dist/engine/model-router/complexity-analyzer.d.ts.map +1 -0
  71. package/dist/engine/model-router/complexity-analyzer.js +182 -0
  72. package/dist/engine/model-router/complexity-analyzer.js.map +1 -0
  73. package/dist/engine/model-router/cost-estimator.d.ts +6 -0
  74. package/dist/engine/model-router/cost-estimator.d.ts.map +1 -0
  75. package/dist/engine/model-router/cost-estimator.js +60 -0
  76. package/dist/engine/model-router/cost-estimator.js.map +1 -0
  77. package/dist/engine/model-router/historical-learner.d.ts +26 -0
  78. package/dist/engine/model-router/historical-learner.d.ts.map +1 -0
  79. package/dist/engine/model-router/historical-learner.js +91 -0
  80. package/dist/engine/model-router/historical-learner.js.map +1 -0
  81. package/dist/engine/model-router/rules-engine.d.ts +13 -0
  82. package/dist/engine/model-router/rules-engine.d.ts.map +1 -0
  83. package/dist/engine/model-router/rules-engine.js +142 -0
  84. package/dist/engine/model-router/rules-engine.js.map +1 -0
  85. package/dist/engine/spec-coverage/criteria-mapper.d.ts +1 -2
  86. package/dist/engine/spec-coverage/criteria-mapper.d.ts.map +1 -1
  87. package/dist/engine/spec-coverage/criteria-mapper.js +4 -203
  88. package/dist/engine/spec-coverage/criteria-mapper.js.map +1 -1
  89. package/dist/engine/spec-coverage/keyword-extractor.d.ts +10 -0
  90. package/dist/engine/spec-coverage/keyword-extractor.d.ts.map +1 -0
  91. package/dist/engine/spec-coverage/keyword-extractor.js +147 -0
  92. package/dist/engine/spec-coverage/keyword-extractor.js.map +1 -0
  93. package/dist/engine/spec-coverage/test-matchers.d.ts +9 -0
  94. package/dist/engine/spec-coverage/test-matchers.d.ts.map +1 -0
  95. package/dist/engine/spec-coverage/test-matchers.js +59 -0
  96. package/dist/engine/spec-coverage/test-matchers.js.map +1 -0
  97. package/dist/engine/spec-templates/catalog-extra.d.ts +1 -1
  98. package/dist/engine/spec-templates/catalog-extra.d.ts.map +1 -1
  99. package/dist/engine/spec-templates/catalog-extra.js +8 -363
  100. package/dist/engine/spec-templates/catalog-extra.js.map +1 -1
  101. package/dist/engine/spec-templates/catalog-industry.d.ts +4 -0
  102. package/dist/engine/spec-templates/catalog-industry.d.ts.map +1 -0
  103. package/dist/engine/spec-templates/catalog-industry.js +19 -0
  104. package/dist/engine/spec-templates/catalog-industry.js.map +1 -0
  105. package/dist/engine/spec-templates/catalog.d.ts +1 -1
  106. package/dist/engine/spec-templates/catalog.d.ts.map +1 -1
  107. package/dist/engine/spec-templates/catalog.js +12 -381
  108. package/dist/engine/spec-templates/catalog.js.map +1 -1
  109. package/dist/engine/spec-templates/custom-loader.d.ts +12 -0
  110. package/dist/engine/spec-templates/custom-loader.d.ts.map +1 -0
  111. package/dist/engine/spec-templates/custom-loader.js +99 -0
  112. package/dist/engine/spec-templates/custom-loader.js.map +1 -0
  113. package/dist/engine/spec-templates/index.d.ts +4 -2
  114. package/dist/engine/spec-templates/index.d.ts.map +1 -1
  115. package/dist/engine/spec-templates/index.js +4 -2
  116. package/dist/engine/spec-templates/index.js.map +1 -1
  117. package/dist/engine/spec-templates/query.d.ts +12 -4
  118. package/dist/engine/spec-templates/query.d.ts.map +1 -1
  119. package/dist/engine/spec-templates/query.js +29 -7
  120. package/dist/engine/spec-templates/query.js.map +1 -1
  121. package/dist/engine/spec-templates/renderer.d.ts +27 -2
  122. package/dist/engine/spec-templates/renderer.d.ts.map +1 -1
  123. package/dist/engine/spec-templates/renderer.js +119 -4
  124. package/dist/engine/spec-templates/renderer.js.map +1 -1
  125. package/dist/engine/spec-templates/templates-api-ui.d.ts +6 -0
  126. package/dist/engine/spec-templates/templates-api-ui.d.ts.map +1 -0
  127. package/dist/engine/spec-templates/templates-api-ui.js +215 -0
  128. package/dist/engine/spec-templates/templates-api-ui.js.map +1 -0
  129. package/dist/engine/spec-templates/templates-auth-crud.d.ts +6 -0
  130. package/dist/engine/spec-templates/templates-auth-crud.d.ts.map +1 -0
  131. package/dist/engine/spec-templates/templates-auth-crud.js +225 -0
  132. package/dist/engine/spec-templates/templates-auth-crud.js.map +1 -0
  133. package/dist/engine/spec-templates/templates-data-security.d.ts +6 -0
  134. package/dist/engine/spec-templates/templates-data-security.d.ts.map +1 -0
  135. package/dist/engine/spec-templates/templates-data-security.js +198 -0
  136. package/dist/engine/spec-templates/templates-data-security.js.map +1 -0
  137. package/dist/engine/spec-templates/templates-industry-ecom.d.ts +6 -0
  138. package/dist/engine/spec-templates/templates-industry-ecom.d.ts.map +1 -0
  139. package/dist/engine/spec-templates/templates-industry-ecom.js +209 -0
  140. package/dist/engine/spec-templates/templates-industry-ecom.js.map +1 -0
  141. package/dist/engine/spec-templates/templates-industry-fintech.d.ts +8 -0
  142. package/dist/engine/spec-templates/templates-industry-fintech.d.ts.map +1 -0
  143. package/dist/engine/spec-templates/templates-industry-fintech.js +350 -0
  144. package/dist/engine/spec-templates/templates-industry-fintech.js.map +1 -0
  145. package/dist/engine/spec-templates/templates-industry-health-ecom.d.ts +3 -0
  146. package/dist/engine/spec-templates/templates-industry-health-ecom.d.ts.map +1 -0
  147. package/dist/engine/spec-templates/templates-industry-health-ecom.js +5 -0
  148. package/dist/engine/spec-templates/templates-industry-health-ecom.js.map +1 -0
  149. package/dist/engine/spec-templates/templates-industry-health.d.ts +6 -0
  150. package/dist/engine/spec-templates/templates-industry-health.d.ts.map +1 -0
  151. package/dist/engine/spec-templates/templates-industry-health.js +208 -0
  152. package/dist/engine/spec-templates/templates-industry-health.js.map +1 -0
  153. package/dist/engine/spec-templates/templates-industry-saas.d.ts +8 -0
  154. package/dist/engine/spec-templates/templates-industry-saas.d.ts.map +1 -0
  155. package/dist/engine/spec-templates/templates-industry-saas.js +323 -0
  156. package/dist/engine/spec-templates/templates-industry-saas.js.map +1 -0
  157. package/dist/engine/spec-templates/templates-perf-integration.d.ts +6 -0
  158. package/dist/engine/spec-templates/templates-perf-integration.d.ts.map +1 -0
  159. package/dist/engine/spec-templates/templates-perf-integration.js +226 -0
  160. package/dist/engine/spec-templates/templates-perf-integration.js.map +1 -0
  161. package/dist/engine/vector-store/hnsw.d.ts +37 -0
  162. package/dist/engine/vector-store/hnsw.d.ts.map +1 -0
  163. package/dist/engine/vector-store/hnsw.js +294 -0
  164. package/dist/engine/vector-store/hnsw.js.map +1 -0
  165. package/dist/engine/vector-store/similarity.d.ts +21 -0
  166. package/dist/engine/vector-store/similarity.d.ts.map +1 -0
  167. package/dist/engine/vector-store/similarity.js +86 -0
  168. package/dist/engine/vector-store/similarity.js.map +1 -0
  169. package/dist/engine/vector-store/tfidf.d.ts +35 -0
  170. package/dist/engine/vector-store/tfidf.d.ts.map +1 -0
  171. package/dist/engine/vector-store/tfidf.js +255 -0
  172. package/dist/engine/vector-store/tfidf.js.map +1 -0
  173. package/dist/index.js +6 -0
  174. package/dist/index.js.map +1 -1
  175. package/dist/storage/vector-store/backend-factory.d.ts +9 -0
  176. package/dist/storage/vector-store/backend-factory.d.ts.map +1 -0
  177. package/dist/storage/vector-store/backend-factory.js +33 -0
  178. package/dist/storage/vector-store/backend-factory.js.map +1 -0
  179. package/dist/storage/vector-store/json-fallback.d.ts +21 -0
  180. package/dist/storage/vector-store/json-fallback.d.ts.map +1 -0
  181. package/dist/storage/vector-store/json-fallback.js +85 -0
  182. package/dist/storage/vector-store/json-fallback.js.map +1 -0
  183. package/dist/storage/vector-store/migrator.d.ts +10 -0
  184. package/dist/storage/vector-store/migrator.d.ts.map +1 -0
  185. package/dist/storage/vector-store/migrator.js +139 -0
  186. package/dist/storage/vector-store/migrator.js.map +1 -0
  187. package/dist/storage/vector-store/sqlite-adapter.d.ts +28 -0
  188. package/dist/storage/vector-store/sqlite-adapter.d.ts.map +1 -0
  189. package/dist/storage/vector-store/sqlite-adapter.js +142 -0
  190. package/dist/storage/vector-store/sqlite-adapter.js.map +1 -0
  191. package/dist/tools/ci-planu-handler.d.ts +8 -0
  192. package/dist/tools/ci-planu-handler.d.ts.map +1 -0
  193. package/dist/tools/ci-planu-handler.js +44 -0
  194. package/dist/tools/ci-planu-handler.js.map +1 -0
  195. package/dist/tools/create-spec/constitution-validator.d.ts +4 -0
  196. package/dist/tools/create-spec/constitution-validator.d.ts.map +1 -0
  197. package/dist/tools/create-spec/constitution-validator.js +37 -0
  198. package/dist/tools/create-spec/constitution-validator.js.map +1 -0
  199. package/dist/tools/create-spec/post-creation.d.ts +11 -0
  200. package/dist/tools/create-spec/post-creation.d.ts.map +1 -0
  201. package/dist/tools/create-spec/post-creation.js +48 -0
  202. package/dist/tools/create-spec/post-creation.js.map +1 -0
  203. package/dist/tools/create-spec/spec-builder.d.ts +14 -0
  204. package/dist/tools/create-spec/spec-builder.d.ts.map +1 -0
  205. package/dist/tools/create-spec/spec-builder.js +131 -0
  206. package/dist/tools/create-spec/spec-builder.js.map +1 -0
  207. package/dist/tools/create-spec.d.ts.map +1 -1
  208. package/dist/tools/create-spec.js +42 -172
  209. package/dist/tools/create-spec.js.map +1 -1
  210. package/dist/tools/init-project/handler.d.ts.map +1 -1
  211. package/dist/tools/init-project/handler.js +24 -159
  212. package/dist/tools/init-project/handler.js.map +1 -1
  213. package/dist/tools/init-project/result-builder.d.ts +4 -0
  214. package/dist/tools/init-project/result-builder.d.ts.map +1 -0
  215. package/dist/tools/init-project/result-builder.js +150 -0
  216. package/dist/tools/init-project/result-builder.js.map +1 -0
  217. package/dist/tools/learn.d.ts.map +1 -1
  218. package/dist/tools/learn.js +67 -14
  219. package/dist/tools/learn.js.map +1 -1
  220. package/dist/tools/recommend-model-handler.d.ts +8 -0
  221. package/dist/tools/recommend-model-handler.d.ts.map +1 -0
  222. package/dist/tools/recommend-model-handler.js +65 -0
  223. package/dist/tools/recommend-model-handler.js.map +1 -0
  224. package/dist/tools/register-ci-tools.d.ts.map +1 -1
  225. package/dist/tools/register-ci-tools.js +36 -0
  226. package/dist/tools/register-ci-tools.js.map +1 -1
  227. package/dist/tools/register-model-tools.d.ts +3 -0
  228. package/dist/tools/register-model-tools.d.ts.map +1 -0
  229. package/dist/tools/register-model-tools.js +50 -0
  230. package/dist/tools/register-model-tools.js.map +1 -0
  231. package/dist/tools/register-search-tools.d.ts +7 -0
  232. package/dist/tools/register-search-tools.d.ts.map +1 -0
  233. package/dist/tools/register-search-tools.js +34 -0
  234. package/dist/tools/register-search-tools.js.map +1 -0
  235. package/dist/tools/register-template-tools.d.ts.map +1 -1
  236. package/dist/tools/register-template-tools.js +21 -8
  237. package/dist/tools/register-template-tools.js.map +1 -1
  238. package/dist/tools/register-transform-tools.d.ts +3 -0
  239. package/dist/tools/register-transform-tools.d.ts.map +1 -0
  240. package/dist/tools/register-transform-tools.js +29 -0
  241. package/dist/tools/register-transform-tools.js.map +1 -0
  242. package/dist/tools/semantic-search-handler.d.ts +7 -0
  243. package/dist/tools/semantic-search-handler.d.ts.map +1 -0
  244. package/dist/tools/semantic-search-handler.js +72 -0
  245. package/dist/tools/semantic-search-handler.js.map +1 -0
  246. package/dist/tools/spec-templates.d.ts +1 -1
  247. package/dist/tools/spec-templates.d.ts.map +1 -1
  248. package/dist/tools/spec-templates.js +20 -6
  249. package/dist/tools/spec-templates.js.map +1 -1
  250. package/dist/tools/transform-code-handler.d.ts +7 -0
  251. package/dist/tools/transform-code-handler.d.ts.map +1 -0
  252. package/dist/tools/transform-code-handler.js +58 -0
  253. package/dist/tools/transform-code-handler.js.map +1 -0
  254. package/dist/types/advanced-framework.d.ts +47 -0
  255. package/dist/types/advanced-framework.d.ts.map +1 -0
  256. package/dist/types/advanced-framework.js +3 -0
  257. package/dist/types/advanced-framework.js.map +1 -0
  258. package/dist/types/ci.d.ts +51 -0
  259. package/dist/types/ci.d.ts.map +1 -1
  260. package/dist/types/code-transforms.d.ts +114 -0
  261. package/dist/types/code-transforms.d.ts.map +1 -0
  262. package/dist/types/code-transforms.js +11 -0
  263. package/dist/types/code-transforms.js.map +1 -0
  264. package/dist/types/css-framework.d.ts +110 -0
  265. package/dist/types/css-framework.d.ts.map +1 -0
  266. package/dist/types/css-framework.js +3 -0
  267. package/dist/types/css-framework.js.map +1 -0
  268. package/dist/types/dashboard.d.ts +77 -0
  269. package/dist/types/dashboard.d.ts.map +1 -0
  270. package/dist/types/dashboard.js +2 -0
  271. package/dist/types/dashboard.js.map +1 -0
  272. package/dist/types/index.d.ts +3 -0
  273. package/dist/types/index.d.ts.map +1 -1
  274. package/dist/types/index.js +3 -0
  275. package/dist/types/index.js.map +1 -1
  276. package/dist/types/model-routing.d.ts +127 -0
  277. package/dist/types/model-routing.d.ts.map +1 -0
  278. package/dist/types/model-routing.js +3 -0
  279. package/dist/types/model-routing.js.map +1 -0
  280. package/dist/types/project/core.d.ts +46 -5
  281. package/dist/types/project/core.d.ts.map +1 -1
  282. package/dist/types/spec/core.d.ts +28 -1
  283. package/dist/types/spec/core.d.ts.map +1 -1
  284. package/dist/types/spec/inputs.d.ts +1 -6
  285. package/dist/types/spec/inputs.d.ts.map +1 -1
  286. package/dist/types/spec-templates.d.ts +51 -1
  287. package/dist/types/spec-templates.d.ts.map +1 -1
  288. package/dist/types/ui.d.ts +3 -231
  289. package/dist/types/ui.d.ts.map +1 -1
  290. package/dist/types/ui.js +7 -1
  291. package/dist/types/ui.js.map +1 -1
  292. package/dist/types/vector-store.d.ts +144 -0
  293. package/dist/types/vector-store.d.ts.map +1 -0
  294. package/dist/types/vector-store.js +3 -0
  295. package/dist/types/vector-store.js.map +1 -0
  296. package/package.json +1 -1
  297. package/src/config/model-routing-rules.json +98 -0
@@ -0,0 +1,294 @@
1
+ // engine/vector-store/hnsw.ts — HNSW index for approximate nearest neighbor search.
2
+ // SPEC-075 AC-02: Pure TypeScript, O(log n), recall > 0.9.
3
+ import { cosineSimilarity } from './similarity.js';
4
+ /**
5
+ * HNSW (Hierarchical Navigable Small World) index.
6
+ * For corpus < flatSearchThreshold, delegates to brute-force flat search.
7
+ */
8
+ export class HNSWIndex {
9
+ config;
10
+ nodes = new Map();
11
+ entryPoint = null;
12
+ maxLayer = 0;
13
+ constructor(config) {
14
+ this.config = {
15
+ M: config?.M ?? 16,
16
+ efConstruction: config?.efConstruction ?? 200,
17
+ efSearch: config?.efSearch ?? 50,
18
+ flatSearchThreshold: config?.flatSearchThreshold ?? 1000,
19
+ };
20
+ }
21
+ /** Number of indexed vectors. */
22
+ get size() {
23
+ return this.nodes.size;
24
+ }
25
+ /** Insert a vector into the index. */
26
+ insert(id, vector) {
27
+ const level = this.randomLevel();
28
+ const layers = [];
29
+ for (let i = 0; i <= level; i++) {
30
+ layers.push(new Map());
31
+ }
32
+ const node = { id, vector, layers };
33
+ if (this.nodes.size === 0) {
34
+ this.nodes.set(id, node);
35
+ this.entryPoint = id;
36
+ this.maxLayer = level;
37
+ return;
38
+ }
39
+ // Navigate from top to insertion level
40
+ /* v8 ignore start -- entryPoint always set when nodes.size > 0 */
41
+ let currentId = this.entryPoint ?? id;
42
+ /* v8 ignore stop */
43
+ for (let lc = this.maxLayer; lc > level; lc--) {
44
+ currentId = this.greedyClosest(currentId, vector, lc);
45
+ }
46
+ // Insert at each layer from level down to 0
47
+ for (let lc = Math.min(level, this.maxLayer); lc >= 0; lc--) {
48
+ const neighbors = this.searchLayer(currentId, vector, this.config.efConstruction, lc);
49
+ const selected = neighbors.slice(0, this.config.M);
50
+ for (const nb of selected) {
51
+ const sim = nb.similarity;
52
+ node.layers[lc]?.set(nb.id, sim);
53
+ const nbNode = this.nodes.get(nb.id);
54
+ /* v8 ignore start -- neighbor always exists and has layers at lc */
55
+ if (nbNode && lc < nbNode.layers.length) {
56
+ /* v8 ignore stop */
57
+ nbNode.layers[lc]?.set(id, sim);
58
+ // Prune if too many connections
59
+ /* v8 ignore start -- lc always within nbNode.layers bounds */
60
+ if ((nbNode.layers[lc]?.size ?? 0) > this.config.M * 2) {
61
+ /* v8 ignore stop */
62
+ this.pruneConnections(nbNode, lc);
63
+ }
64
+ }
65
+ }
66
+ const first = selected[0];
67
+ /* v8 ignore start -- searchLayer always returns at least one result */
68
+ if (first) {
69
+ /* v8 ignore stop */
70
+ currentId = first.id;
71
+ }
72
+ }
73
+ this.nodes.set(id, node);
74
+ if (level > this.maxLayer) {
75
+ this.maxLayer = level;
76
+ this.entryPoint = id;
77
+ }
78
+ }
79
+ /** Remove a vector from the index. */
80
+ remove(id) {
81
+ const node = this.nodes.get(id);
82
+ if (!node) {
83
+ return false;
84
+ }
85
+ // Remove references from neighbors
86
+ for (let lc = 0; lc < node.layers.length; lc++) {
87
+ const layer = node.layers[lc];
88
+ /* v8 ignore start -- defensive: layers always exist within bounds */
89
+ if (!layer) {
90
+ continue;
91
+ }
92
+ /* v8 ignore stop */
93
+ for (const neighborId of layer.keys()) {
94
+ const neighbor = this.nodes.get(neighborId);
95
+ /* v8 ignore start -- neighbor always exists in graph */
96
+ if (neighbor && lc < neighbor.layers.length) {
97
+ /* v8 ignore stop */
98
+ neighbor.layers[lc]?.delete(id);
99
+ }
100
+ }
101
+ }
102
+ this.nodes.delete(id);
103
+ // Update entry point if needed
104
+ if (this.entryPoint === id) {
105
+ /* v8 ignore start -- Map.keys().next().value always defined when size > 0 */
106
+ this.entryPoint = this.nodes.size > 0 ? (this.nodes.keys().next().value ?? null) : null;
107
+ /* v8 ignore stop */
108
+ this.maxLayer = 0;
109
+ for (const n of this.nodes.values()) {
110
+ if (n.layers.length - 1 > this.maxLayer) {
111
+ this.maxLayer = n.layers.length - 1;
112
+ this.entryPoint = n.id;
113
+ }
114
+ }
115
+ }
116
+ return true;
117
+ }
118
+ /** Search for the top-K nearest neighbors. Uses flat search for small corpus. */
119
+ search(query, topK) {
120
+ if (this.nodes.size === 0) {
121
+ return [];
122
+ }
123
+ // Flat search for small corpus
124
+ if (this.nodes.size < this.config.flatSearchThreshold) {
125
+ return this.flatSearch(query, topK);
126
+ }
127
+ return this.hnswSearch(query, topK);
128
+ }
129
+ /** Brute-force flat search -- guaranteed recall = 1.0. */
130
+ flatSearch(query, topK) {
131
+ const results = [];
132
+ for (const node of this.nodes.values()) {
133
+ results.push({ id: node.id, similarity: cosineSimilarity(query, node.vector) });
134
+ }
135
+ results.sort((a, b) => b.similarity - a.similarity);
136
+ return results.slice(0, topK);
137
+ }
138
+ /** HNSW graph search -- approximate, O(log n). */
139
+ hnswSearch(query, topK) {
140
+ /* v8 ignore start -- entryPoint always set when called (size > 0) */
141
+ let currentId = this.entryPoint ?? '';
142
+ /* v8 ignore stop */
143
+ // Traverse from top layer to layer 1
144
+ for (let lc = this.maxLayer; lc > 0; lc--) {
145
+ currentId = this.greedyClosest(currentId, query, lc);
146
+ }
147
+ // Search at layer 0 with efSearch candidates
148
+ const candidates = this.searchLayer(currentId, query, this.config.efSearch, 0);
149
+ return candidates.slice(0, topK);
150
+ }
151
+ /** Greedy walk to the closest node in a given layer. */
152
+ greedyClosest(startId, query, layer) {
153
+ let bestId = startId;
154
+ const startNode = this.nodes.get(startId);
155
+ /* v8 ignore start -- defensive: startId always valid when called internally */
156
+ if (!startNode) {
157
+ return bestId;
158
+ }
159
+ /* v8 ignore stop */
160
+ let bestSim = cosineSimilarity(query, startNode.vector);
161
+ let improved = true;
162
+ while (improved) {
163
+ improved = false;
164
+ const node = this.nodes.get(bestId);
165
+ /* v8 ignore start -- defensive: bestId always valid in walk */
166
+ if (!node || layer >= node.layers.length) {
167
+ break;
168
+ }
169
+ /* v8 ignore stop */
170
+ const neighbors = node.layers[layer];
171
+ /* v8 ignore start -- defensive: layer within bounds */
172
+ if (!neighbors) {
173
+ break;
174
+ }
175
+ /* v8 ignore stop */
176
+ for (const neighborId of neighbors.keys()) {
177
+ const neighbor = this.nodes.get(neighborId);
178
+ /* v8 ignore start -- defensive: neighbor always valid in graph */
179
+ if (!neighbor) {
180
+ continue;
181
+ }
182
+ /* v8 ignore stop */
183
+ const sim = cosineSimilarity(query, neighbor.vector);
184
+ if (sim > bestSim) {
185
+ bestSim = sim;
186
+ bestId = neighborId;
187
+ improved = true;
188
+ }
189
+ }
190
+ }
191
+ return bestId;
192
+ }
193
+ /** Search a single layer, returning ef closest candidates. */
194
+ searchLayer(startId, query, ef, layer) {
195
+ const visited = new Set([startId]);
196
+ const startNode = this.nodes.get(startId);
197
+ /* v8 ignore start -- defensive: startId always valid */
198
+ if (!startNode) {
199
+ return [];
200
+ }
201
+ /* v8 ignore stop */
202
+ const candidates = [
203
+ { id: startId, similarity: cosineSimilarity(query, startNode.vector) },
204
+ ];
205
+ const queue = [startId];
206
+ while (queue.length > 0) {
207
+ const currentId = queue.shift();
208
+ /* v8 ignore start -- defensive: queue checked non-empty */
209
+ if (!currentId) {
210
+ continue;
211
+ }
212
+ /* v8 ignore stop */
213
+ const current = this.nodes.get(currentId);
214
+ /* v8 ignore start -- defensive: currentId always valid */
215
+ if (!current || layer >= current.layers.length) {
216
+ continue;
217
+ }
218
+ /* v8 ignore stop */
219
+ const neighbors = current.layers[layer];
220
+ /* v8 ignore start -- defensive: layer within bounds */
221
+ if (!neighbors) {
222
+ continue;
223
+ }
224
+ /* v8 ignore stop */
225
+ for (const neighborId of neighbors.keys()) {
226
+ if (visited.has(neighborId)) {
227
+ continue;
228
+ }
229
+ visited.add(neighborId);
230
+ const neighbor = this.nodes.get(neighborId);
231
+ /* v8 ignore start -- defensive: neighbor always in graph */
232
+ if (!neighbor) {
233
+ continue;
234
+ }
235
+ /* v8 ignore stop */
236
+ const sim = cosineSimilarity(query, neighbor.vector);
237
+ candidates.push({ id: neighborId, similarity: sim });
238
+ queue.push(neighborId);
239
+ // Keep candidate list bounded
240
+ /* v8 ignore start -- requires corpus > ef*2 neighbors from a single node */
241
+ if (candidates.length > ef * 2) {
242
+ candidates.sort((a, b) => b.similarity - a.similarity);
243
+ candidates.length = ef;
244
+ }
245
+ /* v8 ignore stop */
246
+ }
247
+ }
248
+ candidates.sort((a, b) => b.similarity - a.similarity);
249
+ return candidates.slice(0, ef);
250
+ }
251
+ /** Prune connections to keep at most M neighbors. */
252
+ pruneConnections(node, layer) {
253
+ const layerMap = node.layers[layer];
254
+ /* v8 ignore start -- defensive: layer always valid when called */
255
+ if (!layerMap) {
256
+ return;
257
+ }
258
+ /* v8 ignore stop */
259
+ const entries = [...layerMap.entries()].sort((a, b) => b[1] - a[1]);
260
+ layerMap.clear();
261
+ for (const [id, sim] of entries.slice(0, this.config.M)) {
262
+ layerMap.set(id, sim);
263
+ }
264
+ }
265
+ /** Random level for a new node (geometric distribution). */
266
+ randomLevel() {
267
+ const ml = 1 / Math.log(this.config.M);
268
+ let level = 0;
269
+ while (Math.random() < ml && level < 16) {
270
+ level++;
271
+ }
272
+ return level;
273
+ }
274
+ /** Export the index for serialization. */
275
+ exportState() {
276
+ const nodes = [...this.nodes.values()].map((n) => ({
277
+ id: n.id,
278
+ vector: n.vector,
279
+ layers: n.layers.map((l) => [...l.entries()]),
280
+ }));
281
+ return { nodes, entryPoint: this.entryPoint, maxLayer: this.maxLayer };
282
+ }
283
+ /** Import the index from serialized form. */
284
+ importState(state) {
285
+ this.nodes.clear();
286
+ for (const n of state.nodes) {
287
+ const layers = n.layers.map((l) => new Map(l));
288
+ this.nodes.set(n.id, { id: n.id, vector: n.vector, layers });
289
+ }
290
+ this.entryPoint = state.entryPoint;
291
+ this.maxLayer = state.maxLayer;
292
+ }
293
+ }
294
+ //# sourceMappingURL=hnsw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hnsw.js","sourceRoot":"","sources":["../../../src/engine/vector-store/hnsw.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Compute cosine similarity between two vectors.
3
+ * Returns a value in [0, 1] where 1 means identical direction.
4
+ */
5
+ export declare function cosineSimilarity(a: number[], b: number[]): number;
6
+ /**
7
+ * Compute Jaccard similarity between two binary-ish vectors.
8
+ * Treats non-zero values as "present". Returns value in [0, 1].
9
+ */
10
+ export declare function jaccardSimilarity(a: number[], b: number[]): number;
11
+ /**
12
+ * Combined similarity: weighted average of cosine and jaccard.
13
+ * Default weights: 0.8 cosine + 0.2 jaccard.
14
+ */
15
+ export declare function combinedSimilarity(a: number[], b: number[], cosineWeight?: number): number;
16
+ /**
17
+ * Normalize a vector to unit length (L2 norm).
18
+ * Returns a new array. If the vector is zero, returns a zero vector.
19
+ */
20
+ export declare function normalizeVector(v: number[]): number[];
21
+ //# sourceMappingURL=similarity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../../src/engine/vector-store/similarity.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CA2BjE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CA4BlE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,YAAY,SAAM,GAAG,MAAM,CAIvF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAUrD"}
@@ -0,0 +1,86 @@
1
+ // engine/vector-store/similarity.ts — Similarity metrics for vector comparison.
2
+ // SPEC-075: cosine, jaccard, combined similarity functions.
3
+ /**
4
+ * Compute cosine similarity between two vectors.
5
+ * Returns a value in [0, 1] where 1 means identical direction.
6
+ */
7
+ export function cosineSimilarity(a, b) {
8
+ if (a.length === 0 || b.length === 0) {
9
+ return 0;
10
+ }
11
+ if (a.length !== b.length) {
12
+ return 0;
13
+ }
14
+ let dot = 0;
15
+ let normA = 0;
16
+ let normB = 0;
17
+ for (let i = 0; i < a.length; i++) {
18
+ /* v8 ignore start -- noUncheckedIndexedAccess: i always within bounds */
19
+ const ai = a[i] ?? 0;
20
+ const bi = b[i] ?? 0;
21
+ /* v8 ignore stop */
22
+ dot += ai * bi;
23
+ normA += ai * ai;
24
+ normB += bi * bi;
25
+ }
26
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
27
+ if (denom === 0) {
28
+ return 0;
29
+ }
30
+ return dot / denom;
31
+ }
32
+ /**
33
+ * Compute Jaccard similarity between two binary-ish vectors.
34
+ * Treats non-zero values as "present". Returns value in [0, 1].
35
+ */
36
+ export function jaccardSimilarity(a, b) {
37
+ if (a.length === 0 || b.length === 0) {
38
+ return 0;
39
+ }
40
+ if (a.length !== b.length) {
41
+ return 0;
42
+ }
43
+ let intersection = 0;
44
+ let union = 0;
45
+ for (let i = 0; i < a.length; i++) {
46
+ /* v8 ignore start -- noUncheckedIndexedAccess: i always within bounds */
47
+ const aPresent = (a[i] ?? 0) !== 0;
48
+ const bPresent = (b[i] ?? 0) !== 0;
49
+ /* v8 ignore stop */
50
+ if (aPresent || bPresent) {
51
+ union++;
52
+ if (aPresent && bPresent) {
53
+ intersection++;
54
+ }
55
+ }
56
+ }
57
+ if (union === 0) {
58
+ return 0;
59
+ }
60
+ return intersection / union;
61
+ }
62
+ /**
63
+ * Combined similarity: weighted average of cosine and jaccard.
64
+ * Default weights: 0.8 cosine + 0.2 jaccard.
65
+ */
66
+ export function combinedSimilarity(a, b, cosineWeight = 0.8) {
67
+ const cos = cosineSimilarity(a, b);
68
+ const jac = jaccardSimilarity(a, b);
69
+ return cos * cosineWeight + jac * (1 - cosineWeight);
70
+ }
71
+ /**
72
+ * Normalize a vector to unit length (L2 norm).
73
+ * Returns a new array. If the vector is zero, returns a zero vector.
74
+ */
75
+ export function normalizeVector(v) {
76
+ let norm = 0;
77
+ for (const val of v) {
78
+ norm += val * val;
79
+ }
80
+ norm = Math.sqrt(norm);
81
+ if (norm === 0) {
82
+ return v.map(() => 0);
83
+ }
84
+ return v.map((val) => val / norm);
85
+ }
86
+ //# sourceMappingURL=similarity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.js","sourceRoot":"","sources":["../../../src/engine/vector-store/similarity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { TFIDFConfig } from '../../types/index.js';
2
+ /** Tokenize text: split on whitespace/punctuation, split camelCase, lowercase, remove stop words. */
3
+ export declare function tokenize(text: string, stopWords?: Set<string>): string[];
4
+ /** TF-IDF engine: stateful, maintains vocabulary (IDF) across documents. */
5
+ export declare class TFIDFEngine {
6
+ private readonly config;
7
+ private readonly docFreq;
8
+ private docCount;
9
+ private vocabulary;
10
+ private vocabDirty;
11
+ constructor(config?: Partial<TFIDFConfig>);
12
+ /** Add a document to the corpus (updates IDF). */
13
+ addDocument(text: string): void;
14
+ /** Rebuild vocabulary: top-K most discriminating terms by IDF. */
15
+ private rebuildVocabulary;
16
+ /** Generate a normalized TF-IDF embedding for the given text. */
17
+ embed(text: string): number[];
18
+ /** Batch embed multiple texts. */
19
+ batchEmbed(texts: string[]): number[][];
20
+ /** Get current vocabulary size. */
21
+ getVocabularySize(): number;
22
+ /** Get document count in corpus. */
23
+ getDocumentCount(): number;
24
+ /** Export state for serialization. */
25
+ exportState(): {
26
+ docFreq: [string, number][];
27
+ docCount: number;
28
+ };
29
+ /** Import state from serialized form. */
30
+ importState(state: {
31
+ docFreq: [string, number][];
32
+ docCount: number;
33
+ }): void;
34
+ }
35
+ //# sourceMappingURL=tfidf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tfidf.d.ts","sourceRoot":"","sources":["../../../src/engine/vector-store/tfidf.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAwJxD,qGAAqG;AACrG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,GAAG,CAAC,MAAM,CAAsB,GAAG,MAAM,EAAE,CAS5F;AAED,4EAA4E;AAC5E,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,UAAU,CAAQ;gBAEd,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAQzC,kDAAkD;IAClD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAU/B,kEAAkE;IAClE,OAAO,CAAC,iBAAiB;IAiBzB,iEAAiE;IACjE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IA0B7B,kCAAkC;IAClC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,EAAE;IAIvC,mCAAmC;IACnC,iBAAiB,IAAI,MAAM;IAK3B,oCAAoC;IACpC,gBAAgB,IAAI,MAAM;IAI1B,sCAAsC;IACtC,WAAW,IAAI;QAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAOhE,yCAAyC;IACzC,WAAW,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAQ5E"}