claude-flow 3.5.39 → 3.5.40

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.5.39",
3
+ "version": "3.5.40",
4
4
  "description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -0,0 +1,13 @@
1
+ /**
2
+ * V3 CLI Cleanup Command
3
+ * Removes project artifacts created by claude-flow/ruflo
4
+ *
5
+ * Created with ruv.io
6
+ */
7
+ import type { Command } from '../types.js';
8
+ /**
9
+ * Cleanup command definition
10
+ */
11
+ export declare const cleanupCommand: Command;
12
+ export default cleanupCommand;
13
+ //# sourceMappingURL=cleanup.d.ts.map
@@ -0,0 +1,218 @@
1
+ /**
2
+ * V3 CLI Cleanup Command
3
+ * Removes project artifacts created by claude-flow/ruflo
4
+ *
5
+ * Created with ruv.io
6
+ */
7
+ import { output } from '../output.js';
8
+ import { existsSync, statSync, rmSync, readdirSync } from 'fs';
9
+ import { join } from 'path';
10
+ /**
11
+ * Artifact directories and files that claude-flow/ruflo may create
12
+ */
13
+ const ARTIFACT_DIRS = [
14
+ { path: '.claude', description: 'Claude settings, helpers, agents' },
15
+ { path: '.claude-flow', description: 'Capabilities and configuration' },
16
+ { path: 'data', description: 'Memory databases' },
17
+ { path: '.swarm', description: 'Swarm state' },
18
+ { path: '.hive-mind', description: 'Consensus state' },
19
+ { path: 'coordination', description: 'Coordination data' },
20
+ { path: 'memory', description: 'Memory storage' },
21
+ ];
22
+ const ARTIFACT_FILES = [
23
+ { path: 'claude-flow.config.json', description: 'Claude Flow configuration' },
24
+ ];
25
+ /**
26
+ * Paths to preserve when --keep-config is set
27
+ */
28
+ const KEEP_CONFIG_PATHS = [
29
+ 'claude-flow.config.json',
30
+ join('.claude', 'settings.json'),
31
+ ];
32
+ /**
33
+ * Calculate the total size of a path (file or directory) in bytes
34
+ */
35
+ function getSize(fullPath) {
36
+ try {
37
+ const stat = statSync(fullPath);
38
+ if (stat.isFile()) {
39
+ return stat.size;
40
+ }
41
+ if (stat.isDirectory()) {
42
+ let total = 0;
43
+ const entries = readdirSync(fullPath, { withFileTypes: true });
44
+ for (const entry of entries) {
45
+ total += getSize(join(fullPath, entry.name));
46
+ }
47
+ return total;
48
+ }
49
+ }
50
+ catch {
51
+ // Permission errors, broken symlinks, etc.
52
+ }
53
+ return 0;
54
+ }
55
+ /**
56
+ * Format bytes into a human-readable string
57
+ */
58
+ function formatSize(bytes) {
59
+ if (bytes === 0)
60
+ return '0 B';
61
+ const units = ['B', 'KB', 'MB', 'GB'];
62
+ const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
63
+ const value = bytes / Math.pow(1024, i);
64
+ return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
65
+ }
66
+ /**
67
+ * Cleanup command definition
68
+ */
69
+ export const cleanupCommand = {
70
+ name: 'cleanup',
71
+ description: 'Remove project artifacts created by claude-flow/ruflo',
72
+ aliases: ['clean'],
73
+ options: [
74
+ {
75
+ name: 'dry-run',
76
+ short: 'n',
77
+ description: 'Show what would be removed without deleting (default behavior)',
78
+ type: 'boolean',
79
+ default: true,
80
+ },
81
+ {
82
+ name: 'force',
83
+ short: 'f',
84
+ description: 'Actually delete the artifacts',
85
+ type: 'boolean',
86
+ default: false,
87
+ },
88
+ {
89
+ name: 'keep-config',
90
+ short: 'k',
91
+ description: 'Preserve claude-flow.config.json and .claude/settings.json',
92
+ type: 'boolean',
93
+ default: false,
94
+ },
95
+ ],
96
+ examples: [
97
+ {
98
+ command: 'cleanup',
99
+ description: 'Show what would be removed (dry run)',
100
+ },
101
+ {
102
+ command: 'cleanup --force',
103
+ description: 'Remove all claude-flow artifacts',
104
+ },
105
+ {
106
+ command: 'cleanup --force --keep-config',
107
+ description: 'Remove artifacts but keep configuration files',
108
+ },
109
+ ],
110
+ action: async (ctx) => {
111
+ const force = ctx.flags.force === true;
112
+ const keepConfig = ctx.flags['keep-config'] === true;
113
+ const cwd = ctx.cwd;
114
+ const dryRun = !force;
115
+ output.writeln();
116
+ output.writeln(output.bold(dryRun
117
+ ? 'Claude Flow Cleanup (dry run)'
118
+ : 'Claude Flow Cleanup'));
119
+ output.writeln();
120
+ const found = [];
121
+ let totalSize = 0;
122
+ // Scan directories
123
+ for (const artifact of ARTIFACT_DIRS) {
124
+ const fullPath = join(cwd, artifact.path);
125
+ if (existsSync(fullPath)) {
126
+ const size = getSize(fullPath);
127
+ found.push({ path: artifact.path, description: artifact.description, size, type: 'dir' });
128
+ totalSize += size;
129
+ }
130
+ }
131
+ // Scan files
132
+ for (const artifact of ARTIFACT_FILES) {
133
+ const fullPath = join(cwd, artifact.path);
134
+ if (existsSync(fullPath)) {
135
+ const size = getSize(fullPath);
136
+ found.push({ path: artifact.path, description: artifact.description, size, type: 'file' });
137
+ totalSize += size;
138
+ }
139
+ }
140
+ if (found.length === 0) {
141
+ output.writeln(output.info('No claude-flow artifacts found in the current directory.'));
142
+ return { success: true, message: 'Nothing to clean' };
143
+ }
144
+ // Mark items that would be skipped due to --keep-config
145
+ if (keepConfig) {
146
+ for (const item of found) {
147
+ if (KEEP_CONFIG_PATHS.includes(item.path)) {
148
+ item.skipped = true;
149
+ }
150
+ }
151
+ }
152
+ // Display what was found
153
+ output.writeln(output.bold('Artifacts found:'));
154
+ output.writeln();
155
+ let removedCount = 0;
156
+ let removedSize = 0;
157
+ let skippedCount = 0;
158
+ for (const item of found) {
159
+ const sizeStr = formatSize(item.size);
160
+ const typeLabel = item.type === 'dir' ? 'dir ' : 'file';
161
+ if (item.skipped) {
162
+ output.writeln(output.dim(` [skip] ${typeLabel} ${item.path} (${sizeStr}) - ${item.description}`));
163
+ skippedCount++;
164
+ continue;
165
+ }
166
+ if (dryRun) {
167
+ output.writeln(output.warning(` [would remove] ${typeLabel} ${item.path} (${sizeStr}) - ${item.description}`));
168
+ }
169
+ else {
170
+ // Actually delete
171
+ try {
172
+ const fullPath = join(cwd, item.path);
173
+ if (item.type === 'dir') {
174
+ rmSync(fullPath, { recursive: true, force: true });
175
+ }
176
+ else {
177
+ rmSync(fullPath, { force: true });
178
+ }
179
+ output.writeln(output.success(` [removed] ${typeLabel} ${item.path} (${sizeStr}) - ${item.description}`));
180
+ removedCount++;
181
+ removedSize += item.size;
182
+ }
183
+ catch (err) {
184
+ const msg = err instanceof Error ? err.message : String(err);
185
+ output.writeln(output.error(` [failed] ${typeLabel} ${item.path} - ${msg}`));
186
+ }
187
+ }
188
+ }
189
+ // Summary
190
+ output.writeln();
191
+ output.writeln(output.bold('Summary:'));
192
+ if (dryRun) {
193
+ const actionable = found.filter(f => !f.skipped);
194
+ output.writeln(` Found ${actionable.length} artifact(s) totaling ${formatSize(totalSize)}`);
195
+ if (skippedCount > 0) {
196
+ output.writeln(` ${skippedCount} item(s) would be preserved (--keep-config)`);
197
+ }
198
+ output.writeln();
199
+ output.writeln(output.dim(' This was a dry run. Use --force to actually remove artifacts.'));
200
+ }
201
+ else {
202
+ output.writeln(` Removed ${removedCount} artifact(s) totaling ${formatSize(removedSize)}`);
203
+ if (skippedCount > 0) {
204
+ output.writeln(` Preserved ${skippedCount} item(s) (--keep-config)`);
205
+ }
206
+ }
207
+ output.writeln();
208
+ return {
209
+ success: true,
210
+ message: dryRun
211
+ ? `Dry run: ${found.length} artifact(s) found`
212
+ : `Removed ${removedCount} artifact(s)`,
213
+ data: { found, removedCount, removedSize, dryRun },
214
+ };
215
+ },
216
+ };
217
+ export default cleanupCommand;
218
+ //# sourceMappingURL=cleanup.js.map
@@ -29,6 +29,7 @@ export { ruvectorCommand } from './ruvector/index.js';
29
29
  export { hiveMindCommand } from './hive-mind.js';
