claude-flow 3.7.0-alpha.46 → 3.7.0-alpha.48

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.7.0-alpha.46",
3
+ "version": "3.7.0-alpha.48",
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",
@@ -940,5 +940,185 @@ export const embeddingsTools = [
940
940
  };
941
941
  },
942
942
  },
943
+ // ============================================================
944
+ // ADR-121 Phase 5b — DiskannSnapshot MCP tools (alpha.47 CLI)
945
+ // ============================================================
946
+ //
947
+ // Process-level registry of named DiskannSnapshot handles. Build
948
+ // an index once, search it many times. Persistence to disk via
949
+ // the snapshot's storagePath; the handle is keyed by `name`.
950
+ // For in-memory snapshots, set persist: false and the index is
951
+ // re-built only while this process lives.
952
+ {
953
+ name: 'embeddings_diskann_build',
954
+ description: 'Build a DiskANN/Vamana ANN index from a batch of (id, vector) pairs. Use when you have a fixed corpus (≥10k vectors typical) that needs sub-millisecond ANN search and you want persistence across process restarts — for streaming inserts at smaller scale use SearchableEmbeddingCache instead, for batch in-memory 32×-compressed use RabitqSnapshot. Pair with embeddings_diskann_search to query, embeddings_diskann_status to inspect. Requires @ruvector/diskann (optional peer dep — throws a clear named error if missing).',
955
+ category: 'embeddings',
956
+ inputSchema: {
957
+ type: 'object',
958
+ properties: {
959
+ name: { type: 'string', description: 'Snapshot handle name (used by search + status). Must be unique per process.' },
960
+ dimension: { type: 'number', description: 'Embedding dimension.' },
961
+ entries: {
962
+ type: 'array',
963
+ description: 'Vectors to index. Each entry: { id: string, vector: number[] }.',
964
+ items: {
965
+ type: 'object',
966
+ properties: {
967
+ id: { type: 'string' },
968
+ vector: { type: 'array', items: { type: 'number' } },
969
+ },
970
+ required: ['id', 'vector'],
971
+ },
972
+ },
973
+ storagePath: { type: 'string', description: 'Optional directory for on-disk persistence (snapshot survives restarts via embeddings_diskann_load).' },
974
+ },
975
+ required: ['name', 'dimension', 'entries'],
976
+ },
977
+ handler: async (input) => {
978
+ const { getDiskannRegistry } = await import('../memory/diskann-registry.js');
979
+ const registry = getDiskannRegistry();
980
+ const name = input.name;
981
+ const dimension = input.dimension;
982
+ const entries = input.entries;
983
+ const storagePath = input.storagePath;
984
+ try {
985
+ const stats = await registry.build({ name, dimension, entries, storagePath });
986
+ return { success: true, name, ...stats };
987
+ }
988
+ catch (err) {
989
+ return { success: false, name, error: err instanceof Error ? err.message : String(err) };
990
+ }
991
+ },
992
+ },
993
+ {
994
+ name: 'embeddings_diskann_search',
995
+ description: 'Search a previously-built DiskANN index for the k nearest neighbors of a query vector. Use when you built an index via embeddings_diskann_build and now need ANN retrieval — returns ids + L2² distances sorted ascending. For text→vector→search in one call, pair with embeddings_generate first. For exact-match key lookup over a streaming cache, use SearchableEmbeddingCache.get instead.',
996
+ category: 'embeddings',
997
+ inputSchema: {
998
+ type: 'object',
999
+ properties: {
1000
+ name: { type: 'string', description: 'Snapshot handle name (set by embeddings_diskann_build).' },
1001
+ vector: { type: 'array', items: { type: 'number' }, description: 'Query vector. Must match the index dimension.' },
1002
+ k: { type: 'number', description: 'Number of nearest neighbors to return.' },
1003
+ },
1004
+ required: ['name', 'vector', 'k'],
1005
+ },
1006
+ handler: async (input) => {
1007
+ const { getDiskannRegistry } = await import('../memory/diskann-registry.js');
1008
+ const registry = getDiskannRegistry();
1009
+ const name = input.name;
1010
+ const vector = new Float32Array(input.vector);
1011
+ const k = input.k;
1012
+ try {
1013
+ const hits = await registry.search(name, vector, k);
1014
+ return { success: true, name, k, hits };
1015
+ }
1016
+ catch (err) {
1017
+ return { success: false, name, error: err instanceof Error ? err.message : String(err) };
1018
+ }
1019
+ },
1020
+ },
1021
+ {
1022
+ name: 'embeddings_diskann_status',
1023
+ description: 'List all DiskANN snapshots currently held by this MCP server, with their dimension, vector count, and storage path. Use when you want to inventory in-process indexes before opening a new one, or when debugging "which snapshot did I build?". For checking whether the @ruvector/diskann peer dep itself is installed, use embeddings_check_ruvector_sidecar (the family probe) instead.',
1024
+ category: 'embeddings',
1025
+ inputSchema: { type: 'object', properties: {} },
1026
+ handler: async () => {
1027
+ const { getDiskannRegistry } = await import('../memory/diskann-registry.js');
1028
+ const registry = getDiskannRegistry();
1029
+ return { success: true, snapshots: registry.list() };
1030
+ },
1031
+ },
1032
+ // ============================================================
1033
+ // ADR-121 Phase 8 (CLI) — AnnRouter MCP tools (alpha.48)
1034
+ // ============================================================
1035
+ //
1036
+ // Composition layer: agents declare the workload shape
1037
+ // (corpusSize/persistent/mutable) and the router picks between
1038
+ // HNSW / RaBitQ / DiskANN. The decision is returned to the agent
1039
+ // so they can see what was picked + why (useful for routing
1040
+ // explanations + cost attribution).
1041
+ {
1042
+ name: 'embeddings_ann_router_build',
1043
+ description: "Build an ANN index using AnnRouter — auto-selects between HNSW / RaBitQ / DiskANN based on workload. Use when you have a corpus to index and don't want to choose between the three backings yourself — declare the workload ({corpusSize, persistent, mutable}) and the router picks. Pair with embeddings_ann_router_search to query, embeddings_ann_router_status to see what was picked. For direct DiskANN control (e.g. for known billion-scale persistent indexes), use embeddings_diskann_build instead.",
1044
+ category: 'embeddings',
1045
+ inputSchema: {
1046
+ type: 'object',
1047
+ properties: {
1048
+ name: { type: 'string', description: 'Handle name. Must be unique per process.' },
1049
+ workload: {
1050
+ type: 'object',
1051
+ properties: {
1052
+ corpusSize: { type: 'number', description: 'Approximate corpus size.' },
1053
+ dimension: { type: 'number' },
1054
+ persistent: { type: 'boolean', description: 'Survive process restarts? Forces DiskANN.' },
1055
+ mutable: { type: 'boolean', description: 'Streaming inserts/deletes after build? Prefers HNSW.' },
1056
+ storagePath: { type: 'string', description: 'On-disk path; required when persistent=true.' },
1057
+ },
1058
+ required: ['corpusSize', 'dimension'],
1059
+ },
1060
+ entries: {
1061
+ type: 'array',
1062
+ items: {
1063
+ type: 'object',
1064
+ properties: { id: { type: 'string' }, vector: { type: 'array', items: { type: 'number' } } },
1065
+ required: ['id', 'vector'],
1066
+ },
1067
+ },
1068
+ },
1069
+ required: ['name', 'workload', 'entries'],
1070
+ },
1071
+ handler: async (input) => {
1072
+ const { getAnnRouterRegistry } = await import('../memory/ann-router-registry.js');
1073
+ const registry = getAnnRouterRegistry();
1074
+ try {
1075
+ const result = await registry.build({
1076
+ name: input.name,
1077
+ workload: input.workload,
1078
+ entries: input.entries,
1079
+ });
1080
+ return { success: true, name: input.name, ...result };
1081
+ }
1082
+ catch (err) {
1083
+ return { success: false, name: input.name, error: err instanceof Error ? err.message : String(err) };
1084
+ }
1085
+ },
1086
+ },
1087
+ {
1088
+ name: 'embeddings_ann_router_search',
1089
+ description: 'Search a named AnnRouter handle for the k nearest neighbors. Returns hits with the routing-decision-aware score (cosine sim for HNSW; L2 distance for RaBitQ/DiskANN — interpret relative to embeddings_ann_router_status). For raw DiskANN search use embeddings_diskann_search; for raw HNSW use SearchableEmbeddingCache.search directly.',
1090
+ category: 'embeddings',
1091
+ inputSchema: {
1092
+ type: 'object',
1093
+ properties: {
1094
+ name: { type: 'string' },
1095
+ vector: { type: 'array', items: { type: 'number' } },
1096
+ k: { type: 'number' },
1097
+ },
1098
+ required: ['name', 'vector', 'k'],
1099
+ },
1100
+ handler: async (input) => {
1101
+ const { getAnnRouterRegistry } = await import('../memory/ann-router-registry.js');
1102
+ const registry = getAnnRouterRegistry();
1103
+ try {
1104
+ const hits = await registry.search(input.name, new Float32Array(input.vector), input.k);
1105
+ return { success: true, name: input.name, k: input.k, hits };
1106
+ }
1107
+ catch (err) {
1108
+ return { success: false, name: input.name, error: err instanceof Error ? err.message : String(err) };
1109
+ }
1110
+ },
1111
+ },
1112
+ {
1113
+ name: 'embeddings_ann_router_status',
1114
+ description: 'List all AnnRouter handles, each with its decided backing, routing reason, and current count. Use to inventory routed indexes + confirm the router picked what you expected. For peer-dep family availability use embeddings_check_ruvector_sidecar.',
1115
+ category: 'embeddings',
1116
+ inputSchema: { type: 'object', properties: {} },
1117
+ handler: async () => {
1118
+ const { getAnnRouterRegistry } = await import('../memory/ann-router-registry.js');
1119
+ const registry = getAnnRouterRegistry();
1120
+ return { success: true, handles: registry.list() };
1121
+ },
1122
+ },
943
1123
  ];
