moflo 4.9.36 → 4.9.37

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.
@@ -403,7 +403,7 @@ export async function bridgeSearchEntries(options) {
403
403
  let rows;
404
404
  try {
405
405
  const sql = `
406
- SELECT id, key, namespace, content, embedding
406
+ SELECT id, key, namespace, content, metadata, embedding
407
407
  FROM memory_entries
408
408
  WHERE status = 'active' ${nsFilter}
409
409
  LIMIT 1000
@@ -459,6 +459,7 @@ export async function bridgeSearchEntries(options) {
459
459
  const provenance = usedSemantic
460
460
  ? `semantic:${semanticScore.toFixed(3)}+bm25:${bm25ScoreVal.toFixed(3)}`
461
461
  : `bm25:${bm25ScoreVal.toFixed(3)}`;
462
+ const metadataStr = row.metadata != null ? String(row.metadata) : undefined;
462
463
  results.push({
463
464
  id: String(row.id).substring(0, 12),
464
465
  // The substring is a fallback id-prefix when key is missing —
@@ -468,6 +469,7 @@ export async function bridgeSearchEntries(options) {
468
469
  score,
469
470
  namespace: String(row.namespace || 'default'),
470
471
  provenance,
472
+ metadata: metadataStr,
471
473
  });
472
474
  }
473
475
  }
@@ -542,13 +544,14 @@ export async function bridgeGetEntry(options) {
542
544
  updatedAt: cached.updatedAt || new Date().toISOString(),
543
545
  hasEmbedding: !!cached.embedding,
544
546
  tags: cached.tags || [],
547
+ metadata: cached.metadata || undefined,
545
548
  },
546
549
  };
547
550
  }
548
551
  let row;
549
552
  try {
550
553
  const stmt = ctx.db.prepare(`
551
- SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags
554
+ SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags, metadata
552
555
  FROM memory_entries
553
556
  WHERE status = 'active' AND key = ? AND namespace = ?
554
557
  LIMIT 1
@@ -591,6 +594,7 @@ export async function bridgeGetEntry(options) {
591
594
  updatedAt: row.updated_at || new Date().toISOString(),
592
595
  hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
593
596
  tags,
597
+ metadata: row.metadata != null ? String(row.metadata) : undefined,
594
598
  };
595
599
  await cacheSet(registry, cacheKey, entry);
596
600
  return { success: true, found: true, cacheHit: false, entry };
@@ -424,8 +424,8 @@ export async function getHNSWIndex(options) {
424
424
  // adjacency. When the sidecar IS loaded we skip the per-row JSON.parse
425
425
  // of the embedding column, which is the expensive part on a populated
426
426
  // consumer DB.
427
- const SELECT_WITH_EMBEDDING = `id, key, namespace, content, embedding`;
428
- const SELECT_METADATA_ONLY = `id, key, namespace, content`;
427
+ const SELECT_WITH_EMBEDDING = `id, key, namespace, content, metadata, embedding`;
428
+ const SELECT_METADATA_ONLY = `id, key, namespace, content, metadata`;
429
429
  if (fs.existsSync(dbPath)) {
430
430
  try {
431
431
  const initSqlJs = (await mofloImport('sql.js')).default;
@@ -442,7 +442,9 @@ export async function getHNSWIndex(options) {
442
442
  let parseSkipped = 0;
443
443
  if (result[0]?.values) {
444
444
  for (const row of result[0].values) {
445
- const [id, key, ns, content, embeddingJson] = row;
445
+ // Column order matches SELECT_WITH_EMBEDDING / SELECT_METADATA_ONLY.
446
+ // When sidecar is loaded, embeddingJson is undefined (column absent).
447
+ const [id, key, ns, content, metadataJson, embeddingJson] = row;
446
448
  if (!sidecarLoaded) {
447
449
  const vec = parseEmbeddingJson(embeddingJson);
448
450
  if (!vec) {
@@ -455,7 +457,8 @@ export async function getHNSWIndex(options) {
455
457
  id: String(id),
456
458
  key: key || String(id),
457
459
  namespace: ns || 'default',
458
- content: content || ''
460
+ content: content || '',
461
+ metadata: metadataJson || undefined
459
462
  });
460
463
  }
461
464
  }
@@ -545,7 +548,8 @@ export async function searchHNSWIndex(queryEmbedding, options) {
545
548
  key: entry.key || entry.id.substring(0, 15),
546
549
  content: entry.content.substring(0, 60) + (entry.content.length > 60 ? '...' : ''),
547
550
  score,
548
- namespace: entry.namespace
551
+ namespace: entry.namespace,
552
+ metadata: entry.metadata
549
553
  });
550
554
  if (filtered.length >= k)
551
555
  break;
@@ -1817,7 +1821,7 @@ export async function searchEntries(options) {
1817
1821
  const db = new SQL.Database(fileBuffer);
1818
1822
  // Get entries with embeddings
1819
1823
  const entries = db.exec(`
1820
- SELECT id, key, namespace, content, embedding
1824
+ SELECT id, key, namespace, content, metadata, embedding
1821
1825
  FROM memory_entries
1822
1826
  WHERE status = 'active'
1823
1827
  ${namespace !== 'all' ? `AND namespace = '${namespace.replace(/'/g, "''")}'` : ''}
@@ -1826,7 +1830,7 @@ export async function searchEntries(options) {
1826
1830
  const results = [];
1827
1831
  if (entries[0]?.values) {
1828
1832
  for (const row of entries[0].values) {
1829
- const [id, key, ns, content, embeddingJson] = row;
1833
+ const [id, key, ns, content, metadataJson, embeddingJson] = row;
1830
1834
  let score = 0;
1831
1835
  if (embeddingJson) {
1832
1836
  try {
@@ -1849,7 +1853,8 @@ export async function searchEntries(options) {
1849
1853
  key: key || id.substring(0, 15),
1850
1854
  content: (content || '').substring(0, 60) + ((content || '').length > 60 ? '...' : ''),
1851
1855
  score,
1852
- namespace: ns || 'default'
1856
+ namespace: ns || 'default',
1857
+ metadata: metadataJson || undefined
1853
1858
  });
1854
1859
  }
1855
1860
  }
@@ -1987,7 +1992,7 @@ export async function getEntry(options) {
1987
1992
  const db = new SQL.Database(fileBuffer);
1988
1993
  // Find entry by key
1989
1994
  const result = db.exec(`
1990
- SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags
1995
+ SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags, metadata
1991
1996
  FROM memory_entries
1992
1997
  WHERE status = 'active'
1993
1998
  AND key = '${key.replace(/'/g, "''")}'
@@ -1998,7 +2003,7 @@ export async function getEntry(options) {
1998
2003
  db.close();
1999
2004
  return { success: true, found: false };
2000
2005
  }
2001
- const [id, entryKey, ns, content, embedding, accessCount, createdAt, updatedAt, tagsJson] = result[0].values[0];
2006
+ const [id, entryKey, ns, content, embedding, accessCount, createdAt, updatedAt, tagsJson, metadataJson] = result[0].values[0];
2002
2007
  // Update access count
2003
2008
  db.run(`
2004
2009
  UPDATE memory_entries
@@ -2028,7 +2033,8 @@ export async function getEntry(options) {
2028
2033
  createdAt: createdAt || new Date().toISOString(),
2029
2034
  updatedAt: updatedAt || new Date().toISOString(),
2030
2035
  hasEmbedding: !!embedding && embedding.length > 10,
2031
- tags
2036
+ tags,
2037
+ metadata: metadataJson || undefined
2032
2038
  }
2033
2039
  };
2034
2040
  }
@@ -21,7 +21,7 @@ const BOOTSTRAP_JSON_REL = '.claude/helpers/subagent-bootstrap.json';
21
21
  // Defense-in-depth copy of the canonical directive in subagent-bootstrap.json.
22
22
  // Kept as a single-line literal so the parity test can verify it matches the
23
23
  // JSON via plain substring containment.
24
- const FALLBACK_DIRECTIVE = 'MANDATORY FIRST ACTION: Your very first tool call MUST be mcp__moflo__memory_search (any query, any namespace). The memory-first gate WILL BLOCK all Glob, Grep, and Read calls until you do this. After memory search, follow `.claude/guidance/moflo-subagents.md` protocol.';
24
+ const FALLBACK_DIRECTIVE = 'MANDATORY FIRST ACTION: Your very first tool call MUST be mcp__moflo__memory_search (any query, any namespace). The memory-first gate WILL BLOCK all Glob, Grep, and Read calls until you do this. After memory search, follow `.claude/guidance/moflo-subagents.md` protocol. When search returns chunk hits, traverse via mcp__moflo__memory_get_neighbors before retrieving — see `.claude/guidance/moflo-memory-protocol.md`.';
25
25
  function loadDirective() {
26
26
  const jsonPath = locateMofloRootPath(BOOTSTRAP_JSON_REL);
27
27
  if (!jsonPath) {
@@ -2,5 +2,5 @@
2
2
  * Auto-generated by build. Do not edit manually.
3
3
  * Source of truth: root package.json → scripts/sync-version.mjs
4
4
  */
5
- export const VERSION = '4.9.36';
5
+ export const VERSION = '4.9.37';
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moflo",
3
- "version": "4.9.36",
3
+ "version": "4.9.37",
4
4
  "description": "MoFlo — AI agent orchestration for Claude Code. A standalone, opinionated toolkit with semantic memory, learned routing, gates, spells, and the /flo issue-execution skill.",
5
5
  "main": "dist/src/cli/index.js",
6
6
  "type": "module",
@@ -97,7 +97,7 @@
97
97
  "@typescript-eslint/eslint-plugin": "^7.18.0",
98
98
  "@typescript-eslint/parser": "^7.18.0",
99
99
  "eslint": "^8.0.0",
100
- "moflo": "^4.9.35",
100
+ "moflo": "^4.9.36",
101
101
  "tsx": "^4.21.0",
102
102
  "typescript": "^5.9.3",
103
103
  "vitest": "^4.0.0"