30
30
  export { guidanceCommand } from './guidance.js';
31
31
  export { applianceCommand } from './appliance.js';
32
+ export { cleanupCommand } from './cleanup.js';
32
33
  export declare function getConfigCommand(): Promise<Command | undefined>;
33
34
  export declare function getMigrateCommand(): Promise<Command | undefined>;
34
35
  export declare function getWorkflowCommand(): Promise<Command | undefined>;
@@ -52,6 +53,7 @@ export declare function getIssuesCommand(): Promise<Command | undefined>;
52
53
  export declare function getRuvectorCommand(): Promise<Command | undefined>;
53
54
  export declare function getGuidanceCommand(): Promise<Command | undefined>;
54
55
  export declare function getApplianceCommand(): Promise<Command | undefined>;
56
+ export declare function getCleanupCommand(): Promise<Command | undefined>;
55
57
  /**
56
58
  * Core commands loaded synchronously (available immediately)
57
59
  * Advanced commands loaded on-demand for faster startup
@@ -63,6 +63,7 @@ const commandLoaders = {
63
63
  appliance: () => import('./appliance.js'),
64
64
  'appliance-advanced': () => import('./appliance-advanced.js'),
65
65
  'transfer-store': () => import('./transfer-store.js'),
66
+ cleanup: () => import('./cleanup.js'),
66
67
  };
67
68
  // Cache for loaded commands
68
69
  const loadedCommands = new Map();
@@ -132,6 +133,7 @@ import updateCommand from './update.js';
132
133
  import { processCommand } from './process.js';
133
134
  import { guidanceCommand } from './guidance.js';
134
135
  import { applianceCommand } from './appliance.js';
136
+ import { cleanupCommand } from './cleanup.js';
135
137
  // Pre-populate cache with core commands
136
138
  loadedCommands.set('init', initCommand);
137
139
  loadedCommands.set('start', startCommand);
@@ -152,6 +154,7 @@ loadedCommands.set('security', securityCommand);
152
154
  loadedCommands.set('ruvector', ruvectorCommand);
153
155
  loadedCommands.set('hive-mind', hiveMindCommand);
154
156
  loadedCommands.set('guidance', guidanceCommand);
157
+ loadedCommands.set('cleanup', cleanupCommand);
155
158
  // =============================================================================
156
159
  // Exports (maintain backwards compatibility)
157
160
  // =============================================================================
@@ -176,6 +179,7 @@ export { ruvectorCommand } from './ruvector/index.js';
176
179
  export { hiveMindCommand } from './hive-mind.js';
177
180
  export { guidanceCommand } from './guidance.js';
178
181
  export { applianceCommand } from './appliance.js';
182
+ export { cleanupCommand } from './cleanup.js';
179
183
  // Lazy-loaded command re-exports (for backwards compatibility, but async-only)
180
184
  export async function getConfigCommand() { return loadCommand('config'); }
181
185
  export async function getMigrateCommand() { return loadCommand('migrate'); }
@@ -200,6 +204,7 @@ export async function getIssuesCommand() { return loadCommand('issues'); }
200
204
  export async function getRuvectorCommand() { return loadCommand('ruvector'); }
201
205
  export async function getGuidanceCommand() { return loadCommand('guidance'); }
202
206
  export async function getApplianceCommand() { return loadCommand('appliance'); }
207
+ export async function getCleanupCommand() { return loadCommand('cleanup'); }
203
208
  /**
204
209
  * Core commands loaded synchronously (available immediately)
205
210
  * Advanced commands loaded on-demand for faster startup
@@ -225,6 +230,7 @@ export const commands = [
225
230
  ruvectorCommand,
226
231
  hiveMindCommand,
227
232
  guidanceCommand,
233
+ cleanupCommand,
228
234
  ];
229
235
  /**
230
236
  * Commands organized by category for help display
@@ -273,6 +279,7 @@ export const commandsByCategory = {
273
279
  updateCommand,
274
280
  processCommand,
275
281
  applianceCommand,
282
+ cleanupCommand,
276
283
  ],
277
284
  };
278
285
  /**
@@ -34,6 +34,9 @@ import { coordinationTools } from './mcp-tools/coordination-tools.js';
34
34
  import { browserTools } from './mcp-tools/browser-tools.js';
35
35
  // Phase 6: AgentDB v3 controller tools
36
36
  import { agentdbTools } from './mcp-tools/agentdb-tools.js';
37
+ // RuVector WASM tools
38
+ import { ruvllmWasmTools } from './mcp-tools/ruvllm-tools.js';
39
+ import { wasmAgentTools } from './mcp-tools/wasm-agent-tools.js';
37
40
  /**
38
41
  * MCP Tool Registry
39
42
  * Maps tool names to their handler functions
@@ -73,6 +76,9 @@ registerTools([
73
76
  ...browserTools,
74
77
  // Phase 6: AgentDB v3 controller tools
75
78
  ...agentdbTools,
79
+ // RuVector WASM tools
80
+ ...ruvllmWasmTools,
81
+ ...wasmAgentTools,
76
82
  ]);
77
83
  /**
78
84
  * MCP Client Error
@@ -20,4 +20,6 @@ export { transferTools } from './transfer-tools.js';
20
20
  export { securityTools } from './security-tools.js';
21
21
  export { embeddingsTools } from './embeddings-tools.js';
22
22
  export { claimsTools } from './claims-tools.js';
23
+ export { wasmAgentTools } from './wasm-agent-tools.js';
24
+ export { ruvllmWasmTools } from './ruvllm-tools.js';
23
25
  //# sourceMappingURL=index.d.ts.map
@@ -19,4 +19,6 @@ export { transferTools } from './transfer-tools.js';
19
19
  export { securityTools } from './security-tools.js';
20
20
  export { embeddingsTools } from './embeddings-tools.js';
21
21
  export { claimsTools } from './claims-tools.js';
22
+ export { wasmAgentTools } from './wasm-agent-tools.js';
23
+ export { ruvllmWasmTools } from './ruvllm-tools.js';
22
24
  //# sourceMappingURL=index.js.map
@@ -1315,6 +1315,42 @@ export async function loadEmbeddingModel(options) {
1315
1315
  loadTime: Date.now() - startTime
1316
1316
  };
1317
1317
  }
1318
+ // Fallback: Check for ruvector ONNX embedder (bundled MiniLM-L6-v2 since v0.2.15)
1319
+ // v0.2.16: LoRA B=0 fix makes AdaptiveEmbedder safe (identity when untrained)
1320
+ // Note: isReady() returns false until first embed() call (lazy init), so we
1321
+ // skip the isReady() gate and verify with a probe embed instead.
1322
+ const ruvector = await import('ruvector').catch(() => null);
1323
+ if (ruvector?.initOnnxEmbedder) {
1324
+ try {
1325
+ await ruvector.initOnnxEmbedder();
1326
+ // Fallback: OptimizedOnnxEmbedder (raw ONNX, lazy-inits on first embed)
1327
+ const onnxEmb = ruvector.getOptimizedOnnxEmbedder?.();
1328
+ if (onnxEmb?.embed) {
1329
+ // Probe embed to trigger lazy ONNX init and verify it works
1330
+ const probe = await onnxEmb.embed('test');
1331
+ if (probe && probe.length > 0 && (Array.isArray(probe) ? probe.some((v) => v !== 0) : true)) {
1332
+ if (verbose) {
1333
+ console.log(`Loading ruvector ONNX embedder (all-MiniLM-L6-v2, ${probe.length}d)...`);
1334
+ }
1335
+ embeddingModelState = {
1336
+ loaded: true,
1337
+ model: (text) => onnxEmb.embed(text),
1338
+ tokenizer: null,
1339
+ dimensions: probe.length || 384
1340
+ };
1341
+ return {
1342
+ success: true,
1343
+ dimensions: probe.length || 384,
1344
+ modelName: 'ruvector/onnx',
1345
+ loadTime: Date.now() - startTime
1346
+ };
1347
+ }
1348
+ }
1349
+ }
1350
+ catch {
1351
+ // ruvector ONNX init failed, continue to next fallback
1352
+ }
1353
+ }
1318
1354
  // Legacy fallback: Check for agentic-flow core embeddings
1319
1355
  const agenticFlow = await import('agentic-flow').catch(() => null);
1320
1356
  if (agenticFlow && agenticFlow.embeddings) {
@@ -1378,12 +1414,17 @@ export async function generateEmbedding(text) {
1378
1414
  if (state.model && typeof state.model === 'function') {
1379
1415
  try {
1380
1416
  const output = await state.model(text, { pooling: 'mean', normalize: true });
1381
- const embedding = Array.from(output.data);
1382
- return {
1383
- embedding,
1384
- dimensions: embedding.length,
1385
- model: 'onnx'
1386
- };
1417
+ // Handle both @xenova/transformers (output.data) and ruvector (plain array) formats
1418
+ const embedding = output?.data
1419
+ ? Array.from(output.data)
1420
+ : Array.isArray(output) ? output : null;
1421
+ if (embedding) {
1422
+ return {
1423
+ embedding,
1424
+ dimensions: embedding.length,
1425
+ model: 'onnx'
1426
+ };
1427
+ }
1387
1428
  }
1388
1429
  catch {
1389
1430
  // Fall through to fallback
@@ -1774,13 +1815,18 @@ export async function searchEntries(options) {
1774
1815
  const fileBuffer = fs.readFileSync(dbPath);
1775
1816
  const db = new SQL.Database(fileBuffer);
1776
1817
  // Get entries with embeddings
1777
- const entries = db.exec(`
1778
- SELECT id, key, namespace, content, embedding
1779
- FROM memory_entries
1780
- WHERE status = 'active'
1781
- ${namespace !== 'all' ? `AND namespace = '${namespace.replace(/'/g, "''")}'` : ''}
1782
- LIMIT 1000
1783
- `);
1818
+ const searchStmt = db.prepare(namespace !== 'all'
1819
+ ? `SELECT id, key, namespace, content, embedding FROM memory_entries WHERE status = 'active' AND namespace = ? LIMIT 1000`
1820
+ : `SELECT id, key, namespace, content, embedding FROM memory_entries WHERE status = 'active' LIMIT 1000`);
1821
+ if (namespace !== 'all') {
1822
+ searchStmt.bind([namespace]);
1823
+ }
1824
+ const searchRows = [];
1825
+ while (searchStmt.step()) {
1826
+ searchRows.push(searchStmt.get());
1827
+ }
1828
+ searchStmt.free();
1829
+ const entries = searchRows.length > 0 ? [{ values: searchRows }] : [];
1784
1830
  const results = [];
1785
1831
  if (entries[0]?.values) {
1786
1832
  for (const row of entries[0].values) {
@@ -1880,21 +1926,37 @@ export async function listEntries(options) {
1880
1926
  const fileBuffer = fs.readFileSync(dbPath);
1881
1927
  const db = new SQL.Database(fileBuffer);
1882
1928
  // Get total count
1883
- const countQuery = namespace
1884
- ? `SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active' AND namespace = '${namespace.replace(/'/g, "''")}'`
1885
- : `SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`;
1886
- const countResult = db.exec(countQuery);
1929
+ const countStmt = namespace
1930
+ ? db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active' AND namespace = ?`)
1931
+ : db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`);
1932
+ if (namespace) {
1933
+ countStmt.bind([namespace]);
1934
+ }
1935
+ const countRows = [];
1936
+ while (countStmt.step()) {
1937
+ countRows.push(countStmt.get());
1938
+ }
1939
+ countStmt.free();
1940
+ const countResult = countRows.length > 0 ? [{ values: countRows }] : [];
1887
1941
  const total = countResult[0]?.values?.[0]?.[0] || 0;
1888
1942
  // Get entries
1889
- const listQuery = `
1890
- SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at
1891
- FROM memory_entries
1892
- WHERE status = 'active'
1893
- ${namespace ? `AND namespace = '${namespace.replace(/'/g, "''")}'` : ''}
1894
- ORDER BY updated_at DESC
1895
- LIMIT ${limit} OFFSET ${offset}
1896
- `;
1897
- const result = db.exec(listQuery);
1943
+ const safeLimit = parseInt(String(limit), 10) || 100;
1944
+ const safeOffset = parseInt(String(offset), 10) || 0;
1945
+ const listStmt = namespace
1946
+ ? db.prepare(`SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at FROM memory_entries WHERE status = 'active' AND namespace = ? ORDER BY updated_at DESC LIMIT ? OFFSET ?`)
1947
+ : db.prepare(`SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at FROM memory_entries WHERE status = 'active' ORDER BY updated_at DESC LIMIT ? OFFSET ?`);
1948
+ if (namespace) {
1949
+ listStmt.bind([namespace, safeLimit, safeOffset]);
1950
+ }
1951
+ else {
1952
+ listStmt.bind([safeLimit, safeOffset]);
1953
+ }
1954
+ const listRows = [];
1955
+ while (listStmt.step()) {
1956
+ listRows.push(listStmt.get());
1957
+ }
1958
+ listStmt.free();
1959
+ const result = listRows.length > 0 ? [{ values: listRows }] : [];
1898
1960
  const entries = [];
1899
1961
  if (result[0]?.values) {
1900
1962
  for (const row of result[0].values) {
@@ -1949,14 +2011,21 @@ export async function getEntry(options) {
1949
2011
  const fileBuffer = fs.readFileSync(dbPath);
1950
2012
  const db = new SQL.Database(fileBuffer);
1951
2013
  // Find entry by key
1952
- const result = db.exec(`
2014
+ const getStmt = db.prepare(`
1953
2015
  SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags
1954
2016
  FROM memory_entries
1955
2017
  WHERE status = 'active'
1956
- AND key = '${key.replace(/'/g, "''")}'
1957
- AND namespace = '${namespace.replace(/'/g, "''")}'
2018
+ AND key = ?
2019
+ AND namespace = ?
1958
2020
  LIMIT 1
1959
2021
  `);
2022
+ getStmt.bind([key, namespace]);
2023
+ const getRows = [];
2024
+ while (getStmt.step()) {
2025
+ getRows.push(getStmt.get());
2026
+ }
2027
+ getStmt.free();
2028
+ const result = getRows.length > 0 ? [{ values: getRows }] : [];
1960
2029
  if (!result[0]?.values?.[0]) {
1961
2030
  db.close();
1962
2031
  return { success: true, found: false };
@@ -1966,8 +2035,8 @@ export async function getEntry(options) {
1966
2035
  db.run(`
1967
2036
  UPDATE memory_entries
1968
2037
  SET access_count = access_count + 1, last_accessed_at = strftime('%s', 'now') * 1000
1969
- WHERE id = '${String(id).replace(/'/g, "''")}'
1970
- `);
2038
+ WHERE id = ?
2039
+ `, [String(id)]);
1971
2040
  // Save updated database
1972
2041
  const data = db.export();
1973
2042
  fs.writeFileSync(dbPath, Buffer.from(data));
@@ -2039,13 +2108,20 @@ export async function deleteEntry(options) {
2039
2108
  const fileBuffer = fs.readFileSync(dbPath);
2040
2109
  const db = new SQL.Database(fileBuffer);
2041
2110
  // Check if entry exists first
2042
- const checkResult = db.exec(`
2111
+ const checkStmt = db.prepare(`
2043
2112
  SELECT id FROM memory_entries
2044
2113
  WHERE status = 'active'
2045
- AND key = '${key.replace(/'/g, "''")}'
2046
- AND namespace = '${namespace.replace(/'/g, "''")}'
2114
+ AND key = ?
2115
+ AND namespace = ?
2047
2116
  LIMIT 1
2048
2117
  `);
2118
+ checkStmt.bind([key, namespace]);
2119
+ const checkRows = [];
2120
+ while (checkStmt.step()) {
2121
+ checkRows.push(checkStmt.get());
2122
+ }
2123
+ checkStmt.free();
2124
+ const checkResult = checkRows.length > 0 ? [{ values: checkRows }] : [];
2049
2125
  if (!checkResult[0]?.values?.[0]) {
2050
2126
  // Get remaining count before closing
2051
2127
  const countResult = db.exec(`SELECT COUNT(*) FROM memory_entries WHERE status = 'active'`);
@@ -2069,10 +2145,10 @@ export async function deleteEntry(options) {
2069
2145
  SET status = 'deleted',
2070
2146
  embedding = NULL,
2071
2147
  updated_at = strftime('%s', 'now') * 1000
2072
- WHERE key = '${key.replace(/'/g, "''")}'
2073
- AND namespace = '${namespace.replace(/'/g, "''")}'
2148
+ WHERE key = ?
2149
+ AND namespace = ?
2074
2150
  AND status = 'active'
2075
- `);
2151
+ `, [key, namespace]);
2076
2152
  // Get remaining count
2077
2153
  const countResult = db.exec(`SELECT COUNT(*) FROM memory_entries WHERE status = 'active'`);
2078
2154
  const remainingEntries = countResult[0]?.values?.[0]?.[0] || 0;
@@ -23,6 +23,8 @@ export { FlashAttention, getFlashAttention, resetFlashAttention, computeAttentio
23
23
  export { LoRAAdapter, getLoRAAdapter, resetLoRAAdapter, createLoRAAdapter, adaptEmbedding, trainLoRA, getLoRAStats, DEFAULT_RANK, DEFAULT_ALPHA, INPUT_DIM as LORA_INPUT_DIM, OUTPUT_DIM as LORA_OUTPUT_DIM, type LoRAConfig, type LoRAWeights, type AdaptationResult, type LoRAStats, } from './lora-adapter.js';
24
24
  export { ModelRouter, getModelRouter, resetModelRouter, createModelRouter, routeToModel, routeToModelFull, analyzeTaskComplexity, getModelRouterStats, recordModelOutcome, MODEL_CAPABILITIES, COMPLEXITY_INDICATORS, type ClaudeModel, type ModelRouterConfig, type ModelRoutingResult, type ComplexityAnalysis, } from './model-router.js';
25
25
  export { SemanticRouter, createSemanticRouter, type Intent, type RouteResult, type RouterConfig, } from './semantic-router.js';
26
+ export { isRuvllmWasmAvailable, initRuvllmWasm, getRuvllmStatus, createHnswRouter, createSonaInstant, createMicroLora, formatChat, createKvCache, createGenerateConfig, createBufferPool, createInferenceArena, HNSW_MAX_SAFE_PATTERNS, type HnswRouterConfig, type HnswPattern, type HnswRouteResult, type SonaConfig, type MicroLoraConfig, type ChatMessage, type GenerateOptions, type RuvllmStatus, } from './ruvllm-wasm.js';
27
+ export { isAgentWasmAvailable, initAgentWasm, createWasmAgent, promptWasmAgent, executeWasmTool, getWasmAgent, listWasmAgents, terminateWasmAgent, getWasmAgentState, getWasmAgentTools, getWasmAgentTodos, exportWasmState, createWasmMcpServer, listGalleryTemplates, getGalleryCount, getGalleryCategories, searchGalleryTemplates, getGalleryTemplate, createAgentFromTemplate, buildRvfContainer, buildRvfFromTemplate, type WasmAgentConfig, type WasmAgentInfo, type GalleryTemplate, type GalleryTemplateDetail, type ToolResult, } from './agent-wasm.js';
26
28
  /**
27
29
  * Check if ruvector packages are available
28
30
  */
