agent-nuvira 1.14.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 (379) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +891 -0
  3. package/dist/agent-sdk/src/agent.d.ts +118 -0
  4. package/dist/agent-sdk/src/agent.d.ts.map +1 -0
  5. package/dist/agent-sdk/src/agent.js +88 -0
  6. package/dist/agent-sdk/src/agent.js.map +1 -0
  7. package/dist/agent-sdk/src/index.d.ts +33 -0
  8. package/dist/agent-sdk/src/index.d.ts.map +1 -0
  9. package/dist/agent-sdk/src/index.js +32 -0
  10. package/dist/agent-sdk/src/index.js.map +1 -0
  11. package/dist/agent-sdk/src/register.d.ts +70 -0
  12. package/dist/agent-sdk/src/register.d.ts.map +1 -0
  13. package/dist/agent-sdk/src/register.js +181 -0
  14. package/dist/agent-sdk/src/register.js.map +1 -0
  15. package/dist/agent-sdk/src/scaffold.d.ts +50 -0
  16. package/dist/agent-sdk/src/scaffold.d.ts.map +1 -0
  17. package/dist/agent-sdk/src/scaffold.js +291 -0
  18. package/dist/agent-sdk/src/scaffold.js.map +1 -0
  19. package/dist/agent-sdk/src/testing.d.ts +187 -0
  20. package/dist/agent-sdk/src/testing.d.ts.map +1 -0
  21. package/dist/agent-sdk/src/testing.js +243 -0
  22. package/dist/agent-sdk/src/testing.js.map +1 -0
  23. package/dist/agent-sdk/src/types.d.ts +202 -0
  24. package/dist/agent-sdk/src/types.d.ts.map +1 -0
  25. package/dist/agent-sdk/src/types.js +11 -0
  26. package/dist/agent-sdk/src/types.js.map +1 -0
  27. package/dist/agents/agent.d.ts +132 -0
  28. package/dist/agents/agent.d.ts.map +1 -0
  29. package/dist/agents/agent.js +19 -0
  30. package/dist/agents/agent.js.map +1 -0
  31. package/dist/agents/agents/context-gatherer.d.ts +42 -0
  32. package/dist/agents/agents/context-gatherer.d.ts.map +1 -0
  33. package/dist/agents/agents/context-gatherer.js +366 -0
  34. package/dist/agents/agents/context-gatherer.js.map +1 -0
  35. package/dist/agents/agents/debugger.d.ts +58 -0
  36. package/dist/agents/agents/debugger.d.ts.map +1 -0
  37. package/dist/agents/agents/debugger.js +257 -0
  38. package/dist/agents/agents/debugger.js.map +1 -0
  39. package/dist/agents/agents/git-agent.d.ts +34 -0
  40. package/dist/agents/agents/git-agent.d.ts.map +1 -0
  41. package/dist/agents/agents/git-agent.js +200 -0
  42. package/dist/agents/agents/git-agent.js.map +1 -0
  43. package/dist/agents/agents/github-release-agent.d.ts +65 -0
  44. package/dist/agents/agents/github-release-agent.d.ts.map +1 -0
  45. package/dist/agents/agents/github-release-agent.js +439 -0
  46. package/dist/agents/agents/github-release-agent.js.map +1 -0
  47. package/dist/agents/agents/package-agent.d.ts +33 -0
  48. package/dist/agents/agents/package-agent.d.ts.map +1 -0
  49. package/dist/agents/agents/package-agent.js +233 -0
  50. package/dist/agents/agents/package-agent.js.map +1 -0
  51. package/dist/agents/agents/planner.d.ts +26 -0
  52. package/dist/agents/agents/planner.d.ts.map +1 -0
  53. package/dist/agents/agents/planner.js +222 -0
  54. package/dist/agents/agents/planner.js.map +1 -0
  55. package/dist/agents/agents/reviewer.d.ts +34 -0
  56. package/dist/agents/agents/reviewer.d.ts.map +1 -0
  57. package/dist/agents/agents/reviewer.js +159 -0
  58. package/dist/agents/agents/reviewer.js.map +1 -0
  59. package/dist/agents/agents/runner.d.ts +73 -0
  60. package/dist/agents/agents/runner.d.ts.map +1 -0
  61. package/dist/agents/agents/runner.js +299 -0
  62. package/dist/agents/agents/runner.js.map +1 -0
  63. package/dist/agents/agents/security-agent.d.ts +33 -0
  64. package/dist/agents/agents/security-agent.d.ts.map +1 -0
  65. package/dist/agents/agents/security-agent.js +184 -0
  66. package/dist/agents/agents/security-agent.js.map +1 -0
  67. package/dist/agents/agents/tester.d.ts +96 -0
  68. package/dist/agents/agents/tester.d.ts.map +1 -0
  69. package/dist/agents/agents/tester.js +410 -0
  70. package/dist/agents/agents/tester.js.map +1 -0
  71. package/dist/agents/agents/writer.d.ts +51 -0
  72. package/dist/agents/agents/writer.d.ts.map +1 -0
  73. package/dist/agents/agents/writer.js +384 -0
  74. package/dist/agents/agents/writer.js.map +1 -0
  75. package/dist/agents/context-vault.d.ts +49 -0
  76. package/dist/agents/context-vault.d.ts.map +1 -0
  77. package/dist/agents/context-vault.js +134 -0
  78. package/dist/agents/context-vault.js.map +1 -0
  79. package/dist/agents/orchestrator.d.ts +97 -0
  80. package/dist/agents/orchestrator.d.ts.map +1 -0
  81. package/dist/agents/orchestrator.js +696 -0
  82. package/dist/agents/orchestrator.js.map +1 -0
  83. package/dist/agents/utils/file-tree.d.ts +28 -0
  84. package/dist/agents/utils/file-tree.d.ts.map +1 -0
  85. package/dist/agents/utils/file-tree.js +93 -0
  86. package/dist/agents/utils/file-tree.js.map +1 -0
  87. package/dist/cli/agent.d.ts +25 -0
  88. package/dist/cli/agent.d.ts.map +1 -0
  89. package/dist/cli/agent.js +374 -0
  90. package/dist/cli/agent.js.map +1 -0
  91. package/dist/cli/benchmark.d.ts +24 -0
  92. package/dist/cli/benchmark.d.ts.map +1 -0
  93. package/dist/cli/benchmark.js +235 -0
  94. package/dist/cli/benchmark.js.map +1 -0
  95. package/dist/cli/cache.d.ts +12 -0
  96. package/dist/cli/cache.d.ts.map +1 -0
  97. package/dist/cli/cache.js +58 -0
  98. package/dist/cli/cache.js.map +1 -0
  99. package/dist/cli/chat.d.ts +37 -0
  100. package/dist/cli/chat.d.ts.map +1 -0
  101. package/dist/cli/chat.js +393 -0
  102. package/dist/cli/chat.js.map +1 -0
  103. package/dist/cli/commands.d.ts +24 -0
  104. package/dist/cli/commands.d.ts.map +1 -0
  105. package/dist/cli/commands.js +18 -0
  106. package/dist/cli/commands.js.map +1 -0
  107. package/dist/cli/config.d.ts +19 -0
  108. package/dist/cli/config.d.ts.map +1 -0
  109. package/dist/cli/config.js +162 -0
  110. package/dist/cli/config.js.map +1 -0
  111. package/dist/cli/dashboard.d.ts +34 -0
  112. package/dist/cli/dashboard.d.ts.map +1 -0
  113. package/dist/cli/dashboard.js +126 -0
  114. package/dist/cli/dashboard.js.map +1 -0
  115. package/dist/cli/doctor.d.ts +68 -0
  116. package/dist/cli/doctor.d.ts.map +1 -0
  117. package/dist/cli/doctor.js +585 -0
  118. package/dist/cli/doctor.js.map +1 -0
  119. package/dist/cli/edit.d.ts +11 -0
  120. package/dist/cli/edit.d.ts.map +1 -0
  121. package/dist/cli/edit.js +86 -0
  122. package/dist/cli/edit.js.map +1 -0
  123. package/dist/cli/execute.d.ts +25 -0
  124. package/dist/cli/execute.d.ts.map +1 -0
  125. package/dist/cli/execute.js +186 -0
  126. package/dist/cli/execute.js.map +1 -0
  127. package/dist/cli/federation.d.ts +31 -0
  128. package/dist/cli/federation.d.ts.map +1 -0
  129. package/dist/cli/federation.js +387 -0
  130. package/dist/cli/federation.js.map +1 -0
  131. package/dist/cli/history.d.ts +22 -0
  132. package/dist/cli/history.d.ts.map +1 -0
  133. package/dist/cli/history.js +140 -0
  134. package/dist/cli/history.js.map +1 -0
  135. package/dist/cli/init.d.ts +49 -0
  136. package/dist/cli/init.d.ts.map +1 -0
  137. package/dist/cli/init.js +423 -0
  138. package/dist/cli/init.js.map +1 -0
  139. package/dist/cli/learn.d.ts +31 -0
  140. package/dist/cli/learn.d.ts.map +1 -0
  141. package/dist/cli/learn.js +320 -0
  142. package/dist/cli/learn.js.map +1 -0
  143. package/dist/cli/memory.d.ts +38 -0
  144. package/dist/cli/memory.d.ts.map +1 -0
  145. package/dist/cli/memory.js +295 -0
  146. package/dist/cli/memory.js.map +1 -0
  147. package/dist/cli/model-picker.d.ts +18 -0
  148. package/dist/cli/model-picker.d.ts.map +1 -0
  149. package/dist/cli/model-picker.js +225 -0
  150. package/dist/cli/model-picker.js.map +1 -0
  151. package/dist/cli/models.d.ts +11 -0
  152. package/dist/cli/models.d.ts.map +1 -0
  153. package/dist/cli/models.js +132 -0
  154. package/dist/cli/models.js.map +1 -0
  155. package/dist/cli/plan.d.ts +11 -0
  156. package/dist/cli/plan.d.ts.map +1 -0
  157. package/dist/cli/plan.js +94 -0
  158. package/dist/cli/plan.js.map +1 -0
  159. package/dist/cli/plugins.d.ts +15 -0
  160. package/dist/cli/plugins.d.ts.map +1 -0
  161. package/dist/cli/plugins.js +123 -0
  162. package/dist/cli/plugins.js.map +1 -0
  163. package/dist/cli/router.d.ts +20 -0
  164. package/dist/cli/router.d.ts.map +1 -0
  165. package/dist/cli/router.js +142 -0
  166. package/dist/cli/router.js.map +1 -0
  167. package/dist/cli/run.d.ts +22 -0
  168. package/dist/cli/run.d.ts.map +1 -0
  169. package/dist/cli/run.js +110 -0
  170. package/dist/cli/run.js.map +1 -0
  171. package/dist/cli/sandbox.d.ts +27 -0
  172. package/dist/cli/sandbox.d.ts.map +1 -0
  173. package/dist/cli/sandbox.js +264 -0
  174. package/dist/cli/sandbox.js.map +1 -0
  175. package/dist/cli/sdk.d.ts +27 -0
  176. package/dist/cli/sdk.d.ts.map +1 -0
  177. package/dist/cli/sdk.js +204 -0
  178. package/dist/cli/sdk.js.map +1 -0
  179. package/dist/cli/stats.d.ts +18 -0
  180. package/dist/cli/stats.d.ts.map +1 -0
  181. package/dist/cli/stats.js +78 -0
  182. package/dist/cli/stats.js.map +1 -0
  183. package/dist/cli/team.d.ts +42 -0
  184. package/dist/cli/team.d.ts.map +1 -0
  185. package/dist/cli/team.js +473 -0
  186. package/dist/cli/team.js.map +1 -0
  187. package/dist/cli/workflow.d.ts +27 -0
  188. package/dist/cli/workflow.d.ts.map +1 -0
  189. package/dist/cli/workflow.js +347 -0
  190. package/dist/cli/workflow.js.map +1 -0
  191. package/dist/config/manager.d.ts +37 -0
  192. package/dist/config/manager.d.ts.map +1 -0
  193. package/dist/config/manager.js +147 -0
  194. package/dist/config/manager.js.map +1 -0
  195. package/dist/config/types.d.ts +53 -0
  196. package/dist/config/types.d.ts.map +1 -0
  197. package/dist/config/types.js +2 -0
  198. package/dist/config/types.js.map +1 -0
  199. package/dist/context/cache.d.ts +27 -0
  200. package/dist/context/cache.d.ts.map +1 -0
  201. package/dist/context/cache.js +116 -0
  202. package/dist/context/cache.js.map +1 -0
  203. package/dist/context/history.d.ts +87 -0
  204. package/dist/context/history.d.ts.map +1 -0
  205. package/dist/context/history.js +249 -0
  206. package/dist/context/history.js.map +1 -0
  207. package/dist/context/parser.d.ts +61 -0
  208. package/dist/context/parser.d.ts.map +1 -0
  209. package/dist/context/parser.js +194 -0
  210. package/dist/context/parser.js.map +1 -0
  211. package/dist/federation/client.d.ts +49 -0
  212. package/dist/federation/client.d.ts.map +1 -0
  213. package/dist/federation/client.js +239 -0
  214. package/dist/federation/client.js.map +1 -0
  215. package/dist/federation/protocol.d.ts +155 -0
  216. package/dist/federation/protocol.d.ts.map +1 -0
  217. package/dist/federation/protocol.js +57 -0
  218. package/dist/federation/protocol.js.map +1 -0
  219. package/dist/federation/server.d.ts +25 -0
  220. package/dist/federation/server.d.ts.map +1 -0
  221. package/dist/federation/server.js +401 -0
  222. package/dist/federation/server.js.map +1 -0
  223. package/dist/index.d.ts +67 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +93 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/inference/factory.d.ts +20 -0
  228. package/dist/inference/factory.d.ts.map +1 -0
  229. package/dist/inference/factory.js +46 -0
  230. package/dist/inference/factory.js.map +1 -0
  231. package/dist/inference/gemini-adapter.d.ts +17 -0
  232. package/dist/inference/gemini-adapter.d.ts.map +1 -0
  233. package/dist/inference/gemini-adapter.js +176 -0
  234. package/dist/inference/gemini-adapter.js.map +1 -0
  235. package/dist/inference/groq-adapter.d.ts +17 -0
  236. package/dist/inference/groq-adapter.d.ts.map +1 -0
  237. package/dist/inference/groq-adapter.js +103 -0
  238. package/dist/inference/groq-adapter.js.map +1 -0
  239. package/dist/inference/interface.d.ts +49 -0
  240. package/dist/inference/interface.d.ts.map +1 -0
  241. package/dist/inference/interface.js +2 -0
  242. package/dist/inference/interface.js.map +1 -0
  243. package/dist/inference/local-adapter.d.ts +35 -0
  244. package/dist/inference/local-adapter.d.ts.map +1 -0
  245. package/dist/inference/local-adapter.js +311 -0
  246. package/dist/inference/local-adapter.js.map +1 -0
  247. package/dist/inference/model-catalog.d.ts +53 -0
  248. package/dist/inference/model-catalog.d.ts.map +1 -0
  249. package/dist/inference/model-catalog.js +306 -0
  250. package/dist/inference/model-catalog.js.map +1 -0
  251. package/dist/inference/nim-adapter.d.ts +17 -0
  252. package/dist/inference/nim-adapter.d.ts.map +1 -0
  253. package/dist/inference/nim-adapter.js +103 -0
  254. package/dist/inference/nim-adapter.js.map +1 -0
  255. package/dist/inference/openrouter-adapter.d.ts +17 -0
  256. package/dist/inference/openrouter-adapter.d.ts.map +1 -0
  257. package/dist/inference/openrouter-adapter.js +105 -0
  258. package/dist/inference/openrouter-adapter.js.map +1 -0
  259. package/dist/inference/sse.d.ts +20 -0
  260. package/dist/inference/sse.d.ts.map +1 -0
  261. package/dist/inference/sse.js +91 -0
  262. package/dist/inference/sse.js.map +1 -0
  263. package/dist/learning/agent-stats.d.ts +109 -0
  264. package/dist/learning/agent-stats.d.ts.map +1 -0
  265. package/dist/learning/agent-stats.js +240 -0
  266. package/dist/learning/agent-stats.js.map +1 -0
  267. package/dist/learning/benchmark.d.ts +161 -0
  268. package/dist/learning/benchmark.d.ts.map +1 -0
  269. package/dist/learning/benchmark.js +589 -0
  270. package/dist/learning/benchmark.js.map +1 -0
  271. package/dist/learning/cost-tracker.d.ts +101 -0
  272. package/dist/learning/cost-tracker.d.ts.map +1 -0
  273. package/dist/learning/cost-tracker.js +224 -0
  274. package/dist/learning/cost-tracker.js.map +1 -0
  275. package/dist/learning/feedback.d.ts +88 -0
  276. package/dist/learning/feedback.d.ts.map +1 -0
  277. package/dist/learning/feedback.js +169 -0
  278. package/dist/learning/feedback.js.map +1 -0
  279. package/dist/learning/hybrid-router.d.ts +201 -0
  280. package/dist/learning/hybrid-router.d.ts.map +1 -0
  281. package/dist/learning/hybrid-router.js +450 -0
  282. package/dist/learning/hybrid-router.js.map +1 -0
  283. package/dist/learning/model-compare.d.ts +76 -0
  284. package/dist/learning/model-compare.d.ts.map +1 -0
  285. package/dist/learning/model-compare.js +252 -0
  286. package/dist/learning/model-compare.js.map +1 -0
  287. package/dist/learning/model-router.d.ts +68 -0
  288. package/dist/learning/model-router.d.ts.map +1 -0
  289. package/dist/learning/model-router.js +140 -0
  290. package/dist/learning/model-router.js.map +1 -0
  291. package/dist/learning/pattern-extractor.d.ts +99 -0
  292. package/dist/learning/pattern-extractor.d.ts.map +1 -0
  293. package/dist/learning/pattern-extractor.js +310 -0
  294. package/dist/learning/pattern-extractor.js.map +1 -0
  295. package/dist/learning/scorer.d.ts +51 -0
  296. package/dist/learning/scorer.d.ts.map +1 -0
  297. package/dist/learning/scorer.js +64 -0
  298. package/dist/learning/scorer.js.map +1 -0
  299. package/dist/learning/self-improver.d.ts +48 -0
  300. package/dist/learning/self-improver.d.ts.map +1 -0
  301. package/dist/learning/self-improver.js +161 -0
  302. package/dist/learning/self-improver.js.map +1 -0
  303. package/dist/memory/embedder.d.ts +65 -0
  304. package/dist/memory/embedder.d.ts.map +1 -0
  305. package/dist/memory/embedder.js +424 -0
  306. package/dist/memory/embedder.js.map +1 -0
  307. package/dist/memory/memory-integration.d.ts +56 -0
  308. package/dist/memory/memory-integration.d.ts.map +1 -0
  309. package/dist/memory/memory-integration.js +95 -0
  310. package/dist/memory/memory-integration.js.map +1 -0
  311. package/dist/memory/trajectory-store.d.ts +149 -0
  312. package/dist/memory/trajectory-store.d.ts.map +1 -0
  313. package/dist/memory/trajectory-store.js +476 -0
  314. package/dist/memory/trajectory-store.js.map +1 -0
  315. package/dist/memory/vector-store.d.ts +78 -0
  316. package/dist/memory/vector-store.d.ts.map +1 -0
  317. package/dist/memory/vector-store.js +186 -0
  318. package/dist/memory/vector-store.js.map +1 -0
  319. package/dist/plugins/agent-plugin.d.ts +73 -0
  320. package/dist/plugins/agent-plugin.d.ts.map +1 -0
  321. package/dist/plugins/agent-plugin.js +199 -0
  322. package/dist/plugins/agent-plugin.js.map +1 -0
  323. package/dist/plugins/registry.d.ts +61 -0
  324. package/dist/plugins/registry.d.ts.map +1 -0
  325. package/dist/plugins/registry.js +67 -0
  326. package/dist/plugins/registry.js.map +1 -0
  327. package/dist/sandbox/images.d.ts +31 -0
  328. package/dist/sandbox/images.d.ts.map +1 -0
  329. package/dist/sandbox/images.js +129 -0
  330. package/dist/sandbox/images.js.map +1 -0
  331. package/dist/sandbox/manager.d.ts +134 -0
  332. package/dist/sandbox/manager.d.ts.map +1 -0
  333. package/dist/sandbox/manager.js +470 -0
  334. package/dist/sandbox/manager.js.map +1 -0
  335. package/dist/sandbox/types.d.ts +113 -0
  336. package/dist/sandbox/types.d.ts.map +1 -0
  337. package/dist/sandbox/types.js +107 -0
  338. package/dist/sandbox/types.js.map +1 -0
  339. package/dist/security/scanner.d.ts +53 -0
  340. package/dist/security/scanner.d.ts.map +1 -0
  341. package/dist/security/scanner.js +271 -0
  342. package/dist/security/scanner.js.map +1 -0
  343. package/dist/team/config.d.ts +50 -0
  344. package/dist/team/config.d.ts.map +1 -0
  345. package/dist/team/config.js +108 -0
  346. package/dist/team/config.js.map +1 -0
  347. package/dist/team/memory.d.ts +63 -0
  348. package/dist/team/memory.d.ts.map +1 -0
  349. package/dist/team/memory.js +282 -0
  350. package/dist/team/memory.js.map +1 -0
  351. package/dist/team/review.d.ts +123 -0
  352. package/dist/team/review.d.ts.map +1 -0
  353. package/dist/team/review.js +293 -0
  354. package/dist/team/review.js.map +1 -0
  355. package/dist/utils/env.d.ts +19 -0
  356. package/dist/utils/env.d.ts.map +1 -0
  357. package/dist/utils/env.js +250 -0
  358. package/dist/utils/env.js.map +1 -0
  359. package/dist/utils/logger.d.ts +11 -0
  360. package/dist/utils/logger.d.ts.map +1 -0
  361. package/dist/utils/logger.js +45 -0
  362. package/dist/utils/logger.js.map +1 -0
  363. package/dist/web-dashboard/server.d.ts +59 -0
  364. package/dist/web-dashboard/server.d.ts.map +1 -0
  365. package/dist/web-dashboard/server.js +418 -0
  366. package/dist/web-dashboard/server.js.map +1 -0
  367. package/dist/workflow/registry.d.ts +127 -0
  368. package/dist/workflow/registry.d.ts.map +1 -0
  369. package/dist/workflow/registry.js +482 -0
  370. package/dist/workflow/registry.js.map +1 -0
  371. package/dist/workflow/templates.d.ts +93 -0
  372. package/dist/workflow/templates.d.ts.map +1 -0
  373. package/dist/workflow/templates.js +481 -0
  374. package/dist/workflow/templates.js.map +1 -0
  375. package/package.json +78 -0
  376. package/src/web-dashboard/public/assets/index-B08nDkSB.css +1 -0
  377. package/src/web-dashboard/public/assets/index-BKL8YOFD.js +135 -0
  378. package/src/web-dashboard/public/assets/index-BKL8YOFD.js.map +1 -0
  379. package/src/web-dashboard/public/index.html +13 -0
