cogmem 3.6.5 → 3.7.1
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/CHANGELOG.md +24 -0
- package/MEMORY_ATLAS.md +59 -12
- package/README.md +21 -13
- package/RELEASE_CHECKLIST.md +5 -4
- package/dist/agent/AgentMemoryBackend.d.ts +24 -3
- package/dist/agent/AgentMemoryBackend.js +285 -55
- package/dist/agent/AgentRecallQueryCompiler.d.ts +1 -1
- package/dist/agent/AgentRecallQueryCompiler.js +13 -1
- package/dist/agent/MemoryUsageReceipt.js +8 -10
- package/dist/agent/SessionWorkingState.js +3 -2
- package/dist/agent/UntrustedMemorySerializer.d.ts +2 -0
- package/dist/agent/UntrustedMemorySerializer.js +14 -0
- package/dist/atlas/ActionFrameExtractor.js +2 -0
- package/dist/atlas/EpisodeTitleGenerator.d.ts +31 -0
- package/dist/atlas/EpisodeTitleGenerator.js +191 -0
- package/dist/atlas/FacetQueryPlanner.d.ts +33 -0
- package/dist/atlas/FacetQueryPlanner.js +229 -0
- package/dist/atlas/GraphCurator.d.ts +30 -0
- package/dist/atlas/GraphCurator.js +501 -0
- package/dist/atlas/MemoryAtlasIndexer.d.ts +15 -0
- package/dist/atlas/MemoryAtlasIndexer.js +55 -6
- package/dist/atlas/MemoryAtlasQueryCompiler.js +10 -7
- package/dist/atlas/MemoryAtlasService.d.ts +4 -1
- package/dist/atlas/MemoryAtlasService.js +174 -11
- package/dist/atlas/MemoryAtlasTypes.d.ts +75 -11
- package/dist/bin/memory.js +18 -5
- package/dist/factory.d.ts +18 -0
- package/dist/factory.js +41 -2
- package/dist/host/openclaw/AutoMemoryPluginInstaller.js +135 -39
- package/dist/mcp/server.js +1 -1
- package/dist/recall/RecallExplanation.d.ts +1 -1
- package/dist/store/MemoryAtlasStore.d.ts +12 -1
- package/dist/store/MemoryAtlasStore.js +353 -15
- package/dist/utils/ActionKindRegistry.d.ts +10 -0
- package/dist/utils/ActionKindRegistry.js +18 -0
- package/dist/utils/EntityCueExtractor.d.ts +13 -0
- package/dist/utils/EntityCueExtractor.js +81 -0
- package/examples/hermes-backend/AGENTS.md +3 -3
- package/examples/hermes-backend/README.md +1 -1
- package/examples/hermes-backend/SKILL.md +14 -5
- package/examples/hermes-backend/references/operations.md +12 -9
- package/examples/openclaw-backend/AGENTS.md +3 -2
- package/examples/openclaw-backend/README.md +3 -2
- package/examples/openclaw-backend/SKILL.md +31 -9
- package/examples/openclaw-backend/references/operations.md +29 -11
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { resolveCogmemConfigPath } from '../../config/CogmemConfig.js';
|
|
7
7
|
const PLUGIN_ID = 'cogmem-auto-memory';
|
|
8
|
-
const PLUGIN_VERSION = '0.
|
|
8
|
+
const PLUGIN_VERSION = '0.7.1';
|
|
9
9
|
function defaultPublicEntrypoint() {
|
|
10
10
|
return join(resolve(dirname(fileURLToPath(import.meta.url)), '../..'), 'public.js');
|
|
11
11
|
}
|
|
@@ -516,15 +516,29 @@ function createMemoryUsageReceipt(input) {
|
|
|
516
516
|
|
|
517
517
|
function formatSourceAnchor(anchor) {
|
|
518
518
|
return [
|
|
519
|
-
anchor.memoryId ? 'memory:' + anchor.memoryId : '',
|
|
520
|
-
anchor.eventId ? 'event:' + anchor.eventId : '',
|
|
521
|
-
anchor.sessionId ? 'session:' + anchor.sessionId : '',
|
|
522
|
-
anchor.role ? 'role:' + anchor.role : '',
|
|
519
|
+
anchor.memoryId ? 'memory:' + serializeUntrustedMemory(anchor.memoryId, 160) : '',
|
|
520
|
+
anchor.eventId ? 'event:' + serializeUntrustedMemory(anchor.eventId, 160) : '',
|
|
521
|
+
anchor.sessionId ? 'session:' + serializeUntrustedMemory(anchor.sessionId, 160) : '',
|
|
522
|
+
anchor.role ? 'role:' + serializeUntrustedMemory(anchor.role, 80) : '',
|
|
523
523
|
].filter(Boolean).join('; ');
|
|
524
524
|
}
|
|
525
525
|
|
|
526
526
|
function listLines(values) {
|
|
527
|
-
return values.length ? values.map((value) => '- ' + value) : ['- none'];
|
|
527
|
+
return values.length ? values.map((value) => '- ' + serializeUntrustedMemory(value, 260)) : ['- none'];
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function serializeUntrustedMemory(input, limit) {
|
|
531
|
+
const clean = stripCogmemRecallBlocks(String(input || '')).text
|
|
532
|
+
.replace(new RegExp('</?COGMEM_[A-Z0-9_:-]+[^>]*>', 'gi'), '')
|
|
533
|
+
.replace(new RegExp('[\\\\u0000-\\\\u0008\\\\u000b\\\\u000c\\\\u000e-\\\\u001f\\\\u007f]', 'g'), ' ')
|
|
534
|
+
.replace(new RegExp('\\\\s+', 'g'), ' ')
|
|
535
|
+
.trim()
|
|
536
|
+
.replace(/&/g, '&')
|
|
537
|
+
.replace(/</g, '<')
|
|
538
|
+
.replace(/>/g, '>')
|
|
539
|
+
.replace(/"/g, '"')
|
|
540
|
+
.replace(/'/g, ''');
|
|
541
|
+
return clean.slice(0, Math.max(0, Number(limit || 500)));
|
|
528
542
|
}
|
|
529
543
|
|
|
530
544
|
function clampBlock(text, closingTag, maxChars) {
|
|
@@ -535,14 +549,14 @@ function clampBlock(text, closingTag, maxChars) {
|
|
|
535
549
|
|
|
536
550
|
function formatMemoryUsageBridge(receipt, maxChars) {
|
|
537
551
|
const lines = [
|
|
538
|
-
'<COGMEM_TURN_BRIDGE turn_id="' +
|
|
552
|
+
'<COGMEM_TURN_BRIDGE turn_id="' + serializeUntrustedMemory(receipt.turnId, 180) + '" source="cogmem" compact="true" ttl_turns="' + receipt.ttlTurns + '" compile_allowed="false">',
|
|
539
553
|
'Previous assistant answer used Cogmem memory.',
|
|
540
554
|
'',
|
|
541
555
|
'Used memory themes:',
|
|
542
556
|
...listLines(receipt.usedThemes || []),
|
|
543
557
|
'',
|
|
544
558
|
'Working conclusion produced in that turn:',
|
|
545
|
-
'- ' + (receipt.workingConclusion || 'No compact conclusion recorded.'),
|
|
559
|
+
'- ' + serializeUntrustedMemory(receipt.workingConclusion || 'No compact conclusion recorded.', 260),
|
|
546
560
|
'',
|
|
547
561
|
'Source anchors:',
|
|
548
562
|
...listLines((receipt.sourceAnchors || []).map(formatSourceAnchor)),
|
|
@@ -608,7 +622,7 @@ function formatSessionWorkingState(state, maxChars) {
|
|
|
608
622
|
const lines = [
|
|
609
623
|
'<COGMEM_SESSION_STATE scope="current_session" compact="true" persistence="session_only" compile_allowed="false">',
|
|
610
624
|
'Current working topic:',
|
|
611
|
-
'- ' + (state.currentTopic || 'unspecified'),
|
|
625
|
+
'- ' + serializeUntrustedMemory(state.currentTopic || 'unspecified', 180),
|
|
612
626
|
'',
|
|
613
627
|
'Current design direction:',
|
|
614
628
|
...listLines(state.designDirection || []),
|
|
@@ -663,6 +677,9 @@ function classifyRecallIntent(query) {
|
|
|
663
677
|
if (/原话|怎么说的|完整对话|上一句|下一句|exact quote|verbatim/.test(text)) {
|
|
664
678
|
return 'forensic_quote';
|
|
665
679
|
}
|
|
680
|
+
if (/(让你.{0,20}(对|给|把)?.{0,20}(做过|做了|启动|安装|配置|修改|重启|停止|操作|处理|执行)|对.{0,30}(做过什么|做了什么|哪些操作)|what did (i ask you to do|you do) to|operations? on)/i.test(text)) {
|
|
681
|
+
return 'action_history';
|
|
682
|
+
}
|
|
666
683
|
if (/记得.{0,12}(聊过|讨论过|说过)|还记得|之前.{0,12}(聊过|讨论过|说过)|以前.{0,12}(聊过|讨论过|说过)|(过去|几个月前|半年前|上个月|前几天|昨天|上次|上个).{0,20}(聊过|讨论过|说过)|当时.{0,12}(聊|说|问)|那次.{0,12}(聊|说|问)|有没有.{0,12}(记录|聊过|讨论过)|have we discussed|did we talk about|previously discussed/.test(text)) {
|
|
667
684
|
return 'historical_discussion';
|
|
668
685
|
}
|
|
@@ -992,7 +1009,7 @@ function audit(config, record) {
|
|
|
992
1009
|
const plugin = {
|
|
993
1010
|
id: PLUGIN_ID,
|
|
994
1011
|
name: 'CogMem Auto Memory',
|
|
995
|
-
version: '
|
|
1012
|
+
version: '${PLUGIN_VERSION}',
|
|
996
1013
|
register(api) {
|
|
997
1014
|
if (!api || typeof api.on !== 'function') {
|
|
998
1015
|
throw new Error('OpenClaw plugin API missing api.on');
|
|
@@ -1314,7 +1331,7 @@ async function recallPayload(input, config, kernel, memory, formatStrategyContex
|
|
|
1314
1331
|
let result = await memory.recall({
|
|
1315
1332
|
agentId: config.agentId || 'openclaw', projectId: config.projectId || 'openclaw',
|
|
1316
1333
|
query: input.query || '', sessionId: input.sessionId, threadId: input.threadId,
|
|
1317
|
-
excludeSessionId: input.excludeSessionId, intent: input.intent ||
|
|
1334
|
+
excludeSessionId: input.excludeSessionId, intent: input.intent || undefined,
|
|
1318
1335
|
anchorEventId: input.anchorEventId, anchorText: input.anchorText,
|
|
1319
1336
|
limit: Number(config.limit || 3), retrievalPolicy: strategyCapsule && strategyCapsule.retrievalPolicy,
|
|
1320
1337
|
});
|
|
@@ -1327,7 +1344,7 @@ async function recallPayload(input, config, kernel, memory, formatStrategyContex
|
|
|
1327
1344
|
result = await memory.recall({
|
|
1328
1345
|
agentId: config.agentId || 'openclaw', projectId: config.projectId || 'openclaw',
|
|
1329
1346
|
query: input.query || '', sessionId: input.sessionId, threadId: input.threadId,
|
|
1330
|
-
excludeSessionId: input.excludeSessionId, intent: input.intent ||
|
|
1347
|
+
excludeSessionId: input.excludeSessionId, intent: input.intent || undefined,
|
|
1331
1348
|
anchorEventId: input.anchorEventId, anchorText: input.anchorText,
|
|
1332
1349
|
limit: Number(config.limit || 3), retrievalPolicy: strategyCapsule && strategyCapsule.retrievalPolicy,
|
|
1333
1350
|
});
|
|
@@ -1338,18 +1355,42 @@ async function recallPayload(input, config, kernel, memory, formatStrategyContex
|
|
|
1338
1355
|
maxMemoryRatio: Number(config.contextMemoryMaxRatio || 0.25), strategy: strategyCapsule,
|
|
1339
1356
|
candidates: result.items.map(contextCandidateFromRecallItem),
|
|
1340
1357
|
});
|
|
1341
|
-
|
|
1358
|
+
let plannedResult = activationPlan
|
|
1342
1359
|
? { ...result, items: activationPlan.selected.map((candidate) => candidate.recallItem) }
|
|
1343
1360
|
: result;
|
|
1361
|
+
let activationReceipt = activationPlan && activationPlan.receipt;
|
|
1362
|
+
if (activationPlan && Array.isArray(result.items)) {
|
|
1363
|
+
const selectedIds = new Set(plannedResult.items.map((item) => item && item.id).filter(Boolean));
|
|
1364
|
+
const strictFacetItem = (result.decisionTrace && result.decisionTrace.selectedLane === 'facet_graph_raw_ledger')
|
|
1365
|
+
? result.items.find((item) => item && item.canonicalId && Array.isArray(item.matchedFacets) && item.matchedFacets.length > 0)
|
|
1366
|
+
: undefined;
|
|
1367
|
+
if (strictFacetItem && !selectedIds.has(strictFacetItem.id)) {
|
|
1368
|
+
plannedResult = { ...plannedResult, items: [strictFacetItem, ...plannedResult.items].slice(0, Number(config.limit || 3)) };
|
|
1369
|
+
activationReceipt = {
|
|
1370
|
+
...(activationReceipt || {}),
|
|
1371
|
+
facetGraphRetained: true,
|
|
1372
|
+
retainedCanonicalId: strictFacetItem.canonicalId,
|
|
1373
|
+
matchedFacets: strictFacetItem.matchedFacets,
|
|
1374
|
+
reason: 'strict_facet_match_must_not_be_silently_dropped',
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1344
1378
|
const anchorItem = plannedResult.items.find((item) => item && item.sourceAnchor && item.sourceAnchor.eventId);
|
|
1379
|
+
const selectedCanonicalIds = new Set(plannedResult.items.map((item) => item && item.canonicalId).filter(Boolean));
|
|
1380
|
+
const selectedEpisodeCards = Array.isArray(result.atlasCards)
|
|
1381
|
+
? result.atlasCards.filter((card) => card && selectedCanonicalIds.has(card.canonicalId))
|
|
1382
|
+
: [];
|
|
1383
|
+
plannedResult = { ...plannedResult, atlasCards: selectedEpisodeCards };
|
|
1345
1384
|
const recallContext = formatRecallContext(plannedResult, config);
|
|
1346
1385
|
return {
|
|
1347
1386
|
context: recallContext ? (strategyCapsule ? formatStrategyContext(strategyCapsule) + '\n\n' : '') + recallContext : '',
|
|
1348
1387
|
items: compactRecallItems(plannedResult.items, config), itemCount: plannedResult.items.length,
|
|
1349
|
-
recallMode: result.recallMode, fallbackUsed: result.fallbackUsed, intent: input.intent || 'memory_recall',
|
|
1388
|
+
recallMode: result.recallMode, fallbackUsed: result.fallbackUsed, intent: (result.queryPlan && result.queryPlan.intent) || input.intent || 'memory_recall',
|
|
1350
1389
|
anchorEventId: anchorItem && anchorItem.sourceAnchor && anchorItem.sourceAnchor.eventId,
|
|
1351
1390
|
anchorText: anchorItem && anchorItem.text, queryPlan: result.queryPlan, decisionTrace: result.decisionTrace,
|
|
1352
|
-
|
|
1391
|
+
atlasCards: result.atlasCards, selectedEpisodeCards,
|
|
1392
|
+
relatedButNotSelected: result.relatedButNotSelected, relaxationTrace: result.relaxationTrace,
|
|
1393
|
+
activationReceipt, strategyCapsule,
|
|
1353
1394
|
strategyReplanned: replan.replanned, strategyReplanReason: replan.reason,
|
|
1354
1395
|
recallLatencyMs: Date.now() - recallStartedAt,
|
|
1355
1396
|
};
|
|
@@ -1394,16 +1435,27 @@ function stripCogmemRecallBlocks(text) {
|
|
|
1394
1435
|
|
|
1395
1436
|
function formatAtlasContext(result, maxChars) {
|
|
1396
1437
|
const nodes = Array.isArray(result && result.nodes) ? result.nodes : [];
|
|
1397
|
-
|
|
1438
|
+
const cards = Array.isArray(result && result.cards) ? result.cards : [];
|
|
1439
|
+
if (!nodes.length && !cards.length) return '';
|
|
1398
1440
|
const edges = Array.isArray(result && result.edges) ? result.edges : [];
|
|
1399
1441
|
const actions = Array.isArray(result && result.nextActions) ? result.nextActions : [];
|
|
1400
1442
|
const nodeDetails = Array.isArray(result && result.nodeDetails) ? result.nodeDetails : [];
|
|
1401
1443
|
const lines = [
|
|
1402
|
-
'<COGMEM_MEMORY_ATLAS version="memory_atlas.
|
|
1444
|
+
'<COGMEM_MEMORY_ATLAS version="memory_atlas.v2" volatile="true" persistence="forbidden" evidence_authority="raw_event_ids_only">',
|
|
1403
1445
|
'Bounded navigation map; use it to choose nodes and paths, not as durable evidence.',
|
|
1404
|
-
'Matched facets: ' + safeAtlasText(JSON.stringify(result.facets || {}),
|
|
1446
|
+
'Matched facets: ' + safeAtlasText(JSON.stringify(result.facets && result.facets.planner || result.facets || {}), 1400),
|
|
1405
1447
|
'Cold memory resurrected: ' + String(result.coldMemoryResurrected === true),
|
|
1406
1448
|
'',
|
|
1449
|
+
'Selected memory cards:',
|
|
1450
|
+
...cards.slice(0, 8).map((card) => '- ' + formatAtlasCard(card)),
|
|
1451
|
+
...(cards.length ? [
|
|
1452
|
+
'',
|
|
1453
|
+
'Related but not selected:',
|
|
1454
|
+
...cards.flatMap((card) => Array.isArray(card.relatedButNotSelected) ? card.relatedButNotSelected : [])
|
|
1455
|
+
.slice(0, 8)
|
|
1456
|
+
.map((card) => '- ' + safeAtlasText(card.displayTitle, 160) + ' [' + safeAtlasText(card.reason, 160) + ']'),
|
|
1457
|
+
'',
|
|
1458
|
+
] : []),
|
|
1407
1459
|
'Nodes:',
|
|
1408
1460
|
...nodes.slice(0, 30).map((node) => '- ' + JSON.stringify({
|
|
1409
1461
|
id: safeAtlasText(node.id, 500), type: safeAtlasText(node.nodeType, 80),
|
|
@@ -1435,10 +1487,20 @@ function formatAtlasContext(result, maxChars) {
|
|
|
1435
1487
|
}
|
|
1436
1488
|
|
|
1437
1489
|
function safeAtlasText(input, limit) {
|
|
1490
|
+
return serializeUntrustedMemory(input, limit);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
function serializeUntrustedMemory(input, limit) {
|
|
1438
1494
|
const clean = stripCogmemRecallBlocks(String(input || '')).text
|
|
1439
|
-
.replace(
|
|
1495
|
+
.replace(/<\/?COGMEM_[A-Z0-9_:-]+[^>]*>/gi, '')
|
|
1496
|
+
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, ' ')
|
|
1440
1497
|
.replace(/\s+/g, ' ')
|
|
1441
|
-
.trim()
|
|
1498
|
+
.trim()
|
|
1499
|
+
.replace(/&/g, '&')
|
|
1500
|
+
.replace(/</g, '<')
|
|
1501
|
+
.replace(/>/g, '>')
|
|
1502
|
+
.replace(/"/g, '"')
|
|
1503
|
+
.replace(/'/g, ''');
|
|
1442
1504
|
return clean.slice(0, Math.max(0, Number(limit || 500)));
|
|
1443
1505
|
}
|
|
1444
1506
|
|
|
@@ -1695,6 +1757,9 @@ function compactRecallItems(items, config) {
|
|
|
1695
1757
|
projectId: item.projectId,
|
|
1696
1758
|
sourceAnchor: item.sourceAnchor,
|
|
1697
1759
|
whyMatched: item.whyMatched,
|
|
1760
|
+
canonicalId: item.canonicalId,
|
|
1761
|
+
displayTitle: item.displayTitle,
|
|
1762
|
+
matchedFacets: item.matchedFacets,
|
|
1698
1763
|
}));
|
|
1699
1764
|
}
|
|
1700
1765
|
|
|
@@ -1731,34 +1796,47 @@ function formatRecallContext(result, config) {
|
|
|
1731
1796
|
if (result.decisionTrace) {
|
|
1732
1797
|
lines.push('recallDecision=' + formatRecallDecision(result.decisionTrace));
|
|
1733
1798
|
}
|
|
1799
|
+
if (Array.isArray(result.atlasCards) && result.atlasCards.length) {
|
|
1800
|
+
lines.push('selectedMemoryCards=' + result.atlasCards.slice(0, Number(config.memoryContextMaxItems || config.limit || 3)).map(formatAtlasCard).join(' | '));
|
|
1801
|
+
}
|
|
1802
|
+
if (Array.isArray(result.relaxationTrace) && result.relaxationTrace.length) {
|
|
1803
|
+
lines.push('relaxationTrace=' + result.relaxationTrace.map((step) => serializeUntrustedMemory(step.from, 80) + ' -> ' + serializeUntrustedMemory(step.to, 80) + ' (' + serializeUntrustedMemory(step.reason, 160) + ')').join(' | '));
|
|
1804
|
+
}
|
|
1805
|
+
if (Array.isArray(result.relatedButNotSelected) && result.relatedButNotSelected.length) {
|
|
1806
|
+
lines.push('relatedButNotSelected=' + result.relatedButNotSelected.slice(0, 4).map((item) => serializeUntrustedMemory(item.displayTitle, 160) + ' [' + serializeUntrustedMemory(item.reason, 160) + ']').join(' | '));
|
|
1807
|
+
}
|
|
1734
1808
|
lines.push('');
|
|
1735
1809
|
if (result.narrative && result.narrative.summary) {
|
|
1736
|
-
lines.push(result.narrative.summary);
|
|
1810
|
+
lines.push(serializeUntrustedMemory(result.narrative.summary, 800));
|
|
1737
1811
|
}
|
|
1738
1812
|
const maxItems = Number(config.memoryContextMaxItems || config.limit || 3);
|
|
1739
1813
|
const sourceWindowMaxChars = Number(config.sourceWindowMaxChars || 1200);
|
|
1740
1814
|
const includeSourceWindow = config.includeSourceWindowByDefault === true;
|
|
1741
1815
|
for (const item of result.items.slice(0, maxItems)) {
|
|
1742
|
-
const source = item.source ? ' [' + item.source + ']' : '';
|
|
1743
|
-
lines.push('- ' + item.text + source);
|
|
1816
|
+
const source = item.source ? ' [' + serializeUntrustedMemory(item.source, 220) + ']' : '';
|
|
1817
|
+
lines.push('- ' + serializeUntrustedMemory(item.text, 500) + source);
|
|
1744
1818
|
const sourceType = item.sourceType || 'compiled_memory';
|
|
1745
1819
|
const quote = item.canAnswerExactQuote === true ? 'true' : 'false';
|
|
1746
1820
|
const confidence = Number.isFinite(item.confidence) ? String(item.confidence) : 'unknown';
|
|
1747
|
-
const anchor = item.sourceAnchor ? '; anchorEvent=' + (item.sourceAnchor.eventId || 'unknown')
|
|
1748
|
-
+ (item.sourceAnchor.sessionId ? '; session=' + item.sourceAnchor.sessionId : '')
|
|
1749
|
-
+ (item.sourceAnchor.role ? '; role=' + item.sourceAnchor.role : '') : '';
|
|
1750
|
-
const why = item.whyMatched ? '; whyMatched=' + item.whyMatched : '';
|
|
1751
|
-
|
|
1821
|
+
const anchor = item.sourceAnchor ? '; anchorEvent=' + serializeUntrustedMemory(item.sourceAnchor.eventId || 'unknown', 160)
|
|
1822
|
+
+ (item.sourceAnchor.sessionId ? '; session=' + serializeUntrustedMemory(item.sourceAnchor.sessionId, 160) : '')
|
|
1823
|
+
+ (item.sourceAnchor.role ? '; role=' + serializeUntrustedMemory(item.sourceAnchor.role, 80) : '') : '';
|
|
1824
|
+
const why = item.whyMatched ? '; whyMatched=' + serializeUntrustedMemory(item.whyMatched, 180) : '';
|
|
1825
|
+
const canonical = item.canonicalId ? '; canonicalId=' + serializeUntrustedMemory(item.canonicalId, 180) : '';
|
|
1826
|
+
const matchedFacets = Array.isArray(item.matchedFacets) && item.matchedFacets.length
|
|
1827
|
+
? '; matchedFacets=' + item.matchedFacets.map((facet) => serializeUntrustedMemory(facet.type, 80) + ':' + serializeUntrustedMemory(facet.value, 160)).join(',')
|
|
1828
|
+
: '';
|
|
1829
|
+
lines.push(' sourceType=' + serializeUntrustedMemory(sourceType, 120) + '; confidence=' + confidence + '; canAnswerExactQuote=' + quote + canonical + matchedFacets + anchor + why);
|
|
1752
1830
|
if (item.sourceContext && item.sourceContext.event) {
|
|
1753
1831
|
const anchorEvent = item.sourceContext.event;
|
|
1754
1832
|
const anchorFormatted = formatContextEvent(anchorEvent, Math.min(220, sourceWindowMaxChars));
|
|
1755
1833
|
lines.push(' sourceContext=' + anchorFormatted.line);
|
|
1756
1834
|
lines.push(' sourceWindow=' + formatSourceWindow(item.sourceContext.window, item.sourceContext));
|
|
1757
1835
|
if (item.sourceContext.locator && item.sourceContext.locator.command) {
|
|
1758
|
-
lines.push(' sourceLocator=' + item.sourceContext.locator.command);
|
|
1836
|
+
lines.push(' sourceLocator=' + serializeUntrustedMemory(item.sourceContext.locator.command, 500));
|
|
1759
1837
|
} else if (item.sourceContext.event.eventId) {
|
|
1760
1838
|
const project = item.sourceContext.event.projectId ? ' --project ' + item.sourceContext.event.projectId : '';
|
|
1761
|
-
lines.push(' sourceLocator=cogmem memory show --event ' + item.sourceContext.event.eventId + project + ' --before 2 --after 2 --json');
|
|
1839
|
+
lines.push(' sourceLocator=' + serializeUntrustedMemory('cogmem memory show --event ' + item.sourceContext.event.eventId + project + ' --before 2 --after 2 --json', 500));
|
|
1762
1840
|
}
|
|
1763
1841
|
const seenEventIds = new Set([anchorEvent.eventId].filter(Boolean));
|
|
1764
1842
|
const before = uniqueWindowEvents(Array.isArray(item.sourceContext.before) ? item.sourceContext.before : [], seenEventIds).slice(-2);
|
|
@@ -1801,6 +1879,24 @@ function formatRecallDecision(trace) {
|
|
|
1801
1879
|
+ ',raw:' + Number(counts.rawLedger || 0);
|
|
1802
1880
|
}
|
|
1803
1881
|
|
|
1882
|
+
function formatAtlasCard(card) {
|
|
1883
|
+
const facets = Array.isArray(card && card.matchedFacets)
|
|
1884
|
+
? card.matchedFacets.map((facet) => serializeUntrustedMemory(facet.type, 80) + ':' + serializeUntrustedMemory(facet.value, 160)).join(',')
|
|
1885
|
+
: '';
|
|
1886
|
+
const paths = Array.isArray(card && card.matchedPaths)
|
|
1887
|
+
? card.matchedPaths.map((path) => serializeUntrustedMemory(path.relation, 80) + '@' + serializeUntrustedMemory(path.facet && path.facet.nodeId || 'facet', 180)).slice(0, 6).join(',')
|
|
1888
|
+
: '';
|
|
1889
|
+
const locator = card && card.sourceLocator && card.sourceLocator.command ? '; sourceLocator=' + serializeUntrustedMemory(card.sourceLocator.command, 500) : '';
|
|
1890
|
+
const why = card && card.whyMatched ? '; whyMatched=' + serializeUntrustedMemory(card.whyMatched, 180) : '';
|
|
1891
|
+
return serializeUntrustedMemory(card && card.canonicalId || 'episode:unknown', 180)
|
|
1892
|
+
+ '; title=' + serializeUntrustedMemory(card && card.displayTitle, 120)
|
|
1893
|
+
+ '; summary=' + serializeUntrustedMemory(card && card.oneLineSummary, 180)
|
|
1894
|
+
+ (facets ? '; matchedFacets=' + facets : '')
|
|
1895
|
+
+ (paths ? '; matchedPaths=' + paths : '')
|
|
1896
|
+
+ why
|
|
1897
|
+
+ locator;
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1804
1900
|
function clampRecallContext(text, maxChars) {
|
|
1805
1901
|
const closingTag = '</COGMEM_RECALL_CONTEXT>';
|
|
1806
1902
|
if (text.length <= maxChars) return text;
|
|
@@ -1809,10 +1905,10 @@ function clampRecallContext(text, maxChars) {
|
|
|
1809
1905
|
}
|
|
1810
1906
|
|
|
1811
1907
|
function formatContextEvent(event, limit) {
|
|
1812
|
-
const truncation = truncateLineWithMeta(event && event.text, limit);
|
|
1813
|
-
const label = contextEventLabel(event);
|
|
1814
|
-
const role = event && event.role ? event.role : 'unknown';
|
|
1815
|
-
const eventId = event && event.eventId ? event.eventId : 'unknown';
|
|
1908
|
+
const truncation = truncateLineWithMeta(serializeUntrustedMemory(event && event.text, limit), limit);
|
|
1909
|
+
const label = serializeUntrustedMemory(contextEventLabel(event), 120);
|
|
1910
|
+
const role = serializeUntrustedMemory(event && event.role ? event.role : 'unknown', 80);
|
|
1911
|
+
const eventId = serializeUntrustedMemory(event && event.eventId ? event.eventId : 'unknown', 160);
|
|
1816
1912
|
const charRange = event && event.charRange ? '; charRange=' + event.charRange.start + '-' + event.charRange.end : '';
|
|
1817
1913
|
const sourceRange = formatSourceRange(event && event.sourceRange);
|
|
1818
1914
|
const textLength = Number.isFinite(event && event.textLength) ? event.textLength : truncation.originalChars;
|
|
@@ -1834,17 +1930,17 @@ function formatSourceWindow(window, context) {
|
|
|
1834
1930
|
const dropped = Array.isArray(window && window.droppedOverlapEventIds) ? window.droppedOverlapEventIds : [];
|
|
1835
1931
|
return 'before=' + formatWindowSide(before)
|
|
1836
1932
|
+ '; after=' + formatWindowSide(after)
|
|
1837
|
-
+ '; overlap=' + (overlapEventIds.length ? overlapEventIds.join(',') : 'none')
|
|
1838
|
-
+ '; droppedOverlap=' + (dropped.length ? dropped.join(',') : 'none')
|
|
1839
|
-
+ '; overlapHandling=' + ((window && window.overlapHandling) || 'drop_from_after');
|
|
1933
|
+
+ '; overlap=' + (overlapEventIds.length ? overlapEventIds.map((id) => serializeUntrustedMemory(id, 120)).join(',') : 'none')
|
|
1934
|
+
+ '; droppedOverlap=' + (dropped.length ? dropped.map((id) => serializeUntrustedMemory(id, 120)).join(',') : 'none')
|
|
1935
|
+
+ '; overlapHandling=' + serializeUntrustedMemory((window && window.overlapHandling) || 'drop_from_after', 120);
|
|
1840
1936
|
}
|
|
1841
1937
|
|
|
1842
1938
|
function formatWindowSide(side) {
|
|
1843
1939
|
return 'requestedCount=' + Number(side.requestedCount || 0)
|
|
1844
1940
|
+ ', count=' + Number(side.count || 0)
|
|
1845
1941
|
+ ', excludesAnchor=' + (side.excludesAnchor !== false)
|
|
1846
|
-
+ ', ordering=' + (side.ordering || 'chronological')
|
|
1847
|
-
+ ', roleFilter=' + (side.roleFilter || 'all');
|
|
1942
|
+
+ ', ordering=' + serializeUntrustedMemory(side.ordering || 'chronological', 80)
|
|
1943
|
+
+ ', roleFilter=' + serializeUntrustedMemory(side.roleFilter || 'all', 80);
|
|
1848
1944
|
}
|
|
1849
1945
|
|
|
1850
1946
|
function uniqueWindowEvents(events, seenEventIds) {
|
package/dist/mcp/server.js
CHANGED
|
@@ -44,7 +44,7 @@ export interface RecallExplanation {
|
|
|
44
44
|
projectId?: string;
|
|
45
45
|
agentId?: string;
|
|
46
46
|
collection?: string;
|
|
47
|
-
recallMode: MemoryKernelNavigationResult['recallMode'] | 'raw_ledger_fallback';
|
|
47
|
+
recallMode: MemoryKernelNavigationResult['recallMode'] | 'raw_ledger_fallback' | 'atlas_facet_recall' | 'atlas_raw_grounded_recall';
|
|
48
48
|
fallbackUsed: boolean;
|
|
49
49
|
narrative?: NonNullable<MemoryKernelNavigationResult['navigation']>['narrative'];
|
|
50
50
|
pulseTrace?: NonNullable<MemoryKernelNavigationResult['navigation']>['pulse']['trace'];
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type Database from 'bun:sqlite';
|
|
2
|
-
import type {
|
|
2
|
+
import type { FacetQueryPlan } from '../atlas/FacetQueryPlanner.js';
|
|
3
|
+
import type { MemoryAtlasAction, MemoryAtlasCard, MemoryAtlasEdge, MemoryAtlasNode, MemoryAtlasRelatedCard } from '../atlas/MemoryAtlasTypes.js';
|
|
4
|
+
export declare const MEMORY_ATLAS_PROJECTION_NAME = "memory_atlas.v2";
|
|
5
|
+
export declare const MEMORY_ATLAS_PROJECTION_SCHEMA_VERSION = "3.7.2";
|
|
3
6
|
export declare class MemoryAtlasStore {
|
|
4
7
|
readonly db: Database;
|
|
5
8
|
constructor(db: Database);
|
|
@@ -18,6 +21,9 @@ export declare class MemoryAtlasStore {
|
|
|
18
21
|
keywords?: string[];
|
|
19
22
|
targetNodeIds?: string[];
|
|
20
23
|
}): MemoryAtlasNode[];
|
|
24
|
+
searchCanonicalEpisodeCards(projectId: string, plan: FacetQueryPlan, limit: number): MemoryAtlasCard[];
|
|
25
|
+
relatedEpisodeCards(projectId: string, canonicalId: string, selectedIds: Set<string>, limit: number): MemoryAtlasRelatedCard[];
|
|
26
|
+
private topicRelatedCardsForPlan;
|
|
21
27
|
resolveTargetNodeIds(projectId: string, query: string): {
|
|
22
28
|
nodeIds: string[];
|
|
23
29
|
entitySourceIds: string[];
|
|
@@ -46,6 +52,8 @@ export declare class MemoryAtlasStore {
|
|
|
46
52
|
decay(projectId?: string, factor?: number, now?: number): number;
|
|
47
53
|
projectionNeedsRefresh(projectId: string): boolean;
|
|
48
54
|
markProjectionClean(projectId: string, metadata?: Record<string, unknown>, now?: number): void;
|
|
55
|
+
markProjectionDirty(projectId: string, metadata?: Record<string, unknown>, now?: number): void;
|
|
56
|
+
aggregateFacetNodeSupport(projectId: string, now?: number): void;
|
|
49
57
|
markProjectionFailed(projectId: string, error: string, now?: number): void;
|
|
50
58
|
getProjectionState(projectId: string): {
|
|
51
59
|
status: string;
|
|
@@ -56,5 +64,8 @@ export declare class MemoryAtlasStore {
|
|
|
56
64
|
countDocuments(projectId?: string): number;
|
|
57
65
|
private refreshFtsNode;
|
|
58
66
|
private topicRelationEdges;
|
|
67
|
+
private episodeEdgesForFacet;
|
|
68
|
+
private episodeRows;
|
|
69
|
+
private cardFromEpisodeRow;
|
|
59
70
|
}
|
|
60
71
|
//# sourceMappingURL=MemoryAtlasStore.d.ts.map
|