claude-flow 3.6.5 → 3.6.7
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/.claude/scheduled_tasks.lock +1 -0
- package/package.json +1 -1
- package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js +93 -32
- package/v3/@claude-flow/cli/dist/src/mcp-tools/embeddings-tools.js +3 -3
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.d.ts +15 -0
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +45 -0
- package/v3/@claude-flow/cli/dist/src/memory/rabitq-index.js +45 -29
- package/v3/@claude-flow/cli/package.json +1 -1
- package/v3/@claude-flow/guidance/dist/analyzer.js +33 -1
- package/v3/@claude-flow/guidance/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"sessionId":"ea43bca2-cc37-44fb-97ff-f1c914a31fb1","pid":12017,"procStart":"Tue Apr 28 01:25:58 2026","acquiredAt":1777350938971}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.7",
|
|
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",
|
|
@@ -8,47 +8,97 @@ import { validateIdentifier, validateText } from './validate-input.js';
|
|
|
8
8
|
// Session registry for multi-session support
|
|
9
9
|
const browserSessions = new Map();
|
|
10
10
|
/**
|
|
11
|
-
* Execute agent-browser CLI command
|
|
11
|
+
* Execute agent-browser CLI command.
|
|
12
|
+
* Tries global agent-browser first, falls back to npx if ENOENT.
|
|
12
13
|
*/
|
|
13
14
|
async function execBrowserCommand(args, session = 'default') {
|
|
14
15
|
const { execFileSync } = await import('child_process');
|
|
16
|
+
const fullArgs = ['--session', session, '--json', ...args];
|
|
17
|
+
let result;
|
|
15
18
|
try {
|
|
16
|
-
|
|
17
|
-
const result = execFileSync('agent-browser', fullArgs, {
|
|
19
|
+
result = execFileSync('agent-browser', fullArgs, {
|
|
18
20
|
encoding: 'utf-8',
|
|
19
21
|
timeout: 30000,
|
|
20
22
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const err = error;
|
|
26
|
+
if (err.code === 'ENOENT') {
|
|
27
|
+
try {
|
|
28
|
+
result = execFileSync('npx', ['--yes', 'agent-browser', ...fullArgs], {
|
|
29
|
+
encoding: 'utf-8',
|
|
30
|
+
timeout: 60000,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch (npxError) {
|
|
34
|
+
const npxErr = npxError;
|
|
35
|
+
return {
|
|
36
|
+
content: [{
|
|
37
|
+
type: 'text',
|
|
38
|
+
text: JSON.stringify({
|
|
39
|
+
success: false,
|
|
40
|
+
error: npxErr.code === 'ENOENT'
|
|
41
|
+
? 'Neither agent-browser nor npx found. Install with: npm i -g agent-browser'
|
|
42
|
+
: npxErr instanceof Error ? npxErr.message : String(npxError),
|
|
43
|
+
}),
|
|
44
|
+
}],
|
|
45
|
+
isError: true,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
27
48
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
49
|
+
else {
|
|
50
|
+
return {
|
|
51
|
+
content: [{
|
|
52
|
+
type: 'text',
|
|
53
|
+
text: JSON.stringify({
|
|
54
|
+
success: false,
|
|
55
|
+
error: err instanceof Error ? err.message : String(error),
|
|
56
|
+
}),
|
|
57
|
+
}],
|
|
58
|
+
isError: true,
|
|
59
|
+
};
|
|
32
60
|
}
|
|
33
|
-
return {
|
|
34
|
-
content: [{
|
|
35
|
-
type: 'text',
|
|
36
|
-
text: JSON.stringify(data, null, 2),
|
|
37
|
-
}],
|
|
38
|
-
};
|
|
39
61
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
type: 'text',
|
|
44
|
-
text: JSON.stringify({
|
|
45
|
-
success: false,
|
|
46
|
-
error: error instanceof Error ? error.message : String(error),
|
|
47
|
-
}),
|
|
48
|
-
}],
|
|
49
|
-
isError: true,
|
|
50
|
-
};
|
|
62
|
+
let data;
|
|
63
|
+
try {
|
|
64
|
+
data = JSON.parse(result);
|
|
51
65
|
}
|
|
66
|
+
catch {
|
|
67
|
+
data = result.trim();
|
|
68
|
+
}
|
|
69
|
+
const sessionInfo = browserSessions.get(session);
|
|
70
|
+
if (sessionInfo) {
|
|
71
|
+
sessionInfo.lastActivity = new Date().toISOString();
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
content: [{
|
|
75
|
+
type: 'text',
|
|
76
|
+
text: JSON.stringify(data, null, 2),
|
|
77
|
+
}],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Read a sysctl value, returning the trimmed string or null.
|
|
82
|
+
*/
|
|
83
|
+
function readSysctl(name) {
|
|
84
|
+
try {
|
|
85
|
+
const { readFileSync, existsSync } = require('fs');
|
|
86
|
+
const p = `/proc/sys/kernel/${name}`;
|
|
87
|
+
if (existsSync(p))
|
|
88
|
+
return readFileSync(p, 'utf-8').trim();
|
|
89
|
+
}
|
|
90
|
+
catch { /* not Linux or can't read */ }
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Detect if Linux needs --no-sandbox for Chrome.
|
|
95
|
+
* Checks both legacy userns flag and Ubuntu 24.04+ AppArmor restriction.
|
|
96
|
+
*/
|
|
97
|
+
function needsNoSandbox() {
|
|
98
|
+
if (process.platform !== 'linux')
|
|
99
|
+
return false;
|
|
100
|
+
return readSysctl('unprivileged_userns_clone') === '0' ||
|
|
101
|
+
readSysctl('apparmor_restrict_unprivileged_userns') === '1';
|
|
52
102
|
}
|
|
53
103
|
/**
|
|
54
104
|
* Browser MCP Tools
|
|
@@ -72,6 +122,11 @@ export const browserTools = [
|
|
|
72
122
|
enum: ['load', 'domcontentloaded', 'networkidle'],
|
|
73
123
|
description: 'Wait condition',
|
|
74
124
|
},
|
|
125
|
+
args: {
|
|
126
|
+
type: 'array',
|
|
127
|
+
items: { type: 'string' },
|
|
128
|
+
description: 'Additional Chrome launch args (e.g., ["--no-sandbox", "--disable-dev-shm-usage"])',
|
|
129
|
+
},
|
|
75
130
|
},
|
|
76
131
|
required: ['url'],
|
|
77
132
|
},
|
|
@@ -85,9 +140,15 @@ export const browserTools = [
|
|
|
85
140
|
return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: vS.error }) }], isError: true };
|
|
86
141
|
}
|
|
87
142
|
const { url, session, waitUntil } = input;
|
|
143
|
+
const launchArgs = input.args || [];
|
|
144
|
+
if (needsNoSandbox() && !launchArgs.includes('--no-sandbox')) {
|
|
145
|
+
launchArgs.push('--no-sandbox');
|
|
146
|
+
}
|
|
88
147
|
const args = ['open', url];
|
|
89
148
|
if (waitUntil)
|
|
90
149
|
args.push('--wait-until', waitUntil);
|
|
150
|
+
if (launchArgs.length > 0)
|
|
151
|
+
args.push('--args', launchArgs.join(' '));
|
|
91
152
|
// Create session if new
|
|
92
153
|
const sessionId = session || 'default';
|
|
93
154
|
if (!browserSessions.has(sessionId)) {
|
|
@@ -369,13 +430,13 @@ export const browserTools = [
|
|
|
369
430
|
},
|
|
370
431
|
{
|
|
371
432
|
name: 'browser_hover',
|
|
372
|
-
description: 'Hover over an element',
|
|
433
|
+
description: 'Hover over an element using ref (@e1) or CSS selector',
|
|
373
434
|
category: 'browser',
|
|
374
435
|
tags: ['interaction'],
|
|
375
436
|
inputSchema: {
|
|
376
437
|
type: 'object',
|
|
377
438
|
properties: {
|
|
378
|
-
target: { type: 'string', description: 'Element ref or CSS selector' },
|
|
439
|
+
target: { type: 'string', description: 'Element ref (@e1) or CSS selector' },
|
|
379
440
|
session: { type: 'string', description: 'Session ID' },
|
|
380
441
|
},
|
|
381
442
|
required: ['target'],
|
|
@@ -412,7 +412,7 @@ export const embeddingsTools = [
|
|
|
412
412
|
query,
|
|
413
413
|
limit: topK,
|
|
414
414
|
threshold,
|
|
415
|
-
namespace: namespace || '
|
|
415
|
+
namespace: namespace || 'all'
|
|
416
416
|
});
|
|
417
417
|
const searchTime = (performance.now() - startTime).toFixed(2);
|
|
418
418
|
return {
|
|
@@ -428,7 +428,7 @@ export const embeddingsTools = [
|
|
|
428
428
|
model: config.model,
|
|
429
429
|
topK,
|
|
430
430
|
threshold,
|
|
431
|
-
namespace: namespace || '
|
|
431
|
+
namespace: namespace || 'all',
|
|
432
432
|
searchTime: `${searchTime}ms`,
|
|
433
433
|
indexType: config.hyperbolic.enabled ? 'HNSW (hyperbolic)' : 'HNSW (euclidean)',
|
|
434
434
|
resultCount: searchResult.results.length
|
|
@@ -446,7 +446,7 @@ export const embeddingsTools = [
|
|
|
446
446
|
model: config.model,
|
|
447
447
|
topK,
|
|
448
448
|
threshold,
|
|
449
|
-
namespace: namespace || '
|
|
449
|
+
namespace: namespace || 'all',
|
|
450
450
|
searchTime: `${searchTime}ms`,
|
|
451
451
|
indexType: config.hyperbolic.enabled ? 'HNSW (hyperbolic)' : 'HNSW (euclidean)',
|
|
452
452
|
},
|
|
@@ -405,4 +405,19 @@ export declare function bridgeContextSynthesize(params: {
|
|
|
405
405
|
export declare function bridgeSemanticRoute(params: {
|
|
406
406
|
input: string;
|
|
407
407
|
}): Promise<any>;
|
|
408
|
+
/**
|
|
409
|
+
* Export all embeddings from the bridge's better-sqlite3 connection.
|
|
410
|
+
* Used by RaBitQ to build its index from the same data that memory_store writes.
|
|
411
|
+
* Returns null if bridge is unavailable (caller falls back to sql.js).
|
|
412
|
+
*/
|
|
413
|
+
export declare function bridgeGetAllEmbeddings(options?: {
|
|
414
|
+
dimensions?: number;
|
|
415
|
+
limit?: number;
|
|
416
|
+
dbPath?: string;
|
|
417
|
+
}): Promise<Array<{
|
|
418
|
+
id: string;
|
|
419
|
+
key: string;
|
|
420
|
+
namespace: string;
|
|
421
|
+
embedding: number[];
|
|
422
|
+
}> | null>;
|
|
408
423
|
//# sourceMappingURL=memory-bridge.d.ts.map
|
|
@@ -1554,6 +1554,51 @@ export async function bridgeSemanticRoute(params) {
|
|
|
1554
1554
|
return { route: null, error: e.message };
|
|
1555
1555
|
}
|
|
1556
1556
|
}
|
|
1557
|
+
// ===== RaBitQ data export =====
|
|
1558
|
+
/**
|
|
1559
|
+
* Export all embeddings from the bridge's better-sqlite3 connection.
|
|
1560
|
+
* Used by RaBitQ to build its index from the same data that memory_store writes.
|
|
1561
|
+
* Returns null if bridge is unavailable (caller falls back to sql.js).
|
|
1562
|
+
*/
|
|
1563
|
+
export async function bridgeGetAllEmbeddings(options) {
|
|
1564
|
+
const registry = await getRegistry(options?.dbPath);
|
|
1565
|
+
if (!registry)
|
|
1566
|
+
return null;
|
|
1567
|
+
const ctx = getDb(registry);
|
|
1568
|
+
if (!ctx)
|
|
1569
|
+
return null;
|
|
1570
|
+
try {
|
|
1571
|
+
const dims = options?.dimensions ?? 384;
|
|
1572
|
+
const maxRows = options?.limit ?? 50000;
|
|
1573
|
+
const rows = ctx.db.prepare(`
|
|
1574
|
+
SELECT id, key, namespace, embedding
|
|
1575
|
+
FROM memory_entries
|
|
1576
|
+
WHERE status = 'active' AND embedding IS NOT NULL
|
|
1577
|
+
LIMIT ?
|
|
1578
|
+
`).all(maxRows);
|
|
1579
|
+
const results = [];
|
|
1580
|
+
for (const row of rows) {
|
|
1581
|
+
if (!row.embedding)
|
|
1582
|
+
continue;
|
|
1583
|
+
try {
|
|
1584
|
+
const emb = JSON.parse(row.embedding);
|
|
1585
|
+
if (emb.length !== dims)
|
|
1586
|
+
continue;
|
|
1587
|
+
results.push({
|
|
1588
|
+
id: String(row.id),
|
|
1589
|
+
key: row.key || String(row.id),
|
|
1590
|
+
namespace: row.namespace || 'default',
|
|
1591
|
+
embedding: emb,
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
catch { /* skip invalid */ }
|
|
1595
|
+
}
|
|
1596
|
+
return results;
|
|
1597
|
+
}
|
|
1598
|
+
catch {
|
|
1599
|
+
return null;
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1557
1602
|
// ===== Utility =====
|
|
1558
1603
|
function cosineSim(a, b) {
|
|
1559
1604
|
if (!a || !b || a.length === 0 || b.length === 0)
|
|
@@ -55,41 +55,57 @@ export async function buildRabitqIndex(options) {
|
|
|
55
55
|
const dimensions = options?.dimensions ?? 384;
|
|
56
56
|
const swarmDir = path.resolve(process.cwd(), '.swarm');
|
|
57
57
|
const dbPath = options?.dbPath ? path.resolve(options.dbPath) : path.join(swarmDir, 'memory.db');
|
|
58
|
-
if (!fs.existsSync(dbPath)) {
|
|
59
|
-
rabitqInitializing = false;
|
|
60
|
-
return { success: false, vectorCount: 0, dimensions, compressionRatio: 0, buildTimeMs: 0, error: 'Database not found' };
|
|
61
|
-
}
|
|
62
|
-
// Load embeddings from SQLite
|
|
63
|
-
const initSqlJs = (await import('sql.js')).default;
|
|
64
|
-
const SQL = await initSqlJs();
|
|
65
|
-
const fileBuffer = fs.readFileSync(dbPath);
|
|
66
|
-
const db = new SQL.Database(fileBuffer);
|
|
67
|
-
const result = db.exec(`
|
|
68
|
-
SELECT id, key, namespace, embedding
|
|
69
|
-
FROM memory_entries
|
|
70
|
-
WHERE status = 'active' AND embedding IS NOT NULL
|
|
71
|
-
LIMIT 50000
|
|
72
|
-
`);
|
|
73
58
|
const entries = [];
|
|
74
59
|
const vectors = [];
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
entries.push({ id: String(id), key: key || String(id), namespace: ns || 'default' });
|
|
85
|
-
vectors.push(...embedding);
|
|
60
|
+
// Try bridge first (reads via better-sqlite3, sees WAL data)
|
|
61
|
+
let usedBridge = false;
|
|
62
|
+
try {
|
|
63
|
+
const { bridgeGetAllEmbeddings } = await import('./memory-bridge.js');
|
|
64
|
+
const bridgeRows = await bridgeGetAllEmbeddings({ dimensions, dbPath: options?.dbPath });
|
|
65
|
+
if (bridgeRows && bridgeRows.length > 0) {
|
|
66
|
+
for (const row of bridgeRows) {
|
|
67
|
+
entries.push({ id: row.id, key: row.key, namespace: row.namespace });
|
|
68
|
+
vectors.push(...row.embedding);
|
|
86
69
|
}
|
|
87
|
-
|
|
88
|
-
|
|
70
|
+
usedBridge = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch { /* bridge unavailable, fall through */ }
|
|
74
|
+
// Fallback: read .swarm/memory.db via sql.js
|
|
75
|
+
if (!usedBridge) {
|
|
76
|
+
if (!fs.existsSync(dbPath)) {
|
|
77
|
+
rabitqInitializing = false;
|
|
78
|
+
return { success: false, vectorCount: 0, dimensions, compressionRatio: 0, buildTimeMs: 0, error: 'Database not found' };
|
|
79
|
+
}
|
|
80
|
+
const initSqlJs = (await import('sql.js')).default;
|
|
81
|
+
const SQL = await initSqlJs();
|
|
82
|
+
const fileBuffer = fs.readFileSync(dbPath);
|
|
83
|
+
const db = new SQL.Database(fileBuffer);
|
|
84
|
+
const result = db.exec(`
|
|
85
|
+
SELECT id, key, namespace, embedding
|
|
86
|
+
FROM memory_entries
|
|
87
|
+
WHERE status = 'active' AND embedding IS NOT NULL
|
|
88
|
+
LIMIT 50000
|
|
89
|
+
`);
|
|
90
|
+
if (result[0]?.values) {
|
|
91
|
+
for (const row of result[0].values) {
|
|
92
|
+
const [id, key, ns, embeddingJson] = row;
|
|
93
|
+
if (!embeddingJson)
|
|
94
|
+
continue;
|
|
95
|
+
try {
|
|
96
|
+
const embedding = JSON.parse(embeddingJson);
|
|
97
|
+
if (embedding.length !== dimensions)
|
|
98
|
+
continue;
|
|
99
|
+
entries.push({ id: String(id), key: key || String(id), namespace: ns || 'default' });
|
|
100
|
+
vectors.push(...embedding);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// skip invalid
|
|
104
|
+
}
|
|
89
105
|
}
|
|
90
106
|
}
|
|
107
|
+
db.close();
|
|
91
108
|
}
|
|
92
|
-
db.close();
|
|
93
109
|
if (entries.length < 2) {
|
|
94
110
|
rabitqInitializing = false;
|
|
95
111
|
return { success: false, vectorCount: entries.length, dimensions, compressionRatio: 0, buildTimeMs: Date.now() - startTime, error: 'Need at least 2 vectors to build RaBitQ index' };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.7",
|
|
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",
|
|
@@ -336,11 +336,32 @@ function isContentAwareExecutor(executor) {
|
|
|
336
336
|
return 'setContext' in executor && typeof executor.setContext === 'function';
|
|
337
337
|
}
|
|
338
338
|
class DefaultHeadlessExecutor {
|
|
339
|
+
contextContent = null;
|
|
340
|
+
setContext(claudeMdContent) {
|
|
341
|
+
this.contextContent = claudeMdContent;
|
|
342
|
+
}
|
|
339
343
|
async execute(prompt, workDir) {
|
|
340
344
|
const { execFile } = await import('node:child_process');
|
|
341
345
|
const { promisify } = await import('node:util');
|
|
346
|
+
const fs = await import('node:fs/promises');
|
|
347
|
+
const { join } = await import('node:path');
|
|
342
348
|
const execFileAsync = promisify(execFile);
|
|
343
|
-
|
|
349
|
+
const claudeMdPath = join(workDir, 'CLAUDE.md');
|
|
350
|
+
const backupPath = join(workDir, '.CLAUDE.md.ab-backup');
|
|
351
|
+
let swapped = false;
|
|
352
|
+
if (this.contextContent !== null) {
|
|
353
|
+
try {
|
|
354
|
+
await fs.copyFile(claudeMdPath, backupPath);
|
|
355
|
+
}
|
|
356
|
+
catch { /* no file to back up */ }
|
|
357
|
+
if (this.contextContent.length > 0) {
|
|
358
|
+
await fs.writeFile(claudeMdPath, this.contextContent, 'utf-8');
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
await fs.unlink(claudeMdPath).catch(() => { });
|
|
362
|
+
}
|
|
363
|
+
swapped = true;
|
|
364
|
+
}
|
|
344
365
|
try {
|
|
345
366
|
const { stdout, stderr } = await execFileAsync('claude', ['-p', prompt, '--output-format', 'json'], { timeout: 60000, maxBuffer: 10 * 1024 * 1024, encoding: 'utf-8', cwd: workDir });
|
|
346
367
|
return { stdout, stderr, exitCode: 0 };
|
|
@@ -348,6 +369,17 @@ class DefaultHeadlessExecutor {
|
|
|
348
369
|
catch (error) {
|
|
349
370
|
return { stdout: error.stdout ?? '', stderr: error.stderr ?? '', exitCode: error.code ?? 1 };
|
|
350
371
|
}
|
|
372
|
+
finally {
|
|
373
|
+
if (swapped) {
|
|
374
|
+
try {
|
|
375
|
+
await fs.copyFile(backupPath, claudeMdPath);
|
|
376
|
+
await fs.unlink(backupPath);
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
await fs.unlink(claudeMdPath).catch(() => { });
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
351
383
|
}
|
|
352
384
|
}
|
|
353
385
|
function getDefaultBenchmarkTasks() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/guidance",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.2",
|
|
4
4
|
"description": "Guidance Control Plane - Compiles, retrieves, enforces, and evolves guidance rules for Claude Code sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|