agentic-flow 2.0.1-alpha.2 → 2.0.1-alpha.20

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 (218) hide show
  1. package/CHANGELOG.md +352 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentdb/controllers/EmbeddingService.d.ts +37 -0
  4. package/dist/agentdb/controllers/EmbeddingService.d.ts.map +1 -0
  5. package/dist/agentdb/controllers/EmbeddingService.js +1 -0
  6. package/dist/agentdb/controllers/EmbeddingService.js.map +1 -0
  7. package/dist/billing/mcp/tools.d.ts.map +1 -1
  8. package/dist/billing/mcp/tools.js +2 -0
  9. package/dist/billing/mcp/tools.js.map +1 -1
  10. package/dist/cli/commands/hooks.d.ts +18 -0
  11. package/dist/cli/commands/hooks.d.ts.map +1 -0
  12. package/dist/cli/commands/hooks.js +755 -0
  13. package/dist/cli/commands/hooks.js.map +1 -0
  14. package/dist/cli-proxy.d.ts +1 -1
  15. package/dist/cli-proxy.d.ts.map +1 -1
  16. package/dist/cli-proxy.js +28 -1
  17. package/dist/cli-proxy.js.map +1 -1
  18. package/dist/core/agentdb-fast.js +3 -3
  19. package/dist/core/agentdb-fast.js.map +1 -1
  20. package/dist/core/agentdb-wrapper-enhanced.d.ts.map +1 -1
  21. package/dist/core/agentdb-wrapper-enhanced.js +32 -17
  22. package/dist/core/agentdb-wrapper-enhanced.js.map +1 -1
  23. package/dist/core/attention-native.d.ts +1 -0
  24. package/dist/core/attention-native.d.ts.map +1 -1
  25. package/dist/core/attention-native.js +6 -1
  26. package/dist/core/attention-native.js.map +1 -1
  27. package/dist/federation/integrations/supabase-adapter-debug.js +3 -3
  28. package/dist/federation/integrations/supabase-adapter-debug.js.map +1 -1
  29. package/dist/intelligence/EmbeddingCache.d.ts +112 -0
  30. package/dist/intelligence/EmbeddingCache.d.ts.map +1 -0
  31. package/dist/intelligence/EmbeddingCache.js +624 -0
  32. package/dist/intelligence/EmbeddingCache.js.map +1 -0
  33. package/dist/intelligence/EmbeddingService.d.ts +380 -0
  34. package/dist/intelligence/EmbeddingService.d.ts.map +1 -0
  35. package/dist/intelligence/EmbeddingService.js +1484 -0
  36. package/dist/intelligence/EmbeddingService.js.map +1 -0
  37. package/dist/intelligence/IntelligenceStore.d.ts +168 -0
  38. package/dist/intelligence/IntelligenceStore.d.ts.map +1 -0
  39. package/dist/intelligence/IntelligenceStore.js +364 -0
  40. package/dist/intelligence/IntelligenceStore.js.map +1 -0
  41. package/dist/intelligence/RuVectorIntelligence.d.ts +362 -0
  42. package/dist/intelligence/RuVectorIntelligence.d.ts.map +1 -0
  43. package/dist/intelligence/RuVectorIntelligence.js +853 -0
  44. package/dist/intelligence/RuVectorIntelligence.js.map +1 -0
  45. package/dist/intelligence/embedding-benchmark.d.ts +7 -0
  46. package/dist/intelligence/embedding-benchmark.d.ts.map +1 -0
  47. package/dist/intelligence/embedding-benchmark.js +155 -0
  48. package/dist/intelligence/embedding-benchmark.js.map +1 -0
  49. package/dist/intelligence/index.d.ts +14 -0
  50. package/dist/intelligence/index.d.ts.map +1 -0
  51. package/dist/intelligence/index.js +14 -0
  52. package/dist/intelligence/index.js.map +1 -0
  53. package/dist/llm/RuvLLMOrchestrator.d.ts +184 -0
  54. package/dist/llm/RuvLLMOrchestrator.d.ts.map +1 -0
  55. package/dist/llm/RuvLLMOrchestrator.js +442 -0
  56. package/dist/llm/RuvLLMOrchestrator.js.map +1 -0
  57. package/dist/llm/index.d.ts +9 -0
  58. package/dist/llm/index.d.ts.map +1 -0
  59. package/dist/llm/index.js +8 -0
  60. package/dist/llm/index.js.map +1 -0
  61. package/dist/mcp/claudeFlowSdkServer.d.ts.map +1 -1
  62. package/dist/mcp/claudeFlowSdkServer.js +86 -21
  63. package/dist/mcp/claudeFlowSdkServer.js.map +1 -1
  64. package/dist/mcp/fastmcp/servers/hooks-server.d.ts +15 -0
  65. package/dist/mcp/fastmcp/servers/hooks-server.d.ts.map +1 -0
  66. package/dist/mcp/fastmcp/servers/hooks-server.js +63 -0
  67. package/dist/mcp/fastmcp/servers/hooks-server.js.map +1 -0
  68. package/dist/mcp/fastmcp/tools/hooks/benchmark.d.ts +20 -0
  69. package/dist/mcp/fastmcp/tools/hooks/benchmark.d.ts.map +1 -0
  70. package/dist/mcp/fastmcp/tools/hooks/benchmark.js +110 -0
  71. package/dist/mcp/fastmcp/tools/hooks/benchmark.js.map +1 -0
  72. package/dist/mcp/fastmcp/tools/hooks/build-agents.d.ts +7 -0
  73. package/dist/mcp/fastmcp/tools/hooks/build-agents.d.ts.map +1 -0
  74. package/dist/mcp/fastmcp/tools/hooks/build-agents.js +276 -0
  75. package/dist/mcp/fastmcp/tools/hooks/build-agents.js.map +1 -0
  76. package/dist/mcp/fastmcp/tools/hooks/explain.d.ts +6 -0
  77. package/dist/mcp/fastmcp/tools/hooks/explain.d.ts.map +1 -0
  78. package/dist/mcp/fastmcp/tools/hooks/explain.js +164 -0
  79. package/dist/mcp/fastmcp/tools/hooks/explain.js.map +1 -0
  80. package/dist/mcp/fastmcp/tools/hooks/index.d.ts +28 -0
  81. package/dist/mcp/fastmcp/tools/hooks/index.d.ts.map +1 -0
  82. package/dist/mcp/fastmcp/tools/hooks/index.js +59 -0
  83. package/dist/mcp/fastmcp/tools/hooks/index.js.map +1 -0
  84. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.d.ts +307 -0
  85. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.d.ts.map +1 -0
  86. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.js +714 -0
  87. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.js.map +1 -0
  88. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.d.ts +58 -0
  89. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.d.ts.map +1 -0
  90. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.js +425 -0
  91. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.js.map +1 -0
  92. package/dist/mcp/fastmcp/tools/hooks/metrics.d.ts +6 -0
  93. package/dist/mcp/fastmcp/tools/hooks/metrics.d.ts.map +1 -0
  94. package/dist/mcp/fastmcp/tools/hooks/metrics.js +137 -0
  95. package/dist/mcp/fastmcp/tools/hooks/metrics.js.map +1 -0
  96. package/dist/mcp/fastmcp/tools/hooks/post-command.d.ts +7 -0
  97. package/dist/mcp/fastmcp/tools/hooks/post-command.d.ts.map +1 -0
  98. package/dist/mcp/fastmcp/tools/hooks/post-command.js +91 -0
  99. package/dist/mcp/fastmcp/tools/hooks/post-command.js.map +1 -0
  100. package/dist/mcp/fastmcp/tools/hooks/post-edit.d.ts +12 -0
  101. package/dist/mcp/fastmcp/tools/hooks/post-edit.d.ts.map +1 -0
  102. package/dist/mcp/fastmcp/tools/hooks/post-edit.js +146 -0
  103. package/dist/mcp/fastmcp/tools/hooks/post-edit.js.map +1 -0
  104. package/dist/mcp/fastmcp/tools/hooks/pre-command.d.ts +7 -0
  105. package/dist/mcp/fastmcp/tools/hooks/pre-command.d.ts.map +1 -0
  106. package/dist/mcp/fastmcp/tools/hooks/pre-command.js +70 -0
  107. package/dist/mcp/fastmcp/tools/hooks/pre-command.js.map +1 -0
  108. package/dist/mcp/fastmcp/tools/hooks/pre-edit.d.ts +14 -0
  109. package/dist/mcp/fastmcp/tools/hooks/pre-edit.d.ts.map +1 -0
  110. package/dist/mcp/fastmcp/tools/hooks/pre-edit.js +121 -0
  111. package/dist/mcp/fastmcp/tools/hooks/pre-edit.js.map +1 -0
  112. package/dist/mcp/fastmcp/tools/hooks/pretrain.d.ts +7 -0
  113. package/dist/mcp/fastmcp/tools/hooks/pretrain.d.ts.map +1 -0
  114. package/dist/mcp/fastmcp/tools/hooks/pretrain.js +171 -0
  115. package/dist/mcp/fastmcp/tools/hooks/pretrain.js.map +1 -0
  116. package/dist/mcp/fastmcp/tools/hooks/route.d.ts +12 -0
  117. package/dist/mcp/fastmcp/tools/hooks/route.d.ts.map +1 -0
  118. package/dist/mcp/fastmcp/tools/hooks/route.js +267 -0
  119. package/dist/mcp/fastmcp/tools/hooks/route.js.map +1 -0
  120. package/dist/mcp/fastmcp/tools/hooks/shared.d.ts +46 -0
  121. package/dist/mcp/fastmcp/tools/hooks/shared.d.ts.map +1 -0
  122. package/dist/mcp/fastmcp/tools/hooks/shared.js +159 -0
  123. package/dist/mcp/fastmcp/tools/hooks/shared.js.map +1 -0
  124. package/dist/mcp/fastmcp/tools/hooks/transfer.d.ts +7 -0
  125. package/dist/mcp/fastmcp/tools/hooks/transfer.d.ts.map +1 -0
  126. package/dist/mcp/fastmcp/tools/hooks/transfer.js +151 -0
  127. package/dist/mcp/fastmcp/tools/hooks/transfer.js.map +1 -0
  128. package/dist/mcp/tools/agent-booster-tools.d.ts +10 -1
  129. package/dist/mcp/tools/agent-booster-tools.d.ts.map +1 -1
  130. package/dist/mcp/tools/agent-booster-tools.js.map +1 -1
  131. package/dist/mcp/tools/sona-tools.d.ts.map +1 -1
  132. package/dist/mcp/tools/sona-tools.js +15 -3
  133. package/dist/mcp/tools/sona-tools.js.map +1 -1
  134. package/dist/memory/SharedMemoryPool.d.ts +16 -3
  135. package/dist/memory/SharedMemoryPool.d.ts.map +1 -1
  136. package/dist/memory/SharedMemoryPool.js +33 -1
  137. package/dist/memory/SharedMemoryPool.js.map +1 -1
  138. package/dist/middleware/auth.middleware.d.ts +114 -0
  139. package/dist/middleware/auth.middleware.d.ts.map +1 -0
  140. package/dist/middleware/auth.middleware.js +222 -0
  141. package/dist/middleware/auth.middleware.js.map +1 -0
  142. package/dist/optimizations/agent-booster-migration.d.ts.map +1 -1
  143. package/dist/optimizations/agent-booster-migration.js.map +1 -1
  144. package/dist/proxy/anthropic-to-gemini.d.ts.map +1 -1
  145. package/dist/proxy/anthropic-to-gemini.js.map +1 -1
  146. package/dist/proxy/anthropic-to-openrouter.d.ts.map +1 -1
  147. package/dist/proxy/anthropic-to-openrouter.js.map +1 -1
  148. package/dist/proxy/anthropic-to-requesty.d.ts.map +1 -1
  149. package/dist/proxy/anthropic-to-requesty.js.map +1 -1
  150. package/dist/proxy/quic-proxy.d.ts +0 -1
  151. package/dist/proxy/quic-proxy.d.ts.map +1 -1
  152. package/dist/proxy/quic-proxy.js +2 -1
  153. package/dist/proxy/quic-proxy.js.map +1 -1
  154. package/dist/reasoningbank/AdvancedMemory.d.ts.map +1 -1
  155. package/dist/reasoningbank/AdvancedMemory.js +12 -1
  156. package/dist/reasoningbank/AdvancedMemory.js.map +1 -1
  157. package/dist/reasoningbank/HybridBackend.d.ts +9 -0
  158. package/dist/reasoningbank/HybridBackend.d.ts.map +1 -1
  159. package/dist/reasoningbank/HybridBackend.js +48 -4
  160. package/dist/reasoningbank/HybridBackend.js.map +1 -1
  161. package/dist/reasoningbank/backend-selector.d.ts +1 -1
  162. package/dist/reasoningbank/backend-selector.d.ts.map +1 -1
  163. package/dist/reasoningbank/backend-selector.js.map +1 -1
  164. package/dist/reasoningbank/index-new.d.ts +0 -6
  165. package/dist/reasoningbank/index-new.d.ts.map +1 -1
  166. package/dist/reasoningbank/index-new.js +9 -7
  167. package/dist/reasoningbank/index-new.js.map +1 -1
  168. package/dist/reasoningbank/index.d.ts +1 -6
  169. package/dist/reasoningbank/index.d.ts.map +1 -1
  170. package/dist/reasoningbank/index.js +10 -7
  171. package/dist/reasoningbank/index.js.map +1 -1
  172. package/dist/router/providers/onnx-local.d.ts.map +1 -1
  173. package/dist/router/providers/onnx-local.js +3 -1
  174. package/dist/router/providers/onnx-local.js.map +1 -1
  175. package/dist/routing/CircuitBreakerRouter.d.ts +187 -0
  176. package/dist/routing/CircuitBreakerRouter.d.ts.map +1 -0
  177. package/dist/routing/CircuitBreakerRouter.js +460 -0
  178. package/dist/routing/CircuitBreakerRouter.js.map +1 -0
  179. package/dist/routing/SemanticRouter.d.ts +164 -0
  180. package/dist/routing/SemanticRouter.d.ts.map +1 -0
  181. package/dist/routing/SemanticRouter.js +291 -0
  182. package/dist/routing/SemanticRouter.js.map +1 -0
  183. package/dist/routing/index.d.ts +12 -0
  184. package/dist/routing/index.d.ts.map +1 -0
  185. package/dist/routing/index.js +10 -0
  186. package/dist/routing/index.js.map +1 -0
  187. package/dist/services/embedding-service.d.ts.map +1 -1
  188. package/dist/services/embedding-service.js +5 -2
  189. package/dist/services/embedding-service.js.map +1 -1
  190. package/dist/services/sona-agent-training.js +1 -1
  191. package/dist/services/sona-agent-training.js.map +1 -1
  192. package/dist/services/sona-agentdb-integration.d.ts.map +1 -1
  193. package/dist/services/sona-agentdb-integration.js +10 -5
  194. package/dist/services/sona-agentdb-integration.js.map +1 -1
  195. package/dist/services/sona-service.d.ts +6 -6
  196. package/dist/services/sona-service.d.ts.map +1 -1
  197. package/dist/services/sona-service.js +3 -1
  198. package/dist/services/sona-service.js.map +1 -1
  199. package/dist/utils/agentdb-runtime-patch.d.ts +1 -0
  200. package/dist/utils/agentdb-runtime-patch.d.ts.map +1 -1
  201. package/dist/utils/agentdb-runtime-patch.js +97 -2
  202. package/dist/utils/agentdb-runtime-patch.js.map +1 -1
  203. package/dist/utils/audit-logger.d.ts +115 -0
  204. package/dist/utils/audit-logger.d.ts.map +1 -0
  205. package/dist/utils/audit-logger.js +228 -0
  206. package/dist/utils/audit-logger.js.map +1 -0
  207. package/dist/utils/cli.d.ts +1 -1
  208. package/dist/utils/cli.d.ts.map +1 -1
  209. package/dist/utils/cli.js +5 -0
  210. package/dist/utils/cli.js.map +1 -1
  211. package/dist/utils/input-validator.d.ts +116 -0
  212. package/dist/utils/input-validator.d.ts.map +1 -0
  213. package/dist/utils/input-validator.js +299 -0
  214. package/dist/utils/input-validator.js.map +1 -0
  215. package/dist/utils/rate-limiter.js +2 -2
  216. package/dist/utils/rate-limiter.js.map +1 -1
  217. package/package.json +14 -3
  218. package/scripts/postinstall.js +72 -0
