@claude-flow/cli 3.32.34 → 3.32.36
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/.claude/helpers/helpers.manifest.json +5 -5
- package/.claude/helpers/hook-handler.cjs +30 -0
- package/.claude/helpers/intelligence.cjs +47 -4
- package/.claude/helpers/statusline.cjs +169 -6
- package/bin/cli.js +25 -1
- package/catalog-manifest.json +4 -4
- package/dist/src/commands/agent.js +50 -2
- package/dist/src/commands/doctor.js +159 -11
- package/dist/src/commands/hooks.js +63 -4
- package/dist/src/commands/mcp.js +1 -1
- package/dist/src/commands/memory-distill.js +1 -0
- package/dist/src/commands/metaharness.js +4 -0
- package/dist/src/commands/swarm.js +89 -5
- package/dist/src/config-adapter.js +1 -0
- package/dist/src/index.js +3 -2
- package/dist/src/init/executor.js +16 -10
- package/dist/src/init/helpers-generator.js +15 -4
- package/dist/src/init/statusline-generator.js +18 -5
- package/dist/src/mcp-server.d.ts +25 -0
- package/dist/src/mcp-server.js +57 -2
- package/dist/src/mcp-tools/agent-tools.js +10 -0
- package/dist/src/mcp-tools/embeddings-tools.js +51 -10
- package/dist/src/mcp-tools/hooks-tools.js +120 -60
- package/dist/src/mcp-tools/memory-tools.js +14 -2
- package/dist/src/mcp-tools/metaharness-tools.js +7 -0
- package/dist/src/mcp-tools/swarm-tools.d.ts +16 -0
- package/dist/src/mcp-tools/swarm-tools.js +172 -7
- package/dist/src/memory/memory-bridge.d.ts +2 -0
- package/dist/src/memory/memory-bridge.js +5 -1
- package/dist/src/memory/memory-initializer.d.ts +9 -1
- package/dist/src/memory/memory-initializer.js +66 -19
- package/dist/src/services/daemon-autostart.js +7 -4
- package/dist/src/services/flywheel-receipt.d.ts +3 -0
- package/dist/src/services/flywheel-receipt.js +1 -0
- package/dist/src/services/harness-flywheel-runtime.d.ts +6 -0
- package/dist/src/services/harness-flywheel-runtime.js +19 -19
- package/dist/src/services/harness-flywheel.d.ts +2 -0
- package/dist/src/services/harness-flywheel.js +1 -0
- package/dist/src/services/harness-project-anchor.d.ts +23 -0
- package/dist/src/services/harness-project-anchor.js +129 -0
- package/dist/src/services/learned-routing.d.ts +34 -0
- package/dist/src/services/learned-routing.js +85 -0
- package/dist/src/services/memory-distillation.d.ts +1 -0
- package/dist/src/services/memory-distillation.js +81 -5
- package/dist/src/services/pheromone-adaptive.d.ts +71 -0
- package/dist/src/services/pheromone-adaptive.js +214 -0
- package/dist/src/services/worker-daemon.js +5 -1
- package/node_modules/@claude-flow/codex/.agents/skills/github-automation/SKILL.md +32 -0
- package/node_modules/@claude-flow/codex/.agents/skills/performance-analysis/SKILL.md +32 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.d.ts +4 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.js +20 -1
- package/node_modules/@claude-flow/codex/dist/dual-mode/cli.js.map +1 -1
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts +4 -0
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js +18 -2
- package/node_modules/@claude-flow/codex/dist/dual-mode/orchestrator.js.map +1 -1
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts +11 -5
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js +84 -849
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js.map +1 -1
- package/node_modules/@claude-flow/codex/dist/initializer.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/initializer.js +9 -13
- package/node_modules/@claude-flow/codex/dist/initializer.js.map +1 -1
- package/package.json +1 -1
- package/plugins/ruflo-metaharness/scripts/_harness.mjs +5 -1
- package/plugins/ruflo-metaharness/scripts/_invoke.mjs +12 -13
- package/plugins/ruflo-metaharness/scripts/mcp-scan.mjs +7 -8
- package/plugins/ruflo-metaharness/scripts/smoke.sh +58 -2
- package/plugins/ruflo-metaharness/scripts/test-similarity.mjs +38 -0
- package/plugins/ruflo-metaharness/scripts/threat-model.mjs +4 -1
|
@@ -775,11 +775,22 @@ export function generateIntelligenceStub() {
|
|
|
775
775
|
"const path = require('path');",
|
|
776
776
|
"const os = require('os');",
|
|
777
777
|
'',
|
|
778
|
-
|
|
778
|
+
'function resolveProjectRoot(startDir) {',
|
|
779
|
+
' if (process.env.CLAUDE_PROJECT_DIR) return path.resolve(process.env.CLAUDE_PROJECT_DIR);',
|
|
780
|
+
' var dir = path.resolve(startDir || process.cwd());',
|
|
781
|
+
' while (true) {',
|
|
782
|
+
' if (fs.existsSync(path.join(dir, ".git")) || fs.existsSync(path.join(dir, ".claude-flow"))) return dir;',
|
|
783
|
+
' var parent = path.dirname(dir);',
|
|
784
|
+
' if (parent === dir) return path.resolve(startDir || process.cwd());',
|
|
785
|
+
' dir = parent;',
|
|
786
|
+
' }',
|
|
787
|
+
'}',
|
|
788
|
+
"const PROJECT_ROOT = resolveProjectRoot(process.cwd());",
|
|
789
|
+
"const DATA_DIR = path.join(PROJECT_ROOT, '.claude-flow', 'data');",
|
|
779
790
|
"const STORE_PATH = path.join(DATA_DIR, 'auto-memory-store.json');",
|
|
780
791
|
"const RANKED_PATH = path.join(DATA_DIR, 'ranked-context.json');",
|
|
781
792
|
"const PENDING_PATH = path.join(DATA_DIR, 'pending-insights.jsonl');",
|
|
782
|
-
"const SESSION_DIR = path.join(
|
|
793
|
+
"const SESSION_DIR = path.join(PROJECT_ROOT, '.claude-flow', 'sessions');",
|
|
783
794
|
"const SESSION_FILE = path.join(SESSION_DIR, 'current.json');",
|
|
784
795
|
'',
|
|
785
796
|
'function ensureDir(dir) {',
|
|
@@ -823,8 +834,8 @@ export function generateIntelligenceStub() {
|
|
|
823
834
|
' var entries = [];',
|
|
824
835
|
' var candidates = [',
|
|
825
836
|
' path.join(os.homedir(), ".claude", "projects"),',
|
|
826
|
-
' path.join(
|
|
827
|
-
' path.join(
|
|
837
|
+
' path.join(PROJECT_ROOT, ".claude-flow", "memory"),',
|
|
838
|
+
' path.join(PROJECT_ROOT, ".claude", "memory"),',
|
|
828
839
|
' ];',
|
|
829
840
|
' for (var i = 0; i < candidates.length; i++) {',
|
|
830
841
|
' try {',
|
|
@@ -53,6 +53,16 @@ function getInstalledCliVersionLocal() {
|
|
|
53
53
|
return '0.0.0';
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
function compareVersionsLocal(a, b) {
|
|
57
|
+
const pa = a.split(/[.-]/).map(part => Number.parseInt(part, 10) || 0);
|
|
58
|
+
const pb = b.split(/[.-]/).map(part => Number.parseInt(part, 10) || 0);
|
|
59
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
60
|
+
const delta = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
61
|
+
if (delta !== 0)
|
|
62
|
+
return delta;
|
|
63
|
+
}
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
56
66
|
/**
|
|
57
67
|
* Generate optimized statusline script
|
|
58
68
|
* Output format:
|
|
@@ -91,10 +101,12 @@ export function generateStatuslineScript(options) {
|
|
|
91
101
|
// getInstalledCliVersionLocal() above — reuse the pattern for the
|
|
92
102
|
// same reason it exists there.
|
|
93
103
|
let helperContent = null;
|
|
104
|
+
let helperPackageRoot = '';
|
|
94
105
|
try {
|
|
95
106
|
const esmRequire = createRequire(import.meta.url);
|
|
96
107
|
const pkgJsonPath = esmRequire.resolve('@claude-flow/cli/package.json');
|
|
97
|
-
|
|
108
|
+
helperPackageRoot = path.dirname(pkgJsonPath);
|
|
109
|
+
const helperPath = path.join(helperPackageRoot, '.claude', 'helpers', 'statusline.cjs');
|
|
98
110
|
helperContent = fs.readFileSync(helperPath, 'utf-8');
|
|
99
111
|
}
|
|
100
112
|
catch {
|
|
@@ -105,6 +117,7 @@ export function generateStatuslineScript(options) {
|
|
|
105
117
|
if (pkg && pkg.name === '@claude-flow/cli') {
|
|
106
118
|
const candidate = path.join(dir, '.claude', 'helpers', 'statusline.cjs');
|
|
107
119
|
if (fs.existsSync(candidate)) {
|
|
120
|
+
helperPackageRoot = dir;
|
|
108
121
|
helperContent = fs.readFileSync(candidate, 'utf-8');
|
|
109
122
|
break;
|
|
110
123
|
}
|
|
@@ -128,15 +141,15 @@ export function generateStatuslineScript(options) {
|
|
|
128
141
|
// whatever the helper hard-codes) ships. Add a paired test in
|
|
129
142
|
// statusline-cost-display.test.ts before changing either token.
|
|
130
143
|
helperContent = helperContent.replace(/maxAgents: \d+,/, `maxAgents: ${maxAgents},`);
|
|
144
|
+
helperContent = helperContent.replace(/const BAKED_INSTALL_ROOT = "[^"]*";/, `const BAKED_INSTALL_ROOT = ${JSON.stringify(helperPackageRoot)};`);
|
|
131
145
|
// Only overwrite the helper's baked version if OURS resolves higher.
|
|
132
146
|
// Otherwise the substitution could DOWNGRADE (test environments where
|
|
133
147
|
// esmRequire.resolve happens to hit an older node_modules install would
|
|
134
|
-
// clobber a fresh committed helper).
|
|
135
|
-
//
|
|
136
|
-
// reliable at this stage of the version space.
|
|
148
|
+
// clobber a fresh committed helper). Compare numeric components:
|
|
149
|
+
// lexicographic comparison freezes 3.32.24 below 3.32.8 (#2811).
|
|
137
150
|
const helperVerMatch = helperContent.match(/let ver = "([^"]+)";/);
|
|
138
151
|
const helperVer = helperVerMatch ? helperVerMatch[1] : '';
|
|
139
|
-
if (!helperVer || bakedVersion >
|
|
152
|
+
if (!helperVer || compareVersionsLocal(bakedVersion, helperVer) > 0) {
|
|
140
153
|
helperContent = helperContent.replace(/let ver = "[^"]+";/, `let ver = ${JSON.stringify(bakedVersion)};`);
|
|
141
154
|
}
|
|
142
155
|
return helperContent;
|
package/dist/src/mcp-server.d.ts
CHANGED
|
@@ -48,6 +48,31 @@ export interface MCPServerStatus {
|
|
|
48
48
|
metrics?: Record<string, number>;
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
|
+
export declare function parseMcpToolSelection(value: string | undefined): string[] | 'all';
|
|
52
|
+
/**
|
|
53
|
+
* Apply the existing `--tools` contract to advertised schemas. A selector can
|
|
54
|
+
* be an exact tool name, a category, or a namespace prefix (`memory` matches
|
|
55
|
+
* `memory_store`). Execution remains registered internally; only the fixed
|
|
56
|
+
* per-request schema catalogue is reduced.
|
|
57
|
+
*/
|
|
58
|
+
export declare function filterAdvertisedMcpTools<T extends {
|
|
59
|
+
name: string;
|
|
60
|
+
category?: string;
|
|
61
|
+
}>(tools: T[], selection: string[] | 'all'): T[];
|
|
62
|
+
export interface McpSchemaOverhead {
|
|
63
|
+
toolCount: number;
|
|
64
|
+
bytes: number;
|
|
65
|
+
estimatedTokens: number;
|
|
66
|
+
contextWindowTokens?: number;
|
|
67
|
+
ratio?: number;
|
|
68
|
+
risk: 'normal' | 'high';
|
|
69
|
+
}
|
|
70
|
+
/** Conservative JSON-size estimate for the fixed tools/list catalogue. */
|
|
71
|
+
export declare function assessMcpSchemaOverhead(tools: Array<{
|
|
72
|
+
name: string;
|
|
73
|
+
description?: string;
|
|
74
|
+
inputSchema?: unknown;
|
|
75
|
+
}>, contextWindowTokens?: number): McpSchemaOverhead;
|
|
51
76
|
/**
|
|
52
77
|
* MCP Server Manager
|
|
53
78
|
*
|
package/dist/src/mcp-server.js
CHANGED
|
@@ -42,6 +42,54 @@ const DEFAULT_OPTIONS = {
|
|
|
42
42
|
daemonize: false,
|
|
43
43
|
timeout: 30000,
|
|
44
44
|
};
|
|
45
|
+
export function parseMcpToolSelection(value) {
|
|
46
|
+
if (!value || value.trim().toLowerCase() === 'all')
|
|
47
|
+
return 'all';
|
|
48
|
+
const selectors = value.split(',').map((item) => item.trim()).filter(Boolean);
|
|
49
|
+
return selectors.length > 0 ? selectors : 'all';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Apply the existing `--tools` contract to advertised schemas. A selector can
|
|
53
|
+
* be an exact tool name, a category, or a namespace prefix (`memory` matches
|
|
54
|
+
* `memory_store`). Execution remains registered internally; only the fixed
|
|
55
|
+
* per-request schema catalogue is reduced.
|
|
56
|
+
*/
|
|
57
|
+
export function filterAdvertisedMcpTools(tools, selection) {
|
|
58
|
+
if (selection === 'all')
|
|
59
|
+
return tools;
|
|
60
|
+
const selectors = new Set(selection.map((item) => item.toLowerCase()));
|
|
61
|
+
return tools.filter((tool) => {
|
|
62
|
+
const name = tool.name.toLowerCase();
|
|
63
|
+
const category = tool.category?.toLowerCase();
|
|
64
|
+
return selectors.has(name)
|
|
65
|
+
|| (category !== undefined && selectors.has(category))
|
|
66
|
+
|| Array.from(selectors).some((selector) => name.startsWith(`${selector}_`));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** Conservative JSON-size estimate for the fixed tools/list catalogue. */
|
|
70
|
+
export function assessMcpSchemaOverhead(tools, contextWindowTokens) {
|
|
71
|
+
const catalogue = tools.map((tool) => ({
|
|
72
|
+
name: tool.name,
|
|
73
|
+
description: tool.description,
|
|
74
|
+
inputSchema: tool.inputSchema,
|
|
75
|
+
}));
|
|
76
|
+
const bytes = Buffer.byteLength(JSON.stringify(catalogue), 'utf8');
|
|
77
|
+
const estimatedTokens = Math.ceil(bytes / 4);
|
|
78
|
+
const validWindow = Number.isFinite(contextWindowTokens) && Number(contextWindowTokens) > 0
|
|
79
|
+
? Number(contextWindowTokens)
|
|
80
|
+
: undefined;
|
|
81
|
+
const ratio = validWindow ? estimatedTokens / validWindow : undefined;
|
|
82
|
+
return {
|
|
83
|
+
toolCount: tools.length,
|
|
84
|
+
bytes,
|
|
85
|
+
estimatedTokens,
|
|
86
|
+
...(validWindow === undefined ? {} : { contextWindowTokens: validWindow }),
|
|
87
|
+
...(ratio === undefined ? {} : { ratio }),
|
|
88
|
+
risk: (ratio !== undefined ? ratio >= 0.2 : estimatedTokens >= 8_000)
|
|
89
|
+
? 'high'
|
|
90
|
+
: 'normal',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
45
93
|
/**
|
|
46
94
|
* MCP Server Manager
|
|
47
95
|
*
|
|
@@ -55,7 +103,14 @@ export class MCPServerManager extends EventEmitter {
|
|
|
55
103
|
healthCheckInterval;
|
|
56
104
|
constructor(options = {}) {
|
|
57
105
|
super();
|
|
58
|
-
|
|
106
|
+
// `options.tools`, populated by the `mcp start --tools` CLI flag, is
|
|
107
|
+
// spread last below and therefore takes precedence over this env fallback.
|
|
108
|
+
const environmentTools = parseMcpToolSelection(process.env.CLAUDE_FLOW_MCP_TOOLS);
|
|
109
|
+
this.options = {
|
|
110
|
+
...DEFAULT_OPTIONS,
|
|
111
|
+
...(environmentTools === 'all' ? {} : { tools: environmentTools }),
|
|
112
|
+
...options,
|
|
113
|
+
};
|
|
59
114
|
}
|
|
60
115
|
/**
|
|
61
116
|
* Start the MCP server
|
|
@@ -420,7 +475,7 @@ export class MCPServerManager extends EventEmitter {
|
|
|
420
475
|
},
|
|
421
476
|
};
|
|
422
477
|
case 'tools/list':
|
|
423
|
-
const tools = listMCPTools();
|
|
478
|
+
const tools = filterAdvertisedMcpTools(listMCPTools(), this.options.tools);
|
|
424
479
|
return {
|
|
425
480
|
jsonrpc: '2.0',
|
|
426
481
|
id: message.id,
|
|
@@ -9,6 +9,7 @@ import { join } from 'node:path';
|
|
|
9
9
|
import { getProjectCwd } from './types.js';
|
|
10
10
|
import { validateIdentifier, validateText, validateAgentSpawn } from './validate-input.js';
|
|
11
11
|
import { executeAgentTask } from './agent-execute-core.js';
|
|
12
|
+
import { pheromoneAgentEligibility } from './swarm-tools.js';
|
|
12
13
|
// Storage paths
|
|
13
14
|
const STORAGE_DIR = '.claude-flow';
|
|
14
15
|
const AGENT_DIR = 'agents';
|
|
@@ -383,6 +384,15 @@ export const agentTools = [
|
|
|
383
384
|
const vP = validateText(input.prompt, 'prompt');
|
|
384
385
|
if (!vP.valid)
|
|
385
386
|
return { success: false, error: `Input validation failed: ${vP.error}` };
|
|
387
|
+
const pheromone = pheromoneAgentEligibility(input.agentId);
|
|
388
|
+
if (!pheromone.eligible) {
|
|
389
|
+
return {
|
|
390
|
+
success: false,
|
|
391
|
+
agentId: input.agentId,
|
|
392
|
+
suspended: true,
|
|
393
|
+
error: pheromone.reason,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
386
396
|
// Delegate to the shared core (also used by the workflow runtime).
|
|
387
397
|
return executeAgentTask({
|
|
388
398
|
agentId: input.agentId,
|
|
@@ -50,13 +50,16 @@ async function getRealEmbeddingFunction() {
|
|
|
50
50
|
}
|
|
51
51
|
return realEmbeddingFn;
|
|
52
52
|
}
|
|
53
|
-
// Generate real ONNX embedding (falls back to deterministic hash if ONNX unavailable)
|
|
54
53
|
async function generateRealEmbedding(text, dimension) {
|
|
55
54
|
const realFn = await getRealEmbeddingFunction();
|
|
56
55
|
if (realFn) {
|
|
57
56
|
try {
|
|
58
57
|
const result = await realFn(text);
|
|
59
|
-
return
|
|
58
|
+
return {
|
|
59
|
+
embedding: result.embedding,
|
|
60
|
+
backend: result.backend ?? 'onnx',
|
|
61
|
+
model: result.model,
|
|
62
|
+
};
|
|
60
63
|
}
|
|
61
64
|
catch {
|
|
62
65
|
// Fall through to fallback
|
|
@@ -75,7 +78,11 @@ async function generateRealEmbedding(text, dimension) {
|
|
|
75
78
|
}
|
|
76
79
|
// L2 normalize
|
|
77
80
|
const norm = Math.sqrt(embedding.reduce((sum, x) => sum + x * x, 0));
|
|
78
|
-
return
|
|
81
|
+
return {
|
|
82
|
+
embedding: embedding.map(x => x / norm),
|
|
83
|
+
backend: 'mock',
|
|
84
|
+
model: 'hash-fallback',
|
|
85
|
+
};
|
|
79
86
|
}
|
|
80
87
|
// Convert Euclidean embedding to Poincaré ball
|
|
81
88
|
function toPoincare(euclidean, curvature) {
|
|
@@ -238,7 +245,8 @@ export const embeddingsTools = [
|
|
|
238
245
|
}
|
|
239
246
|
const useHyperbolic = input.hyperbolic === true && config.hyperbolic.enabled;
|
|
240
247
|
// Generate real ONNX embedding
|
|
241
|
-
const
|
|
248
|
+
const generated = await generateRealEmbedding(text, config.dimension);
|
|
249
|
+
const embedding = generated.embedding;
|
|
242
250
|
let result;
|
|
243
251
|
let geometry;
|
|
244
252
|
if (useHyperbolic) {
|
|
@@ -254,6 +262,8 @@ export const embeddingsTools = [
|
|
|
254
262
|
embedding: result,
|
|
255
263
|
metadata: {
|
|
256
264
|
model: config.model,
|
|
265
|
+
embeddingBackend: generated.backend,
|
|
266
|
+
semanticGrounded: generated.backend === 'onnx',
|
|
257
267
|
dimension: config.dimension,
|
|
258
268
|
geometry,
|
|
259
269
|
curvature: useHyperbolic ? config.hyperbolic.curvature : null,
|
|
@@ -309,10 +319,13 @@ export const embeddingsTools = [
|
|
|
309
319
|
return { success: false, error: v.error };
|
|
310
320
|
}
|
|
311
321
|
// Generate real ONNX embeddings for both texts
|
|
312
|
-
const [
|
|
322
|
+
const [generated1, generated2] = await Promise.all([
|
|
313
323
|
generateRealEmbedding(text1, config.dimension),
|
|
314
324
|
generateRealEmbedding(text2, config.dimension)
|
|
315
325
|
]);
|
|
326
|
+
const emb1 = generated1.embedding;
|
|
327
|
+
const emb2 = generated2.embedding;
|
|
328
|
+
const embeddingBackend = generated1.backend === 'onnx' && generated2.backend === 'onnx' ? 'onnx' : 'mock';
|
|
316
329
|
let similarity;
|
|
317
330
|
let distance;
|
|
318
331
|
switch (metric) {
|
|
@@ -341,14 +354,21 @@ export const embeddingsTools = [
|
|
|
341
354
|
similarity,
|
|
342
355
|
distance,
|
|
343
356
|
metric,
|
|
357
|
+
embeddingBackend,
|
|
358
|
+
semanticGrounded: embeddingBackend === 'onnx',
|
|
344
359
|
texts: {
|
|
345
360
|
text1: { length: text1.length, preview: text1.slice(0, 50) },
|
|
346
361
|
text2: { length: text2.length, preview: text2.slice(0, 50) },
|
|
347
362
|
},
|
|
348
|
-
interpretation:
|
|
349
|
-
similarity > 0.
|
|
350
|
-
similarity > 0.
|
|
351
|
-
similarity > 0.
|
|
363
|
+
interpretation: embeddingBackend === 'onnx'
|
|
364
|
+
? similarity > 0.8 ? 'very similar'
|
|
365
|
+
: similarity > 0.6 ? 'similar'
|
|
366
|
+
: similarity > 0.4 ? 'somewhat similar'
|
|
367
|
+
: similarity > 0.2 ? 'different' : 'very different'
|
|
368
|
+
: null,
|
|
369
|
+
warning: embeddingBackend === 'mock'
|
|
370
|
+
? 'Hash fallback scores are deterministic but not semantically meaningful.'
|
|
371
|
+
: undefined,
|
|
352
372
|
};
|
|
353
373
|
},
|
|
354
374
|
},
|
|
@@ -426,6 +446,8 @@ export const embeddingsTools = [
|
|
|
426
446
|
})),
|
|
427
447
|
metadata: {
|
|
428
448
|
model: config.model,
|
|
449
|
+
embeddingBackend: queryEmbedding.backend,
|
|
450
|
+
semanticGrounded: queryEmbedding.backend === 'onnx',
|
|
429
451
|
topK,
|
|
430
452
|
threshold,
|
|
431
453
|
namespace: namespace || 'all',
|
|
@@ -433,6 +455,9 @@ export const embeddingsTools = [
|
|
|
433
455
|
indexType: config.hyperbolic.enabled ? 'HNSW (hyperbolic)' : 'HNSW (euclidean)',
|
|
434
456
|
resultCount: searchResult.results.length
|
|
435
457
|
},
|
|
458
|
+
warning: queryEmbedding.backend === 'mock'
|
|
459
|
+
? 'Results use a hash fallback and are not semantically ranked.'
|
|
460
|
+
: undefined,
|
|
436
461
|
};
|
|
437
462
|
}
|
|
438
463
|
catch {
|
|
@@ -444,12 +469,17 @@ export const embeddingsTools = [
|
|
|
444
469
|
results: [],
|
|
445
470
|
metadata: {
|
|
446
471
|
model: config.model,
|
|
472
|
+
embeddingBackend: queryEmbedding.backend,
|
|
473
|
+
semanticGrounded: queryEmbedding.backend === 'onnx',
|
|
447
474
|
topK,
|
|
448
475
|
threshold,
|
|
449
476
|
namespace: namespace || 'all',
|
|
450
477
|
searchTime: `${searchTime}ms`,
|
|
451
478
|
indexType: config.hyperbolic.enabled ? 'HNSW (hyperbolic)' : 'HNSW (euclidean)',
|
|
452
479
|
},
|
|
480
|
+
warning: queryEmbedding.backend === 'mock'
|
|
481
|
+
? 'Hash fallback is active; semantic search is unavailable.'
|
|
482
|
+
: undefined,
|
|
453
483
|
message: 'No embeddings indexed yet. Use memory store to add documents.',
|
|
454
484
|
};
|
|
455
485
|
}
|
|
@@ -795,6 +825,8 @@ export const embeddingsTools = [
|
|
|
795
825
|
}
|
|
796
826
|
catch { /* not installed */ }
|
|
797
827
|
const ruvectorEnabled = config.neural.ruvector?.enabled ?? false;
|
|
828
|
+
const backendProbe = await generateRealEmbedding('ruflo embedding backend probe', config.dimension);
|
|
829
|
+
const semanticGrounded = backendProbe.backend === 'onnx';
|
|
798
830
|
return {
|
|
799
831
|
success: true,
|
|
800
832
|
initialized: true,
|
|
@@ -822,11 +854,20 @@ export const embeddingsTools = [
|
|
|
822
854
|
models: config.modelPath,
|
|
823
855
|
},
|
|
824
856
|
initializedAt: config.initialized,
|
|
857
|
+
embeddingBackend: backendProbe.backend,
|
|
858
|
+
semanticGrounded,
|
|
859
|
+
warning: semanticGrounded
|
|
860
|
+
? undefined
|
|
861
|
+
: 'Hash fallback is active. Similarity scores are deterministic but not semantically meaningful.',
|
|
825
862
|
capabilities: {
|
|
826
863
|
onnxModels: ['Xenova/all-MiniLM-L6-v2', 'Xenova/all-mpnet-base-v2'],
|
|
827
864
|
geometries: ['euclidean', 'poincare'],
|
|
828
865
|
normalizations: ['L2', 'L1', 'minmax', 'zscore'],
|
|
829
|
-
features: [
|
|
866
|
+
features: [
|
|
867
|
+
...(semanticGrounded ? ['semantic search'] : []),
|
|
868
|
+
'hyperbolic projection',
|
|
869
|
+
'neural substrate',
|
|
870
|
+
],
|
|
830
871
|
},
|
|
831
872
|
};
|
|
832
873
|
},
|