claude-flow 3.59.13 → 3.59.15

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": 1792634570394,
2
+ "adoptedAt": 1792652697736,
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.13",
3
+ "version": "3.59.15",
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-22T02:03:09.504Z",
5
- "gitSha": "056a11ec",
4
+ "generatedAt": "2026-10-22T07:59:21.864Z",
5
+ "gitSha": "b2c74c22",
6
6
  "catalog": {
7
7
  "agents": 176,
8
8
  "tools": 432,
@@ -27,6 +27,28 @@
27
27
  * pre-release channel, pin deliberately rather than floating) until the fix
28
28
  * is promoted to `latest`, tracked by the same issue.
29
29
  *
30
+ * UPDATE (2026-10-22, #4371): `2.0.0-alpha.5`'s own `optionalDependencies`
31
+ * claimed `@agntcy/slim-bindings-linux-arm64-musl@2.0.0-alpha.5`, but that
32
+ * platform package was never published upstream (its own first version is
33
+ * `2.1.1-rc.2` — confirmed via `npm view @agntcy/slim-bindings-linux-arm64-musl
34
+ * versions`, which is also true of every other `2.0.0-alpha.*`/`2.0.0`/`2.1.0`
35
+ * release). npm tolerates an unresolvable optional dependency and silently
36
+ * skips it, so this never surfaced in this repo's own npm-based CI, but
37
+ * strict resolvers (`mise`'s `aube` backend, pnpm in some modes) fail the
38
+ * whole install. `package.json` now pins `2.1.1` — the earliest release where
39
+ * every platform's optional package actually exists at that exact version
40
+ * (verified against the live registry for all 8 platforms). Re-verified live
41
+ * under plain Node against the real installed `2.1.1` package: the dynamic
42
+ * `import()` resolves with zero errors (same module shape — a `Session`/
43
+ * `Channel`/`App`-class-based SDK, not the `joinGroup`/`createSlimTransport`/
44
+ * `publishAgentRecord` flat functions `transport.ts`/`swarm-join.ts`/
45
+ * `publish.ts` call. Confirmed this mismatch predates this pin change — it
46
+ * was equally absent from `2.0.0-alpha.5` — so it's a pre-existing gap this
47
+ * version bump does not introduce or worsen; tracked separately in #4376),
48
+ * and the full
49
+ * `__tests__/agntcy/agntcy-commands.test.ts` suite (19 tests, including the
50
+ * real-resolution "configured: true" case) passes against this version.
51
+ *
30
52
  * This module's existing graceful-degradation design already handled this
31
53
  * correctly without any change to its logic: `detectAgntcyRuntime()`'s
32
54
  * catch-all branch (anything other than MODULE_NOT_FOUND) reports the real
@@ -27,6 +27,28 @@
27
27
  * pre-release channel, pin deliberately rather than floating) until the fix
28
28
  * is promoted to `latest`, tracked by the same issue.
29
29
  *
30
+ * UPDATE (2026-10-22, #4371): `2.0.0-alpha.5`'s own `optionalDependencies`
31
+ * claimed `@agntcy/slim-bindings-linux-arm64-musl@2.0.0-alpha.5`, but that
32
+ * platform package was never published upstream (its own first version is
33
+ * `2.1.1-rc.2` — confirmed via `npm view @agntcy/slim-bindings-linux-arm64-musl
34
+ * versions`, which is also true of every other `2.0.0-alpha.*`/`2.0.0`/`2.1.0`
35
+ * release). npm tolerates an unresolvable optional dependency and silently
36
+ * skips it, so this never surfaced in this repo's own npm-based CI, but
37
+ * strict resolvers (`mise`'s `aube` backend, pnpm in some modes) fail the
38
+ * whole install. `package.json` now pins `2.1.1` — the earliest release where
39
+ * every platform's optional package actually exists at that exact version
40
+ * (verified against the live registry for all 8 platforms). Re-verified live
41
+ * under plain Node against the real installed `2.1.1` package: the dynamic
42
+ * `import()` resolves with zero errors (same module shape — a `Session`/
43
+ * `Channel`/`App`-class-based SDK, not the `joinGroup`/`createSlimTransport`/
44
+ * `publishAgentRecord` flat functions `transport.ts`/`swarm-join.ts`/
45
+ * `publish.ts` call. Confirmed this mismatch predates this pin change — it
46
+ * was equally absent from `2.0.0-alpha.5` — so it's a pre-existing gap this
47
+ * version bump does not introduce or worsen; tracked separately in #4376),
48
+ * and the full
49
+ * `__tests__/agntcy/agntcy-commands.test.ts` suite (19 tests, including the
50
+ * real-resolution "configured: true" case) passes against this version.
51
+ *
30
52
  * This module's existing graceful-degradation design already handled this
31
53
  * correctly without any change to its logic: `detectAgntcyRuntime()`'s
32
54
  * catch-all branch (anything other than MODULE_NOT_FOUND) reports the real
@@ -41,6 +41,15 @@ export declare function isEncryptionEnabled(): boolean;
41
41
  * encryption is enabled but no key resolves, this throws with a clear
42
42
  * message rather than silently falling back to plaintext (fail-closed).
43
43
  *
44
+ * The optional `context` selects which missing-key message to throw:
45
+ * - `'encrypt'` (default): the caller is about to encrypt because
46
+ * `CLAUDE_FLOW_ENCRYPT_AT_REST` is set, so the original message is
47
+ * accurate.
48
+ * - `'decrypt'`: the caller hit an RFE1-encrypted blob on read (e.g. a
49
+ * store restored from another machine) while the enable flag may be
50
+ * unset (issue #3212). The message echoes the flag's actual value and
51
+ * the on-disk state instead of asserting the flag is set.
52
+ *
44
53
  * Accepted encodings (auto-detected by length):
45
54
  * - 64-char hex (32 bytes)
46
55
  * - 44-char base64 (32 bytes + padding)
@@ -49,7 +58,7 @@ export declare function isEncryptionEnabled(): boolean;
49
58
  * Anything else is rejected — we'd rather fail loudly than encrypt with a
50
59
  * truncated key.
51
60
  */
52
- export declare function getKey(): Buffer;
61
+ export declare function getKey(context?: 'encrypt' | 'decrypt'): Buffer;
53
62
  /**
54
63
  * Decode a key string. Exposed for testing and for the future passphrase
55
64
  * resolver, which will scrypt-derive a Buffer and hand it back through here
@@ -58,6 +58,15 @@ export function isEncryptionEnabled() {
58
58
  * encryption is enabled but no key resolves, this throws with a clear
59
59
  * message rather than silently falling back to plaintext (fail-closed).
60
60
  *
61
+ * The optional `context` selects which missing-key message to throw:
62
+ * - `'encrypt'` (default): the caller is about to encrypt because
63
+ * `CLAUDE_FLOW_ENCRYPT_AT_REST` is set, so the original message is
64
+ * accurate.
65
+ * - `'decrypt'`: the caller hit an RFE1-encrypted blob on read (e.g. a
66
+ * store restored from another machine) while the enable flag may be
67
+ * unset (issue #3212). The message echoes the flag's actual value and
68
+ * the on-disk state instead of asserting the flag is set.
69
+ *
61
70
  * Accepted encodings (auto-detected by length):
62
71
  * - 64-char hex (32 bytes)
63
72
  * - 44-char base64 (32 bytes + padding)
@@ -66,9 +75,16 @@ export function isEncryptionEnabled() {
66
75
  * Anything else is rejected — we'd rather fail loudly than encrypt with a
67
76
  * truncated key.
68
77
  */
69
- export function getKey() {
78
+ export function getKey(context = 'encrypt') {
70
79
  const raw = process.env[ENV_KEY_VAR];
71
80
  if (!raw) {
81
+ if (context === 'decrypt') {
82
+ const flag = process.env[ENV_ENABLE_FLAG] ?? 'unset';
83
+ throw new Error(`${ENV_KEY_VAR} is required but not set ` +
84
+ `(${ENV_ENABLE_FLAG}=${flag}; the store on disk is RFE1-encrypted). ` +
85
+ `Supply the key this store was encrypted with — a newly generated key will not decrypt it. ` +
86
+ `Provide a 32-byte key as 64-char hex or 44-char base64.`);
87
+ }
72
88
  throw new Error(`${ENV_ENABLE_FLAG} is set but ${ENV_KEY_VAR} is not. ` +
73
89
  `Provide a 32-byte key as 64-char hex or 44-char base64. ` +
74
90
  `See ADR-096 for keychain/passphrase support (coming in a follow-up).`);
@@ -172,7 +172,9 @@ export function readFileMaybeEncrypted(path, encoding = 'utf-8') {
172
172
  const raw = readFileSync(path);
173
173
  let plain;
174
174
  if (isEncryptedBlob(raw)) {
175
- plain = decryptBuffer(raw, getKey());
175
+ // 'decrypt': the blob on disk is RFE1-encrypted but the enable flag may
176
+ // be unset (e.g. store restored from another machine) — see #3212.
177
+ plain = decryptBuffer(raw, getKey('decrypt'));
176
178
  }
177
179
  else {
178
180
  plain = raw;
@@ -21,6 +21,17 @@ import { DEFAULT_SEARCH_THRESHOLD, nearMisses } from '../memory/search-defaults.
21
21
  const MEMORY_DIR = '.swarm';
22
22
  const LEGACY_MEMORY_FILE = 'store.json';
23
23
  const LEGACY_MEMORY_DIR = '.claude-flow/memory';
24
+ /**
25
+ * #3196: allow an MCP caller to select the same explicit store the CLI accepts
26
+ * via `--path`. No path means the existing MCP default is unchanged; this is
27
+ * deliberately not an implicit `CLAUDE_FLOW_DB_PATH` override because the
28
+ * native/encrypted CLI store and the AgentDB sibling are separate backends.
29
+ */
30
+ function resolveDbPathOption(inputDbPath) {
31
+ return typeof inputDbPath === 'string' && inputDbPath.trim().length > 0
32
+ ? resolve(inputDbPath)
33
+ : undefined;
34
+ }
24
35
  const MIGRATION_MARKER = '.migrated-to-sqlite';
25
36
  function getMemoryDir() {
26
37
  return resolve(MEMORY_DIR);
@@ -439,6 +450,7 @@ export const memoryTools = [
439
450
  enum: ['user_claim', 'agent_output', 'system_observation', 'tool_result', 'unknown'],
440
451
  description: 'ADR-323: who/what produced this value, so shared-namespace retrieval can filter by trust level instead of conflating a user\'s stated claim with an agent\'s own output. Default: "unknown".',
441
452
  },
453
+ dbPath: { type: 'string', description: 'Explicit SQLite store to read/write; omit to use the MCP default (the native/AgentDB sibling).' },
442
454
  },
443
455
  required: ['key', 'value'],
444
456
  },
@@ -447,7 +459,9 @@ export const memoryTools = [
447
459
  if (missingKey) {
448
460
  return { success: false, key: input.key, stored: false, hasEmbedding: false, ...missingKey };
449
461
  }
450
- await ensureInitialized();
462
+ const dbPath = resolveDbPathOption(input.dbPath);
463
+ if (!dbPath)
464
+ await ensureInitialized();
451
465
  const { storeEntry } = await getMemoryFunctions();
452
466
  const key = input.key;
453
467
  const namespace = input.namespace || 'default';
@@ -486,6 +500,7 @@ export const memoryTools = [
486
500
  ttl,
487
501
  upsert,
488
502
  provenanceType,
503
+ dbPath,
489
504
  });
490
505
  const duration = performance.now() - startTime;
491
506
  return {
@@ -522,6 +537,7 @@ export const memoryTools = [
522
537
  properties: {
523
538
  key: { type: 'string', description: 'Memory key' },
524
539
  namespace: { type: 'string', description: 'Namespace (default: "default")' },
540
+ dbPath: { type: 'string', description: 'Explicit SQLite store to read/write; omit to use the MCP default (the native/AgentDB sibling).' },
525
541
  },
526
542
  required: ['key'],
527
543
  },
@@ -530,13 +546,15 @@ export const memoryTools = [
530
546
  if (missingKey) {
531
547
  return { key: input.key, namespace: input.namespace, value: null, found: false, ...missingKey };
532
548
  }
533
- await ensureInitialized();
549
+ const dbPath = resolveDbPathOption(input.dbPath);
550
+ if (!dbPath)
551
+ await ensureInitialized();
534
552
  const { getEntry } = await getMemoryFunctions();
535
553
  const key = input.key;
536
554
  const namespace = input.namespace || 'default';
537
555
  validateMemoryInput(key, undefined, undefined, namespace);
538
556
  try {
539
- const result = await getEntry({ key, namespace });
557
+ const result = await getEntry({ key, namespace, dbPath });
540
558
  if (result.found && result.entry) {
541
559
  // Try to parse JSON value
542
560
  let value = result.entry.content;
@@ -594,6 +612,7 @@ export const memoryTools = [
594
612
  items: { type: 'string', enum: ['user_claim', 'agent_output', 'system_observation', 'tool_result', 'unknown'] },
595
613
  description: 'ADR-323: restrict results to these provenance types (e.g. exclude user_claim when fact-checking). Omit for no filtering. Enforced for standard and SmartRetrieval searches.',
596
614
  },
615
+ dbPath: { type: 'string', description: 'Explicit SQLite store to read/write; omit to use the MCP default (the native/AgentDB sibling).' },
597
616
  },
598
617
  required: ['query'],
599
618
  },
@@ -602,7 +621,9 @@ export const memoryTools = [
602
621
  if (missingQuery) {
603
622
  return { query: input.query, results: [], total: 0, ...missingQuery };
604
623
  }
605
- await ensureInitialized();
624
+ const dbPath = resolveDbPathOption(input.dbPath);
625
+ if (!dbPath)
626
+ await ensureInitialized();
606
627
  const { searchEntries } = await getMemoryFunctions();
607
628
  const query = input.query;
608
629
  const provenanceFilter = input.provenance_filter;
@@ -649,6 +670,7 @@ export const memoryTools = [
649
670
  limit: req.limit || limit * 3,
650
671
  threshold: req.threshold ?? threshold,
651
672
  provenanceFilter,
673
+ dbPath,
652
674
  });
653
675
  return {
654
676
  results: r.results.map(e => ({
@@ -693,7 +715,7 @@ export const memoryTools = [
693
715
  };
694
716
  });
695
717
  const smartNearMisses = results.length === 0 && thresholdWasDefault
696
- ? await nearMisses(searchEntries, { query, namespace, provenanceFilter })
718
+ ? await nearMisses(searchEntries, { query, namespace, provenanceFilter, dbPath })
697
719
  : undefined;
698
720
  return {
699
721
  query,
@@ -721,6 +743,7 @@ export const memoryTools = [
721
743
  limit,
722
744
  threshold,
723
745
  provenanceFilter,
746
+ dbPath,
724
747
  });
725
748
  if (!result.success) {
726
749
  return { query, results: [], total: 0, error: result.error };
@@ -744,7 +767,7 @@ export const memoryTools = [
744
767
  };
745
768
  });
746
769
  const nearMissInfo = results.length === 0 && thresholdWasDefault
747
- ? await nearMisses(searchEntries, { query, namespace, provenanceFilter })
770
+ ? await nearMisses(searchEntries, { query, namespace, provenanceFilter, dbPath })
748
771
  : undefined;
749
772
  return {
750
773
  query,
@@ -775,6 +798,7 @@ export const memoryTools = [
775
798
  properties: {
776
799
  key: { type: 'string', description: 'Memory key' },
777
800
  namespace: { type: 'string', description: 'Namespace (default: "default")' },
801
+ dbPath: { type: 'string', description: 'Explicit SQLite store to read/write; omit to use the MCP default (the native/AgentDB sibling).' },
778
802
  },
779
803
  required: ['key'],
780
804
  },
@@ -783,13 +807,15 @@ export const memoryTools = [
783
807
  if (missingKey) {
784
808
  return { success: false, key: input.key, namespace: input.namespace, deleted: false, ...missingKey };
785
809
  }
786
- await ensureInitialized();
810
+ const dbPath = resolveDbPathOption(input.dbPath);
811
+ if (!dbPath)
812
+ await ensureInitialized();
787
813
  const { deleteEntry } = await getMemoryFunctions();
788
814
  const key = input.key;
789
815
  const namespace = input.namespace || 'default';
790
816
  validateMemoryInput(key, undefined, undefined, namespace);
791
817
  try {
792
- const result = await deleteEntry({ key, namespace });
818
+ const result = await deleteEntry({ key, namespace, dbPath });
793
819
  return {
794
820
  success: result.deleted,
795
821
  key,
@@ -825,10 +851,13 @@ export const memoryTools = [
825
851
  },
826
852
  limit: { type: 'number', description: 'Maximum results (default: 50)' },
827
853
  offset: { type: 'number', description: 'Offset for pagination (default: 0)' },
854
+ dbPath: { type: 'string', description: 'Explicit SQLite store to read/write; omit to use the MCP default (the native/AgentDB sibling).' },
828
855
  },
829
856
  },
830
857
  handler: async (input) => {
831
- await ensureInitialized();
858
+ const dbPath = resolveDbPathOption(input.dbPath);
859
+ if (!dbPath)
860
+ await ensureInitialized();
832
861
  const { listEntries } = await getMemoryFunctions();
833
862
  const namespace = input.namespace;
834
863
  const tags = Array.isArray(input.tags)
@@ -847,6 +876,7 @@ export const memoryTools = [
847
876
  tags,
848
877
  limit,
849
878
  offset,
879
+ dbPath,
850
880
  });
851
881
  const entries = result.entries.map(e => ({
852
882
  key: e.key,
@@ -884,14 +914,14 @@ export const memoryTools = [
884
914
  inputSchema: {
885
915
  type: 'object',
886
916
  properties: {
887
- dbPath: { type: 'string', description: 'Database file to inspect; omitted uses the MCP store default' },
917
+ dbPath: { type: 'string', description: 'Explicit SQLite store to read/write; omit to use the MCP default (the native/AgentDB sibling).' },
888
918
  },
889
919
  },
890
920
  handler: async (input) => {
891
921
  if (input.dbPath !== undefined && (typeof input.dbPath !== 'string' || !input.dbPath.trim())) {
892
922
  return memoryStatsUnavailable('dbPath must be a non-empty string');
893
923
  }
894
- const dbPath = typeof input.dbPath === 'string' ? resolve(input.dbPath) : undefined;
924
+ const dbPath = resolveDbPathOption(input.dbPath);
895
925
  // An explicit read must not initialize or migrate the unrelated default store.
896
926
  if (!dbPath)
897
927
  await ensureInitialized();
@@ -304,10 +304,10 @@ export const terminalTools = [
304
304
  // Return combined history from all sessions
305
305
  const allHistory = Object.values(store.sessions)
306
306
  .flatMap(s => s.history.map(h => ({ ...h, sessionId: s.id })))
307
- .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
308
- .slice(offset, offset + limit);
307
+ .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
309
308
  return {
310
- history: allHistory,
309
+ history: allHistory.slice(offset, offset + limit),
310
+ // Every stored entry, like the single-session branch, not just this page.
311
311
  total: allHistory.length,
312
312
  };
313
313
  },
@@ -583,7 +583,8 @@ export const workflowTools = [
583
583
  }
584
584
  // Sort by creation date (newest first)
585
585
  workflows.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
586
- // Apply limit
586
+ // Count the matches before the limit cuts the page down
587
+ const total = workflows.length;
587
588
  const limit = input.limit || 20;
588
589
  workflows = workflows.slice(0, limit);
589
590
  return {
@@ -595,7 +596,7 @@ export const workflowTools = [
595
596
  createdAt: w.createdAt,
596
597
  completedAt: w.completedAt,
597
598
  })),
598
- total: workflows.length,
599
+ total,
599
600
  filters: { status: input.status },
600
601
  };
601
602
  },
@@ -404,14 +404,22 @@ export class WorkerDaemon extends EventEmitter {
404
404
  return {};
405
405
  }
406
406
  try {
407
- // The CLI writes nested objects; legacy files use dotted keys. Scoped
407
+ // The CLI writes nested objects; legacy files use dotted keys. Each
408
+ // key resolves independently through scopes.project -> values -> root
409
+ // — `values` is the envelope config_set writes for its default scope
410
+ // (#3192 — without this, config_set daemon.idleSecs 0 has no effect
411
+ // on the running daemon even though it succeeds and updates
412
+ // config.json) — rather than picking one whole object as "cfg", since
413
+ // a config.json can legitimately have some keys written under
414
+ // scopes.project (project-scoped config_set calls) and others under
415
+ // values (default-scope config_set calls) at the same time. Scoped
408
416
  // values retain precedence, including explicit false and zero.
409
417
  const read = (obj, key) => {
410
418
  if (!obj)
411
419
  return undefined;
412
420
  return obj[key] ?? key.split('.').reduce((value, part) => value && typeof value === 'object' && Object.hasOwn(value, part) ? value[part] : undefined, obj);
413
421
  };
414
- const get = (key) => read(raw?.scopes?.project, key) ?? read(raw, key);
422
+ const get = (key) => read(raw?.scopes?.project, key) ?? read(raw?.values, key) ?? read(raw, key);
415
423
  const rawAutoStart = get('daemon.autoStart');
416
424
  const rawCpuLoad = get('daemon.resourceThresholds.maxCpuLoad');
417
425
  const rawMinMem = get('daemon.resourceThresholds.minFreeMemoryPercent');
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.59.13",
3
+ "version": "3.59.15",
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",
@@ -129,7 +129,7 @@
129
129
  "@claude-flow/memory": "3.0.8"
130
130
  },
131
131
  "optionalDependencies": {
132
- "@agntcy/slim-bindings": "2.0.0-alpha.5",
132
+ "@agntcy/slim-bindings": "2.1.1",
133
133
  "@claude-flow/memory": "3.0.8",
134
134
  "@metaharness/darwin": "~0.12.0",
135
135
  "@metaharness/flywheel": "~0.1.10",