@@ -33,6 +33,10 @@ export { FlashAttention, getFlashAttention, resetFlashAttention, computeAttentio
33
33
  export { LoRAAdapter, getLoRAAdapter, resetLoRAAdapter, createLoRAAdapter, adaptEmbedding, trainLoRA, getLoRAStats, DEFAULT_RANK, DEFAULT_ALPHA, INPUT_DIM as LORA_INPUT_DIM, OUTPUT_DIM as LORA_OUTPUT_DIM, } from './lora-adapter.js';
34
34
  export { ModelRouter, getModelRouter, resetModelRouter, createModelRouter, routeToModel, routeToModelFull, analyzeTaskComplexity, getModelRouterStats, recordModelOutcome, MODEL_CAPABILITIES, COMPLEXITY_INDICATORS, } from './model-router.js';
35
35
  export { SemanticRouter, createSemanticRouter, } from './semantic-router.js';
36
+ // ── RuVector LLM WASM (inference utilities) ─────────────────
37
+ export { isRuvllmWasmAvailable, initRuvllmWasm, getRuvllmStatus, createHnswRouter, createSonaInstant, createMicroLora, formatChat, createKvCache, createGenerateConfig, createBufferPool, createInferenceArena, HNSW_MAX_SAFE_PATTERNS, } from './ruvllm-wasm.js';
38
+ // ── Agent WASM (sandboxed agent runtime) ────────────────────
39
+ export { isAgentWasmAvailable, initAgentWasm, createWasmAgent, promptWasmAgent, executeWasmTool, getWasmAgent, listWasmAgents, terminateWasmAgent, getWasmAgentState, getWasmAgentTools, getWasmAgentTodos, exportWasmState, createWasmMcpServer, listGalleryTemplates, getGalleryCount, getGalleryCategories, searchGalleryTemplates, getGalleryTemplate, createAgentFromTemplate, buildRvfContainer, buildRvfFromTemplate, } from './agent-wasm.js';
36
40
  /**
37
41
  * Check if ruvector packages are available
38
42
  */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.5.39",
3
+ "version": "3.5.40",
4
4
  "type": "module",
5
5
  "description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -75,7 +75,6 @@
75
75
  "test": "vitest run",
76
76
  "test:plugin-store": "npx tsx src/plugins/tests/standalone-test.ts",
77
77
  "test:pattern-store": "npx tsx src/transfer/store/tests/standalone-test.ts",
78
- "preinstall": "node bin/preinstall.cjs || true",
79
78
  "prepublishOnly": "cp ../../../README.md ./README.md",
80
79
  "release": "npm version prerelease --preid=alpha && npm run publish:all",
81
80
  "publish:all": "./scripts/publish.sh"
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- // Preinstall hook — no-op (cache repair removed in 3.1.0-alpha.53)