cognitive-core 0.0.2 → 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 (329) hide show
  1. package/README.md +302 -116
  2. package/SKILL.md +193 -0
  3. package/dist/agents/index.d.ts +3 -0
  4. package/dist/agents/index.d.ts.map +1 -0
  5. package/dist/agents/index.js +5 -0
  6. package/dist/agents/index.js.map +1 -0
  7. package/dist/agents/mock-provider.d.ts +23 -0
  8. package/dist/agents/mock-provider.d.ts.map +1 -0
  9. package/dist/agents/mock-provider.js +71 -0
  10. package/dist/agents/mock-provider.js.map +1 -0
  11. package/dist/agents/types.d.ts +98 -0
  12. package/dist/agents/types.d.ts.map +1 -0
  13. package/dist/agents/types.js +44 -0
  14. package/dist/agents/types.js.map +1 -0
  15. package/dist/atlas.d.ts +196 -0
  16. package/dist/atlas.d.ts.map +1 -0
  17. package/dist/atlas.js +373 -0
  18. package/dist/atlas.js.map +1 -0
  19. package/dist/bin/cognitive-core.d.ts +18 -0
  20. package/dist/bin/cognitive-core.d.ts.map +1 -0
  21. package/dist/bin/cognitive-core.js +419 -0
  22. package/dist/bin/cognitive-core.js.map +1 -0
  23. package/dist/embeddings/bm25.d.ts +104 -0
  24. package/dist/embeddings/bm25.d.ts.map +1 -0
  25. package/dist/embeddings/bm25.js +264 -0
  26. package/dist/embeddings/bm25.js.map +1 -0
  27. package/dist/embeddings/index.d.ts +12 -0
  28. package/dist/embeddings/index.d.ts.map +1 -0
  29. package/dist/embeddings/index.js +16 -0
  30. package/dist/embeddings/index.js.map +1 -0
  31. package/dist/embeddings/manager.d.ts +112 -0
  32. package/dist/embeddings/manager.d.ts.map +1 -0
  33. package/dist/embeddings/manager.js +215 -0
  34. package/dist/embeddings/manager.js.map +1 -0
  35. package/dist/embeddings/provider.d.ts +101 -0
  36. package/dist/embeddings/provider.d.ts.map +1 -0
  37. package/dist/embeddings/provider.js +232 -0
  38. package/dist/embeddings/provider.js.map +1 -0
  39. package/dist/embeddings/vector-store.d.ts +101 -0
  40. package/dist/embeddings/vector-store.d.ts.map +1 -0
  41. package/dist/embeddings/vector-store.js +256 -0
  42. package/dist/embeddings/vector-store.js.map +1 -0
  43. package/dist/factory.d.ts +193 -0
  44. package/dist/factory.d.ts.map +1 -0
  45. package/dist/factory.js +109 -0
  46. package/dist/factory.js.map +1 -0
  47. package/dist/index.d.ts +30 -453
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +84 -509
  50. package/dist/index.js.map +1 -0
  51. package/dist/learning/analyzer.d.ts +110 -0
  52. package/dist/learning/analyzer.d.ts.map +1 -0
  53. package/dist/learning/analyzer.js +213 -0
  54. package/dist/learning/analyzer.js.map +1 -0
  55. package/dist/learning/effectiveness.d.ts +158 -0
  56. package/dist/learning/effectiveness.d.ts.map +1 -0
  57. package/dist/learning/effectiveness.js +251 -0
  58. package/dist/learning/effectiveness.js.map +1 -0
  59. package/dist/learning/index.d.ts +8 -0
  60. package/dist/learning/index.d.ts.map +1 -0
  61. package/dist/learning/index.js +11 -0
  62. package/dist/learning/index.js.map +1 -0
  63. package/dist/learning/llm-extractor.d.ts +88 -0
  64. package/dist/learning/llm-extractor.d.ts.map +1 -0
  65. package/dist/learning/llm-extractor.js +372 -0
  66. package/dist/learning/llm-extractor.js.map +1 -0
  67. package/dist/learning/meta-learner.d.ts +80 -0
  68. package/dist/learning/meta-learner.d.ts.map +1 -0
  69. package/dist/learning/meta-learner.js +355 -0
  70. package/dist/learning/meta-learner.js.map +1 -0
  71. package/dist/learning/pipeline.d.ts +65 -0
  72. package/dist/learning/pipeline.d.ts.map +1 -0
  73. package/dist/learning/pipeline.js +170 -0
  74. package/dist/learning/pipeline.js.map +1 -0
  75. package/dist/learning/playbook-extractor.d.ts +113 -0
  76. package/dist/learning/playbook-extractor.d.ts.map +1 -0
  77. package/dist/learning/playbook-extractor.js +523 -0
  78. package/dist/learning/playbook-extractor.js.map +1 -0
  79. package/dist/learning/usage-inference.d.ts +82 -0
  80. package/dist/learning/usage-inference.d.ts.map +1 -0
  81. package/dist/learning/usage-inference.js +261 -0
  82. package/dist/learning/usage-inference.js.map +1 -0
  83. package/dist/mcp/index.d.ts +6 -0
  84. package/dist/mcp/index.d.ts.map +1 -0
  85. package/dist/mcp/index.js +6 -0
  86. package/dist/mcp/index.js.map +1 -0
  87. package/dist/mcp/playbook-server.d.ts +120 -0
  88. package/dist/mcp/playbook-server.d.ts.map +1 -0
  89. package/dist/mcp/playbook-server.js +427 -0
  90. package/dist/mcp/playbook-server.js.map +1 -0
  91. package/dist/memory/curated-loader.d.ts +62 -0
  92. package/dist/memory/curated-loader.d.ts.map +1 -0
  93. package/dist/memory/curated-loader.js +106 -0
  94. package/dist/memory/curated-loader.js.map +1 -0
  95. package/dist/memory/experience.d.ts +122 -0
  96. package/dist/memory/experience.d.ts.map +1 -0
  97. package/dist/memory/experience.js +392 -0
  98. package/dist/memory/experience.js.map +1 -0
  99. package/dist/memory/index.d.ts +6 -0
  100. package/dist/memory/index.d.ts.map +1 -0
  101. package/dist/memory/index.js +9 -0
  102. package/dist/memory/index.js.map +1 -0
  103. package/dist/memory/meta.d.ts +90 -0
  104. package/dist/memory/meta.d.ts.map +1 -0
  105. package/dist/memory/meta.js +362 -0
  106. package/dist/memory/meta.js.map +1 -0
  107. package/dist/memory/playbook.d.ts +133 -0
  108. package/dist/memory/playbook.d.ts.map +1 -0
  109. package/dist/memory/playbook.js +357 -0
  110. package/dist/memory/playbook.js.map +1 -0
  111. package/dist/memory/system.d.ts +167 -0
  112. package/dist/memory/system.d.ts.map +1 -0
  113. package/dist/memory/system.js +383 -0
  114. package/dist/memory/system.js.map +1 -0
  115. package/dist/runtime/backends/acp.d.ts +67 -0
  116. package/dist/runtime/backends/acp.d.ts.map +1 -0
  117. package/dist/runtime/backends/acp.js +290 -0
  118. package/dist/runtime/backends/acp.js.map +1 -0
  119. package/dist/runtime/backends/index.d.ts +5 -0
  120. package/dist/runtime/backends/index.d.ts.map +1 -0
  121. package/dist/runtime/backends/index.js +6 -0
  122. package/dist/runtime/backends/index.js.map +1 -0
  123. package/dist/runtime/backends/mock.d.ts +67 -0
  124. package/dist/runtime/backends/mock.d.ts.map +1 -0
  125. package/dist/runtime/backends/mock.js +153 -0
  126. package/dist/runtime/backends/mock.js.map +1 -0
  127. package/dist/runtime/backends/subprocess.d.ts +56 -0
  128. package/dist/runtime/backends/subprocess.d.ts.map +1 -0
  129. package/dist/runtime/backends/subprocess.js +260 -0
  130. package/dist/runtime/backends/subprocess.js.map +1 -0
  131. package/dist/runtime/flows/learning.d.ts +73 -0
  132. package/dist/runtime/flows/learning.d.ts.map +1 -0
  133. package/dist/runtime/flows/learning.js +116 -0
  134. package/dist/runtime/flows/learning.js.map +1 -0
  135. package/dist/runtime/flows/validation.d.ts +122 -0
  136. package/dist/runtime/flows/validation.d.ts.map +1 -0
  137. package/dist/runtime/flows/validation.js +223 -0
  138. package/dist/runtime/flows/validation.js.map +1 -0
  139. package/dist/runtime/index.d.ts +6 -0
  140. package/dist/runtime/index.d.ts.map +1 -0
  141. package/dist/runtime/index.js +8 -0
  142. package/dist/runtime/index.js.map +1 -0
  143. package/dist/runtime/manager.d.ts +116 -0
  144. package/dist/runtime/manager.d.ts.map +1 -0
  145. package/dist/runtime/manager.js +416 -0
  146. package/dist/runtime/manager.js.map +1 -0
  147. package/dist/runtime/types.d.ts +138 -0
  148. package/dist/runtime/types.d.ts.map +1 -0
  149. package/dist/runtime/types.js +2 -0
  150. package/dist/runtime/types.js.map +1 -0
  151. package/dist/search/evaluator.d.ts +102 -0
  152. package/dist/search/evaluator.d.ts.map +1 -0
  153. package/dist/search/evaluator.js +352 -0
  154. package/dist/search/evaluator.js.map +1 -0
  155. package/dist/search/index.d.ts +7 -0
  156. package/dist/search/index.d.ts.map +1 -0
  157. package/dist/search/index.js +11 -0
  158. package/dist/search/index.js.map +1 -0
  159. package/dist/search/refinement-loop.d.ts +73 -0
  160. package/dist/search/refinement-loop.d.ts.map +1 -0
  161. package/dist/search/refinement-loop.js +245 -0
  162. package/dist/search/refinement-loop.js.map +1 -0
  163. package/dist/search/refinement-types.d.ts +154 -0
  164. package/dist/search/refinement-types.d.ts.map +1 -0
  165. package/dist/search/refinement-types.js +99 -0
  166. package/dist/search/refinement-types.js.map +1 -0
  167. package/dist/search/router.d.ts +61 -0
  168. package/dist/search/router.d.ts.map +1 -0
  169. package/dist/search/router.js +197 -0
  170. package/dist/search/router.js.map +1 -0
  171. package/dist/search/solver.d.ts +75 -0
  172. package/dist/search/solver.d.ts.map +1 -0
  173. package/dist/search/solver.js +216 -0
  174. package/dist/search/solver.js.map +1 -0
  175. package/dist/search/verification-runner.d.ts +125 -0
  176. package/dist/search/verification-runner.d.ts.map +1 -0
  177. package/dist/search/verification-runner.js +440 -0
  178. package/dist/search/verification-runner.js.map +1 -0
  179. package/dist/surfacing/index.d.ts +2 -0
  180. package/dist/surfacing/index.d.ts.map +1 -0
  181. package/dist/surfacing/index.js +2 -0
  182. package/dist/surfacing/index.js.map +1 -0
  183. package/dist/surfacing/skill-library.d.ts +158 -0
  184. package/dist/surfacing/skill-library.d.ts.map +1 -0
  185. package/dist/surfacing/skill-library.js +429 -0
  186. package/dist/surfacing/skill-library.js.map +1 -0
  187. package/dist/types/config.d.ts +1113 -0
  188. package/dist/types/config.d.ts.map +1 -0
  189. package/dist/types/config.js +274 -0
  190. package/dist/types/config.js.map +1 -0
  191. package/dist/types/index.d.ts +9 -0
  192. package/dist/types/index.d.ts.map +1 -0
  193. package/dist/types/index.js +14 -0
  194. package/dist/types/index.js.map +1 -0
  195. package/dist/types/memory.d.ts +339 -0
  196. package/dist/types/memory.d.ts.map +1 -0
  197. package/dist/types/memory.js +207 -0
  198. package/dist/types/memory.js.map +1 -0
  199. package/dist/types/meta.d.ts +146 -0
  200. package/dist/types/meta.d.ts.map +1 -0
  201. package/dist/types/meta.js +51 -0
  202. package/dist/types/meta.js.map +1 -0
  203. package/dist/types/outcome.d.ts +42 -0
  204. package/dist/types/outcome.d.ts.map +1 -0
  205. package/dist/types/outcome.js +50 -0
  206. package/dist/types/outcome.js.map +1 -0
  207. package/dist/types/playbook.d.ts +119 -0
  208. package/dist/types/playbook.d.ts.map +1 -0
  209. package/dist/types/playbook.js +71 -0
  210. package/dist/types/playbook.js.map +1 -0
  211. package/dist/types/step.d.ts +44 -0
  212. package/dist/types/step.d.ts.map +1 -0
  213. package/dist/types/step.js +32 -0
  214. package/dist/types/step.js.map +1 -0
  215. package/dist/types/task.d.ts +91 -0
  216. package/dist/types/task.d.ts.map +1 -0
  217. package/dist/types/task.js +39 -0
  218. package/dist/types/task.js.map +1 -0
  219. package/dist/types/trajectory.d.ts +221 -0
  220. package/dist/types/trajectory.d.ts.map +1 -0
  221. package/dist/types/trajectory.js +60 -0
  222. package/dist/types/trajectory.js.map +1 -0
  223. package/dist/utils/index.d.ts +4 -0
  224. package/dist/utils/index.d.ts.map +1 -0
  225. package/dist/utils/index.js +4 -0
  226. package/dist/utils/index.js.map +1 -0
  227. package/dist/utils/similarity.d.ts +31 -0
  228. package/dist/utils/similarity.d.ts.map +1 -0
  229. package/dist/utils/similarity.js +107 -0
  230. package/dist/utils/similarity.js.map +1 -0
  231. package/dist/utils/storage.d.ts +106 -0
  232. package/dist/utils/storage.d.ts.map +1 -0
  233. package/dist/utils/storage.js +203 -0
  234. package/dist/utils/storage.js.map +1 -0
  235. package/dist/utils/validation.d.ts +129 -0
  236. package/dist/utils/validation.d.ts.map +1 -0
  237. package/dist/utils/validation.js +171 -0
  238. package/dist/utils/validation.js.map +1 -0
  239. package/package.json +50 -34
  240. package/scripts/migrate-to-playbooks.ts +307 -0
  241. package/src/agents/index.ts +14 -0
  242. package/src/agents/mock-provider.ts +93 -0
  243. package/src/agents/types.ts +137 -0
  244. package/src/atlas.ts +560 -0
  245. package/src/bin/cognitive-core.ts +470 -0
  246. package/src/embeddings/bm25.ts +337 -0
  247. package/src/embeddings/index.ts +39 -0
  248. package/src/embeddings/manager.ts +288 -0
  249. package/src/embeddings/provider.ts +311 -0
  250. package/src/embeddings/vector-store.ts +353 -0
  251. package/src/factory.ts +263 -0
  252. package/src/index.ts +246 -0
  253. package/src/learning/analyzer.ts +335 -0
  254. package/src/learning/effectiveness.ts +428 -0
  255. package/src/learning/index.ts +58 -0
  256. package/src/learning/llm-extractor.ts +542 -0
  257. package/src/learning/meta-learner.ts +516 -0
  258. package/src/learning/pipeline.ts +244 -0
  259. package/src/learning/playbook-extractor.ts +702 -0
  260. package/src/learning/usage-inference.ts +372 -0
  261. package/src/mcp/index.ts +12 -0
  262. package/src/mcp/playbook-server.ts +565 -0
  263. package/src/memory/curated-loader.ts +160 -0
  264. package/src/memory/experience.ts +515 -0
  265. package/src/memory/index.ts +27 -0
  266. package/src/memory/meta.ts +506 -0
  267. package/src/memory/playbook.ts +493 -0
  268. package/src/memory/system.ts +551 -0
  269. package/src/runtime/backends/acp.ts +378 -0
  270. package/src/runtime/backends/index.ts +24 -0
  271. package/src/runtime/backends/mock.ts +218 -0
  272. package/src/runtime/backends/subprocess.ts +356 -0
  273. package/src/runtime/flows/learning.ts +183 -0
  274. package/src/runtime/flows/validation.ts +381 -0
  275. package/src/runtime/index.ts +53 -0
  276. package/src/runtime/manager.ts +541 -0
  277. package/src/runtime/types.ts +157 -0
  278. package/src/search/evaluator.ts +474 -0
  279. package/src/search/index.ts +59 -0
  280. package/src/search/refinement-loop.ts +363 -0
  281. package/src/search/refinement-types.ts +159 -0
  282. package/src/search/router.ts +261 -0
  283. package/src/search/solver.ts +303 -0
  284. package/src/search/verification-runner.ts +570 -0
  285. package/src/surfacing/index.ts +6 -0
  286. package/src/surfacing/skill-library.ts +594 -0
  287. package/src/types/config.ts +333 -0
  288. package/src/types/index.ts +130 -0
  289. package/src/types/memory.ts +270 -0
  290. package/src/types/meta.ts +218 -0
  291. package/src/types/outcome.ts +66 -0
  292. package/src/types/playbook.ts +196 -0
  293. package/src/types/step.ts +40 -0
  294. package/src/types/task.ts +52 -0
  295. package/src/types/trajectory.ts +80 -0
  296. package/src/utils/index.ts +38 -0
  297. package/src/utils/similarity.ts +139 -0
  298. package/src/utils/storage.ts +249 -0
  299. package/src/utils/validation.ts +286 -0
  300. package/tests/embeddings/bm25.test.ts +130 -0
  301. package/tests/embeddings/manager.test.ts +205 -0
  302. package/tests/integration/atlas.test.ts +266 -0
  303. package/tests/integration/e2e.test.ts +929 -0
  304. package/tests/learning/analyzer.test.ts +426 -0
  305. package/tests/learning/effectiveness.test.ts +542 -0
  306. package/tests/learning/pipeline.test.ts +176 -0
  307. package/tests/learning/playbook-extractor-provenance.test.ts +114 -0
  308. package/tests/learning/usage-inference.test.ts +254 -0
  309. package/tests/mcp/playbook-server.test.ts +252 -0
  310. package/tests/memory/experience.test.ts +198 -0
  311. package/tests/memory/playbook.test.ts +338 -0
  312. package/tests/memory/provenance.test.ts +639 -0
  313. package/tests/memory/system.test.ts +325 -0
  314. package/tests/runtime/agent-manager.test.ts +512 -0
  315. package/tests/runtime/mock-backend.test.ts +248 -0
  316. package/tests/search/refinement-loop.test.ts +468 -0
  317. package/tests/search/refinement.test.ts +267 -0
  318. package/tests/search/router.test.ts +427 -0
  319. package/tests/surfacing/skill-library.test.ts +292 -0
  320. package/tests/types/outcome.test.ts +147 -0
  321. package/tests/types/step.test.ts +133 -0
  322. package/tests/types/task.test.ts +158 -0
  323. package/tests/types/trajectory.test.ts +253 -0
  324. package/tests/utils/similarity.test.ts +188 -0
  325. package/tests/utils/validation.test.ts +252 -0
  326. package/tsconfig.json +25 -0
  327. package/vitest.config.ts +22 -0
  328. package/dist/index.d.mts +0 -466
  329. package/dist/index.mjs +0 -478
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Embedding Provider Interface and Implementations
3
+ *
4
+ * Provides a unified interface for generating embeddings from text.
5
+ * Supports hosted providers (OpenAI, etc.) and local models.
6
+ */
7
+
8
+ /**
9
+ * Interface for embedding providers (hosted or local)
10
+ */
11
+ export interface EmbeddingProvider {
12
+ /** Provider name for logging/debugging */
13
+ readonly name: string;
14
+
15
+ /** Embedding dimension */
16
+ readonly dimension: number;
17
+
18
+ /** Embed a single text */
19
+ embed(text: string): Promise<number[]>;
20
+
21
+ /** Embed multiple texts (batch) */
22
+ embedBatch(texts: string[]): Promise<number[][]>;
23
+ }
24
+
25
+ /**
26
+ * OpenAI embedding provider
27
+ */
28
+ export class OpenAIEmbeddingProvider implements EmbeddingProvider {
29
+ readonly name = "openai";
30
+ readonly dimension: number;
31
+ private apiKey: string;
32
+ private model: string;
33
+ private baseUrl: string;
34
+
35
+ constructor(options: {
36
+ apiKey: string;
37
+ model?: string;
38
+ dimension?: number;
39
+ baseUrl?: string;
40
+ }) {
41
+ this.apiKey = options.apiKey;
42
+ this.model = options.model ?? "text-embedding-3-small";
43
+ this.dimension = options.dimension ?? 1536;
44
+ this.baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
45
+ }
46
+
47
+ async embed(text: string): Promise<number[]> {
48
+ const [embedding] = await this.embedBatch([text]);
49
+ return embedding;
50
+ }
51
+
52
+ async embedBatch(texts: string[]): Promise<number[][]> {
53
+ const response = await fetch(`${this.baseUrl}/embeddings`, {
54
+ method: "POST",
55
+ headers: {
56
+ Authorization: `Bearer ${this.apiKey}`,
57
+ "Content-Type": "application/json",
58
+ },
59
+ body: JSON.stringify({
60
+ model: this.model,
61
+ input: texts,
62
+ dimensions: this.dimension,
63
+ }),
64
+ });
65
+
66
+ if (!response.ok) {
67
+ const error = await response.text();
68
+ throw new Error(`OpenAI embedding error: ${response.status} - ${error}`);
69
+ }
70
+
71
+ const data = (await response.json()) as {
72
+ data: Array<{ embedding: number[]; index: number }>;
73
+ };
74
+
75
+ // Sort by index to maintain order
76
+ const sorted = data.data.sort((a, b) => a.index - b.index);
77
+ return sorted.map((item) => item.embedding);
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Anthropic Voyage embedding provider
83
+ * Uses Voyage AI embeddings via Anthropic partnership
84
+ */
85
+ export class VoyageEmbeddingProvider implements EmbeddingProvider {
86
+ readonly name = "voyage";
87
+ readonly dimension: number;
88
+ private apiKey: string;
89
+ private model: string;
90
+
91
+ constructor(options: { apiKey: string; model?: string; dimension?: number }) {
92
+ this.apiKey = options.apiKey;
93
+ this.model = options.model ?? "voyage-2";
94
+ this.dimension = options.dimension ?? 1024;
95
+ }
96
+
97
+ async embed(text: string): Promise<number[]> {
98
+ const [embedding] = await this.embedBatch([text]);
99
+ return embedding;
100
+ }
101
+
102
+ async embedBatch(texts: string[]): Promise<number[][]> {
103
+ const response = await fetch("https://api.voyageai.com/v1/embeddings", {
104
+ method: "POST",
105
+ headers: {
106
+ Authorization: `Bearer ${this.apiKey}`,
107
+ "Content-Type": "application/json",
108
+ },
109
+ body: JSON.stringify({
110
+ model: this.model,
111
+ input: texts,
112
+ }),
113
+ });
114
+
115
+ if (!response.ok) {
116
+ const error = await response.text();
117
+ throw new Error(`Voyage embedding error: ${response.status} - ${error}`);
118
+ }
119
+
120
+ const data = (await response.json()) as {
121
+ data: Array<{ embedding: number[]; index: number }>;
122
+ };
123
+
124
+ const sorted = data.data.sort((a, b) => a.index - b.index);
125
+ return sorted.map((item) => item.embedding);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Local embedding provider using @huggingface/transformers
131
+ * Runs transformer models locally in Node.js using ONNX runtime
132
+ */
133
+ export class LocalEmbeddingProvider implements EmbeddingProvider {
134
+ readonly name = "local";
135
+ readonly dimension: number;
136
+ private modelName: string;
137
+ private extractor: any = null;
138
+ private initPromise: Promise<void> | null = null;
139
+
140
+ /** Default model - all-MiniLM-L6-v2 is small and fast with good quality */
141
+ static readonly DEFAULT_MODEL = "sentence-transformers/all-MiniLM-L6-v2";
142
+ /** Dimensions for common models */
143
+ static readonly MODEL_DIMENSIONS: Record<string, number> = {
144
+ "sentence-transformers/all-MiniLM-L6-v2": 384,
145
+ "sentence-transformers/all-MiniLM-L12-v2": 384,
146
+ "BAAI/bge-small-en-v1.5": 384,
147
+ "BAAI/bge-base-en-v1.5": 768,
148
+ "intfloat/e5-small-v2": 384,
149
+ "intfloat/e5-base-v2": 768,
150
+ // Keep Xenova aliases for backwards compatibility
151
+ "Xenova/all-MiniLM-L6-v2": 384,
152
+ "Xenova/all-MiniLM-L12-v2": 384,
153
+ "Xenova/bge-small-en-v1.5": 384,
154
+ "Xenova/bge-base-en-v1.5": 768,
155
+ "Xenova/e5-small-v2": 384,
156
+ "Xenova/e5-base-v2": 768,
157
+ };
158
+
159
+ constructor(options?: {
160
+ modelName?: string;
161
+ modelPath?: string; // Alias for modelName for backwards compatibility
162
+ dimension?: number;
163
+ }) {
164
+ this.modelName =
165
+ options?.modelName ??
166
+ options?.modelPath ??
167
+ LocalEmbeddingProvider.DEFAULT_MODEL;
168
+
169
+ // Auto-detect dimension from known models or use provided/default
170
+ this.dimension =
171
+ options?.dimension ??
172
+ LocalEmbeddingProvider.MODEL_DIMENSIONS[this.modelName] ??
173
+ 384;
174
+ }
175
+
176
+ /** Get the model name/path */
177
+ get modelPath(): string {
178
+ return this.modelName;
179
+ }
180
+
181
+ private async initialize(): Promise<void> {
182
+ if (this.extractor) return;
183
+
184
+ // Prevent multiple concurrent initializations
185
+ if (this.initPromise) {
186
+ await this.initPromise;
187
+ return;
188
+ }
189
+
190
+ this.initPromise = this.doInitialize();
191
+ await this.initPromise;
192
+ }
193
+
194
+ private async doInitialize(): Promise<void> {
195
+ try {
196
+ // Dynamic import to avoid issues if transformers.js isn't installed
197
+ const { pipeline } = await import("@huggingface/transformers");
198
+
199
+ // Create feature-extraction pipeline for embeddings
200
+ this.extractor = await pipeline("feature-extraction", this.modelName, {
201
+ dtype: "fp32", // Use fp32 for better compatibility
202
+ });
203
+ } catch (error) {
204
+ const message = error instanceof Error ? error.message : String(error);
205
+ throw new Error(
206
+ `Failed to initialize local embedding model "${this.modelName}": ${message}`,
207
+ );
208
+ }
209
+ }
210
+
211
+ async embed(text: string): Promise<number[]> {
212
+ await this.initialize();
213
+
214
+ // Run the extractor
215
+ const output = await this.extractor(text, {
216
+ pooling: "mean", // Mean pooling over tokens
217
+ normalize: true, // L2 normalize the output
218
+ });
219
+
220
+ // Convert tensor to array
221
+ return Array.from(output.data as Float32Array);
222
+ }
223
+
224
+ async embedBatch(texts: string[]): Promise<number[][]> {
225
+ await this.initialize();
226
+
227
+ // Process in batch for better efficiency
228
+ const results: number[][] = [];
229
+
230
+ for (const text of texts) {
231
+ const output = await this.extractor(text, {
232
+ pooling: "mean",
233
+ normalize: true,
234
+ });
235
+ results.push(Array.from(output.data as Float32Array));
236
+ }
237
+
238
+ return results;
239
+ }
240
+
241
+ /**
242
+ * Check if a model is available locally (cached)
243
+ * This can be used to pre-warm the cache
244
+ */
245
+ async isModelCached(): Promise<boolean> {
246
+ try {
247
+ const { env } = await import("@huggingface/transformers");
248
+ // Check if model files exist in cache
249
+ // This is a simplified check - the actual cache structure may vary
250
+ return env.cacheDir !== undefined;
251
+ } catch {
252
+ return false;
253
+ }
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Configuration for embedding providers
259
+ */
260
+ export interface EmbeddingProviderConfig {
261
+ type: "openai" | "voyage" | "local" | "none";
262
+ apiKey?: string;
263
+ model?: string;
264
+ modelPath?: string;
265
+ dimension?: number;
266
+ baseUrl?: string;
267
+ }
268
+
269
+ /**
270
+ * Create an embedding provider from configuration
271
+ */
272
+ export function createEmbeddingProvider(
273
+ config: EmbeddingProviderConfig,
274
+ ): EmbeddingProvider | null {
275
+ switch (config.type) {
276
+ case "openai":
277
+ if (!config.apiKey) {
278
+ throw new Error("OpenAI embedding provider requires apiKey");
279
+ }
280
+ return new OpenAIEmbeddingProvider({
281
+ apiKey: config.apiKey,
282
+ model: config.model,
283
+ dimension: config.dimension,
284
+ baseUrl: config.baseUrl,
285
+ });
286
+
287
+ case "voyage":
288
+ if (!config.apiKey) {
289
+ throw new Error("Voyage embedding provider requires apiKey");
290
+ }
291
+ return new VoyageEmbeddingProvider({
292
+ apiKey: config.apiKey,
293
+ model: config.model,
294
+ dimension: config.dimension,
295
+ });
296
+
297
+ case "local":
298
+ // Local provider now has sensible defaults
299
+ return new LocalEmbeddingProvider({
300
+ modelName: config.model,
301
+ modelPath: config.modelPath,
302
+ dimension: config.dimension,
303
+ });
304
+
305
+ case "none":
306
+ return null;
307
+
308
+ default:
309
+ return null;
310
+ }
311
+ }
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Vector Store using sqlite-vec
3
+ *
4
+ * Provides efficient vector similarity search using SQLite with the sqlite-vec extension.
5
+ * sqlite-vec is optimized for in-process vector search without the overhead of external services.
6
+ */
7
+
8
+ import Database from 'better-sqlite3';
9
+ import * as sqliteVec from 'sqlite-vec';
10
+ import type { MemoryItemType } from './bm25.js';
11
+
12
+ export interface VectorSearchResult {
13
+ id: string;
14
+ score: number;
15
+ content: string;
16
+ type: MemoryItemType;
17
+ }
18
+
19
+ /**
20
+ * Vector store using sqlite-vec for efficient similarity search
21
+ */
22
+ export class SqliteVectorStore {
23
+ private db: Database.Database;
24
+ private dimension: number;
25
+ private tableName: string;
26
+ private initialized: boolean = false;
27
+
28
+ constructor(options: {
29
+ dbPath: string;
30
+ dimension: number;
31
+ tableName?: string;
32
+ }) {
33
+ this.dimension = options.dimension;
34
+ this.tableName = options.tableName ?? 'atlas_embeddings';
35
+
36
+ // Create or open the database
37
+ this.db = new Database(options.dbPath);
38
+
39
+ // Load the sqlite-vec extension
40
+ sqliteVec.load(this.db);
41
+
42
+ this.initialize();
43
+ }
44
+
45
+ /**
46
+ * Initialize the database schema
47
+ */
48
+ private initialize(): void {
49
+ if (this.initialized) return;
50
+
51
+ // Create metadata table for storing content and type info
52
+ this.db.exec(`
53
+ CREATE TABLE IF NOT EXISTS ${this.tableName}_meta (
54
+ id TEXT PRIMARY KEY,
55
+ type TEXT NOT NULL,
56
+ content TEXT NOT NULL,
57
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP
58
+ )
59
+ `);
60
+
61
+ // Create virtual table for vector search using vec0
62
+ // Note: vec0 uses a separate storage model optimized for vector operations
63
+ this.db.exec(`
64
+ CREATE VIRTUAL TABLE IF NOT EXISTS ${this.tableName}_vec USING vec0(
65
+ id TEXT PRIMARY KEY,
66
+ embedding FLOAT[${this.dimension}]
67
+ )
68
+ `);
69
+
70
+ // Create index on type for filtering
71
+ this.db.exec(`
72
+ CREATE INDEX IF NOT EXISTS idx_${this.tableName}_type
73
+ ON ${this.tableName}_meta(type)
74
+ `);
75
+
76
+ this.initialized = true;
77
+ }
78
+
79
+ /**
80
+ * Insert or update a vector with metadata
81
+ */
82
+ insert(
83
+ id: string,
84
+ embedding: number[],
85
+ type: MemoryItemType,
86
+ content: string
87
+ ): void {
88
+ if (embedding.length !== this.dimension) {
89
+ throw new Error(
90
+ `Embedding dimension mismatch: expected ${this.dimension}, got ${embedding.length}`
91
+ );
92
+ }
93
+
94
+ // Use a transaction for atomicity
95
+ const transaction = this.db.transaction(() => {
96
+ // Insert or replace metadata
97
+ const metaStmt = this.db.prepare(`
98
+ INSERT OR REPLACE INTO ${this.tableName}_meta (id, type, content)
99
+ VALUES (?, ?, ?)
100
+ `);
101
+ metaStmt.run(id, type, content);
102
+
103
+ // Insert or replace vector
104
+ // sqlite-vec expects vectors as JSON arrays or binary blobs
105
+ const vecStmt = this.db.prepare(`
106
+ INSERT OR REPLACE INTO ${this.tableName}_vec (id, embedding)
107
+ VALUES (?, ?)
108
+ `);
109
+ vecStmt.run(id, JSON.stringify(embedding));
110
+ });
111
+
112
+ transaction();
113
+ }
114
+
115
+ /**
116
+ * Insert multiple vectors in batch
117
+ */
118
+ insertBatch(
119
+ items: Array<{
120
+ id: string;
121
+ embedding: number[];
122
+ type: MemoryItemType;
123
+ content: string;
124
+ }>
125
+ ): void {
126
+ const transaction = this.db.transaction(() => {
127
+ const metaStmt = this.db.prepare(`
128
+ INSERT OR REPLACE INTO ${this.tableName}_meta (id, type, content)
129
+ VALUES (?, ?, ?)
130
+ `);
131
+
132
+ const vecStmt = this.db.prepare(`
133
+ INSERT OR REPLACE INTO ${this.tableName}_vec (id, embedding)
134
+ VALUES (?, ?)
135
+ `);
136
+
137
+ for (const item of items) {
138
+ if (item.embedding.length !== this.dimension) {
139
+ throw new Error(
140
+ `Embedding dimension mismatch for ${item.id}: expected ${this.dimension}, got ${item.embedding.length}`
141
+ );
142
+ }
143
+ metaStmt.run(item.id, item.type, item.content);
144
+ vecStmt.run(item.id, JSON.stringify(item.embedding));
145
+ }
146
+ });
147
+
148
+ transaction();
149
+ }
150
+
151
+ /**
152
+ * Search for similar vectors
153
+ */
154
+ search(
155
+ queryEmbedding: number[],
156
+ options: {
157
+ k?: number;
158
+ type?: MemoryItemType;
159
+ threshold?: number;
160
+ } = {}
161
+ ): VectorSearchResult[] {
162
+ if (queryEmbedding.length !== this.dimension) {
163
+ throw new Error(
164
+ `Query embedding dimension mismatch: expected ${this.dimension}, got ${queryEmbedding.length}`
165
+ );
166
+ }
167
+
168
+ const k = options.k ?? 10;
169
+ const threshold = options.threshold ?? 0;
170
+
171
+ // Build the query based on whether we're filtering by type
172
+ let query: string;
173
+ let params: unknown[];
174
+
175
+ if (options.type) {
176
+ // Join with metadata table to filter by type
177
+ query = `
178
+ SELECT
179
+ v.id,
180
+ m.type,
181
+ m.content,
182
+ vec_distance_cosine(v.embedding, ?) as distance
183
+ FROM ${this.tableName}_vec v
184
+ JOIN ${this.tableName}_meta m ON v.id = m.id
185
+ WHERE m.type = ?
186
+ ORDER BY distance ASC
187
+ LIMIT ?
188
+ `;
189
+ params = [JSON.stringify(queryEmbedding), options.type, k];
190
+ } else {
191
+ query = `
192
+ SELECT
193
+ v.id,
194
+ m.type,
195
+ m.content,
196
+ vec_distance_cosine(v.embedding, ?) as distance
197
+ FROM ${this.tableName}_vec v
198
+ JOIN ${this.tableName}_meta m ON v.id = m.id
199
+ ORDER BY distance ASC
200
+ LIMIT ?
201
+ `;
202
+ params = [JSON.stringify(queryEmbedding), k];
203
+ }
204
+
205
+ const stmt = this.db.prepare(query);
206
+ const results = stmt.all(...params) as Array<{
207
+ id: string;
208
+ type: MemoryItemType;
209
+ content: string;
210
+ distance: number;
211
+ }>;
212
+
213
+ // Convert distance to similarity score (1 - distance for cosine)
214
+ return results
215
+ .map((r) => ({
216
+ id: r.id,
217
+ type: r.type,
218
+ content: r.content,
219
+ score: 1 - r.distance,
220
+ }))
221
+ .filter((r) => r.score >= threshold);
222
+ }
223
+
224
+ /**
225
+ * Get a vector by ID
226
+ */
227
+ get(id: string): { embedding: number[]; type: MemoryItemType; content: string } | null {
228
+ const metaStmt = this.db.prepare(`
229
+ SELECT type, content FROM ${this.tableName}_meta WHERE id = ?
230
+ `);
231
+ const meta = metaStmt.get(id) as { type: MemoryItemType; content: string } | undefined;
232
+
233
+ if (!meta) return null;
234
+
235
+ const vecStmt = this.db.prepare(`
236
+ SELECT embedding FROM ${this.tableName}_vec WHERE id = ?
237
+ `);
238
+ const vec = vecStmt.get(id) as { embedding: string } | undefined;
239
+
240
+ if (!vec) return null;
241
+
242
+ return {
243
+ embedding: JSON.parse(vec.embedding) as number[],
244
+ type: meta.type,
245
+ content: meta.content,
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Check if an ID exists
251
+ */
252
+ has(id: string): boolean {
253
+ const stmt = this.db.prepare(`
254
+ SELECT 1 FROM ${this.tableName}_meta WHERE id = ? LIMIT 1
255
+ `);
256
+ return stmt.get(id) !== undefined;
257
+ }
258
+
259
+ /**
260
+ * Delete a vector
261
+ */
262
+ delete(id: string): boolean {
263
+ const transaction = this.db.transaction(() => {
264
+ const metaStmt = this.db.prepare(
265
+ `DELETE FROM ${this.tableName}_meta WHERE id = ?`
266
+ );
267
+ const vecStmt = this.db.prepare(
268
+ `DELETE FROM ${this.tableName}_vec WHERE id = ?`
269
+ );
270
+
271
+ const metaResult = metaStmt.run(id);
272
+ vecStmt.run(id);
273
+
274
+ return metaResult.changes > 0;
275
+ });
276
+
277
+ return transaction();
278
+ }
279
+
280
+ /**
281
+ * Get the number of vectors stored
282
+ */
283
+ get count(): number {
284
+ const stmt = this.db.prepare(
285
+ `SELECT COUNT(*) as count FROM ${this.tableName}_meta`
286
+ );
287
+ const result = stmt.get() as { count: number };
288
+ return result.count;
289
+ }
290
+
291
+ /**
292
+ * Get count by type
293
+ */
294
+ countByType(type: MemoryItemType): number {
295
+ const stmt = this.db.prepare(
296
+ `SELECT COUNT(*) as count FROM ${this.tableName}_meta WHERE type = ?`
297
+ );
298
+ const result = stmt.get(type) as { count: number };
299
+ return result.count;
300
+ }
301
+
302
+ /**
303
+ * Clear all vectors
304
+ */
305
+ clear(): void {
306
+ const transaction = this.db.transaction(() => {
307
+ this.db.exec(`DELETE FROM ${this.tableName}_meta`);
308
+ this.db.exec(`DELETE FROM ${this.tableName}_vec`);
309
+ });
310
+
311
+ transaction();
312
+ }
313
+
314
+ /**
315
+ * Close the database connection
316
+ */
317
+ close(): void {
318
+ this.db.close();
319
+ }
320
+
321
+ /**
322
+ * Get database statistics
323
+ */
324
+ getStats(): {
325
+ totalVectors: number;
326
+ byType: Record<MemoryItemType, number>;
327
+ dimension: number;
328
+ } {
329
+ const types: MemoryItemType[] = ['experience', 'strategy', 'concept', 'skill'];
330
+ const byType: Record<MemoryItemType, number> = {} as Record<MemoryItemType, number>;
331
+
332
+ for (const type of types) {
333
+ byType[type] = this.countByType(type);
334
+ }
335
+
336
+ return {
337
+ totalVectors: this.count,
338
+ byType,
339
+ dimension: this.dimension,
340
+ };
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Create a new vector store
346
+ */
347
+ export function createVectorStore(options: {
348
+ dbPath: string;
349
+ dimension: number;
350
+ tableName?: string;
351
+ }): SqliteVectorStore {
352
+ return new SqliteVectorStore(options);
353
+ }