@remnic/core 1.1.0 → 1.1.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/dist/access-audit.d.ts +56 -0
- package/dist/access-audit.js +9 -0
- package/dist/access-cli.js +62 -45
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +16 -9
- package/dist/access-http.js +25 -17
- package/dist/access-mcp.d.ts +16 -9
- package/dist/access-mcp.js +29 -7
- package/dist/access-schema.d.ts +124 -33
- package/dist/access-schema.js +5 -1
- package/dist/{access-service-HmO1Trrx.d.ts → access-service-Br8ZydTK.d.ts} +158 -63
- package/dist/access-service.d.ts +13 -6
- package/dist/access-service.js +22 -14
- package/dist/bootstrap.d.ts +6 -3
- package/dist/briefing.d.ts +1 -0
- package/dist/briefing.js +7 -6
- package/dist/buffer-surprise-report.d.ts +70 -0
- package/dist/buffer-surprise-report.js +7 -0
- package/dist/buffer-surprise-report.js.map +1 -0
- package/dist/buffer-surprise.d.ts +98 -0
- package/dist/buffer-surprise.js +11 -0
- package/dist/buffer-surprise.js.map +1 -0
- package/dist/buffer.d.ts +100 -2
- package/dist/buffer.js +1 -1
- package/dist/calibration.js +5 -5
- package/dist/causal-behavior.js +4 -4
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +17 -16
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +4 -4
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-QNJMBKFK.js → chunk-2LGMW3DJ.js} +3 -2
- package/dist/chunk-2LGMW3DJ.js.map +1 -0
- package/dist/{chunk-QDYXG4CS.js → chunk-3FPTCC3Z.js} +4 -3
- package/dist/chunk-3FPTCC3Z.js.map +1 -0
- package/dist/chunk-3GPTTA4J.js +57 -0
- package/dist/chunk-3GPTTA4J.js.map +1 -0
- package/dist/{chunk-44ICJRF3.js → chunk-3GXCSUXR.js} +4 -4
- package/dist/{chunk-ITRLGI2T.js → chunk-3OGMS3PE.js} +2 -2
- package/dist/chunk-54V4BZWP.js +139 -0
- package/dist/chunk-54V4BZWP.js.map +1 -0
- package/dist/chunk-5JRF2PZA.js +67 -0
- package/dist/chunk-5JRF2PZA.js.map +1 -0
- package/dist/chunk-64NJRYU2.js +332 -0
- package/dist/chunk-64NJRYU2.js.map +1 -0
- package/dist/{chunk-OIT5QGG4.js → chunk-6AUUAZEX.js} +72 -2
- package/dist/chunk-6AUUAZEX.js.map +1 -0
- package/dist/{chunk-ZVBB3T7V.js → chunk-7I7FKFZH.js} +24 -22
- package/dist/chunk-7I7FKFZH.js.map +1 -0
- package/dist/chunk-AJU4PJGY.js +126 -0
- package/dist/chunk-AJU4PJGY.js.map +1 -0
- package/dist/chunk-ASAITVLA.js +64 -0
- package/dist/chunk-ASAITVLA.js.map +1 -0
- package/dist/{chunk-3QHL5ABG.js → chunk-B5WXLVDY.js} +187 -6
- package/dist/chunk-B5WXLVDY.js.map +1 -0
- package/dist/{chunk-SYUK3VLY.js → chunk-BGJGXLZ7.js} +111 -2
- package/dist/{chunk-SYUK3VLY.js.map → chunk-BGJGXLZ7.js.map} +1 -1
- package/dist/{chunk-MBJHSA7F.js → chunk-BK2EFTE2.js} +258 -13
- package/dist/chunk-BK2EFTE2.js.map +1 -0
- package/dist/chunk-C4SQJZAF.js +486 -0
- package/dist/chunk-C4SQJZAF.js.map +1 -0
- package/dist/{chunk-6UJ47TVX.js → chunk-CUPFXL3J.js} +2 -2
- package/dist/chunk-DF3RVK3X.js +119 -0
- package/dist/chunk-DF3RVK3X.js.map +1 -0
- package/dist/{chunk-37UIFYWO.js → chunk-DFTTJYSO.js} +108 -9
- package/dist/chunk-DFTTJYSO.js.map +1 -0
- package/dist/chunk-DGVM5SFL.js +69 -0
- package/dist/chunk-DGVM5SFL.js.map +1 -0
- package/dist/chunk-EIR5VLIH.js +90 -0
- package/dist/chunk-EIR5VLIH.js.map +1 -0
- package/dist/{chunk-PAORGQRI.js → chunk-EPQJM2GC.js} +37 -23
- package/dist/chunk-EPQJM2GC.js.map +1 -0
- package/dist/{chunk-GV6NLQ4X.js → chunk-F5VP6YCB.js} +374 -16
- package/dist/chunk-F5VP6YCB.js.map +1 -0
- package/dist/{chunk-6ZH4TU6I.js → chunk-FAAFWE4G.js} +2 -1
- package/dist/chunk-FAAFWE4G.js.map +1 -0
- package/dist/{chunk-7WQ6SLIE.js → chunk-FVA6TGI3.js} +2 -2
- package/dist/chunk-GDFS42HT.js +206 -0
- package/dist/chunk-GDFS42HT.js.map +1 -0
- package/dist/{chunk-MVTHXUBX.js → chunk-GKFXUTJ2.js} +479 -20
- package/dist/chunk-GKFXUTJ2.js.map +1 -0
- package/dist/{chunk-NQEVYWX6.js → chunk-HK3FGIEW.js} +209 -5
- package/dist/chunk-HK3FGIEW.js.map +1 -0
- package/dist/chunk-IISBCCWR.js +52 -0
- package/dist/chunk-IISBCCWR.js.map +1 -0
- package/dist/{chunk-WBSAYXVI.js → chunk-INXV5JBT.js} +198 -42
- package/dist/chunk-INXV5JBT.js.map +1 -0
- package/dist/chunk-JBMSGZEQ.js +441 -0
- package/dist/chunk-JBMSGZEQ.js.map +1 -0
- package/dist/{chunk-J4IYOZZ5.js → chunk-JXS5PDQ7.js} +3 -1
- package/dist/chunk-JXS5PDQ7.js.map +1 -0
- package/dist/{chunk-6LX5ORAS.js → chunk-KUB6JU6H.js} +4 -4
- package/dist/chunk-KVBLZUKV.js +173 -0
- package/dist/chunk-KVBLZUKV.js.map +1 -0
- package/dist/chunk-LBLXEFWK.js +51 -0
- package/dist/chunk-LBLXEFWK.js.map +1 -0
- package/dist/{chunk-3WHVNEN7.js → chunk-LTCGGW2D.js} +1 -1
- package/dist/chunk-LTCGGW2D.js.map +1 -0
- package/dist/{chunk-UEYA6UC7.js → chunk-NZLQTHS5.js} +25 -2
- package/dist/chunk-NZLQTHS5.js.map +1 -0
- package/dist/chunk-PVPWZSSI.js +37 -0
- package/dist/chunk-PVPWZSSI.js.map +1 -0
- package/dist/{chunk-4NRAJUDS.js → chunk-RBBWYEFJ.js} +1 -1
- package/dist/chunk-RFYAYKTD.js +146 -0
- package/dist/chunk-RFYAYKTD.js.map +1 -0
- package/dist/{chunk-DHHP2Z4X.js → chunk-RGLL5SPU.js} +2 -2
- package/dist/{chunk-3SV6CQHO.js → chunk-S3EEFKNY.js} +101 -65
- package/dist/chunk-S3EEFKNY.js.map +1 -0
- package/dist/chunk-SOBJ6NEY.js +18 -0
- package/dist/chunk-SOBJ6NEY.js.map +1 -0
- package/dist/{chunk-JIU55F3X.js → chunk-SPI27QT6.js} +2 -2
- package/dist/chunk-TVVEYCNW.js +65 -0
- package/dist/chunk-TVVEYCNW.js.map +1 -0
- package/dist/chunk-ULYOGL6R.js +322 -0
- package/dist/chunk-ULYOGL6R.js.map +1 -0
- package/dist/{chunk-47UU5PU2.js → chunk-VBVG2M5G.js} +18 -3
- package/dist/chunk-VBVG2M5G.js.map +1 -0
- package/dist/{chunk-7ECD5ATE.js → chunk-VDX363PS.js} +2 -2
- package/dist/{chunk-DEPL3635.js → chunk-VYM3VWOF.js} +1432 -188
- package/dist/chunk-VYM3VWOF.js.map +1 -0
- package/dist/{chunk-MTLYEMJB.js → chunk-WCLICCGB.js} +18 -3
- package/dist/chunk-WCLICCGB.js.map +1 -0
- package/dist/{chunk-4LACOVZX.js → chunk-WVVA7F5A.js} +2 -2
- package/dist/chunk-X6GF3FX2.js +26 -0
- package/dist/chunk-X6GF3FX2.js.map +1 -0
- package/dist/{chunk-3QFQGRHO.js → chunk-XMHBH5H6.js} +4 -4
- package/dist/{chunk-BLKTA7MM.js → chunk-YNQKWQT4.js} +50 -17
- package/dist/chunk-YNQKWQT4.js.map +1 -0
- package/dist/chunk-ZAIM4TUE.js +488 -0
- package/dist/chunk-ZAIM4TUE.js.map +1 -0
- package/dist/{chunk-N42IWANG.js → chunk-ZEM3OK2K.js} +2 -2
- package/dist/chunk-ZZTOURJI.js +91 -0
- package/dist/chunk-ZZTOURJI.js.map +1 -0
- package/dist/{cli-BneVIEvh.d.ts → cli-BkeRaYfk.d.ts} +2 -2
- package/dist/cli.d.ts +13 -6
- package/dist/cli.js +40 -29
- package/dist/config.js +1 -1
- package/dist/consolidation-operator.d.ts +41 -0
- package/dist/consolidation-operator.js +11 -0
- package/dist/consolidation-operator.js.map +1 -0
- package/dist/consolidation-provenance-check.d.ts +68 -0
- package/dist/consolidation-provenance-check.js +9 -0
- package/dist/consolidation-provenance-check.js.map +1 -0
- package/dist/consolidation-undo.d.ts +123 -0
- package/dist/consolidation-undo.js +426 -0
- package/dist/consolidation-undo.js.map +1 -0
- package/dist/{contradiction-scan-GR33PONM.js → contradiction-scan-E3GJTI4F.js} +43 -7
- package/dist/contradiction-scan-E3GJTI4F.js.map +1 -0
- package/dist/cross-namespace-budget.d.ts +133 -0
- package/dist/cross-namespace-budget.js +9 -0
- package/dist/cross-namespace-budget.js.map +1 -0
- package/dist/direct-answer-wiring.js +5 -70
- package/dist/direct-answer-wiring.js.map +1 -1
- package/dist/{engine-5TIQBYZR.js → engine-F3GOXGE5.js} +8 -7
- package/dist/engine-F3GOXGE5.js.map +1 -0
- package/dist/entity-retrieval.d.ts +1 -0
- package/dist/entity-retrieval.js +7 -6
- package/dist/explicit-capture.d.ts +6 -3
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-judge-telemetry.d.ts +113 -0
- package/dist/extraction-judge-telemetry.js +14 -0
- package/dist/extraction-judge-telemetry.js.map +1 -0
- package/dist/extraction-judge-training.d.ts +85 -0
- package/dist/extraction-judge-training.js +16 -0
- package/dist/extraction-judge-training.js.map +1 -0
- package/dist/extraction-judge.d.ts +124 -2
- package/dist/extraction-judge.js +11 -1
- package/dist/extraction.js +6 -5
- package/dist/fallback-llm.js +2 -2
- package/dist/graph-recall.d.ts +100 -0
- package/dist/graph-recall.js +8 -0
- package/dist/graph-recall.js.map +1 -0
- package/dist/graph-retrieval.d.ts +271 -0
- package/dist/graph-retrieval.js +21 -0
- package/dist/graph-retrieval.js.map +1 -0
- package/dist/importance.js +1 -1
- package/dist/index.d.ts +585 -20
- package/dist/index.js +503 -312
- package/dist/index.js.map +1 -1
- package/dist/memory-worth-bench.d.ts +51 -0
- package/dist/memory-worth-bench.js +131 -0
- package/dist/memory-worth-bench.js.map +1 -0
- package/dist/memory-worth-filter.d.ts +128 -0
- package/dist/memory-worth-filter.js +10 -0
- package/dist/memory-worth-filter.js.map +1 -0
- package/dist/memory-worth-outcomes.d.ts +118 -0
- package/dist/memory-worth-outcomes.js +9 -0
- package/dist/memory-worth-outcomes.js.map +1 -0
- package/dist/memory-worth.d.ts +102 -0
- package/dist/memory-worth.js +7 -0
- package/dist/memory-worth.js.map +1 -0
- package/dist/operator-toolkit.d.ts +40 -1
- package/dist/operator-toolkit.js +23 -14
- package/dist/{orchestrator-DRYA6_lW.d.ts → orchestrator-CmJ-NTdJ.d.ts} +233 -8
- package/dist/orchestrator.d.ts +6 -3
- package/dist/orchestrator.js +49 -39
- package/dist/page-versioning.d.ts +12 -1
- package/dist/page-versioning.js +5 -3
- package/dist/{port-C1GZFv8h.d.ts → port-BADbLZU5.d.ts} +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +5 -3
- package/dist/qmd.js +1 -1
- package/dist/reasoning-trace-recall.d.ts +90 -0
- package/dist/reasoning-trace-recall.js +13 -0
- package/dist/reasoning-trace-recall.js.map +1 -0
- package/dist/reasoning-trace-types.d.ts +54 -0
- package/dist/reasoning-trace-types.js +17 -0
- package/dist/reasoning-trace-types.js.map +1 -0
- package/dist/recall-audit-anomaly.d.ts +112 -0
- package/dist/recall-audit-anomaly.js +11 -0
- package/dist/recall-audit-anomaly.js.map +1 -0
- package/dist/recall-audit.js +5 -44
- package/dist/recall-audit.js.map +1 -1
- package/dist/recall-explain-renderer.d.ts +49 -0
- package/dist/recall-explain-renderer.js +18 -0
- package/dist/recall-explain-renderer.js.map +1 -0
- package/dist/recall-state.d.ts +12 -1
- package/dist/recall-state.js +1 -1
- package/dist/recall-xray-cli.d.ts +40 -0
- package/dist/recall-xray-cli.js +11 -0
- package/dist/recall-xray-cli.js.map +1 -0
- package/dist/recall-xray-renderer.d.ts +44 -0
- package/dist/recall-xray-renderer.js +18 -0
- package/dist/recall-xray-renderer.js.map +1 -0
- package/dist/recall-xray.d.ts +179 -0
- package/dist/recall-xray.js +13 -0
- package/dist/recall-xray.js.map +1 -0
- package/dist/resume-bundles.js +5 -5
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +17 -0
- package/dist/retrieval-tiers.js +9 -0
- package/dist/retrieval-tiers.js.map +1 -0
- package/dist/schemas.d.ts +287 -31
- package/dist/schemas.js +1 -1
- package/dist/{semantic-consolidation-DrvSYRdB.d.ts → semantic-consolidation-CxJU6MJk.d.ts} +62 -1
- package/dist/semantic-consolidation.d.ts +2 -1
- package/dist/semantic-consolidation.js +21 -7
- package/dist/semantic-rule-promotion.js +7 -6
- package/dist/semantic-rule-verifier.js +7 -6
- package/dist/storage.d.ts +82 -1
- package/dist/storage.js +6 -5
- package/dist/summarizer.js +3 -3
- package/dist/temporal-supersession.d.ts +1 -0
- package/dist/tier-migration.d.ts +2 -1
- package/dist/types.d.ts +276 -2
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +7 -6
- package/package.json +1 -1
- package/dist/chunk-37UIFYWO.js.map +0 -1
- package/dist/chunk-3QHL5ABG.js.map +0 -1
- package/dist/chunk-3SV6CQHO.js.map +0 -1
- package/dist/chunk-3WHVNEN7.js.map +0 -1
- package/dist/chunk-47UU5PU2.js.map +0 -1
- package/dist/chunk-6ZH4TU6I.js.map +0 -1
- package/dist/chunk-BLKTA7MM.js.map +0 -1
- package/dist/chunk-DEPL3635.js.map +0 -1
- package/dist/chunk-GV6NLQ4X.js.map +0 -1
- package/dist/chunk-J4IYOZZ5.js.map +0 -1
- package/dist/chunk-LAYN4LDC.js +0 -267
- package/dist/chunk-LAYN4LDC.js.map +0 -1
- package/dist/chunk-MBJHSA7F.js.map +0 -1
- package/dist/chunk-MTLYEMJB.js.map +0 -1
- package/dist/chunk-MVTHXUBX.js.map +0 -1
- package/dist/chunk-NQEVYWX6.js.map +0 -1
- package/dist/chunk-OIT5QGG4.js.map +0 -1
- package/dist/chunk-PAORGQRI.js.map +0 -1
- package/dist/chunk-QDYXG4CS.js.map +0 -1
- package/dist/chunk-QNJMBKFK.js.map +0 -1
- package/dist/chunk-UEYA6UC7.js.map +0 -1
- package/dist/chunk-UVJFDP7P.js +0 -202
- package/dist/chunk-UVJFDP7P.js.map +0 -1
- package/dist/chunk-WBSAYXVI.js.map +0 -1
- package/dist/chunk-ZVBB3T7V.js.map +0 -1
- package/dist/contradiction-scan-GR33PONM.js.map +0 -1
- /package/dist/{engine-5TIQBYZR.js.map → access-audit.js.map} +0 -0
- /package/dist/{chunk-44ICJRF3.js.map → chunk-3GXCSUXR.js.map} +0 -0
- /package/dist/{chunk-ITRLGI2T.js.map → chunk-3OGMS3PE.js.map} +0 -0
- /package/dist/{chunk-6UJ47TVX.js.map → chunk-CUPFXL3J.js.map} +0 -0
- /package/dist/{chunk-7WQ6SLIE.js.map → chunk-FVA6TGI3.js.map} +0 -0
- /package/dist/{chunk-6LX5ORAS.js.map → chunk-KUB6JU6H.js.map} +0 -0
- /package/dist/{chunk-4NRAJUDS.js.map → chunk-RBBWYEFJ.js.map} +0 -0
- /package/dist/{chunk-DHHP2Z4X.js.map → chunk-RGLL5SPU.js.map} +0 -0
- /package/dist/{chunk-JIU55F3X.js.map → chunk-SPI27QT6.js.map} +0 -0
- /package/dist/{chunk-7ECD5ATE.js.map → chunk-VDX363PS.js.map} +0 -0
- /package/dist/{chunk-4LACOVZX.js.map → chunk-WVVA7F5A.js.map} +0 -0
- /package/dist/{chunk-3QFQGRHO.js.map → chunk-XMHBH5H6.js.map} +0 -0
- /package/dist/{chunk-N42IWANG.js.map → chunk-ZEM3OK2K.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
CompoundingEngine,
|
|
3
3
|
SharedContextManager,
|
|
4
4
|
defaultTierMigrationCycleBudget
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RGLL5SPU.js";
|
|
6
6
|
import {
|
|
7
7
|
extractTopics
|
|
8
8
|
} from "./chunk-UHGBNIOS.js";
|
|
@@ -11,9 +11,6 @@ import {
|
|
|
11
11
|
applyUtilityRankingRuntimeDelta,
|
|
12
12
|
loadUtilityRuntimeValues
|
|
13
13
|
} from "./chunk-FSFEQI74.js";
|
|
14
|
-
import {
|
|
15
|
-
HourlySummarizer
|
|
16
|
-
} from "./chunk-N42IWANG.js";
|
|
17
14
|
import {
|
|
18
15
|
applyTemporalSupersession,
|
|
19
16
|
normalizeSupersessionKey,
|
|
@@ -32,11 +29,8 @@ import {
|
|
|
32
29
|
SessionObserverState
|
|
33
30
|
} from "./chunk-JR4ZC3G4.js";
|
|
34
31
|
import {
|
|
35
|
-
|
|
36
|
-
} from "./chunk-
|
|
37
|
-
import {
|
|
38
|
-
findUnresolvedEntityRefs
|
|
39
|
-
} from "./chunk-X7XN6YU4.js";
|
|
32
|
+
HourlySummarizer
|
|
33
|
+
} from "./chunk-ZEM3OK2K.js";
|
|
40
34
|
import {
|
|
41
35
|
RelevanceStore
|
|
42
36
|
} from "./chunk-5NPGSAVB.js";
|
|
@@ -66,10 +60,19 @@ import {
|
|
|
66
60
|
applyRuntimeRetrievalPolicy
|
|
67
61
|
} from "./chunk-5IZL4DCV.js";
|
|
68
62
|
import {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
} from "./chunk-
|
|
63
|
+
LastRecallStore,
|
|
64
|
+
TierMigrationStatusStore,
|
|
65
|
+
clampGraphRecallExpandedEntries
|
|
66
|
+
} from "./chunk-VBVG2M5G.js";
|
|
67
|
+
import {
|
|
68
|
+
buildXraySnapshot
|
|
69
|
+
} from "./chunk-KVBLZUKV.js";
|
|
70
|
+
import {
|
|
71
|
+
findUnresolvedEntityRefs
|
|
72
|
+
} from "./chunk-X7XN6YU4.js";
|
|
73
|
+
import {
|
|
74
|
+
applyReasoningTraceBoost
|
|
75
|
+
} from "./chunk-ZZTOURJI.js";
|
|
73
76
|
import {
|
|
74
77
|
reorderRecallResultsWithMmr
|
|
75
78
|
} from "./chunk-YDBIWGNI.js";
|
|
@@ -77,10 +80,10 @@ import {
|
|
|
77
80
|
createRecallSectionMetricRecorder
|
|
78
81
|
} from "./chunk-7DHTMOND.js";
|
|
79
82
|
import {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
buildQmdRecallCacheKey,
|
|
84
|
+
getCachedQmdRecall,
|
|
85
|
+
setCachedQmdRecall
|
|
86
|
+
} from "./chunk-YCN4BVDK.js";
|
|
84
87
|
import {
|
|
85
88
|
NegativeExampleStore
|
|
86
89
|
} from "./chunk-D654IBA6.js";
|
|
@@ -88,8 +91,9 @@ import {
|
|
|
88
91
|
evaluateMemoryActionPolicy
|
|
89
92
|
} from "./chunk-H63EDPFJ.js";
|
|
90
93
|
import {
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
applyMemoryWorthFilter,
|
|
95
|
+
buildMemoryWorthCounterMap
|
|
96
|
+
} from "./chunk-3GPTTA4J.js";
|
|
93
97
|
import {
|
|
94
98
|
hasBroadGraphIntent,
|
|
95
99
|
inferIntentFromText,
|
|
@@ -98,16 +102,28 @@ import {
|
|
|
98
102
|
planRecallMode
|
|
99
103
|
} from "./chunk-GGD5W7TB.js";
|
|
100
104
|
import {
|
|
105
|
+
classifyMemoryKind
|
|
106
|
+
} from "./chunk-YAZNBMNF.js";
|
|
107
|
+
import {
|
|
108
|
+
EXTRACTION_JUDGE_VERDICT_CATEGORY,
|
|
109
|
+
recordJudgeVerdict
|
|
110
|
+
} from "./chunk-AJU4PJGY.js";
|
|
111
|
+
import {
|
|
112
|
+
recordJudgeTrainingPair
|
|
113
|
+
} from "./chunk-DF3RVK3X.js";
|
|
114
|
+
import {
|
|
115
|
+
createDeferCountMap,
|
|
101
116
|
createVerdictCache,
|
|
117
|
+
getVerdictKind,
|
|
102
118
|
judgeFactDurability,
|
|
103
119
|
validateProcedureExtraction
|
|
104
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-C4SQJZAF.js";
|
|
105
121
|
import {
|
|
106
122
|
ExtractionEngine
|
|
107
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-S3EEFKNY.js";
|
|
108
124
|
import {
|
|
109
125
|
parseMemoryActionEligibilityContext
|
|
110
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-NZLQTHS5.js";
|
|
111
127
|
import {
|
|
112
128
|
ProfilingCollector
|
|
113
129
|
} from "./chunk-NBNN5GOB.js";
|
|
@@ -118,8 +134,8 @@ import {
|
|
|
118
134
|
LocalLlmClient
|
|
119
135
|
} from "./chunk-JL2PU6AI.js";
|
|
120
136
|
import {
|
|
121
|
-
|
|
122
|
-
} from "./chunk-
|
|
137
|
+
tryDirectAnswer
|
|
138
|
+
} from "./chunk-6AUUAZEX.js";
|
|
123
139
|
import {
|
|
124
140
|
EmbeddingFallback
|
|
125
141
|
} from "./chunk-ALXMCZEU.js";
|
|
@@ -127,20 +143,24 @@ import {
|
|
|
127
143
|
buildEntityRecallSection,
|
|
128
144
|
entityRecentTranscriptLookbackHours,
|
|
129
145
|
readRecentEntityTranscriptEntries
|
|
130
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-FVA6TGI3.js";
|
|
147
|
+
import {
|
|
148
|
+
formatDaySummaryMemories
|
|
149
|
+
} from "./chunk-GZCUW5IC.js";
|
|
131
150
|
import {
|
|
132
151
|
RoutingRulesStore,
|
|
152
|
+
expandTildePath,
|
|
133
153
|
normalizeReplaySessionKey
|
|
134
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-EPQJM2GC.js";
|
|
135
155
|
import {
|
|
136
156
|
searchVerifiedEpisodes
|
|
137
|
-
} from "./chunk-
|
|
157
|
+
} from "./chunk-CUPFXL3J.js";
|
|
138
158
|
import {
|
|
139
159
|
ThreadingManager
|
|
140
160
|
} from "./chunk-JRNQ3RNA.js";
|
|
141
161
|
import {
|
|
142
162
|
searchVerifiedSemanticRules
|
|
143
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-SPI27QT6.js";
|
|
144
164
|
import {
|
|
145
165
|
searchWorkProductLedgerEntries
|
|
146
166
|
} from "./chunk-CULXMQJH.js";
|
|
@@ -154,10 +174,10 @@ import {
|
|
|
154
174
|
createConversationIndexRuntime,
|
|
155
175
|
createSearchBackend,
|
|
156
176
|
writeConversationChunks
|
|
157
|
-
} from "./chunk-
|
|
177
|
+
} from "./chunk-7I7FKFZH.js";
|
|
158
178
|
import {
|
|
159
179
|
parseQmdExplain
|
|
160
|
-
} from "./chunk-
|
|
180
|
+
} from "./chunk-YNQKWQT4.js";
|
|
161
181
|
import {
|
|
162
182
|
PolicyRuntimeManager
|
|
163
183
|
} from "./chunk-EABGC2TL.js";
|
|
@@ -170,7 +190,10 @@ import {
|
|
|
170
190
|
import {
|
|
171
191
|
isAboveImportanceThreshold,
|
|
172
192
|
scoreImportance
|
|
173
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-JXS5PDQ7.js";
|
|
194
|
+
import {
|
|
195
|
+
launchProcessSync
|
|
196
|
+
} from "./chunk-LK6SGL53.js";
|
|
174
197
|
import {
|
|
175
198
|
collectNativeKnowledgeChunks,
|
|
176
199
|
formatNativeKnowledgeSection,
|
|
@@ -179,6 +202,9 @@ import {
|
|
|
179
202
|
import {
|
|
180
203
|
recordEvalShadowRecall
|
|
181
204
|
} from "./chunk-K6WK37A6.js";
|
|
205
|
+
import {
|
|
206
|
+
GraphIndex
|
|
207
|
+
} from "./chunk-C2EFFULQ.js";
|
|
182
208
|
import {
|
|
183
209
|
CODEX_THREAD_KEY_PREFIX
|
|
184
210
|
} from "./chunk-3PG3H5TD.js";
|
|
@@ -191,22 +217,28 @@ import {
|
|
|
191
217
|
refineCompressionGuidelineCandidateSemantically,
|
|
192
218
|
renderCompressionGuidelinesMarkdown
|
|
193
219
|
} from "./chunk-2NMMFZ5T.js";
|
|
220
|
+
import {
|
|
221
|
+
semanticChunkContent
|
|
222
|
+
} from "./chunk-KVE7R4CG.js";
|
|
223
|
+
import {
|
|
224
|
+
chunkContent
|
|
225
|
+
} from "./chunk-4WMCPJWX.js";
|
|
226
|
+
import {
|
|
227
|
+
SmartBuffer
|
|
228
|
+
} from "./chunk-JBMSGZEQ.js";
|
|
194
229
|
import {
|
|
195
230
|
buildConsolidationPrompt,
|
|
196
231
|
buildExtensionsBlockForConsolidation,
|
|
232
|
+
buildOperatorAwareConsolidationPrompt,
|
|
233
|
+
chooseConsolidationOperator,
|
|
197
234
|
findSimilarClusters,
|
|
198
235
|
materializeAfterSemanticConsolidation,
|
|
199
|
-
parseConsolidationResponse
|
|
200
|
-
|
|
236
|
+
parseConsolidationResponse,
|
|
237
|
+
parseOperatorAwareConsolidationResponse
|
|
238
|
+
} from "./chunk-BGJGXLZ7.js";
|
|
201
239
|
import {
|
|
202
240
|
FallbackLlmClient
|
|
203
|
-
} from "./chunk-
|
|
204
|
-
import {
|
|
205
|
-
GraphIndex
|
|
206
|
-
} from "./chunk-C2EFFULQ.js";
|
|
207
|
-
import {
|
|
208
|
-
chunkContent
|
|
209
|
-
} from "./chunk-4WMCPJWX.js";
|
|
241
|
+
} from "./chunk-3GXCSUXR.js";
|
|
210
242
|
import {
|
|
211
243
|
buildRecallQueryPolicy
|
|
212
244
|
} from "./chunk-6HZ6AO2P.js";
|
|
@@ -217,15 +249,12 @@ import {
|
|
|
217
249
|
import {
|
|
218
250
|
BootstrapEngine
|
|
219
251
|
} from "./chunk-N53K2EXC.js";
|
|
220
|
-
import {
|
|
221
|
-
BoxBuilder
|
|
222
|
-
} from "./chunk-URB2WSKZ.js";
|
|
223
|
-
import {
|
|
224
|
-
SmartBuffer
|
|
225
|
-
} from "./chunk-UVJFDP7P.js";
|
|
226
252
|
import {
|
|
227
253
|
isDisagreementPrompt
|
|
228
254
|
} from "./chunk-XYIK4LF6.js";
|
|
255
|
+
import {
|
|
256
|
+
BoxBuilder
|
|
257
|
+
} from "./chunk-URB2WSKZ.js";
|
|
229
258
|
import {
|
|
230
259
|
abortError,
|
|
231
260
|
isAbortError,
|
|
@@ -235,20 +264,21 @@ import {
|
|
|
235
264
|
resolveHomeDir
|
|
236
265
|
} from "./chunk-MARWOCVP.js";
|
|
237
266
|
import {
|
|
267
|
+
listTrustZoneRecords,
|
|
238
268
|
searchTrustZoneRecords
|
|
239
269
|
} from "./chunk-EQINRHYR.js";
|
|
270
|
+
import {
|
|
271
|
+
buildProcedurePersistBody
|
|
272
|
+
} from "./chunk-QDW3E4RD.js";
|
|
240
273
|
import {
|
|
241
274
|
shouldSkipImplicitExtraction
|
|
242
|
-
} from "./chunk-
|
|
275
|
+
} from "./chunk-3FPTCC3Z.js";
|
|
243
276
|
import {
|
|
244
277
|
selectRouteRule
|
|
245
|
-
} from "./chunk-
|
|
246
|
-
import {
|
|
247
|
-
buildProcedurePersistBody
|
|
248
|
-
} from "./chunk-QDW3E4RD.js";
|
|
278
|
+
} from "./chunk-2LGMW3DJ.js";
|
|
249
279
|
import {
|
|
250
280
|
searchCausalTrajectories
|
|
251
|
-
} from "./chunk-
|
|
281
|
+
} from "./chunk-RBBWYEFJ.js";
|
|
252
282
|
import {
|
|
253
283
|
canReadNamespace,
|
|
254
284
|
defaultNamespaceForPrincipal,
|
|
@@ -267,10 +297,10 @@ import {
|
|
|
267
297
|
normalizeAttributePairs,
|
|
268
298
|
normalizeEntityName,
|
|
269
299
|
parseEntityFile
|
|
270
|
-
} from "./chunk-
|
|
300
|
+
} from "./chunk-F5VP6YCB.js";
|
|
271
301
|
import {
|
|
272
302
|
confidenceTier
|
|
273
|
-
} from "./chunk-
|
|
303
|
+
} from "./chunk-LTCGGW2D.js";
|
|
274
304
|
import {
|
|
275
305
|
attachCitation,
|
|
276
306
|
hasCitationForTemplate,
|
|
@@ -291,17 +321,17 @@ import {
|
|
|
291
321
|
} from "./chunk-2ODBA7MQ.js";
|
|
292
322
|
|
|
293
323
|
// src/orchestrator.ts
|
|
294
|
-
import
|
|
324
|
+
import path7 from "path";
|
|
295
325
|
import os from "os";
|
|
296
326
|
import { createHash as createHash2, randomBytes } from "crypto";
|
|
297
327
|
import { existsSync as existsSync2 } from "fs";
|
|
298
328
|
import {
|
|
299
|
-
mkdir as
|
|
329
|
+
mkdir as mkdir5,
|
|
300
330
|
readdir as readdir3,
|
|
301
|
-
readFile as
|
|
331
|
+
readFile as readFile4,
|
|
302
332
|
stat as stat3,
|
|
303
333
|
unlink as unlink2,
|
|
304
|
-
writeFile as
|
|
334
|
+
writeFile as writeFile4
|
|
305
335
|
} from "fs/promises";
|
|
306
336
|
|
|
307
337
|
// src/migrate/from-engram.ts
|
|
@@ -878,7 +908,7 @@ async function buildProcedureRecallSection(storage, prompt, config) {
|
|
|
878
908
|
10,
|
|
879
909
|
Math.max(
|
|
880
910
|
1,
|
|
881
|
-
typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) :
|
|
911
|
+
typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) : 2
|
|
882
912
|
)
|
|
883
913
|
);
|
|
884
914
|
const all = await storage.readAllMemories();
|
|
@@ -1119,12 +1149,253 @@ async function decideSemanticDedup(content, lookup, options) {
|
|
|
1119
1149
|
};
|
|
1120
1150
|
}
|
|
1121
1151
|
|
|
1122
|
-
// src/
|
|
1152
|
+
// src/taxonomy/default-taxonomy.ts
|
|
1153
|
+
var DEFAULT_TAXONOMY = {
|
|
1154
|
+
version: 1,
|
|
1155
|
+
categories: [
|
|
1156
|
+
{
|
|
1157
|
+
id: "corrections",
|
|
1158
|
+
name: "Corrections",
|
|
1159
|
+
description: "Corrections to previously stored information",
|
|
1160
|
+
filingRules: ["Any update that supersedes a prior fact"],
|
|
1161
|
+
priority: 10,
|
|
1162
|
+
memoryCategories: ["correction"]
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
id: "principles",
|
|
1166
|
+
name: "Principles",
|
|
1167
|
+
description: "Rules, guidelines, and recurring patterns",
|
|
1168
|
+
filingRules: ["A guiding principle, rule, or skill"],
|
|
1169
|
+
priority: 20,
|
|
1170
|
+
memoryCategories: ["principle", "rule", "skill"]
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
id: "procedures",
|
|
1174
|
+
name: "Procedures",
|
|
1175
|
+
description: "Ordered multi-step workflows the user repeats",
|
|
1176
|
+
filingRules: ["A repeatable sequence of steps or commands for a task"],
|
|
1177
|
+
priority: 25,
|
|
1178
|
+
memoryCategories: ["procedure"]
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
id: "entities",
|
|
1182
|
+
name: "Entities",
|
|
1183
|
+
description: "People, organizations, places, projects",
|
|
1184
|
+
filingRules: ["Named entity with attributes"],
|
|
1185
|
+
priority: 30,
|
|
1186
|
+
memoryCategories: ["entity", "relationship"]
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
id: "decisions",
|
|
1190
|
+
name: "Decisions",
|
|
1191
|
+
description: "Choices made and their rationale",
|
|
1192
|
+
filingRules: ["A decision or commitment with reasoning"],
|
|
1193
|
+
priority: 35,
|
|
1194
|
+
memoryCategories: ["decision", "commitment"]
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
id: "preferences",
|
|
1198
|
+
name: "Preferences",
|
|
1199
|
+
description: "User likes, dislikes, and style choices",
|
|
1200
|
+
filingRules: ["Anything expressing a preference or taste"],
|
|
1201
|
+
priority: 40,
|
|
1202
|
+
memoryCategories: ["preference"]
|
|
1203
|
+
},
|
|
1204
|
+
{
|
|
1205
|
+
id: "facts",
|
|
1206
|
+
name: "Facts",
|
|
1207
|
+
description: "Objective statements about the world",
|
|
1208
|
+
filingRules: ["Any factual claim or piece of information"],
|
|
1209
|
+
priority: 50,
|
|
1210
|
+
memoryCategories: ["fact"]
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
id: "moments",
|
|
1214
|
+
name: "Moments",
|
|
1215
|
+
description: "Significant events or experiences",
|
|
1216
|
+
filingRules: ["A specific event worth remembering"],
|
|
1217
|
+
priority: 60,
|
|
1218
|
+
memoryCategories: ["moment"]
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
id: "reasoning-traces",
|
|
1222
|
+
name: "Reasoning Traces",
|
|
1223
|
+
description: "Stored intermediate reasoning / solution chains for a problem the agent previously solved",
|
|
1224
|
+
filingRules: [
|
|
1225
|
+
"A multi-step reasoning chain or solution walkthrough the agent can replay for a similar problem"
|
|
1226
|
+
],
|
|
1227
|
+
priority: 55,
|
|
1228
|
+
memoryCategories: ["reasoning_trace"]
|
|
1229
|
+
}
|
|
1230
|
+
]
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
// src/taxonomy/resolver-doc-generator.ts
|
|
1234
|
+
function generateResolverDocument(taxonomy) {
|
|
1235
|
+
const sorted = [...taxonomy.categories].sort((a, b) => {
|
|
1236
|
+
if (a.priority !== b.priority) return a.priority - b.priority;
|
|
1237
|
+
return a.id.localeCompare(b.id);
|
|
1238
|
+
});
|
|
1239
|
+
const lines = [
|
|
1240
|
+
"# Memory Filing Resolver",
|
|
1241
|
+
"",
|
|
1242
|
+
"Given a new piece of knowledge, follow this tree to determine where it belongs.",
|
|
1243
|
+
""
|
|
1244
|
+
];
|
|
1245
|
+
let step = 1;
|
|
1246
|
+
for (const cat of sorted) {
|
|
1247
|
+
lines.push(`## Step ${step}: ${cat.description}?`);
|
|
1248
|
+
lines.push("");
|
|
1249
|
+
for (const rule of cat.filingRules) {
|
|
1250
|
+
lines.push(`- ${rule}`);
|
|
1251
|
+
}
|
|
1252
|
+
lines.push("");
|
|
1253
|
+
lines.push(
|
|
1254
|
+
`> YES: File under **${cat.id}/** (priority ${cat.priority})`
|
|
1255
|
+
);
|
|
1256
|
+
lines.push("");
|
|
1257
|
+
step++;
|
|
1258
|
+
}
|
|
1259
|
+
lines.push("## Tie-breaking");
|
|
1260
|
+
lines.push("");
|
|
1261
|
+
lines.push(
|
|
1262
|
+
"If a fact could go in multiple categories, file under the one with the **lowest priority number**."
|
|
1263
|
+
);
|
|
1264
|
+
lines.push("");
|
|
1265
|
+
lines.push(`---`);
|
|
1266
|
+
lines.push(`*Generated from taxonomy v${taxonomy.version}*`);
|
|
1267
|
+
lines.push("");
|
|
1268
|
+
return lines.join("\n");
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// src/taxonomy/taxonomy-loader.ts
|
|
1272
|
+
import { readFile as readFile3, mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
1123
1273
|
import path3 from "path";
|
|
1124
|
-
|
|
1274
|
+
var TAXONOMY_DIR = ".taxonomy";
|
|
1275
|
+
var TAXONOMY_FILE = "taxonomy.json";
|
|
1276
|
+
var MAX_SLUG_LENGTH = 32;
|
|
1277
|
+
var SLUG_RE = /^[a-z][a-z0-9-]*$/;
|
|
1278
|
+
function validateSlug(slug) {
|
|
1279
|
+
if (slug.length === 0) {
|
|
1280
|
+
throw new Error("Taxonomy category ID must not be empty");
|
|
1281
|
+
}
|
|
1282
|
+
if (slug.length > MAX_SLUG_LENGTH) {
|
|
1283
|
+
throw new Error(
|
|
1284
|
+
`Taxonomy category ID "${slug}" exceeds ${MAX_SLUG_LENGTH} characters`
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
if (!SLUG_RE.test(slug)) {
|
|
1288
|
+
throw new Error(
|
|
1289
|
+
`Taxonomy category ID "${slug}" is invalid: must be lowercase letters, digits, and hyphens, starting with a letter`
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
function validateTaxonomy(taxonomy) {
|
|
1294
|
+
if (typeof taxonomy.version !== "number" || taxonomy.version < 1) {
|
|
1295
|
+
throw new Error("Taxonomy version must be a positive integer");
|
|
1296
|
+
}
|
|
1297
|
+
if (!Array.isArray(taxonomy.categories)) {
|
|
1298
|
+
throw new Error("Taxonomy categories must be an array");
|
|
1299
|
+
}
|
|
1300
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
1301
|
+
for (const cat of taxonomy.categories) {
|
|
1302
|
+
validateSlug(cat.id);
|
|
1303
|
+
if (seenIds.has(cat.id)) {
|
|
1304
|
+
throw new Error(`Duplicate taxonomy category ID: "${cat.id}"`);
|
|
1305
|
+
}
|
|
1306
|
+
seenIds.add(cat.id);
|
|
1307
|
+
if (typeof cat.name !== "string" || cat.name.trim().length === 0) {
|
|
1308
|
+
throw new Error(`Taxonomy category "${cat.id}" must have a non-empty name`);
|
|
1309
|
+
}
|
|
1310
|
+
if (typeof cat.description !== "string" || cat.description.trim().length === 0) {
|
|
1311
|
+
throw new Error(`Taxonomy category "${cat.id}" must have a non-empty description`);
|
|
1312
|
+
}
|
|
1313
|
+
if (!Array.isArray(cat.filingRules)) {
|
|
1314
|
+
throw new Error(`Taxonomy category "${cat.id}" filingRules must be an array`);
|
|
1315
|
+
}
|
|
1316
|
+
if (typeof cat.priority !== "number" || !Number.isFinite(cat.priority)) {
|
|
1317
|
+
throw new Error(`Taxonomy category "${cat.id}" must have a finite numeric priority`);
|
|
1318
|
+
}
|
|
1319
|
+
if (!Array.isArray(cat.memoryCategories)) {
|
|
1320
|
+
throw new Error(`Taxonomy category "${cat.id}" memoryCategories must be an array`);
|
|
1321
|
+
}
|
|
1322
|
+
if (cat.parentId !== void 0) {
|
|
1323
|
+
if (typeof cat.parentId !== "string") {
|
|
1324
|
+
throw new Error(`Taxonomy category "${cat.id}" parentId must be a string if set`);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
for (const cat of taxonomy.categories) {
|
|
1329
|
+
if (cat.parentId !== void 0 && !seenIds.has(cat.parentId)) {
|
|
1330
|
+
throw new Error(
|
|
1331
|
+
`Taxonomy category "${cat.id}" references unknown parentId "${cat.parentId}"`
|
|
1332
|
+
);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
async function loadTaxonomy(memoryDir) {
|
|
1337
|
+
const taxonomyPath = path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
1338
|
+
let raw;
|
|
1339
|
+
try {
|
|
1340
|
+
raw = await readFile3(taxonomyPath, "utf-8");
|
|
1341
|
+
} catch (err) {
|
|
1342
|
+
if (err instanceof Error && err.code === "ENOENT") {
|
|
1343
|
+
return structuredClone(DEFAULT_TAXONOMY);
|
|
1344
|
+
}
|
|
1345
|
+
throw err;
|
|
1346
|
+
}
|
|
1347
|
+
const parsed = JSON.parse(raw);
|
|
1348
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
1349
|
+
throw new Error("taxonomy.json must be a JSON object");
|
|
1350
|
+
}
|
|
1351
|
+
const obj = parsed;
|
|
1352
|
+
const userVersion = typeof obj.version === "number" ? obj.version : DEFAULT_TAXONOMY.version;
|
|
1353
|
+
const userCategories = Array.isArray(obj.categories) ? obj.categories : [];
|
|
1354
|
+
const userIdCounts = /* @__PURE__ */ new Map();
|
|
1355
|
+
for (const cat of userCategories) {
|
|
1356
|
+
const id = typeof cat.id === "string" ? cat.id : String(cat.id);
|
|
1357
|
+
userIdCounts.set(id, (userIdCounts.get(id) ?? 0) + 1);
|
|
1358
|
+
}
|
|
1359
|
+
const duplicateIds = [...userIdCounts.entries()].filter(([, count]) => count > 1).map(([id]) => id);
|
|
1360
|
+
if (duplicateIds.length > 0) {
|
|
1361
|
+
throw new Error(
|
|
1362
|
+
`Duplicate category IDs in taxonomy.json: ${duplicateIds.map((id) => `"${id}"`).join(", ")}`
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
const mergedMap = /* @__PURE__ */ new Map();
|
|
1366
|
+
for (const cat of DEFAULT_TAXONOMY.categories) {
|
|
1367
|
+
mergedMap.set(cat.id, { ...cat });
|
|
1368
|
+
}
|
|
1369
|
+
for (const cat of userCategories) {
|
|
1370
|
+
mergedMap.set(cat.id, cat);
|
|
1371
|
+
}
|
|
1372
|
+
const merged = {
|
|
1373
|
+
version: userVersion,
|
|
1374
|
+
categories: [...mergedMap.values()]
|
|
1375
|
+
};
|
|
1376
|
+
validateTaxonomy(merged);
|
|
1377
|
+
return merged;
|
|
1378
|
+
}
|
|
1379
|
+
async function saveTaxonomy(memoryDir, taxonomy) {
|
|
1380
|
+
validateTaxonomy(taxonomy);
|
|
1381
|
+
const dir = path3.join(memoryDir, TAXONOMY_DIR);
|
|
1382
|
+
await mkdir3(dir, { recursive: true });
|
|
1383
|
+
const filePath = path3.join(dir, TAXONOMY_FILE);
|
|
1384
|
+
await writeFile3(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
|
|
1385
|
+
}
|
|
1386
|
+
function getTaxonomyDir(memoryDir) {
|
|
1387
|
+
return path3.join(memoryDir, TAXONOMY_DIR);
|
|
1388
|
+
}
|
|
1389
|
+
function getTaxonomyFilePath(memoryDir) {
|
|
1390
|
+
return path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
// src/lcm/schema.ts
|
|
1394
|
+
import path4 from "path";
|
|
1395
|
+
import { mkdir as mkdir4 } from "fs/promises";
|
|
1125
1396
|
var LCM_SCHEMA_VERSION = 1;
|
|
1126
1397
|
function openLcmDatabase(memoryDir) {
|
|
1127
|
-
const dbPath =
|
|
1398
|
+
const dbPath = path4.join(memoryDir, "state", "lcm.sqlite");
|
|
1128
1399
|
const db = openBetterSqlite3(dbPath);
|
|
1129
1400
|
db.pragma("journal_mode = WAL");
|
|
1130
1401
|
db.pragma("busy_timeout = 5000");
|
|
@@ -1133,7 +1404,7 @@ function openLcmDatabase(memoryDir) {
|
|
|
1133
1404
|
return db;
|
|
1134
1405
|
}
|
|
1135
1406
|
async function ensureLcmStateDir(memoryDir) {
|
|
1136
|
-
await
|
|
1407
|
+
await mkdir4(path4.join(memoryDir, "state"), { recursive: true });
|
|
1137
1408
|
}
|
|
1138
1409
|
function applySchema(db) {
|
|
1139
1410
|
const versionRow = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_meta'").get();
|
|
@@ -2397,7 +2668,7 @@ function chunkTranscriptEntries(sessionKey, entries, opts) {
|
|
|
2397
2668
|
|
|
2398
2669
|
// src/conversation-index/cleanup.ts
|
|
2399
2670
|
import { readdir as readdir2, rm as rm3 } from "fs/promises";
|
|
2400
|
-
import
|
|
2671
|
+
import path5 from "path";
|
|
2401
2672
|
async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
2402
2673
|
if (!Number.isFinite(retentionDays) || retentionDays <= 0) return;
|
|
2403
2674
|
const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1e3;
|
|
@@ -2405,7 +2676,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
|
2405
2676
|
const sessions = await readdir2(rootDir, { withFileTypes: true });
|
|
2406
2677
|
for (const s of sessions) {
|
|
2407
2678
|
if (!s.isDirectory()) continue;
|
|
2408
|
-
const sessionDir =
|
|
2679
|
+
const sessionDir = path5.join(rootDir, s.name);
|
|
2409
2680
|
const dayDirs = await readdir2(sessionDir, { withFileTypes: true });
|
|
2410
2681
|
for (const d of dayDirs) {
|
|
2411
2682
|
if (!d.isDirectory()) continue;
|
|
@@ -2413,7 +2684,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
|
2413
2684
|
const dayMs = (/* @__PURE__ */ new Date(d.name + "T00:00:00.000Z")).getTime();
|
|
2414
2685
|
if (!Number.isFinite(dayMs)) continue;
|
|
2415
2686
|
if (dayMs < cutoffMs) {
|
|
2416
|
-
await rm3(
|
|
2687
|
+
await rm3(path5.join(sessionDir, d.name), { recursive: true, force: true });
|
|
2417
2688
|
}
|
|
2418
2689
|
}
|
|
2419
2690
|
try {
|
|
@@ -2429,6 +2700,264 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
|
2429
2700
|
}
|
|
2430
2701
|
}
|
|
2431
2702
|
|
|
2703
|
+
// src/coding/git-context.ts
|
|
2704
|
+
import path6 from "path";
|
|
2705
|
+
var DEFAULT_GIT_TIMEOUT_MS = 2e3;
|
|
2706
|
+
function defaultGitInvoker() {
|
|
2707
|
+
return (cwd, args) => {
|
|
2708
|
+
const result = launchProcessSync("git", args, {
|
|
2709
|
+
cwd,
|
|
2710
|
+
encoding: "utf-8",
|
|
2711
|
+
timeout: DEFAULT_GIT_TIMEOUT_MS,
|
|
2712
|
+
shell: false
|
|
2713
|
+
});
|
|
2714
|
+
if (result.error) {
|
|
2715
|
+
return { stdout: "", exitCode: 127 };
|
|
2716
|
+
}
|
|
2717
|
+
return {
|
|
2718
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
2719
|
+
exitCode: typeof result.status === "number" ? result.status : 1
|
|
2720
|
+
};
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
function stableHash(input) {
|
|
2724
|
+
let hash = 2166136261;
|
|
2725
|
+
for (let i = 0; i < input.length; i++) {
|
|
2726
|
+
hash ^= input.charCodeAt(i);
|
|
2727
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
2728
|
+
}
|
|
2729
|
+
return hash.toString(16).padStart(8, "0");
|
|
2730
|
+
}
|
|
2731
|
+
function normalizeOriginUrl(rawUrl) {
|
|
2732
|
+
let url = rawUrl.trim();
|
|
2733
|
+
if (!url) return "";
|
|
2734
|
+
if (/\.git$/i.test(url)) url = url.slice(0, -4);
|
|
2735
|
+
if (/^[A-Za-z]:[\\/]/.test(url)) {
|
|
2736
|
+
return url.toLowerCase();
|
|
2737
|
+
}
|
|
2738
|
+
const protoMatch = /^[a-z][a-z0-9+.-]*:\/\/(?:[^@/]+@)?(\[[^\]]+\]|[^/:]*)(?::(\d+))?(\/.*)?$/i.exec(url);
|
|
2739
|
+
if (protoMatch) {
|
|
2740
|
+
let host = protoMatch[1] ?? "";
|
|
2741
|
+
const wasBracketed = host.startsWith("[") && host.endsWith("]");
|
|
2742
|
+
if (wasBracketed) host = host.slice(1, -1);
|
|
2743
|
+
const port = protoMatch[2];
|
|
2744
|
+
const repoPath = (protoMatch[3] ?? "").replace(/^\/+/, "");
|
|
2745
|
+
const hostPort = port ? wasBracketed ? `[${host}]:${port}` : `${host}:${port}` : host;
|
|
2746
|
+
const prefix = hostPort.length > 0 ? hostPort : "localhost";
|
|
2747
|
+
return `${prefix}/${repoPath}`.toLowerCase();
|
|
2748
|
+
}
|
|
2749
|
+
const scpMatch = /^(?:([^@\s/]+)@)?(\[[^\]]+\]|[^:@\s/]+):(.+)$/.exec(url);
|
|
2750
|
+
if (scpMatch) {
|
|
2751
|
+
let host = scpMatch[2] ?? "";
|
|
2752
|
+
if (host.startsWith("[") && host.endsWith("]")) host = host.slice(1, -1);
|
|
2753
|
+
const repoPath = scpMatch[3] ?? "";
|
|
2754
|
+
if (repoPath.startsWith("//")) {
|
|
2755
|
+
return url.toLowerCase();
|
|
2756
|
+
}
|
|
2757
|
+
return `${host}/${repoPath.replace(/^\/+/, "")}`.toLowerCase();
|
|
2758
|
+
}
|
|
2759
|
+
return url.toLowerCase();
|
|
2760
|
+
}
|
|
2761
|
+
async function resolveGitContext(cwd, options = {}) {
|
|
2762
|
+
try {
|
|
2763
|
+
if (typeof cwd !== "string" || cwd.length === 0) return null;
|
|
2764
|
+
const expanded = expandTildePath(cwd);
|
|
2765
|
+
if (!path6.isAbsolute(expanded)) return null;
|
|
2766
|
+
const invoker = options.invoker ?? defaultGitInvoker();
|
|
2767
|
+
const topLevel = invoker(expanded, ["rev-parse", "--show-toplevel"]);
|
|
2768
|
+
if (topLevel.exitCode !== 0) return null;
|
|
2769
|
+
const rootPath = topLevel.stdout.trim();
|
|
2770
|
+
if (!rootPath) return null;
|
|
2771
|
+
const branchResult = invoker(rootPath, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
2772
|
+
let branch = null;
|
|
2773
|
+
if (branchResult.exitCode === 0) {
|
|
2774
|
+
const raw = branchResult.stdout.trim();
|
|
2775
|
+
branch = raw && raw !== "HEAD" ? raw : null;
|
|
2776
|
+
} else {
|
|
2777
|
+
const unbornRef = invoker(rootPath, ["symbolic-ref", "--quiet", "HEAD"]);
|
|
2778
|
+
if (unbornRef.exitCode === 0) {
|
|
2779
|
+
const raw = unbornRef.stdout.trim();
|
|
2780
|
+
const prefix = "refs/heads/";
|
|
2781
|
+
if (raw.startsWith(prefix)) {
|
|
2782
|
+
const candidate = raw.slice(prefix.length);
|
|
2783
|
+
if (candidate) branch = candidate;
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
const originResult = invoker(rootPath, ["remote", "get-url", "origin"]);
|
|
2788
|
+
let projectId;
|
|
2789
|
+
if (originResult.exitCode === 0) {
|
|
2790
|
+
const normalized = normalizeOriginUrl(originResult.stdout);
|
|
2791
|
+
projectId = normalized ? `origin:${stableHash(normalized)}` : `root:${stableHash(rootPath)}`;
|
|
2792
|
+
} else {
|
|
2793
|
+
projectId = `root:${stableHash(rootPath)}`;
|
|
2794
|
+
}
|
|
2795
|
+
const headRef = invoker(rootPath, ["symbolic-ref", "--quiet", "refs/remotes/origin/HEAD"]);
|
|
2796
|
+
let defaultBranch = null;
|
|
2797
|
+
if (headRef.exitCode === 0) {
|
|
2798
|
+
const raw = headRef.stdout.trim();
|
|
2799
|
+
const prefix = "refs/remotes/origin/";
|
|
2800
|
+
if (raw.startsWith(prefix)) {
|
|
2801
|
+
const candidate = raw.slice(prefix.length);
|
|
2802
|
+
if (candidate) defaultBranch = candidate;
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
return {
|
|
2806
|
+
projectId,
|
|
2807
|
+
branch,
|
|
2808
|
+
rootPath,
|
|
2809
|
+
defaultBranch
|
|
2810
|
+
};
|
|
2811
|
+
} catch {
|
|
2812
|
+
return null;
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
// src/coding/coding-namespace.ts
|
|
2817
|
+
function sanitizeFragment(input) {
|
|
2818
|
+
if (typeof input !== "string") return "";
|
|
2819
|
+
const trimmed = input.trim().toLowerCase();
|
|
2820
|
+
let out = "";
|
|
2821
|
+
let prevIsDash = true;
|
|
2822
|
+
for (let i = 0; i < trimmed.length; i += 1) {
|
|
2823
|
+
const c = trimmed[i];
|
|
2824
|
+
const cc = trimmed.charCodeAt(i);
|
|
2825
|
+
const isSafe = cc >= 48 && cc <= 57 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
|
|
2826
|
+
if (isSafe) {
|
|
2827
|
+
out += c;
|
|
2828
|
+
prevIsDash = false;
|
|
2829
|
+
} else if (!prevIsDash) {
|
|
2830
|
+
out += "-";
|
|
2831
|
+
prevIsDash = true;
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
if (out.endsWith("-")) out = out.slice(0, -1);
|
|
2835
|
+
return out;
|
|
2836
|
+
}
|
|
2837
|
+
var MAX_NAMESPACE_LEN = 64;
|
|
2838
|
+
var HASH_SUFFIX_LEN = 9;
|
|
2839
|
+
function capLength(value) {
|
|
2840
|
+
if (value.length <= MAX_NAMESPACE_LEN) return value;
|
|
2841
|
+
const hash = stableHash(value);
|
|
2842
|
+
let end = MAX_NAMESPACE_LEN - HASH_SUFFIX_LEN;
|
|
2843
|
+
while (end > 0 && value.charCodeAt(end - 1) === 45) end -= 1;
|
|
2844
|
+
return `${value.slice(0, end)}-${hash}`;
|
|
2845
|
+
}
|
|
2846
|
+
function projectNamespaceName(projectId) {
|
|
2847
|
+
const frag = sanitizeFragment(projectId);
|
|
2848
|
+
return capLength(`project-${frag || "unknown"}`);
|
|
2849
|
+
}
|
|
2850
|
+
function sanitizeBaseFragment(input) {
|
|
2851
|
+
if (typeof input !== "string") return "";
|
|
2852
|
+
const trimmed = input.trim();
|
|
2853
|
+
let out = "";
|
|
2854
|
+
let prevIsDash = true;
|
|
2855
|
+
for (let i = 0; i < trimmed.length; i += 1) {
|
|
2856
|
+
const c = trimmed[i];
|
|
2857
|
+
const cc = trimmed.charCodeAt(i);
|
|
2858
|
+
const isSafe = cc >= 48 && cc <= 57 || cc >= 65 && cc <= 90 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
|
|
2859
|
+
if (isSafe) {
|
|
2860
|
+
out += c;
|
|
2861
|
+
prevIsDash = false;
|
|
2862
|
+
} else if (!prevIsDash) {
|
|
2863
|
+
out += "-";
|
|
2864
|
+
prevIsDash = true;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
if (out.endsWith("-")) out = out.slice(0, -1);
|
|
2868
|
+
return out;
|
|
2869
|
+
}
|
|
2870
|
+
function combineNamespaces(base, overlay) {
|
|
2871
|
+
const baseFrag = sanitizeBaseFragment(base);
|
|
2872
|
+
const overlayFrag = sanitizeFragment(overlay);
|
|
2873
|
+
if (!baseFrag) return capLength(overlayFrag || "unknown");
|
|
2874
|
+
if (!overlayFrag) return capLength(baseFrag);
|
|
2875
|
+
return capLength(`${baseFrag}-${overlayFrag}`);
|
|
2876
|
+
}
|
|
2877
|
+
function branchNamespaceName(projectId, branch) {
|
|
2878
|
+
const projectFrag = sanitizeFragment(projectId);
|
|
2879
|
+
const trimmedBranch = branch.trim();
|
|
2880
|
+
const branchFrag = sanitizeFragment(trimmedBranch);
|
|
2881
|
+
const disambig = trimmedBranch.length > 0 && branchFrag !== trimmedBranch;
|
|
2882
|
+
const base = `project-${projectFrag || "unknown"}-branch-${branchFrag || "unknown"}`;
|
|
2883
|
+
const suffixed = disambig ? `${base}-${stableHash(trimmedBranch)}` : base;
|
|
2884
|
+
return capLength(suffixed);
|
|
2885
|
+
}
|
|
2886
|
+
function resolveCodingNamespaceOverlay(codingContext, config) {
|
|
2887
|
+
if (!codingContext) return null;
|
|
2888
|
+
if (!config.projectScope) return null;
|
|
2889
|
+
const projectId = typeof codingContext.projectId === "string" ? codingContext.projectId.trim() : "";
|
|
2890
|
+
if (!projectId) return null;
|
|
2891
|
+
const projectNs = projectNamespaceName(projectId);
|
|
2892
|
+
if (config.branchScope && typeof codingContext.branch === "string" && codingContext.branch.length > 0) {
|
|
2893
|
+
const branchNs = branchNamespaceName(projectId, codingContext.branch);
|
|
2894
|
+
return {
|
|
2895
|
+
namespace: branchNs,
|
|
2896
|
+
readFallbacks: [projectNs],
|
|
2897
|
+
scope: "branch"
|
|
2898
|
+
};
|
|
2899
|
+
}
|
|
2900
|
+
return {
|
|
2901
|
+
namespace: projectNs,
|
|
2902
|
+
readFallbacks: [],
|
|
2903
|
+
scope: "project"
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2906
|
+
function describeCodingScope(codingContext, config) {
|
|
2907
|
+
const projectId = codingContext?.projectId ?? null;
|
|
2908
|
+
const branch = codingContext?.branch ?? null;
|
|
2909
|
+
if (!codingContext) {
|
|
2910
|
+
return {
|
|
2911
|
+
scope: "none",
|
|
2912
|
+
projectId: null,
|
|
2913
|
+
branch: null,
|
|
2914
|
+
effectiveNamespace: null,
|
|
2915
|
+
readFallbacks: [],
|
|
2916
|
+
disabledReason: "no-context"
|
|
2917
|
+
};
|
|
2918
|
+
}
|
|
2919
|
+
if (!config.projectScope) {
|
|
2920
|
+
return {
|
|
2921
|
+
scope: "none",
|
|
2922
|
+
projectId,
|
|
2923
|
+
branch,
|
|
2924
|
+
effectiveNamespace: null,
|
|
2925
|
+
readFallbacks: [],
|
|
2926
|
+
disabledReason: "disabled"
|
|
2927
|
+
};
|
|
2928
|
+
}
|
|
2929
|
+
const trimmedId = typeof projectId === "string" ? projectId.trim() : "";
|
|
2930
|
+
if (!trimmedId) {
|
|
2931
|
+
return {
|
|
2932
|
+
scope: "none",
|
|
2933
|
+
projectId,
|
|
2934
|
+
branch,
|
|
2935
|
+
effectiveNamespace: null,
|
|
2936
|
+
readFallbacks: [],
|
|
2937
|
+
disabledReason: "empty-project"
|
|
2938
|
+
};
|
|
2939
|
+
}
|
|
2940
|
+
const overlay = resolveCodingNamespaceOverlay(codingContext, config);
|
|
2941
|
+
if (!overlay) {
|
|
2942
|
+
return {
|
|
2943
|
+
scope: "none",
|
|
2944
|
+
projectId,
|
|
2945
|
+
branch,
|
|
2946
|
+
effectiveNamespace: null,
|
|
2947
|
+
readFallbacks: [],
|
|
2948
|
+
disabledReason: "disabled"
|
|
2949
|
+
};
|
|
2950
|
+
}
|
|
2951
|
+
return {
|
|
2952
|
+
scope: overlay.scope,
|
|
2953
|
+
projectId,
|
|
2954
|
+
branch,
|
|
2955
|
+
effectiveNamespace: overlay.namespace,
|
|
2956
|
+
readFallbacks: overlay.readFallbacks,
|
|
2957
|
+
disabledReason: null
|
|
2958
|
+
};
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2432
2961
|
// src/orchestrator.ts
|
|
2433
2962
|
function dedupeEntitySynthesisEvidenceEntries(entries) {
|
|
2434
2963
|
const dedupedEvidenceEntries = [];
|
|
@@ -2493,6 +3022,20 @@ function fingerprintEntitySynthesisEvidence(entity) {
|
|
|
2493
3022
|
fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? "");
|
|
2494
3023
|
return fingerprint.digest("hex");
|
|
2495
3024
|
}
|
|
3025
|
+
function mapRecallSourceToXrayServedBy(source) {
|
|
3026
|
+
switch (source) {
|
|
3027
|
+
case "recent_scan":
|
|
3028
|
+
return "recent-scan";
|
|
3029
|
+
case "hot_qmd":
|
|
3030
|
+
case "hot_embedding":
|
|
3031
|
+
case "cold_fallback":
|
|
3032
|
+
case "none":
|
|
3033
|
+
return "hybrid";
|
|
3034
|
+
}
|
|
3035
|
+
const _exhaustive = source;
|
|
3036
|
+
void _exhaustive;
|
|
3037
|
+
return "hybrid";
|
|
3038
|
+
}
|
|
2496
3039
|
var abortRecallError = abortError;
|
|
2497
3040
|
function throwIfRecallAborted(signal, message = "recall aborted") {
|
|
2498
3041
|
throwIfAborted(signal, message);
|
|
@@ -2515,7 +3058,7 @@ async function raceRecallAbort(promise, signal, message = "recall aborted") {
|
|
|
2515
3058
|
}
|
|
2516
3059
|
var COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
2517
3060
|
function defaultWorkspaceDir() {
|
|
2518
|
-
return
|
|
3061
|
+
return path7.join(os.homedir(), ".openclaw", "workspace");
|
|
2519
3062
|
}
|
|
2520
3063
|
function sanitizeSessionKeyForFilename(sessionKey) {
|
|
2521
3064
|
const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
@@ -2683,11 +3226,11 @@ function mergeGraphExpandedResults(primary, expanded) {
|
|
|
2683
3226
|
return Array.from(mergedByPath.values());
|
|
2684
3227
|
}
|
|
2685
3228
|
function graphPathRelativeToStorage(storageDir, candidatePath) {
|
|
2686
|
-
const absolutePath =
|
|
2687
|
-
const rel =
|
|
3229
|
+
const absolutePath = path7.isAbsolute(candidatePath) ? candidatePath : path7.resolve(storageDir, candidatePath);
|
|
3230
|
+
const rel = path7.relative(storageDir, absolutePath);
|
|
2688
3231
|
if (!rel || rel === ".") return null;
|
|
2689
3232
|
if (rel.startsWith("..")) return null;
|
|
2690
|
-
return rel.split(
|
|
3233
|
+
return rel.split(path7.sep).join("/");
|
|
2691
3234
|
}
|
|
2692
3235
|
function normalizeGraphActivationScore(score) {
|
|
2693
3236
|
const bounded = Number.isFinite(score) && score > 0 ? score : 0;
|
|
@@ -2829,7 +3372,7 @@ function buildMemoryPathById(allMemsForGraph, storageDir) {
|
|
|
2829
3372
|
for (const mem of allMemsForGraph ?? []) {
|
|
2830
3373
|
const id = mem.frontmatter.id;
|
|
2831
3374
|
if (!id) continue;
|
|
2832
|
-
pathById.set(id,
|
|
3375
|
+
pathById.set(id, path7.relative(storageDir, mem.path));
|
|
2833
3376
|
}
|
|
2834
3377
|
return pathById;
|
|
2835
3378
|
}
|
|
@@ -2837,7 +3380,7 @@ function appendMemoryToGraphContext(options) {
|
|
|
2837
3380
|
if (!Array.isArray(options.allMemsForGraph)) return;
|
|
2838
3381
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
2839
3382
|
options.allMemsForGraph.push({
|
|
2840
|
-
path:
|
|
3383
|
+
path: path7.join(options.storageDir, options.memoryRelPath),
|
|
2841
3384
|
content: options.content,
|
|
2842
3385
|
frontmatter: {
|
|
2843
3386
|
id: options.memoryId,
|
|
@@ -2857,15 +3400,16 @@ function resolvePersistedMemoryRelativePath(options) {
|
|
|
2857
3400
|
const persisted = options.pathById.get(options.memoryId);
|
|
2858
3401
|
if (persisted) return persisted;
|
|
2859
3402
|
if (options.category === "correction") {
|
|
2860
|
-
return
|
|
3403
|
+
return path7.join("corrections", `${options.memoryId}.md`);
|
|
2861
3404
|
}
|
|
3405
|
+
const subtree = options.category === "procedure" ? "procedures" : options.category === "reasoning_trace" ? "reasoning-traces" : "facts";
|
|
2862
3406
|
const idParts = options.memoryId.split("-");
|
|
2863
3407
|
const maybeTimestamp = Number(idParts[1]);
|
|
2864
3408
|
if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
|
|
2865
3409
|
const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
|
|
2866
|
-
return
|
|
3410
|
+
return path7.join(subtree, day, `${options.memoryId}.md`);
|
|
2867
3411
|
}
|
|
2868
|
-
return
|
|
3412
|
+
return path7.join(subtree, `${options.memoryId}.md`);
|
|
2869
3413
|
}
|
|
2870
3414
|
var Orchestrator = class _Orchestrator {
|
|
2871
3415
|
storage;
|
|
@@ -2884,12 +3428,39 @@ var Orchestrator = class _Orchestrator {
|
|
|
2884
3428
|
localLlm;
|
|
2885
3429
|
fastLlm;
|
|
2886
3430
|
judgeVerdictCache;
|
|
2887
|
-
|
|
3431
|
+
/**
|
|
3432
|
+
* Per-orchestrator defer-counter map (issue #562, PR 2). Tracks how many
|
|
3433
|
+
* times the judge has returned `"defer"` for a given candidate content
|
|
3434
|
+
* hash so the defer cap can be enforced.
|
|
3435
|
+
*/
|
|
3436
|
+
judgeDeferCounts;
|
|
3437
|
+
/**
|
|
3438
|
+
* Side-channel: number of facts deferred in the most recent
|
|
3439
|
+
* `persistExtraction` call (issue #562, PR 2). The caller reads this after
|
|
3440
|
+
* `persistExtraction` returns to decide whether to retain buffer turns for
|
|
3441
|
+
* the next extraction pass. Not part of the return signature because many
|
|
3442
|
+
* callers already destructure `persistedIds` by position.
|
|
3443
|
+
*/
|
|
3444
|
+
lastPersistExtractionDeferredCount = 0;
|
|
3445
|
+
_fastGatewayLlm;
|
|
3446
|
+
get fastGatewayLlm() {
|
|
3447
|
+
return this._fastGatewayLlm;
|
|
3448
|
+
}
|
|
2888
3449
|
modelRegistry;
|
|
2889
3450
|
relevance;
|
|
2890
3451
|
negatives;
|
|
2891
3452
|
lastRecall;
|
|
2892
3453
|
tierMigrationStatus;
|
|
3454
|
+
/**
|
|
3455
|
+
* In-memory X-ray snapshot from the most recent `recall()` call that
|
|
3456
|
+
* was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is
|
|
3457
|
+
* per-process; later slices add CLI/HTTP/MCP surfaces that consume
|
|
3458
|
+
* this via the shared renderer. `null` until the first capture, and
|
|
3459
|
+
* NEVER overwritten by a recall that did not request capture —
|
|
3460
|
+
* requests without the flag leave prior captures intact so the
|
|
3461
|
+
* capturing caller can still read their snapshot back.
|
|
3462
|
+
*/
|
|
3463
|
+
lastXraySnapshot = null;
|
|
2893
3464
|
embeddingFallback;
|
|
2894
3465
|
conversationIndexDir;
|
|
2895
3466
|
extraction;
|
|
@@ -2905,6 +3476,16 @@ var Orchestrator = class _Orchestrator {
|
|
|
2905
3476
|
/** Lossless Context Management engine — proactive session archive + DAG summarization. */
|
|
2906
3477
|
lcmEngine = null;
|
|
2907
3478
|
rerankCache = new RerankCache();
|
|
3479
|
+
/**
|
|
3480
|
+
* Short-TTL cache for Memory Worth counter lookups so interactive recall
|
|
3481
|
+
* doesn't trigger a full `readAllMemories` scan per query. Keyed by
|
|
3482
|
+
* namespace; the filter unions across namespaces at query time. The TTL
|
|
3483
|
+
* is intentionally short (seconds, not minutes) because counters are
|
|
3484
|
+
* mutated by `recordMemoryOutcome` asynchronously and we'd rather serve
|
|
3485
|
+
* a 30-second-stale worth score than a stable-but-wrong one.
|
|
3486
|
+
*/
|
|
3487
|
+
memoryWorthCounterCache = /* @__PURE__ */ new Map();
|
|
3488
|
+
static MEMORY_WORTH_CACHE_TTL_MS = 3e4;
|
|
2908
3489
|
/**
|
|
2909
3490
|
* Per-session workspace overrides keyed by sessionKey.
|
|
2910
3491
|
* Set by the before_agent_start hook so recall() uses the correct
|
|
@@ -2912,6 +3493,14 @@ var Orchestrator = class _Orchestrator {
|
|
|
2912
3493
|
* Using a Map prevents concurrent sessions from overwriting each other.
|
|
2913
3494
|
*/
|
|
2914
3495
|
_recallWorkspaceOverrides = /* @__PURE__ */ new Map();
|
|
3496
|
+
/**
|
|
3497
|
+
* Per-session coding-agent context (issue #569). Populated by connectors at
|
|
3498
|
+
* session-start (PRs 5/6/7) via `setCodingContextForSession`. Used by both
|
|
3499
|
+
* the recall path and the write path so that memory routing respects the
|
|
3500
|
+
* project/branch scope a session is operating in (rule 42 — read + write
|
|
3501
|
+
* through the same namespace layer).
|
|
3502
|
+
*/
|
|
3503
|
+
_codingContextBySession = /* @__PURE__ */ new Map();
|
|
2915
3504
|
routingRulesStore = null;
|
|
2916
3505
|
contentHashIndex = null;
|
|
2917
3506
|
artifactSourceStatusCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -2945,6 +3534,10 @@ var Orchestrator = class _Orchestrator {
|
|
|
2945
3534
|
runtimePolicyValues = null;
|
|
2946
3535
|
utilityRuntimeValues = null;
|
|
2947
3536
|
evalShadowWriteChain = Promise.resolve();
|
|
3537
|
+
// Pending background observation-mode direct-answer annotations (#518).
|
|
3538
|
+
// Tracks fire-and-forget `annotateDirectAnswerTier` calls so callers (tests,
|
|
3539
|
+
// waitForDirectAnswerObservationIdle) can await settlement.
|
|
3540
|
+
directAnswerObservationChain = Promise.resolve();
|
|
2948
3541
|
// Initialization gate: recall() awaits this before proceeding
|
|
2949
3542
|
initPromise = null;
|
|
2950
3543
|
resolveInit = null;
|
|
@@ -2983,6 +3576,9 @@ var Orchestrator = class _Orchestrator {
|
|
|
2983
3576
|
this.deferredInitAbort = null;
|
|
2984
3577
|
}
|
|
2985
3578
|
}
|
|
3579
|
+
async disposeSearchBackendIfNeeded() {
|
|
3580
|
+
await this.qmd.dispose?.();
|
|
3581
|
+
}
|
|
2986
3582
|
/** Set per-session workspace for the next recall() call (compaction reset). @internal */
|
|
2987
3583
|
setRecallWorkspaceOverride(sessionKey, dir) {
|
|
2988
3584
|
this._recallWorkspaceOverrides.set(sessionKey, dir);
|
|
@@ -2995,10 +3591,96 @@ var Orchestrator = class _Orchestrator {
|
|
|
2995
3591
|
return resolvePrincipal(sessionKey, this.config);
|
|
2996
3592
|
}
|
|
2997
3593
|
resolveSelfNamespace(sessionKey) {
|
|
2998
|
-
|
|
3594
|
+
const base = defaultNamespaceForPrincipal(
|
|
2999
3595
|
this.resolvePrincipal(sessionKey),
|
|
3000
3596
|
this.config
|
|
3001
3597
|
);
|
|
3598
|
+
return this.applyCodingNamespaceOverlay(sessionKey, base);
|
|
3599
|
+
}
|
|
3600
|
+
/**
|
|
3601
|
+
* Attach a coding-agent context to a session (issue #569). Called by the
|
|
3602
|
+
* Claude Code / Codex / Cursor connectors at session start after
|
|
3603
|
+
* `resolveGitContext(cwd)`. The context is consulted by the recall path
|
|
3604
|
+
* and the write path so that memories route to a project- (and optionally
|
|
3605
|
+
* branch-) scoped namespace.
|
|
3606
|
+
*
|
|
3607
|
+
* Pass `null` to clear.
|
|
3608
|
+
*/
|
|
3609
|
+
setCodingContextForSession(sessionKey, codingContext) {
|
|
3610
|
+
if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
|
|
3611
|
+
if (!this._codingContextBySession) {
|
|
3612
|
+
this._codingContextBySession = /* @__PURE__ */ new Map();
|
|
3613
|
+
}
|
|
3614
|
+
if (codingContext === null) {
|
|
3615
|
+
this._codingContextBySession.delete(sessionKey);
|
|
3616
|
+
return;
|
|
3617
|
+
}
|
|
3618
|
+
this._codingContextBySession.set(sessionKey, codingContext);
|
|
3619
|
+
}
|
|
3620
|
+
/**
|
|
3621
|
+
* Read-only accessor for the coding context attached to a session. Returns
|
|
3622
|
+
* `null` when none is set. Used by `remnic doctor` and by tests.
|
|
3623
|
+
*
|
|
3624
|
+
* Defensive `_codingContextBySession` lookup — legacy orchestrator-flush
|
|
3625
|
+
* tests use `Object.create(Orchestrator.prototype)` which does not run
|
|
3626
|
+
* class-field initializers, so the Map may be undefined on stubs.
|
|
3627
|
+
*/
|
|
3628
|
+
getCodingContextForSession(sessionKey) {
|
|
3629
|
+
if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
|
|
3630
|
+
return this._codingContextBySession?.get(sessionKey) ?? null;
|
|
3631
|
+
}
|
|
3632
|
+
/**
|
|
3633
|
+
* Shared helper used by both the recall path and the write path (rule 42).
|
|
3634
|
+
*
|
|
3635
|
+
* Given a base namespace computed from the principal, returns the overlaid
|
|
3636
|
+
* coding namespace when the session has a coding context AND
|
|
3637
|
+
* `codingMode.projectScope` is true AND `namespacesEnabled` is true.
|
|
3638
|
+
* Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.
|
|
3639
|
+
*
|
|
3640
|
+
* Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with
|
|
3641
|
+
* the principal-derived `baseNamespace` rather than replacing it, so two
|
|
3642
|
+
* principals working in the same repository do not share memories through
|
|
3643
|
+
* a common `project-*` namespace.
|
|
3644
|
+
*
|
|
3645
|
+
* Namespaces-disabled gate: when `namespacesEnabled` is false, the
|
|
3646
|
+
* storage router maps every namespace to the same `memoryDir`. Returning
|
|
3647
|
+
* `project-*` in that mode would create apparent route separation with
|
|
3648
|
+
* no actual storage isolation — a false-isolation trap. In that mode we
|
|
3649
|
+
* return `baseNamespace` unchanged so coding mode degrades to the existing
|
|
3650
|
+
* unscoped behavior.
|
|
3651
|
+
*
|
|
3652
|
+
* @internal
|
|
3653
|
+
*/
|
|
3654
|
+
applyCodingNamespaceOverlay(sessionKey, baseNamespace) {
|
|
3655
|
+
if (!this.config.namespacesEnabled) return baseNamespace;
|
|
3656
|
+
const codingContext = this.getCodingContextForSession(sessionKey);
|
|
3657
|
+
const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
|
|
3658
|
+
if (!overlay) return baseNamespace;
|
|
3659
|
+
return combineNamespaces(baseNamespace, overlay.namespace);
|
|
3660
|
+
}
|
|
3661
|
+
/**
|
|
3662
|
+
* Read-side overlay: returns the list of namespaces a session should read
|
|
3663
|
+
* from, including any read fallbacks (branch → project asymmetry lands in
|
|
3664
|
+
* PR 3; PR 2 returns an empty fallbacks list).
|
|
3665
|
+
*
|
|
3666
|
+
* Returns `null` when:
|
|
3667
|
+
* - `namespacesEnabled` is false (overlay would create false isolation)
|
|
3668
|
+
* - no context attached to the session
|
|
3669
|
+
* - `codingMode.projectScope` is false (CLAUDE.md #30 escape hatch)
|
|
3670
|
+
*
|
|
3671
|
+
* The returned `namespace` / `readFallbacks` are RAW overlay fragments
|
|
3672
|
+
* (e.g. `project-origin-ab12`). Callers MUST combine them with the
|
|
3673
|
+
* principal-derived base through `combineNamespaces()` before passing to
|
|
3674
|
+
* storage, so principal isolation is preserved (rule 42).
|
|
3675
|
+
*
|
|
3676
|
+
* @internal
|
|
3677
|
+
*/
|
|
3678
|
+
applyCodingRecallOverlay(sessionKey) {
|
|
3679
|
+
if (!this.config.namespacesEnabled) return null;
|
|
3680
|
+
const codingContext = this.getCodingContextForSession(sessionKey);
|
|
3681
|
+
const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
|
|
3682
|
+
if (!overlay) return null;
|
|
3683
|
+
return { namespace: overlay.namespace, readFallbacks: overlay.readFallbacks };
|
|
3002
3684
|
}
|
|
3003
3685
|
async getStorageForNamespace(namespace) {
|
|
3004
3686
|
const ns = typeof namespace === "string" && namespace.trim().length > 0 ? namespace.trim() : this.config.defaultNamespace;
|
|
@@ -3083,7 +3765,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3083
3765
|
this.config = config;
|
|
3084
3766
|
this.profiler = new ProfilingCollector({
|
|
3085
3767
|
enabled: config.profilingEnabled,
|
|
3086
|
-
storageDir: config.profilingStorageDir ||
|
|
3768
|
+
storageDir: config.profilingStorageDir || path7.join(config.memoryDir, "profiling"),
|
|
3087
3769
|
maxTraces: config.profilingMaxTraces
|
|
3088
3770
|
});
|
|
3089
3771
|
this.storageRouter = new NamespaceStorageRouter(config);
|
|
@@ -3110,7 +3792,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3110
3792
|
this.compounding = config.compoundingEnabled ? new CompoundingEngine(config) : void 0;
|
|
3111
3793
|
this.buffer = new SmartBuffer(config, this.storage);
|
|
3112
3794
|
this.transcript = new TranscriptManager(config);
|
|
3113
|
-
this.conversationIndexDir =
|
|
3795
|
+
this.conversationIndexDir = path7.join(
|
|
3114
3796
|
config.memoryDir,
|
|
3115
3797
|
"conversation-index",
|
|
3116
3798
|
"chunks"
|
|
@@ -3134,6 +3816,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3134
3816
|
this.transcript
|
|
3135
3817
|
);
|
|
3136
3818
|
this.judgeVerdictCache = createVerdictCache();
|
|
3819
|
+
this.judgeDeferCounts = createDeferCountMap();
|
|
3137
3820
|
this.localLlm = new LocalLlmClient(config, this.modelRegistry);
|
|
3138
3821
|
this.localLlm.disableThinking = config.localLlmDisableThinking;
|
|
3139
3822
|
this.fastLlm = config.localLlmFastEnabled ? (() => {
|
|
@@ -3149,7 +3832,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3149
3832
|
client.disableThinking = true;
|
|
3150
3833
|
return client;
|
|
3151
3834
|
})() : this.localLlm;
|
|
3152
|
-
this.
|
|
3835
|
+
this._fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig) : null;
|
|
3153
3836
|
if (config.modelSource === "gateway") {
|
|
3154
3837
|
log.debug(
|
|
3155
3838
|
`orchestrator: gateway model source active` + (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : "") + (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : "")
|
|
@@ -3163,7 +3846,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3163
3846
|
this.modelRegistry
|
|
3164
3847
|
);
|
|
3165
3848
|
this.threading = new ThreadingManager(
|
|
3166
|
-
|
|
3849
|
+
path7.join(config.memoryDir, "threads"),
|
|
3167
3850
|
config.threadingGapMinutes
|
|
3168
3851
|
);
|
|
3169
3852
|
this.tmtBuilder = new TmtBuilder(config.memoryDir, {
|
|
@@ -3349,9 +4032,9 @@ var Orchestrator = class _Orchestrator {
|
|
|
3349
4032
|
* routes through the gateway chain. Otherwise uses the local fast LLM.
|
|
3350
4033
|
*/
|
|
3351
4034
|
async fastChatCompletion(messages, options) {
|
|
3352
|
-
if (this.
|
|
4035
|
+
if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
|
|
3353
4036
|
const agentId = this.config.fastGatewayAgentId || this.config.gatewayAgentId || void 0;
|
|
3354
|
-
const result2 = await this.
|
|
4037
|
+
const result2 = await this._fastGatewayLlm.chatCompletion(
|
|
3355
4038
|
messages,
|
|
3356
4039
|
{ temperature: options.temperature, maxTokens: options.maxTokens, timeoutMs: options.timeoutMs, agentId }
|
|
3357
4040
|
);
|
|
@@ -3366,7 +4049,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3366
4049
|
* Otherwise returns the local fast LLM directly.
|
|
3367
4050
|
*/
|
|
3368
4051
|
get fastLlmForRerank() {
|
|
3369
|
-
if (this.
|
|
4052
|
+
if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
|
|
3370
4053
|
return {
|
|
3371
4054
|
chatCompletion: (messages, options) => this.fastChatCompletion(messages, options ?? {})
|
|
3372
4055
|
};
|
|
@@ -3408,7 +4091,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3408
4091
|
promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled
|
|
3409
4092
|
});
|
|
3410
4093
|
if (this.config.factDeduplicationEnabled) {
|
|
3411
|
-
const stateDir =
|
|
4094
|
+
const stateDir = path7.join(this.config.memoryDir, "state");
|
|
3412
4095
|
this.contentHashIndex = new ContentHashIndex(stateDir);
|
|
3413
4096
|
await this.contentHashIndex.load();
|
|
3414
4097
|
log.info(
|
|
@@ -3437,7 +4120,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3437
4120
|
const files = await readdir3(wsDir).catch(() => []);
|
|
3438
4121
|
for (const f of files) {
|
|
3439
4122
|
if (!f.startsWith(".compaction-reset-signal-")) continue;
|
|
3440
|
-
const fp =
|
|
4123
|
+
const fp = path7.join(wsDir, f);
|
|
3441
4124
|
const s = await stat3(fp).catch(() => null);
|
|
3442
4125
|
if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
|
|
3443
4126
|
await unlink2(fp).catch(() => {
|
|
@@ -3466,6 +4149,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3466
4149
|
(entry) => entry.namespace === this.config.defaultNamespace
|
|
3467
4150
|
)?.state ?? "unknown";
|
|
3468
4151
|
if (defaultState === "missing") {
|
|
4152
|
+
await this.disposeSearchBackendIfNeeded();
|
|
3469
4153
|
this.qmd = new NoopSearchBackend();
|
|
3470
4154
|
log.warn(
|
|
3471
4155
|
"Search collection missing for Remnic memory store; disabling search retrieval for this runtime (fallback retrieval remains enabled)"
|
|
@@ -3526,10 +4210,11 @@ var Orchestrator = class _Orchestrator {
|
|
|
3526
4210
|
log.info("QMD startup sync: updating index to match current disk state");
|
|
3527
4211
|
if (this.config.namespacesEnabled) {
|
|
3528
4212
|
await this.namespaceSearchRouter.updateNamespaces(
|
|
3529
|
-
this.configuredNamespaces()
|
|
4213
|
+
this.configuredNamespaces(),
|
|
4214
|
+
{ signal }
|
|
3530
4215
|
);
|
|
3531
4216
|
} else {
|
|
3532
|
-
await this.qmd.update();
|
|
4217
|
+
await this.qmd.update({ signal });
|
|
3533
4218
|
}
|
|
3534
4219
|
log.info("QMD startup sync: complete");
|
|
3535
4220
|
this.deferredSyncSucceeded = true;
|
|
@@ -3546,7 +4231,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3546
4231
|
const warmupNs = this.config.defaultNamespace;
|
|
3547
4232
|
log.info("QMD warmup: pre-loading models with a test search");
|
|
3548
4233
|
warmupPromises.push(
|
|
3549
|
-
this.qmd.search("warmup", warmupNs, 1).then(() => {
|
|
4234
|
+
this.qmd.search("warmup", warmupNs, 1, void 0, { signal }).then(() => {
|
|
3550
4235
|
log.info("QMD warmup: complete");
|
|
3551
4236
|
}).catch((err) => {
|
|
3552
4237
|
log.debug(`QMD warmup search failed (non-fatal): ${err}`);
|
|
@@ -3686,6 +4371,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3686
4371
|
if ("available" in this.qmd) {
|
|
3687
4372
|
this.qmd.available = false;
|
|
3688
4373
|
}
|
|
4374
|
+
await this.disposeSearchBackendIfNeeded();
|
|
3689
4375
|
this.qmd = new NoopSearchBackend();
|
|
3690
4376
|
log.warn("startupSearchSync: search collection missing; disabling search (fallback retrieval remains enabled)");
|
|
3691
4377
|
return false;
|
|
@@ -3700,9 +4386,12 @@ var Orchestrator = class _Orchestrator {
|
|
|
3700
4386
|
log.info("startupSearchSync: updating index to match current disk state");
|
|
3701
4387
|
let namespacesUpdated = 0;
|
|
3702
4388
|
if (this.config.namespacesEnabled) {
|
|
3703
|
-
namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(
|
|
4389
|
+
namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(
|
|
4390
|
+
namespaces,
|
|
4391
|
+
{ signal }
|
|
4392
|
+
);
|
|
3704
4393
|
} else {
|
|
3705
|
-
await this.qmd.update(signal);
|
|
4394
|
+
await this.qmd.update({ signal });
|
|
3706
4395
|
}
|
|
3707
4396
|
if (signal?.aborted) {
|
|
3708
4397
|
log.debug("startupSearchSync: aborted after update");
|
|
@@ -3746,7 +4435,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3746
4435
|
*/
|
|
3747
4436
|
async autoRegisterDaySummaryCron() {
|
|
3748
4437
|
const home = resolveHomeDir();
|
|
3749
|
-
const jobsPath =
|
|
4438
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3750
4439
|
try {
|
|
3751
4440
|
if (!existsSync2(jobsPath)) {
|
|
3752
4441
|
log.debug(
|
|
@@ -3770,7 +4459,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3770
4459
|
}
|
|
3771
4460
|
async autoRegisterNightlyGovernanceCron() {
|
|
3772
4461
|
const home = process.env.HOME || os.homedir();
|
|
3773
|
-
const jobsPath =
|
|
4462
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3774
4463
|
try {
|
|
3775
4464
|
if (!existsSync2(jobsPath)) {
|
|
3776
4465
|
log.debug("nightly governance cron: jobs.json not found, skipping auto-register");
|
|
@@ -3792,7 +4481,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3792
4481
|
}
|
|
3793
4482
|
async autoRegisterProceduralMiningCron() {
|
|
3794
4483
|
const home = resolveHomeDir();
|
|
3795
|
-
const jobsPath =
|
|
4484
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3796
4485
|
try {
|
|
3797
4486
|
if (!existsSync2(jobsPath)) {
|
|
3798
4487
|
log.debug("procedural mining cron: jobs.json not found, skipping auto-register");
|
|
@@ -3812,7 +4501,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3812
4501
|
}
|
|
3813
4502
|
async autoRegisterContradictionScanCron() {
|
|
3814
4503
|
const home = resolveHomeDir();
|
|
3815
|
-
const jobsPath =
|
|
4504
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3816
4505
|
try {
|
|
3817
4506
|
if (!existsSync2(jobsPath)) {
|
|
3818
4507
|
log.debug("contradiction scan cron: jobs.json not found, skipping auto-register");
|
|
@@ -3848,15 +4537,15 @@ var Orchestrator = class _Orchestrator {
|
|
|
3848
4537
|
this.lastFileHygieneRunAtMs = now;
|
|
3849
4538
|
if (hygiene.rotateEnabled) {
|
|
3850
4539
|
for (const rel of hygiene.rotatePaths) {
|
|
3851
|
-
const abs =
|
|
4540
|
+
const abs = path7.isAbsolute(rel) ? rel : path7.join(this.config.workspaceDir, rel);
|
|
3852
4541
|
try {
|
|
3853
|
-
const raw = await
|
|
4542
|
+
const raw = await readFile4(abs, "utf-8");
|
|
3854
4543
|
if (raw.length > hygiene.rotateMaxBytes) {
|
|
3855
|
-
const archiveDir =
|
|
4544
|
+
const archiveDir = path7.join(
|
|
3856
4545
|
this.config.workspaceDir,
|
|
3857
4546
|
hygiene.archiveDir
|
|
3858
4547
|
);
|
|
3859
|
-
const base =
|
|
4548
|
+
const base = path7.basename(abs);
|
|
3860
4549
|
const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
|
|
3861
4550
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
3862
4551
|
filePath: abs,
|
|
@@ -3864,7 +4553,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3864
4553
|
archivePrefix: prefix,
|
|
3865
4554
|
keepTailChars: hygiene.rotateKeepTailChars
|
|
3866
4555
|
});
|
|
3867
|
-
await
|
|
4556
|
+
await writeFile4(abs, newContent, "utf-8");
|
|
3868
4557
|
}
|
|
3869
4558
|
} catch {
|
|
3870
4559
|
}
|
|
@@ -3881,8 +4570,8 @@ var Orchestrator = class _Orchestrator {
|
|
|
3881
4570
|
log.warn(w.message);
|
|
3882
4571
|
}
|
|
3883
4572
|
if (hygiene.warningsLogEnabled && warnings.length > 0) {
|
|
3884
|
-
const fp =
|
|
3885
|
-
await
|
|
4573
|
+
const fp = path7.join(this.config.memoryDir, hygiene.warningsLogPath);
|
|
4574
|
+
await mkdir5(path7.dirname(fp), { recursive: true });
|
|
3886
4575
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3887
4576
|
const block = `
|
|
3888
4577
|
|
|
@@ -3891,11 +4580,11 @@ var Orchestrator = class _Orchestrator {
|
|
|
3891
4580
|
` + warnings.map((w) => `- ${w.message}`).join("\n") + "\n";
|
|
3892
4581
|
let existing = "";
|
|
3893
4582
|
try {
|
|
3894
|
-
existing = await
|
|
4583
|
+
existing = await readFile4(fp, "utf-8");
|
|
3895
4584
|
} catch {
|
|
3896
4585
|
existing = "# Engram File Hygiene Warnings\n";
|
|
3897
4586
|
}
|
|
3898
|
-
await
|
|
4587
|
+
await writeFile4(fp, existing + block, "utf-8");
|
|
3899
4588
|
}
|
|
3900
4589
|
}
|
|
3901
4590
|
}
|
|
@@ -3979,14 +4668,15 @@ var Orchestrator = class _Orchestrator {
|
|
|
3979
4668
|
}
|
|
3980
4669
|
for (const cluster of clusters) {
|
|
3981
4670
|
try {
|
|
3982
|
-
|
|
4671
|
+
const operatorAwareEnabled = this.config.operatorAwareConsolidationEnabled === true;
|
|
4672
|
+
let prompt = operatorAwareEnabled ? buildOperatorAwareConsolidationPrompt(cluster) : buildConsolidationPrompt(cluster);
|
|
3983
4673
|
if (extensionsBlock.length > 0) {
|
|
3984
4674
|
prompt += "\n\n" + extensionsBlock;
|
|
3985
4675
|
}
|
|
3986
4676
|
const messages = [
|
|
3987
4677
|
{
|
|
3988
4678
|
role: "system",
|
|
3989
|
-
content: "You are a memory consolidation system. Output only the consolidated memory text."
|
|
4679
|
+
content: operatorAwareEnabled ? 'You are a memory consolidation system. Return ONLY a JSON object with two keys, "operator" and "output". The "operator" value MUST be one of the exact strings "merge", "update", or "split" \u2014 never a pipe-separated placeholder, never prose. The "output" value is the canonical memory text.' : "You are a memory consolidation system. Output only the consolidated memory text."
|
|
3990
4680
|
},
|
|
3991
4681
|
{ role: "user", content: prompt }
|
|
3992
4682
|
];
|
|
@@ -4012,13 +4702,31 @@ var Orchestrator = class _Orchestrator {
|
|
|
4012
4702
|
result.errors++;
|
|
4013
4703
|
continue;
|
|
4014
4704
|
}
|
|
4015
|
-
|
|
4705
|
+
let canonicalContent;
|
|
4706
|
+
let operator;
|
|
4707
|
+
if (operatorAwareEnabled) {
|
|
4708
|
+
const parsed = parseOperatorAwareConsolidationResponse(
|
|
4709
|
+
response.content,
|
|
4710
|
+
cluster
|
|
4711
|
+
);
|
|
4712
|
+
canonicalContent = parsed.output;
|
|
4713
|
+
operator = parsed.operator;
|
|
4714
|
+
} else {
|
|
4715
|
+
canonicalContent = parseConsolidationResponse(response.content);
|
|
4716
|
+
operator = chooseConsolidationOperator(cluster);
|
|
4717
|
+
}
|
|
4016
4718
|
cluster.canonicalContent = canonicalContent;
|
|
4017
4719
|
const sorted = [...cluster.memories].sort(
|
|
4018
4720
|
(a, b) => new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime()
|
|
4019
4721
|
);
|
|
4020
4722
|
const newest = sorted[0];
|
|
4021
4723
|
const lineageIds = cluster.memories.map((m) => m.frontmatter.id);
|
|
4724
|
+
const derivedFromEntries = [];
|
|
4725
|
+
for (const m of cluster.memories) {
|
|
4726
|
+
if (!m.path) continue;
|
|
4727
|
+
const entry = await this.storage.snapshotForProvenance(m.path);
|
|
4728
|
+
if (entry) derivedFromEntries.push(entry);
|
|
4729
|
+
}
|
|
4022
4730
|
const canonicalId = await this.storage.writeMemory(
|
|
4023
4731
|
newest.frontmatter.category,
|
|
4024
4732
|
canonicalContent,
|
|
@@ -4031,7 +4739,9 @@ var Orchestrator = class _Orchestrator {
|
|
|
4031
4739
|
)
|
|
4032
4740
|
],
|
|
4033
4741
|
source: "semantic-consolidation",
|
|
4034
|
-
lineage: lineageIds
|
|
4742
|
+
lineage: lineageIds,
|
|
4743
|
+
derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : void 0,
|
|
4744
|
+
derivedVia: operator
|
|
4035
4745
|
}
|
|
4036
4746
|
);
|
|
4037
4747
|
result.memoriesConsolidated++;
|
|
@@ -4273,18 +4983,18 @@ ${evidenceText}`
|
|
|
4273
4983
|
const datesToScan = [yesterday, utcToday].filter(
|
|
4274
4984
|
(v, i, a) => a.indexOf(v) === i
|
|
4275
4985
|
);
|
|
4276
|
-
const factsBaseDir =
|
|
4986
|
+
const factsBaseDir = path7.join(storage.dir, "facts");
|
|
4277
4987
|
const MAX_CHARS = 1e5;
|
|
4278
4988
|
const facts = [];
|
|
4279
4989
|
for (const date of datesToScan) {
|
|
4280
|
-
const factsDir =
|
|
4990
|
+
const factsDir = path7.join(factsBaseDir, date);
|
|
4281
4991
|
try {
|
|
4282
4992
|
const entries = await readdir3(factsDir, { withFileTypes: true });
|
|
4283
4993
|
for (const entry of entries) {
|
|
4284
4994
|
if (!entry.name.endsWith(".md")) continue;
|
|
4285
|
-
const fullPath =
|
|
4995
|
+
const fullPath = path7.join(factsDir, entry.name);
|
|
4286
4996
|
try {
|
|
4287
|
-
const raw = await
|
|
4997
|
+
const raw = await readFile4(fullPath, "utf-8");
|
|
4288
4998
|
const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
4289
4999
|
if (!fmMatch) continue;
|
|
4290
5000
|
const fmBlock = fmMatch[1];
|
|
@@ -4298,7 +5008,7 @@ ${evidenceText}`
|
|
|
4298
5008
|
facts.push({
|
|
4299
5009
|
path: fullPath,
|
|
4300
5010
|
frontmatter: {
|
|
4301
|
-
id: fm.id ||
|
|
5011
|
+
id: fm.id || path7.basename(entry.name, ".md"),
|
|
4302
5012
|
category: fm.category || "fact",
|
|
4303
5013
|
created: fm.created || "unknown",
|
|
4304
5014
|
updated: fm.updated || fm.created || "unknown",
|
|
@@ -4319,15 +5029,15 @@ ${evidenceText}`
|
|
|
4319
5029
|
(a, b) => a.frontmatter.created < b.frontmatter.created ? -1 : 1
|
|
4320
5030
|
);
|
|
4321
5031
|
const hourlySummaries = [];
|
|
4322
|
-
const hourlyBaseDir =
|
|
5032
|
+
const hourlyBaseDir = path7.join(storage.dir, "summaries", "hourly");
|
|
4323
5033
|
try {
|
|
4324
5034
|
const sessionKeys = await readdir3(hourlyBaseDir, { withFileTypes: true });
|
|
4325
5035
|
for (const sk of sessionKeys) {
|
|
4326
5036
|
if (!sk.isDirectory()) continue;
|
|
4327
5037
|
for (const date of datesToScan) {
|
|
4328
|
-
const summaryFile =
|
|
5038
|
+
const summaryFile = path7.join(hourlyBaseDir, sk.name, `${date}.md`);
|
|
4329
5039
|
try {
|
|
4330
|
-
const raw = await
|
|
5040
|
+
const raw = await readFile4(summaryFile, "utf-8");
|
|
4331
5041
|
if (raw.trim().length > 0) {
|
|
4332
5042
|
hourlySummaries.push(raw.trim());
|
|
4333
5043
|
}
|
|
@@ -4423,13 +5133,13 @@ ${evidenceText}`
|
|
|
4423
5133
|
}
|
|
4424
5134
|
async getLastGraphRecallSnapshot(namespace) {
|
|
4425
5135
|
const storage = await this.getStorage(namespace);
|
|
4426
|
-
const snapshotPath =
|
|
5136
|
+
const snapshotPath = path7.join(
|
|
4427
5137
|
storage.dir,
|
|
4428
5138
|
"state",
|
|
4429
5139
|
"last_graph_recall.json"
|
|
4430
5140
|
);
|
|
4431
5141
|
try {
|
|
4432
|
-
const raw = await
|
|
5142
|
+
const raw = await readFile4(snapshotPath, "utf-8");
|
|
4433
5143
|
const parsed = JSON.parse(raw);
|
|
4434
5144
|
if (!parsed || typeof parsed !== "object") return null;
|
|
4435
5145
|
return {
|
|
@@ -4462,9 +5172,9 @@ ${evidenceText}`
|
|
|
4462
5172
|
}
|
|
4463
5173
|
async getLastIntentSnapshot(namespace) {
|
|
4464
5174
|
const storage = await this.getStorage(namespace);
|
|
4465
|
-
const snapshotPath =
|
|
5175
|
+
const snapshotPath = path7.join(storage.dir, "state", "last_intent.json");
|
|
4466
5176
|
try {
|
|
4467
|
-
const raw = await
|
|
5177
|
+
const raw = await readFile4(snapshotPath, "utf-8");
|
|
4468
5178
|
const parsed = JSON.parse(raw);
|
|
4469
5179
|
if (!parsed || typeof parsed !== "object") return null;
|
|
4470
5180
|
const graphDecision = parsed.graphDecision && typeof parsed.graphDecision === "object" ? parsed.graphDecision : void 0;
|
|
@@ -4495,13 +5205,13 @@ ${evidenceText}`
|
|
|
4495
5205
|
}
|
|
4496
5206
|
async getLastQmdRecallSnapshot(namespace) {
|
|
4497
5207
|
const storage = await this.getStorage(namespace);
|
|
4498
|
-
const snapshotPath =
|
|
5208
|
+
const snapshotPath = path7.join(
|
|
4499
5209
|
storage.dir,
|
|
4500
5210
|
"state",
|
|
4501
5211
|
"last_qmd_recall.json"
|
|
4502
5212
|
);
|
|
4503
5213
|
try {
|
|
4504
|
-
const raw = await
|
|
5214
|
+
const raw = await readFile4(snapshotPath, "utf-8");
|
|
4505
5215
|
const parsed = JSON.parse(raw);
|
|
4506
5216
|
if (!parsed || typeof parsed !== "object") return null;
|
|
4507
5217
|
return {
|
|
@@ -4647,7 +5357,7 @@ ${r.snippet.trim()}
|
|
|
4647
5357
|
const entries = await readdir3(dir, { withFileTypes: true });
|
|
4648
5358
|
let total = 0;
|
|
4649
5359
|
for (const entry of entries) {
|
|
4650
|
-
const fullPath =
|
|
5360
|
+
const fullPath = path7.join(dir, entry.name);
|
|
4651
5361
|
if (entry.isDirectory()) {
|
|
4652
5362
|
total += await this.countConversationChunkDocs(fullPath);
|
|
4653
5363
|
continue;
|
|
@@ -4918,11 +5628,24 @@ ${r.snippet.trim()}
|
|
|
4918
5628
|
reject(new Error("recall timeout"));
|
|
4919
5629
|
}, RECALL_TIMEOUT_MS);
|
|
4920
5630
|
});
|
|
5631
|
+
let recallResult;
|
|
4921
5632
|
try {
|
|
4922
|
-
|
|
5633
|
+
recallResult = await Promise.race([recallPromise, timeoutPromise]);
|
|
4923
5634
|
} finally {
|
|
4924
5635
|
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
4925
5636
|
}
|
|
5637
|
+
if (this.config.recallDirectAnswerEnabled && sessionKey) {
|
|
5638
|
+
try {
|
|
5639
|
+
this.enqueueDirectAnswerObservation(
|
|
5640
|
+
prompt,
|
|
5641
|
+
sessionKey,
|
|
5642
|
+
options.namespace?.trim() || void 0
|
|
5643
|
+
);
|
|
5644
|
+
} catch (err) {
|
|
5645
|
+
log.debug(`direct-answer observation setup failed: ${err}`);
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
return recallResult;
|
|
4926
5649
|
} catch (err) {
|
|
4927
5650
|
this.logRecallFailure(err);
|
|
4928
5651
|
this.profiler.endTrace();
|
|
@@ -4931,6 +5654,183 @@ ${r.snippet.trim()}
|
|
|
4931
5654
|
options.abortSignal?.removeEventListener("abort", onAbort);
|
|
4932
5655
|
}
|
|
4933
5656
|
}
|
|
5657
|
+
/**
|
|
5658
|
+
* Return the most recent X-ray snapshot captured during a
|
|
5659
|
+
* `recall()` call that passed `xrayCapture: true` (issue #570 PR 1).
|
|
5660
|
+
* Returns `null` when no such capture has occurred on this
|
|
5661
|
+
* orchestrator instance. Returned snapshot is a deep copy so
|
|
5662
|
+
* caller mutation cannot tear the stored value.
|
|
5663
|
+
*/
|
|
5664
|
+
getLastXraySnapshot() {
|
|
5665
|
+
if (!this.lastXraySnapshot) return null;
|
|
5666
|
+
return structuredClone(this.lastXraySnapshot);
|
|
5667
|
+
}
|
|
5668
|
+
/** Clear the captured X-ray snapshot. Exposed for tests / explicit reset. */
|
|
5669
|
+
clearLastXraySnapshot() {
|
|
5670
|
+
this.lastXraySnapshot = null;
|
|
5671
|
+
}
|
|
5672
|
+
/**
|
|
5673
|
+
* Await the in-flight observation-mode direct-answer annotation chain.
|
|
5674
|
+
* Resolves to true when settled, false on timeout.
|
|
5675
|
+
*/
|
|
5676
|
+
async waitForDirectAnswerObservationIdle(timeoutMs = 6e4) {
|
|
5677
|
+
let timeoutHandle = null;
|
|
5678
|
+
try {
|
|
5679
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
5680
|
+
timeoutHandle = setTimeout(() => resolve("timeout"), timeoutMs);
|
|
5681
|
+
});
|
|
5682
|
+
const result = await Promise.race([
|
|
5683
|
+
this.directAnswerObservationChain.then(() => "ok"),
|
|
5684
|
+
timeoutPromise
|
|
5685
|
+
]);
|
|
5686
|
+
if (result === "timeout") {
|
|
5687
|
+
log.warn(
|
|
5688
|
+
`waitForDirectAnswerObservationIdle timed out after ${timeoutMs}ms`
|
|
5689
|
+
);
|
|
5690
|
+
return false;
|
|
5691
|
+
}
|
|
5692
|
+
return true;
|
|
5693
|
+
} finally {
|
|
5694
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
5695
|
+
}
|
|
5696
|
+
}
|
|
5697
|
+
enqueueDirectAnswerObservation(prompt, sessionKey, namespaceOverride) {
|
|
5698
|
+
const expectedSnapshot = this.lastRecall.get(sessionKey);
|
|
5699
|
+
if (expectedSnapshot === null) return;
|
|
5700
|
+
if (expectedSnapshot.plannerMode === "no_recall") return;
|
|
5701
|
+
const principal = resolvePrincipal(sessionKey, this.config);
|
|
5702
|
+
const observationCodingOverlay = namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config) ? null : this.applyCodingRecallOverlay(sessionKey);
|
|
5703
|
+
const observationPrincipalSelf = defaultNamespaceForPrincipal(principal, this.config);
|
|
5704
|
+
const observationCodingSelf = observationCodingOverlay ? combineNamespaces(observationPrincipalSelf, observationCodingOverlay.namespace) : null;
|
|
5705
|
+
let observationNamespaces;
|
|
5706
|
+
if (namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)) {
|
|
5707
|
+
observationNamespaces = [namespaceOverride];
|
|
5708
|
+
} else if (observationCodingOverlay && observationCodingSelf) {
|
|
5709
|
+
const base = recallNamespacesForPrincipal(principal, this.config);
|
|
5710
|
+
const mapped = base.map(
|
|
5711
|
+
(ns) => ns === observationPrincipalSelf ? observationCodingSelf : ns
|
|
5712
|
+
);
|
|
5713
|
+
const fallbackNs = observationCodingOverlay.readFallbacks.map(
|
|
5714
|
+
(fallback) => combineNamespaces(observationPrincipalSelf, fallback)
|
|
5715
|
+
);
|
|
5716
|
+
observationNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
|
|
5717
|
+
} else {
|
|
5718
|
+
observationNamespaces = recallNamespacesForPrincipal(principal, this.config);
|
|
5719
|
+
}
|
|
5720
|
+
const observationQueryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {
|
|
5721
|
+
cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,
|
|
5722
|
+
cronRecallNormalizedQueryMaxChars: this.config.cronRecallNormalizedQueryMaxChars,
|
|
5723
|
+
cronRecallInstructionHeavyTokenCap: this.effectiveCronRecallInstructionHeavyTokenCap(),
|
|
5724
|
+
cronConversationRecallMode: this.config.cronConversationRecallMode
|
|
5725
|
+
});
|
|
5726
|
+
const observationQuery = observationQueryPolicy.retrievalQuery || prompt;
|
|
5727
|
+
const expectedIdentity = {
|
|
5728
|
+
writeNonce: expectedSnapshot.writeNonce,
|
|
5729
|
+
traceId: expectedSnapshot.traceId,
|
|
5730
|
+
recordedAt: expectedSnapshot.recordedAt
|
|
5731
|
+
};
|
|
5732
|
+
const previous = this.directAnswerObservationChain;
|
|
5733
|
+
this.directAnswerObservationChain = previous.catch(() => void 0).then(async () => {
|
|
5734
|
+
try {
|
|
5735
|
+
await this.annotateDirectAnswerTier(
|
|
5736
|
+
observationQuery,
|
|
5737
|
+
sessionKey,
|
|
5738
|
+
observationNamespaces,
|
|
5739
|
+
expectedIdentity,
|
|
5740
|
+
void 0
|
|
5741
|
+
);
|
|
5742
|
+
} catch (err) {
|
|
5743
|
+
log.debug(`direct-answer observation chain error: ${err}`);
|
|
5744
|
+
}
|
|
5745
|
+
});
|
|
5746
|
+
}
|
|
5747
|
+
async annotateDirectAnswerTier(prompt, sessionKey, namespaces, expectedIdentity, _parentAbortSignal) {
|
|
5748
|
+
const tierStart = Date.now();
|
|
5749
|
+
try {
|
|
5750
|
+
if (namespaces.length === 0) return;
|
|
5751
|
+
const trustZoneByNsAndRecordId = /* @__PURE__ */ new Map();
|
|
5752
|
+
const trustZoneKey = (ns, recordId) => `${ns}\0${recordId}`;
|
|
5753
|
+
const scopedStorages = /* @__PURE__ */ new Map();
|
|
5754
|
+
for (const ns of namespaces) {
|
|
5755
|
+
const storage = await this.storageRouter.storageFor(ns);
|
|
5756
|
+
scopedStorages.set(ns, storage);
|
|
5757
|
+
const trustZones = await listTrustZoneRecords({
|
|
5758
|
+
memoryDir: storage.dir,
|
|
5759
|
+
trustZoneStoreDir: this.config.trustZoneStoreDir,
|
|
5760
|
+
limit: 200
|
|
5761
|
+
}).catch(() => ({
|
|
5762
|
+
allRecords: []
|
|
5763
|
+
}));
|
|
5764
|
+
for (const record of trustZones.allRecords ?? []) {
|
|
5765
|
+
trustZoneByNsAndRecordId.set(
|
|
5766
|
+
trustZoneKey(ns, record.recordId),
|
|
5767
|
+
record.zone
|
|
5768
|
+
);
|
|
5769
|
+
}
|
|
5770
|
+
}
|
|
5771
|
+
const memoryNamespaceByPath = /* @__PURE__ */ new Map();
|
|
5772
|
+
const memoryNamespaceById = /* @__PURE__ */ new Map();
|
|
5773
|
+
let candidatesConsidered = 0;
|
|
5774
|
+
const sources = {
|
|
5775
|
+
taxonomy: DEFAULT_TAXONOMY,
|
|
5776
|
+
listCandidateMemories: async (options) => {
|
|
5777
|
+
const targetNs = options.namespace;
|
|
5778
|
+
const storage = scopedStorages.get(targetNs) ?? await this.storageRouter.storageFor(targetNs);
|
|
5779
|
+
const all = await storage.readAllMemories();
|
|
5780
|
+
const active = [];
|
|
5781
|
+
for (const m of all) {
|
|
5782
|
+
if ((m.frontmatter.status ?? "active") === "active") {
|
|
5783
|
+
active.push(m);
|
|
5784
|
+
memoryNamespaceByPath.set(m.path, targetNs);
|
|
5785
|
+
if (m.frontmatter.id) {
|
|
5786
|
+
memoryNamespaceById.set(m.frontmatter.id, targetNs);
|
|
5787
|
+
}
|
|
5788
|
+
}
|
|
5789
|
+
}
|
|
5790
|
+
candidatesConsidered += active.length;
|
|
5791
|
+
return active;
|
|
5792
|
+
},
|
|
5793
|
+
trustZoneFor: async (memoryId) => {
|
|
5794
|
+
const ns = memoryNamespaceById.get(memoryId);
|
|
5795
|
+
if (!ns) return null;
|
|
5796
|
+
return trustZoneByNsAndRecordId.get(
|
|
5797
|
+
trustZoneKey(ns, memoryId)
|
|
5798
|
+
) ?? null;
|
|
5799
|
+
},
|
|
5800
|
+
importanceFor: (memory) => typeof memory.frontmatter.importance?.score === "number" ? memory.frontmatter.importance.score : 0
|
|
5801
|
+
};
|
|
5802
|
+
let result;
|
|
5803
|
+
for (const ns of namespaces) {
|
|
5804
|
+
const r = await tryDirectAnswer({
|
|
5805
|
+
query: prompt,
|
|
5806
|
+
namespace: ns,
|
|
5807
|
+
config: this.config,
|
|
5808
|
+
sources
|
|
5809
|
+
});
|
|
5810
|
+
if (r.eligible && r.winner) {
|
|
5811
|
+
result = r;
|
|
5812
|
+
break;
|
|
5813
|
+
}
|
|
5814
|
+
}
|
|
5815
|
+
if (!result?.eligible || !result?.winner) return;
|
|
5816
|
+
const explain = {
|
|
5817
|
+
tier: "direct-answer",
|
|
5818
|
+
tierReason: result.narrative,
|
|
5819
|
+
filteredBy: result.filteredBy,
|
|
5820
|
+
candidatesConsidered,
|
|
5821
|
+
latencyMs: Date.now() - tierStart,
|
|
5822
|
+
sourceAnchors: [{ path: result.winner.memory.path }]
|
|
5823
|
+
};
|
|
5824
|
+
await this.lastRecall.annotateTierExplain(
|
|
5825
|
+
sessionKey,
|
|
5826
|
+
explain,
|
|
5827
|
+
expectedIdentity
|
|
5828
|
+
);
|
|
5829
|
+
} catch (err) {
|
|
5830
|
+
if (err instanceof Error && err.name === "AbortError") return;
|
|
5831
|
+
log.debug(`direct-answer observation failed: ${err}`);
|
|
5832
|
+
}
|
|
5833
|
+
}
|
|
4934
5834
|
logRecallFailure(err) {
|
|
4935
5835
|
const now = Date.now();
|
|
4936
5836
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -5334,7 +6234,7 @@ ${r.snippet.trim()}
|
|
|
5334
6234
|
0
|
|
5335
6235
|
);
|
|
5336
6236
|
seedPaths.push(
|
|
5337
|
-
...seedRelativePaths.map((rel) =>
|
|
6237
|
+
...seedRelativePaths.map((rel) => path7.join(storage.dir, rel))
|
|
5338
6238
|
);
|
|
5339
6239
|
const seedSet = new Set(seedRelativePaths);
|
|
5340
6240
|
const expanded = await this.graphIndexFor(storage).spreadingActivation(
|
|
@@ -5344,7 +6244,7 @@ ${r.snippet.trim()}
|
|
|
5344
6244
|
if (expanded.length === 0) continue;
|
|
5345
6245
|
for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
|
|
5346
6246
|
if (seedSet.has(candidate.path)) continue;
|
|
5347
|
-
const memoryPath =
|
|
6247
|
+
const memoryPath = path7.resolve(storage.dir, candidate.path);
|
|
5348
6248
|
const memory = await storage.readMemoryByPath(memoryPath);
|
|
5349
6249
|
if (!memory) continue;
|
|
5350
6250
|
if (isArtifactMemoryPath(memory.path)) continue;
|
|
@@ -5368,7 +6268,7 @@ ${r.snippet.trim()}
|
|
|
5368
6268
|
path: memory.path,
|
|
5369
6269
|
score,
|
|
5370
6270
|
namespace,
|
|
5371
|
-
seed:
|
|
6271
|
+
seed: path7.resolve(storage.dir, candidate.seed),
|
|
5372
6272
|
hopDepth: candidate.hopDepth,
|
|
5373
6273
|
decayedWeight: candidate.decayedWeight,
|
|
5374
6274
|
graphType: candidate.graphType
|
|
@@ -5384,12 +6284,12 @@ ${r.snippet.trim()}
|
|
|
5384
6284
|
}
|
|
5385
6285
|
async recordLastGraphRecallSnapshot(options) {
|
|
5386
6286
|
try {
|
|
5387
|
-
const snapshotPath =
|
|
6287
|
+
const snapshotPath = path7.join(
|
|
5388
6288
|
options.storage.dir,
|
|
5389
6289
|
"state",
|
|
5390
6290
|
"last_graph_recall.json"
|
|
5391
6291
|
);
|
|
5392
|
-
await
|
|
6292
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
5393
6293
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5394
6294
|
const totalSeedCount = options.seedPaths.length;
|
|
5395
6295
|
const totalExpandedCount = options.expandedPaths.length;
|
|
@@ -5416,20 +6316,20 @@ ${r.snippet.trim()}
|
|
|
5416
6316
|
finalResults: (options.finalResults ?? []).slice(0, 64),
|
|
5417
6317
|
shadowComparison: options.shadowComparison
|
|
5418
6318
|
};
|
|
5419
|
-
await
|
|
6319
|
+
await writeFile4(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
5420
6320
|
} catch (err) {
|
|
5421
6321
|
log.debug(`last graph recall write failed: ${err}`);
|
|
5422
6322
|
}
|
|
5423
6323
|
}
|
|
5424
6324
|
async recordLastIntentSnapshot(options) {
|
|
5425
6325
|
try {
|
|
5426
|
-
const snapshotPath =
|
|
6326
|
+
const snapshotPath = path7.join(
|
|
5427
6327
|
options.storage.dir,
|
|
5428
6328
|
"state",
|
|
5429
6329
|
"last_intent.json"
|
|
5430
6330
|
);
|
|
5431
|
-
await
|
|
5432
|
-
await
|
|
6331
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
6332
|
+
await writeFile4(
|
|
5433
6333
|
snapshotPath,
|
|
5434
6334
|
JSON.stringify(options.snapshot, null, 2),
|
|
5435
6335
|
"utf-8"
|
|
@@ -5440,13 +6340,13 @@ ${r.snippet.trim()}
|
|
|
5440
6340
|
}
|
|
5441
6341
|
async recordLastQmdRecallSnapshot(options) {
|
|
5442
6342
|
try {
|
|
5443
|
-
const snapshotPath =
|
|
6343
|
+
const snapshotPath = path7.join(
|
|
5444
6344
|
options.storage.dir,
|
|
5445
6345
|
"state",
|
|
5446
6346
|
"last_qmd_recall.json"
|
|
5447
6347
|
);
|
|
5448
|
-
await
|
|
5449
|
-
await
|
|
6348
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
6349
|
+
await writeFile4(
|
|
5450
6350
|
snapshotPath,
|
|
5451
6351
|
JSON.stringify(options.snapshot, null, 2),
|
|
5452
6352
|
"utf-8"
|
|
@@ -5460,9 +6360,9 @@ ${r.snippet.trim()}
|
|
|
5460
6360
|
const stateDir = await this.resolveStateDirForNamespace(
|
|
5461
6361
|
options.namespace
|
|
5462
6362
|
);
|
|
5463
|
-
const snapshotPath =
|
|
5464
|
-
await
|
|
5465
|
-
await
|
|
6363
|
+
const snapshotPath = path7.join(stateDir, "last_intent.json");
|
|
6364
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
6365
|
+
await writeFile4(
|
|
5466
6366
|
snapshotPath,
|
|
5467
6367
|
JSON.stringify(options.snapshot, null, 2),
|
|
5468
6368
|
"utf-8"
|
|
@@ -5473,12 +6373,12 @@ ${r.snippet.trim()}
|
|
|
5473
6373
|
}
|
|
5474
6374
|
async resolveStateDirForNamespace(namespace) {
|
|
5475
6375
|
if (!this.config.namespacesEnabled) {
|
|
5476
|
-
return
|
|
6376
|
+
return path7.join(this.config.memoryDir, "state");
|
|
5477
6377
|
}
|
|
5478
6378
|
if (namespace !== this.config.defaultNamespace) {
|
|
5479
|
-
return
|
|
6379
|
+
return path7.join(this.config.memoryDir, "namespaces", namespace, "state");
|
|
5480
6380
|
}
|
|
5481
|
-
const candidate =
|
|
6381
|
+
const candidate = path7.join(
|
|
5482
6382
|
this.config.memoryDir,
|
|
5483
6383
|
"namespaces",
|
|
5484
6384
|
this.config.defaultNamespace
|
|
@@ -5486,11 +6386,11 @@ ${r.snippet.trim()}
|
|
|
5486
6386
|
try {
|
|
5487
6387
|
const candidateStat = await stat3(candidate);
|
|
5488
6388
|
if (candidateStat.isDirectory()) {
|
|
5489
|
-
return
|
|
6389
|
+
return path7.join(candidate, "state");
|
|
5490
6390
|
}
|
|
5491
6391
|
} catch {
|
|
5492
6392
|
}
|
|
5493
|
-
return
|
|
6393
|
+
return path7.join(this.config.memoryDir, "state");
|
|
5494
6394
|
}
|
|
5495
6395
|
buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
|
|
5496
6396
|
return results.slice(0, limit).map((result) => ({
|
|
@@ -5576,7 +6476,10 @@ ${r.snippet.trim()}
|
|
|
5576
6476
|
}
|
|
5577
6477
|
return reserved;
|
|
5578
6478
|
}
|
|
5579
|
-
getRecallBudgetChars() {
|
|
6479
|
+
getRecallBudgetChars(override) {
|
|
6480
|
+
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
6481
|
+
return Math.floor(override);
|
|
6482
|
+
}
|
|
5580
6483
|
const configuredBudget = this.config.recallBudgetChars;
|
|
5581
6484
|
if (typeof configuredBudget === "number" && Number.isFinite(configuredBudget) && configuredBudget >= 0) {
|
|
5582
6485
|
return Math.floor(configuredBudget);
|
|
@@ -5587,7 +6490,7 @@ ${r.snippet.trim()}
|
|
|
5587
6490
|
}
|
|
5588
6491
|
return 0;
|
|
5589
6492
|
}
|
|
5590
|
-
assembleRecallSections(sectionBuckets) {
|
|
6493
|
+
assembleRecallSections(sectionBuckets, budgetOverride) {
|
|
5591
6494
|
const orderedEntries = [];
|
|
5592
6495
|
const pipeline = Array.isArray(this.config.recallPipeline) ? this.config.recallPipeline : [];
|
|
5593
6496
|
const orderedIds = pipeline.filter((entry) => entry.enabled !== false).map((entry) => entry.id);
|
|
@@ -5603,7 +6506,7 @@ ${r.snippet.trim()}
|
|
|
5603
6506
|
if (chunks.length === 0) continue;
|
|
5604
6507
|
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
5605
6508
|
}
|
|
5606
|
-
const budget = this.getRecallBudgetChars();
|
|
6509
|
+
const budget = this.getRecallBudgetChars(budgetOverride);
|
|
5607
6510
|
if (budget === 0) {
|
|
5608
6511
|
return {
|
|
5609
6512
|
sections: [],
|
|
@@ -5735,6 +6638,13 @@ ${r.snippet.trim()}
|
|
|
5735
6638
|
let recalledMemoryCount = 0;
|
|
5736
6639
|
let recalledMemoryIds = [];
|
|
5737
6640
|
let recalledMemoryPaths = [];
|
|
6641
|
+
const xrayBranchPoolSize = {
|
|
6642
|
+
hot_qmd: 0,
|
|
6643
|
+
hot_embedding: 0,
|
|
6644
|
+
cold_fallback: 0,
|
|
6645
|
+
recent_scan: 0
|
|
6646
|
+
};
|
|
6647
|
+
const xrayColdPoolSink = { size: 0 };
|
|
5738
6648
|
let identityInjectionModeUsed = "none";
|
|
5739
6649
|
let identityInjectedChars = 0;
|
|
5740
6650
|
let identityInjectionTruncated = false;
|
|
@@ -5795,7 +6705,7 @@ ${r.snippet.trim()}
|
|
|
5795
6705
|
this.config.verbatimArtifactsMaxRecall
|
|
5796
6706
|
);
|
|
5797
6707
|
const embeddingFetchLimit = computedFetchLimit;
|
|
5798
|
-
const principal = resolvePrincipal(sessionKey, this.config);
|
|
6708
|
+
const principal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
|
|
5799
6709
|
const namespaceOverride = options.namespace?.trim() || void 0;
|
|
5800
6710
|
const readableRecallNamespaces = recallNamespacesForPrincipal(
|
|
5801
6711
|
principal,
|
|
@@ -5806,8 +6716,24 @@ ${r.snippet.trim()}
|
|
|
5806
6716
|
`namespace override is not readable: ${namespaceOverride}`
|
|
5807
6717
|
);
|
|
5808
6718
|
}
|
|
5809
|
-
const
|
|
5810
|
-
const
|
|
6719
|
+
const codingOverlay = namespaceOverride ? null : this.applyCodingRecallOverlay(sessionKey);
|
|
6720
|
+
const principalSelfNamespace = defaultNamespaceForPrincipal(principal, this.config);
|
|
6721
|
+
const codingSelfNamespace = codingOverlay ? combineNamespaces(principalSelfNamespace, codingOverlay.namespace) : null;
|
|
6722
|
+
const selfNamespace = namespaceOverride ?? codingSelfNamespace ?? principalSelfNamespace;
|
|
6723
|
+
let recallNamespaces;
|
|
6724
|
+
if (namespaceOverride) {
|
|
6725
|
+
recallNamespaces = [namespaceOverride];
|
|
6726
|
+
} else if (codingOverlay && codingSelfNamespace) {
|
|
6727
|
+
const mapped = readableRecallNamespaces.map(
|
|
6728
|
+
(ns) => ns === principalSelfNamespace ? codingSelfNamespace : ns
|
|
6729
|
+
);
|
|
6730
|
+
const fallbackNs = codingOverlay.readFallbacks.map(
|
|
6731
|
+
(fallback) => combineNamespaces(principalSelfNamespace, fallback)
|
|
6732
|
+
);
|
|
6733
|
+
recallNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
|
|
6734
|
+
} else {
|
|
6735
|
+
recallNamespaces = readableRecallNamespaces;
|
|
6736
|
+
}
|
|
5811
6737
|
const qmdAvailable = this.qmd.isAvailable();
|
|
5812
6738
|
let graphDecisionStatus = recallDecision.plannedMode === "graph_mode" ? "skipped" : "not_requested";
|
|
5813
6739
|
let graphDecisionReason = recallDecision.graphReason;
|
|
@@ -5824,7 +6750,7 @@ ${r.snippet.trim()}
|
|
|
5824
6750
|
const graphExpandedResultPaths = /* @__PURE__ */ new Set();
|
|
5825
6751
|
const graphSourceLabelsForPath = (resultPath) => {
|
|
5826
6752
|
const labels = [];
|
|
5827
|
-
const normalizedPath = resultPath.split(
|
|
6753
|
+
const normalizedPath = resultPath.split(path7.sep).join("/");
|
|
5828
6754
|
const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
|
|
5829
6755
|
if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
|
|
5830
6756
|
if (graphExpandedResultPaths.has(resultPath))
|
|
@@ -5862,6 +6788,32 @@ ${r.snippet.trim()}
|
|
|
5862
6788
|
const earlySessionKey = sessionKey ?? "default";
|
|
5863
6789
|
this._recallWorkspaceOverrides.delete(earlySessionKey);
|
|
5864
6790
|
timings.total = `${Date.now() - recallStart}ms`;
|
|
6791
|
+
if (options.xrayCapture === true && !options.abortSignal?.aborted) {
|
|
6792
|
+
try {
|
|
6793
|
+
this.lastXraySnapshot = buildXraySnapshot({
|
|
6794
|
+
query: retrievalQuery,
|
|
6795
|
+
tierExplain: null,
|
|
6796
|
+
results: [],
|
|
6797
|
+
filters: [
|
|
6798
|
+
{
|
|
6799
|
+
name: "planner-mode",
|
|
6800
|
+
considered: 0,
|
|
6801
|
+
admitted: 0,
|
|
6802
|
+
reason: "no_recall"
|
|
6803
|
+
}
|
|
6804
|
+
],
|
|
6805
|
+
budget: {
|
|
6806
|
+
chars: this.getRecallBudgetChars(options.budgetCharsOverride),
|
|
6807
|
+
used: 0
|
|
6808
|
+
},
|
|
6809
|
+
sessionKey,
|
|
6810
|
+
namespace: selfNamespace,
|
|
6811
|
+
traceId
|
|
6812
|
+
});
|
|
6813
|
+
} catch (err) {
|
|
6814
|
+
log.debug(`x-ray capture (no_recall) failed: ${err}`);
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
5865
6817
|
if (sessionKey) {
|
|
5866
6818
|
this.lastRecall.record({
|
|
5867
6819
|
sessionKey,
|
|
@@ -7011,16 +7963,16 @@ ${formatted}`;
|
|
|
7011
7963
|
if (!this.config.compactionResetEnabled) return null;
|
|
7012
7964
|
const workspaceDir = compactionWorkspaceDir || this.config.workspaceDir || defaultWorkspaceDir();
|
|
7013
7965
|
const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
|
|
7014
|
-
const signalPath =
|
|
7966
|
+
const signalPath = path7.join(
|
|
7015
7967
|
workspaceDir,
|
|
7016
7968
|
`.compaction-reset-signal-${safeSessionKey}`
|
|
7017
7969
|
);
|
|
7018
|
-
const bootPath =
|
|
7970
|
+
const bootPath = path7.join(workspaceDir, "BOOT.md");
|
|
7019
7971
|
try {
|
|
7020
7972
|
const signalStat = await stat3(signalPath).catch(() => null);
|
|
7021
7973
|
if (!signalStat) return null;
|
|
7022
7974
|
const signalAge = Date.now() - signalStat.mtimeMs;
|
|
7023
|
-
const signalData = JSON.parse(await
|
|
7975
|
+
const signalData = JSON.parse(await readFile4(signalPath, "utf-8"));
|
|
7024
7976
|
if (signalData.sessionKey !== effectiveSessionKey) {
|
|
7025
7977
|
log.debug(
|
|
7026
7978
|
`recall: compaction signal is for ${signalData.sessionKey}, not ${effectiveSessionKey} \u2014 skipping`
|
|
@@ -7040,7 +7992,7 @@ ${formatted}`;
|
|
|
7040
7992
|
|
|
7041
7993
|
`;
|
|
7042
7994
|
try {
|
|
7043
|
-
const bootContent = await
|
|
7995
|
+
const bootContent = await readFile4(bootPath, "utf-8");
|
|
7044
7996
|
section += "### BOOT.md (working state before compaction)\n\n";
|
|
7045
7997
|
section += bootContent + "\n";
|
|
7046
7998
|
} catch {
|
|
@@ -7747,7 +8699,18 @@ ${tmtNode.summary}`
|
|
|
7747
8699
|
"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
|
|
7748
8700
|
);
|
|
7749
8701
|
}
|
|
8702
|
+
if (this.config.recallMemoryWorthFilterEnabled && memoryResults.length > 0) {
|
|
8703
|
+
try {
|
|
8704
|
+
memoryResults = await this.applyMemoryWorthRerank(memoryResults, recallNamespaces);
|
|
8705
|
+
} catch (err) {
|
|
8706
|
+
log.debug("memory-worth filter failed open", { error: err.message });
|
|
8707
|
+
}
|
|
8708
|
+
}
|
|
7750
8709
|
const effectiveGateScore = preAugmentTopScore > 0 ? Math.max(preAugmentTopScore, maxSpecializedScore) : 0;
|
|
8710
|
+
xrayBranchPoolSize.hot_qmd = Math.max(
|
|
8711
|
+
xrayBranchPoolSize.hot_qmd,
|
|
8712
|
+
memoryResults.length
|
|
8713
|
+
);
|
|
7751
8714
|
let confidenceGateRejected = false;
|
|
7752
8715
|
if (this.config.recallConfidenceGateEnabled && effectiveGateScore > 0) {
|
|
7753
8716
|
if (effectiveGateScore < this.config.recallConfidenceGateThreshold) {
|
|
@@ -7761,7 +8724,8 @@ ${tmtNode.summary}`
|
|
|
7761
8724
|
memoryResults = this.diversifyAndLimitRecallResults(
|
|
7762
8725
|
"memories",
|
|
7763
8726
|
memoryResults,
|
|
7764
|
-
recallResultLimit
|
|
8727
|
+
recallResultLimit,
|
|
8728
|
+
retrievalQuery
|
|
7765
8729
|
);
|
|
7766
8730
|
if (this.config.memoryReconstructionEnabled && memoryResults.length > 0) {
|
|
7767
8731
|
try {
|
|
@@ -7846,10 +8810,15 @@ ${tmtNode.summary}`
|
|
|
7846
8810
|
recallNamespaces,
|
|
7847
8811
|
retrievalQuery
|
|
7848
8812
|
);
|
|
8813
|
+
xrayBranchPoolSize.hot_embedding = Math.max(
|
|
8814
|
+
xrayBranchPoolSize.hot_embedding,
|
|
8815
|
+
boostedScoped.length
|
|
8816
|
+
);
|
|
7849
8817
|
const scoped = this.diversifyAndLimitRecallResults(
|
|
7850
8818
|
"memories",
|
|
7851
8819
|
boostedScoped,
|
|
7852
|
-
recallResultLimit
|
|
8820
|
+
recallResultLimit,
|
|
8821
|
+
retrievalQuery
|
|
7853
8822
|
);
|
|
7854
8823
|
if (scoped.length > 0) {
|
|
7855
8824
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -7882,7 +8851,8 @@ ${tmtNode.summary}`
|
|
|
7882
8851
|
recallResultLimit,
|
|
7883
8852
|
recallMode,
|
|
7884
8853
|
queryAwarePrefilter,
|
|
7885
|
-
abortSignal: options.abortSignal
|
|
8854
|
+
abortSignal: options.abortSignal,
|
|
8855
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
7886
8856
|
});
|
|
7887
8857
|
if (longTerm.length > 0) {
|
|
7888
8858
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -7966,10 +8936,15 @@ ${tmtNode.summary}`
|
|
|
7966
8936
|
recallNamespaces,
|
|
7967
8937
|
retrievalQuery
|
|
7968
8938
|
);
|
|
8939
|
+
xrayBranchPoolSize.hot_embedding = Math.max(
|
|
8940
|
+
xrayBranchPoolSize.hot_embedding,
|
|
8941
|
+
boostedScoped.length
|
|
8942
|
+
);
|
|
7969
8943
|
const scoped = this.diversifyAndLimitRecallResults(
|
|
7970
8944
|
"memories",
|
|
7971
8945
|
boostedScoped,
|
|
7972
|
-
recallResultLimit
|
|
8946
|
+
recallResultLimit,
|
|
8947
|
+
retrievalQuery
|
|
7973
8948
|
);
|
|
7974
8949
|
if (scoped.length > 0) {
|
|
7975
8950
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8023,7 +8998,8 @@ ${tmtNode.summary}`
|
|
|
8023
8998
|
recallResultLimit,
|
|
8024
8999
|
recallMode,
|
|
8025
9000
|
queryAwarePrefilter,
|
|
8026
|
-
abortSignal: options.abortSignal
|
|
9001
|
+
abortSignal: options.abortSignal,
|
|
9002
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
8027
9003
|
});
|
|
8028
9004
|
if (longTerm.length > 0) {
|
|
8029
9005
|
recallSource = "cold_fallback";
|
|
@@ -8065,10 +9041,15 @@ ${tmtNode.summary}`
|
|
|
8065
9041
|
retrievalQuery,
|
|
8066
9042
|
preloadedMap
|
|
8067
9043
|
)).sort((a, b) => b.score - a.score);
|
|
9044
|
+
xrayBranchPoolSize.recent_scan = Math.max(
|
|
9045
|
+
xrayBranchPoolSize.recent_scan,
|
|
9046
|
+
boostedRecent.length
|
|
9047
|
+
);
|
|
8068
9048
|
const recent = this.diversifyAndLimitRecallResults(
|
|
8069
9049
|
"memories",
|
|
8070
9050
|
boostedRecent,
|
|
8071
|
-
recallResultLimit
|
|
9051
|
+
recallResultLimit,
|
|
9052
|
+
retrievalQuery
|
|
8072
9053
|
);
|
|
8073
9054
|
if (recent.length > 0) {
|
|
8074
9055
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8101,7 +9082,8 @@ ${tmtNode.summary}`
|
|
|
8101
9082
|
recallResultLimit,
|
|
8102
9083
|
recallMode,
|
|
8103
9084
|
queryAwarePrefilter,
|
|
8104
|
-
abortSignal: options.abortSignal
|
|
9085
|
+
abortSignal: options.abortSignal,
|
|
9086
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
8105
9087
|
});
|
|
8106
9088
|
if (longTerm.length > 0) {
|
|
8107
9089
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8137,7 +9119,8 @@ ${tmtNode.summary}`
|
|
|
8137
9119
|
recallResultLimit,
|
|
8138
9120
|
recallMode,
|
|
8139
9121
|
queryAwarePrefilter,
|
|
8140
|
-
abortSignal: options.abortSignal
|
|
9122
|
+
abortSignal: options.abortSignal,
|
|
9123
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
8141
9124
|
});
|
|
8142
9125
|
if (longTerm.length > 0) {
|
|
8143
9126
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8296,7 +9279,10 @@ _Context: ${topQuestion.context}_`
|
|
|
8296
9279
|
);
|
|
8297
9280
|
const timingParts = Object.entries(timings).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
8298
9281
|
log.info(`recall timings: ${timingParts}`);
|
|
8299
|
-
const assembledRecall = this.assembleRecallSections(
|
|
9282
|
+
const assembledRecall = this.assembleRecallSections(
|
|
9283
|
+
sectionBuckets,
|
|
9284
|
+
options.budgetCharsOverride
|
|
9285
|
+
);
|
|
8300
9286
|
const context = assembledRecall.sections.length === 0 ? "" : assembledRecall.sections.join("\n\n---\n\n");
|
|
8301
9287
|
const sourcesUsed = this.collectLastRecallSources(
|
|
8302
9288
|
sectionBuckets,
|
|
@@ -8312,6 +9298,73 @@ _Context: ${topQuestion.context}_`
|
|
|
8312
9298
|
includedSections: assembledRecall.includedIds,
|
|
8313
9299
|
omittedSections: assembledRecall.omittedIds
|
|
8314
9300
|
});
|
|
9301
|
+
if (options.xrayCapture === true && !options.abortSignal?.aborted) {
|
|
9302
|
+
try {
|
|
9303
|
+
const servedBy = mapRecallSourceToXrayServedBy(recallSource);
|
|
9304
|
+
const idFromPath = (p) => {
|
|
9305
|
+
const match = p.match(/([^/]+)\.md$/);
|
|
9306
|
+
return match ? match[1] ?? null : null;
|
|
9307
|
+
};
|
|
9308
|
+
const results = [];
|
|
9309
|
+
for (const recalledPath of recalledMemoryPaths) {
|
|
9310
|
+
const derivedId = idFromPath(recalledPath);
|
|
9311
|
+
if (!derivedId) continue;
|
|
9312
|
+
results.push({
|
|
9313
|
+
memoryId: derivedId,
|
|
9314
|
+
path: recalledPath,
|
|
9315
|
+
servedBy,
|
|
9316
|
+
scoreDecomposition: { final: 0 },
|
|
9317
|
+
admittedBy: []
|
|
9318
|
+
});
|
|
9319
|
+
}
|
|
9320
|
+
let xrayConsidered;
|
|
9321
|
+
switch (recallSource) {
|
|
9322
|
+
case "hot_qmd":
|
|
9323
|
+
xrayConsidered = xrayBranchPoolSize.hot_qmd;
|
|
9324
|
+
break;
|
|
9325
|
+
case "hot_embedding":
|
|
9326
|
+
xrayConsidered = xrayBranchPoolSize.hot_embedding;
|
|
9327
|
+
break;
|
|
9328
|
+
case "cold_fallback":
|
|
9329
|
+
xrayConsidered = xrayColdPoolSink.size;
|
|
9330
|
+
break;
|
|
9331
|
+
case "recent_scan":
|
|
9332
|
+
xrayConsidered = xrayBranchPoolSize.recent_scan;
|
|
9333
|
+
break;
|
|
9334
|
+
case "none":
|
|
9335
|
+
xrayConsidered = recalledMemoryCount;
|
|
9336
|
+
break;
|
|
9337
|
+
default: {
|
|
9338
|
+
const _exhaustive = recallSource;
|
|
9339
|
+
void _exhaustive;
|
|
9340
|
+
xrayConsidered = recalledMemoryCount;
|
|
9341
|
+
}
|
|
9342
|
+
}
|
|
9343
|
+
xrayConsidered = Math.max(xrayConsidered, recalledMemoryIds.length);
|
|
9344
|
+
const filters = [
|
|
9345
|
+
{
|
|
9346
|
+
name: "recall-result-limit",
|
|
9347
|
+
considered: xrayConsidered,
|
|
9348
|
+
admitted: recalledMemoryIds.length
|
|
9349
|
+
}
|
|
9350
|
+
];
|
|
9351
|
+
this.lastXraySnapshot = buildXraySnapshot({
|
|
9352
|
+
query: retrievalQuery,
|
|
9353
|
+
tierExplain: null,
|
|
9354
|
+
results,
|
|
9355
|
+
filters,
|
|
9356
|
+
budget: {
|
|
9357
|
+
chars: this.getRecallBudgetChars(options.budgetCharsOverride),
|
|
9358
|
+
used: assembledRecall.finalChars
|
|
9359
|
+
},
|
|
9360
|
+
sessionKey,
|
|
9361
|
+
namespace: selfNamespace,
|
|
9362
|
+
traceId
|
|
9363
|
+
});
|
|
9364
|
+
} catch (err) {
|
|
9365
|
+
log.debug(`x-ray capture failed: ${err}`);
|
|
9366
|
+
}
|
|
9367
|
+
}
|
|
8315
9368
|
if (sessionKey) {
|
|
8316
9369
|
throwIfRecallAborted(options.abortSignal);
|
|
8317
9370
|
this.lastRecall.record({
|
|
@@ -8788,7 +9841,10 @@ ${normalized}`).digest("hex");
|
|
|
8788
9841
|
return;
|
|
8789
9842
|
}
|
|
8790
9843
|
const principal = resolvePrincipal(sessionKey, this.config);
|
|
8791
|
-
const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride :
|
|
9844
|
+
const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : this.applyCodingNamespaceOverlay(
|
|
9845
|
+
sessionKey,
|
|
9846
|
+
defaultNamespaceForPrincipal(principal, this.config)
|
|
9847
|
+
);
|
|
8792
9848
|
const storage = await this.storageRouter.storageFor(selfNamespace);
|
|
8793
9849
|
const shouldPersistProcessedFingerprint = normalizedTurns.some(
|
|
8794
9850
|
(turn) => turn.persistProcessedFingerprint === true
|
|
@@ -8881,6 +9937,24 @@ ${normalized}`).digest("hex");
|
|
|
8881
9937
|
} catch (error) {
|
|
8882
9938
|
postPersistMetaError = error;
|
|
8883
9939
|
}
|
|
9940
|
+
try {
|
|
9941
|
+
if (clearBufferAfterExtraction && !this.config.extractionJudgeShadow) {
|
|
9942
|
+
const deferredCount = this.lastPersistExtractionDeferredCount;
|
|
9943
|
+
if (deferredCount > 0 && normalizedTurns.length > 0) {
|
|
9944
|
+
await this.buffer.retainDeferredTurns(
|
|
9945
|
+
bufferKey,
|
|
9946
|
+
normalizedTurns,
|
|
9947
|
+
10
|
|
9948
|
+
);
|
|
9949
|
+
} else {
|
|
9950
|
+
await this.buffer.retainDeferredTurns(bufferKey, [], 0);
|
|
9951
|
+
}
|
|
9952
|
+
}
|
|
9953
|
+
} catch (err) {
|
|
9954
|
+
log.debug(
|
|
9955
|
+
`extraction-judge: defer retention failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
|
|
9956
|
+
);
|
|
9957
|
+
}
|
|
8884
9958
|
await clearBuffer({ ignoreAbort: true });
|
|
8885
9959
|
if (this.config.memoryBoxesEnabled && persistedIds.length > 0) {
|
|
8886
9960
|
const extractionTopics = deriveTopicsFromExtraction(result);
|
|
@@ -9013,7 +10087,7 @@ ${normalized}`).digest("hex");
|
|
|
9013
10087
|
);
|
|
9014
10088
|
this.tierMigrationInFlight = true;
|
|
9015
10089
|
try {
|
|
9016
|
-
const coldStorage = new StorageManager(
|
|
10090
|
+
const coldStorage = new StorageManager(path7.join(storage.dir, "cold"));
|
|
9017
10091
|
const [hotMemories, coldMemories] = await Promise.all([
|
|
9018
10092
|
storage.readAllMemories(),
|
|
9019
10093
|
coldStorage.readAllMemories()
|
|
@@ -9462,6 +10536,7 @@ ${normalized}`).digest("hex");
|
|
|
9462
10536
|
}
|
|
9463
10537
|
let judgeVerdictsByFactIndex = null;
|
|
9464
10538
|
let judgeGatedCount = 0;
|
|
10539
|
+
this.lastPersistExtractionDeferredCount = 0;
|
|
9465
10540
|
if (this.config.extractionJudgeEnabled) {
|
|
9466
10541
|
try {
|
|
9467
10542
|
const judgeCandidates = [];
|
|
@@ -9496,12 +10571,56 @@ ${normalized}`).digest("hex");
|
|
|
9496
10571
|
});
|
|
9497
10572
|
candidateToFactIndex.push(fi);
|
|
9498
10573
|
}
|
|
10574
|
+
const judgeTelemetryOpts = {
|
|
10575
|
+
enabled: this.config.extractionJudgeTelemetryEnabled === true,
|
|
10576
|
+
memoryDir: this.config.memoryDir
|
|
10577
|
+
};
|
|
10578
|
+
const judgeTrainingOpts = {
|
|
10579
|
+
enabled: this.config.collectJudgeTrainingPairs === true,
|
|
10580
|
+
...this.config.judgeTrainingDir ? { directory: this.config.judgeTrainingDir } : {}
|
|
10581
|
+
};
|
|
10582
|
+
const judgeTelemetryHandler = judgeTelemetryOpts.enabled || judgeTrainingOpts.enabled ? (obs) => {
|
|
10583
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
10584
|
+
const verdictKind = getVerdictKind(obs.verdict);
|
|
10585
|
+
if (judgeTelemetryOpts.enabled) {
|
|
10586
|
+
const event = {
|
|
10587
|
+
version: 1,
|
|
10588
|
+
category: EXTRACTION_JUDGE_VERDICT_CATEGORY,
|
|
10589
|
+
ts,
|
|
10590
|
+
verdictKind,
|
|
10591
|
+
reason: obs.verdict.reason,
|
|
10592
|
+
deferrals: obs.priorDeferrals,
|
|
10593
|
+
elapsedMs: obs.elapsedMs,
|
|
10594
|
+
candidateCategory: obs.candidate.category,
|
|
10595
|
+
confidence: obs.candidate.confidence,
|
|
10596
|
+
contentHash: obs.contentHash,
|
|
10597
|
+
fromCache: obs.source === "cache",
|
|
10598
|
+
...obs.source === "llm-cap-rejected" ? { deferCapTriggered: true } : {}
|
|
10599
|
+
};
|
|
10600
|
+
void recordJudgeVerdict(event, judgeTelemetryOpts);
|
|
10601
|
+
}
|
|
10602
|
+
if (judgeTrainingOpts.enabled) {
|
|
10603
|
+
const pair = {
|
|
10604
|
+
version: 1,
|
|
10605
|
+
ts,
|
|
10606
|
+
candidateText: obs.candidate.text,
|
|
10607
|
+
candidateCategory: obs.candidate.category,
|
|
10608
|
+
...typeof obs.candidate.confidence === "number" ? { candidateConfidence: obs.candidate.confidence } : {},
|
|
10609
|
+
verdictKind,
|
|
10610
|
+
reason: obs.verdict.reason,
|
|
10611
|
+
priorDeferrals: obs.priorDeferrals
|
|
10612
|
+
};
|
|
10613
|
+
void recordJudgeTrainingPair(pair, judgeTrainingOpts);
|
|
10614
|
+
}
|
|
10615
|
+
} : void 0;
|
|
9499
10616
|
const judgeResult = await judgeFactDurability(
|
|
9500
10617
|
judgeCandidates,
|
|
9501
10618
|
this.config,
|
|
9502
10619
|
this.localLlm,
|
|
9503
10620
|
new FallbackLlmClient(this.config.gatewayConfig),
|
|
9504
|
-
this.judgeVerdictCache
|
|
10621
|
+
this.judgeVerdictCache,
|
|
10622
|
+
this.judgeDeferCounts,
|
|
10623
|
+
judgeTelemetryHandler
|
|
9505
10624
|
);
|
|
9506
10625
|
judgeVerdictsByFactIndex = /* @__PURE__ */ new Map();
|
|
9507
10626
|
for (const [candidateIdx, verdict] of judgeResult.verdicts) {
|
|
@@ -9511,8 +10630,9 @@ ${normalized}`).digest("hex");
|
|
|
9511
10630
|
}
|
|
9512
10631
|
}
|
|
9513
10632
|
log.info(
|
|
9514
|
-
`extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.elapsed}ms`
|
|
10633
|
+
`extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.deferred} deferred` + (judgeResult.deferredCappedToReject > 0 ? ` (${judgeResult.deferredCappedToReject} cap-rejected)` : "") + `, ${judgeResult.elapsed}ms`
|
|
9515
10634
|
);
|
|
10635
|
+
this.lastPersistExtractionDeferredCount = judgeResult.deferred;
|
|
9516
10636
|
} catch (err) {
|
|
9517
10637
|
log.warn(
|
|
9518
10638
|
`extraction-judge: pipeline error, proceeding without filtering (fail-open): ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9587,10 +10707,17 @@ ${normalized}`).digest("hex");
|
|
|
9587
10707
|
if (judgeVerdictsByFactIndex) {
|
|
9588
10708
|
const verdict = judgeVerdictsByFactIndex.get(factLoopIndex);
|
|
9589
10709
|
if (verdict && !verdict.durable) {
|
|
10710
|
+
const verdictKind = getVerdictKind(verdict);
|
|
9590
10711
|
if (this.config.extractionJudgeShadow) {
|
|
9591
10712
|
log.info(
|
|
9592
|
-
`extraction-judge[shadow]: would
|
|
10713
|
+
`extraction-judge[shadow]: would ${verdictKind} "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
|
|
10714
|
+
);
|
|
10715
|
+
} else if (verdictKind === "defer") {
|
|
10716
|
+
judgeGatedCount++;
|
|
10717
|
+
log.debug(
|
|
10718
|
+
`extraction-judge: deferred "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
|
|
9593
10719
|
);
|
|
10720
|
+
continue;
|
|
9594
10721
|
} else {
|
|
9595
10722
|
judgeGatedCount++;
|
|
9596
10723
|
log.debug(
|
|
@@ -10133,7 +11260,7 @@ ${normalized}`).digest("hex");
|
|
|
10133
11260
|
const allMems = allMemsForGraph ?? [];
|
|
10134
11261
|
for (const m of allMems) {
|
|
10135
11262
|
if (m.frontmatter.entityRef === entityRef) {
|
|
10136
|
-
const rel =
|
|
11263
|
+
const rel = path7.relative(storage.dir, m.path);
|
|
10137
11264
|
if (rel !== memoryRelPath) entitySiblings.push(rel);
|
|
10138
11265
|
}
|
|
10139
11266
|
}
|
|
@@ -10404,14 +11531,14 @@ ${normalized}`).digest("hex");
|
|
|
10404
11531
|
}
|
|
10405
11532
|
if (this.config.semanticConsolidationEnabled) {
|
|
10406
11533
|
try {
|
|
10407
|
-
const stateFilePath =
|
|
11534
|
+
const stateFilePath = path7.join(
|
|
10408
11535
|
this.config.memoryDir,
|
|
10409
11536
|
"state",
|
|
10410
11537
|
"semantic-consolidation-last-run.json"
|
|
10411
11538
|
);
|
|
10412
11539
|
let shouldRun = true;
|
|
10413
11540
|
try {
|
|
10414
|
-
const stateRaw = await
|
|
11541
|
+
const stateRaw = await readFile4(stateFilePath, "utf-8");
|
|
10415
11542
|
const stateData = JSON.parse(stateRaw);
|
|
10416
11543
|
if (stateData.lastRunAt) {
|
|
10417
11544
|
const lastRunMs = new Date(stateData.lastRunAt).getTime();
|
|
@@ -10434,9 +11561,9 @@ ${normalized}`).digest("hex");
|
|
|
10434
11561
|
allMemories = await this.storage.readAllMemories();
|
|
10435
11562
|
}
|
|
10436
11563
|
if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
|
|
10437
|
-
const stateDir =
|
|
10438
|
-
await
|
|
10439
|
-
await
|
|
11564
|
+
const stateDir = path7.join(this.config.memoryDir, "state");
|
|
11565
|
+
await mkdir5(stateDir, { recursive: true });
|
|
11566
|
+
await writeFile4(
|
|
10440
11567
|
stateFilePath,
|
|
10441
11568
|
JSON.stringify({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
10442
11569
|
"utf-8"
|
|
@@ -10908,13 +12035,13 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
|
|
|
10908
12035
|
protectedCategories: this.config.lifecycleProtectedCategories
|
|
10909
12036
|
}
|
|
10910
12037
|
};
|
|
10911
|
-
const metricsPath =
|
|
12038
|
+
const metricsPath = path7.join(
|
|
10912
12039
|
this.storage.dir,
|
|
10913
12040
|
"state",
|
|
10914
12041
|
"lifecycle-metrics.json"
|
|
10915
12042
|
);
|
|
10916
|
-
await
|
|
10917
|
-
await
|
|
12043
|
+
await mkdir5(path7.dirname(metricsPath), { recursive: true });
|
|
12044
|
+
await writeFile4(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
|
|
10918
12045
|
}
|
|
10919
12046
|
/**
|
|
10920
12047
|
* Archive old, low-importance, rarely-accessed facts (v6.0).
|
|
@@ -11417,11 +12544,97 @@ ${lines.join("\n\n")}`;
|
|
|
11417
12544
|
*
|
|
11418
12545
|
* Callers must pass the full candidate pool (post-rerank, pre-slice).
|
|
11419
12546
|
*/
|
|
11420
|
-
|
|
12547
|
+
async applyMemoryWorthRerank(results, namespaces) {
|
|
12548
|
+
const counters = /* @__PURE__ */ new Map();
|
|
12549
|
+
const seenNamespaces = /* @__PURE__ */ new Set();
|
|
12550
|
+
const nowMs = Date.now();
|
|
12551
|
+
for (const [key, entry] of this.memoryWorthCounterCache) {
|
|
12552
|
+
if (nowMs - entry.at >= _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
|
|
12553
|
+
this.memoryWorthCounterCache.delete(key);
|
|
12554
|
+
}
|
|
12555
|
+
}
|
|
12556
|
+
for (const ns of namespaces) {
|
|
12557
|
+
if (seenNamespaces.has(ns)) continue;
|
|
12558
|
+
seenNamespaces.add(ns);
|
|
12559
|
+
try {
|
|
12560
|
+
const cached = this.memoryWorthCounterCache.get(ns);
|
|
12561
|
+
let nsMap;
|
|
12562
|
+
if (cached && nowMs - cached.at < _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
|
|
12563
|
+
nsMap = cached.counters;
|
|
12564
|
+
} else {
|
|
12565
|
+
const storage = await this.getStorage(ns);
|
|
12566
|
+
const memories = await storage.readAllMemories();
|
|
12567
|
+
nsMap = buildMemoryWorthCounterMap(memories);
|
|
12568
|
+
this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });
|
|
12569
|
+
}
|
|
12570
|
+
for (const [path8, c] of nsMap) counters.set(path8, c);
|
|
12571
|
+
} catch (err) {
|
|
12572
|
+
log.debug("memory-worth: failed to read namespace, skipping", {
|
|
12573
|
+
namespace: ns,
|
|
12574
|
+
error: err.message
|
|
12575
|
+
});
|
|
12576
|
+
}
|
|
12577
|
+
}
|
|
12578
|
+
const missing = results.filter((r) => !counters.has(r.path));
|
|
12579
|
+
if (missing.length > 0) {
|
|
12580
|
+
let reader = null;
|
|
12581
|
+
for (const ns of namespaces) {
|
|
12582
|
+
try {
|
|
12583
|
+
reader = await this.getStorage(ns);
|
|
12584
|
+
break;
|
|
12585
|
+
} catch {
|
|
12586
|
+
}
|
|
12587
|
+
}
|
|
12588
|
+
if (reader) {
|
|
12589
|
+
for (const r of missing) {
|
|
12590
|
+
try {
|
|
12591
|
+
const memory = await reader.readMemoryByPath(r.path);
|
|
12592
|
+
if (!memory) continue;
|
|
12593
|
+
const fm = memory.frontmatter;
|
|
12594
|
+
if (fm.mw_success === void 0 && fm.mw_fail === void 0) continue;
|
|
12595
|
+
counters.set(r.path, {
|
|
12596
|
+
mw_success: fm.mw_success,
|
|
12597
|
+
mw_fail: fm.mw_fail,
|
|
12598
|
+
lastAccessed: fm.lastAccessed
|
|
12599
|
+
});
|
|
12600
|
+
} catch (err) {
|
|
12601
|
+
log.debug("memory-worth: direct path lookup failed", {
|
|
12602
|
+
path: r.path,
|
|
12603
|
+
error: err.message
|
|
12604
|
+
});
|
|
12605
|
+
}
|
|
12606
|
+
}
|
|
12607
|
+
}
|
|
12608
|
+
}
|
|
12609
|
+
if (counters.size === 0) return results;
|
|
12610
|
+
const rankedInputs = results.map((r, i) => ({
|
|
12611
|
+
path: r.path,
|
|
12612
|
+
// Large positive rank score so multiplier math stays well-scaled and
|
|
12613
|
+
// we never hit zero; descending so earlier items rank higher.
|
|
12614
|
+
score: results.length - i
|
|
12615
|
+
}));
|
|
12616
|
+
const filtered = applyMemoryWorthFilter(rankedInputs, {
|
|
12617
|
+
counters,
|
|
12618
|
+
now: /* @__PURE__ */ new Date(),
|
|
12619
|
+
halfLifeMs: this.config.recallMemoryWorthHalfLifeMs > 0 ? this.config.recallMemoryWorthHalfLifeMs : void 0
|
|
12620
|
+
});
|
|
12621
|
+
const byPath = new Map(results.map((r) => [r.path, r]));
|
|
12622
|
+
const reordered = [];
|
|
12623
|
+
for (const item of filtered) {
|
|
12624
|
+
const original = byPath.get(item.path);
|
|
12625
|
+
if (original) reordered.push(original);
|
|
12626
|
+
}
|
|
12627
|
+
return reordered;
|
|
12628
|
+
}
|
|
12629
|
+
diversifyAndLimitRecallResults(sectionId, results, limit, retrievalQuery) {
|
|
11421
12630
|
const safeLimit = typeof limit === "number" && Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 0;
|
|
11422
12631
|
if (!Array.isArray(results) || results.length === 0) return [];
|
|
11423
12632
|
if (safeLimit === 0) return [];
|
|
11424
|
-
const
|
|
12633
|
+
const boosted = this.config.recallReasoningTraceBoostEnabled && typeof retrievalQuery === "string" ? applyReasoningTraceBoost(results, {
|
|
12634
|
+
enabled: true,
|
|
12635
|
+
query: retrievalQuery
|
|
12636
|
+
}) : results;
|
|
12637
|
+
const diversified = this.applyMmrToQmdResults(sectionId, boosted);
|
|
11425
12638
|
return diversified.slice(0, safeLimit);
|
|
11426
12639
|
}
|
|
11427
12640
|
/**
|
|
@@ -11525,12 +12738,12 @@ ${lines.join("\n\n")}`;
|
|
|
11525
12738
|
*/
|
|
11526
12739
|
semanticDedupScopeFor(targetStorage) {
|
|
11527
12740
|
if (!this.config.namespacesEnabled) return {};
|
|
11528
|
-
const memoryDir =
|
|
11529
|
-
const storageDir =
|
|
12741
|
+
const memoryDir = path7.resolve(this.config.memoryDir);
|
|
12742
|
+
const storageDir = path7.resolve(targetStorage.dir);
|
|
11530
12743
|
if (storageDir === memoryDir) {
|
|
11531
12744
|
return { pathExcludePrefixes: ["namespaces/"] };
|
|
11532
12745
|
}
|
|
11533
|
-
let rel =
|
|
12746
|
+
let rel = path7.relative(memoryDir, storageDir);
|
|
11534
12747
|
if (!rel || rel.startsWith("..")) {
|
|
11535
12748
|
log.debug(
|
|
11536
12749
|
`semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
|
|
@@ -11549,7 +12762,7 @@ ${lines.join("\n\n")}`;
|
|
|
11549
12762
|
if (hits.length === 0) return [];
|
|
11550
12763
|
const results = [];
|
|
11551
12764
|
for (const hit of hits) {
|
|
11552
|
-
const fullPath =
|
|
12765
|
+
const fullPath = path7.isAbsolute(hit.path) ? hit.path : path7.join(this.config.memoryDir, hit.path);
|
|
11553
12766
|
const memory = await this.storage.readMemoryByPath(fullPath);
|
|
11554
12767
|
if (!memory) continue;
|
|
11555
12768
|
results.push({
|
|
@@ -11726,10 +12939,26 @@ ${lines.join("\n\n")}`;
|
|
|
11726
12939
|
"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
|
|
11727
12940
|
);
|
|
11728
12941
|
}
|
|
12942
|
+
if (this.config.recallMemoryWorthFilterEnabled && results.length > 0) {
|
|
12943
|
+
try {
|
|
12944
|
+
results = await this.applyMemoryWorthRerank(results, options.recallNamespaces);
|
|
12945
|
+
} catch (err) {
|
|
12946
|
+
log.debug("memory-worth filter (cold) failed open", {
|
|
12947
|
+
error: err.message
|
|
12948
|
+
});
|
|
12949
|
+
}
|
|
12950
|
+
}
|
|
12951
|
+
if (options.xrayPoolSizeSink) {
|
|
12952
|
+
options.xrayPoolSizeSink.size = Math.max(
|
|
12953
|
+
options.xrayPoolSizeSink.size,
|
|
12954
|
+
results.length
|
|
12955
|
+
);
|
|
12956
|
+
}
|
|
11729
12957
|
return this.diversifyAndLimitRecallResults(
|
|
11730
12958
|
"memories",
|
|
11731
12959
|
results,
|
|
11732
|
-
options.recallResultLimit
|
|
12960
|
+
options.recallResultLimit,
|
|
12961
|
+
options.prompt
|
|
11733
12962
|
);
|
|
11734
12963
|
}
|
|
11735
12964
|
// ---------------------------------------------------------------------------
|
|
@@ -12123,8 +13352,8 @@ ${lines.join("\n\n")}`;
|
|
|
12123
13352
|
}
|
|
12124
13353
|
namespaceFromStorageDir(storageDir) {
|
|
12125
13354
|
if (!this.config.namespacesEnabled) return this.config.defaultNamespace;
|
|
12126
|
-
const resolvedStorageDir =
|
|
12127
|
-
const resolvedMemoryDir =
|
|
13355
|
+
const resolvedStorageDir = path7.resolve(storageDir);
|
|
13356
|
+
const resolvedMemoryDir = path7.resolve(this.config.memoryDir);
|
|
12128
13357
|
if (resolvedStorageDir === resolvedMemoryDir)
|
|
12129
13358
|
return this.config.defaultNamespace;
|
|
12130
13359
|
const m = resolvedStorageDir.match(/[\\/]namespaces[\\/]([^\\/]+)$/);
|
|
@@ -12157,6 +13386,21 @@ export {
|
|
|
12157
13386
|
migrateFromEngram,
|
|
12158
13387
|
buildProcedureRecallSection,
|
|
12159
13388
|
decideSemanticDedup,
|
|
13389
|
+
DEFAULT_TAXONOMY,
|
|
13390
|
+
generateResolverDocument,
|
|
13391
|
+
validateSlug,
|
|
13392
|
+
validateTaxonomy,
|
|
13393
|
+
loadTaxonomy,
|
|
13394
|
+
saveTaxonomy,
|
|
13395
|
+
getTaxonomyDir,
|
|
13396
|
+
getTaxonomyFilePath,
|
|
13397
|
+
stableHash,
|
|
13398
|
+
normalizeOriginUrl,
|
|
13399
|
+
resolveGitContext,
|
|
13400
|
+
projectNamespaceName,
|
|
13401
|
+
branchNamespaceName,
|
|
13402
|
+
resolveCodingNamespaceOverlay,
|
|
13403
|
+
describeCodingScope,
|
|
12160
13404
|
dedupeEntitySynthesisEvidenceEntries,
|
|
12161
13405
|
defaultWorkspaceDir,
|
|
12162
13406
|
sanitizeSessionKeyForFilename,
|
|
@@ -12185,4 +13429,4 @@ export {
|
|
|
12185
13429
|
resolvePersistedMemoryRelativePath,
|
|
12186
13430
|
Orchestrator
|
|
12187
13431
|
};
|
|
12188
|
-
//# sourceMappingURL=chunk-
|
|
13432
|
+
//# sourceMappingURL=chunk-VYM3VWOF.js.map
|