@@ -0,0 +1,161 @@
1
+ /**
2
+ * SelfImprover — The self-improvement loop that ties together scoring,
3
+ * agent performance tracking, pattern extraction, and model optimization.
4
+ *
5
+ * After each orchestration run (when `useMemory: true`), the SelfImprover:
6
+ * 1. Scores the trajectory (how well did we do?)
7
+ * 2. Records per-agent stats (which agents/models succeed/fail?)
8
+ * 3. Periodically extracts patterns from high-scoring trajectories
9
+ * 4. Provides optimization recommendations (best models per agent)
10
+ *
11
+ * The SelfImprover is called by the Orchestrator post-execution hook.
12
+ * Users can also interact with it via the `buff learn` CLI commands.
13
+ */
14
+ import { getTrajectoryStore } from '../memory/trajectory-store.js';
15
+ import { getPatternStore } from './pattern-extractor.js';
16
+ import { getAgentStats } from './agent-stats.js';
17
+ import { scoreOrchestrationResult } from './scorer.js';
18
+ import { logger } from '../utils/logger.js';
19
+ // ─── Constants ──────────────────────────────────────────────────────────────
20
+ /** How many successful runs before auto-extracting patterns */
21
+ const PATTERN_EXTRACTION_INTERVAL = 5;
22
+ /** How many trajectories to pass for pattern extraction */
23
+ const TRAJECTORIES_FOR_EXTRACTION = 3;
24
+ /** Minimum score to consider a trajectory as "good" */
25
+ const GOOD_SCORE_THRESHOLD = 0.6;
26
+ // ─── SelfImprover ───────────────────────────────────────────────────────────
27
+ export class SelfImprover {
28
+ runCountSinceLastExtraction = 0;
29
+ /**
30
+ * Process a completed orchestration run through the self-improvement loop.
31
+ * Scores the result, tracks agent stats, and conditionally extracts patterns.
32
+ *
33
+ * @param result The completed orchestration result
34
+ * @param callLLM LLM function for pattern extraction
35
+ * @param agentModels The model map used for this run (for tracking model perf)
36
+ * @param verbose Whether to log details
37
+ */
38
+ async processRun(result, callLLM, agentModels, verbose = false) {
39
+ // Step 1: Score the trajectory
40
+ const score = scoreOrchestrationResult(result);
41
+ if (verbose) {
42
+ logger.info(` Self-improvement: trajectory score = ${(score * 100).toFixed(0)}%`);
43
+ }
44
+ // Step 2: Record per-agent stats
45
+ const stats = getAgentStats();
46
+ stats.recordRuns(result.agentResults, agentModels);
47
+ // Step 3: Conditionally extract patterns from good trajectories
48
+ if (score >= GOOD_SCORE_THRESHOLD) {
49
+ this.runCountSinceLastExtraction++;
50
+ if (this.runCountSinceLastExtraction >= PATTERN_EXTRACTION_INTERVAL) {
51
+ this.runCountSinceLastExtraction = 0;
52
+ if (verbose) {
53
+ logger.info(' Extracting coding patterns from successful trajectories...');
54
+ }
55
+ await this.extractPatterns(callLLM, verbose);
56
+ }
57
+ }
58
+ }
59
+ /**
60
+ * Force pattern extraction from the best trajectories in the store.
61
+ */
62
+ async extractPatterns(callLLM, verbose = false) {
63
+ try {
64
+ const store = getTrajectoryStore();
65
+ const allTrajectories = store.getAll();
66
+ // Get the highest-scoring trajectories
67
+ const best = allTrajectories
68
+ .filter((t) => t.score !== undefined)
69
+ .sort((a, b) => (b.score || 0) - (a.score || 0))
70
+ .slice(0, TRAJECTORIES_FOR_EXTRACTION);
71
+ if (best.length < 2) {
72
+ if (verbose) {
73
+ logger.info(' Not enough scored trajectories for pattern extraction');
74
+ }
75
+ return 0;
76
+ }
77
+ const patternStore = getPatternStore();
78
+ const count = await patternStore.extractFromTrajectories(best, callLLM);
79
+ if (verbose && count > 0) {
80
+ logger.success(` Extracted ${count} new pattern(s) from ${best.length} trajectories`);
81
+ }
82
+ return count;
83
+ }
84
+ catch (err) {
85
+ if (verbose) {
86
+ logger.debug(`Pattern extraction failed: ${err}`);
87
+ }
88
+ return 0;
89
+ }
90
+ }
91
+ /**
92
+ * Get optimization recommendations based on collected stats.
93
+ * Returns a recommended model map for the Orchestrator.
94
+ */
95
+ getOptimizedModelMap() {
96
+ const stats = getAgentStats();
97
+ const allAgents = stats.getAllAgents();
98
+ const modelMap = {};
99
+ for (const agentType of Object.keys(allAgents)) {
100
+ const bestModel = stats.getBestModel(agentType);
101
+ if (bestModel) {
102
+ modelMap[agentType] = bestModel;
103
+ }
104
+ }
105
+ return modelMap;
106
+ }
107
+ /**
108
+ * Get a human-readable summary of the self-improvement status.
109
+ */
110
+ getStatus() {
111
+ const stats = getAgentStats();
112
+ const patternStore = getPatternStore();
113
+ const patterns = patternStore.getAll();
114
+ const store = getTrajectoryStore();
115
+ const allTrajectories = store.getAll();
116
+ const lines = [
117
+ '🔄 Self-Improvement Status',
118
+ '',
119
+ '── Trajectories ──',
120
+ ` Total stored: ${allTrajectories.length}`,
121
+ ` Scored: ${allTrajectories.filter((t) => t.score !== undefined).length}`,
122
+ ` Avg score: ${this.averageScore(allTrajectories)}`,
123
+ '',
124
+ '── Patterns ──',
125
+ ` Total patterns: ${patterns.length}`,
126
+ ` Domains covered: ${[...new Set(patterns.flatMap((p) => p.applicableDomains))].join(', ') || 'none'}`,
127
+ '',
128
+ `── Performance ──`,
129
+ ` Total runs tracked: ${stats.getRaw().totalRuns}`,
130
+ ` Agents tracked: ${Object.keys(stats.getAllAgents()).length}`,
131
+ ];
132
+ lines.push('');
133
+ lines.push(stats.formatStats());
134
+ lines.push('');
135
+ lines.push(stats.formatModelRecommendations());
136
+ return lines.join('\n');
137
+ }
138
+ /**
139
+ * Reset extraction counter (called when user manually extracts patterns).
140
+ */
141
+ resetExtractionCounter() {
142
+ this.runCountSinceLastExtraction = 0;
143
+ }
144
+ // ── Private ────────────────────────────────────────────────────────────
145
+ averageScore(trajectories) {
146
+ const scored = trajectories.filter((t) => t.score !== undefined);
147
+ if (scored.length === 0)
148
+ return 'N/A';
149
+ const avg = scored.reduce((sum, t) => sum + (t.score || 0), 0) / scored.length;
150
+ return `${(avg * 100).toFixed(0)}%`;
151
+ }
152
+ }
153
+ // Singleton
154
+ let improverInstance = null;
155
+ export function getSelfImprover() {
156
+ if (!improverInstance) {
157
+ improverInstance = new SelfImprover();
158
+ }
159
+ return improverInstance;
160
+ }
161
+ //# sourceMappingURL=self-improver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-improver.js","sourceRoot":"","sources":["../../src/learning/self-improver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Embedder — Generates vector embeddings from text using a tiered approach.
3
+ *
4
+ * Embedding Tier Strategy:
5
+ * Tier 1: @huggingface/transformers (fast, local, 384-dim) — DEFAULT
6
+ * Tier 2: Python sentence-transformers via subprocess
7
+ * Tier 3: LLM-based (any configured InferenceProvider) — FALLBACK
8
+ *
9
+ * The embedder auto-selects the best available tier, caches results to avoid
10
+ * redundant computation, and gracefully degrades when tiers are unavailable.
11
+ *
12
+ * Dimensionality: 384 (all-MiniLM-L6-v2 default) — 6x more expressive than
13
+ * the previous 64-dim LLM-based embeddings while being 10x faster and free.
14
+ */
15
+ import type { LLMCallFn } from '../agents/agent.js';
16
+ /** Dimensionality of the generated embeddings (all-MiniLM-L6-v2 default) */
17
+ export declare const EMBEDDING_DIM = 384;
18
+ /**
19
+ * Generate a vector embedding for the given text.
20
+ *
21
+ * Uses a tiered approach:
22
+ * 1. @huggingface/transformers (fast local embeddings) — preferred
23
+ * 2. Python sentence-transformers via subprocess
24
+ * 3. LLM-based embedding (requires callLLM function) — fallback
25
+ *
26
+ * @param text The text to embed (e.g., a user goal or task description)
27
+ * @param callLLM Optional LLM call function (only needed for Tier 3 fallback)
28
+ * @param forceLLM If true, skip native tiers and use LLM directly (useful for testing)
29
+ * @returns A promise that resolves to a number[] embedding vector (384-dim)
30
+ */
31
+ export declare function embed(text: string, callLLM?: LLMCallFn, forceLLM?: boolean): Promise<number[]>;
32
+ /**
33
+ * Reset the tier availability cache.
34
+ * Call this when the environment changes (e.g., user installs a package)
35
+ * or in test setup to force re-detection.
36
+ */
37
+ export declare function resetEmbeddingTierCache(): void;
38
+ /**
39
+ * Set the force-LLM mode for testing.
40
+ * When called with force=true, all native embedding tiers are disabled
41
+ * and only the LLM-based fallback (Tier 3) is used.
42
+ */
43
+ export declare function setForceLLM(force: boolean): void;
44
+ /**
45
+ * Check if @huggingface/transformers is available.
46
+ * This is a lightweight check that doesn't load the model.
47
+ */
48
+ export declare function isXenovaAvailable(): Promise<boolean>;
49
+ /**
50
+ * Check if Python sentence-transformers is available.
51
+ */
52
+ export declare function isPythonAvailable(): Promise<boolean>;
53
+ /**
54
+ * Get the name of the currently active embedding tier.
55
+ */
56
+ export declare function getActiveEmbeddingTier(): Promise<string>;
57
+ /**
58
+ * Clear the in-memory embedding cache.
59
+ */
60
+ export declare function clearEmbeddingCache(): void;
61
+ /**
62
+ * Get the current size of the embedding cache.
63
+ */
64
+ export declare function embeddingCacheSize(): number;
65
+ //# sourceMappingURL=embedder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedder.d.ts","sourceRoot":"","sources":["../../src/memory/embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKpD,4EAA4E;AAC5E,eAAO,MAAM,aAAa,MAAM,CAAC;AAyEjC;;;;;;;;;;;;GAYG;AACH,wBAAsB,KAAK,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,SAAS,EACnB,QAAQ,CAAC,EAAE,OAAO,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiDnB;AAyND;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAQhD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAY1D;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAmB1D;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC,CAI9D;AAID;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
@@ -0,0 +1,424 @@
1
+ /**
2
+ * Embedder — Generates vector embeddings from text using a tiered approach.
3
+ *
4
+ * Embedding Tier Strategy:
5
+ * Tier 1: @huggingface/transformers (fast, local, 384-dim) — DEFAULT
6
+ * Tier 2: Python sentence-transformers via subprocess
7
+ * Tier 3: LLM-based (any configured InferenceProvider) — FALLBACK
8
+ *
9
+ * The embedder auto-selects the best available tier, caches results to avoid
10
+ * redundant computation, and gracefully degrades when tiers are unavailable.
11
+ *
12
+ * Dimensionality: 384 (all-MiniLM-L6-v2 default) — 6x more expressive than
13
+ * the previous 64-dim LLM-based embeddings while being 10x faster and free.
14
+ */
15
+ import { createHash } from 'node:crypto';
16
+ import { spawn } from 'node:child_process';
17
+ import { logger } from '../utils/logger.js';
18
+ // ─── Constants ──────────────────────────────────────────────────────────────
19
+ /** Dimensionality of the generated embeddings (all-MiniLM-L6-v2 default) */
20
+ export const EMBEDDING_DIM = 384;
21
+ /** Max text length for embedding (characters) */
22
+ const MAX_EMBEDDING_TEXT_LENGTH = 2000;
23
+ /** Default model for @huggingface/transformers */
24
+ const XENOVA_MODEL = 'Xenova/all-MiniLM-L6-v2';
25
+ /** LLM-based embedding system prompt (Tier 3 fallback) */
26
+ const EMBEDDING_PROMPT = `You are a semantic embedding generator. Given a piece of text, generate a dense vector representation that captures its semantic meaning.
27
+
28
+ Return ONLY a valid JSON array of ${EMBEDDING_DIM} floating-point numbers between -1 and 1.
29
+ No markdown, no explanations, no code blocks — just the raw JSON array.
30
+
31
+ The vector should encode:
32
+ - The main topic and domain (e.g., "authentication", "database", "CLI tool")
33
+ - The action being requested (e.g., "add", "fix", "refactor", "create")
34
+ - The technology stack or language if mentioned
35
+ - Key entities and concepts
36
+
37
+ Example output: [${Array(5).fill('0.0').join(', ')}, ...]`;
38
+ // ─── Tier Availability Cache ────────────────────────────────────────────────
39
+ let _xenovaAvailable = null;
40
+ let _pythonAvailable = null;
41
+ // ─── In-Memory Cache ────────────────────────────────────────────────────────
42
+ class EmbeddingCache {
43
+ cache = new Map();
44
+ maxSize;
45
+ constructor(maxSize = 200) {
46
+ this.maxSize = maxSize;
47
+ }
48
+ get(key) {
49
+ const value = this.cache.get(key);
50
+ if (value !== undefined) {
51
+ this.cache.delete(key);
52
+ this.cache.set(key, value);
53
+ }
54
+ return value;
55
+ }
56
+ set(key, value) {
57
+ if (this.cache.size >= this.maxSize) {
58
+ const firstKey = this.cache.keys().next().value;
59
+ if (firstKey !== undefined) {
60
+ this.cache.delete(firstKey);
61
+ }
62
+ }
63
+ this.cache.set(key, value);
64
+ }
65
+ get size() {
66
+ return this.cache.size;
67
+ }
68
+ clear() {
69
+ this.cache.clear();
70
+ }
71
+ }
72
+ const cache = new EmbeddingCache();
73
+ // ─── Embedder ───────────────────────────────────────────────────────────────
74
+ function cacheKey(text) {
75
+ return createHash('md5').update(text.toLowerCase().trim()).digest('hex');
76
+ }
77
+ /**
78
+ * Generate a vector embedding for the given text.
79
+ *
80
+ * Uses a tiered approach:
81
+ * 1. @huggingface/transformers (fast local embeddings) — preferred
82
+ * 2. Python sentence-transformers via subprocess
83
+ * 3. LLM-based embedding (requires callLLM function) — fallback
84
+ *
85
+ * @param text The text to embed (e.g., a user goal or task description)
86
+ * @param callLLM Optional LLM call function (only needed for Tier 3 fallback)
87
+ * @param forceLLM If true, skip native tiers and use LLM directly (useful for testing)
88
+ * @returns A promise that resolves to a number[] embedding vector (384-dim)
89
+ */
90
+ export async function embed(text, callLLM, forceLLM) {
91
+ const key = cacheKey(text);
92
+ // Check cache first
93
+ const cached = cache.get(key);
94
+ if (cached)
95
+ return cached;
96
+ const truncatedText = text.slice(0, MAX_EMBEDDING_TEXT_LENGTH);
97
+ // When forceLLM is true, skip native tiers and go directly to LLM
98
+ // This is useful in test environments where mock LLMs are used
99
+ if (!forceLLM) {
100
+ // Tier 1: @huggingface/transformers (fast, local, free)
101
+ try {
102
+ const vector = await embedWithXenova(truncatedText);
103
+ if (vector) {
104
+ cache.set(key, vector);
105
+ return vector;
106
+ }
107
+ }
108
+ catch (err) {
109
+ logger.debug(`Tier 1 embedding (Xenova) failed: ${err}`);
110
+ }
111
+ // Tier 2: Python sentence-transformers via subprocess
112
+ try {
113
+ const vector = await embedWithPython(truncatedText);
114
+ if (vector) {
115
+ cache.set(key, vector);
116
+ return vector;
117
+ }
118
+ }
119
+ catch (err) {
120
+ logger.debug(`Tier 2 embedding (Python) failed: ${err}`);
121
+ }
122
+ }
123
+ // Tier 3: LLM-based embedding (requires callLLM)
124
+ if (callLLM) {
125
+ try {
126
+ const vector = await embedWithLLM(truncatedText, callLLM);
127
+ cache.set(key, vector);
128
+ return vector;
129
+ }
130
+ catch (err) {
131
+ logger.debug(`Tier 3 embedding (LLM) failed: ${err}`);
132
+ }
133
+ }
134
+ // All tiers failed — return zero vector (no meaningful matches)
135
+ logger.debug('All embedding tiers failed, returning zero vector');
136
+ return new Array(EMBEDDING_DIM).fill(0);
137
+ }
138
+ // ─── Tier 1: @huggingface/transformers ──────────────────────────────────────
139
+ /**
140
+ * Generate embedding using @huggingface/transformers (Xenova).
141
+ * This is the fastest and most reliable tier — runs locally with ONNX runtime.
142
+ * Returns null if the library is not installed or model fails to load.
143
+ */
144
+ async function embedWithXenova(text) {
145
+ if (_xenovaAvailable === false)
146
+ return null;
147
+ try {
148
+ // Dynamic import — the package is optional (user may not have it installed)
149
+ const { pipeline } = await import('@huggingface/transformers');
150
+ // Use 'feature-extraction' pipeline with all-MiniLM-L6-v2
151
+ // This model produces 384-dimensional embeddings
152
+ const extractor = await pipeline('feature-extraction', XENOVA_MODEL);
153
+ const output = await extractor(text, {
154
+ pooling: 'mean',
155
+ normalize: true,
156
+ });
157
+ // Convert Tensor to plain JS array
158
+ const arr = output.tolist();
159
+ const vector = arr[0];
160
+ if (!vector || !Array.isArray(vector) || vector.length !== EMBEDDING_DIM) {
161
+ logger.debug(`Xenova embedding returned unexpected shape: ${vector?.length}`);
162
+ return null;
163
+ }
164
+ _xenovaAvailable = true;
165
+ return vector;
166
+ }
167
+ catch (err) {
168
+ _xenovaAvailable = false;
169
+ const msg = err instanceof Error ? err.message : String(err);
170
+ // Provide helpful messages for common issues
171
+ if (msg.includes('Cannot find package') || msg.includes('Cannot find module')) {
172
+ logger.debug('@huggingface/transformers not installed. Install with: npm install @huggingface/transformers');
173
+ }
174
+ else if (msg.includes('download')) {
175
+ logger.debug('Xenova model download failed. Will use fallback embedding.');
176
+ }
177
+ else {
178
+ logger.debug(`Xenova embedding error: ${msg}`);
179
+ }
180
+ return null;
181
+ }
182
+ }
183
+ // ─── Tier 2: Python sentence-transformers ───────────────────────────────────
184
+ /**
185
+ * Generate embedding using Python's sentence-transformers via subprocess.
186
+ * Second fallback — slower than Xenova but doesn't require npm package.
187
+ * Returns null if Python or sentence-transformers is not available.
188
+ */
189
+ async function embedWithPython(text) {
190
+ if (_pythonAvailable === false)
191
+ return null;
192
+ // Escape the text for safe embedding in Python script
193
+ const escapedText = text
194
+ .replace(/\\/g, '\\\\')
195
+ .replace(/'/g, "\\'")
196
+ .replace(/\n/g, '\\n')
197
+ .replace(/\r/g, '\\r');
198
+ const pythonScript = `
199
+ import sys, json
200
+ try:
201
+ from sentence_transformers import SentenceTransformer
202
+ model = SentenceTransformer('all-MiniLM-L6-v2')
203
+ embedding = model.encode('${escapedText}').tolist()
204
+ # Ensure 384 dimensions
205
+ while len(embedding) < ${EMBEDDING_DIM}:
206
+ embedding.append(0.0)
207
+ embedding = embedding[:${EMBEDDING_DIM}]
208
+ print(json.dumps({"embedding": embedding}))
209
+ except ImportError:
210
+ print(json.dumps({"error": "sentence-transformers not installed. Run: pip install sentence-transformers"}))
211
+ sys.exit(1)
212
+ except Exception as e:
213
+ print(json.dumps({"error": str(e)}))
214
+ sys.exit(1)
215
+ `;
216
+ return new Promise((resolve) => {
217
+ const python = spawn('python3', ['-c', pythonScript], {
218
+ stdio: ['pipe', 'pipe', 'pipe'],
219
+ timeout: 30000, // 30 second timeout
220
+ });
221
+ let output = '';
222
+ let errorOutput = '';
223
+ python.stdout?.on('data', (chunk) => {
224
+ output += chunk.toString();
225
+ });
226
+ python.stderr?.on('data', (chunk) => {
227
+ errorOutput += chunk.toString();
228
+ });
229
+ python.on('error', (err) => {
230
+ _pythonAvailable = false;
231
+ if (err.code === 'ENOENT') {
232
+ logger.debug('Python 3 not found. Install sentence-transformers with: pip install sentence-transformers');
233
+ }
234
+ else {
235
+ logger.debug(`Python subprocess error: ${err.message}`);
236
+ }
237
+ resolve(null);
238
+ });
239
+ python.on('close', (exitCode) => {
240
+ if (exitCode === 0) {
241
+ try {
242
+ const parsed = JSON.parse(output);
243
+ if (parsed.error) {
244
+ logger.debug(`Python embedding error: ${parsed.error}`);
245
+ _pythonAvailable = false;
246
+ resolve(null);
247
+ }
248
+ else if (Array.isArray(parsed.embedding) && parsed.embedding.length === EMBEDDING_DIM) {
249
+ _pythonAvailable = true;
250
+ resolve(parsed.embedding);
251
+ }
252
+ else {
253
+ resolve(null);
254
+ }
255
+ }
256
+ catch {
257
+ resolve(null);
258
+ }
259
+ }
260
+ else {
261
+ _pythonAvailable = false;
262
+ if (errorOutput)
263
+ logger.debug(`Python embedding stderr: ${errorOutput.slice(0, 200)}`);
264
+ resolve(null);
265
+ }
266
+ });
267
+ });
268
+ }
269
+ // ─── Tier 3: LLM-based embedding ────────────────────────────────────────────
270
+ /**
271
+ * Generate embedding using an LLM via the InferenceProvider.
272
+ * This is the slowest and most expensive tier — fallback only.
273
+ * Requires a callLLM function (provided by the Orchestrator).
274
+ */
275
+ async function embedWithLLM(text, callLLM) {
276
+ const prompt = `${EMBEDDING_PROMPT}\n\nText to embed:\n${text}`;
277
+ const response = await callLLM(prompt, {
278
+ temperature: 0.1,
279
+ maxTokens: 2048,
280
+ });
281
+ const vector = parseLLMEmbedding(response);
282
+ return vector;
283
+ }
284
+ /**
285
+ * Parse an embedding vector from the LLM's text response.
286
+ * Tries multiple strategies to extract a valid array of numbers.
287
+ */
288
+ function parseLLMEmbedding(response) {
289
+ const trimmed = response.trim();
290
+ // Strategy 1: Direct JSON parse
291
+ try {
292
+ const parsed = JSON.parse(trimmed);
293
+ if (isValidEmbedding(parsed))
294
+ return parsed;
295
+ }
296
+ catch {
297
+ // Fall through
298
+ }
299
+ // Strategy 2: Extract from ```json code block
300
+ const jsonMatch = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
301
+ if (jsonMatch) {
302
+ try {
303
+ const parsed = JSON.parse(jsonMatch[1].trim());
304
+ if (isValidEmbedding(parsed))
305
+ return parsed;
306
+ }
307
+ catch {
308
+ // Fall through
309
+ }
310
+ }
311
+ // Strategy 3: Find array pattern in text
312
+ const arrayMatch = trimmed.match(/\[[\s\S]*?\]/);
313
+ if (arrayMatch) {
314
+ try {
315
+ const parsed = JSON.parse(arrayMatch[0]);
316
+ if (isValidEmbedding(parsed))
317
+ return parsed;
318
+ }
319
+ catch {
320
+ // Fall through
321
+ }
322
+ }
323
+ // Fallback: return zero vector (no meaningful match)
324
+ logger.debug('Could not parse embedding from LLM response, using zero vector');
325
+ return new Array(EMBEDDING_DIM).fill(0);
326
+ }
327
+ /**
328
+ * Validate that a parsed value is a valid embedding vector.
329
+ */
330
+ function isValidEmbedding(value) {
331
+ if (!Array.isArray(value))
332
+ return false;
333
+ if (value.length !== EMBEDDING_DIM)
334
+ return false;
335
+ return value.every((v) => typeof v === 'number' && isFinite(v));
336
+ }
337
+ // ─── Detection Helpers ──────────────────────────────────────────────────────
338
+ /**
339
+ * Reset the tier availability cache.
340
+ * Call this when the environment changes (e.g., user installs a package)
341
+ * or in test setup to force re-detection.
342
+ */
343
+ export function resetEmbeddingTierCache() {
344
+ _xenovaAvailable = null;
345
+ _pythonAvailable = null;
346
+ }
347
+ /**
348
+ * Set the force-LLM mode for testing.
349
+ * When called with force=true, all native embedding tiers are disabled
350
+ * and only the LLM-based fallback (Tier 3) is used.
351
+ */
352
+ export function setForceLLM(force) {
353
+ if (force) {
354
+ _xenovaAvailable = false;
355
+ _pythonAvailable = false;
356
+ }
357
+ else {
358
+ _xenovaAvailable = null;
359
+ _pythonAvailable = null;
360
+ }
361
+ }
362
+ /**
363
+ * Check if @huggingface/transformers is available.
364
+ * This is a lightweight check that doesn't load the model.
365
+ */
366
+ export async function isXenovaAvailable() {
367
+ if (_xenovaAvailable !== null)
368
+ return _xenovaAvailable;
369
+ try {
370
+ // Try to resolve the package without loading it
371
+ await import('@huggingface/transformers');
372
+ _xenovaAvailable = true;
373
+ return true;
374
+ }
375
+ catch {
376
+ _xenovaAvailable = false;
377
+ return false;
378
+ }
379
+ }
380
+ /**
381
+ * Check if Python sentence-transformers is available.
382
+ */
383
+ export async function isPythonAvailable() {
384
+ if (_pythonAvailable !== null)
385
+ return _pythonAvailable;
386
+ return new Promise((resolve) => {
387
+ const python = spawn('python3', ['-c', 'from sentence_transformers import SentenceTransformer; print("ok")'], {
388
+ stdio: ['pipe', 'pipe', 'pipe'],
389
+ timeout: 10000,
390
+ });
391
+ python.on('close', (code) => {
392
+ _pythonAvailable = code === 0;
393
+ resolve(code === 0);
394
+ });
395
+ python.on('error', () => {
396
+ _pythonAvailable = false;
397
+ resolve(false);
398
+ });
399
+ });
400
+ }
401
+ /**
402
+ * Get the name of the currently active embedding tier.
403
+ */
404
+ export async function getActiveEmbeddingTier() {
405
+ if (await isXenovaAvailable())
406
+ return 'local (Xenova, 384-dim)';
407
+ if (await isPythonAvailable())
408
+ return 'python (sentence-transformers, 384-dim)';
409
+ return 'llm (fallback, 384-dim)';
410
+ }
411
+ // ─── Cache Management ───────────────────────────────────────────────────────
412
+ /**
413
+ * Clear the in-memory embedding cache.
414
+ */
415
+ export function clearEmbeddingCache() {
416
+ cache.clear();
417
+ }
418
+ /**
419
+ * Get the current size of the embedding cache.
420
+ */
421
+ export function embeddingCacheSize() {
422
+ return cache.size;
423
+ }
424
+ //# sourceMappingURL=embedder.js.map