monomind 1.16.2 → 1.16.4

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": "monomind",
3
- "version": "1.16.2",
3
+ "version": "1.16.4",
4
4
  "description": "Monomind - 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",
@@ -213,7 +213,11 @@ async function startBackgroundDaemon(projectRoot, quiet, maxCpuLoad, minFreeMemo
213
213
  const __dirname = dirname(__filename);
214
214
  // dist/src/commands -> dist/src -> dist -> package root -> bin/cli.js
215
215
  const cliPath = resolve(join(__dirname, '..', '..', '..', 'bin', 'cli.js'));
216
- validatePath(cliPath, 'CLI path');
216
+ // monolean: CLI may be in global npm install (different drive on Windows) — only
217
+ // check for injection, not directory containment
218
+ if (cliPath.includes('\0') || /[;&|`$<>]/.test(cliPath)) {
219
+ throw new Error('CLI path contains invalid characters');
220
+ }
217
221
  // Verify CLI path exists
218
222
  if (!fs.existsSync(cliPath)) {
219
223
  output.printError(`CLI not found at: ${cliPath}`);
@@ -186,7 +186,11 @@ async function checkMcpServers() {
186
186
  const mcpConfigPaths = [
187
187
  join(homedir(), '.claude/claude_desktop_config.json'),
188
188
  join(homedir(), '.config/claude/mcp.json'),
189
- '.mcp.json'
189
+ '.mcp.json',
190
+ // Claude Code local/project scope stores MCP servers in settings files
191
+ '.claude/settings.json',
192
+ '.claude/settings.local.json',
193
+ join(homedir(), '.claude/settings.json'),
190
194
  ];
191
195
  for (const configPath of mcpConfigPaths) {
192
196
  if (existsSync(configPath) && statSync(configPath).size <= MAX_DOCTOR_CONFIG_BYTES) {
@@ -550,7 +554,6 @@ async function checkMonoesMemory() {
550
554
  return { name: 'Vector Memory', status: 'warn', message: 'Vector memory check failed' };
551
555
  }
552
556
  }
553
- // Check agentic-flow v1 integration (filesystem-based to avoid slow WASM/DB init)
554
557
  // Resolve the path to the bundled (npm-installed) copy of a helper file.
555
558
  // Walks up from this module's location to find the package root, then joins
556
559
  // the relative path. Returns null if not found.
@@ -635,49 +638,6 @@ async function checkHelpersFresh() {
635
638
  return { name: 'Helper Files', status: 'warn', message: `check failed: ${e instanceof Error ? e.message : 'unknown'}` };
636
639
  }
637
640
  }
638
- async function checkAgenticFlow() {
639
- try {
640
- // Walk common node_modules paths to find agentic-flow/package.json
641
- const candidates = [
642
- join(process.cwd(), 'node_modules', 'agentic-flow', 'package.json'),
643
- join(process.cwd(), '..', 'node_modules', 'agentic-flow', 'package.json'),
644
- ];
645
- let pkgJsonPath = null;
646
- for (const p of candidates) {
647
- if (existsSync(p)) {
648
- pkgJsonPath = p;
649
- break;
650
- }
651
- }
652
- if (!pkgJsonPath) {
653
- return {
654
- name: 'agentic-flow',
655
- status: 'warn',
656
- message: 'Not installed (optional — embeddings/routing will use fallbacks)',
657
- fix: 'npm install agentic-flow@latest'
658
- };
659
- }
660
- if (statSync(pkgJsonPath).size > MAX_DOCTOR_PKG_BYTES) {
661
- return { name: 'agentic-flow', status: 'warn', message: 'package.json too large to parse' };
662
- }
663
- const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
664
- const version = pkg.version || 'unknown';
665
- const exports = pkg.exports || {};
666
- const features = [
667
- exports['./reasoningbank'] ? 'ReasoningBank' : null,
668
- exports['./router'] ? 'Router' : null,
669
- exports['./transport/quic'] ? 'QUIC' : null,
670
- ].filter(Boolean);
671
- return {
672
- name: 'agentic-flow',
673
- status: 'pass',
674
- message: `v${version}${features.length ? ' (' + features.join(', ') + ')' : ' (installed)'}`
675
- };
676
- }
677
- catch {
678
- return { name: 'agentic-flow', status: 'warn', message: 'Check failed' };
679
- }
680
- }
681
641
  // Check @monoes native acceleration integration (sona/router/attention/learning-wasm)
682
642
  // Format a 0..1 accuracy as a whole-percent string, or 'n/a' when null.
683
643
  function fmtPct(v) {
@@ -876,7 +836,7 @@ export const doctorCommand = {
876
836
  {
877
837
  name: 'component',
878
838
  short: 'c',
879
- description: 'Check specific component (version, node, npm, config, daemon, memory, api, git, mcp, claude, disk, typescript, monograph, graph-freshness, memory-pkg, helpers, agentic-flow, monoes, gates, gitignore)',
839
+ description: 'Check specific component (version, node, npm, config, daemon, memory, api, git, mcp, claude, disk, typescript, monograph, graph-freshness, memory-pkg, helpers, monoes, gates, gitignore)',
880
840
  type: 'string'
881
841
  },
882
842
  {
@@ -922,7 +882,6 @@ export const doctorCommand = {
922
882
  checkMonographFreshness,
923
883
  checkMonoesMemory,
924
884
  checkHelpersFresh,
925
- checkAgenticFlow,
926
885
  checkMonoesIntegration,
927
886
  checkGuidanceGates,
928
887
  checkGitignoreCoverage,
@@ -945,7 +904,6 @@ export const doctorCommand = {
945
904
  'graph-freshness': checkMonographFreshness,
946
905
  'memory-pkg': checkMonoesMemory,
947
906
  'helpers': checkHelpersFresh,
948
- 'agentic-flow': checkAgenticFlow,
949
907
  'monoes': checkMonoesIntegration,
950
908
  'gates': checkGuidanceGates,
951
909
  'gitignore': checkGitignoreCoverage,
@@ -880,7 +880,7 @@ export const statuslineCommand = {
880
880
  try {
881
881
  const psCmd = isWindows
882
882
  ? 'tasklist /FI "IMAGENAME eq node.exe" 2>NUL | findstr /I /C:"node" >NUL && echo 1 || echo 0'
883
- : 'ps aux 2>/dev/null | grep -c agentic-flow || echo "0"';
883
+ : 'ps aux 2>/dev/null | grep -c "mcp.*start" || echo "0"';
884
884
  const ps = execSync(psCmd, { encoding: 'utf-8' });
885
885
  const raw = parseInt(ps.trim());
886
886
  activeAgents = Math.max(0, isWindows ? raw : raw - 1);
@@ -5,10 +5,10 @@
5
5
  */
6
6
  import { output } from '../output.js';
7
7
  import { callMCPTool, MCPClientError } from '../mcp-client.js';
8
- // Token Optimizer command - integrates agentic-flow Agent Booster
8
+ // Token Optimizer command
9
9
  export const tokenOptimizeCommand = {
10
10
  name: 'token-optimize',
11
- description: 'Token optimization via agentic-flow Agent Booster (30-50% savings)',
11
+ description: 'Token optimization via memory-based context retrieval (30-50% savings)',
12
12
  options: [
13
13
  { name: 'query', short: 'q', type: 'string', description: 'Query for compact context retrieval' },
14
14
  { name: 'agents', short: 'A', type: 'number', description: 'Agent count for optimal config', default: '6' },
@@ -25,7 +25,7 @@ export const tokenOptimizeCommand = {
25
25
  const agentCount = parseInt(ctx.flags['agents'] || '6', 10);
26
26
  const showReport = ctx.flags['report'];
27
27
  const showStats = ctx.flags['stats'];
28
- const spinner = output.createSpinner({ text: 'Checking agentic-flow integration...', spinner: 'dots' });
28
+ const spinner = output.createSpinner({ text: 'Checking memory integration...', spinner: 'dots' });
29
29
  spinner.start();
30
30
  // Inline TokenOptimizer (self-contained, no external imports)
31
31
  const stats = {
@@ -35,26 +35,8 @@ export const tokenOptimizeCommand = {
35
35
  cacheMisses: 0,
36
36
  memoriesRetrieved: 0,
37
37
  };
38
- let agenticFlowAvailable = false;
39
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
- let reasoningBank = null;
41
38
  try {
42
- // Check if agentic-flow v1 is available
43
- const rb = await import('agentic-flow/reasoningbank').catch(() => null);
44
- if (rb) {
45
- agenticFlowAvailable = true;
46
- if (typeof rb.retrieveMemories === 'function') {
47
- reasoningBank = rb;
48
- }
49
- }
50
- else {
51
- // Legacy check for older agentic-flow
52
- const af = await import('agentic-flow').catch(() => null);
53
- if (af)
54
- agenticFlowAvailable = true;
55
- }
56
- const versionLabel = agenticFlowAvailable ? `agentic-flow v1 detected (ReasoningBank: ${reasoningBank ? 'active' : 'unavailable'})` : 'agentic-flow not available (using fallbacks)';
57
- spinner.succeed(versionLabel);
39
+ spinner.succeed('Memory-based token optimization active');
58
40
  output.writeln();
59
41
  // Anti-drift config (hardcoded optimal values from research)
60
42
  const config = {
@@ -69,27 +51,9 @@ export const tokenOptimizeCommand = {
69
51
  `Batch Size: ${config.batchSize}\n` +
70
52
  `Cache: ${config.cacheSizeMB}MB\n` +
71
53
  `Success Rate: ${(config.expectedSuccessRate * 100)}%`);
72
- // If query provided, get compact context via ReasoningBank
73
- if (query && reasoningBank) {
74
- output.writeln();
75
- output.printInfo(`Retrieving compact context for: "${query}"`);
76
- const memories = await reasoningBank.retrieveMemories(query, { k: 5 });
77
- const compactPrompt = reasoningBank.formatMemoriesForPrompt ? reasoningBank.formatMemoriesForPrompt(memories) : '';
78
- // Estimate based on actual query vs compact prompt size difference
79
- const queryTokenEstimate = Math.ceil((query?.length || 0) / 4);
80
- const used = Math.ceil((compactPrompt?.length || 0) / 4);
81
- const tokensSaved = Math.max(0, queryTokenEstimate - used);
82
- stats.totalTokensSaved += tokensSaved;
83
- stats.memoriesRetrieved += Array.isArray(memories) ? memories.length : 0;
84
- output.writeln(` Memories found: ${Array.isArray(memories) ? memories.length : 0}`);
85
- output.writeln(` Tokens saved: ${output.success(String(tokensSaved))}`);
86
- if (compactPrompt) {
87
- output.writeln(` Compact prompt (${compactPrompt.length} chars)`);
88
- }
89
- }
90
- else if (query) {
54
+ if (query) {
91
55
  output.writeln();
92
- output.printInfo('ReasoningBank not available - query skipped');
56
+ output.printInfo(`Context retrieval for: "${query}" — use monomind memory search`);
93
57
  }
94
58
  // Simulate some token savings for demo
95
59
  stats.totalTokensSaved += 200;
@@ -112,7 +76,6 @@ export const tokenOptimizeCommand = {
112
76
  { metric: 'Cache Hit Rate', value: `${hitRate}%` },
113
77
  { metric: 'Memories Retrieved', value: String(stats.memoriesRetrieved) },
114
78
  { metric: 'Est. Monthly Savings', value: `$${savings}` },
115
- { metric: 'Agentic-Flow Active', value: agenticFlowAvailable ? '✓' : '✗' },
116
79
  ],
117
80
  });
118
81
  }
@@ -131,9 +94,9 @@ export const tokenOptimizeCommand = {
131
94
  | Cache Hit Rate | ${hitRate}% |
132
95
  | Memories Retrieved | ${stats.memoriesRetrieved} |
133
96
  | Est. Monthly Savings | $${savings} |
134
- | Agentic-Flow Active | ${agenticFlowAvailable ? '✓' : '✗'} |`);
97
+ | Memories Retrieved | ${stats.memoriesRetrieved} |`);
135
98
  }
136
- return { success: true, data: { config, stats: { ...stats, agenticFlowAvailable } } };
99
+ return { success: true, data: { config, stats } };
137
100
  }
138
101
  catch (error) {
139
102
  spinner.fail('TokenOptimizer failed');
@@ -757,9 +757,9 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
757
757
  if (!fs.existsSync(activityPath)) {
758
758
  const activity = {
759
759
  timestamp: new Date().toISOString(),
760
- processes: { agentic_flow: 0, mcp_server: 0, estimated_agents: 0 },
760
+ processes: { mcp_server: 0, estimated_agents: 0 },
761
761
  swarm: { active: false, agent_count: 0, coordination_active: false },
762
- integration: { agentic_flow_active: false, mcp_active: false },
762
+ integration: { mcp_active: false },
763
763
  _initialized: true
764
764
  };
765
765
  atomicWriteFile(activityPath, JSON.stringify(activity, null, 2));
@@ -1582,7 +1582,6 @@ async function writeInitialMetrics(targetDir, options, result) {
1582
1582
  const activity = {
1583
1583
  timestamp: new Date().toISOString(),
1584
1584
  processes: {
1585
- agentic_flow: 0,
1586
1585
  mcp_server: 0,
1587
1586
  estimated_agents: 0
1588
1587
  },
@@ -1592,7 +1591,6 @@ async function writeInitialMetrics(targetDir, options, result) {
1592
1591
  coordination_active: false
1593
1592
  },
1594
1593
  integration: {
1595
- agentic_flow_active: false,
1596
1594
  mcp_active: false
1597
1595
  },
1598
1596
  _initialized: true
@@ -1977,7 +1975,6 @@ npx monomind@latest hive-mind consensus --propose "task"
1977
1975
  ### Integrated Packages
1978
1976
  | Package | Version | Purpose |
1979
1977
  |---------|---------|---------|
1980
- | agentic-flow | 3.0.0-alpha.1 | Core coordination + ReasoningBank + Router |
1981
1978
  | @lancedb/lancedb | latest | Vector database (ANN search) |
1982
1979
 
1983
1980
  ### Optional Integrations
@@ -159,7 +159,7 @@ const IS_WINDOWS = process.platform === 'win32';
159
159
  */
160
160
  function hookCmd(script, subcommand) {
161
161
  if (IS_WINDOWS) {
162
- return `cmd /c node %CLAUDE_PROJECT_DIR%/${script} ${subcommand}`.trim();
162
+ return `cmd /c node "%CLAUDE_PROJECT_DIR%/${script}" ${subcommand}`.trim();
163
163
  }
164
164
  // Use sh -c to ensure $CLAUDE_PROJECT_DIR is expanded by a real shell,
165
165
  // even if Claude Code doesn't invoke hooks through a shell on macOS.
@@ -180,13 +180,13 @@ function captureHandlerCmd(subcommand) {
180
180
  // capture-handler does not use sh -c wrapper — it reads stdin directly
181
181
  const dir = IS_WINDOWS ? '%CLAUDE_PROJECT_DIR%' : '${CLAUDE_PROJECT_DIR:-.}';
182
182
  return IS_WINDOWS
183
- ? `node ${dir}/.claude/helpers/handlers/capture-handler.cjs ${subcommand}`
183
+ ? `node "${dir}/.claude/helpers/handlers/capture-handler.cjs" ${subcommand}`
184
184
  : `node "${dir}/.claude/helpers/handlers/capture-handler.cjs" ${subcommand}`;
185
185
  }
186
186
  /** Shorthand for standalone CJS helper scripts (no subcommand) */
187
187
  function standaloneHelperCmd(script) {
188
188
  if (IS_WINDOWS) {
189
- return `cmd /c node %CLAUDE_PROJECT_DIR%/.claude/helpers/${script}`;
189
+ return `cmd /c node "%CLAUDE_PROJECT_DIR%/.claude/helpers/${script}"`;
190
190
  }
191
191
  // eslint-disable-next-line no-template-curly-in-string
192
192
  const dir = '${CLAUDE_PROJECT_DIR:-.}';
@@ -200,8 +200,14 @@ function generateStatusLineConfig(_options) {
200
200
  // Claude Code pipes JSON session data to the script via stdin.
201
201
  // Valid fields: type, command, padding (optional).
202
202
  // The script runs after each assistant message (debounced 300ms).
203
- // NOTE: statusline must NOT use `cmd /c` — Claude Code manages its stdin
204
- // directly for statusline commands, and `cmd /c` blocks stdin forwarding.
203
+ // NOTE: statusline must NOT use `cmd /c` on Windows either — Claude Code
204
+ // manages stdin directly for statusline commands; wrappers block forwarding.
205
+ if (IS_WINDOWS) {
206
+ return {
207
+ type: 'command',
208
+ command: 'node "%CLAUDE_PROJECT_DIR%/.claude/helpers/statusline.cjs"',
209
+ };
210
+ }
205
211
  // eslint-disable-next-line no-template-curly-in-string
206
212
  const dir = '${CLAUDE_PROJECT_DIR:-.}';
207
213
  return {
@@ -70,17 +70,22 @@ function getVersion() {
70
70
  }
71
71
  } catch { /* ignore */ }
72
72
  }
73
- // 2. Fallback: npm global prefix
73
+ // 2. Fallback: npm global prefix (lib/node_modules on POSIX, node_modules on Windows)
74
74
  try {
75
75
  const { execSync } = require('child_process');
76
76
  const prefix = execSync('npm config get prefix', { encoding: 'utf-8', timeout: 2000 }).trim();
77
- const globalPkgPath = path.join(prefix, 'lib', 'node_modules', 'monomind', 'package.json');
78
- const globalPkgStat = safeStat(globalPkgPath);
79
- if (!globalPkgStat || globalPkgStat.size > 1024 * 1024) throw new Error('too large');
80
- const pkg = JSON.parse(fs.readFileSync(globalPkgPath, 'utf-8'));
81
- if (pkg.version) return \`v\${pkg.version}\`;
77
+ const candidates = [
78
+ path.join(prefix, 'lib', 'node_modules', 'monomind', 'package.json'),
79
+ path.join(prefix, 'node_modules', 'monomind', 'package.json'),
80
+ ];
81
+ for (const globalPkgPath of candidates) {
82
+ const globalPkgStat = safeStat(globalPkgPath);
83
+ if (!globalPkgStat || globalPkgStat.size > 1024 * 1024) continue;
84
+ const pkg = JSON.parse(fs.readFileSync(globalPkgPath, 'utf-8'));
85
+ if (pkg.version) return \`v\${pkg.version}\`;
86
+ }
82
87
  } catch { /* ignore */ }
83
- return 'v1.0.6';
88
+ return 'v?';
84
89
  }
85
90
  const VERSION = getVersion();
86
91
 
@@ -657,7 +657,7 @@ export class MCPServerManager extends EventEmitter {
657
657
  }
658
658
  // Dynamically import the MCP server package
659
659
  // FIX for issue #942: Use proper package import instead of broken relative path
660
- // @ts-expect-error — @monomind/mcp is an optional peer resolved at runtime
660
+ // @ts-ignore — @monomind/mcp is an optional peer resolved at runtime
661
661
  const { createMCPServer } = await import('@monomind/mcp');
662
662
  const logger = {
663
663
  debug: (msg, data) => this.emit('log', { level: 'debug', msg, data }),
@@ -182,10 +182,11 @@ export const daaTools = [
182
182
  try {
183
183
  const bridge = await import('../memory/memory-bridge.js');
184
184
  await bridge.bridgeRecordFeedback({
185
- taskId: `adapt-${agentId}-${agent.metrics.adaptations}`,
186
- success: performanceScore >= 0.5,
187
- quality: performanceScore,
188
- agent: agentId,
185
+ taskType: agentId,
186
+ action: `adapt-${agentId}-${agent.metrics.adaptations}`,
187
+ outcome: performanceScore >= 0.5 ? 'success' : 'failure',
188
+ confidence: performanceScore,
189
+ metadata: { agentId, adaptations: agent.metrics.adaptations },
189
190
  });
190
191
  _storedIn = 'lancedb';
191
192
  }
@@ -354,7 +354,7 @@ export const hooksPatternStore = {
354
354
  let reasoningResult = null;
355
355
  try {
356
356
  const bridge = await import('../memory/memory-bridge.js');
357
- reasoningResult = await bridge.bridgeStorePattern({ pattern, type, confidence, metadata: metadata });
357
+ reasoningResult = await bridge.bridgeStorePattern({ pattern, taskType: type, confidence });
358
358
  }
359
359
  catch {
360
360
  // Bridge not available
@@ -379,20 +379,20 @@ export const hooksPatternStore = {
379
379
  }
380
380
  }
381
381
  const success = reasoningResult?.success || storeResult.success;
382
- const controller = reasoningResult?.controller || (storeResult.success ? 'bridge-store' : 'none');
382
+ const controller = reasoningResult?.success ? 'lancedb' : (storeResult.success ? 'bridge-store' : 'none');
383
383
  return {
384
- patternId: reasoningResult?.patternId || storeResult.id || patternId,
384
+ patternId: reasoningResult?.id || storeResult.id || patternId,
385
385
  pattern,
386
386
  type,
387
387
  confidence,
388
388
  indexed: success,
389
- hnswIndexed: success && (!!storeResult.embedding || controller === 'reasoningBank'),
389
+ hnswIndexed: success && (!!storeResult.embedding || controller === 'lancedb'),
390
390
  embedding: storeResult.embedding,
391
391
  timestamp,
392
392
  controller,
393
- implementation: controller === 'reasoningBank' ? 'reasoning-bank-controller' : (storeResult.success ? 'real-hnsw-indexed' : 'memory-only'),
394
- note: controller === 'reasoningBank'
395
- ? 'Pattern stored via ReasoningBank controller with HNSW indexing'
393
+ implementation: controller === 'lancedb' ? 'lancedb-controller' : (storeResult.success ? 'real-hnsw-indexed' : 'memory-only'),
394
+ note: controller === 'lancedb'
395
+ ? 'Pattern stored via lancedb bridge with HNSW indexing'
396
396
  : (storeResult.success ? 'Pattern stored with vector embedding for semantic search' : (storeResult.error || 'Store function unavailable')),
397
397
  };
398
398
  },
@@ -428,20 +428,22 @@ export const hooksPatternSearch = {
428
428
  // Phase 3: Try ReasoningBank search via bridge first
429
429
  try {
430
430
  const bridge = await import('../memory/memory-bridge.js');
431
- const rbResult = await bridge.bridgeSearchPatterns({ query, topK, minConfidence });
432
- if (rbResult && rbResult.results.length > 0) {
431
+ const rbResult = await bridge.bridgeSearchPatterns({ query, limit: topK });
432
+ if (rbResult && rbResult.patterns.length > 0) {
433
433
  return {
434
434
  query,
435
- results: rbResult.results.map(r => ({
435
+ results: rbResult.patterns
436
+ .filter((r) => r.score >= minConfidence)
437
+ .map((r) => ({
436
438
  patternId: r.id,
437
- pattern: r.content,
439
+ pattern: r.pattern,
438
440
  similarity: r.score,
439
441
  confidence: r.score,
440
442
  namespace,
441
443
  })),
442
444
  searchTimeMs: 0,
443
- backend: rbResult.controller,
444
- note: `Results from ${rbResult.controller} controller`,
445
+ backend: 'lancedb',
446
+ note: 'Results from lancedb bridge',
445
447
  };
446
448
  }
447
449
  }
@@ -91,13 +91,10 @@ export const hooksPostEdit = {
91
91
  try {
92
92
  const bridge = await import('../memory/memory-bridge.js');
93
93
  feedbackResult = await bridge.bridgeRecordFeedback({
94
- taskId: `edit-${filePath}-${Date.now()}`,
95
- success,
96
- quality: success ? 0.85 : 0.3,
97
- agent,
98
- // B1.2: give the SONA embedder real semantics (the edited file) instead of
99
- // the opaque task ID.
100
- task: `edit ${filePath}`,
94
+ taskType: agent ?? 'coder',
95
+ action: `edit ${filePath}`,
96
+ outcome: success ? 'success' : 'failure',
97
+ confidence: success ? 0.85 : 0.3,
101
98
  });
102
99
  }
103
100
  catch {
@@ -111,8 +108,8 @@ export const hooksPostEdit = {
111
108
  learningUpdate: success ? 'pattern_reinforced' : 'pattern_adjusted',
112
109
  feedback: feedbackResult ? {
113
110
  recorded: feedbackResult.success,
114
- controller: feedbackResult.controller,
115
- updates: feedbackResult.updated,
111
+ controller: feedbackResult.success ? 'lancedb' : 'unavailable',
112
+ updates: feedbackResult.success ? 1 : 0,
116
113
  } : { recorded: false, controller: 'unavailable', updates: 0 },
117
114
  };
118
115
  },
@@ -259,51 +256,56 @@ export const hooksRoute = {
259
256
  if (useSemanticRouter) {
260
257
  try {
261
258
  const bridge = await import('../memory/memory-bridge.js');
262
- const memoryRoute = await bridge.bridgeRouteTask({ task, context });
263
- if (memoryRoute && memoryRoute.confidence > 0.5) {
264
- const agents = memoryRoute.agents.length > 0 ? memoryRoute.agents : ['coder', 'researcher'];
265
- const complexity = task.length > 200 ? 'high' : task.length < 50 ? 'low' : 'medium';
266
- const memoryMethod = `memory-${memoryRoute.controller}`;
267
- const memoryConfidence = Math.round(memoryRoute.confidence * 100) / 100;
268
- // Record the route recommendation so post-task can join the actual outcome
269
- const routeId = randomUUID();
270
- await recordRoute(getRouteOutcomesBaseDir(), {
271
- routeId,
272
- ts: Date.now(),
273
- task,
274
- recommendedAgent: agents[0],
275
- routingMethod: memoryMethod,
276
- confidence: memoryConfidence,
277
- learningMode: 'js',
278
- });
279
- return {
280
- routeId,
281
- task,
282
- routing: {
283
- method: memoryMethod,
284
- backend: memoryRoute.controller,
285
- latencyMs: 0,
286
- throughput: 'N/A',
287
- },
288
- matchedPattern: memoryRoute.route,
289
- semanticMatches: [{ pattern: memoryRoute.route, score: memoryRoute.confidence }],
290
- primaryAgent: {
291
- type: agents[0],
292
- confidence: Math.round(memoryRoute.confidence * 100) / 100,
293
- reason: `memory:${memoryRoute.controller}: "${memoryRoute.route}" (${Math.round(memoryRoute.confidence * 100)}%)`,
294
- },
295
- alternativeAgents: agents.slice(1).map((agent, i) => ({
296
- type: agent,
297
- confidence: Math.round((memoryRoute.confidence - (0.1 * (i + 1))) * 100) / 100,
298
- reason: `Alternative from ${memoryRoute.controller}`,
299
- })),
300
- estimatedMetrics: {
301
- successProbability: Math.round(memoryRoute.confidence * 100) / 100,
302
- estimatedDuration: complexity === 'high' ? '2-4 hours' : complexity === 'medium' ? '30-60 min' : '10-30 min',
303
- complexity,
304
- },
305
- swarmRecommendation: agents.length > 2 ? { topology: 'hierarchical', agents, coordination: 'queen-led' } : null,
306
- };
259
+ const memoryRoute = await bridge.bridgeRouteTask({ task });
260
+ if (memoryRoute && memoryRoute.routes && memoryRoute.routes.length > 0) {
261
+ const topRoute = memoryRoute.routes[0];
262
+ const routeConfidence = topRoute.confidence ?? 0;
263
+ if (routeConfidence > 0.5) {
264
+ const agents = memoryRoute.routes.map((r) => r.agentType);
265
+ const complexity = task.length > 200 ? 'high' : task.length < 50 ? 'low' : 'medium';
266
+ const memoryMethod = 'memory-lancedb';
267
+ const memoryConfidence = Math.round(routeConfidence * 100) / 100;
268
+ const matchedPattern = topRoute.pattern ?? task.slice(0, 60);
269
+ // Record the route recommendation so post-task can join the actual outcome
270
+ const routeId = randomUUID();
271
+ await recordRoute(getRouteOutcomesBaseDir(), {
272
+ routeId,
273
+ ts: Date.now(),
274
+ task,
275
+ recommendedAgent: agents[0],
276
+ routingMethod: memoryMethod,
277
+ confidence: memoryConfidence,
278
+ learningMode: 'js',
279
+ });
280
+ return {
281
+ routeId,
282
+ task,
283
+ routing: {
284
+ method: memoryMethod,
285
+ backend: 'lancedb',
286
+ latencyMs: 0,
287
+ throughput: 'N/A',
288
+ },
289
+ matchedPattern,
290
+ semanticMatches: [{ pattern: matchedPattern, score: routeConfidence }],
291
+ primaryAgent: {
292
+ type: agents[0],
293
+ confidence: memoryConfidence,
294
+ reason: `memory:lancedb: "${matchedPattern}" (${Math.round(routeConfidence * 100)}%)`,
295
+ },
296
+ alternativeAgents: agents.slice(1).map((agent, i) => ({
297
+ type: agent,
298
+ confidence: Math.round((routeConfidence - (0.1 * (i + 1))) * 100) / 100,
299
+ reason: 'Alternative from lancedb',
300
+ })),
301
+ estimatedMetrics: {
302
+ successProbability: memoryConfidence,
303
+ estimatedDuration: complexity === 'high' ? '2-4 hours' : complexity === 'medium' ? '30-60 min' : '10-30 min',
304
+ complexity,
305
+ },
306
+ swarmRecommendation: agents.length > 2 ? { topology: 'hierarchical', agents, coordination: 'queen-led' } : null,
307
+ };
308
+ }
307
309
  }
308
310
  }
309
311
  catch {
@@ -682,17 +684,11 @@ export const hooksPostTask = {
682
684
  try {
683
685
  const bridge = await import('../memory/memory-bridge.js');
684
686
  feedbackResult = await bridge.bridgeRecordFeedback({
685
- taskId,
686
- success,
687
- quality,
688
- agent,
689
- // B1.2: thread the real task description into the SONA trajectory so the
690
- // embedder encodes meaning, not the opaque task ID.
691
- task: cappedPostTask || undefined,
692
- // B1.3: only feed the SONA LoRA update when the outcome is actually known.
693
- outcomeKnown,
694
- duration: params.duration || undefined,
695
- patterns: params.patterns || undefined,
687
+ taskType: agent ?? 'task',
688
+ action: cappedPostTask?.slice(0, 80) ?? taskId,
689
+ outcome: success ? 'success' : (outcomeKnown ? 'failure' : 'partial'),
690
+ confidence: quality,
691
+ metadata: { taskId, duration: params.duration || undefined, patterns: params.patterns || undefined },
696
692
  });
697
693
  }
698
694
  catch {
@@ -705,7 +701,7 @@ export const hooksPostTask = {
705
701
  sourceId: taskId,
706
702
  targetId: `outcome-${taskId}`,
707
703
  relation: success ? 'succeeded' : 'failed',
708
- weight: quality,
704
+ strength: quality,
709
705
  });
710
706
  }
711
707
  catch {
@@ -830,17 +826,17 @@ export const hooksPostTask = {
830
826
  successSource,
831
827
  duration,
832
828
  learningUpdates: {
833
- patternsUpdated: feedbackResult?.updated || (success ? 2 : 1),
829
+ patternsUpdated: feedbackResult?.success ? (success ? 2 : 1) : 0,
834
830
  newPatterns: success ? 1 : 0,
835
831
  trajectoryId: `traj-${Date.now()}`,
836
- controller: feedbackResult?.controller || 'none',
832
+ controller: feedbackResult?.success ? 'lancedb' : 'none',
837
833
  outcomePersisted,
838
834
  },
839
835
  quality,
840
836
  feedback: feedbackResult ? {
841
837
  recorded: feedbackResult.success,
842
- controller: feedbackResult.controller,
843
- updates: feedbackResult.updated,
838
+ controller: feedbackResult.success ? 'lancedb' : 'unavailable',
839
+ updates: feedbackResult.success ? 1 : 0,
844
840
  } : { recorded: false, controller: 'unavailable', updates: 0 },
845
841
  marReflection,
846
842
  timestamp: new Date().toISOString(),
@@ -1261,12 +1257,12 @@ export const hooksSessionStart = {
1261
1257
  const bridge = await import('../memory/memory-bridge.js');
1262
1258
  const result = await bridge.bridgeSessionStart({
1263
1259
  sessionId,
1264
- context: restoreLatest ? 'restore previous session patterns' : 'new session',
1260
+ metadata: { context: restoreLatest ? 'restore previous session patterns' : 'new session' },
1265
1261
  });
1266
1262
  if (result) {
1267
1263
  sessionMemory = {
1268
- controller: result.controller,
1269
- restoredPatterns: result.restoredPatterns,
1264
+ controller: result.success ? 'lancedb' : 'none',
1265
+ restoredPatterns: 0,
1270
1266
  };
1271
1267
  }
1272
1268
  }
@@ -1351,13 +1347,12 @@ export const hooksSessionEnd = {
1351
1347
  const result = await bridge.bridgeSessionEnd({
1352
1348
  sessionId,
1353
1349
  summary: saveState ? 'Session ended with state saved' : 'Session ended',
1354
- tasksCompleted: taskCount,
1355
- patternsLearned: patternCount,
1350
+ metrics: { tasksCompleted: taskCount, patternsLearned: patternCount },
1356
1351
  });
1357
1352
  if (result) {
1358
1353
  sessionPersistence = {
1359
- controller: result.controller,
1360
- persisted: result.persisted,
1354
+ controller: result.success ? 'lancedb' : 'none',
1355
+ persisted: result.success,
1361
1356
  };
1362
1357
  }
1363
1358
  }
@@ -94,9 +94,9 @@ export const memoryControllers = {
94
94
  return { available: false, controllers: [], error: 'Memory bridge not available — @monomind/memory not installed or missing controller-registry. Use memory_store/memory_search tools instead.' };
95
95
  return {
96
96
  available: true,
97
- controllers,
98
- total: controllers.length,
99
- active: controllers.filter((c) => c.enabled).length,
97
+ controllers: controllers.controllers,
98
+ total: controllers.controllers.length,
99
+ active: controllers.active.length,
100
100
  };
101
101
  }
102
102
  catch (error) {
@@ -125,7 +125,7 @@ export const memoryPatternStore = {
125
125
  const bridge = await getBridge();
126
126
  const result = await bridge.bridgeStorePattern({
127
127
  pattern,
128
- type: validateString(params.type, 'type', 200) ?? 'general',
128
+ taskType: validateString(params.type, 'type', 200) ?? 'general',
129
129
  confidence: validateScore(params.confidence, 0.8),
130
130
  });
131
131
  return result ?? { success: false, error: 'Memory bridge not available. Use memory_store/memory_search instead.' };
@@ -154,12 +154,17 @@ export const memoryPatternSearch = {
154
154
  if (!query)
155
155
  return { results: [], error: 'query is required (non-empty string, max 10KB)' };
156
156
  const bridge = await getBridge();
157
+ const minConfidence = validateScore(params.minConfidence, 0.3);
157
158
  const result = await bridge.bridgeSearchPatterns({
158
159
  query,
159
- topK: validatePositiveInt(params.topK, 5, MAX_TOP_K),
160
- minConfidence: validateScore(params.minConfidence, 0.3),
160
+ limit: validatePositiveInt(params.topK, 5, MAX_TOP_K),
161
161
  });
162
- return result ?? { results: [], controller: 'unavailable' };
162
+ if (!result)
163
+ return { results: [], controller: 'unavailable' };
164
+ return {
165
+ ...result,
166
+ patterns: result.patterns.filter((p) => p.score >= minConfidence),
167
+ };
163
168
  }
164
169
  catch (error) {
165
170
  return { results: [], error: sanitizeError(error) };
@@ -187,10 +192,11 @@ export const memoryFeedback = {
187
192
  return { success: false, error: 'taskId is required (non-empty string, max 500 chars)' };
188
193
  const bridge = await getBridge();
189
194
  const result = await bridge.bridgeRecordFeedback({
190
- taskId,
191
- success: params.success === true,
192
- quality: validateScore(params.quality, 0.85),
193
- agent: validateString(params.agent, 'agent', 200) ?? undefined,
195
+ taskType: validateString(params.agent, 'agent', 200) ?? 'task',
196
+ action: taskId,
197
+ outcome: params.success === true ? 'success' : 'failure',
198
+ confidence: validateScore(params.quality, 0.85),
199
+ metadata: { taskId },
194
200
  });
195
201
  return result ?? { success: false, error: 'Memory bridge not available. Use memory_store/memory_search instead.' };
196
202
  }
@@ -229,7 +235,7 @@ export const memoryCausalEdge = {
229
235
  sourceId,
230
236
  targetId,
231
237
  relation,
232
- weight: typeof params.weight === 'number' ? validateScore(params.weight, 0.5) : undefined,
238
+ strength: typeof params.weight === 'number' ? validateScore(params.weight, 0.5) : undefined,
233
239
  });
234
240
  return result ?? { success: false, error: 'Memory bridge not available. Use memory_store/memory_search instead.' };
235
241
  }
@@ -256,10 +262,7 @@ export const memoryRoute = {
256
262
  if (!task)
257
263
  return { route: 'general', confidence: 0.5, agents: ['coder'], controller: 'error', error: 'task is required (non-empty string)' };
258
264
  const bridge = await getBridge();
259
- const result = await bridge.bridgeRouteTask({
260
- task,
261
- context: validateString(params.context, 'context', 10_000) ?? undefined,
262
- });
265
+ const result = await bridge.bridgeRouteTask({ task });
263
266
  return result ?? { route: 'general', confidence: 0.5, agents: ['coder'], controller: 'fallback' };
264
267
  }
265
268
  catch (error) {
@@ -287,7 +290,7 @@ export const memorySessionStart = {
287
290
  const bridge = await getBridge();
288
291
  const result = await bridge.bridgeSessionStart({
289
292
  sessionId,
290
- context: validateString(params.context, 'context', 10_000) ?? undefined,
293
+ metadata: { context: validateString(params.context, 'context', 10_000) ?? undefined },
291
294
  });
292
295
  return result ?? { success: false, error: 'Memory bridge not available. Use memory_store/memory_search instead.' };
293
296
  }
@@ -318,7 +321,7 @@ export const memorySessionEnd = {
318
321
  const result = await bridge.bridgeSessionEnd({
319
322
  sessionId,
320
323
  summary: validateString(params.summary, 'summary', 50_000) ?? undefined,
321
- tasksCompleted: validatePositiveInt(params.tasksCompleted, 0, 10_000),
324
+ metrics: { tasksCompleted: validatePositiveInt(params.tasksCompleted, 0, 10_000) },
322
325
  });
323
326
  return result ?? { success: false, error: 'Memory bridge not available. Use memory_store/memory_search instead.' };
324
327
  }
@@ -4,8 +4,8 @@
4
4
  * V2 Compatibility - Neural network and ML tools
5
5
  *
6
6
  * ✅ HYBRID Implementation:
7
- * - Uses agentic-flow/reasoningbank for REAL ML embeddings when available
8
- * - Falls back to deterministic hash-based embeddings when ML model not installed
7
+ * - Uses monovector ONNX embeddings when available
8
+ * - Falls back to deterministic hash-based embeddings otherwise
9
9
  * - Pattern storage and search with cosine similarity (real math in all tiers)
10
10
  * - Training stores patterns as searchable embeddings (not simulated)
11
11
  *
@@ -4,8 +4,8 @@
4
4
  * V2 Compatibility - Neural network and ML tools
5
5
  *
6
6
  * ✅ HYBRID Implementation:
7
- * - Uses agentic-flow/reasoningbank for REAL ML embeddings when available
8
- * - Falls back to deterministic hash-based embeddings when ML model not installed
7
+ * - Uses monovector ONNX embeddings when available
8
+ * - Falls back to deterministic hash-based embeddings otherwise
9
9
  * - Pattern storage and search with cosine similarity (real math in all tiers)
10
10
  * - Training stores patterns as searchable embeddings (not simulated)
11
11
  *
@@ -16,19 +16,28 @@ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, statSyn
16
16
  import { join } from 'node:path';
17
17
  const MAX_NEURAL_STORE_BYTES = 50 * 1024 * 1024; // 50 MB
18
18
  const NEURAL_RESERVED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
19
- // Try to import real embeddings agentic-flow v1 ReasoningBank when available,
20
- // otherwise the deterministic hash fallback below.
19
+ // Embeddings via monovector ONNX when available; deterministic hash fallback otherwise.
21
20
  let realEmbeddings = null;
22
21
  let embeddingServiceName = 'none';
23
22
  try {
24
- const rb = await import('agentic-flow/reasoningbank').catch(() => null);
25
- if (rb?.computeEmbedding) {
26
- realEmbeddings = { embed: async (text) => Array.from(await rb.computeEmbedding(text)) };
27
- embeddingServiceName = 'agentic-flow/reasoningbank';
23
+ const monovector = await import('monovector').catch(() => null);
24
+ if (monovector?.getOptimizedOnnxEmbedder) {
25
+ await monovector.initOnnxEmbedder?.();
26
+ const onnxEmb = monovector.getOptimizedOnnxEmbedder();
27
+ if (onnxEmb?.embed) {
28
+ const probe = await onnxEmb.embed('test');
29
+ const hasNonZero = ArrayBuffer.isView(probe) || Array.isArray(probe)
30
+ ? [...probe].some((v) => v !== 0)
31
+ : false;
32
+ if (probe && probe.length > 0 && hasNonZero) {
33
+ realEmbeddings = { embed: async (text) => Array.from(await onnxEmb.embed(text)) };
34
+ embeddingServiceName = 'monovector/onnx';
35
+ }
36
+ }
28
37
  }
29
38
  }
30
39
  catch {
31
- // No embedding provider available, will use fallback
40
+ // No ONNX embedding provider available, will use hash fallback
32
41
  }
33
42
  // Storage paths
34
43
  const STORAGE_DIR = '.monomind';
@@ -76,25 +76,6 @@ export async function loadEmbeddingModel(options) {
76
76
  loadTime: Date.now() - startTime
77
77
  };
78
78
  }
79
- // Fallback: Check for agentic-flow ReasoningBank embeddings (v1)
80
- const reasoningBank = await import('agentic-flow/reasoningbank').catch(() => null);
81
- if (reasoningBank?.computeEmbedding) {
82
- if (verbose) {
83
- console.log('Loading agentic-flow ReasoningBank embedding model...');
84
- }
85
- embeddingModelState = {
86
- loaded: true,
87
- model: { embed: reasoningBank.computeEmbedding },
88
- tokenizer: null,
89
- dimensions: 768
90
- };
91
- return {
92
- success: true,
93
- dimensions: 768,
94
- modelName: 'agentic-flow/reasoningbank',
95
- loadTime: Date.now() - startTime
96
- };
97
- }
98
79
  // Fallback: Check for monovector ONNX embedder (bundled MiniLM-L6-v2 since v0.2.15)
99
80
  // v0.2.16: LoRA B=0 fix makes AdaptiveEmbedder safe (identity when untrained)
100
81
  // Note: isReady() returns false until first embed() call (lazy init), so we
@@ -108,7 +89,8 @@ export async function loadEmbeddingModel(options) {
108
89
  if (onnxEmb?.embed) {
109
90
  // Probe embed to trigger lazy ONNX init and verify it works
110
91
  const probe = await onnxEmb.embed('test');
111
- if (probe && probe.length > 0 && (Array.isArray(probe) ? probe.some((v) => v !== 0) : true)) {
92
+ const probeArr = ArrayBuffer.isView(probe) ? Array.from(probe) : (Array.isArray(probe) ? probe : []);
93
+ if (probe && probe.length > 0 && probeArr.some((v) => v !== 0)) {
112
94
  if (verbose) {
113
95
  console.log(`Loading monovector ONNX embedder (all-MiniLM-L6-v2, ${probe.length}d)...`);
114
96
  }
@@ -131,25 +113,6 @@ export async function loadEmbeddingModel(options) {
131
113
  // monovector ONNX init failed, continue to next fallback
132
114
  }
133
115
  }
134
- // Legacy fallback: Check for agentic-flow core embeddings
135
- const agenticFlow = await import('agentic-flow').catch(() => null);
136
- if (agenticFlow && agenticFlow.embeddings) {
137
- if (verbose) {
138
- console.log('Loading agentic-flow embedding model...');
139
- }
140
- embeddingModelState = {
141
- loaded: true,
142
- model: agenticFlow.embeddings,
143
- tokenizer: null,
144
- dimensions: 768
145
- };
146
- return {
147
- success: true,
148
- dimensions: 768,
149
- modelName: 'agentic-flow',
150
- loadTime: Date.now() - startTime
151
- };
152
- }
153
116
  // No ONNX model available - use fallback
154
117
  embeddingModelState = {
155
118
  loaded: true,
@@ -85,13 +85,6 @@ function saveHNSWMetadata() {
85
85
  * Add entry to HNSW index (with automatic persistence)
86
86
  */
87
87
  export async function addToHNSWIndex(id, embedding, entry) {
88
- // ADR-053: Try LanceDB memory bridge first
89
- const bridge = await getBridge();
90
- if (bridge) {
91
- const bridgeResult = await bridge.bridgeAddToHNSW(id, embedding, entry);
92
- if (bridgeResult === true)
93
- return true;
94
- }
95
88
  const index = await getHNSWIndex({ dimensions: embedding.length });
96
89
  if (!index)
97
90
  return false;
@@ -115,13 +108,6 @@ export async function addToHNSWIndex(id, embedding, entry) {
115
108
  * Returns results sorted by similarity (highest first)
116
109
  */
117
110
  export async function searchHNSWIndex(queryEmbedding, options) {
118
- // ADR-053: Try LanceDB memory bridge first
119
- const bridge = await getBridge();
120
- if (bridge) {
121
- const bridgeResult = await bridge.bridgeSearchHNSW(queryEmbedding, options);
122
- if (bridgeResult)
123
- return bridgeResult;
124
- }
125
111
  const index = await getHNSWIndex({ dimensions: queryEmbedding.length });
126
112
  if (!index)
127
113
  return null;
@@ -320,7 +320,7 @@ export async function deleteEntry(options) {
320
320
  if (bridgeResult.deleted) {
321
321
  rebuildSearchIndex();
322
322
  }
323
- return bridgeResult;
323
+ return { ...bridgeResult, key: options.key, namespace: options.namespace ?? 'default', remainingEntries: 0 };
324
324
  }
325
325
  }
326
326
  // Fallback: raw sql.js
@@ -65,8 +65,6 @@ INSERT OR REPLACE INTO metadata (key, value) VALUES
65
65
 
66
66
  -- Create default vector index configuration
67
67
  -- Dimensions match BRIDGE_EMBEDDING_DIMS=384 (Xenova/all-MiniLM-L6-v2).
68
- -- 768 was a legacy value from the agentic-flow era; 384 is the actual
69
- -- embedding size used by memory-bridge.ts and LanceDB.
70
68
  INSERT OR IGNORE INTO vector_indexes (id, name, dimensions) VALUES
71
69
  ('default', 'default', 384),
72
70
  ('patterns', 'patterns', 384);
@@ -166,7 +166,16 @@ export async function listEntries(options) {
166
166
  if (bridge) {
167
167
  const bridgeResult = await bridge.bridgeListEntries(options);
168
168
  if (bridgeResult)
169
- return bridgeResult;
169
+ return {
170
+ success: bridgeResult.success,
171
+ total: bridgeResult.total,
172
+ error: bridgeResult.error,
173
+ entries: bridgeResult.entries.map((e) => ({
174
+ id: e.id, key: e.key, namespace: e.namespace,
175
+ size: typeof e.content === 'string' ? e.content.length : 0,
176
+ accessCount: e.accessCount, createdAt: e.createdAt, updatedAt: e.updatedAt, hasEmbedding: e.hasEmbedding,
177
+ })),
178
+ };
170
179
  }
171
180
  // Fallback: raw sql.js
172
181
  const { namespace, limit = 20, offset = 0, dbPath: customPath } = options;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "1.16.2",
3
+ "version": "1.16.4",
4
4
  "type": "module",
5
5
  "description": "Monomind 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",
@@ -94,7 +94,6 @@
94
94
  "optionalDependencies": {
95
95
  "sql.js": "^1.14.1",
96
96
  "@monoes/memory": "^1.0.0",
97
- "agentic-flow": "^3.0.0-alpha.1",
98
97
  "@huggingface/transformers": "^3.8.1",
99
98
  "monofence-ai": "*",
100
99
  "@monomind/hooks": "*",