claude-flow 3.45.0 → 3.46.1
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/README.md +2 -0
- package/README.zh-CN.md +424 -0
- package/node_modules/@claude-flow/codex/dist/cli.js +0 -0
- package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js +2 -6
- package/node_modules/@claude-flow/codex/dist/worktrees/coordinator.js.map +1 -1
- package/node_modules/@claude-flow/mcp/dist/transport/http.d.ts.map +1 -1
- package/node_modules/@claude-flow/mcp/dist/transport/http.js +14 -1
- package/node_modules/@claude-flow/mcp/dist/transport/http.js.map +1 -1
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.d.ts +40 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.d.ts.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.js +100 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/a2a/planner-descriptor.js.map +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/bin.js +0 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.d.ts.map +1 -1
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js +1 -0
- package/node_modules/@claude-flow/plugin-agent-federation/dist/index.js.map +1 -1
- package/node_modules/@claude-flow/plugin-agent-federation/package.json +1 -0
- package/node_modules/@claude-flow/security/dist/input-validator.d.ts +6 -6
- package/node_modules/@claude-flow/security/dist/safe-git.d.ts +22 -0
- package/node_modules/@claude-flow/security/dist/safe-git.d.ts.map +1 -0
- package/node_modules/@claude-flow/security/dist/safe-git.js +63 -0
- package/node_modules/@claude-flow/security/dist/safe-git.js.map +1 -0
- package/package.json +3 -3
- package/v3/@claude-flow/cli/README.md +2 -0
- package/v3/@claude-flow/cli/bin/cli.js +13 -0
- package/v3/@claude-flow/cli/bin/mcp-server.js +16 -0
- package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
- package/v3/@claude-flow/cli/dist/src/commands/doctor.d.ts +3 -0
- package/v3/@claude-flow/cli/dist/src/commands/doctor.js +131 -2
- package/v3/@claude-flow/cli/dist/src/commands/embeddings.js +50 -7
- package/v3/@claude-flow/cli/dist/src/commands/init.js +5 -2
- package/v3/@claude-flow/cli/dist/src/commands/mcp.js +27 -4
- package/v3/@claude-flow/cli/dist/src/mcp-server.d.ts +50 -6
- package/v3/@claude-flow/cli/dist/src/mcp-server.js +267 -33
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-execute-core.js +7 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js +20 -8
- package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js +59 -48
- package/v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js +9 -4
- package/v3/@claude-flow/cli/dist/src/mcp-tools/metaharness-tools.js +1 -1
- package/v3/@claude-flow/cli/dist/src/mcp-tools/policy-enforcer.d.ts +4 -4
- package/v3/@claude-flow/cli/dist/src/mcp-tools/policy-enforcer.js +4 -4
- package/v3/@claude-flow/cli/dist/src/mcp-tools/terminal-tools.js +11 -1
- package/v3/@claude-flow/cli/dist/src/mcp-tools/workflow-tools.js +1 -1
- package/v3/@claude-flow/cli/dist/src/memory/ewc-consolidation.d.ts +16 -1
- package/v3/@claude-flow/cli/dist/src/memory/ewc-consolidation.js +63 -13
- package/v3/@claude-flow/cli/dist/src/memory/intelligence.d.ts +6 -2
- package/v3/@claude-flow/cli/dist/src/memory/intelligence.js +18 -11
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +84 -0
- package/v3/@claude-flow/cli/dist/src/runtime/browser-command.d.ts +29 -0
- package/v3/@claude-flow/cli/dist/src/runtime/browser-command.js +101 -0
- package/v3/@claude-flow/cli/dist/src/ruvector/model-router.js +19 -1
- package/v3/@claude-flow/cli/dist/src/services/distill-oracle.js +2 -1
- package/v3/@claude-flow/cli/dist/src/services/git-workspace-identity.js +5 -8
- package/v3/@claude-flow/cli/dist/src/services/policy-runtime.js +114 -4
- package/v3/@claude-flow/cli/dist/src/services/worker-daemon.js +8 -3
- package/v3/@claude-flow/cli/package.json +5 -5
- package/.claude/.proven-config-version +0 -1
- package/.claude/proven-config.json +0 -42
|
@@ -1,14 +1,39 @@
|
|
|
1
1
|
import { AgenticPolicyEngine, createLegacyCompatibleState, isMcpCallerAuthEnabled, decodeTokenEnvelope, publicKeyFromHex, verifyInvocationToken, } from '@claude-flow/security';
|
|
2
2
|
import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
|
-
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
4
|
+
import { closeSync, constants as fsConstants, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readlinkSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
5
5
|
import { dirname, join, resolve } from 'node:path';
|
|
6
|
-
import { userInfo } from 'node:os';
|
|
6
|
+
import { hostname, userInfo } from 'node:os';
|
|
7
7
|
const POLICY_DIR = join('.claude-flow', 'policy');
|
|
8
8
|
const POLICY_FILE = 'state.json';
|
|
9
9
|
const LOCK_FILE = 'state.lock';
|
|
10
10
|
const LOCK_STALE_MS = 30_000;
|
|
11
11
|
const LOCK_WAIT_MS = 5_000;
|
|
12
|
+
// A lock is ~170 bytes plus the hostname (at most 255 bytes).
|
|
13
|
+
const LOCK_MAX_BYTES = 1_024;
|
|
14
|
+
// Linux PID namespace of this process, e.g. `pid:[4026531836]`; undefined on
|
|
15
|
+
// other platforms or without /proc. Recorded in the lock because a pid only
|
|
16
|
+
// identifies a process inside the namespace that wrote it.
|
|
17
|
+
const PID_NAMESPACE = (() => {
|
|
18
|
+
try {
|
|
19
|
+
return readlinkSync('/proc/self/ns/pid');
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
})();
|
|
25
|
+
// Linux boot id: one uuid per kernel boot, shared by every process on that
|
|
26
|
+
// kernel and readable inside containers. Recorded because `host` is only a
|
|
27
|
+
// name: two machines that share a project directory can report the same
|
|
28
|
+
// hostname, and the init PID namespace has the same inode on every Linux host.
|
|
29
|
+
const BOOT_ID = (() => {
|
|
30
|
+
try {
|
|
31
|
+
return readFileSync('/proc/sys/kernel/random/boot_id', 'utf8').trim();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
})();
|
|
12
37
|
function paths(projectRoot) {
|
|
13
38
|
const root = resolve(projectRoot);
|
|
14
39
|
const dir = join(root, POLICY_DIR);
|
|
@@ -17,12 +42,96 @@ function paths(projectRoot) {
|
|
|
17
42
|
function sleep(ms) {
|
|
18
43
|
return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
|
|
19
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Signal-0 existence probe, as in #1799 (`isPidAlive` in swarm-tools.ts), but
|
|
47
|
+
* only ESRCH counts as dead (as `processIsAlive` in helper-refresh.ts): here a
|
|
48
|
+
* false "dead" breaks mutual exclusion, so EPERM (another user's process) and
|
|
49
|
+
* any unexpected error mean alive.
|
|
50
|
+
*/
|
|
51
|
+
function isPidAlive(pid) {
|
|
52
|
+
try {
|
|
53
|
+
process.kill(pid, 0);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
return e.code !== 'ESRCH';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reads a lock only if it is a small regular file: never follows a symlink,
|
|
62
|
+
* never blocks on a FIFO or device, never reads more than LOCK_MAX_BYTES.
|
|
63
|
+
* Anything else returns undefined and the caller keeps the mtime rule.
|
|
64
|
+
*/
|
|
65
|
+
function readLockFile(lockPath) {
|
|
66
|
+
if (!lstatSync(lockPath).isFile())
|
|
67
|
+
return undefined;
|
|
68
|
+
const fd = openSync(lockPath, fsConstants.O_RDONLY | (fsConstants.O_NOFOLLOW ?? 0) | (fsConstants.O_NONBLOCK ?? 0));
|
|
69
|
+
try {
|
|
70
|
+
const stat = fstatSync(fd);
|
|
71
|
+
if (!stat.isFile() || stat.size > LOCK_MAX_BYTES)
|
|
72
|
+
return undefined;
|
|
73
|
+
const buffer = Buffer.alloc(LOCK_MAX_BYTES);
|
|
74
|
+
return buffer.toString('utf8', 0, readSync(fd, buffer, 0, LOCK_MAX_BYTES, 0));
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
closeSync(fd);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A process killed inside a transaction (SIGKILL, OOM, or a signal whose
|
|
82
|
+
* default action terminates it) never runs `finally { release() }`, so every
|
|
83
|
+
* caller, MCP reads included, waited LOCK_WAIT_MS and failed with
|
|
84
|
+
* policy-state-lock-timeout until the orphan's mtime crossed LOCK_STALE_MS.
|
|
85
|
+
* The pid is trusted only if the lock was written by this OS, on this kernel
|
|
86
|
+
* boot and in this PID namespace: anywhere else (a bwrap --unshare-pid
|
|
87
|
+
* sandbox, a container, another machine on a shared filesystem) a live owner
|
|
88
|
+
* also answers ESRCH. Locks without that identity (older ruflo, a crash
|
|
89
|
+
* between create and write, anything unparsable) return false and keep the
|
|
90
|
+
* mtime rule.
|
|
91
|
+
*/
|
|
92
|
+
function lockOwnerIsDead(lockPath) {
|
|
93
|
+
try {
|
|
94
|
+
const read = readLockFile(lockPath);
|
|
95
|
+
if (read === undefined)
|
|
96
|
+
return false;
|
|
97
|
+
const owner = JSON.parse(read);
|
|
98
|
+
if (!owner || owner.host !== hostname() || owner.platform !== process.platform
|
|
99
|
+
|| owner.pidns !== PID_NAMESPACE || owner.boot !== BOOT_ID)
|
|
100
|
+
return false;
|
|
101
|
+
// Without /proc, one Linux kernel boot or PID namespace cannot be told
|
|
102
|
+
// from another, and `host` is only a name.
|
|
103
|
+
if (process.platform === 'linux'
|
|
104
|
+
&& (PID_NAMESPACE === undefined || BOOT_ID === undefined))
|
|
105
|
+
return false;
|
|
106
|
+
const pid = owner.pid;
|
|
107
|
+
if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0 || pid > 0x7fffffff
|
|
108
|
+
|| isPidAlive(pid))
|
|
109
|
+
return false;
|
|
110
|
+
// The lock can change hands while it is read and probed (its owner
|
|
111
|
+
// releases and exits, another process acquires). Re-read it and answer
|
|
112
|
+
// only if it is byte for byte the lock that was read: the next owner's
|
|
113
|
+
// lock always differs in `pid` or `acquiredAt`. `dev`/`ino`/`ctime` cannot
|
|
114
|
+
// stand in for that — ext4 reuses a freed inode number at once, and before
|
|
115
|
+
// Linux 6.13 two files created in one clock tick share a ctime.
|
|
116
|
+
return readLockFile(lockPath) === read;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
20
122
|
async function acquireLock(lockPath) {
|
|
21
123
|
const started = Date.now();
|
|
22
124
|
while (Date.now() - started < LOCK_WAIT_MS) {
|
|
23
125
|
try {
|
|
24
126
|
const fd = openSync(lockPath, 'wx', 0o600);
|
|
25
|
-
writeFileSync(fd, JSON.stringify({
|
|
127
|
+
writeFileSync(fd, JSON.stringify({
|
|
128
|
+
pid: process.pid,
|
|
129
|
+
acquiredAt: Date.now(),
|
|
130
|
+
host: hostname(),
|
|
131
|
+
platform: process.platform,
|
|
132
|
+
pidns: PID_NAMESPACE,
|
|
133
|
+
boot: BOOT_ID,
|
|
134
|
+
}));
|
|
26
135
|
closeSync(fd);
|
|
27
136
|
return () => {
|
|
28
137
|
try {
|
|
@@ -33,7 +142,8 @@ async function acquireLock(lockPath) {
|
|
|
33
142
|
}
|
|
34
143
|
catch {
|
|
35
144
|
try {
|
|
36
|
-
if (
|
|
145
|
+
if (lockOwnerIsDead(lockPath)
|
|
146
|
+
|| Date.now() - statSync(lockPath).mtimeMs > LOCK_STALE_MS)
|
|
37
147
|
unlinkSync(lockPath);
|
|
38
148
|
}
|
|
39
149
|
catch { /* another process changed the lock */ }
|
|
@@ -14,6 +14,7 @@ import { EventEmitter } from 'events';
|
|
|
14
14
|
import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, unlinkSync } from 'fs';
|
|
15
15
|
import { cpus } from 'os';
|
|
16
16
|
import { join } from 'path';
|
|
17
|
+
import { createRequire } from 'node:module';
|
|
17
18
|
import { writeFileAtomic } from '../fs-secure.js';
|
|
18
19
|
import { HeadlessWorkerExecutor, isHeadlessWorker, } from './headless-worker-executor.js';
|
|
19
20
|
// ADR-174 M3: the consolidate worker below drives the real DISTILL/CONSOLIDATE
|
|
@@ -26,6 +27,9 @@ import { backupMemoryDb } from './memory-backup.js';
|
|
|
26
27
|
import { resolveGitWorkspaceIdentity } from './git-workspace-identity.js';
|
|
27
28
|
import { getWorkspaceLeaseRegistry } from './workspace-lease.js';
|
|
28
29
|
import { getRepoSupervisorRegistry } from './repo-supervisor.js';
|
|
30
|
+
// Daemon config is read synchronously from the constructor. In an ESM build,
|
|
31
|
+
// bare `require` is undefined, so use a module-relative require for YAML.
|
|
32
|
+
const requireYaml = createRequire(import.meta.url);
|
|
29
33
|
// Default worker configurations with improved intervals (P0 fix: map 5min -> 15min)
|
|
30
34
|
const DEFAULT_WORKERS = [
|
|
31
35
|
{ type: 'map', intervalMs: 15 * 60 * 1000, offsetMs: 0, priority: 'normal', description: 'Codebase mapping', enabled: true },
|
|
@@ -368,8 +372,7 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
368
372
|
try {
|
|
369
373
|
// Lazy-load yaml so the daemon doesn't hard-require it; if the
|
|
370
374
|
// dep isn't installed, fall back to the previous warn-only path.
|
|
371
|
-
|
|
372
|
-
const yamlMod = require('yaml');
|
|
375
|
+
const yamlMod = requireYaml('yaml');
|
|
373
376
|
const parsed = yamlMod.parse(readFileSync(yPath, 'utf-8'));
|
|
374
377
|
if (parsed && typeof parsed === 'object') {
|
|
375
378
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1013,7 +1016,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
1013
1016
|
return `max age ${Math.round(ttlMs / 1000)}s reached`;
|
|
1014
1017
|
}
|
|
1015
1018
|
if (idleMs > 0) {
|
|
1016
|
-
|
|
1019
|
+
// Worker timestamps survive restarts; they cannot make this process
|
|
1020
|
+
// idle before it has been alive for a full idle window (#3194).
|
|
1021
|
+
const lastActivity = Math.max(this.lastWorkerActivityMs() ?? startedMs, startedMs);
|
|
1017
1022
|
if (now - lastActivity >= idleMs) {
|
|
1018
1023
|
return `idle for ${Math.round(idleMs / 1000)}s (no worker activity)`;
|
|
1019
1024
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.46.1",
|
|
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",
|
|
@@ -98,10 +98,10 @@
|
|
|
98
98
|
"vitest": "^4.1.0"
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
-
"@claude-flow/cli-core": "3.7.0-alpha.
|
|
101
|
+
"@claude-flow/cli-core": "3.7.0-alpha.6",
|
|
102
102
|
"@claude-flow/codex": "3.0.3",
|
|
103
103
|
"@claude-flow/mcp": "3.0.0-alpha.10",
|
|
104
|
-
"@claude-flow/neural": "3.0.0-alpha.
|
|
104
|
+
"@claude-flow/neural": "3.0.0-alpha.10",
|
|
105
105
|
"@claude-flow/plugin-agent-federation": "1.0.0-alpha.18",
|
|
106
106
|
"@claude-flow/security": "3.0.0-alpha.14",
|
|
107
107
|
"@claude-flow/shared": "3.0.0-alpha.7",
|
|
@@ -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.26"
|
|
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.26",
|
|
133
133
|
"@metaharness/darwin": "~0.10.2",
|
|
134
134
|
"@metaharness/flywheel": "~0.1.10",
|
|
135
135
|
"@metaharness/radio": "~0.1.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"adoptedAt": 1790287605043,
|
|
3
|
-
"championId": "sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319",
|
|
4
|
-
"manifest": {
|
|
5
|
-
"schema": "ruflo.proven-config/v1",
|
|
6
|
-
"policy": {
|
|
7
|
-
"ref": "sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319",
|
|
8
|
-
"value": {
|
|
9
|
-
"alpha": 0.3,
|
|
10
|
-
"subjectWeight": 1,
|
|
11
|
-
"mmrLambda": 0.5,
|
|
12
|
-
"bodyWeight": 1.5,
|
|
13
|
-
"typePenaltyFactor": 0.5
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"layer": "framework/node-cli",
|
|
17
|
-
"compatibility": {
|
|
18
|
-
"ruflo": ">=3.24.0"
|
|
19
|
-
},
|
|
20
|
-
"benchmark": {
|
|
21
|
-
"corpus": "ADR-081-labelled-v1",
|
|
22
|
-
"corpusHash": "sha256:2f700b5c363e20a3bd88ce2bc9b87bbbbaa61732c6177894c6ec37890f888982"
|
|
23
|
-
},
|
|
24
|
-
"receipt": {
|
|
25
|
-
"heldOutDelta": 0.07381404928570845,
|
|
26
|
-
"redblue": "PASS",
|
|
27
|
-
"drift": 0,
|
|
28
|
-
"canary": {
|
|
29
|
-
"rollbackRate": 0,
|
|
30
|
-
"latencyP95": 244.612458000076,
|
|
31
|
-
"costPerTask": 0
|
|
32
|
-
},
|
|
33
|
-
"receiptCoverage": 1
|
|
34
|
-
},
|
|
35
|
-
"platform": [
|
|
36
|
-
"linux",
|
|
37
|
-
"macOS",
|
|
38
|
-
"windows"
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
"previous": ""
|
|
42
|
-
}
|