monomind 1.11.5 → 1.11.6

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.11.5",
3
+ "version": "1.11.6",
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",
@@ -32,46 +32,18 @@ const pretrainCommand = {
32
32
  const outputFormat = ctx.flags.output || 'text';
33
33
  const saveFile = ctx.flags.save;
34
34
  const verbose = ctx.flags.verbose === true;
35
- try {
36
- // Dynamically import benchmark suite
37
- const { runPretrainBenchmarkSuite } = await import('../benchmarks/pretrain/index.js');
38
- const results = await runPretrainBenchmarkSuite({
39
- iterations,
40
- warmupIterations: warmup,
41
- verbose,
42
- });
43
- // Output as JSON if requested
44
- if (outputFormat === 'json') {
45
- output.writeln(JSON.stringify(results, null, 2));
46
- }
47
- // Save to file if requested
48
- if (saveFile) {
49
- const resultsDir = join(process.cwd(), '.monomind', 'benchmarks');
50
- if (!existsSync(resultsDir)) {
51
- mkdirSync(resultsDir, { recursive: true });
52
- }
53
- const savePath = saveFile.startsWith('/') ? saveFile : join(resultsDir, saveFile);
54
- const saveTmp = savePath + '.tmp';
55
- writeFileSync(saveTmp, JSON.stringify(results, null, 2));
56
- renameSync(saveTmp, savePath);
57
- output.writeln(output.success(`Results saved to ${savePath}`));
58
- }
59
- const allPassed = results.results.every(r => r.targetMet);
60
- return {
61
- success: true,
62
- message: allPassed
63
- ? 'All benchmark targets met!'
64
- : `${results.results.filter(r => r.targetMet).length}/${results.results.length} targets met`,
65
- };
66
- }
67
- catch (err) {
68
- const errorMsg = err instanceof Error ? err.message : String(err);
69
- output.writeln(output.error(`Benchmark failed: ${errorMsg}`));
70
- return {
71
- success: false,
72
- message: `Benchmark failed: ${errorMsg}`,
73
- };
74
- }
35
+ void iterations;
36
+ void warmup;
37
+ void verbose;
38
+ void outputFormat;
39
+ void saveFile;
40
+ output.writeln();
41
+ output.writeln(output.bold('Pattern-Learning Benchmark'));
42
+ output.writeln(output.dim('─'.repeat(50)));
43
+ output.writeln(output.dim(' The native SONA/EWC++/MoE pre-training benchmark was removed in the lean build.'));
44
+ output.writeln(output.dim(' Use "monomind benchmark neural" to benchmark the active pure-JS intelligence layer.'));
45
+ output.writeln();
46
+ return { success: true };
75
47
  },
76
48
  };
77
49
  // ============================================================================