944
1124
  //# sourceMappingURL=embeddings-tools.js.map
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Process-level registry of named AnnRouter handles backing the
3
+ * `embeddings_ann_router_*` MCP tools.
4
+ *
5
+ * Mirrors the shape of `diskann-registry.ts` but for the unified
6
+ * routing layer. Lifecycle:
7
+ * - `build({ name, workload, entries })` creates an AnnRouter with
8
+ * the given workload, adds the entries, calls build, stashes the
9
+ * handle under `name`. Returns the routing decision so agents
10
+ * can see which backing was picked + why.
11
+ * - `search(name, vector, k)` runs top-k against the named handle.
12
+ * - `list()` returns all handles with their decision + count.
13
+ *
14
+ * ADR-121 Phase 8 (CLI) — cli alpha.48.
15
+ */
16
+ export interface AnnRouterBuildInput {
17
+ readonly name: string;
18
+ readonly workload: {
19
+ readonly corpusSize: number;
20
+ readonly dimension: number;
21
+ readonly persistent?: boolean;
22
+ readonly mutable?: boolean;
23
+ readonly storagePath?: string;
24
+ };
25
+ readonly entries: ReadonlyArray<{
26
+ id: string;
27
+ vector: number[];
28
+ }>;
29
+ }
30
+ export interface AnnRouterDecisionView {
31
+ readonly backing: string;
32
+ readonly reason: string;
33
+ readonly degraded: boolean;
34
+ readonly degradationReason?: string;
35
+ }
36
+ export interface AnnRouterBuildResult {
37
+ readonly decision: AnnRouterDecisionView;
38
+ readonly count: number;
39
+ readonly buildMs: number;
40
+ }
41
+ export interface AnnRouterSearchHit {
42
+ readonly id: string;
43
+ readonly score: number;
44
+ }
45
+ export interface AnnRouterHandleInfo {
46
+ readonly name: string;
47
+ readonly decision: AnnRouterDecisionView;
48
+ readonly count: number;
49
+ }
50
+ declare class AnnRouterRegistry {
51
+ private readonly entries;
52
+ private ctor;
53
+ private loadCtor;
54
+ build(input: AnnRouterBuildInput): Promise<AnnRouterBuildResult>;
55
+ search(name: string, vector: Float32Array, k: number): Promise<AnnRouterSearchHit[]>;
56
+ list(): AnnRouterHandleInfo[];
57
+ clear(): void;
58
+ }
59
+ export declare function getAnnRouterRegistry(): AnnRouterRegistry;
60
+ export {};
61
+ //# sourceMappingURL=ann-router-registry.d.ts.map
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Process-level registry of named AnnRouter handles backing the
3
+ * `embeddings_ann_router_*` MCP tools.
4
+ *
5
+ * Mirrors the shape of `diskann-registry.ts` but for the unified
6
+ * routing layer. Lifecycle:
7
+ * - `build({ name, workload, entries })` creates an AnnRouter with
8
+ * the given workload, adds the entries, calls build, stashes the
9
+ * handle under `name`. Returns the routing decision so agents
10
+ * can see which backing was picked + why.
11
+ * - `search(name, vector, k)` runs top-k against the named handle.
12
+ * - `list()` returns all handles with their decision + count.
13
+ *
14
+ * ADR-121 Phase 8 (CLI) — cli alpha.48.
15
+ */
16
+ class AnnRouterRegistry {
17
+ entries = new Map();
18
+ ctor = null;
19
+ async loadCtor() {
20
+ if (this.ctor)
21
+ return this.ctor;
22
+ const mod = await import('@claude-flow/embeddings/ann-router');
23
+ this.ctor = mod.AnnRouter;
24
+ return this.ctor;
25
+ }
26
+ async build(input) {
27
+ const Ctor = await this.loadCtor();
28
+ const t0 = Date.now();
29
+ const router = await Ctor.create(input.workload);
30
+ const float32 = input.entries.map(e => ({
31
+ id: e.id,
32
+ vector: new Float32Array(e.vector),
33
+ }));
34
+ await router.add(float32);
35
+ await router.build();
36
+ const buildMs = Date.now() - t0;
37
+ this.entries.set(input.name, { router, decision: router.decision });
38
+ return {
39
+ decision: router.decision,
40
+ count: router.count(),
41
+ buildMs,
42
+ };
43
+ }
44
+ async search(name, vector, k) {
45
+ const entry = this.entries.get(name);
46
+ if (!entry) {
47
+ throw new Error(`embeddings_ann_router_search: no router named "${name}" — call embeddings_ann_router_build first`);
48
+ }
49
+ return entry.router.search(vector, k);
50
+ }
51
+ list() {
52
+ const out = [];
53
+ for (const [name, entry] of this.entries) {
54
+ out.push({
55
+ name,
56
+ decision: entry.decision,
57
+ count: entry.router.count(),
58
+ });
59
+ }
60
+ return out;
61
+ }
62
+ clear() {
63
+ this.entries.clear();
64
+ }
65
+ }
66
+ let singleton = null;
67
+ export function getAnnRouterRegistry() {
68
+ if (!singleton)
69
+ singleton = new AnnRouterRegistry();
70
+ return singleton;
71
+ }
72
+ //# sourceMappingURL=ann-router-registry.js.map
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Process-level registry of named `DiskannSnapshot` handles backing
3
+ * the `embeddings_diskann_*` MCP tools.
4
+ *
5
+ * Lifecycle:
6
+ * - `build({ name, dimension, entries, storagePath? })` →
7
+ * creates a snapshot, adds the entries, builds the Vamana graph,
8
+ * persists if storagePath is set, stashes the handle under `name`.
9
+ * - `search(name, vector, k)` → top-k against the named snapshot.
10
+ * - `list()` → inventory of all current snapshots (name, dimension,
11
+ * count, storagePath?).
12
+ *
13
+ * The registry is process-level; agents that want cross-restart
14
+ * persistence should pass `storagePath` on build and reload from
15
+ * disk via a separate `embeddings_diskann_load` follow-up tool.
16
+ *
17
+ * ADR-121 Phase 5b — cli alpha.47.
18
+ */
19
+ export interface DiskannBuildInput {
20
+ readonly name: string;
21
+ readonly dimension: number;
22
+ readonly entries: ReadonlyArray<{
23
+ id: string;
24
+ vector: number[];
25
+ }>;
26
+ readonly storagePath?: string;
27
+ }
28
+ export interface DiskannBuildResult {
29
+ readonly dimension: number;
30
+ readonly count: number;
31
+ readonly buildMs: number;
32
+ readonly storagePath?: string;
33
+ }
34
+ export interface DiskannSearchHit {
35
+ readonly id: string;
36
+ readonly distance: number;
37
+ }
38
+ export interface DiskannSnapshotInfo {
39
+ readonly name: string;
40
+ readonly dimension: number;
41
+ readonly count: number;
42
+ readonly storagePath?: string;
43
+ }
44
+ declare class DiskannRegistry {
45
+ private readonly entries;
46
+ private snapshotCtor;
47
+ private loadCtor;
48
+ build(input: DiskannBuildInput): Promise<DiskannBuildResult>;
49
+ search(name: string, vector: Float32Array, k: number): Promise<DiskannSearchHit[]>;
50
+ list(): DiskannSnapshotInfo[];
51
+ /** Test seam — clear the registry between tests. */
52
+ clear(): void;
53
+ }
54
+ export declare function getDiskannRegistry(): DiskannRegistry;
55
+ export {};
56
+ //# sourceMappingURL=diskann-registry.d.ts.map
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Process-level registry of named `DiskannSnapshot` handles backing
3
+ * the `embeddings_diskann_*` MCP tools.
4
+ *
5
+ * Lifecycle:
6
+ * - `build({ name, dimension, entries, storagePath? })` →
7
+ * creates a snapshot, adds the entries, builds the Vamana graph,
8
+ * persists if storagePath is set, stashes the handle under `name`.
9
+ * - `search(name, vector, k)` → top-k against the named snapshot.
10
+ * - `list()` → inventory of all current snapshots (name, dimension,
11
+ * count, storagePath?).
12
+ *
13
+ * The registry is process-level; agents that want cross-restart
14
+ * persistence should pass `storagePath` on build and reload from
15
+ * disk via a separate `embeddings_diskann_load` follow-up tool.
16
+ *
17
+ * ADR-121 Phase 5b — cli alpha.47.
18
+ */
19
+ class DiskannRegistry {
20
+ entries = new Map();
21
+ snapshotCtor = null;
22
+ async loadCtor() {
23
+ if (this.snapshotCtor)
24
+ return this.snapshotCtor;
25
+ // Same wildcard sub-path import the sidecar tool uses (Phase 5 full).
26
+ const mod = await import('@claude-flow/embeddings/diskann-snapshot');
27
+ this.snapshotCtor = mod.DiskannSnapshot;
28
+ return this.snapshotCtor;
29
+ }
30
+ async build(input) {
31
+ const ctor = await this.loadCtor();
32
+ const t0 = Date.now();
33
+ const snap = await ctor.create({
34
+ dimension: input.dimension,
35
+ storagePath: input.storagePath,
36
+ });
37
+ // Convert plain-number arrays from the MCP input into Float32Array.
38
+ const float32Entries = input.entries.map(e => ({
39
+ id: e.id,
40
+ vector: new Float32Array(e.vector),
41
+ }));
42
+ snap.add(float32Entries);
43
+ await snap.build();
44
+ const buildMs = Date.now() - t0;
45
+ // Replace any existing snapshot under this name.
46
+ this.entries.set(input.name, {
47
+ snapshot: snap,
48
+ dimension: input.dimension,
49
+ storagePath: input.storagePath,
50
+ });
51
+ return {
52
+ dimension: input.dimension,
53
+ count: snap.count(),
54
+ buildMs,
55
+ storagePath: input.storagePath,
56
+ };
57
+ }
58
+ async search(name, vector, k) {
59
+ const entry = this.entries.get(name);
60
+ if (!entry) {
61
+ throw new Error(`embeddings_diskann_search: no snapshot named "${name}" — call embeddings_diskann_build first`);
62
+ }
63
+ return entry.snapshot.search(vector, k);
64
+ }
65
+ list() {
66
+ const out = [];
67
+ for (const [name, entry] of this.entries) {
68
+ out.push({
69
+ name,
70
+ dimension: entry.dimension,
71
+ count: entry.snapshot.count(),
72
+ storagePath: entry.storagePath,
73
+ });
74
+ }
75
+ return out;
76
+ }
77
+ /** Test seam — clear the registry between tests. */
78
+ clear() {
79
+ this.entries.clear();
80
+ }
81
+ }
82
+ let singleton = null;
83
+ export function getDiskannRegistry() {
84
+ if (!singleton)
85
+ singleton = new DiskannRegistry();
86
+ return singleton;
87
+ }
88
+ //# sourceMappingURL=diskann-registry.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.7.0-alpha.46",
3
+ "version": "3.7.0-alpha.48",
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",