claude-flow 3.16.0 → 3.16.2

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.16.0",
3
+ "version": "3.16.2",
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",
@@ -81,14 +81,14 @@
81
81
  "overrides": {
82
82
  "ruvector": "^0.2.27",
83
83
  "better-sqlite3": ">=12.8.0",
84
- "hono": ">=4.11.4",
84
+ "hono": ">=4.12.25",
85
85
  "@ruvector/rvf-wasm": "0.1.5",
86
- "@hono/node-server": ">=1.19.10",
86
+ "@hono/node-server": ">=1.19.14",
87
87
  "flatted": ">=3.4.0",
88
88
  "tar": ">=7.5.11",
89
89
  "picomatch": ">=4.0.3",
90
90
  "path-to-regexp": ">=8.2.1",
91
- "undici": ">=7.18.0",
91
+ "undici": ">=8.5.0",
92
92
  "minimatch": ">=10.0.0",
93
93
  "@isaacs/brace-expansion": ">=5.0.1",
94
94
  "cacache": ">=20.0.0",
@@ -106,8 +106,11 @@
106
106
  "@opentelemetry/exporter-prometheus": ">=0.217.0",
107
107
  "axios": ">=1.13.2",
108
108
  "fast-uri": ">=3.1.0",
109
- "vite": ">=6.4.6",
110
- "ws": ">=8.21.0"
109
+ "vite": ">=8.0.16",
110
+ "ws": ">=8.21.0",
111
+ "@grpc/grpc-js": ">=1.14.4",
112
+ "form-data": ">=4.0.6",
113
+ "http-proxy-middleware": ">=3.0.7"
111
114
  },
112
115
  "devDependencies": {
113
116
  "@openai/codex": "^0.98.0",
@@ -116,7 +119,7 @@
116
119
  "eslint": "^8.0.0",
117
120
  "tsx": "^4.21.0",
118
121
  "typescript": "^5.0.0",
119
- "vitest": "^1.0.0"
122
+ "vitest": "^3.2.6"
120
123
  },
