openclaw-cortex-memory 0.1.0-Alpha.32 → 0.1.0-Alpha.34
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/README.md +35 -19
- package/SKILL.md +2 -2
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -5
- package/dist/index.js.map +1 -1
- package/dist/openclaw.plugin.json +14 -3
- package/dist/src/engine/ts_engine.d.ts +2 -0
- package/dist/src/engine/ts_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.js +19 -8
- package/dist/src/engine/ts_engine.js.map +1 -1
- package/dist/src/quality/llm_output_validator.d.ts +0 -1
- package/dist/src/quality/llm_output_validator.d.ts.map +1 -1
- package/dist/src/quality/llm_output_validator.js +0 -1
- package/dist/src/quality/llm_output_validator.js.map +1 -1
- package/dist/src/store/archive_store.d.ts.map +1 -1
- package/dist/src/store/archive_store.js +9 -5
- package/dist/src/store/archive_store.js.map +1 -1
- package/dist/src/store/graph_memory_store.d.ts.map +1 -1
- package/dist/src/store/graph_memory_store.js +146 -0
- package/dist/src/store/graph_memory_store.js.map +1 -1
- package/dist/src/store/read_store.d.ts.map +1 -1
- package/dist/src/store/read_store.js +22 -7
- package/dist/src/store/read_store.js.map +1 -1
- package/dist/src/store/write_store.d.ts +2 -0
- package/dist/src/store/write_store.d.ts.map +1 -1
- package/dist/src/store/write_store.js +10 -7
- package/dist/src/store/write_store.js.map +1 -1
- package/dist/src/sync/session_sync.d.ts +2 -1
- package/dist/src/sync/session_sync.d.ts.map +1 -1
- package/dist/src/sync/session_sync.js +137 -131
- package/dist/src/sync/session_sync.js.map +1 -1
- package/dist/src/wiki/wiki_maintainer.d.ts +3 -0
- package/dist/src/wiki/wiki_maintainer.d.ts.map +1 -1
- package/dist/src/wiki/wiki_maintainer.js +1 -1
- package/dist/src/wiki/wiki_maintainer.js.map +1 -1
- package/dist/src/wiki/wiki_projector.d.ts +2 -0
- package/dist/src/wiki/wiki_projector.d.ts.map +1 -1
- package/dist/src/wiki/wiki_projector.js +246 -13
- package/dist/src/wiki/wiki_projector.js.map +1 -1
- package/openclaw.plugin.json +14 -3
- package/package.json +4 -3
|
@@ -273,9 +273,12 @@ function tailByCharLimit(text, maxChars) {
|
|
|
273
273
|
}
|
|
274
274
|
return source.slice(-Math.floor(maxChars)).trim();
|
|
275
275
|
}
|
|
276
|
+
function normalizeOneLineText(value) {
|
|
277
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
278
|
+
}
|
|
276
279
|
const LOW_INFORMATION_LINE = /^(ok|okay|got it|roger|noted|sure|thanks|thank you|received|copy that|understood)\b/i;
|
|
277
|
-
const LOW_VALUE_ONLY_LINE = /^(
|
|
278
|
-
const ACTIVE_VALUE_SIGNAL_PATTERN = /(
|
|
280
|
+
const LOW_VALUE_ONLY_LINE = /^(ok|okay|got it|roger|noted|thanks|thank you|received|copy that|understood|sounds good)[\s.!?,]*$/i;
|
|
281
|
+
const ACTIVE_VALUE_SIGNAL_PATTERN = /(decision|trade-?off|constraint|requirement|fix|error|exception|blocked|rollback|deploy|progress|milestone|action item|owner|next step|todo|deadline|eta|issue|bug|metric|latency|error rate|cost|url|link|path|file|config|parameter|version|commit|pr|ticket)/i;
|
|
279
282
|
const ACTIVE_VALUE_EVIDENCE_PATTERN = /(https?:\/\/|www\.|[`#/:\\]|[A-Za-z]:\\|\/[A-Za-z0-9._\-\/]+|\b\d+(?:\.\d+)?%?\b|#\d{1,8})/;
|
|
280
283
|
function denoiseTranscriptForWrite(transcript) {
|
|
281
284
|
const raw = (transcript || "").trim();
|
|
@@ -334,33 +337,33 @@ function buildEventSnippet(text) {
|
|
|
334
337
|
.map(line => line.trim())
|
|
335
338
|
.filter(Boolean)
|
|
336
339
|
.filter(line => line.length >= 8);
|
|
337
|
-
const actionPattern = /(
|
|
340
|
+
const actionPattern = /(decision|fix|error|exception|blocked|deploy|progress|action item|owner|resolved|depends|complete)/i;
|
|
338
341
|
const picked = lines.filter(line => actionPattern.test(line));
|
|
339
342
|
const use = picked.length > 0 ? picked : lines.slice(-20);
|
|
340
343
|
return use.slice(-30).join("\n").slice(-8000);
|
|
341
344
|
}
|
|
342
345
|
const TASK_INSTRUCTION_PATTERNS = [
|
|
343
|
-
|
|
346
|
+
/please|can you|need to|task|implement|fix|investigate|optimi[sz]e|deploy|enable|review/i,
|
|
344
347
|
/please|can you|need to|task|implement|fix|investigate|optimi[sz]e|deploy|enable|review/i,
|
|
345
348
|
];
|
|
346
349
|
const COMPLETION_REPORT_PATTERNS = [
|
|
347
|
-
|
|
350
|
+
/done|completed|fixed|implemented|deployed|resolved|report|summary|finished/i,
|
|
348
351
|
/done|completed|fixed|implemented|deployed|resolved|report|summary|finished/i,
|
|
349
352
|
];
|
|
350
353
|
const USER_ACCEPTANCE_PATTERNS = [
|
|
351
|
-
|
|
354
|
+
/approved|accepted|looks good|great|works|thank you|confirmed|ok/i,
|
|
352
355
|
/approved|accepted|looks good|great|works|thank you|confirmed/i,
|
|
353
356
|
];
|
|
354
357
|
const FAILURE_PATTERNS = [
|
|
355
|
-
|
|
358
|
+
/failed|error|exception|blocked|timeout|rollback|incident/i,
|
|
356
359
|
/failed|error|exception|blocked|timeout|rollback|incident/i,
|
|
357
360
|
];
|
|
358
361
|
const SUCCESS_PATTERNS = [
|
|
359
|
-
|
|
362
|
+
/success|completed|fixed|resolved|passed|stable|recovered|works/i,
|
|
360
363
|
/success|completed|fixed|resolved|passed|stable|recovered|works/i,
|
|
361
364
|
];
|
|
362
|
-
const USER_ROLE_HINT = /^(user|human|customer|client
|
|
363
|
-
const AGENT_ROLE_HINT = /^(assistant|agent|ai|system|openclaw|claude|gpt
|
|
365
|
+
const USER_ROLE_HINT = /^(user|human|customer|client)/i;
|
|
366
|
+
const AGENT_ROLE_HINT = /^(assistant|agent|ai|system|openclaw|claude|gpt)/i;
|
|
364
367
|
function matchesAnyPattern(text, patterns) {
|
|
365
368
|
return patterns.some(pattern => pattern.test(text));
|
|
366
369
|
}
|
|
@@ -381,11 +384,9 @@ function parseTranscriptLines(transcript) {
|
|
|
381
384
|
}).filter(item => item.text.length > 0);
|
|
382
385
|
}
|
|
383
386
|
function summarizeForArchive(text, maxChars) {
|
|
387
|
+
void maxChars;
|
|
384
388
|
const normalized = text.replace(/\s+/g, " ").trim();
|
|
385
|
-
|
|
386
|
-
return normalized;
|
|
387
|
-
}
|
|
388
|
-
return `${normalized.slice(0, Math.max(40, maxChars - 1)).trim()}…`;
|
|
389
|
+
return normalized;
|
|
389
390
|
}
|
|
390
391
|
function evaluateTaskLifecycle(transcript) {
|
|
391
392
|
const parsed = parseTranscriptLines(transcript);
|
|
@@ -477,16 +478,9 @@ function appendLifecycleArchiveDecision(decisions, transcript, logger) {
|
|
|
477
478
|
if (!fallbackGraph) {
|
|
478
479
|
return decisions;
|
|
479
480
|
}
|
|
480
|
-
const
|
|
481
|
-
"Task lifecycle
|
|
482
|
-
lifecycle
|
|
483
|
-
lifecycle.reportText ? `Completion: ${summarizeForArchive(lifecycle.reportText, 220)}` : "",
|
|
484
|
-
lifecycle.acceptanceText ? `Acceptance: ${summarizeForArchive(lifecycle.acceptanceText, 160)}` : "",
|
|
485
|
-
lifecycle.failThenSuccess
|
|
486
|
-
? "The execution included setbacks/errors followed by successful completion, so the reusable experience value is high."
|
|
487
|
-
: "",
|
|
488
|
-
].filter(Boolean);
|
|
489
|
-
const summary = summaryParts.join(" ");
|
|
481
|
+
const summary = lifecycle.failThenSuccess
|
|
482
|
+
? "Task lifecycle closed: user request, failure iteration, final completion, and user acceptance."
|
|
483
|
+
: "Task lifecycle closed: user request, completion report, and user acceptance.";
|
|
490
484
|
const cause = lifecycle.taskText
|
|
491
485
|
? summarizeForArchive(lifecycle.taskText, 220)
|
|
492
486
|
: "User issued a concrete task request.";
|
|
@@ -509,9 +503,6 @@ function appendLifecycleArchiveDecision(decisions, transcript, logger) {
|
|
|
509
503
|
entities: fallbackGraph.entities,
|
|
510
504
|
relations: fallbackGraph.relations,
|
|
511
505
|
entity_types: fallbackGraph.entity_types,
|
|
512
|
-
outcome: lifecycle.acceptanceText
|
|
513
|
-
? summarizeForArchive(lifecycle.acceptanceText, 180)
|
|
514
|
-
: "User acknowledged and accepted the delivery.",
|
|
515
506
|
confidence: typeof fallbackGraph.confidence === "number" ? fallbackGraph.confidence : confidence,
|
|
516
507
|
},
|
|
517
508
|
reason: "lifecycle_archive_fallback",
|
|
@@ -530,13 +521,13 @@ const GRAPH_REWRITE_SCOPE_FIELDS = [
|
|
|
530
521
|
const GRAPH_REWRITE_SCOPE_SET = new Set(GRAPH_REWRITE_SCOPE_FIELDS);
|
|
531
522
|
const WRITE_GATE_PROMPT_VERSION = "write-gate.v1.7.9";
|
|
532
523
|
const WRITE_GATE_STAGE_AB_PROMPT_VERSION = "write-gate.ab.v1.1.5";
|
|
533
|
-
const WRITE_GATE_STAGE_C_PROMPT_VERSION = "write-gate.c.v1.
|
|
524
|
+
const WRITE_GATE_STAGE_C_PROMPT_VERSION = "write-gate.c.v1.5.0";
|
|
534
525
|
const WRITE_GATE_STAGE_D_PROMPT_VERSION = "write-gate.d.v1.1.0";
|
|
535
526
|
const WRITE_GATE_GRAPH_REWRITE_PROMPT_VERSION = "write-gate.graph-rewrite.v1.1.0";
|
|
536
527
|
const WRITE_GATE_REGRESSION_SAMPLES = [
|
|
537
|
-
"
|
|
538
|
-
"
|
|
539
|
-
"
|
|
528
|
+
"Example A: \"Discussed three options today, no final decision yet\" => active_only",
|
|
529
|
+
"Example B: \"Decided to use plan B and completed rollout, error rate dropped to 0.2%\" => archive_event",
|
|
530
|
+
"Example C: \"ok received thanks\" => skip",
|
|
540
531
|
];
|
|
541
532
|
function buildActiveValuePromptHint(schema) {
|
|
542
533
|
const pick = (source, wanted) => {
|
|
@@ -627,18 +618,7 @@ function buildStablePersonalFactGraph(text) {
|
|
|
627
618
|
if (!source)
|
|
628
619
|
return null;
|
|
629
620
|
const genericTokens = new Set([
|
|
630
|
-
"user",
|
|
631
|
-
"person",
|
|
632
|
-
"people",
|
|
633
|
-
"system",
|
|
634
|
-
"assistant",
|
|
635
|
-
"agent",
|
|
636
|
-
"用户",
|
|
637
|
-
"系统",
|
|
638
|
-
"助手",
|
|
639
|
-
"实体",
|
|
640
|
-
"问题",
|
|
641
|
-
"方案",
|
|
621
|
+
"user", "person", "people", "system", "assistant", "agent",
|
|
642
622
|
]);
|
|
643
623
|
const normalizeToken = (value) => value.trim().toLowerCase();
|
|
644
624
|
const isConcreteName = (value) => {
|
|
@@ -649,47 +629,41 @@ function buildStablePersonalFactGraph(text) {
|
|
|
649
629
|
return false;
|
|
650
630
|
if (/^(wife|husband|spouse|child|kid|children)$/i.test(name))
|
|
651
631
|
return false;
|
|
652
|
-
if (/^(妻子|丈夫|配偶|孩子|儿子|女儿)$/.test(name))
|
|
653
|
-
return false;
|
|
654
632
|
return true;
|
|
655
633
|
};
|
|
656
634
|
const extractConcreteName = (candidate) => {
|
|
657
|
-
const cleaned = (candidate || "").trim().replace(/[
|
|
635
|
+
const cleaned = (candidate || "").trim().replace(/[.,;:!?]+$/g, "");
|
|
658
636
|
return isConcreteName(cleaned) ? cleaned : "";
|
|
659
637
|
};
|
|
660
638
|
const findSubjectName = () => {
|
|
661
639
|
const patterns = [
|
|
662
640
|
/([A-Za-z][A-Za-z0-9._-]{1,40})\s*'s\s*(wife|husband|spouse|child|kid|daughter|son)\b/i,
|
|
663
|
-
/([\u4e00-\u9fff]{2,12})\s*的\s*(妻子|老婆|配偶|爱人|丈夫|老公|孩子|儿子|女儿)/,
|
|
664
641
|
/\b([A-Z][a-zA-Z0-9._-]{1,40})\b/,
|
|
665
642
|
];
|
|
666
643
|
for (const pattern of patterns) {
|
|
667
644
|
const hit = source.match(pattern);
|
|
668
645
|
const candidate = hit ? extractConcreteName(hit[1] || "") : "";
|
|
669
|
-
if (candidate)
|
|
646
|
+
if (candidate)
|
|
670
647
|
return candidate;
|
|
671
|
-
}
|
|
672
648
|
}
|
|
673
649
|
return "";
|
|
674
650
|
};
|
|
675
651
|
const subjectName = findSubjectName();
|
|
676
|
-
if (!subjectName)
|
|
652
|
+
if (!subjectName)
|
|
677
653
|
return null;
|
|
678
|
-
}
|
|
679
654
|
const entities = new Set([subjectName]);
|
|
680
655
|
const entity_types = { [subjectName]: "Person" };
|
|
681
656
|
const relations = [];
|
|
682
657
|
const relationKeys = new Set();
|
|
683
658
|
const addRelation = (relation) => {
|
|
684
659
|
const relationKey = `${relation.source}|${relation.type}|${relation.target}`;
|
|
685
|
-
if (relationKeys.has(relationKey))
|
|
660
|
+
if (relationKeys.has(relationKey))
|
|
686
661
|
return;
|
|
687
|
-
}
|
|
688
662
|
relationKeys.add(relationKey);
|
|
689
663
|
relations.push(relation);
|
|
690
664
|
};
|
|
691
|
-
const spouseNameHit = source.match(/(
|
|
692
|
-
const spouseName = spouseNameHit ? extractConcreteName(spouseNameHit[
|
|
665
|
+
const spouseNameHit = source.match(/(?:wife|husband|spouse)(?:\s*(?:named|is|:|-)?\s*)?([A-Za-z][A-Za-z0-9._-]{1,40})/i);
|
|
666
|
+
const spouseName = spouseNameHit ? extractConcreteName(spouseNameHit[1] || "") : "";
|
|
693
667
|
if (spouseName) {
|
|
694
668
|
entities.add(spouseName);
|
|
695
669
|
entity_types[spouseName] = "FamilyMember";
|
|
@@ -702,8 +676,8 @@ function buildStablePersonalFactGraph(text) {
|
|
|
702
676
|
confidence: 0.9,
|
|
703
677
|
});
|
|
704
678
|
}
|
|
705
|
-
const childNameHit = source.match(/(
|
|
706
|
-
const childName = childNameHit ? extractConcreteName(childNameHit[
|
|
679
|
+
const childNameHit = source.match(/(?:child|kid|daughter|son)(?:\s*(?:named|is|:|-)?\s*)?([A-Za-z][A-Za-z0-9._-]{1,40})/i);
|
|
680
|
+
const childName = childNameHit ? extractConcreteName(childNameHit[1] || "") : "";
|
|
707
681
|
if (childName) {
|
|
708
682
|
entities.add(childName);
|
|
709
683
|
entity_types[childName] = "FamilyMember";
|
|
@@ -716,50 +690,49 @@ function buildStablePersonalFactGraph(text) {
|
|
|
716
690
|
confidence: 0.88,
|
|
717
691
|
});
|
|
718
692
|
}
|
|
719
|
-
const birthdayMatch = source.match(/
|
|
693
|
+
const birthdayMatch = source.match(/birthday[^\n]*?(\d{4}-\d{2}-\d{2}|\d{1,2}[/-]\d{1,2})/i);
|
|
720
694
|
if (birthdayMatch && spouseName) {
|
|
721
|
-
const dateEntity = birthdayMatch[
|
|
695
|
+
const dateEntity = birthdayMatch[1];
|
|
722
696
|
entities.add(dateEntity);
|
|
723
697
|
entity_types[dateEntity] = "Date";
|
|
724
698
|
addRelation({
|
|
725
699
|
source: spouseName,
|
|
726
700
|
target: dateEntity,
|
|
727
701
|
type: "birthday_on",
|
|
728
|
-
evidence_span: birthdayMatch[
|
|
702
|
+
evidence_span: birthdayMatch[1],
|
|
729
703
|
context_chunk: source.slice(0, 160).trim(),
|
|
730
704
|
confidence: 0.92,
|
|
731
705
|
});
|
|
732
706
|
}
|
|
733
707
|
if (birthdayMatch && childName) {
|
|
734
|
-
const dateEntity = birthdayMatch[
|
|
708
|
+
const dateEntity = birthdayMatch[1];
|
|
735
709
|
entities.add(dateEntity);
|
|
736
710
|
entity_types[dateEntity] = "Date";
|
|
737
711
|
addRelation({
|
|
738
712
|
source: childName,
|
|
739
713
|
target: dateEntity,
|
|
740
714
|
type: "birthday_on",
|
|
741
|
-
evidence_span: birthdayMatch[
|
|
715
|
+
evidence_span: birthdayMatch[1],
|
|
742
716
|
context_chunk: source.slice(0, 160).trim(),
|
|
743
717
|
confidence: 0.9,
|
|
744
718
|
});
|
|
745
719
|
}
|
|
746
|
-
const anniversaryMatch = source.match(/
|
|
720
|
+
const anniversaryMatch = source.match(/anniversary[^\n]*?(\d{4}-\d{2}-\d{2}|\d{1,2}[/-]\d{1,2})/i);
|
|
747
721
|
if (anniversaryMatch) {
|
|
748
|
-
const dateEntity = anniversaryMatch[
|
|
722
|
+
const dateEntity = anniversaryMatch[1];
|
|
749
723
|
entities.add(dateEntity);
|
|
750
724
|
entity_types[dateEntity] = "Date";
|
|
751
725
|
addRelation({
|
|
752
726
|
source: subjectName,
|
|
753
727
|
target: dateEntity,
|
|
754
728
|
type: "anniversary_on",
|
|
755
|
-
evidence_span: anniversaryMatch[
|
|
729
|
+
evidence_span: anniversaryMatch[1],
|
|
756
730
|
context_chunk: source.slice(0, 160).trim(),
|
|
757
731
|
confidence: 0.9,
|
|
758
732
|
});
|
|
759
733
|
}
|
|
760
|
-
if (relations.length === 0)
|
|
734
|
+
if (relations.length === 0)
|
|
761
735
|
return null;
|
|
762
|
-
}
|
|
763
736
|
return {
|
|
764
737
|
entities: [...entities],
|
|
765
738
|
entity_types,
|
|
@@ -828,7 +801,6 @@ function parseArchiveEventPayload(value) {
|
|
|
828
801
|
entities,
|
|
829
802
|
entity_types,
|
|
830
803
|
relations,
|
|
831
|
-
outcome: typeof obj.outcome === "string" ? obj.outcome.trim() : "",
|
|
832
804
|
confidence: typeof obj.confidence === "number" ? Math.max(0, Math.min(1, obj.confidence)) : 0.6,
|
|
833
805
|
};
|
|
834
806
|
}
|
|
@@ -1269,13 +1241,16 @@ function parseWritePlanDecisions(rootObj, logger, schema) {
|
|
|
1269
1241
|
if (!candidateId)
|
|
1270
1242
|
continue;
|
|
1271
1243
|
trustedCandidateIds.add(candidateId);
|
|
1272
|
-
const sourceSlice = firstString([payload.source_slice, payload.
|
|
1244
|
+
const sourceSlice = firstString([payload.source_slice, payload.sourceSlice]) || "";
|
|
1273
1245
|
if (sourceSlice && !candidateTextById.has(candidateId)) {
|
|
1274
1246
|
candidateTextById.set(candidateId, sourceSlice);
|
|
1275
1247
|
}
|
|
1276
|
-
const
|
|
1277
|
-
if (
|
|
1278
|
-
activePayloadById.set(candidateId,
|
|
1248
|
+
const activeSummary = normalizeOneLineText(firstString([payload.summary, payload.active_summary, payload.activeSummary]) || "");
|
|
1249
|
+
if (activeSummary || sourceSlice) {
|
|
1250
|
+
activePayloadById.set(candidateId, {
|
|
1251
|
+
summary: activeSummary,
|
|
1252
|
+
source_slice: sourceSlice.trim(),
|
|
1253
|
+
});
|
|
1279
1254
|
}
|
|
1280
1255
|
}
|
|
1281
1256
|
const archivePayloadById = new Map();
|
|
@@ -1321,7 +1296,6 @@ function parseWritePlanDecisions(rootObj, logger, schema) {
|
|
|
1321
1296
|
entities: eventValidation.cleaned.entities,
|
|
1322
1297
|
entity_types: eventValidation.cleaned.entity_types,
|
|
1323
1298
|
relations: eventValidation.cleaned.relations,
|
|
1324
|
-
outcome: eventValidation.cleaned.outcome || "",
|
|
1325
1299
|
confidence: eventValidation.cleaned.confidence,
|
|
1326
1300
|
});
|
|
1327
1301
|
}
|
|
@@ -1411,12 +1385,15 @@ function parseWritePlanDecisions(rootObj, logger, schema) {
|
|
|
1411
1385
|
targetLayer = activePayloadById.has(candidateId) ? "active_only" : "skip";
|
|
1412
1386
|
event = undefined;
|
|
1413
1387
|
}
|
|
1414
|
-
const
|
|
1388
|
+
const activePayload = activePayloadById.get(candidateId);
|
|
1389
|
+
const activeSummary = activePayload?.summary || "";
|
|
1390
|
+
const activeSourceSlice = activePayload?.source_slice || "";
|
|
1415
1391
|
decisions.push({
|
|
1416
1392
|
candidate_id: candidateId,
|
|
1417
1393
|
candidate_text: candidateTextById.get(candidateId),
|
|
1418
1394
|
target_layer: targetLayer,
|
|
1419
|
-
|
|
1395
|
+
active_summary: activeSummary || undefined,
|
|
1396
|
+
active_source_slice: activeSourceSlice || undefined,
|
|
1420
1397
|
event: targetLayer === "archive_event" ? event : undefined,
|
|
1421
1398
|
graph: graphPayloadById.get(candidateId),
|
|
1422
1399
|
merge_hint: mergeHintById.get(candidateId),
|
|
@@ -1458,7 +1435,6 @@ function parseLegacyRoutingDecisions(rootObj, logger, schema) {
|
|
|
1458
1435
|
entities: eventValidation.cleaned.entities,
|
|
1459
1436
|
entity_types: eventValidation.cleaned.entity_types,
|
|
1460
1437
|
relations: eventValidation.cleaned.relations,
|
|
1461
|
-
outcome: eventValidation.cleaned.outcome || "",
|
|
1462
1438
|
confidence: eventValidation.cleaned.confidence,
|
|
1463
1439
|
};
|
|
1464
1440
|
}
|
|
@@ -1473,7 +1449,15 @@ function parseLegacyRoutingDecisions(rootObj, logger, schema) {
|
|
|
1473
1449
|
candidate_id: candidateId,
|
|
1474
1450
|
candidate_text: candidateTextById.get(candidateId) || undefined,
|
|
1475
1451
|
target_layer: target,
|
|
1476
|
-
|
|
1452
|
+
active_summary: normalizeOneLineText(typeof obj.summary === "string"
|
|
1453
|
+
? obj.summary
|
|
1454
|
+
: (typeof obj.active_summary === "string"
|
|
1455
|
+
? obj.active_summary
|
|
1456
|
+
: (typeof obj.active_text === "string" ? obj.active_text : ""))) || undefined,
|
|
1457
|
+
active_source_slice: firstString([
|
|
1458
|
+
obj.source_slice,
|
|
1459
|
+
obj.source_span,
|
|
1460
|
+
]) || undefined,
|
|
1477
1461
|
event: event || undefined,
|
|
1478
1462
|
graph: toAppendableGraphPayload(parseGraphPayload(obj.graph)),
|
|
1479
1463
|
reason: typeof obj.reason === "string" ? obj.reason.trim() : "",
|
|
@@ -1534,7 +1518,7 @@ function parseLlmGateDecisions(raw, logger, schema) {
|
|
|
1534
1518
|
const deduped = [];
|
|
1535
1519
|
const seen = new Set();
|
|
1536
1520
|
for (const item of legacyOutput) {
|
|
1537
|
-
const key = `${item.candidate_id || ""}|${item.target_layer}|${item.event?.summary || item.
|
|
1521
|
+
const key = `${item.candidate_id || ""}|${item.target_layer}|${item.event?.summary || item.active_summary || item.reason || ""}`;
|
|
1538
1522
|
if (seen.has(key))
|
|
1539
1523
|
continue;
|
|
1540
1524
|
seen.add(key);
|
|
@@ -1629,10 +1613,10 @@ async function extractGateDecisionsWithLlm(args) {
|
|
|
1629
1613
|
"Task: execute Stage A+B only (denoise + candidate split + route classification).",
|
|
1630
1614
|
"Route classes: active_only | archive_event | skip.",
|
|
1631
1615
|
"Rules:",
|
|
1632
|
-
"- Denoise first: remove pure acknowledgements/politeness/chitchat/repeated filler (for example:
|
|
1616
|
+
"- Denoise first: remove pure acknowledgements/politeness/chitchat/repeated filler (for example: 婵犻潧鍊婚弲顐⑩枔?闂佽 鍋撻悹鍝勬惈閻?闁荤姴顑冮崹濂告⒓?ok/got it/thanks) when they contain no task facts.",
|
|
1633
1617
|
`- Keep factual evidence during denoise using dictionary-grounded signals. ${activeValuePromptHint}`,
|
|
1634
1618
|
`- ${entityDictionaryPromptHint}`,
|
|
1635
|
-
"- Concrete entities must be source-grounded names or aliases from the dictionary above; reject generic placeholders (e.g., user/person/system
|
|
1619
|
+
"- Concrete entities must be source-grounded names or aliases from the dictionary above; reject generic placeholders (e.g., user/person/system/闂傚倸鍋嗛崳锝夈€?闂佸搫鍊介~澶愩€?闁诲骸婀遍崑妯肩礊?thing).",
|
|
1636
1620
|
"- Semantic event split rule: one candidate = one principal event with a coherent subject + action/decision + object/outcome in the same phase.",
|
|
1637
1621
|
"- Split into different candidates when topic/goal/subject changes, or when a new decision/outcome starts.",
|
|
1638
1622
|
"- Merge sentences into one candidate when they describe the same event progression in one phase.",
|
|
@@ -1644,6 +1628,10 @@ async function extractGateDecisionsWithLlm(args) {
|
|
|
1644
1628
|
"- skip: noise/repetition/chitchat/no clear business value.",
|
|
1645
1629
|
"- Archive task-lifecycle by default when all three are present: user instruction -> agent completion report -> user acceptance.",
|
|
1646
1630
|
"- If failure/iteration then eventual success exists, prefer archive_event.",
|
|
1631
|
+
"Candidate field definitions:",
|
|
1632
|
+
"- span: source text slice for this candidate (verbatim excerpt from transcript snippet, may contain minor noise).",
|
|
1633
|
+
"- normalized_text: denoised and normalized version of span for the same candidate; keep meaning unchanged.",
|
|
1634
|
+
"- When both are available, normalized_text is the canonical text field for downstream stages.",
|
|
1647
1635
|
"Output schema:",
|
|
1648
1636
|
"{\"write_plan\":{\"candidates\":[{\"candidate_id\":\"c1\",\"route\":\"archive_event\",\"span\":\"...\",\"normalized_text\":\"...\",\"reason\":\"...\"}]}}",
|
|
1649
1637
|
...WRITE_GATE_REGRESSION_SAMPLES,
|
|
@@ -1675,51 +1663,60 @@ async function extractGateDecisionsWithLlm(args) {
|
|
|
1675
1663
|
"C2) Build archive_payloads[] for archive_event candidates.",
|
|
1676
1664
|
"C3) Build graph_payloads[] for candidates with stable graph facts (independent from route).",
|
|
1677
1665
|
"Keep candidate_id exactly equal to input candidates.",
|
|
1678
|
-
"- For active_only route, C1 active_text is required and must contain valuable reusable information, not only acknowledgement/politeness.",
|
|
1679
1666
|
"- For archive_event route, C2 archive payload must include complete cause/process/result; if confidence < 0.35, prefer no archive payload for that candidate.",
|
|
1667
|
+
"- For every candidate routed to active_only or archive_event, C3 graph_payload is REQUIRED (non-optional).",
|
|
1668
|
+
"- For durable personal profile facts (family relation, birthday, anniversary, long-term schedule), C3 graph payload remains REQUIRED as a strict subset of the rule above.",
|
|
1680
1669
|
"- Preserve key entities/relations/URLs/document paths/exact numbers/timepoints from source text; do NOT over-abstract placeholders.",
|
|
1681
1670
|
`- ${stableGraphFactHint}`,
|
|
1682
1671
|
`- ${entityDictionaryPromptHint}`,
|
|
1683
1672
|
"- Concrete entities in C1/C2/C3 must follow the dictionary above and remain source-grounded; do not output generic placeholders.",
|
|
1684
|
-
"- Each C1/C2/C3 item must carry source_slice
|
|
1685
|
-
"- source_slice
|
|
1673
|
+
"- Each C1/C2/C3 item must carry source_slice.",
|
|
1674
|
+
"- source_slice must come from the [CANDIDATES] object in this same request: use the denoised source segment text of the same candidate_id (prefer normalized_text, then span).",
|
|
1675
|
+
"- In [CANDIDATES], normalized_text means denoised canonical candidate text, and span means original source slice; keep source_slice semantically consistent with these fields.",
|
|
1676
|
+
"- source_slice is a trace field for executor write path and retrieval backtracking; keep it source-faithful (do not paraphrase, truncate, or invent text).",
|
|
1686
1677
|
"C1 field requirements (active_payloads[] item):",
|
|
1687
1678
|
"- candidate_id: required; must match one input candidate_id exactly.",
|
|
1688
|
-
"- source_slice: required; denoised
|
|
1689
|
-
"-
|
|
1690
|
-
"- active_text should preserve concrete entities, decisions, blockers/risks, next actions, owners, deadlines, metrics, URLs/paths/config/version details when present.",
|
|
1679
|
+
"- source_slice: required; must be the denoised original text from this C1 candidate slice (full candidate text, DO NOT truncate or excerpt).",
|
|
1680
|
+
"- summary: required; preserve key information (cause, subject, object, and important entities grounded in the graph schema dictionary/aliases above), include stage result for process updates, and stay within 100 characters.",
|
|
1691
1681
|
"C2 field requirements (archive_payloads[] item):",
|
|
1692
1682
|
"- candidate_id: required; must match one input candidate_id exactly.",
|
|
1693
|
-
"- source_slice: required; denoised
|
|
1683
|
+
"- source_slice: required; must be the denoised original text from this C2 candidate slice.",
|
|
1694
1684
|
"- event_type: required; must be dictionary-grounded to schema eventTypes/eventTypeAliases.",
|
|
1695
|
-
"- summary: required;
|
|
1685
|
+
"- summary: required; must explain cause->process->result end-to-end and stay within 100 characters.",
|
|
1696
1686
|
"- cause: required; explain why the event happened.",
|
|
1697
1687
|
"- process: required; explain key execution/decision process.",
|
|
1698
1688
|
"- result: required; explain final result/state.",
|
|
1699
1689
|
"- entities: recommended; if present, use concrete entity names from source text.",
|
|
1700
1690
|
"- entity_types: recommended; if entities are present, provide valid schema type for each entity.",
|
|
1701
1691
|
"- relations: optional; if provided, each relation should be source-grounded and schema-compatible.",
|
|
1702
|
-
"- outcome: optional short conclusion.",
|
|
1703
1692
|
"- confidence: recommended numeric score in [0,1].",
|
|
1704
|
-
"
|
|
1705
|
-
"-
|
|
1706
|
-
"
|
|
1707
|
-
"-
|
|
1708
|
-
"-
|
|
1709
|
-
"- source_text_nav
|
|
1710
|
-
"-
|
|
1693
|
+
"C3 field requirements (graph_payloads[] item):",
|
|
1694
|
+
"- candidate_id: required; must match one input candidate_id exactly.",
|
|
1695
|
+
"- source_slice: required; must be the denoised original text from this candidate slice.",
|
|
1696
|
+
"- summary: required; must cover every entity listed in entities[] and explain key relations among entities.",
|
|
1697
|
+
"- source_text_nav: required trace object for source-location and replay; it links graph facts to the original memory/event for retrieval, citation, and debugging.",
|
|
1698
|
+
"- source_text_nav.layer: required; active_only or archive_event, and should be consistent with the candidate route/context.",
|
|
1699
|
+
"- source_text_nav.session_id: required; session id where this candidate comes from (copy from current routing context).",
|
|
1700
|
+
"- source_text_nav.source_file: required; source file identifier/path where this candidate comes from (copy from current routing context).",
|
|
1701
|
+
"- source_text_nav.source_memory_id: required; stable memory record id for this candidate in the source layer (use source_event_id when no separate memory id exists).",
|
|
1702
|
+
"- source_text_nav.source_event_id: required; stable event trace id for this candidate used for full-text backtracking.",
|
|
1703
|
+
"- entities: required array of concrete entities from source text.",
|
|
1704
|
+
"- entity_types: required map; every entity in entities[] must have a valid schema type.",
|
|
1705
|
+
"- relations: required array; each relation must be source-grounded and schema-compatible.",
|
|
1706
|
+
"- confidence: required number in [0,1].",
|
|
1707
|
+
"C3 additional requirements:",
|
|
1708
|
+
"- For archive_event candidates, extract richer source-grounded entities/relations from source_slice + cause/process/result when available (archive facts are higher-value).",
|
|
1711
1709
|
"- Key-entity protection: entities explicitly mentioned in candidate span should not be dropped.",
|
|
1712
1710
|
"- Normalize alias/cross-language references to one canonical entity when possible.",
|
|
1713
1711
|
`- ${args.relationPromptHint}`,
|
|
1714
1712
|
"- Every relation must include: source,target,type,relation_origin,evidence_span,context_chunk,confidence.",
|
|
1715
1713
|
"- If relation_origin is llm_custom, relation_definition is required.",
|
|
1716
|
-
"- If evidence_span/context_chunk/confidence is missing, do not output that relation.",
|
|
1717
1714
|
"Output structure (C1/C2/C3 are different item schemas):",
|
|
1718
|
-
"- write_plan.active_payloads[] item (C1): {candidate_id,source_slice,
|
|
1719
|
-
"- write_plan.archive_payloads[] item (C2): {candidate_id,source_slice,event_type,summary,cause,process,result,entities,entity_types,relations,
|
|
1715
|
+
"- write_plan.active_payloads[] item (C1): {candidate_id,source_slice,summary}",
|
|
1716
|
+
"- write_plan.archive_payloads[] item (C2): {candidate_id,source_slice,event_type,summary,cause,process,result,entities,entity_types,relations,confidence}",
|
|
1720
1717
|
"- write_plan.graph_payloads[] item (C3): {candidate_id,source_slice,summary,source_text_nav,entities,entity_types,relations,confidence}",
|
|
1721
1718
|
"Top-level output schema:",
|
|
1722
|
-
"{\"write_plan\":{\"active_payloads\":[{\"candidate_id\":\"c1\",\"source_slice\":\"...\",\"
|
|
1719
|
+
"{\"write_plan\":{\"active_payloads\":[{\"candidate_id\":\"c1\",\"source_slice\":\"...\",\"summary\":\"...\"}],\"archive_payloads\":[{\"candidate_id\":\"c2\",\"source_slice\":\"...\",\"event_type\":\"decision\",\"summary\":\"...\",\"cause\":\"...\",\"process\":\"...\",\"result\":\"...\",\"entities\":[\"A\"],\"entity_types\":{\"A\":\"Project\"},\"relations\":[],\"confidence\":0.82}],\"graph_payloads\":[{\"candidate_id\":\"c1\",\"source_slice\":\"...\",\"summary\":\"...\",\"source_text_nav\":{\"layer\":\"active_only\",\"session_id\":\"s1\",\"source_file\":\"daily_summary:2026-04-03.md\",\"source_memory_id\":\"evt_1\",\"source_event_id\":\"evt_1\"},\"entities\":[\"A\"],\"entity_types\":{\"A\":\"Project\"},\"relations\":[{\"source\":\"A\",\"target\":\"B\",\"type\":\"depends_on\",\"relation_origin\":\"canonical\",\"evidence_span\":\"A 婵炴挻纰嶇换鍡欑矉?B\",\"context_chunk\":\"闂佸憡顭囬崰鎰板几閸愨晝鈻斿┑鐘辫兌閻熸捇鏌?..\",\"confidence\":0.9}],\"confidence\":0.8}]}}",
|
|
1723
1720
|
"Output JSON only. Do NOT output merge_hints/graph_rewrite.",
|
|
1724
1721
|
"",
|
|
1725
1722
|
"[CANDIDATES]",
|
|
@@ -1766,7 +1763,7 @@ async function extractGateDecisionsWithLlm(args) {
|
|
|
1766
1763
|
"- For every Stage C graph_payload candidate, output one merge_hints item and one graph_rewrite item.",
|
|
1767
1764
|
"- Do not output active_payloads/archive_payloads/graph_payloads in this stage.",
|
|
1768
1765
|
"Output schema:",
|
|
1769
|
-
"{\"write_plan\":{\"merge_hints\":[{\"candidate_id\":\"c1\",\"same_event\":false,\"same_entity_pairs\":[[\"Ava\",\"
|
|
1766
|
+
"{\"write_plan\":{\"merge_hints\":[{\"candidate_id\":\"c1\",\"same_event\":false,\"same_entity_pairs\":[[\"Ava\",\"Ava\"]],\"suggested_action\":\"merge_aliases\",\"reason\":\"Alias pair refers to the same person\"}],\"graph_rewrite\":[{\"candidate_id\":\"c1\",\"rewrite_required\":true,\"rewrite_reason\":\"entity canonicalization changed summary and relations\",\"rewrite_scope\":[\"summary\",\"entities\",\"entity_types\",\"relations\"],\"graph_rewrite_payload\":{\"summary\":\"...\",\"entities\":[\"Ava\",\"Joe\"],\"entity_types\":{\"Ava\":\"Person\",\"Joe\":\"Person\"},\"relations\":[{\"source\":\"Joe\",\"target\":\"Ava\",\"type\":\"has_spouse\",\"relation_origin\":\"canonical\",\"evidence_span\":\"Joe is spouse of Ava\",\"context_chunk\":\"source snippet context\",\"confidence\":0.91}],\"confidence\":0.86}}]}}",
|
|
1770
1767
|
"Output JSON only.",
|
|
1771
1768
|
"",
|
|
1772
1769
|
"[CANDIDATES]",
|
|
@@ -1842,7 +1839,9 @@ async function rewriteGraphPayloadWithLlm(args) {
|
|
|
1842
1839
|
"- Do not output related_to.",
|
|
1843
1840
|
`- ${args.relationPromptHint}`,
|
|
1844
1841
|
"Field contract (required):",
|
|
1845
|
-
"- graph_payload.summary:
|
|
1842
|
+
"- graph_payload.summary: must cover all entities and key relations.",
|
|
1843
|
+
"- If source_text_nav.layer is active_only, summary must preserve key information (cause, subject, object and important entities grounded in the graph schema dictionary/aliases), include stage result for process updates, and stay within 100 characters.",
|
|
1844
|
+
"- summary should remain model-authored text; do not apply rule-based hard truncation after generation.",
|
|
1846
1845
|
"- graph_payload.source_text_nav: required object with layer,session_id,source_file,source_memory_id,source_event_id; fulltext_anchor optional.",
|
|
1847
1846
|
"- graph_payload.entities: required array of concrete entity names; deduplicated.",
|
|
1848
1847
|
"- graph_payload.entity_types: required map; every entity in entities should have a type from dictionary.",
|
|
@@ -1971,6 +1970,7 @@ function createSessionSync(options) {
|
|
|
1971
1970
|
try {
|
|
1972
1971
|
fallbackWrite = await options.writeStore.writeMemory({
|
|
1973
1972
|
text: tailByCharLimit(normalizedTranscript, activeTextMaxChars),
|
|
1973
|
+
sourceText: normalizedTranscript,
|
|
1974
1974
|
role: "system",
|
|
1975
1975
|
source: `sync_gate_fallback:${args.sourceFile}`,
|
|
1976
1976
|
sessionId: args.sessionId,
|
|
@@ -2015,25 +2015,8 @@ function createSessionSync(options) {
|
|
|
2015
2015
|
let graphRewriteApplied = 0;
|
|
2016
2016
|
let graphRewriteFailed = 0;
|
|
2017
2017
|
const archiveInputs = [];
|
|
2018
|
-
function
|
|
2019
|
-
|
|
2020
|
-
return entities.every(entity => normalizedSummary.includes(entity.toLowerCase()));
|
|
2021
|
-
}
|
|
2022
|
-
function buildAppendSummary(payload) {
|
|
2023
|
-
const entities = Array.isArray(payload.entities) ? payload.entities : [];
|
|
2024
|
-
const relations = Array.isArray(payload.relations) ? payload.relations : [];
|
|
2025
|
-
const current = typeof payload.summary === "string" ? payload.summary.trim() : "";
|
|
2026
|
-
const relationText = relations
|
|
2027
|
-
.slice(0, 3)
|
|
2028
|
-
.map(item => `${item.source} ${item.type} ${item.target}`)
|
|
2029
|
-
.join("; ");
|
|
2030
|
-
const base = current || (relationText
|
|
2031
|
-
? `Graph extraction captured key relations: ${relationText}.`
|
|
2032
|
-
: "Graph extraction captured key entities and relations.");
|
|
2033
|
-
if (entities.length === 0 || summaryMentionsAllEntities(base, entities)) {
|
|
2034
|
-
return base;
|
|
2035
|
-
}
|
|
2036
|
-
return `${base} Entities: ${entities.join(", ")}.`;
|
|
2018
|
+
function resolveGraphSummary(payload) {
|
|
2019
|
+
return typeof payload.summary === "string" ? payload.summary.trim() : "";
|
|
2037
2020
|
}
|
|
2038
2021
|
function buildAppendSourceTextNav(argsForAppend) {
|
|
2039
2022
|
const nav = argsForAppend.graphPayload?.source_text_nav;
|
|
@@ -2065,7 +2048,12 @@ function createSessionSync(options) {
|
|
|
2065
2048
|
if (!appendableGraph) {
|
|
2066
2049
|
return;
|
|
2067
2050
|
}
|
|
2068
|
-
const summary =
|
|
2051
|
+
const summary = resolveGraphSummary(appendableGraph);
|
|
2052
|
+
if (!summary) {
|
|
2053
|
+
graphSkipped += 1;
|
|
2054
|
+
options.logger.info(`graph_skip_reason=missing_summary source_event_id=${argsForAppend.sourceEventId}`);
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2069
2057
|
const sourceTextNav = buildAppendSourceTextNav({
|
|
2070
2058
|
sourceEventId: argsForAppend.sourceEventId,
|
|
2071
2059
|
sourceLayer: argsForAppend.sourceLayer,
|
|
@@ -2116,10 +2104,15 @@ function createSessionSync(options) {
|
|
|
2116
2104
|
}
|
|
2117
2105
|
for (const decision of routedDecisions) {
|
|
2118
2106
|
llmDecisions += 1;
|
|
2107
|
+
const decisionActiveSummary = normalizeOneLineText(decision.active_summary || "");
|
|
2108
|
+
const decisionActiveSourceSlice = (decision.active_source_slice || "").trim();
|
|
2119
2109
|
const fallbackGraphPayload = !decision.graph
|
|
2120
|
-
? buildStablePersonalFactGraph(
|
|
2110
|
+
? buildStablePersonalFactGraph(decisionActiveSummary || decision.candidate_text || normalizedTranscript)
|
|
2121
2111
|
: null;
|
|
2122
2112
|
let graphPayload = mergeGraphPayload(toAppendableGraphPayload(decision.graph), toAppendableGraphPayload(fallbackGraphPayload || undefined));
|
|
2113
|
+
if (decisionActiveSummary && graphPayload && !normalizeOneLineText(graphPayload.summary || "")) {
|
|
2114
|
+
graphPayload = { ...graphPayload, summary: decisionActiveSummary };
|
|
2115
|
+
}
|
|
2123
2116
|
const mergeReviewed = applyMergeHintToGraphPayload({
|
|
2124
2117
|
graphPayload,
|
|
2125
2118
|
mergeHint: decision.merge_hint,
|
|
@@ -2155,7 +2148,7 @@ function createSessionSync(options) {
|
|
|
2155
2148
|
const rewritten = await rewriteGraphPayloadWithLlm({
|
|
2156
2149
|
llm: { model: llmModel, apiKey: llmApiKey, baseUrl: llmBaseUrl },
|
|
2157
2150
|
transcript: normalizedTranscript,
|
|
2158
|
-
candidateText: decision.candidate_text ||
|
|
2151
|
+
candidateText: decision.candidate_text || decisionActiveSummary,
|
|
2159
2152
|
graphPayload,
|
|
2160
2153
|
rewritePlan: decision.graph_rewrite,
|
|
2161
2154
|
mergeHint: decision.merge_hint,
|
|
@@ -2199,8 +2192,14 @@ function createSessionSync(options) {
|
|
|
2199
2192
|
}
|
|
2200
2193
|
if (decision.target_layer === "active_only") {
|
|
2201
2194
|
activeAttempted += 1;
|
|
2202
|
-
const
|
|
2203
|
-
|
|
2195
|
+
const activeSummary = decisionActiveSummary
|
|
2196
|
+
|| normalizeOneLineText(graphPayload?.summary || "")
|
|
2197
|
+
|| normalizeOneLineText(decision.candidate_text || "");
|
|
2198
|
+
const activeText = tailByCharLimit(activeSummary, activeTextMaxChars);
|
|
2199
|
+
const activeSourceSlice = decisionActiveSourceSlice;
|
|
2200
|
+
if (activeSummary && graphPayload && !normalizeOneLineText(graphPayload.summary || "")) {
|
|
2201
|
+
graphPayload = { ...graphPayload, summary: activeSummary };
|
|
2202
|
+
}
|
|
2204
2203
|
if (!activeText) {
|
|
2205
2204
|
if (graphPayload) {
|
|
2206
2205
|
const graphOnlySourceEventId = buildGraphOnlySourceEventId({
|
|
@@ -2212,12 +2211,18 @@ function createSessionSync(options) {
|
|
|
2212
2211
|
sourceEventId: graphOnlySourceEventId,
|
|
2213
2212
|
sourceLayer: "active_only",
|
|
2214
2213
|
eventType: "insight",
|
|
2215
|
-
sourceText: normalizedTranscript,
|
|
2214
|
+
sourceText: decision.candidate_text || normalizedTranscript,
|
|
2216
2215
|
graphPayload,
|
|
2217
2216
|
});
|
|
2218
2217
|
}
|
|
2219
2218
|
skipped += 1;
|
|
2220
|
-
bumpReason("
|
|
2219
|
+
bumpReason("active_summary_missing");
|
|
2220
|
+
continue;
|
|
2221
|
+
}
|
|
2222
|
+
if (!activeSourceSlice) {
|
|
2223
|
+
skipped += 1;
|
|
2224
|
+
bumpReason("active_source_slice_missing");
|
|
2225
|
+
options.logger.warn(`sync_skip reason=active_source_slice_missing session=${args.sessionId} candidate_id=${decision.candidate_id || "unknown"}`);
|
|
2221
2226
|
continue;
|
|
2222
2227
|
}
|
|
2223
2228
|
if (!hasValuableActiveContent(activeText)) {
|
|
@@ -2231,7 +2236,7 @@ function createSessionSync(options) {
|
|
|
2231
2236
|
sourceEventId: graphOnlySourceEventId,
|
|
2232
2237
|
sourceLayer: "active_only",
|
|
2233
2238
|
eventType: "insight",
|
|
2234
|
-
sourceText:
|
|
2239
|
+
sourceText: activeSourceSlice,
|
|
2235
2240
|
graphPayload,
|
|
2236
2241
|
});
|
|
2237
2242
|
}
|
|
@@ -2250,6 +2255,8 @@ function createSessionSync(options) {
|
|
|
2250
2255
|
try {
|
|
2251
2256
|
writeResult = await options.writeStore.writeMemory({
|
|
2252
2257
|
text: activeText,
|
|
2258
|
+
summary: activeSummary || undefined,
|
|
2259
|
+
sourceText: activeSourceSlice,
|
|
2253
2260
|
role: "system",
|
|
2254
2261
|
source: `sync_gate_active:${args.sourceFile}`,
|
|
2255
2262
|
sessionId: args.sessionId,
|
|
@@ -2274,7 +2281,7 @@ function createSessionSync(options) {
|
|
|
2274
2281
|
sourceEventId: activeSourceEventId,
|
|
2275
2282
|
sourceLayer: "active_only",
|
|
2276
2283
|
eventType: "insight",
|
|
2277
|
-
sourceText:
|
|
2284
|
+
sourceText: activeSourceSlice,
|
|
2278
2285
|
graphPayload,
|
|
2279
2286
|
});
|
|
2280
2287
|
}
|
|
@@ -2318,7 +2325,6 @@ function createSessionSync(options) {
|
|
|
2318
2325
|
entities: decision.event.entities,
|
|
2319
2326
|
relations: decision.event.relations,
|
|
2320
2327
|
entity_types: decision.event.entity_types,
|
|
2321
|
-
outcome: decision.event.outcome,
|
|
2322
2328
|
confidence: decision.event.confidence,
|
|
2323
2329
|
session_id: args.sessionId,
|
|
2324
2330
|
source_file: args.sourceFile,
|