@@ -79,7 +51,7 @@ const pretrainCommand = {
79
51
  // ============================================================================
80
52
  const neuralCommand = {
81
53
  name: 'neural',
82
- description: 'Benchmark neural operations (embeddings, WASM, Flash Attention)',
54
+ description: 'Benchmark neural operations (embeddings, HNSW, cosine similarity)',
83
55
  options: [
84
56
  { name: 'iterations', short: 'i', type: 'number', description: 'Benchmark iterations', default: '100' },
85
57
  { name: 'dimension', short: 'd', type: 'number', description: 'Embedding dimension', default: '384' },
@@ -182,8 +154,8 @@ const neuralCommand = {
182
154
  target: 5.0,
183
155
  met: cosineMean <= 5.0,
184
156
  });
185
- // 3. Flash Attention Search (if available)
186
- spinner.setText('Benchmarking flash attention search...');
157
+ // 3. Softmax-weighted top-K search (pure-JS)
158
+ spinner.setText('Benchmarking softmax top-K search...');
187
159
  const flashTimes = [];
188
160
  try {
189
161
  const memory = await import('../memory/memory-initializer.js');
@@ -196,13 +168,13 @@ const neuralCommand = {
196
168
  }
197
169
  }
198
170
  catch {
199
- // Flash attention not available
171
+ // not available
200
172
  }
201
173
  if (flashTimes.length > 0) {
202
174
  const flashMean = flashTimes.reduce((a, b) => a + b, 0) / flashTimes.length;
203
175
  const flashSorted = [...flashTimes].sort((a, b) => a - b);
204
176
  results.push({
205
- name: 'Flash Attention Search',
177
+ name: 'Softmax Top-K Search',
206
178
  mean: flashMean,
207
179
  p95: percentile(flashSorted, 95),
208
180
  p99: percentile(flashSorted, 99),
@@ -11,7 +11,7 @@
11
11
  * github.com/nokhodian/monomind
12
12
  */
13
13
  import { output } from '../output.js';
14
- import { createKeywordRouter, isMonovectorAvailable, } from '../monovector/index.js';
14
+ import { createKeywordRouter, } from '../monovector/index.js';
15
15
  /**
16
16
  * Available agent types for routing
17
17
  */
@@ -86,7 +86,7 @@ const routeTaskCommand = {
86
86
  ],
87
87
  examples: [
88
88
  { command: 'monomind route task "implement authentication"', description: 'Route task to best agent' },
89
- { command: 'monomind route task "write unit tests" --q-learning', description: 'Use Q-Learning routing' },
89
+ { command: 'monomind route task "write unit tests" --q-learning', description: 'Use keyword-based routing' },
90
90
  { command: 'monomind route task "review code" --agent reviewer', description: 'Force specific agent' },
91
91
  ],
92
92
  action: async (ctx) => {
@@ -103,7 +103,7 @@ const routeTaskCommand = {
103
103
  spinner.start();
104
104
  try {
105
105
  if (forceAgent) {
106
- // Bypass Q-Learning, use specified agent
106
+ // Use specified agent directly
107
107
  const agent = getAgentType(forceAgent) ||
108
108
  AGENT_TYPES.find(a => a.name.toLowerCase() === forceAgent.toLowerCase());
109
109
  if (!agent) {
@@ -134,7 +134,7 @@ const routeTaskCommand = {
134
134
  }
135
135
  return { success: true, data: { agentId: agent.id, agentName: agent.name } };
136
136
  }
137
- // Use Q-Learning routing
137
+ // Use keyword-based routing
138
138
  const router = await getRouter();
139
139
  const result = await router.route(taskDescription, useExploration);
140
140
  const agent = getAgentType(result.route) || AGENT_TYPES[0];
@@ -177,7 +177,7 @@ const routeTaskCommand = {
177
177
  ``,
178
178
  `Description: ${agent.description}`,
179
179
  `Capabilities: ${capabilities.join(', ')}`,
180
- ].join('\n'), 'Q-Learning Routing');
180
+ ].join('\n'), 'Keyword Routing');
181
181
  if (alternatives.length > 0) {
182
182
  output.writeln();
183
183
  output.writeln(output.bold('Alternatives:'));
@@ -263,7 +263,7 @@ const listAgentsCommand = {
263
263
  // ============================================================================
264
264
  const statsCommand = {
265
265
  name: 'stats',
266
- description: 'Show Q-Learning router statistics',
266
+ description: 'Show keyword router statistics',
267
267
  options: [
268
268
  {
269
269
  name: 'json',
@@ -281,18 +281,12 @@ const statsCommand = {
281
281
  try {
282
282
  const router = await getRouter();
283
283
  const stats = router.getStats();
284
- const monovectorAvailable = await isMonovectorAvailable();
285
- const monovectorStatus = {
286
- available: monovectorAvailable,
287
- wasmAccelerated: stats.useNative === 1,
288
- backend: stats.useNative === 1 ? 'monovector-native' : 'fallback',
289
- };
290
284
  if (jsonOutput) {
291
- output.printJson({ stats, monovector: monovectorStatus });
285
+ output.printJson({ stats, backend: 'keyword-routing-js' });
292
286
  }
293
287
  else {
294
288
  output.writeln();
295
- output.writeln(output.bold('Q-Learning Router Statistics'));
289
+ output.writeln(output.bold('Keyword Router Statistics'));
296
290
  output.writeln();
297
291
  output.printTable({
298
292
  columns: [
@@ -301,22 +295,13 @@ const statsCommand = {
301
295
  ],
302
296
  data: [
303
297
  { metric: 'Update Count', value: String(stats.updateCount) },
304
- { metric: 'Q-Table Size', value: String(stats.qTableSize) },
298
+ { metric: 'Pattern Count', value: String(stats.qTableSize) },
305
299
  { metric: 'Step Count', value: String(stats.stepCount) },
306
- { metric: 'Epsilon', value: stats.epsilon.toFixed(4) },
307
- { metric: 'Avg TD Error', value: stats.avgTDError.toFixed(4) },
308
- { metric: 'Native Backend', value: stats.useNative === 1 ? 'Yes' : 'No' },
300
+ { metric: 'Backend', value: 'keyword-routing (JS)' },
309
301
  ],
310
302
  });
311
- output.writeln();
312
- output.writeln(output.bold('MonoVector Status'));
313
- output.printList([
314
- `Available: ${monovectorStatus.available ? output.success('Yes') : output.warning('No (using fallback)')}`,
315
- `WASM Accelerated: ${monovectorStatus.wasmAccelerated ? output.success('Yes') : 'No'}`,
316
- `Backend: ${monovectorStatus.backend}`,
317
- ]);
318
303
  }
319
- return { success: true, data: { stats, monovector: monovectorStatus } };
304
+ return { success: true, data: { stats } };
320
305
  }
321
306
  catch (error) {
322
307
  output.printError(error instanceof Error ? error.message : String(error));
@@ -406,7 +391,7 @@ const feedbackCommand = {
406
391
  // ============================================================================
407
392
  const resetCommand = {
408
393
  name: 'reset',
409
- description: 'Reset the Q-Learning router state',
394
+ description: 'Reset the keyword router state',
410
395
  options: [
411
396
  {
412
397
  name: 'force',
@@ -430,7 +415,7 @@ const resetCommand = {
430
415
  try {
431
416
  const router = await getRouter();
432
417
  router.reset();
433
- output.printSuccess('Q-Learning router state has been reset');
418
+ output.printSuccess('Keyword router state has been reset');
434
419
  return { success: true };
435
420
  }
436
421
  catch (error) {
@@ -854,7 +839,7 @@ const semanticRouteCommand = {
854
839
  // ============================================================================
855
840
  export const routeCommand = {
856
841
  name: 'route',
857
- description: 'Intelligent task-to-agent routing using Q-Learning',
842
+ description: 'Intelligent task-to-agent routing using keyword matching',
858
843
  subcommands: [
859
844
  routeTaskCommand,
860
845
  semanticRouteCommand,
@@ -870,7 +855,7 @@ export const routeCommand = {
870
855
  {
871
856
  name: 'q-learning',
872
857
  short: 'q',
873
- description: 'Use Q-Learning for agent selection',
858
+ description: 'Use keyword-based agent selection',
874
859
  type: 'boolean',
875
860
  default: true,
876
861
  },
@@ -883,7 +868,7 @@ export const routeCommand = {
883
868
  ],
884
869
  examples: [
885
870
  { command: 'monomind route "implement feature"', description: 'Route task to best agent' },
886
- { command: 'monomind route "write tests" --q-learning', description: 'Use Q-Learning routing' },
871
+ { command: 'monomind route "write tests" --q-learning', description: 'Use keyword-based routing' },
887
872
  { command: 'monomind route --agent coder "fix bug"', description: 'Force specific agent' },
888
873
  { command: 'monomind route list-agents', description: 'List available agents' },
889
874
  { command: 'monomind route stats', description: 'Show routing statistics' },
@@ -923,12 +908,10 @@ export const routeCommand = {
923
908
  'Provides confidence scores and alternatives',
924
909
  ]);
925
910
  output.writeln();
926
- // Show quick status
927
- const monovectorAvailable = await isMonovectorAvailable();
928
911
  output.writeln(output.bold('Backend Status:'));
929
912
  output.printList([
930
- `MonoVector: ${monovectorAvailable ? output.success('Available') : output.warning('Fallback mode')}`,
931
- `Backend: ${monovectorAvailable ? 'monovector-native' : 'JavaScript fallback'}`,
913
+ `Routing: ${output.success('keyword-based (JS)')}`,
914
+ `Learning: trajectory recording + outcome correlation`,
932
915
  ]);
933
916
  output.writeln();
934
917
  output.writeln(output.dim('Run "monomind route <subcommand> --help" for more info'));
@@ -5,7 +5,6 @@
5
5
  import { mkdirSync, writeFileSync, renameSync, existsSync, readFileSync, statSync, unlinkSync, readdirSync } from 'fs';
6
6
  import { dirname, join, resolve, sep } from 'path';
7
7
  import { getProjectCwd } from './types.js';
8
- import { getCapabilities } from '../monovector/capabilities.js';
9
8
  import { randomUUID } from 'node:crypto';
10
9
  import { recordRoute, joinOutcome, joinLatestUnresolved } from '../monovector/route-outcomes.js';
11
10
  import { recordCommand, deriveRecentSuccess } from '../monovector/command-outcomes.js';
@@ -706,8 +705,6 @@ export const hooksRoute = {
706
705
  const agentdbConfidence = Math.round(agentdbRoute.confidence * 100) / 100;
707
706
  // Record the route recommendation so post-task can join the actual outcome
708
707
  const routeId = randomUUID();
709
- const caps = await getCapabilities();
710
- const learningMode = (caps.sona || caps.router === 'native' || caps.attention) ? 'native' : 'js';
711
708
  await recordRoute(getRouteOutcomesBaseDir(), {
712
709
  routeId,
713
710
  ts: Date.now(),
@@ -715,7 +712,7 @@ export const hooksRoute = {
715
712
  recommendedAgent: agents[0],
716
713
  routingMethod: agentdbMethod,
717
714
  confidence: agentdbConfidence,
718
- learningMode,
715
+ learningMode: 'js',
719
716
  });
720
717
  return {
721
718
  routeId,
@@ -797,8 +794,6 @@ export const hooksRoute = {
797
794
  const primaryConfidence = Math.round(confidence * 100) / 100;
798
795
  // Record the route recommendation so post-task can join the actual outcome
799
796
  const routeId = randomUUID();
800
- const caps = await getCapabilities();
801
- const learningMode = (caps.sona || caps.router === 'native' || caps.attention) ? 'native' : 'js';
802
797
  await recordRoute(getRouteOutcomesBaseDir(), {
803
798
  routeId,
804
799
  ts: Date.now(),
@@ -806,7 +801,7 @@ export const hooksRoute = {
806
801
  recommendedAgent: agents[0],
807
802
  routingMethod,
808
803
  confidence: primaryConfidence,
809
- learningMode,
804
+ learningMode: 'js',
810
805
  });
811
806
  return {
812
807
  routeId,
@@ -18,7 +18,7 @@ import { homedir } from 'os';
18
18
  import { execSync } from 'child_process';
19
19
  import { createServer } from 'http';
20
20
  import { performance } from 'perf_hooks';
21
- import { openDb, closeDb, ftsSearch, getNode, getNodesForFile, getEdgesForSource, getEdgesForTarget, countNodes, countEdges, snapshotFromDb, toHtml, MonographError, } from '@monoes/monograph';
21
+ import { openDb, closeDb, ftsSearch, getNode, getNodesForFile, getEdgesForSource, getEdgesForTarget, countNodes, countEdges, snapshotFromDb, toHtml, } from '@monoes/monograph';
22
22
  // ─── Tier 1: Fully implementable from primitives ───────────────────────────────
23
23
  // 1. hybridQuery
24
24
  // BM25-only at monograph@1.1.0 (no vector storage). score = -rank (descending, .toFixed-safe).
@@ -878,7 +878,7 @@ export async function installSkillsForPlatform(repoPath, communities, opts) {
878
878
  }
879
879
  // 18. runEmbed — embeddings unsupported at 1.1.0; throws so handler catches gracefully
880
880
  export async function runEmbed(_db, _opts) {
881
- throw new MonographError('Embeddings are not supported in @monoes/monograph@1.1.0 — upgrade to a version with native vector storage, or install @huggingface/transformers and a compat build.');
881
+ throw new Error('Embeddings are not supported in @monoes/monograph@1.1.0 — no vector storage in this schema version.');
882
882
  }
883
883
  // ─── Groups (Tier 2) ──────────────────────────────────────────────────────────
884
884
  // Helper: read group config (groups.json or group.yaml)
@@ -416,8 +416,7 @@ export declare function bridgeContextSynthesize(params: {
416
416
  }): Promise<any>;
417
417
  /**
418
418
  * Route via SemanticRouter.
419
- * Available since agentdb 3.0.0-alpha.10 — uses @monoes/router for
420
- * semantic matching with keyword fallback.
419
+ * Available since agentdb 3.0.0-alpha.10 — semantic matching with keyword fallback.
421
420
  */
422
421
  export declare function bridgeSemanticRoute(params: {
423
422
  input: string;
@@ -1671,8 +1671,7 @@ export async function bridgeContextSynthesize(params) {
1671
1671
  }
1672
1672
  /**
1673
1673
  * Route via SemanticRouter.
1674
- * Available since agentdb 3.0.0-alpha.10 — uses @monoes/router for
1675
- * semantic matching with keyword fallback.
1674
+ * Available since agentdb 3.0.0-alpha.10 — semantic matching with keyword fallback.
1676
1675
  */
1677
1676
  export async function bridgeSemanticRoute(params) {
1678
1677
  const registry = await getRegistry();
@@ -378,121 +378,13 @@ export async function getHNSWIndex(options) {
378
378
  }
379
379
  hnswInitializing = true;
380
380
  try {
381
- // Lean teardown: the native @monoes/core HNSW backend (WASM VectorDb) has been
382
- // removed. Callers of getHNSWIndex() already treat a null return as "no native
383
- // index use the pure-JS / brute-force fallback", so we short-circuit here.
384
- const monovectorModule = await import('@monoes/core').catch(() => null);
385
- if (!monovectorModule) {
386
- hnswInitializing = false;
387
- return null; // HNSW not available — pure-JS fallback path
388
- }
389
- // ESM returns { default: { VectorDb, ... } }, CJS returns { VectorDb, ... }
390
- const monovectorCore = monovectorModule.default || monovectorModule;
391
- if (!monovectorCore?.VectorDb) {
392
- hnswInitializing = false;
393
- return null; // VectorDb not found
394
- }
395
- const { VectorDb } = monovectorCore;
396
- // Persistent storage paths — resolve to absolute to survive CWD changes
397
- const swarmDir = path.resolve(process.cwd(), '.swarm');
398
- if (!fs.existsSync(swarmDir)) {
399
- fs.mkdirSync(swarmDir, { recursive: true });
400
- }
401
- const hnswPath = path.join(swarmDir, 'hnsw.index');
402
- const metadataPath = path.join(swarmDir, 'hnsw.metadata.json');
403
- const dbPath = options?.dbPath ? path.resolve(options.dbPath) : path.join(swarmDir, 'memory.db');
404
- // Create HNSW index with persistent storage
405
- // @monoes/core uses string enum for distanceMetric: 'Cosine', 'Euclidean', 'DotProduct', 'Manhattan'
406
- const db = new VectorDb({
407
- dimensions,
408
- distanceMetric: 'Cosine',
409
- storagePath: hnswPath // Persistent storage!
410
- });
411
- // Load metadata (entry info) if exists
412
- const entries = new Map();
413
- if (fs.existsSync(metadataPath)) {
414
- try {
415
- const metadataJson = fs.readFileSync(metadataPath, 'utf-8');
416
- const metadata = JSON.parse(metadataJson);
417
- for (const [key, value] of metadata) {
418
- entries.set(key, value);
419
- }
420
- }
421
- catch {
422
- // Metadata load failed, will rebuild
423
- }
424
- }
425
- hnswIndex = {
426
- db,
427
- entries,
428
- dimensions,
429
- initialized: false
430
- };
431
- // Check if index already has data (from persistent storage)
432
- const existingLen = await db.len();
433
- if (existingLen > 0 && entries.size > 0) {
434
- // Index loaded from disk, skip SQLite sync
435
- hnswIndex.initialized = true;
436
- hnswInitializing = false;
437
- return hnswIndex;
438
- }
439
- if (fs.existsSync(dbPath)) {
440
- try {
441
- // Reject symlinks and oversized DB files. Without this a symlink at the
442
- // dbPath pointing at /dev/zero or a 100GB sparse file would OOM the CLI
443
- // on the next memory operation.
444
- const stat = fs.lstatSync(dbPath);
445
- if (stat.isSymbolicLink() || stat.size > 256 * 1024 * 1024) {
446
- return null;
447
- }
448
- const initSqlJs = (await import('sql.js')).default;
449
- const SQL = await initSqlJs();
450
- const fileBuffer = fs.readFileSync(dbPath);
451
- const sqlDb = new SQL.Database(fileBuffer);
452
- // Load all entries with embeddings
453
- const result = sqlDb.exec(`
454
- SELECT id, key, namespace, content, embedding
455
- FROM memory_entries
456
- WHERE status = 'active' AND embedding IS NOT NULL
457
- LIMIT 10000
458
- `);
459
- if (result[0]?.values) {
460
- for (const row of result[0].values) {
461
- const [id, key, ns, content, embeddingJson] = row;
462
- if (embeddingJson) {
463
- try {
464
- const embedding = safeParseEmbeddingLocal(embeddingJson);
465
- if (!embedding)
466
- continue;
467
- const vector = new Float32Array(embedding);
468
- await db.insert({
469
- id: String(id),
470
- vector
471
- });
472
- hnswIndex.entries.set(String(id), {
473
- id: String(id),
474
- key: key || String(id),
475
- namespace: ns || 'default',
476
- content: content || ''
477
- });
478
- }
479
- catch {
480
- // Skip invalid embeddings
481
- }
482
- }
483
- }
484
- }
485
- sqlDb.close();
486
- }
487
- catch {
488
- // SQLite load failed, start with empty index
489
- }
490
- }
491
- // initialized = true even on empty DB — absence of vectors is a valid ready state,
492
- // not a failure. The concurrent-waiter null-check at line ~395 relies on this.
493
- hnswIndex.initialized = true;
381
+ // Native @monoes/core HNSW (WASM VectorDb) was removed in the lean teardown.
382
+ // This function is kept for callers that check its return value all callers
383
+ // already handle null by falling back to the pure-JS / brute-force path.
384
+ // The AgentDB bridge (memory-bridge.ts) provides HNSW via agentdb instead.
385
+ // Native backend removed — return null so callers use the pure-JS fallback.
494
386
  hnswInitializing = false;
495
- return hnswIndex;
387
+ return null;
496
388
  }
497
389
  catch {
498
390
  hnswInitializing = false;
@@ -576,7 +468,7 @@ export async function searchHNSWIndex(queryEmbedding, options) {
576
468
  continue;
577
469
  }
578
470
  // Convert cosine distance to similarity score (1 - distance)
579
- // Cosine distance from @monoes/core: 0 = identical, 2 = opposite
471
+ // Cosine distance convention: 0 = identical, 2 = opposite
580
472
  const score = 1 - (result.score / 2);
581
473
  filtered.push({
582
474
  id: entry.id.substring(0, 12),
@@ -1329,6 +1221,48 @@ export async function loadEmbeddingModel(options) {
1329
1221
  }
1330
1222
  }
1331
1223
  try {
1224
+ // Tier 0: @monomind/embeddings — bundles @xenova/transformers as a hard dep, so it
1225
+ // resolves from the CLI even when a bare `import('@xenova/transformers')` does NOT
1226
+ // (the CLI doesn't declare @xenova directly). Without this, the chain below falls
1227
+ // straight through to the hash fallback and "semantic" search is lexical-only.
1228
+ const embPkg = await import('@monomind/embeddings').catch(() => null);
1229
+ if (embPkg && typeof embPkg.createEmbeddingService === 'function') {
1230
+ try {
1231
+ const service = embPkg.createEmbeddingService({
1232
+ provider: 'transformers',
1233
+ model: 'Xenova/all-MiniLM-L6-v2',
1234
+ normalization: 'l2',
1235
+ enableCache: true,
1236
+ });
1237
+ // Probe triggers the (lazy) model load and verifies real vectors come back.
1238
+ const probe = await service.embed('probe');
1239
+ const probeVec = probe?.embedding;
1240
+ const dims = (probeVec && probeVec.length) || 384;
1241
+ if (probeVec && dims > 1) {
1242
+ if (verbose) {
1243
+ console.log(`Loaded @monomind/embeddings (Transformers MiniLM-L6, ${dims}d)...`);
1244
+ }
1245
+ embeddingModelState = {
1246
+ loaded: true,
1247
+ // Match generateEmbedding's consumer: a callable returning a plain number[]
1248
+ // (it accepts either `{ data }` or an Array.isArray(...) result).
1249
+ model: async (text) => Array.from((await service.embed(String(text))).embedding),
1250
+ tokenizer: null,
1251
+ dimensions: dims,
1252
+ };
1253
+ return {
1254
+ success: true,
1255
+ dimensions: dims,
1256
+ modelName: '@monomind/embeddings (transformers/MiniLM-L6)',
1257
+ loadTime: Date.now() - startTime,
1258
+ };
1259
+ }
1260
+ }
1261
+ catch {
1262
+ // Embeddings package present but model load failed (offline / download error);
1263
+ // fall through to the remaining providers and ultimately the hash fallback.
1264
+ }
1265
+ }
1332
1266
  // Try to import @xenova/transformers for ONNX embeddings
1333
1267
  const transformers = await import('@xenova/transformers').catch(() => null);
1334
1268
  if (transformers) {
@@ -1,9 +1,7 @@
1
1
  /**
2
2
  * MonoVector Integration Module for Monomind CLI (lean)
3
3
  *
4
- * After the SONA / native / WASM teardown this module provides only the
5
- * lightweight surface:
6
- * - Capability probing: getCapabilities() — stubbed, always reports JS-only
4
+ * After the SONA / native / WASM teardown this module provides:
7
5
  * - Initialization state: createInitState()
8
6
  * - Keyword-based task routing: createKeywordRouter()
9
7
  * - Route recommendation→outcome records: recordRoute(), joinOutcome(), accuracy
@@ -11,7 +9,6 @@
11
9
  *
12
10
  * @module @monomind/cli/monovector
13
11
  */
14
- export { getCapabilities, getCachedCapabilities, resetCapabilitiesCache, refreshCapabilities, type MonoesCapabilities } from './capabilities.js';
15
12
  export { createInitState, type InitState, type InitStatus } from './init-state.js';
16
13
  export { recordRoute, joinOutcome, joinLatestUnresolved, readOutcomes, computeRoutingAccuracy, computeAdherence, type RouteOutcomeRecord, type RoutingAccuracy, } from './route-outcomes.js';
17
14
  export { DiffClassifier, createDiffClassifier, analyzeDiff, analyzeDiffSync, assessFileRisk, assessOverallRisk, classifyDiff, suggestReviewers, getGitDiffNumstat, getGitDiffNumstatAsync, clearDiffCache, clearAllDiffCaches, type DiffClassification, type DiffHunk, type DiffChange, type FileDiff, type DiffAnalysis, type DiffClassifierConfig, type DiffFile, type RiskLevel, type FileRisk, type OverallRisk, type DiffAnalysisResult, } from './diff-classifier.js';
@@ -54,8 +51,4 @@ export interface KeywordRouterConfig {
54
51
  discountFactor?: number;
55
52
  }
56
53
  export declare function createKeywordRouter(_config?: KeywordRouterConfig): KeywordRouter;
57
- /** @deprecated Use (await getCapabilities()).sona */
58
- export declare function isMonovectorAvailable(): Promise<boolean>;
59
- /** @deprecated Use (await getCapabilities()).learningWasm */
60
- export declare function isWasmBackendAvailable(): Promise<boolean>;
61
54
  //# sourceMappingURL=index.d.ts.map
@@ -1,9 +1,7 @@
1
1
  /**
2
2
  * MonoVector Integration Module for Monomind CLI (lean)
3
3
  *
4
- * After the SONA / native / WASM teardown this module provides only the
5
- * lightweight surface:
6
- * - Capability probing: getCapabilities() — stubbed, always reports JS-only
4
+ * After the SONA / native / WASM teardown this module provides:
7
5
  * - Initialization state: createInitState()
8
6
  * - Keyword-based task routing: createKeywordRouter()
9
7
  * - Route recommendation→outcome records: recordRoute(), joinOutcome(), accuracy
@@ -11,8 +9,6 @@
11
9
  *
12
10
  * @module @monomind/cli/monovector
13
11
  */
14
- import { getCapabilities } from './capabilities.js';
15
- export { getCapabilities, getCachedCapabilities, resetCapabilitiesCache, refreshCapabilities } from './capabilities.js';
16
12
  export { createInitState } from './init-state.js';
17
13
  export { recordRoute, joinOutcome, joinLatestUnresolved, readOutcomes, computeRoutingAccuracy, computeAdherence, } from './route-outcomes.js';
18
14
  export { DiffClassifier, createDiffClassifier, analyzeDiff, analyzeDiffSync, assessFileRisk, assessOverallRisk, classifyDiff, suggestReviewers, getGitDiffNumstat, getGitDiffNumstatAsync, clearDiffCache, clearAllDiffCaches, } from './diff-classifier.js';
@@ -56,12 +52,4 @@ export function createKeywordRouter(_config) {
56
52
  import() { },
57
53
  };
58
54
  }
59
- /** @deprecated Use (await getCapabilities()).sona */
60
- export async function isMonovectorAvailable() {
61
- return (await getCapabilities()).sona;
62
- }
63
- /** @deprecated Use (await getCapabilities()).learningWasm */
64
- export async function isWasmBackendAvailable() {
65
- return (await getCapabilities()).learningWasm;
66
- }
67
55
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "1.11.5",
3
+ "version": "1.11.6",
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",
@@ -68,7 +68,6 @@
68
68
  "dist",
69
69
  "bin",
70
70
  ".claude",
71
- "bundled-graph",
72
71
  "scripts",
73
72
  "README.md"
74
73
  ],
@@ -1,73 +0,0 @@
1
- import Graph from 'graphology';
2
- // Mirrors upstream graphify's _normalize_id: lowercase + collapse non-alphanumeric to underscores.
3
- function normalizeId(s) {
4
- return s.replace(/[^a-zA-Z0-9]+/g, '_').replace(/^_+|_+$/g, '').toLowerCase();
5
- }
6
- /**
7
- * Build a graphology Graph from extracted nodes and edges.
8
- * Deduplicates nodes by id, merges parallel edges with higher weight.
9
- */
10
- export function buildGraph(extraction) {
11
- const graph = new Graph({ type: 'directed', multi: false });
12
- // Add all nodes — merge attributes if already present (dedup by id)
13
- for (const node of extraction.nodes) {
14
- if (!graph.hasNode(node.id)) {
15
- graph.addNode(node.id, { ...node });
16
- }
17
- else {
18
- graph.mergeNodeAttributes(node.id, { ...node });
19
- }
20
- }
21
- // Build normalized ID lookup to remap mismatched edge endpoints before stubbing.
22
- const normToId = new Map();
23
- graph.forEachNode((id) => {
24
- normToId.set(normalizeId(id), id);
25
- });
26
- // Add edges — skip self-loops, remap via normalization, stub only true externals
27
- for (const edge of extraction.edges) {
28
- let src = edge.source;
29
- let tgt = edge.target;
30
- if (!graph.hasNode(src)) {
31
- const remapped = normToId.get(normalizeId(src));
32
- if (remapped) {
33
- src = remapped;
34
- }
35
- else {
36
- graph.addNode(src, { id: src, label: src, fileType: 'unknown', sourceFile: '' });
37
- normToId.set(normalizeId(src), src);
38
- }
39
- }
40
- if (!graph.hasNode(tgt)) {
41
- const remapped = normToId.get(normalizeId(tgt));
42
- if (remapped) {
43
- tgt = remapped;
44
- }
45
- else {
46
- graph.addNode(tgt, { id: tgt, label: tgt, fileType: 'unknown', sourceFile: '' });
47
- normToId.set(normalizeId(tgt), tgt);
48
- }
49
- }
50
- if (src === tgt)
51
- continue;
52
- try {
53
- graph.addEdge(src, tgt, {
54
- relation: edge.relation,
55
- confidence: edge.confidence,
56
- confidenceScore: edge.confidenceScore,
57
- weight: edge.weight ?? 1,
58
- sourceFile: edge.sourceFile,
59
- sourceLocation: edge.sourceLocation,
60
- });
61
- }
62
- catch {
63
- // Edge already exists — bump its weight
64
- const existing = graph.edge(src, tgt);
65
- if (existing) {
66
- const prev = graph.getEdgeAttribute(existing, 'weight') ?? 1;
67
- graph.setEdgeAttribute(existing, 'weight', prev + 1);
68
- }
69
- }
70
- }
71
- return graph;
72
- }
73
- //# sourceMappingURL=build.js.map
@@ -1,120 +0,0 @@
1
- import Graph from 'graphology';
2
- export async function detectCommunities(graph) {
3
- let louvainFn = null;
4
- try {
5
- const mod = await import('graphology-communities-louvain');
6
- louvainFn = mod.default;
7
- }
8
- catch { /* louvain not available */ }
9
- if (louvainFn) {
10
- try {
11
- const assignment = louvainFn(graph);
12
- for (const [nodeId, communityId] of Object.entries(assignment)) {
13
- graph.setNodeAttribute(nodeId, 'community', communityId);
14
- }
15
- const communities = {};
16
- for (const [nodeId, communityId] of Object.entries(assignment)) {
17
- if (!communities[communityId])
18
- communities[communityId] = [];
19
- communities[communityId].push(nodeId);
20
- }
21
- return splitOversizedCommunities(graph, communities, 0.25, louvainFn);
22
- }
23
- catch { /* fall through */ }
24
- }
25
- return splitOversizedCommunities(graph, fallbackCluster(graph), 0.25, louvainFn);
26
- }
27
- function fallbackCluster(graph) {
28
- const dirMap = new Map();
29
- let nextId = 0;
30
- const communities = {};
31
- graph.forEachNode((id, attrs) => {
32
- const file = attrs.sourceFile || '';
33
- const parts = file.split('/');
34
- const dir = parts.length > 1 ? parts.slice(0, -1).join('/') : 'root';
35
- if (!dirMap.has(dir))
36
- dirMap.set(dir, nextId++);
37
- const cid = dirMap.get(dir);
38
- graph.setNodeAttribute(id, 'community', cid);
39
- if (!communities[cid])
40
- communities[cid] = [];
41
- communities[cid].push(id);
42
- });
43
- return communities;
44
- }
45
- export function cohesionScore(graph, communityNodes) {
46
- const memberSet = new Set(communityNodes);
47
- let totalEdges = 0;
48
- let internalEdges = 0;
49
- graph.forEachEdge((_edge, _attrs, source, target) => {
50
- const srcIn = memberSet.has(source);
51
- const tgtIn = memberSet.has(target);
52
- if (srcIn || tgtIn) {
53
- totalEdges++;
54
- if (srcIn && tgtIn)
55
- internalEdges++;
56
- }
57
- });
58
- return totalEdges === 0 ? 1.0 : internalEdges / totalEdges;
59
- }
60
- export function splitOversizedCommunities(graph, communities, threshold = 0.25, louvainFn = null) {
61
- const maxSize = threshold * graph.order;
62
- const allIds = Object.keys(communities).map(Number);
63
- let nextId = allIds.length > 0 ? Math.max(...allIds) + 1 : 0;
64
- for (const [cidStr, members] of Object.entries(communities)) {
65
- if (members.length <= maxSize)
66
- continue;
67
- const cid = Number(cidStr);
68
- // Attempt topology-based second pass via Louvain on the community subgraph
69
- if (louvainFn && members.length >= 10) {
70
- try {
71
- const memberSet = new Set(members);
72
- const subG = new Graph({ type: 'undirected', multi: false });
73
- for (const nodeId of members)
74
- subG.addNode(nodeId);
75
- graph.forEachEdge((_e, _a, source, target) => {
76
- if (memberSet.has(source) && memberSet.has(target) && source !== target && !subG.hasEdge(source, target))
77
- subG.addEdge(source, target);
78
- });
79
- const subAssignment = louvainFn(subG);
80
- const subCommunityCount = new Set(Object.values(subAssignment)).size;
81
- if (subCommunityCount > 1 && subCommunityCount <= Math.ceil(members.length / 2)) {
82
- const subIdMap = new Map();
83
- const newSubIds = {};
84
- for (const [nodeId, localId] of Object.entries(subAssignment)) {
85
- if (!subIdMap.has(localId))
86
- subIdMap.set(localId, nextId++);
87
- const globalId = subIdMap.get(localId);
88
- graph.setNodeAttribute(nodeId, 'community', globalId);
89
- if (!newSubIds[globalId])
90
- newSubIds[globalId] = [];
91
- newSubIds[globalId].push(nodeId);
92
- }
93
- delete communities[cid];
94
- Object.assign(communities, newSubIds);
95
- continue;
96
- }
97
- }
98
- catch { /* fall through to directory heuristic */ }
99
- }
100
- // Directory heuristic fallback
101
- const subMap = new Map();
102
- const newSubIds = {};
103
- for (const nodeId of members) {
104
- const file = graph.getNodeAttribute(nodeId, 'sourceFile') || '';
105
- const parts = file.split('/');
106
- const parentDir = parts.length > 1 ? parts[parts.length - 2] : 'root';
107
- if (!subMap.has(parentDir))
108
- subMap.set(parentDir, nextId++);
109
- const subId = subMap.get(parentDir);
110
- graph.setNodeAttribute(nodeId, 'community', subId);
111
- if (!newSubIds[subId])
112
- newSubIds[subId] = [];
113
- newSubIds[subId].push(nodeId);
114
- }
115
- delete communities[cid];
116
- Object.assign(communities, newSubIds);
117
- }
118
- return communities;
119
- }
120
- //# sourceMappingURL=cluster.js.map
@@ -1,57 +0,0 @@
1
- {
2
- "name": "@monomind/graph",
3
- "version": "1.4.0",
4
- "type": "module",
5
- "description": "Knowledge graph engine for monomind — AST extraction, graph construction, community detection, and persistent codebase understanding",
6
- "main": "./dist/src/index.js",
7
- "types": "./dist/src/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/src/index.d.ts",
11
- "import": "./dist/src/index.js"
12
- }
13
- },
14
- "files": [
15
- "dist",
16
- "src"
17
- ],
18
- "scripts": {
19
- "build": "tsc",
20
- "test": "vitest run",
21
- "clean": "rm -rf dist"
22
- },
23
- "dependencies": {
24
- "graphology": "^0.25.4",
25
- "graphology-types": "^0.24.7",
26
- "graphology-communities-louvain": "^2.0.1",
27
- "graphology-shortest-path": "^2.0.2",
28
- "graphology-traversal": "^0.3.1",
29
- "graphology-metrics": "^2.4.0",
30
- "chokidar": "^3.6.0"
31
- },
32
- "devDependencies": {
33
- "@types/node": "^20.0.0",
34
- "typescript": "^5.3.0",
35
- "vitest": "^4.1.4"
36
- },
37
- "optionalDependencies": {
38
- "node-tree-sitter": "^0.22.4",
39
- "tree-sitter-typescript": "^0.23.2",
40
- "tree-sitter-javascript": "^0.23.1",
41
- "tree-sitter-python": "^0.23.6",
42
- "tree-sitter-go": "^0.23.4",
43
- "tree-sitter-rust": "^0.23.2",
44
- "tree-sitter-java": "^0.23.5",
45
- "tree-sitter-c": "^0.23.4",
46
- "tree-sitter-cpp": "^0.23.4",
47
- "tree-sitter-ruby": "^0.23.1",
48
- "tree-sitter-c-sharp": "^0.23.1",
49
- "tree-sitter-kotlin": "^0.3.9",
50
- "tree-sitter-swift": "^0.6.1",
51
- "tree-sitter-scala": "^0.23.4",
52
- "tree-sitter-php": "^0.23.11"
53
- },
54
- "publishConfig": {
55
- "access": "public"
56
- }
57
- }