@claude-flow/cli 3.42.2 → 3.42.4
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
3.42.
|
|
1
|
+
3.42.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": {
|
|
3
|
-
"version": "3.42.
|
|
3
|
+
"version": "3.42.4",
|
|
4
4
|
"files": {
|
|
5
5
|
"auto-memory-hook.mjs": "85fe05c757421c52137c0bc8545a0896bab6b4714538c2a11d1d0835bfcc8c1c",
|
|
6
6
|
"hook-handler.cjs": "209d9fafe10e17d1be0866727f6f9cf9ac66f9a0793f1c793a4f58319e8e4583",
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
"statusline.cjs": "4a48353b4f1566fa4379b00fd0321b6676a22b6cc91fbbd8380ac5183d619468"
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
|
-
"signature": "
|
|
11
|
+
"signature": "zyopDoOW51Qkc0k2PpDbEv/puqT45lcx8EFnRQmwioIEDI/mv8KV140ZWcjEaa7lvIDW/epdB333K7bMW122Dw==",
|
|
12
12
|
"algorithm": "ed25519"
|
|
13
13
|
}
|
package/catalog-manifest.json
CHANGED
|
@@ -1413,34 +1413,192 @@ export function generateRufloHookCjs() {
|
|
|
1413
1413
|
*
|
|
1414
1414
|
* Always exits 0 — hook subcommands are best-effort telemetry and must
|
|
1415
1415
|
* never block a Claude Code turn.
|
|
1416
|
+
*
|
|
1417
|
+
* Windows argv integrity: hook-derived values (a Bash tool's \`command\`, a file path) must
|
|
1418
|
+
* reach the CLI as literal argv and never as shell syntax. Two layers, in
|
|
1419
|
+
* this order:
|
|
1420
|
+
*
|
|
1421
|
+
* 1. resolveInvocation() maps the command to a real executable — and on
|
|
1422
|
+
* Windows maps npm's .cmd shim to the package's own .js entrypoint —
|
|
1423
|
+
* so the spawn runs \`node <entry>\` with shell:false and NO cmd.exe in
|
|
1424
|
+
* the chain at all. Nothing to escape, nothing to re-tokenize, and no
|
|
1425
|
+
* %VAR% expansion. (The escaped fallback was measured on a real
|
|
1426
|
+
* windows-latest runner and does pass %VAR% through literally; layer 1
|
|
1427
|
+
* is still preferred because it removes the parser rather than
|
|
1428
|
+
* out-guessing it.)
|
|
1429
|
+
* 2. escapeCmdArg() guards the residual Windows path where step 1 cannot
|
|
1430
|
+
* identify an entrypoint. Escaping is strictly the weaker layer: it is
|
|
1431
|
+
* only reachable when resolution fails, and it is the one part of this
|
|
1432
|
+
* file that a non-Windows CI run cannot prove.
|
|
1416
1433
|
*/
|
|
1417
1434
|
|
|
1418
1435
|
'use strict';
|
|
1419
1436
|
|
|
1420
|
-
const { spawnSync
|
|
1437
|
+
const { spawnSync } = require('child_process');
|
|
1421
1438
|
const fs = require('fs');
|
|
1439
|
+
const path = require('path');
|
|
1422
1440
|
|
|
1423
1441
|
function done() { process.exit(0); }
|
|
1424
1442
|
|
|
1425
|
-
|
|
1443
|
+
/** Case-insensitive env lookup — Windows env keys are not case-stable. */
|
|
1444
|
+
function envValue(env, name) {
|
|
1445
|
+
const key = Object.keys(env).find((c) => c.toLowerCase() === name.toLowerCase());
|
|
1446
|
+
return key ? env[key] : undefined;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* Locate a command on PATH using fs only.
|
|
1451
|
+
*
|
|
1452
|
+
* Deliberately NOT \`execSync('where ...')\` / \`command -v\`: that spawns a
|
|
1453
|
+
* shell on every hook invocation, which is both the thing this file is
|
|
1454
|
+
* trying to get away from and a per-turn cost. Taking \`env\` and \`platform\`
|
|
1455
|
+
* as arguments is what lets the Windows branch be exercised from a
|
|
1456
|
+
* Linux/macOS CI run — see the Windows argv tests.
|
|
1457
|
+
*/
|
|
1458
|
+
function resolveCommandPath(command, env = process.env, platform = process.platform) {
|
|
1459
|
+
const hasSeparator = command.includes('/') || command.includes('\\\\');
|
|
1460
|
+
const dirs = hasSeparator
|
|
1461
|
+
? ['']
|
|
1462
|
+
: (envValue(env, 'PATH') || '').split(platform === 'win32' ? ';' : path.delimiter);
|
|
1463
|
+
const hasExtension = path.extname(command) !== '';
|
|
1464
|
+
const extensions = platform === 'win32' && !(hasSeparator && hasExtension)
|
|
1465
|
+
? (envValue(env, 'PATHEXT') || '.COM;.EXE;.BAT;.CMD').split(';')
|
|
1466
|
+
: [''];
|
|
1467
|
+
for (const dir of dirs) {
|
|
1468
|
+
for (const ext of extensions) {
|
|
1469
|
+
const base = path.resolve(dir || '.', command);
|
|
1470
|
+
const candidates = ext
|
|
1471
|
+
? [base + ext.toLowerCase(), base + ext.toUpperCase()]
|
|
1472
|
+
: [base];
|
|
1473
|
+
for (const file of candidates) {
|
|
1474
|
+
try {
|
|
1475
|
+
fs.accessSync(file, platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK);
|
|
1476
|
+
if (fs.statSync(file).isFile()) return file;
|
|
1477
|
+
} catch { /* keep searching */ }
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
return null;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
/**
|
|
1485
|
+
* Map an npm-generated Windows shim (ruflo.cmd / npx.cmd / …) to the .js
|
|
1486
|
+
* entrypoint it would have run, so it can be executed as \`node <entry>\`
|
|
1487
|
+
* with no shell.
|
|
1488
|
+
*
|
|
1489
|
+
* Handles both npm layouts: a global prefix (\`<prefix>/ruflo.cmd\` beside
|
|
1490
|
+
* \`<prefix>/node_modules/ruflo\`) and a local one (\`node_modules/.bin/ruflo.cmd\`
|
|
1491
|
+
* beside \`node_modules/ruflo\`). \`npx\` lives in the \`npm\` package, hence the
|
|
1492
|
+
* command→package mapping rather than assuming they match.
|
|
1493
|
+
*
|
|
1494
|
+
* The entrypoint comes from the package's own \`bin\` field, never a guessed
|
|
1495
|
+
* filename, and is required to resolve inside the package directory — a
|
|
1496
|
+
* manifest pointing outside it is refused rather than followed.
|
|
1497
|
+
*/
|
|
1498
|
+
function resolveNpmShim(shimPath) {
|
|
1499
|
+
const command = path.basename(shimPath, path.extname(shimPath)).toLowerCase();
|
|
1500
|
+
const packageName = command === 'npx' ? 'npm' : command;
|
|
1501
|
+
if (!['ruflo', 'claude-flow', 'npm'].includes(packageName)) return null;
|
|
1426
1502
|
try {
|
|
1427
|
-
const
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1503
|
+
const shimDir = path.dirname(shimPath);
|
|
1504
|
+
const packageDir = path.basename(shimDir).toLowerCase() === '.bin'
|
|
1505
|
+
? path.resolve(shimDir, '..', packageName)
|
|
1506
|
+
: path.resolve(shimDir, 'node_modules', packageName);
|
|
1507
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(packageDir, 'package.json'), 'utf8'));
|
|
1508
|
+
const declared = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin?.[command];
|
|
1509
|
+
if (typeof declared !== 'string') return null;
|
|
1510
|
+
const canonicalPackageDir = fs.realpathSync(packageDir);
|
|
1511
|
+
const canonicalEntry = fs.realpathSync(path.resolve(packageDir, declared));
|
|
1512
|
+
const relativeEntry = path.relative(canonicalPackageDir, canonicalEntry);
|
|
1513
|
+
if (relativeEntry.startsWith('..' + path.sep) || path.isAbsolute(relativeEntry)) return null;
|
|
1514
|
+
if (!fs.statSync(canonicalEntry).isFile()) return null;
|
|
1515
|
+
return { command: process.execPath, args: [canonicalEntry] };
|
|
1516
|
+
} catch { return null; }
|
|
1433
1517
|
}
|
|
1434
1518
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1519
|
+
/**
|
|
1520
|
+
* Decide how to run \`bin\` without a shell. Returns {command, args}, or null
|
|
1521
|
+
* when no shell-free invocation could be identified (Windows shim that is
|
|
1522
|
+
* not an npm package entry) — the caller then falls back to the escaped
|
|
1523
|
+
* cmd.exe path rather than dropping the hook.
|
|
1524
|
+
*/
|
|
1525
|
+
function resolveInvocation(bin, binArgs, options = {}) {
|
|
1526
|
+
const env = options.env || process.env;
|
|
1527
|
+
const platform = options.platform || process.platform;
|
|
1528
|
+
const commandPath = resolveCommandPath(bin, env, platform);
|
|
1529
|
+
if (!commandPath) return null;
|
|
1530
|
+
if (platform === 'win32' && /\\.(?:cmd|bat|ps1)$/i.test(commandPath)) {
|
|
1531
|
+
const npmBin = resolveNpmShim(commandPath);
|
|
1532
|
+
return npmBin ? { command: npmBin.command, args: [...npmBin.args, ...binArgs] } : null;
|
|
1533
|
+
}
|
|
1534
|
+
return { command: commandPath, args: binArgs };
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
/**
|
|
1538
|
+
* Escape one argv element so it survives BOTH parsers a Windows shell:true
|
|
1539
|
+
* spawn puts it through before the target CLI ever sees it:
|
|
1540
|
+
* 1. cmd.exe's own line tokenizer, which still scans for & | < > ^ % ! " ( )
|
|
1541
|
+
* even inside a per-argument quoted segment — quoting alone does not
|
|
1542
|
+
* shield cmd.exe metacharacters, and this runs a SECOND time when the
|
|
1543
|
+
* resolved binary is itself a .cmd shim (npm's \`ruflo\`/\`claude-flow\`/
|
|
1544
|
+
* \`npx\` global installs on Windows), because launching a .cmd file is
|
|
1545
|
+
* cmd.exe re-invoking itself on the command line.
|
|
1546
|
+
* 2. The eventual CommandLineToArgvW argv parse in the target process,
|
|
1547
|
+
* which needs backslash-before-quote sequences doubled and the value
|
|
1548
|
+
* quoted so it lands as ONE argument.
|
|
1549
|
+
* Without this, a hook-derived value (e.g. a Bash tool's \`command\`, or a
|
|
1550
|
+
* file path) containing a shell metacharacter can be reinterpreted as a
|
|
1551
|
+
* separate command / redirection instead of reaching the CLI as literal
|
|
1552
|
+
* data — this is the class of bug in CVE-2024-27980 (Node's own .bat/.cmd
|
|
1553
|
+
* argument-injection advisory). Algorithm: https://qntm.org/cmd, the same
|
|
1554
|
+
* reference the \`cross-spawn\` package's Windows escaping is built from.
|
|
1555
|
+
*
|
|
1556
|
+
* Byte-identical to plugins/ruflo-core/scripts/ruflo-hook.cjs so the four
|
|
1557
|
+
* copies can be diffed against each other. This is the fallback, not the
|
|
1558
|
+
* primary defence: resolveInvocation() above is preferred because it removes
|
|
1559
|
+
* cmd.exe from the chain entirely rather than out-guessing its tokenizer.
|
|
1560
|
+
*/
|
|
1561
|
+
function escapeCmdArg(arg) {
|
|
1562
|
+
let s = String(arg);
|
|
1563
|
+
s = s.replace(/(\\\\*)"/g, '$1$1\\\\"').replace(/(\\\\*)$/, '$1$1');
|
|
1564
|
+
s = \`"\${s}"\`;
|
|
1565
|
+
return s.replace(/[()%!^"<>&|;,]/g, '^$&');
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
function invokeHook(bin, binArgs, hookArgs, stdinData, options = {}) {
|
|
1569
|
+
const env = options.env || process.env;
|
|
1570
|
+
const platform = options.platform || process.platform;
|
|
1571
|
+
const spawnOpts = {
|
|
1439
1572
|
input: stdinData || '',
|
|
1440
1573
|
encoding: 'utf8',
|
|
1441
1574
|
stdio: ['pipe', 'ignore', 'ignore'],
|
|
1442
1575
|
timeout: 30_000,
|
|
1443
|
-
|
|
1576
|
+
env,
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
// Layer 1: no shell. CreateProcess/execve receives the argv array
|
|
1580
|
+
// verbatim, so nothing in it can be reinterpreted as syntax.
|
|
1581
|
+
const invocation = resolveInvocation(bin, binArgs, { env, platform });
|
|
1582
|
+
if (invocation) {
|
|
1583
|
+
const result = spawnSync(invocation.command, [...invocation.args, ...hookArgs], {
|
|
1584
|
+
...spawnOpts,
|
|
1585
|
+
shell: false,
|
|
1586
|
+
});
|
|
1587
|
+
return result.status === 0;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
// Layer 2: Windows shim we could not map to an entrypoint. cmd.exe is
|
|
1591
|
+
// unavoidable here (CreateProcess cannot launch a .cmd, and Node has
|
|
1592
|
+
// refused to since CVE-2024-27980), so every element is escaped. Losing
|
|
1593
|
+
// the hook entirely would be the wrong trade — telemetry is best-effort,
|
|
1594
|
+
// but silently doing nothing hides breakage.
|
|
1595
|
+
const useShell = platform === 'win32';
|
|
1596
|
+
const args = [...binArgs, ...hookArgs];
|
|
1597
|
+
const result = spawnSync(
|
|
1598
|
+
useShell ? escapeCmdArg(bin) : bin,
|
|
1599
|
+
useShell ? args.map(escapeCmdArg) : args,
|
|
1600
|
+
{ ...spawnOpts, shell: useShell },
|
|
1601
|
+
);
|
|
1444
1602
|
return result.status === 0;
|
|
1445
1603
|
}
|
|
1446
1604
|
|
|
@@ -1455,13 +1613,21 @@ function main() {
|
|
|
1455
1613
|
|
|
1456
1614
|
const hookArgs = ['hooks', subcommand, ...rest];
|
|
1457
1615
|
|
|
1458
|
-
|
|
1459
|
-
|
|
1616
|
+
// Presence is checked separately from invocation strategy: a command that
|
|
1617
|
+
// exists but cannot be resolved to an entrypoint still runs, via layer 2.
|
|
1618
|
+
if (resolveCommandPath('ruflo')) { invokeHook('ruflo', [], hookArgs, stdinData); done(); }
|
|
1619
|
+
if (resolveCommandPath('claude-flow')) { invokeHook('claude-flow', [], hookArgs, stdinData); done(); }
|
|
1460
1620
|
invokeHook('npx', ['--prefer-offline', '--yes', 'ruflo@latest'], hookArgs, stdinData);
|
|
1461
1621
|
done();
|
|
1462
1622
|
}
|
|
1463
1623
|
|
|
1464
|
-
|
|
1624
|
+
// Test seam: the Windows argv suite require()s this file to drive resolveInvocation()
|
|
1625
|
+
// and invokeHook() with a simulated { platform: 'win32', env } — which is how
|
|
1626
|
+
// the Windows branch is proved from a Linux/macOS CI run. hooks.json always
|
|
1627
|
+
// invokes this file directly, so main() runs unconditionally otherwise.
|
|
1628
|
+
if (!globalThis.__RUFLO_HOOK_IMPORT_ONLY__) main();
|
|
1629
|
+
|
|
1630
|
+
module.exports = { invokeHook, resolveCommandPath, resolveInvocation, resolveNpmShim, escapeCmdArg };
|
|
1465
1631
|
`;
|
|
1466
1632
|
}
|
|
1467
1633
|
//# sourceMappingURL=helpers-generator.js.map
|
|
@@ -481,7 +481,7 @@ export const memoryTools = [
|
|
|
481
481
|
},
|
|
482
482
|
{
|
|
483
483
|
name: 'memory_search',
|
|
484
|
-
description: 'Find stored memories by meaning (vector similarity), not by literal text — finds "JWT auth pattern" when you query "token-based login flow". Use when native Grep is wrong because Grep matches characters and you need to find conceptually-related entries across past sessions.
|
|
484
|
+
description: 'Find stored memories by meaning (vector similarity), not by literal text — finds "JWT auth pattern" when you query "token-based login flow". Use when native Grep is wrong because Grep matches characters and you need to find conceptually-related entries across past sessions. Returns top-k with similarity: raw retrieval relevance, which may include lexical scoring and is not guaranteed to be cosine similarity. With smart=true, similarity is the highest raw score across query variants; rankingScore is the composite relevance score used by the ranking pipeline, not cosine similarity, probability, or confidence. Diversity can change result order.',
|
|
485
485
|
category: 'memory',
|
|
486
486
|
inputSchema: {
|
|
487
487
|
type: 'object',
|
|
@@ -489,8 +489,8 @@ export const memoryTools = [
|
|
|
489
489
|
query: { type: 'string', description: 'Search query (semantic similarity)' },
|
|
490
490
|
namespace: { type: 'string', description: 'Namespace to search (default: all namespaces — omit to search across every namespace)' },
|
|
491
491
|
limit: { type: 'number', description: 'Maximum results (default: 10)' },
|
|
492
|
-
threshold: { type: 'number', description: 'Minimum
|
|
493
|
-
smart: { type: 'boolean', description: 'Enable SmartRetrieval
|
|
492
|
+
threshold: { type: 'number', description: 'Minimum raw retrieval relevance 0-1 for candidate admission, applied per query before SmartRetrieval ranking; not a floor on rankingScore (default: 0.3)' },
|
|
493
|
+
smart: { type: 'boolean', description: 'Enable SmartRetrieval — query expansion, RRF fusion, recency boost, MMR diversity; preserves raw similarity and adds rankingScore (default: false)' },
|
|
494
494
|
provenance_filter: {
|
|
495
495
|
type: 'array',
|
|
496
496
|
items: { type: 'string', enum: ['user_claim', 'agent_output', 'system_observation', 'tool_result', 'unknown'] },
|
|
@@ -553,6 +553,7 @@ export const memoryTools = [
|
|
|
553
553
|
key: e.key,
|
|
554
554
|
content: e.content,
|
|
555
555
|
score: e.score,
|
|
556
|
+
rawScore: e.score,
|
|
556
557
|
namespace: e.namespace,
|
|
557
558
|
provenanceType: e.provenanceType,
|
|
558
559
|
// Dream Cycle 2026-09-03: thread the already-computed
|
|
@@ -579,7 +580,8 @@ export const memoryTools = [
|
|
|
579
580
|
key: r.key,
|
|
580
581
|
namespace: r.namespace,
|
|
581
582
|
value,
|
|
582
|
-
similarity: r.
|
|
583
|
+
similarity: r.rawScore,
|
|
584
|
+
rankingScore: r.score,
|
|
583
585
|
provenanceType: r.provenanceType,
|
|
584
586
|
};
|
|
585
587
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.42.
|
|
3
|
+
"version": "3.42.4",
|
|
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",
|
|
@@ -125,11 +125,11 @@
|
|
|
125
125
|
"ws": "^8.21.0",
|
|
126
126
|
"yaml": "^2.8.0",
|
|
127
127
|
"zod": "^3.22.0",
|
|
128
|
-
"@claude-flow/memory": "^3.0.0-alpha.
|
|
128
|
+
"@claude-flow/memory": "^3.0.0-alpha.23"
|
|
129
129
|
},
|
|
130
130
|
"optionalDependencies": {
|
|
131
131
|
"@agntcy/slim-bindings": "2.0.0-alpha.5",
|
|
132
|
-
"@claude-flow/memory": "^3.0.0-alpha.
|
|
132
|
+
"@claude-flow/memory": "^3.0.0-alpha.23",
|
|
133
133
|
"@metaharness/darwin": "~0.10.2",
|
|
134
134
|
"@metaharness/flywheel": "~0.1.10",
|
|
135
135
|
"@metaharness/radio": "~0.1.0",
|