claude-flow 3.59.5 → 3.59.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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "adoptedAt": 1792556117950,
2
+ "adoptedAt": 1792565467884,
3
3
  "championId": "sha256:6141a8ea990c5063b77e090ae8f37f9c539d8aa8f58dcceb30f3a82f97e57319",
4
4
  "manifest": {
5
5
  "schema": "ruflo.proven-config/v1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.59.5",
3
+ "version": "3.59.7",
4
4
  "workspaces": [
5
5
  "v3/@claude-flow/codex",
6
6
  "v3/@claude-flow/mcp",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generation": 7,
4
- "generatedAt": "2026-10-21T04:15:49.428Z",
5
- "gitSha": "5f5f5941",
4
+ "generatedAt": "2026-10-21T06:52:34.888Z",
5
+ "gitSha": "51d42418",
6
6
  "catalog": {
7
7
  "agents": 176,
8
8
  "tools": 432,
@@ -1627,10 +1627,12 @@ const exportCommand = {
1627
1627
  description: 'Include vector embeddings',
1628
1628
  type: 'boolean',
1629
1629
  default: true
1630
- }
1630
+ },
1631
+ DB_PATH_OPTION
1631
1632
  ],
1632
1633
  examples: [
1633
1634
  { command: 'claude-flow memory export -o ./backup.json', description: 'Export all to JSON' },
1635
+ { command: 'claude-flow memory export -o ./agentdb.json --path .swarm/agentdb-memory.db', description: 'Export one specific store' },
1634
1636
  { command: 'claude-flow memory export -o ./data.csv -f csv', description: 'Export to CSV' }
1635
1637
  ],
1636
1638
  action: async (ctx) => {
@@ -1647,6 +1649,7 @@ const exportCommand = {
1647
1649
  format,
1648
1650
  namespace: ctx.flags.namespace,
1649
1651
  includeVectors: ctx.flags.includeVectors ?? true,
1652
+ dbPath: resolveDbPath(ctx.flags.path),
1650
1653
  });
1651
1654
  // memory_export reports failure as { error } rather than throwing; without
1652
1655
  // this check the command printed "Exported to undefined" and then crashed
@@ -1587,13 +1587,20 @@ export const memoryTools = [
1587
1587
  properties: {
1588
1588
  outputPath: { type: 'string', description: 'File path to write the JSON export to' },
1589
1589
  format: { type: 'string', enum: ['json', 'csv'], description: 'Export format (csv falls back to json today)' },
1590
+ dbPath: { type: 'string', description: 'Explicit memory DB to export (default: the AgentDB store plus the CLI sibling)' },
1590
1591
  namespace: { type: 'string', description: 'Limit export to one namespace' },
1591
1592
  includeVectors: { type: 'boolean', description: 'Include embedding vectors (advisory — not exported yet)' },
1592
1593
  },
1593
1594
  required: ['outputPath'],
1594
1595
  },
1595
1596
  handler: async (input) => {
1596
- await ensureInitialized();
1597
+ const requestedDbPath = typeof input.dbPath === 'string' && input.dbPath.trim()
1598
+ ? resolve(input.dbPath)
1599
+ : undefined;
1600
+ // An explicit file selection is a single-store read. Do not initialize or
1601
+ // migrate the unrelated default store just to export a snapshot.
1602
+ if (!requestedDbPath)
1603
+ await ensureInitialized();
1597
1604
  const { listEntries } = await getMemoryFunctions();
1598
1605
  const outputPath = String(input.outputPath ?? '');
1599
1606
  if (!outputPath)
@@ -1619,7 +1626,7 @@ export const memoryTools = [
1619
1626
  } while (out.length < total);
1620
1627
  return { entries: out };
1621
1628
  };
1622
- const primary = await readStore();
1629
+ const primary = await readStore(requestedDbPath);
1623
1630
  if ('error' in primary)
1624
1631
  return { error: primary.error };
1625
1632
  // #4148: the default reader is the AgentDB bridge, but the CLI's own store
@@ -1627,7 +1634,9 @@ export const memoryTools = [
1627
1634
  // sees, so an export silently covered one store and reported success. Read
1628
1635
  // the CLI store too and merge, newest copy of a (namespace, key) winning.
1629
1636
  const warnings = [];
1630
- const stores = [{ store: 'default', entries: primary.entries.length }];
1637
+ const stores = [
1638
+ { store: requestedDbPath ?? 'default', entries: primary.entries.length },
1639
+ ];
1631
1640
  const merged = new Map();
1632
1641
  const keep = (e) => {
1633
1642
  const id = `${e.namespace}\u0000${e.key}`;
@@ -1636,15 +1645,19 @@ export const memoryTools = [
1636
1645
  merged.set(id, e);
1637
1646
  };
1638
1647
  primary.entries.forEach(keep);
1639
- const cliStore = await resolveCliStorePath();
1640
- if (cliStore && existsSync(cliStore)) {
1641
- const secondary = await readStore(cliStore);
1642
- if ('error' in secondary) {
1643
- warnings.push(`Could not read the CLI store ${cliStore} (${secondary.error}); the export covers the AgentDB store only.`);
1644
- }
1645
- else {
1646
- stores.push({ store: cliStore, entries: secondary.entries.length });
1647
- secondary.entries.forEach(keep);
1648
+ // The implicit default export still merges the sibling CLI store; an
1649
+ // explicit dbPath must cover exactly that file.
1650
+ if (!requestedDbPath) {
1651
+ const cliStore = await resolveCliStorePath();
1652
+ if (cliStore && existsSync(cliStore)) {
1653
+ const secondary = await readStore(cliStore);
1654
+ if ('error' in secondary) {
1655
+ warnings.push(`Could not read the CLI store ${cliStore} (${secondary.error}); the export covers the AgentDB store only.`);
1656
+ }
1657
+ else {
1658
+ stores.push({ store: cliStore, entries: secondary.entries.length });
1659
+ secondary.entries.forEach(keep);
1660
+ }
1648
1661
  }
1649
1662
  }
1650
1663
  const all = { entries: [...merged.values()] };
@@ -502,6 +502,8 @@ export const sessionTools = [
502
502
  else if (sortBy === 'size') {
503
503
  sessions.sort((a, b) => (b.stats?.totalSize ?? 0) - (a.stats?.totalSize ?? 0));
504
504
  }
505
+ // Count every session before applying the limit so callers can tell when the list was truncated
506
+ const total = sessions.length;
505
507
  // Apply limit
506
508
  const limit = input.limit || 10;
507
509
  sessions = sessions.slice(0, limit);
@@ -522,7 +524,7 @@ export const sessionTools = [
522
524
  projection.metrics = s.metrics;
523
525
  return projection;
524
526
  }),
525
- total: sessions.length,
527
+ total,
526
528
  limit,
527
529
  };
528
530
  },
@@ -178,9 +178,13 @@ function reclaimDeadLock(lockPath) {
178
178
  */
179
179
  export async function acquireLock(lockPath) {
180
180
  const started = Date.now();
181
+ // O_NOFOLLOW closes the create-through-a-symlink path on platforms that
182
+ // support it; lstat below still rejects non-regular existing paths.
183
+ const createFlags = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL
184
+ | (process.platform === 'win32' ? 0 : (fsConstants.O_NOFOLLOW ?? 0));
181
185
  while (Date.now() - started < LOCK_WAIT_MS) {
182
186
  try {
183
- const fd = openSync(lockPath, 'wx', 0o600);
187
+ const fd = openSync(lockPath, createFlags, 0o600);
184
188
  const ownership = JSON.stringify({
185
189
  pid: process.pid,
186
190
  acquiredAt: Date.now(),
@@ -204,7 +208,30 @@ export async function acquireLock(lockPath) {
204
208
  catch { /* already released */ }
205
209
  };
206
210
  }
207
- catch {
211
+ catch (error) {
212
+ const code = error?.code;
213
+ // Only EEXIST is normal lock contention. Permission/path/IO failures
214
+ // must not masquerade as a five-second timeout on every MCP call.
215
+ // ELOOP is O_NOFOLLOW rejecting a symlink at the lock path.
216
+ if (code === 'ELOOP') {
217
+ throw new Error('policy-state-lock-error: lock path is not a regular file');
218
+ }
219
+ if (code !== 'EEXIST') {
220
+ throw new Error(`policy-state-lock-error: ${code ?? (error instanceof Error ? error.message : String(error))}`);
221
+ }
222
+ // EEXIST can also mean a directory/FIFO/symlink was planted at the lock
223
+ // path. Those are never a live lock: fail immediately instead of
224
+ // waiting, and never follow/remove the non-regular target.
225
+ try {
226
+ if (!lstatSync(lockPath).isFile()) {
227
+ throw new Error('policy-state-lock-error: lock path is not a regular file');
228
+ }
229
+ }
230
+ catch (statError) {
231
+ if (statError instanceof Error && statError.message.startsWith('policy-state-lock-error:'))
232
+ throw statError;
233
+ // The lock vanished between open() and lstat(); retry immediately.
234
+ }
208
235
  reclaimDeadLock(lockPath);
209
236
  await sleep(10);
210
237
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.59.5",
3
+ "version": "3.59.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",