121
124
  "engines": {
122
125
  "node": ">=20.0.0"
@@ -98,14 +98,26 @@ const startCommand = {
98
98
  // dedup is process-atomic. Lock holder gets to spawn; competing callers
99
99
  // see EEXIST, wait briefly, then re-read the PID file (which the holder
100
100
  // has now written), and return "already running" cleanly.
101
+ // #2484 — previously the lockfile was released BEFORE startBackgroundDaemon
102
+ // ran, opening a race window where a concurrent caller could see no lock
103
+ // AND no PID file (PID hadn't been written yet) and proceed to fork ITS
104
+ // OWN background daemon. EDortta reported 4 identical daemons per Claude
105
+ // Code session on v3.10.37 under exactly this pattern (MCP startup
106
+ // racing with a sibling invocation).
107
+ //
108
+ // Fix: hold the lock across the entire spawn lifecycle (dedup check →
109
+ // killStaleDaemons → fork → PID file write), so the lock-loser ALWAYS
110
+ // sees either a live lock or a populated PID file, never the empty
111
+ // window in between.
112
+ let lockFd = null;
113
+ let lockFile = '';
101
114
  if (!isDaemonProcess) {
102
115
  const stateDir = join(resolve(projectRoot), '.claude-flow');
103
- const lockFile = join(stateDir, 'daemon.lock');
116
+ lockFile = join(stateDir, 'daemon.lock');
104
117
  try {
105
118
  fs.mkdirSync(stateDir, { recursive: true });
106
119
  }
107
120
  catch { /* exists */ }
108
- let lockFd = null;
109
121
  try {
110
122
  lockFd = fs.openSync(lockFile, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY);
111
123
  fs.writeSync(lockFd, String(process.pid));
@@ -139,22 +151,33 @@ const startCommand = {
139
151
  throw e;
140
152
  }
141
153
  }
154
+ // Dedup check while holding the lock.
142
155
  try {
143
156
  const bgPid = getBackgroundDaemonPid(projectRoot);
144
157
  if (bgPid && isProcessRunning(bgPid)) {
145
158
  if (!quiet) {
146
159
  output.printWarning(`Daemon already running in background (PID: ${bgPid}). Stop it first with: daemon stop`);
147
160
  }
161
+ // Release the lock on the early-return path.
162
+ if (lockFd !== null) {
163
+ try {
164
+ fs.closeSync(lockFd);
165
+ }
166
+ catch { /* ignore */ }
167
+ try {
168
+ fs.unlinkSync(lockFile);
169
+ }
170
+ catch { /* ignore */ }
171
+ }
148
172
  return { success: true };
149
173
  }
150
174
  // #1551: Kill any stale daemon processes that weren't tracked by PID file
151
175
  await killStaleDaemons(projectRoot, quiet);
152
176
  }
153
- finally {
154
- // Release the lock so the lock-loser can re-check (or the next
155
- // legitimate invocation can spawn). startBackgroundDaemon below
156
- // writes the PID file synchronously before returning so the
157
- // post-release re-check finds it.
177
+ catch (e) {
178
+ // Anything that throws here MUST still release the lock before
179
+ // rethrowing so we don't leave the lockfile behind for future
180
+ // invocations to wait on for 5s before recovering.
158
181
  if (lockFd !== null) {
159
182
  try {
160
183
  fs.closeSync(lockFd);
@@ -164,23 +187,58 @@ const startCommand = {
164
187
  fs.unlinkSync(lockFile);
165
188
  }
166
189
  catch { /* ignore */ }
190
+ lockFd = null;
167
191
  }
192
+ throw e;
168
193
  }
169
194
  }
170
- // Background mode (default): fork a detached process.
195
+ // Background mode (default): fork a detached process. The lock (if held)
196
+ // is released AFTER startBackgroundDaemon's PID file write completes —
197
+ // see the cleanup inside startBackgroundDaemon's caller path below.
171
198
  // #1968: previously only forwarded resource thresholds — `--workers`,
172
199
  // `--headless`, and `--sandbox` were dropped on the floor when the
173
200
  // launcher forked the foreground child, so `daemon start --workers map`
174
201
  // got the full default worker set instead.
175
202
  if (!foreground) {
176
- return startBackgroundDaemon(projectRoot, quiet, {
177
- maxCpuLoad: rawMaxCpu,
178
- minFreeMemory: rawMinMem,
179
- workers: ctx.flags.workers,
180
- headless: ctx.flags.headless,
181
- sandbox: ctx.flags.sandbox,
182
- ttl: rawTtl,
183
- });
203
+ try {
204
+ return await startBackgroundDaemon(projectRoot, quiet, {
205
+ maxCpuLoad: rawMaxCpu,
206
+ minFreeMemory: rawMinMem,
207
+ workers: ctx.flags.workers,
208
+ headless: ctx.flags.headless,
209
+ sandbox: ctx.flags.sandbox,
210
+ ttl: rawTtl,
211
+ });
212
+ }
213
+ finally {
214
+ // Release the lock NOW — startBackgroundDaemon has either written
215
+ // the PID file (success path) or thrown (in which case the next
216
+ // caller's killStaleDaemons sweep handles the orphan).
217
+ if (lockFd !== null) {
218
+ try {
219
+ fs.closeSync(lockFd);
220
+ }
221
+ catch { /* ignore */ }
222
+ try {
223
+ fs.unlinkSync(lockFile);
224
+ }
225
+ catch { /* ignore */ }
226
+ }
227
+ }
228
+ }
229
+ // Foreground path: release the lock before we start the (potentially
230
+ // long-running) foreground daemon so other callers can dedup against
231
+ // our PID file (foreground writes its own PID).
232
+ if (lockFd !== null) {
233
+ try {
234
+ fs.closeSync(lockFd);
235
+ }
236
+ catch { /* ignore */ }
237
+ try {
238
+ fs.unlinkSync(lockFile);
239
+ }
240
+ catch { /* ignore */ }
241
+ lockFd = null;
184
242
  }
185
243
  // Foreground mode: run in current process (blocks terminal)
186
244
  try {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.16.0",
3
+ "version": "3.16.2",
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",
@@ -93,7 +93,7 @@
93
93
  },
94
94
  "devDependencies": {
95
95
  "typescript": "^5.3.0",
96
- "vitest": "^4.0.16"
96
+ "vitest": "^4.1.0"
97
97
  },
98
98
  "dependencies": {
99
99
  "@claude-flow/cli-core": "3.7.0-alpha.5",
@@ -147,7 +147,7 @@
147
147
  "devDependencies": {
148
148
  "@types/node": "^20.10.0",
149
149
  "typescript": "^5.3.0",
150
- "vitest": "^4.0.16"
150
+ "vitest": "^4.1.0"
151
151
  },
152
152
  "engines": {
153
153
  "node": ">=20.0.0"
@@ -32,7 +32,7 @@
32
32
  "cors": "^2.8.5",
33
33
  "express": "^4.21.0",
34
34
  "helmet": "^7.1.0",
35
- "vitest": "^4.0.16",
35
+ "vitest": "^4.1.0",
36
36
  "ws": "^8.16.0",
37
37
  "zod": "^3.22.4"
38
38
  },