@@ -0,0 +1,624 @@
1
+ /**
2
+ * EmbeddingCache - Persistent cache for embeddings
3
+ *
4
+ * Makes ONNX embeddings practical by caching across sessions:
5
+ * - First embed: ~400ms (ONNX inference)
6
+ * - Cached embed: ~0.1ms (SQLite lookup) or ~0.01ms (in-memory fallback)
7
+ *
8
+ * Storage: ~/.agentic-flow/embedding-cache.db (if SQLite available)
9
+ *
10
+ * Windows Compatibility:
11
+ * - Falls back to in-memory cache if better-sqlite3 compilation fails
12
+ * - No native module compilation required for basic functionality
13
+ */
14
+ import { existsSync, mkdirSync, statSync, readFileSync, writeFileSync } from 'fs';
15
+ import { join } from 'path';
16
+ import { homedir } from 'os';
17
+ import { createHash } from 'crypto';
18
+ // Default config
19
+ const DEFAULT_CONFIG = {
20
+ maxEntries: 10000,
21
+ maxAgeDays: 30,
22
+ dbPath: join(homedir(), '.agentic-flow', 'embedding-cache.db'),
23
+ dimension: 384,
24
+ forceMemory: false,
25
+ };
26
+ // Check if better-sqlite3 is available (native, fastest)
27
+ let BetterSqlite3 = null;
28
+ let nativeSqliteAvailable = false;
29
+ // Check if sql.js is available (WASM, cross-platform)
30
+ let SqlJs = null;
31
+ let wasmSqliteAvailable = false;
32
+ try {
33
+ // Try native SQLite first (fastest)
34
+ BetterSqlite3 = require('better-sqlite3');
35
+ nativeSqliteAvailable = true;
36
+ }
37
+ catch {
38
+ // Native not available, try WASM fallback
39
+ try {
40
+ SqlJs = require('sql.js');
41
+ wasmSqliteAvailable = true;
42
+ }
43
+ catch {
44
+ // Neither available, will use memory cache
45
+ }
46
+ }
47
+ const sqliteAvailable = nativeSqliteAvailable || wasmSqliteAvailable;
48
+ /**
49
+ * In-memory cache fallback for Windows compatibility
50
+ */
51
+ class MemoryCache {
52
+ cache = new Map();
53
+ maxEntries;
54
+ hits = 0;
55
+ misses = 0;
56
+ constructor(maxEntries = 10000) {
57
+ this.maxEntries = maxEntries;
58
+ }
59
+ get(hash) {
60
+ const entry = this.cache.get(hash);
61
+ if (entry) {
62
+ entry.hits++;
63
+ entry.accessed = Date.now();
64
+ this.hits++;
65
+ return { embedding: entry.embedding, dimension: entry.embedding.length };
66
+ }
67
+ this.misses++;
68
+ return null;
69
+ }
70
+ set(hash, text, embedding, model) {
71
+ const now = Date.now();
72
+ this.cache.set(hash, {
73
+ embedding,
74
+ model,
75
+ hits: 1,
76
+ created: now,
77
+ accessed: now,
78
+ });
79
+ // Evict if over limit
80
+ if (this.cache.size > this.maxEntries) {
81
+ this.evictLRU(Math.ceil(this.maxEntries * 0.1));
82
+ }
83
+ }
84
+ has(hash) {
85
+ return this.cache.has(hash);
86
+ }
87
+ evictLRU(count) {
88
+ const entries = Array.from(this.cache.entries())
89
+ .sort((a, b) => a[1].accessed - b[1].accessed)
90
+ .slice(0, count);
91
+ for (const [key] of entries) {
92
+ this.cache.delete(key);
93
+ }
94
+ }
95
+ clear() {
96
+ this.cache.clear();
97
+ this.hits = 0;
98
+ this.misses = 0;
99
+ }
100
+ getStats() {
101
+ const entries = Array.from(this.cache.values());
102
+ const oldest = entries.length > 0 ? Math.min(...entries.map(e => e.created)) : 0;
103
+ const newest = entries.length > 0 ? Math.max(...entries.map(e => e.created)) : 0;
104
+ return {
105
+ totalEntries: this.cache.size,
106
+ hits: this.hits,
107
+ misses: this.misses,
108
+ hitRate: this.hits + this.misses > 0 ? this.hits / (this.hits + this.misses) : 0,
109
+ dbSizeBytes: this.cache.size * 384 * 4, // Approximate
110
+ oldestEntry: oldest,
111
+ newestEntry: newest,
112
+ backend: 'memory',
113
+ };
114
+ }
115
+ }
116
+ /**
117
+ * WASM SQLite cache (sql.js) - Cross-platform with persistence
118
+ * Works on Windows without native compilation
119
+ */
120
+ class WasmSqliteCache {
121
+ db = null;
122
+ config;
123
+ hits = 0;
124
+ misses = 0;
125
+ dirty = false;
126
+ saveTimeout = null;
127
+ constructor(config) {
128
+ this.config = config;
129
+ }
130
+ async init() {
131
+ if (this.db)
132
+ return;
133
+ // Ensure directory exists
134
+ const dir = join(homedir(), '.agentic-flow');
135
+ if (!existsSync(dir)) {
136
+ mkdirSync(dir, { recursive: true });
137
+ }
138
+ // Initialize sql.js
139
+ const SQL = await SqlJs();
140
+ // Load existing database or create new
141
+ const dbPath = this.config.dbPath.replace('.db', '-wasm.db');
142
+ try {
143
+ if (existsSync(dbPath)) {
144
+ const buffer = readFileSync(dbPath);
145
+ this.db = new SQL.Database(buffer);
146
+ }
147
+ else {
148
+ this.db = new SQL.Database();
149
+ }
150
+ }
151
+ catch {
152
+ this.db = new SQL.Database();
153
+ }
154
+ this.initSchema();
155
+ this.cleanupOldEntries();
156
+ }
157
+ initSchema() {
158
+ this.db.run(`
159
+ CREATE TABLE IF NOT EXISTS embeddings (
160
+ hash TEXT PRIMARY KEY,
161
+ text TEXT NOT NULL,
162
+ embedding BLOB NOT NULL,
163
+ dimension INTEGER NOT NULL,
164
+ model TEXT NOT NULL,
165
+ hits INTEGER DEFAULT 1,
166
+ created_at INTEGER NOT NULL,
167
+ last_accessed INTEGER NOT NULL
168
+ )
169
+ `);
170
+ this.db.run(`CREATE INDEX IF NOT EXISTS idx_last_accessed ON embeddings(last_accessed)`);
171
+ this.db.run(`CREATE INDEX IF NOT EXISTS idx_created_at ON embeddings(created_at)`);
172
+ }
173
+ save() {
174
+ // Debounce saves
175
+ if (this.saveTimeout)
176
+ return;
177
+ this.saveTimeout = setTimeout(() => {
178
+ try {
179
+ const data = this.db.export();
180
+ const buffer = Buffer.from(data);
181
+ const dbPath = this.config.dbPath.replace('.db', '-wasm.db');
182
+ writeFileSync(dbPath, buffer);
183
+ this.dirty = false;
184
+ }
185
+ catch (err) {
186
+ console.warn('[WasmSqliteCache] Save failed:', err);
187
+ }
188
+ this.saveTimeout = null;
189
+ }, 1000);
190
+ }
191
+ get(hash) {
192
+ if (!this.db)
193
+ return null;
194
+ const stmt = this.db.prepare(`SELECT embedding, dimension FROM embeddings WHERE hash = ?`);
195
+ stmt.bind([hash]);
196
+ if (stmt.step()) {
197
+ const row = stmt.getAsObject();
198
+ stmt.free();
199
+ this.hits++;
200
+ this.db.run(`UPDATE embeddings SET hits = hits + 1, last_accessed = ? WHERE hash = ?`, [Date.now(), hash]);
201
+ this.dirty = true;
202
+ this.save();
203
+ // Convert Uint8Array to Float32Array
204
+ const uint8 = row.embedding;
205
+ const float32 = new Float32Array(uint8.buffer, uint8.byteOffset, row.dimension);
206
+ return { embedding: float32, dimension: row.dimension };
207
+ }
208
+ stmt.free();
209
+ this.misses++;
210
+ return null;
211
+ }
212
+ set(hash, text, embedding, model) {
213
+ if (!this.db)
214
+ return;
215
+ const now = Date.now();
216
+ const buffer = new Uint8Array(embedding.buffer, embedding.byteOffset, embedding.byteLength);
217
+ this.db.run(`INSERT OR REPLACE INTO embeddings (hash, text, embedding, dimension, model, hits, created_at, last_accessed)
218
+ VALUES (?, ?, ?, ?, ?, 1, ?, ?)`, [hash, text, buffer, embedding.length, model, now, now]);
219
+ this.dirty = true;
220
+ this.maybeEvict();
221
+ this.save();
222
+ }
223
+ has(hash) {
224
+ if (!this.db)
225
+ return false;
226
+ const stmt = this.db.prepare(`SELECT 1 FROM embeddings WHERE hash = ? LIMIT 1`);
227
+ stmt.bind([hash]);
228
+ const found = stmt.step();
229
+ stmt.free();
230
+ return found;
231
+ }
232
+ maybeEvict() {
233
+ const countStmt = this.db.prepare(`SELECT COUNT(*) as count FROM embeddings`);
234
+ countStmt.step();
235
+ const count = countStmt.getAsObject().count;
236
+ countStmt.free();
237
+ if (count > this.config.maxEntries) {
238
+ const toEvict = Math.ceil(this.config.maxEntries * 0.1);
239
+ this.db.run(`DELETE FROM embeddings WHERE hash IN (
240
+ SELECT hash FROM embeddings ORDER BY last_accessed ASC LIMIT ?
241
+ )`, [toEvict]);
242
+ }
243
+ }
244
+ cleanupOldEntries() {
245
+ const cutoff = Date.now() - (this.config.maxAgeDays * 24 * 60 * 60 * 1000);
246
+ this.db.run(`DELETE FROM embeddings WHERE created_at < ?`, [cutoff]);
247
+ }
248
+ clear() {
249
+ if (this.db) {
250
+ this.db.run('DELETE FROM embeddings');
251
+ this.hits = 0;
252
+ this.misses = 0;
253
+ this.save();
254
+ }
255
+ }
256
+ close() {
257
+ if (this.saveTimeout) {
258
+ clearTimeout(this.saveTimeout);
259
+ // Force save
260
+ try {
261
+ const data = this.db.export();
262
+ const buffer = Buffer.from(data);
263
+ const dbPath = this.config.dbPath.replace('.db', '-wasm.db');
264
+ writeFileSync(dbPath, buffer);
265
+ }
266
+ catch { }
267
+ }
268
+ if (this.db) {
269
+ this.db.close();
270
+ this.db = null;
271
+ }
272
+ }
273
+ getStats() {
274
+ if (!this.db) {
275
+ return {
276
+ totalEntries: 0,
277
+ hits: this.hits,
278
+ misses: this.misses,
279
+ hitRate: 0,
280
+ dbSizeBytes: 0,
281
+ oldestEntry: 0,
282
+ newestEntry: 0,
283
+ backend: 'memory',
284
+ };
285
+ }
286
+ const countStmt = this.db.prepare(`SELECT COUNT(*) as count FROM embeddings`);
287
+ countStmt.step();
288
+ const count = countStmt.getAsObject().count;
289
+ countStmt.free();
290
+ const oldestStmt = this.db.prepare(`SELECT MIN(created_at) as oldest FROM embeddings`);
291
+ oldestStmt.step();
292
+ const oldest = oldestStmt.getAsObject().oldest || 0;
293
+ oldestStmt.free();
294
+ const newestStmt = this.db.prepare(`SELECT MAX(created_at) as newest FROM embeddings`);
295
+ newestStmt.step();
296
+ const newest = newestStmt.getAsObject().newest || 0;
297
+ newestStmt.free();
298
+ let dbSizeBytes = 0;
299
+ try {
300
+ const dbPath = this.config.dbPath.replace('.db', '-wasm.db');
301
+ const stats = statSync(dbPath);
302
+ dbSizeBytes = stats.size;
303
+ }
304
+ catch { }
305
+ return {
306
+ totalEntries: count,
307
+ hits: this.hits,
308
+ misses: this.misses,
309
+ hitRate: this.hits + this.misses > 0 ? this.hits / (this.hits + this.misses) : 0,
310
+ dbSizeBytes,
311
+ oldestEntry: oldest,
312
+ newestEntry: newest,
313
+ backend: 'file',
314
+ };
315
+ }
316
+ }
317
+ /**
318
+ * Native SQLite cache (better-sqlite3) - Fastest option
319
+ */
320
+ class SqliteCache {
321
+ db;
322
+ config;
323
+ hits = 0;
324
+ misses = 0;
325
+ // Prepared statements for performance
326
+ stmtGet;
327
+ stmtInsert;
328
+ stmtUpdateHits;
329
+ stmtCount;
330
+ stmtEvictOld;
331
+ stmtEvictLRU;
332
+ stmtHas;
333
+ constructor(config) {
334
+ this.config = config;
335
+ // Ensure directory exists
336
+ const dir = join(homedir(), '.agentic-flow');
337
+ if (!existsSync(dir)) {
338
+ mkdirSync(dir, { recursive: true });
339
+ }
340
+ // Open database with WAL mode for better concurrency
341
+ this.db = new BetterSqlite3(this.config.dbPath);
342
+ this.db.pragma('journal_mode = WAL');
343
+ this.db.pragma('synchronous = NORMAL');
344
+ this.db.pragma('cache_size = 10000');
345
+ this.initSchema();
346
+ this.prepareStatements();
347
+ this.cleanupOldEntries();
348
+ }
349
+ initSchema() {
350
+ this.db.exec(`
351
+ CREATE TABLE IF NOT EXISTS embeddings (
352
+ hash TEXT PRIMARY KEY,
353
+ text TEXT NOT NULL,
354
+ embedding BLOB NOT NULL,
355
+ dimension INTEGER NOT NULL,
356
+ model TEXT NOT NULL,
357
+ hits INTEGER DEFAULT 1,
358
+ created_at INTEGER NOT NULL,
359
+ last_accessed INTEGER NOT NULL
360
+ );
361
+
362
+ CREATE INDEX IF NOT EXISTS idx_last_accessed ON embeddings(last_accessed);
363
+ CREATE INDEX IF NOT EXISTS idx_created_at ON embeddings(created_at);
364
+ CREATE INDEX IF NOT EXISTS idx_model ON embeddings(model);
365
+ `);
366
+ }
367
+ prepareStatements() {
368
+ this.stmtGet = this.db.prepare(`
369
+ SELECT embedding, dimension FROM embeddings WHERE hash = ?
370
+ `);
371
+ this.stmtInsert = this.db.prepare(`
372
+ INSERT OR REPLACE INTO embeddings (hash, text, embedding, dimension, model, hits, created_at, last_accessed)
373
+ VALUES (?, ?, ?, ?, ?, 1, ?, ?)
374
+ `);
375
+ this.stmtUpdateHits = this.db.prepare(`
376
+ UPDATE embeddings SET hits = hits + 1, last_accessed = ? WHERE hash = ?
377
+ `);
378
+ this.stmtCount = this.db.prepare(`SELECT COUNT(*) as count FROM embeddings`);
379
+ this.stmtEvictOld = this.db.prepare(`
380
+ DELETE FROM embeddings WHERE created_at < ?
381
+ `);
382
+ this.stmtEvictLRU = this.db.prepare(`
383
+ DELETE FROM embeddings WHERE hash IN (
384
+ SELECT hash FROM embeddings ORDER BY last_accessed ASC LIMIT ?
385
+ )
386
+ `);
387
+ this.stmtHas = this.db.prepare(`SELECT 1 FROM embeddings WHERE hash = ? LIMIT 1`);
388
+ }
389
+ get(hash) {
390
+ const row = this.stmtGet.get(hash);
391
+ if (row) {
392
+ this.hits++;
393
+ this.stmtUpdateHits.run(Date.now(), hash);
394
+ return {
395
+ embedding: new Float32Array(row.embedding.buffer, row.embedding.byteOffset, row.dimension),
396
+ dimension: row.dimension,
397
+ };
398
+ }
399
+ this.misses++;
400
+ return null;
401
+ }
402
+ set(hash, text, embedding, model) {
403
+ const now = Date.now();
404
+ const buffer = Buffer.from(embedding.buffer, embedding.byteOffset, embedding.byteLength);
405
+ this.stmtInsert.run(hash, text, buffer, embedding.length, model, now, now);
406
+ this.maybeEvict();
407
+ }
408
+ has(hash) {
409
+ return this.stmtHas.get(hash) !== undefined;
410
+ }
411
+ maybeEvict() {
412
+ const count = this.stmtCount.get().count;
413
+ if (count > this.config.maxEntries) {
414
+ const toEvict = Math.ceil(this.config.maxEntries * 0.1);
415
+ this.stmtEvictLRU.run(toEvict);
416
+ }
417
+ }
418
+ cleanupOldEntries() {
419
+ const cutoff = Date.now() - (this.config.maxAgeDays * 24 * 60 * 60 * 1000);
420
+ this.stmtEvictOld.run(cutoff);
421
+ }
422
+ clear() {
423
+ this.db.exec('DELETE FROM embeddings');
424
+ this.hits = 0;
425
+ this.misses = 0;
426
+ }
427
+ vacuum() {
428
+ this.db.exec('VACUUM');
429
+ }
430
+ close() {
431
+ this.db.close();
432
+ }
433
+ getStats() {
434
+ const count = this.stmtCount.get().count;
435
+ const oldest = this.db.prepare(`SELECT MIN(created_at) as oldest FROM embeddings`).get();
436
+ const newest = this.db.prepare(`SELECT MAX(created_at) as newest FROM embeddings`).get();
437
+ let dbSizeBytes = 0;
438
+ try {
439
+ const stats = statSync(this.config.dbPath);
440
+ dbSizeBytes = stats.size;
441
+ }
442
+ catch { }
443
+ return {
444
+ totalEntries: count,
445
+ hits: this.hits,
446
+ misses: this.misses,
447
+ hitRate: this.hits + this.misses > 0 ? this.hits / (this.hits + this.misses) : 0,
448
+ dbSizeBytes,
449
+ oldestEntry: oldest.oldest || 0,
450
+ newestEntry: newest.newest || 0,
451
+ backend: 'sqlite',
452
+ };
453
+ }
454
+ }
455
+ /**
456
+ * EmbeddingCache - Auto-selects best available backend
457
+ *
458
+ * Backend priority:
459
+ * 1. Native SQLite (better-sqlite3) - Fastest, 9000x speedup
460
+ * 2. WASM SQLite (sql.js) - Cross-platform with persistence
461
+ * 3. Memory cache - Fallback, no persistence
462
+ */
463
+ export class EmbeddingCache {
464
+ backend;
465
+ config;
466
+ wasmInitPromise = null;
467
+ constructor(config = {}) {
468
+ this.config = { ...DEFAULT_CONFIG, ...config };
469
+ // Try native SQLite first (fastest)
470
+ if (nativeSqliteAvailable && !this.config.forceMemory) {
471
+ try {
472
+ this.backend = new SqliteCache(this.config);
473
+ return;
474
+ }
475
+ catch (err) {
476
+ console.warn('[EmbeddingCache] Native SQLite failed, trying WASM fallback');
477
+ }
478
+ }
479
+ // Try WASM SQLite second (cross-platform with persistence)
480
+ if (wasmSqliteAvailable && !this.config.forceMemory) {
481
+ this.backend = new WasmSqliteCache(this.config);
482
+ this.wasmInitPromise = this.backend.init().catch(err => {
483
+ console.warn('[EmbeddingCache] WASM SQLite init failed, using memory cache');
484
+ this.backend = new MemoryCache(this.config.maxEntries);
485
+ });
486
+ return;
487
+ }
488
+ // Fallback to memory cache
489
+ this.backend = new MemoryCache(this.config.maxEntries);
490
+ }
491
+ /**
492
+ * Ensure WASM backend is initialized (if using)
493
+ */
494
+ async ensureInit() {
495
+ if (this.wasmInitPromise) {
496
+ await this.wasmInitPromise;
497
+ }
498
+ }
499
+ /**
500
+ * Generate hash key for text + model combination
501
+ */
502
+ hashKey(text, model = 'default') {
503
+ return createHash('sha256').update(`${model}:${text}`).digest('hex').slice(0, 32);
504
+ }
505
+ /**
506
+ * Get embedding from cache
507
+ */
508
+ get(text, model = 'default') {
509
+ const hash = this.hashKey(text, model);
510
+ const result = this.backend.get(hash);
511
+ return result ? result.embedding : null;
512
+ }
513
+ /**
514
+ * Store embedding in cache
515
+ */
516
+ set(text, embedding, model = 'default') {
517
+ const hash = this.hashKey(text, model);
518
+ if (this.backend instanceof SqliteCache) {
519
+ this.backend.set(hash, text, embedding, model);
520
+ }
521
+ else {
522
+ this.backend.set(hash, text, embedding, model);
523
+ }
524
+ }
525
+ /**
526
+ * Check if text is cached
527
+ */
528
+ has(text, model = 'default') {
529
+ const hash = this.hashKey(text, model);
530
+ return this.backend.has(hash);
531
+ }
532
+ /**
533
+ * Get multiple embeddings at once
534
+ */
535
+ getMany(texts, model = 'default') {
536
+ const result = new Map();
537
+ for (const text of texts) {
538
+ const embedding = this.get(text, model);
539
+ if (embedding) {
540
+ result.set(text, embedding);
541
+ }
542
+ }
543
+ return result;
544
+ }
545
+ /**
546
+ * Store multiple embeddings at once
547
+ */
548
+ setMany(entries, model = 'default') {
549
+ for (const { text, embedding } of entries) {
550
+ this.set(text, embedding, model);
551
+ }
552
+ }
553
+ /**
554
+ * Get cache statistics
555
+ */
556
+ getStats() {
557
+ return this.backend.getStats();
558
+ }
559
+ /**
560
+ * Clear all cached embeddings
561
+ */
562
+ clear() {
563
+ this.backend.clear();
564
+ }
565
+ /**
566
+ * Vacuum database (SQLite only)
567
+ */
568
+ vacuum() {
569
+ if (this.backend instanceof SqliteCache) {
570
+ this.backend.vacuum();
571
+ }
572
+ }
573
+ /**
574
+ * Close database connection
575
+ */
576
+ close() {
577
+ if (this.backend instanceof SqliteCache || this.backend instanceof WasmSqliteCache) {
578
+ this.backend.close();
579
+ }
580
+ }
581
+ /**
582
+ * Check if using SQLite backend (native or WASM)
583
+ */
584
+ isSqliteBackend() {
585
+ return this.backend instanceof SqliteCache || this.backend instanceof WasmSqliteCache;
586
+ }
587
+ /**
588
+ * Get backend type
589
+ */
590
+ getBackendType() {
591
+ if (this.backend instanceof SqliteCache)
592
+ return 'native';
593
+ if (this.backend instanceof WasmSqliteCache)
594
+ return 'wasm';
595
+ return 'memory';
596
+ }
597
+ }
598
+ // Singleton instance
599
+ let cacheInstance = null;
600
+ /**
601
+ * Get the singleton embedding cache
602
+ */
603
+ export function getEmbeddingCache(config) {
604
+ if (!cacheInstance) {
605
+ cacheInstance = new EmbeddingCache(config);
606
+ }
607
+ return cacheInstance;
608
+ }
609
+ /**
610
+ * Reset the cache singleton (for testing)
611
+ */
612
+ export function resetEmbeddingCache() {
613
+ if (cacheInstance) {
614
+ cacheInstance.close();
615
+ cacheInstance = null;
616
+ }
617
+ }
618
+ /**
619
+ * Check if SQLite is available
620
+ */
621
+ export function isSqliteAvailable() {
622
+ return sqliteAvailable;
623
+ }
624
+ //# sourceMappingURL=EmbeddingCache.js.map