@remnic/core 9.3.742 → 9.3.744
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-boundary.d.ts +6 -6
- package/dist/access-boundary.js +10 -10
- package/dist/access-cli.js +29 -29
- package/dist/access-http.d.ts +6 -6
- package/dist/access-http.js +15 -15
- package/dist/access-mcp.d.ts +6 -6
- package/dist/access-mcp.js +14 -14
- package/dist/access-operations-batch.js +12 -12
- package/dist/access-operations.d.ts +6 -6
- package/dist/access-operations.js +13 -13
- package/dist/{access-service-K8n12dXu.d.ts → access-service-OT3Gk79W.d.ts} +3 -3
- package/dist/access-service.d.ts +6 -6
- package/dist/access-service.js +9 -9
- package/dist/access-surface-catalog.d.ts +6 -6
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-memory-bridge.js +3 -3
- package/dist/active-recall.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +5 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/buffer.js +2 -2
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +10 -5
- package/dist/capabilities.js +1 -1
- package/dist/{catalog-_Bap6vfD.d.ts → catalog-CX0CjOaf.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +2 -2
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-X5PMDVY4.js → chunk-3EA5LIFJ.js} +4 -4
- package/dist/{chunk-YNHRWFAP.js → chunk-4DLFJJOQ.js} +2 -2
- package/dist/{chunk-WIMKOTNY.js → chunk-5QANTTY2.js} +2 -2
- package/dist/{chunk-AM7YKD7V.js → chunk-5UNSGRCR.js} +5 -5
- package/dist/{chunk-Y6PNYJVO.js → chunk-A2KKLCOS.js} +2 -2
- package/dist/{chunk-O4IWVWSW.js → chunk-AVBT5WEW.js} +3 -3
- package/dist/{chunk-QUNH5UZH.js → chunk-BYLC4DKI.js} +2 -2
- package/dist/{chunk-UOVDO6TC.js → chunk-CHELXDTO.js} +3 -3
- package/dist/{chunk-TQQN64J2.js → chunk-DBSMLRTO.js} +2 -2
- package/dist/{chunk-EZZUNKMJ.js → chunk-DYK27X7V.js} +3 -3
- package/dist/{chunk-K2N6WIZM.js → chunk-E7RGJQWP.js} +2 -2
- package/dist/{chunk-M4WI23X3.js → chunk-EEKDRAWX.js} +2 -2
- package/dist/{chunk-GFJ5ABKS.js → chunk-G5FP7VSQ.js} +11 -11
- package/dist/{chunk-BE6NEQLF.js → chunk-HAZVVOYT.js} +3 -3
- package/dist/{chunk-OT5K26NG.js → chunk-HM6UJPPO.js} +2 -2
- package/dist/{chunk-PI4JHLDD.js → chunk-IP5SANO2.js} +2 -2
- package/dist/{chunk-WHEF76BQ.js → chunk-JRZV3767.js} +2 -2
- package/dist/{chunk-OS5RKJOH.js → chunk-JZ7P26GF.js} +2 -2
- package/dist/{chunk-Y62QPRKV.js → chunk-K5LLP4CY.js} +2 -2
- package/dist/{chunk-C3Z5YJSM.js → chunk-LOPZ2DWR.js} +2 -2
- package/dist/{chunk-BJPL5WAL.js → chunk-MXDG6SRH.js} +3 -3
- package/dist/{chunk-UYYSOMS2.js → chunk-NBP3YHHS.js} +4 -4
- package/dist/{chunk-USHVHI6J.js → chunk-NNL4LJAD.js} +3 -3
- package/dist/{chunk-GPX5E36D.js → chunk-OSMBC3JU.js} +2 -2
- package/dist/{chunk-OUSOMUFV.js → chunk-PE6XR4GG.js} +2 -2
- package/dist/{chunk-CMPXLMC3.js → chunk-PI23H7FV.js} +3 -3
- package/dist/{chunk-WGDE2TJP.js → chunk-QOGXUNWL.js} +4 -4
- package/dist/{chunk-ELL5VYXC.js → chunk-RNWWAS5V.js} +3 -3
- package/dist/{chunk-7HUGLMSW.js → chunk-SODQQCAZ.js} +1013 -821
- package/dist/chunk-SODQQCAZ.js.map +1 -0
- package/dist/{chunk-JMMSVRF4.js → chunk-TQPSOTC7.js} +7 -7
- package/dist/{chunk-AX4TRSRE.js → chunk-U5WVRMCA.js} +2 -2
- package/dist/{chunk-7ADHJ6SU.js → chunk-VE54E6RP.js} +4 -4
- package/dist/{chunk-G7Q4D2G3.js → chunk-VSF7AAGE.js} +1 -3
- package/dist/chunk-VSF7AAGE.js.map +1 -0
- package/dist/{chunk-OVYBENIJ.js → chunk-W3M34XT4.js} +3 -3
- package/dist/{chunk-NHJYUIII.js → chunk-WPLRJ4XM.js} +7 -7
- package/dist/{chunk-UEIF7RWQ.js → chunk-XEADGIAA.js} +6 -6
- package/dist/{cli-BEOLy1xo.d.ts → cli-BQiTZ7Zs.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +21 -21
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +2 -2
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/contradiction/index.js +2 -2
- package/dist/{contradiction-scan-UERKJESC.js → contradiction-scan-3FJYWS3G.js} +3 -3
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/day-summary.js +2 -2
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/embedding-fallback.js +2 -2
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +2 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +5 -4
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +4 -4
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{first-start-migration-GQ3UQNIL.js → first-start-migration-4I3VDSYS.js} +2 -2
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +36 -36
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/mcp-memory-inspector-app.d.ts +6 -6
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +6 -6
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/principal.js +2 -2
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +2 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +11 -11
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/compression-guideline-coordinator.js +2 -2
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +6 -6
- package/dist/{orchestrator-Dr-1v5EL.d.ts → orchestrator-BPQGHpJz.d.ts} +263 -31
- package/dist/orchestrator.d.ts +5 -4
- package/dist/orchestrator.js +24 -24
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/embed-helper.js +2 -2
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +3 -3
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +3 -3
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-DsIEiCka.d.ts → semantic-consolidation-ByzGwC9c.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +2 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/shared-context/manager.js +2 -2
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/{tier-stats-CSKL7BDG.js → tier-stats-5XF4UBRQ.js} +2 -2
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CglNn2V-.d.ts → types-5Jik3r4G.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/package.json +2 -2
- package/src/capabilities.test.ts +0 -2
- package/src/capabilities.ts +7 -6
- package/src/orchestration/contradiction-linking-coordinator.ts +336 -0
- package/src/orchestration/graph-recall-coordinator.ts +471 -0
- package/src/orchestration/recall-section-coordinator.ts +349 -0
- package/src/orchestrator.ts +97 -741
- package/dist/chunk-7HUGLMSW.js.map +0 -1
- package/dist/chunk-G7Q4D2G3.js.map +0 -1
- /package/dist/{chunk-X5PMDVY4.js.map → chunk-3EA5LIFJ.js.map} +0 -0
- /package/dist/{chunk-YNHRWFAP.js.map → chunk-4DLFJJOQ.js.map} +0 -0
- /package/dist/{chunk-WIMKOTNY.js.map → chunk-5QANTTY2.js.map} +0 -0
- /package/dist/{chunk-AM7YKD7V.js.map → chunk-5UNSGRCR.js.map} +0 -0
- /package/dist/{chunk-Y6PNYJVO.js.map → chunk-A2KKLCOS.js.map} +0 -0
- /package/dist/{chunk-O4IWVWSW.js.map → chunk-AVBT5WEW.js.map} +0 -0
- /package/dist/{chunk-QUNH5UZH.js.map → chunk-BYLC4DKI.js.map} +0 -0
- /package/dist/{chunk-UOVDO6TC.js.map → chunk-CHELXDTO.js.map} +0 -0
- /package/dist/{chunk-TQQN64J2.js.map → chunk-DBSMLRTO.js.map} +0 -0
- /package/dist/{chunk-EZZUNKMJ.js.map → chunk-DYK27X7V.js.map} +0 -0
- /package/dist/{chunk-K2N6WIZM.js.map → chunk-E7RGJQWP.js.map} +0 -0
- /package/dist/{chunk-M4WI23X3.js.map → chunk-EEKDRAWX.js.map} +0 -0
- /package/dist/{chunk-GFJ5ABKS.js.map → chunk-G5FP7VSQ.js.map} +0 -0
- /package/dist/{chunk-BE6NEQLF.js.map → chunk-HAZVVOYT.js.map} +0 -0
- /package/dist/{chunk-OT5K26NG.js.map → chunk-HM6UJPPO.js.map} +0 -0
- /package/dist/{chunk-PI4JHLDD.js.map → chunk-IP5SANO2.js.map} +0 -0
- /package/dist/{chunk-WHEF76BQ.js.map → chunk-JRZV3767.js.map} +0 -0
- /package/dist/{chunk-OS5RKJOH.js.map → chunk-JZ7P26GF.js.map} +0 -0
- /package/dist/{chunk-Y62QPRKV.js.map → chunk-K5LLP4CY.js.map} +0 -0
- /package/dist/{chunk-C3Z5YJSM.js.map → chunk-LOPZ2DWR.js.map} +0 -0
- /package/dist/{chunk-BJPL5WAL.js.map → chunk-MXDG6SRH.js.map} +0 -0
- /package/dist/{chunk-UYYSOMS2.js.map → chunk-NBP3YHHS.js.map} +0 -0
- /package/dist/{chunk-USHVHI6J.js.map → chunk-NNL4LJAD.js.map} +0 -0
- /package/dist/{chunk-GPX5E36D.js.map → chunk-OSMBC3JU.js.map} +0 -0
- /package/dist/{chunk-OUSOMUFV.js.map → chunk-PE6XR4GG.js.map} +0 -0
- /package/dist/{chunk-CMPXLMC3.js.map → chunk-PI23H7FV.js.map} +0 -0
- /package/dist/{chunk-WGDE2TJP.js.map → chunk-QOGXUNWL.js.map} +0 -0
- /package/dist/{chunk-ELL5VYXC.js.map → chunk-RNWWAS5V.js.map} +0 -0
- /package/dist/{chunk-JMMSVRF4.js.map → chunk-TQPSOTC7.js.map} +0 -0
- /package/dist/{chunk-AX4TRSRE.js.map → chunk-U5WVRMCA.js.map} +0 -0
- /package/dist/{chunk-7ADHJ6SU.js.map → chunk-VE54E6RP.js.map} +0 -0
- /package/dist/{chunk-OVYBENIJ.js.map → chunk-W3M34XT4.js.map} +0 -0
- /package/dist/{chunk-NHJYUIII.js.map → chunk-WPLRJ4XM.js.map} +0 -0
- /package/dist/{chunk-UEIF7RWQ.js.map → chunk-XEADGIAA.js.map} +0 -0
- /package/dist/{contradiction-scan-UERKJESC.js.map → contradiction-scan-3FJYWS3G.js.map} +0 -0
- /package/dist/{first-start-migration-GQ3UQNIL.js.map → first-start-migration-4I3VDSYS.js.map} +0 -0
- /package/dist/{tier-stats-CSKL7BDG.js.map → tier-stats-5XF4UBRQ.js.map} +0 -0
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
} from "./chunk-C7LDPZJJ.js";
|
|
8
8
|
import {
|
|
9
9
|
CompressionGuidelineCoordinator
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5QANTTY2.js";
|
|
11
11
|
import {
|
|
12
12
|
MaintenanceScheduler
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-MXDG6SRH.js";
|
|
14
14
|
import {
|
|
15
15
|
runPeerProfileReasoner
|
|
16
16
|
} from "./chunk-I74SUMNI.js";
|
|
@@ -29,10 +29,10 @@ import {
|
|
|
29
29
|
import {
|
|
30
30
|
CompoundingEngine,
|
|
31
31
|
defaultTierMigrationCycleBudget
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-CHELXDTO.js";
|
|
33
33
|
import {
|
|
34
34
|
SharedContextManager
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-JRZV3767.js";
|
|
36
36
|
import {
|
|
37
37
|
applyTrustScoreStage,
|
|
38
38
|
buildTrustSignalsForRerank,
|
|
@@ -63,7 +63,7 @@ import {
|
|
|
63
63
|
} from "./chunk-UHGBNIOS.js";
|
|
64
64
|
import {
|
|
65
65
|
HourlySummarizer
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-NNL4LJAD.js";
|
|
67
67
|
import {
|
|
68
68
|
buildTargetedFactRecallSection,
|
|
69
69
|
shouldRecallTargetedFactEvidence
|
|
@@ -160,7 +160,7 @@ import {
|
|
|
160
160
|
} from "./chunk-LTHVM4XN.js";
|
|
161
161
|
import {
|
|
162
162
|
ExtractionEngine
|
|
163
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-QOGXUNWL.js";
|
|
164
164
|
import {
|
|
165
165
|
parseMemoryActionEligibilityContext
|
|
166
166
|
} from "./chunk-5GSUBCZM.js";
|
|
@@ -169,7 +169,7 @@ import {
|
|
|
169
169
|
} from "./chunk-PWFWCGOO.js";
|
|
170
170
|
import {
|
|
171
171
|
LocalLlmClient
|
|
172
|
-
} from "./chunk-
|
|
172
|
+
} from "./chunk-DBSMLRTO.js";
|
|
173
173
|
import {
|
|
174
174
|
buildFocusedListRecallSection,
|
|
175
175
|
shouldRecallFocusedListEvidence
|
|
@@ -187,18 +187,18 @@ import {
|
|
|
187
187
|
} from "./chunk-4463LUIE.js";
|
|
188
188
|
import {
|
|
189
189
|
formatDaySummaryMemories
|
|
190
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-LOPZ2DWR.js";
|
|
191
191
|
import {
|
|
192
192
|
tryDirectAnswer
|
|
193
193
|
} from "./chunk-Q6IP2ARR.js";
|
|
194
194
|
import {
|
|
195
195
|
EmbeddingFallback
|
|
196
|
-
} from "./chunk-
|
|
196
|
+
} from "./chunk-OSMBC3JU.js";
|
|
197
197
|
import {
|
|
198
198
|
buildEntityRecallSection,
|
|
199
199
|
entityRecentTranscriptLookbackHours,
|
|
200
200
|
readRecentEntityTranscriptEntries
|
|
201
|
-
} from "./chunk-
|
|
201
|
+
} from "./chunk-E7RGJQWP.js";
|
|
202
202
|
import {
|
|
203
203
|
RoutingRulesStore
|
|
204
204
|
} from "./chunk-WIWPSQYU.js";
|
|
@@ -228,14 +228,14 @@ import {
|
|
|
228
228
|
import {
|
|
229
229
|
runNamespaceMaintenanceFanout,
|
|
230
230
|
summarizeNamespaceMaintenanceHealth
|
|
231
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-AVBT5WEW.js";
|
|
232
232
|
import {
|
|
233
233
|
NamespaceCatalog,
|
|
234
234
|
planNamespaceMaintenance
|
|
235
|
-
} from "./chunk-
|
|
235
|
+
} from "./chunk-3EA5LIFJ.js";
|
|
236
236
|
import {
|
|
237
237
|
NamespaceStorageRouter
|
|
238
|
-
} from "./chunk-
|
|
238
|
+
} from "./chunk-U5WVRMCA.js";
|
|
239
239
|
import {
|
|
240
240
|
searchHarmonicRetrieval
|
|
241
241
|
} from "./chunk-AV5ZEH4M.js";
|
|
@@ -270,7 +270,7 @@ import {
|
|
|
270
270
|
materializeAfterSemanticConsolidation,
|
|
271
271
|
parseConsolidationResponse,
|
|
272
272
|
parseOperatorAwareConsolidationResponse
|
|
273
|
-
} from "./chunk-
|
|
273
|
+
} from "./chunk-IP5SANO2.js";
|
|
274
274
|
import {
|
|
275
275
|
buildRecallQueryPolicy
|
|
276
276
|
} from "./chunk-LBJBNWS2.js";
|
|
@@ -292,7 +292,7 @@ import {
|
|
|
292
292
|
} from "./chunk-UQ7RN5HK.js";
|
|
293
293
|
import {
|
|
294
294
|
SmartBuffer
|
|
295
|
-
} from "./chunk-
|
|
295
|
+
} from "./chunk-JZ7P26GF.js";
|
|
296
296
|
import {
|
|
297
297
|
isDisagreementPrompt
|
|
298
298
|
} from "./chunk-H3FZVNRN.js";
|
|
@@ -311,7 +311,7 @@ import {
|
|
|
311
311
|
clusterByKey,
|
|
312
312
|
createCorrectionService,
|
|
313
313
|
detectPassiveCorrections
|
|
314
|
-
} from "./chunk-
|
|
314
|
+
} from "./chunk-A2KKLCOS.js";
|
|
315
315
|
import {
|
|
316
316
|
listTrustZoneRecords,
|
|
317
317
|
searchTrustZoneRecords
|
|
@@ -333,14 +333,14 @@ import {
|
|
|
333
333
|
resolveNamespaceFromStorageDir,
|
|
334
334
|
resolveScopePlan,
|
|
335
335
|
resolveScopeProfilePlan
|
|
336
|
-
} from "./chunk-
|
|
336
|
+
} from "./chunk-W3M34XT4.js";
|
|
337
337
|
import {
|
|
338
338
|
NamespaceSearchRouter
|
|
339
|
-
} from "./chunk-
|
|
339
|
+
} from "./chunk-HAZVVOYT.js";
|
|
340
340
|
import {
|
|
341
341
|
createConversationIndexRuntime,
|
|
342
342
|
createSearchBackend
|
|
343
|
-
} from "./chunk-
|
|
343
|
+
} from "./chunk-RNWWAS5V.js";
|
|
344
344
|
import {
|
|
345
345
|
NoopSearchBackend
|
|
346
346
|
} from "./chunk-CYEPCZN5.js";
|
|
@@ -363,7 +363,7 @@ import {
|
|
|
363
363
|
} from "./chunk-QDW3E4RD.js";
|
|
364
364
|
import {
|
|
365
365
|
shouldSkipImplicitExtraction
|
|
366
|
-
} from "./chunk-
|
|
366
|
+
} from "./chunk-K5LLP4CY.js";
|
|
367
367
|
import {
|
|
368
368
|
searchCausalTrajectories
|
|
369
369
|
} from "./chunk-SQNED75R.js";
|
|
@@ -465,7 +465,7 @@ import {
|
|
|
465
465
|
defaultNamespaceForPrincipal,
|
|
466
466
|
recallNamespacesForPrincipal,
|
|
467
467
|
resolvePrincipal
|
|
468
|
-
} from "./chunk-
|
|
468
|
+
} from "./chunk-PE6XR4GG.js";
|
|
469
469
|
import {
|
|
470
470
|
isSafeRouteNamespace,
|
|
471
471
|
selectRouteRule
|
|
@@ -491,7 +491,7 @@ import {
|
|
|
491
491
|
resolveRecallEnhancementCapabilities,
|
|
492
492
|
resolveSecurityCapabilities,
|
|
493
493
|
resolveUtilityLearningCapabilities
|
|
494
|
-
} from "./chunk-
|
|
494
|
+
} from "./chunk-VSF7AAGE.js";
|
|
495
495
|
import {
|
|
496
496
|
sanitizeMemoryContent
|
|
497
497
|
} from "./chunk-5GKPFL3S.js";
|
|
@@ -512,19 +512,19 @@ import {
|
|
|
512
512
|
} from "./chunk-PVGDJXVK.js";
|
|
513
513
|
|
|
514
514
|
// src/orchestrator.ts
|
|
515
|
-
import
|
|
515
|
+
import path7 from "path";
|
|
516
516
|
import os2 from "os";
|
|
517
|
-
import { createHash as
|
|
517
|
+
import { createHash as createHash3, randomBytes } from "crypto";
|
|
518
518
|
import { existsSync, readFileSync } from "fs";
|
|
519
519
|
import {
|
|
520
520
|
lstat,
|
|
521
|
-
mkdir as
|
|
521
|
+
mkdir as mkdir4,
|
|
522
522
|
readdir as readdir2,
|
|
523
523
|
readFile as readFile2,
|
|
524
524
|
realpath,
|
|
525
525
|
stat,
|
|
526
526
|
unlink,
|
|
527
|
-
writeFile as
|
|
527
|
+
writeFile as writeFile4
|
|
528
528
|
} from "fs/promises";
|
|
529
529
|
|
|
530
530
|
// src/procedural/procedure-recall.ts
|
|
@@ -2196,7 +2196,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2196
2196
|
nsMap = buildMemoryWorthCounterMap(memories);
|
|
2197
2197
|
this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });
|
|
2198
2198
|
}
|
|
2199
|
-
for (const [
|
|
2199
|
+
for (const [path8, c] of nsMap) counters.set(path8, c);
|
|
2200
2200
|
} catch (err) {
|
|
2201
2201
|
log.debug("memory-worth: failed to read namespace, skipping", {
|
|
2202
2202
|
namespace: ns,
|
|
@@ -2281,7 +2281,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2281
2281
|
namespaces,
|
|
2282
2282
|
{
|
|
2283
2283
|
readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),
|
|
2284
|
-
readMemoryFrontmatter: async (
|
|
2284
|
+
readMemoryFrontmatter: async (path8) => {
|
|
2285
2285
|
if (!fallbackReader) {
|
|
2286
2286
|
for (const ns of namespaces) {
|
|
2287
2287
|
try {
|
|
@@ -2292,7 +2292,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2292
2292
|
}
|
|
2293
2293
|
}
|
|
2294
2294
|
if (!fallbackReader) return null;
|
|
2295
|
-
const memory = await this.readQmdResultMemory(
|
|
2295
|
+
const memory = await this.readQmdResultMemory(path8, fallbackReader, namespaces);
|
|
2296
2296
|
return memory ? memory.frontmatter : null;
|
|
2297
2297
|
}
|
|
2298
2298
|
},
|
|
@@ -2391,6 +2391,210 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2391
2391
|
}
|
|
2392
2392
|
};
|
|
2393
2393
|
|
|
2394
|
+
// src/orchestration/recall-section-coordinator.ts
|
|
2395
|
+
var RecallSectionCoordinator = class {
|
|
2396
|
+
getConfig;
|
|
2397
|
+
resolveSectionEnabled;
|
|
2398
|
+
constructor(options) {
|
|
2399
|
+
this.getConfig = options.getConfig;
|
|
2400
|
+
this.resolveSectionEnabled = options.resolveSectionEnabled ?? ((id, def) => this.isRecallSectionEnabled(id, def));
|
|
2401
|
+
}
|
|
2402
|
+
getRecallSectionEntry(sectionId) {
|
|
2403
|
+
const pipeline = Array.isArray(this.getConfig().recallPipeline) ? this.getConfig().recallPipeline : [];
|
|
2404
|
+
return pipeline.find((entry) => entry.id === sectionId);
|
|
2405
|
+
}
|
|
2406
|
+
isRecallSectionEnabled(sectionId, defaultEnabled = true) {
|
|
2407
|
+
const entry = this.getRecallSectionEntry(sectionId);
|
|
2408
|
+
if (!entry) return defaultEnabled;
|
|
2409
|
+
return entry.enabled !== false;
|
|
2410
|
+
}
|
|
2411
|
+
isSpecializedRecallSectionEnabled(sectionId, topLevelEnabled) {
|
|
2412
|
+
const entry = this.getRecallSectionEntry(sectionId);
|
|
2413
|
+
if (!entry) return topLevelEnabled;
|
|
2414
|
+
return entry.enabled === true || topLevelEnabled && entry.enabled !== false;
|
|
2415
|
+
}
|
|
2416
|
+
getRecallSectionMaxChars(sectionId) {
|
|
2417
|
+
const entry = this.getRecallSectionEntry(sectionId);
|
|
2418
|
+
if (!entry) return void 0;
|
|
2419
|
+
if (entry.maxChars === null) return null;
|
|
2420
|
+
if (typeof entry.maxChars !== "number") return void 0;
|
|
2421
|
+
return Math.max(0, Math.floor(entry.maxChars));
|
|
2422
|
+
}
|
|
2423
|
+
getRecallSectionNumber(sectionId, key) {
|
|
2424
|
+
const entry = this.getRecallSectionEntry(sectionId);
|
|
2425
|
+
if (!entry) return void 0;
|
|
2426
|
+
const value = entry[key];
|
|
2427
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
2428
|
+
return Math.max(0, Math.floor(value));
|
|
2429
|
+
}
|
|
2430
|
+
appendRecallSection(sectionBuckets, sectionId, content) {
|
|
2431
|
+
if (!this.resolveSectionEnabled(sectionId, true)) return false;
|
|
2432
|
+
const trimmed = content.trim();
|
|
2433
|
+
if (trimmed.length === 0) return false;
|
|
2434
|
+
const maxChars = this.getRecallSectionMaxChars(sectionId);
|
|
2435
|
+
let finalContent = trimmed;
|
|
2436
|
+
if (maxChars === 0) return false;
|
|
2437
|
+
if (typeof maxChars === "number" && finalContent.length > maxChars) {
|
|
2438
|
+
finalContent = `${finalContent.slice(0, maxChars)}
|
|
2439
|
+
|
|
2440
|
+
...(trimmed)
|
|
2441
|
+
`;
|
|
2442
|
+
}
|
|
2443
|
+
const existing = sectionBuckets.get(sectionId) ?? [];
|
|
2444
|
+
existing.push(finalContent);
|
|
2445
|
+
sectionBuckets.set(sectionId, existing);
|
|
2446
|
+
return true;
|
|
2447
|
+
}
|
|
2448
|
+
truncateRecallSectionToBudget(content, maxChars) {
|
|
2449
|
+
if (maxChars <= 0) return "";
|
|
2450
|
+
if (content.length <= maxChars) return content;
|
|
2451
|
+
const suffix = "\n\n...(memory context trimmed)";
|
|
2452
|
+
if (maxChars <= suffix.length) {
|
|
2453
|
+
return content.slice(0, maxChars);
|
|
2454
|
+
}
|
|
2455
|
+
return `${content.slice(0, maxChars - suffix.length)}${suffix}`;
|
|
2456
|
+
}
|
|
2457
|
+
protectedRecallSectionIds(sectionBuckets) {
|
|
2458
|
+
const protectedIds = /* @__PURE__ */ new Set();
|
|
2459
|
+
if ((sectionBuckets.get("memories")?.length ?? 0) > 0) {
|
|
2460
|
+
protectedIds.add("memories");
|
|
2461
|
+
}
|
|
2462
|
+
return protectedIds;
|
|
2463
|
+
}
|
|
2464
|
+
protectedRecallReservationChars(content) {
|
|
2465
|
+
const headingBoundary = content.indexOf("\n\n");
|
|
2466
|
+
const headingChars = headingBoundary >= 0 ? headingBoundary + 2 : Math.min(content.length, 24);
|
|
2467
|
+
return Math.min(content.length, Math.max(headingChars, 24));
|
|
2468
|
+
}
|
|
2469
|
+
estimateReservedRecallBudget(entries, startIndex, protectedIds, alreadyIncludedCount) {
|
|
2470
|
+
const separatorLength = "\n\n---\n\n".length;
|
|
2471
|
+
let reserved = 0;
|
|
2472
|
+
let simulatedIncluded = alreadyIncludedCount;
|
|
2473
|
+
for (let i = startIndex; i < entries.length; i += 1) {
|
|
2474
|
+
const entry = entries[i];
|
|
2475
|
+
if (!entry || !protectedIds.has(entry.id)) continue;
|
|
2476
|
+
if (simulatedIncluded > 0) {
|
|
2477
|
+
reserved += separatorLength;
|
|
2478
|
+
}
|
|
2479
|
+
reserved += this.protectedRecallReservationChars(entry.content);
|
|
2480
|
+
simulatedIncluded += 1;
|
|
2481
|
+
}
|
|
2482
|
+
return reserved;
|
|
2483
|
+
}
|
|
2484
|
+
getRecallBudgetChars(override) {
|
|
2485
|
+
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
2486
|
+
return Math.floor(override);
|
|
2487
|
+
}
|
|
2488
|
+
const configuredBudget = this.getConfig().recallBudgetChars;
|
|
2489
|
+
if (typeof configuredBudget === "number" && Number.isFinite(configuredBudget) && configuredBudget >= 0) {
|
|
2490
|
+
return Math.floor(configuredBudget);
|
|
2491
|
+
}
|
|
2492
|
+
const tokenBudget = this.getConfig().maxMemoryTokens;
|
|
2493
|
+
if (typeof tokenBudget === "number" && Number.isFinite(tokenBudget) && tokenBudget >= 0) {
|
|
2494
|
+
return Math.floor(tokenBudget * 4);
|
|
2495
|
+
}
|
|
2496
|
+
return 0;
|
|
2497
|
+
}
|
|
2498
|
+
assembleRecallSections(sectionBuckets, budgetOverride) {
|
|
2499
|
+
const orderedEntries = [];
|
|
2500
|
+
const pipeline = Array.isArray(this.getConfig().recallPipeline) ? this.getConfig().recallPipeline : [];
|
|
2501
|
+
const orderedIds = pipeline.filter((entry) => entry.enabled !== false).map((entry) => entry.id);
|
|
2502
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2503
|
+
for (const id of orderedIds) {
|
|
2504
|
+
const chunks = sectionBuckets.get(id);
|
|
2505
|
+
if (!chunks || chunks.length === 0) continue;
|
|
2506
|
+
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
2507
|
+
seen.add(id);
|
|
2508
|
+
}
|
|
2509
|
+
for (const [id, chunks] of sectionBuckets.entries()) {
|
|
2510
|
+
if (seen.has(id)) continue;
|
|
2511
|
+
if (chunks.length === 0) continue;
|
|
2512
|
+
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
2513
|
+
}
|
|
2514
|
+
const budget = this.getRecallBudgetChars(budgetOverride);
|
|
2515
|
+
if (budget === 0) {
|
|
2516
|
+
return {
|
|
2517
|
+
sections: [],
|
|
2518
|
+
includedIds: [],
|
|
2519
|
+
omittedIds: orderedEntries.map((entry) => entry.id),
|
|
2520
|
+
truncated: orderedEntries.length > 0,
|
|
2521
|
+
finalChars: 0
|
|
2522
|
+
};
|
|
2523
|
+
}
|
|
2524
|
+
const separator = "\n\n---\n\n";
|
|
2525
|
+
const protectedIds = this.protectedRecallSectionIds(sectionBuckets);
|
|
2526
|
+
const sections = [];
|
|
2527
|
+
const includedIds = [];
|
|
2528
|
+
const omittedIds = [];
|
|
2529
|
+
let usedChars = 0;
|
|
2530
|
+
let truncated = false;
|
|
2531
|
+
for (let index = 0; index < orderedEntries.length; index += 1) {
|
|
2532
|
+
const entry = orderedEntries[index];
|
|
2533
|
+
const separatorChars = sections.length > 0 ? separator.length : 0;
|
|
2534
|
+
const reserve = protectedIds.has(entry.id) ? 0 : this.estimateReservedRecallBudget(
|
|
2535
|
+
orderedEntries,
|
|
2536
|
+
index + 1,
|
|
2537
|
+
protectedIds,
|
|
2538
|
+
sections.length + 1
|
|
2539
|
+
);
|
|
2540
|
+
const availableForEntry = budget - usedChars - separatorChars - reserve;
|
|
2541
|
+
if (availableForEntry <= 0) {
|
|
2542
|
+
omittedIds.push(entry.id);
|
|
2543
|
+
truncated = true;
|
|
2544
|
+
continue;
|
|
2545
|
+
}
|
|
2546
|
+
const finalContent = this.truncateRecallSectionToBudget(
|
|
2547
|
+
entry.content,
|
|
2548
|
+
availableForEntry
|
|
2549
|
+
);
|
|
2550
|
+
if (!finalContent) {
|
|
2551
|
+
omittedIds.push(entry.id);
|
|
2552
|
+
truncated = true;
|
|
2553
|
+
continue;
|
|
2554
|
+
}
|
|
2555
|
+
if (finalContent.length < entry.content.length) {
|
|
2556
|
+
truncated = true;
|
|
2557
|
+
}
|
|
2558
|
+
sections.push(finalContent);
|
|
2559
|
+
includedIds.push(entry.id);
|
|
2560
|
+
usedChars += separatorChars + finalContent.length;
|
|
2561
|
+
}
|
|
2562
|
+
return {
|
|
2563
|
+
sections,
|
|
2564
|
+
includedIds,
|
|
2565
|
+
omittedIds,
|
|
2566
|
+
truncated,
|
|
2567
|
+
finalChars: usedChars
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
buildLastRecallBudgetSummary(options) {
|
|
2571
|
+
return {
|
|
2572
|
+
requestedTopK: options.requestedTopK,
|
|
2573
|
+
appliedTopK: options.recallResultLimit,
|
|
2574
|
+
recallBudgetChars: this.getRecallBudgetChars(),
|
|
2575
|
+
maxMemoryTokens: this.getConfig().maxMemoryTokens,
|
|
2576
|
+
qmdFetchLimit: options.qmdFetchLimit,
|
|
2577
|
+
qmdHybridFetchLimit: options.qmdHybridFetchLimit,
|
|
2578
|
+
finalContextChars: options.finalContextChars,
|
|
2579
|
+
truncated: options.truncated,
|
|
2580
|
+
includedSections: [...options.includedSections ?? []],
|
|
2581
|
+
omittedSections: [...options.omittedSections ?? []]
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
collectLastRecallSources(sectionBuckets, recallSource) {
|
|
2585
|
+
const used = /* @__PURE__ */ new Set();
|
|
2586
|
+
if (recallSource !== "none") {
|
|
2587
|
+
used.add(recallSource);
|
|
2588
|
+
}
|
|
2589
|
+
for (const [sectionId, chunks] of sectionBuckets.entries()) {
|
|
2590
|
+
if (chunks.length > 0) {
|
|
2591
|
+
used.add(sectionId);
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
return [...used];
|
|
2595
|
+
}
|
|
2596
|
+
};
|
|
2597
|
+
|
|
2394
2598
|
// src/orchestration/qmd-result-resolver.ts
|
|
2395
2599
|
import path4 from "path";
|
|
2396
2600
|
function qmdCollectionPathParts(resultPath) {
|
|
@@ -2642,63 +2846,522 @@ var QmdResultResolver = class {
|
|
|
2642
2846
|
}
|
|
2643
2847
|
};
|
|
2644
2848
|
|
|
2645
|
-
// src/
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
cmp = instant - bestInstant;
|
|
2663
|
-
} else {
|
|
2664
|
-
cmp = stamp.localeCompare(bestStamp);
|
|
2665
|
-
}
|
|
2666
|
-
if (cmp > 0 || cmp === 0 && candidate.frontmatter.id > best.frontmatter.id) {
|
|
2667
|
-
best = candidate;
|
|
2668
|
-
bestInstant = instant;
|
|
2669
|
-
bestStamp = stamp;
|
|
2670
|
-
}
|
|
2671
|
-
}
|
|
2672
|
-
return best;
|
|
2673
|
-
}
|
|
2674
|
-
function memoryStamp(memory) {
|
|
2675
|
-
return memory.frontmatter.updated || memory.frontmatter.created || "";
|
|
2676
|
-
}
|
|
2677
|
-
function memoryInstant(memory) {
|
|
2678
|
-
const stamp = memoryStamp(memory);
|
|
2679
|
-
if (stamp.length === 0) return null;
|
|
2680
|
-
const parsed = Date.parse(stamp);
|
|
2681
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
2682
|
-
}
|
|
2683
|
-
var ACTIVE_STATUS = "active";
|
|
2684
|
-
async function runPatternReinforcement(storage, options) {
|
|
2685
|
-
const minCount = Math.max(2, Math.floor(options.minCount));
|
|
2686
|
-
const targetCategories = new Set(options.categories);
|
|
2687
|
-
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
2688
|
-
const nowIso = now().toISOString();
|
|
2689
|
-
if (targetCategories.size === 0) {
|
|
2690
|
-
return emptyResult();
|
|
2849
|
+
// src/orchestration/contradiction-linking-coordinator.ts
|
|
2850
|
+
var ContradictionLinkingCoordinator = class {
|
|
2851
|
+
getConfig;
|
|
2852
|
+
isSearchAvailable;
|
|
2853
|
+
searchAcrossNamespaces;
|
|
2854
|
+
extractMemoryIdsFromResults;
|
|
2855
|
+
namespaceFromPath;
|
|
2856
|
+
storageForNamespace;
|
|
2857
|
+
getExtraction;
|
|
2858
|
+
constructor(options) {
|
|
2859
|
+
this.getConfig = options.getConfig;
|
|
2860
|
+
this.isSearchAvailable = options.isSearchAvailable;
|
|
2861
|
+
this.searchAcrossNamespaces = options.searchAcrossNamespaces;
|
|
2862
|
+
this.extractMemoryIdsFromResults = options.extractMemoryIdsFromResults;
|
|
2863
|
+
this.namespaceFromPath = options.namespaceFromPath;
|
|
2864
|
+
this.storageForNamespace = options.storageForNamespace;
|
|
2865
|
+
this.getExtraction = options.getExtraction;
|
|
2691
2866
|
}
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2867
|
+
/**
|
|
2868
|
+
* Check if a new memory contradicts an existing one.
|
|
2869
|
+
* Uses QMD to find similar memories, then LLM to verify contradiction.
|
|
2870
|
+
*/
|
|
2871
|
+
async checkForContradiction(content, category, namespaceScope) {
|
|
2872
|
+
if (!this.isSearchAvailable()) return null;
|
|
2873
|
+
const config = this.getConfig();
|
|
2874
|
+
const results = await this.searchAcrossNamespaces({
|
|
2875
|
+
query: content,
|
|
2876
|
+
namespaces: [namespaceScope],
|
|
2877
|
+
maxResults: 5,
|
|
2878
|
+
mode: "search"
|
|
2879
|
+
});
|
|
2880
|
+
for (const result of results) {
|
|
2881
|
+
if (result.score < config.contradictionSimilarityThreshold) {
|
|
2882
|
+
continue;
|
|
2883
|
+
}
|
|
2884
|
+
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
2885
|
+
if (!memoryId) continue;
|
|
2886
|
+
const resultNamespace = this.namespaceFromPath(result.path);
|
|
2887
|
+
if (resultNamespace !== namespaceScope) continue;
|
|
2888
|
+
const resultStorage = await this.storageForNamespace(resultNamespace);
|
|
2889
|
+
const existingMemory = await resultStorage.getMemoryById(memoryId);
|
|
2890
|
+
if (!existingMemory) continue;
|
|
2891
|
+
if (existingMemory.frontmatter.status === "superseded" || existingMemory.frontmatter.status === "forgotten") {
|
|
2892
|
+
continue;
|
|
2893
|
+
}
|
|
2894
|
+
const extraction = this.getExtraction();
|
|
2895
|
+
const verification = await extraction.verifyContradiction(
|
|
2896
|
+
{ content, category },
|
|
2897
|
+
{
|
|
2898
|
+
id: existingMemory.frontmatter.id,
|
|
2899
|
+
content: existingMemory.content,
|
|
2900
|
+
category: existingMemory.frontmatter.category,
|
|
2901
|
+
created: existingMemory.frontmatter.created
|
|
2902
|
+
}
|
|
2903
|
+
);
|
|
2904
|
+
if (!verification) continue;
|
|
2905
|
+
if (verification.isContradiction && verification.confidence >= config.contradictionMinConfidence) {
|
|
2906
|
+
if (verification.whichIsNewer === "first") {
|
|
2907
|
+
log.info(
|
|
2908
|
+
`detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory \u2014 existing is newer, incoming fact is stale`
|
|
2909
|
+
);
|
|
2910
|
+
continue;
|
|
2911
|
+
}
|
|
2912
|
+
log.info(
|
|
2913
|
+
`detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory${config.contradictionAutoResolve ? " (auto-resolved)" : " (queued for manual review)"}`
|
|
2914
|
+
);
|
|
2915
|
+
return {
|
|
2916
|
+
supersededId: existingMemory.frontmatter.id,
|
|
2917
|
+
confidence: verification.confidence,
|
|
2918
|
+
reason: verification.reasoning,
|
|
2919
|
+
supersededPath: existingMemory.path,
|
|
2920
|
+
supersededCreated: existingMemory.frontmatter.created,
|
|
2921
|
+
supersededTags: existingMemory.frontmatter.tags ?? []
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
return null;
|
|
2926
|
+
}
|
|
2927
|
+
/**
|
|
2928
|
+
* #1645: Complete the deferred contradiction auto-resolve after writeMemory
|
|
2929
|
+
* returns and the new write's tombstone status is known. Retires the old
|
|
2930
|
+
* memory + deindexes it ONLY when the new write is genuinely active (not
|
|
2931
|
+
* tombstone-blocked / pending_review). A blocked write must not retire the
|
|
2932
|
+
* only active copy — deferring here closes the "contradictionAutoResolve
|
|
2933
|
+
* supersedes before tombstone status is known" defect class.
|
|
2934
|
+
*/
|
|
2935
|
+
async applyDeferredContradictionResolve(contradiction, storage, newMemoryId, postWriteGuard) {
|
|
2936
|
+
const config = this.getConfig();
|
|
2937
|
+
if (postWriteGuard && contradiction && config.contradictionAutoResolve) {
|
|
2938
|
+
try {
|
|
2939
|
+
const blockedRow = await storage.getMemoryById(newMemoryId);
|
|
2940
|
+
if (blockedRow?.frontmatter?.supersedes) {
|
|
2941
|
+
await storage.writeMemoryFrontmatter(blockedRow, { supersedes: void 0 });
|
|
2942
|
+
}
|
|
2943
|
+
} catch (err) {
|
|
2944
|
+
log.warn(
|
|
2945
|
+
`contradiction auto-resolve supersedes clear failed for blocked ${newMemoryId}: ${err}`
|
|
2946
|
+
);
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
if (!contradiction || !config.contradictionAutoResolve || postWriteGuard) {
|
|
2950
|
+
return;
|
|
2951
|
+
}
|
|
2952
|
+
try {
|
|
2953
|
+
await storage.supersedeMemory(
|
|
2954
|
+
contradiction.supersededId,
|
|
2955
|
+
newMemoryId,
|
|
2956
|
+
contradiction.reason
|
|
2957
|
+
);
|
|
2958
|
+
if (resolveIndexingCapabilities(config).queryAwareIndexing && contradiction.supersededPath) {
|
|
2959
|
+
deindexMemory(
|
|
2960
|
+
config.memoryDir,
|
|
2961
|
+
contradiction.supersededPath,
|
|
2962
|
+
contradiction.supersededCreated,
|
|
2963
|
+
contradiction.supersededTags
|
|
2964
|
+
);
|
|
2965
|
+
}
|
|
2966
|
+
} catch (err) {
|
|
2967
|
+
log.warn(
|
|
2968
|
+
`contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
// ---------------------------------------------------------------------------
|
|
2973
|
+
// Memory Linking (Phase 3A)
|
|
2974
|
+
// ---------------------------------------------------------------------------
|
|
2975
|
+
/**
|
|
2976
|
+
* Suggest links for a new memory based on similar existing memories.
|
|
2977
|
+
*/
|
|
2978
|
+
async suggestLinksForMemory(content, category, namespaceScope) {
|
|
2979
|
+
if (!this.isSearchAvailable()) return [];
|
|
2980
|
+
const results = await this.searchAcrossNamespaces({
|
|
2981
|
+
query: content,
|
|
2982
|
+
namespaces: [namespaceScope],
|
|
2983
|
+
maxResults: 5,
|
|
2984
|
+
mode: "search"
|
|
2985
|
+
});
|
|
2986
|
+
if (results.length === 0) return [];
|
|
2987
|
+
const candidates = [];
|
|
2988
|
+
for (const result of results) {
|
|
2989
|
+
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
2990
|
+
if (!memoryId) continue;
|
|
2991
|
+
const resultNamespace = this.namespaceFromPath(result.path);
|
|
2992
|
+
if (resultNamespace !== namespaceScope) continue;
|
|
2993
|
+
const resultStorage = await this.storageForNamespace(resultNamespace);
|
|
2994
|
+
const memory = await resultStorage.getMemoryById(memoryId);
|
|
2995
|
+
if (memory && memory.frontmatter.status !== "superseded" && memory.frontmatter.status !== "forgotten") {
|
|
2996
|
+
candidates.push({
|
|
2997
|
+
id: memory.frontmatter.id,
|
|
2998
|
+
content: memory.content,
|
|
2999
|
+
category: memory.frontmatter.category
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
if (candidates.length === 0) return [];
|
|
3004
|
+
const extraction = this.getExtraction();
|
|
3005
|
+
const suggestions = await extraction.suggestLinks(
|
|
3006
|
+
{ content, category },
|
|
3007
|
+
candidates
|
|
3008
|
+
);
|
|
3009
|
+
if (!suggestions || suggestions.links.length === 0) return [];
|
|
3010
|
+
return suggestions.links.map((link) => ({
|
|
3011
|
+
targetId: link.targetId,
|
|
3012
|
+
linkType: link.linkType,
|
|
3013
|
+
strength: link.strength,
|
|
3014
|
+
reason: link.reason || void 0
|
|
3015
|
+
}));
|
|
3016
|
+
}
|
|
3017
|
+
};
|
|
3018
|
+
|
|
3019
|
+
// src/orchestration/graph-recall-coordinator.ts
|
|
3020
|
+
import { createHash as createHash2 } from "crypto";
|
|
3021
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
3022
|
+
import path5 from "path";
|
|
3023
|
+
function mergeGraphExpandedResults(primary, expanded) {
|
|
3024
|
+
const mergedByPath = /* @__PURE__ */ new Map();
|
|
3025
|
+
for (const item of [...primary, ...expanded]) {
|
|
3026
|
+
const prev = mergedByPath.get(item.path);
|
|
3027
|
+
if (!prev) {
|
|
3028
|
+
mergedByPath.set(item.path, item);
|
|
3029
|
+
continue;
|
|
3030
|
+
}
|
|
3031
|
+
const better = item.score > prev.score ? item : prev;
|
|
3032
|
+
const snippet = prev.snippet || item.snippet;
|
|
3033
|
+
mergedByPath.set(item.path, { ...better, snippet });
|
|
3034
|
+
}
|
|
3035
|
+
return Array.from(mergedByPath.values());
|
|
3036
|
+
}
|
|
3037
|
+
function graphPathRelativeToStorage(storageDir, candidatePath) {
|
|
3038
|
+
const absolutePath = path5.isAbsolute(candidatePath) ? candidatePath : path5.resolve(storageDir, candidatePath);
|
|
3039
|
+
const rel = path5.relative(storageDir, absolutePath);
|
|
3040
|
+
if (!rel || rel === ".") return null;
|
|
3041
|
+
if (rel.startsWith("..")) return null;
|
|
3042
|
+
return rel.split(path5.sep).join("/");
|
|
3043
|
+
}
|
|
3044
|
+
function normalizeGraphActivationScore(score) {
|
|
3045
|
+
const bounded = Number.isFinite(score) && score > 0 ? score : 0;
|
|
3046
|
+
return bounded / (1 + bounded);
|
|
3047
|
+
}
|
|
3048
|
+
function blendGraphExpandedRecallScore(options) {
|
|
3049
|
+
const graphNorm = normalizeGraphActivationScore(options.graphActivationScore);
|
|
3050
|
+
const seedScore = Number.isFinite(options.seedRecallScore) ? Math.min(1, Math.max(0, options.seedRecallScore)) : 0;
|
|
3051
|
+
const weight = Math.min(1, Math.max(0, options.activationWeight));
|
|
3052
|
+
const rawMin = Math.min(1, Math.max(0, options.blendMin));
|
|
3053
|
+
const rawMax = Math.min(1, Math.max(0, options.blendMax));
|
|
3054
|
+
const minBound = Math.min(rawMin, rawMax);
|
|
3055
|
+
const maxBound = Math.max(rawMin, rawMax);
|
|
3056
|
+
const blended = graphNorm * weight + seedScore * (1 - weight);
|
|
3057
|
+
return Math.max(minBound, Math.min(maxBound, blended));
|
|
3058
|
+
}
|
|
3059
|
+
var GraphRecallCoordinator = class {
|
|
3060
|
+
getConfig;
|
|
3061
|
+
getStorage;
|
|
3062
|
+
storageFor;
|
|
3063
|
+
graphIndexFor;
|
|
3064
|
+
namespaceFromPath;
|
|
3065
|
+
resolveColdQmdResultForRecall;
|
|
3066
|
+
storageForAbsoluteQmdResultPath;
|
|
3067
|
+
readQmdResultMemory;
|
|
3068
|
+
constructor(options) {
|
|
3069
|
+
this.getConfig = options.getConfig;
|
|
3070
|
+
this.getStorage = options.getStorage;
|
|
3071
|
+
this.storageFor = options.storageFor;
|
|
3072
|
+
this.graphIndexFor = options.graphIndexFor;
|
|
3073
|
+
this.namespaceFromPath = options.namespaceFromPath;
|
|
3074
|
+
this.resolveColdQmdResultForRecall = options.resolveColdQmdResultForRecall;
|
|
3075
|
+
this.storageForAbsoluteQmdResultPath = options.storageForAbsoluteQmdResultPath;
|
|
3076
|
+
this.readQmdResultMemory = options.readQmdResultMemory;
|
|
3077
|
+
}
|
|
3078
|
+
async expandResultsViaGraph(options) {
|
|
3079
|
+
const config = this.getConfig();
|
|
3080
|
+
const deadlineExpired = () => typeof options.deadlineAtMs === "number" && Date.now() >= options.deadlineAtMs;
|
|
3081
|
+
const byNamespace = /* @__PURE__ */ new Map();
|
|
3082
|
+
const addResultForNamespace = (namespace, result) => {
|
|
3083
|
+
const existing = byNamespace.get(namespace);
|
|
3084
|
+
if (existing) {
|
|
3085
|
+
existing.push(result);
|
|
3086
|
+
} else {
|
|
3087
|
+
byNamespace.set(namespace, [result]);
|
|
3088
|
+
}
|
|
3089
|
+
};
|
|
3090
|
+
const resolvedAmbiguousSeeds = /* @__PURE__ */ new Map();
|
|
3091
|
+
const resolveAmbiguousSeedOwner = async (result, parts) => {
|
|
3092
|
+
const cached = resolvedAmbiguousSeeds.get(result.path);
|
|
3093
|
+
if (cached !== void 0) return cached;
|
|
3094
|
+
if (deadlineExpired()) {
|
|
3095
|
+
resolvedAmbiguousSeeds.set(result.path, null);
|
|
3096
|
+
return null;
|
|
3097
|
+
}
|
|
3098
|
+
let resolvedPath = result.path;
|
|
3099
|
+
let resolvedResult = result;
|
|
3100
|
+
if (parts) {
|
|
3101
|
+
const resolvedCold = await this.resolveColdQmdResultForRecall(
|
|
3102
|
+
result,
|
|
3103
|
+
this.getStorage(),
|
|
3104
|
+
options.recallNamespaces
|
|
3105
|
+
);
|
|
3106
|
+
if (!resolvedCold || deadlineExpired()) {
|
|
3107
|
+
resolvedAmbiguousSeeds.set(result.path, null);
|
|
3108
|
+
return null;
|
|
3109
|
+
}
|
|
3110
|
+
resolvedPath = resolvedCold.result.path;
|
|
3111
|
+
resolvedResult = resolvedCold.result;
|
|
3112
|
+
}
|
|
3113
|
+
if (!path5.isAbsolute(resolvedPath)) {
|
|
3114
|
+
resolvedAmbiguousSeeds.set(result.path, null);
|
|
3115
|
+
return null;
|
|
3116
|
+
}
|
|
3117
|
+
const ownerStorage = await this.storageForAbsoluteQmdResultPath(
|
|
3118
|
+
resolvedPath,
|
|
3119
|
+
this.getStorage(),
|
|
3120
|
+
options.recallNamespaces
|
|
3121
|
+
);
|
|
3122
|
+
const ownerNamespace = ownerStorage?.namespace ?? null;
|
|
3123
|
+
const resolved = ownerNamespace && options.recallNamespaces.includes(ownerNamespace) ? { namespace: ownerNamespace, result: resolvedResult } : null;
|
|
3124
|
+
resolvedAmbiguousSeeds.set(result.path, resolved);
|
|
3125
|
+
return resolved;
|
|
3126
|
+
};
|
|
3127
|
+
const coldCollection = config.qmdColdCollection ?? "openclaw-engram-cold";
|
|
3128
|
+
for (const result of options.memoryResults) {
|
|
3129
|
+
if (deadlineExpired()) break;
|
|
3130
|
+
const parts = qmdCollectionPathParts(result.path);
|
|
3131
|
+
if (parts?.collection === coldCollection) {
|
|
3132
|
+
const resolved = await resolveAmbiguousSeedOwner(result, parts);
|
|
3133
|
+
if (resolved) {
|
|
3134
|
+
addResultForNamespace(resolved.namespace, resolved.result);
|
|
3135
|
+
}
|
|
3136
|
+
continue;
|
|
3137
|
+
}
|
|
3138
|
+
if (path5.isAbsolute(result.path)) {
|
|
3139
|
+
const resolved = await resolveAmbiguousSeedOwner(result, null);
|
|
3140
|
+
if (resolved) {
|
|
3141
|
+
addResultForNamespace(resolved.namespace, resolved.result);
|
|
3142
|
+
}
|
|
3143
|
+
continue;
|
|
3144
|
+
}
|
|
3145
|
+
const ns = this.namespaceFromPath(result.path);
|
|
3146
|
+
if (!options.recallNamespaces.includes(ns)) continue;
|
|
3147
|
+
addResultForNamespace(ns, result);
|
|
3148
|
+
}
|
|
3149
|
+
const perNamespaceSeedCap = Math.max(3, options.recallResultLimit);
|
|
3150
|
+
const perNamespaceExpandedCap = Math.max(8, options.recallResultLimit * 2);
|
|
3151
|
+
const seedPaths = [];
|
|
3152
|
+
const seedResults = [];
|
|
3153
|
+
const expandedPaths = [];
|
|
3154
|
+
const expandedResults = [];
|
|
3155
|
+
for (const [namespace, nsResults] of byNamespace.entries()) {
|
|
3156
|
+
if (deadlineExpired()) break;
|
|
3157
|
+
const storage = await this.storageFor(namespace);
|
|
3158
|
+
const seedCandidates = nsResults.slice(0, perNamespaceSeedCap);
|
|
3159
|
+
seedResults.push(...seedCandidates);
|
|
3160
|
+
const seedRelativePaths = typeof options.deadlineAtMs === "number" ? await this.graphSeedPathsWithinDeadline(
|
|
3161
|
+
storage,
|
|
3162
|
+
seedCandidates,
|
|
3163
|
+
options.deadlineAtMs,
|
|
3164
|
+
[namespace]
|
|
3165
|
+
) : (await Promise.all(
|
|
3166
|
+
seedCandidates.map(
|
|
3167
|
+
(result) => this.graphSeedPathRelativeToStorage(storage, result, [
|
|
3168
|
+
namespace
|
|
3169
|
+
])
|
|
3170
|
+
)
|
|
3171
|
+
)).filter(
|
|
3172
|
+
(value) => typeof value === "string" && value.length > 0
|
|
3173
|
+
);
|
|
3174
|
+
if (deadlineExpired()) break;
|
|
3175
|
+
if (seedRelativePaths.length === 0) continue;
|
|
3176
|
+
const seedRecallScore = seedCandidates.reduce(
|
|
3177
|
+
(max, item) => Math.max(max, item.score),
|
|
3178
|
+
0
|
|
3179
|
+
);
|
|
3180
|
+
seedPaths.push(
|
|
3181
|
+
...seedRelativePaths.map((rel) => path5.join(storage.dir, rel))
|
|
3182
|
+
);
|
|
3183
|
+
const seedSet = new Set(seedRelativePaths);
|
|
3184
|
+
const expanded = await this.graphIndexFor(storage).spreadingActivation(
|
|
3185
|
+
seedRelativePaths,
|
|
3186
|
+
config.maxGraphTraversalSteps,
|
|
3187
|
+
{
|
|
3188
|
+
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {},
|
|
3189
|
+
...typeof options.deadlineAtMs === "number" ? { deadlineAtMs: options.deadlineAtMs } : {}
|
|
3190
|
+
}
|
|
3191
|
+
);
|
|
3192
|
+
if (expanded.length === 0) continue;
|
|
3193
|
+
if (deadlineExpired()) break;
|
|
3194
|
+
for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
|
|
3195
|
+
if (deadlineExpired()) break;
|
|
3196
|
+
if (seedSet.has(candidate.path)) continue;
|
|
3197
|
+
const memoryPath = path5.resolve(storage.dir, candidate.path);
|
|
3198
|
+
const memory = await storage.readMemoryByPath(memoryPath);
|
|
3199
|
+
if (deadlineExpired()) break;
|
|
3200
|
+
if (!memory) continue;
|
|
3201
|
+
if (/(?:^|[\\/])artifacts(?:[\\/]|$)/i.test(memory.path)) continue;
|
|
3202
|
+
if (memory.frontmatter.status && memory.frontmatter.status !== "active")
|
|
3203
|
+
continue;
|
|
3204
|
+
const snippet = memory.content.slice(0, 400);
|
|
3205
|
+
const score = blendGraphExpandedRecallScore({
|
|
3206
|
+
graphActivationScore: candidate.score,
|
|
3207
|
+
seedRecallScore,
|
|
3208
|
+
activationWeight: config.graphExpansionActivationWeight,
|
|
3209
|
+
blendMin: config.graphExpansionBlendMin,
|
|
3210
|
+
blendMax: config.graphExpansionBlendMax
|
|
3211
|
+
});
|
|
3212
|
+
expandedResults.push({
|
|
3213
|
+
docid: memory.frontmatter.id,
|
|
3214
|
+
path: memory.path,
|
|
3215
|
+
snippet,
|
|
3216
|
+
score
|
|
3217
|
+
});
|
|
3218
|
+
expandedPaths.push({
|
|
3219
|
+
path: memory.path,
|
|
3220
|
+
score,
|
|
3221
|
+
namespace,
|
|
3222
|
+
seed: path5.resolve(storage.dir, candidate.seed),
|
|
3223
|
+
hopDepth: candidate.hopDepth,
|
|
3224
|
+
decayedWeight: candidate.decayedWeight,
|
|
3225
|
+
graphType: candidate.graphType,
|
|
3226
|
+
// Issue #681 PR 3/3 — surface the per-edge confidence used for
|
|
3227
|
+
// PageRank weighting / floor pruning so downstream observability
|
|
3228
|
+
// (recall_xray, memory_graph_explain) can attribute ranking and
|
|
3229
|
+
// pruning decisions to specific edges.
|
|
3230
|
+
edgeConfidence: candidate.edgeConfidence
|
|
3231
|
+
});
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
return {
|
|
3235
|
+
merged: mergeGraphExpandedResults(options.memoryResults, expandedResults),
|
|
3236
|
+
seedPaths,
|
|
3237
|
+
expandedPaths,
|
|
3238
|
+
seedResults
|
|
3239
|
+
};
|
|
3240
|
+
}
|
|
3241
|
+
async recordLastGraphRecallSnapshot(options) {
|
|
3242
|
+
try {
|
|
3243
|
+
const snapshotPath = path5.join(
|
|
3244
|
+
options.storage.dir,
|
|
3245
|
+
"state",
|
|
3246
|
+
"last_graph_recall.json"
|
|
3247
|
+
);
|
|
3248
|
+
await mkdir2(path5.dirname(snapshotPath), { recursive: true });
|
|
3249
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3250
|
+
const totalSeedCount = options.seedPaths.length;
|
|
3251
|
+
const totalExpandedCount = options.expandedPaths.length;
|
|
3252
|
+
const seeds = options.seedPaths.slice(0, 64);
|
|
3253
|
+
const expanded = clampGraphRecallExpandedEntries(
|
|
3254
|
+
options.expandedPaths,
|
|
3255
|
+
64
|
|
3256
|
+
);
|
|
3257
|
+
const payload = {
|
|
3258
|
+
recordedAt: now,
|
|
3259
|
+
mode: options.recallMode,
|
|
3260
|
+
queryHash: createHash2("sha256").update(options.prompt).digest("hex"),
|
|
3261
|
+
queryLength: options.prompt.length,
|
|
3262
|
+
namespaces: options.recallNamespaces,
|
|
3263
|
+
seedCount: totalSeedCount,
|
|
3264
|
+
expandedCount: totalExpandedCount,
|
|
3265
|
+
seeds,
|
|
3266
|
+
expanded,
|
|
3267
|
+
status: options.status,
|
|
3268
|
+
reason: options.reason,
|
|
3269
|
+
shadowMode: options.shadowMode === true,
|
|
3270
|
+
queryIntent: options.queryIntent,
|
|
3271
|
+
seedResults: (options.seedResults ?? []).slice(0, 64),
|
|
3272
|
+
finalResults: (options.finalResults ?? []).slice(0, 64),
|
|
3273
|
+
shadowComparison: options.shadowComparison
|
|
3274
|
+
};
|
|
3275
|
+
await writeFile2(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
3276
|
+
} catch (err) {
|
|
3277
|
+
log.debug(`last graph recall write failed: ${err}`);
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
async graphSeedPathRelativeToStorage(storage, result, recallNamespaces = []) {
|
|
3281
|
+
const parts = qmdCollectionPathParts(result.path);
|
|
3282
|
+
if (parts) {
|
|
3283
|
+
const memory = await this.readQmdResultMemory(
|
|
3284
|
+
result.path,
|
|
3285
|
+
storage,
|
|
3286
|
+
recallNamespaces
|
|
3287
|
+
);
|
|
3288
|
+
return memory ? graphPathRelativeToStorage(storage.dir, memory.path) : null;
|
|
3289
|
+
}
|
|
3290
|
+
return graphPathRelativeToStorage(storage.dir, result.path);
|
|
3291
|
+
}
|
|
3292
|
+
async graphSeedPathsWithinDeadline(storage, results, deadlineAtMs, recallNamespaces = []) {
|
|
3293
|
+
const resolved = [];
|
|
3294
|
+
for (const result of results) {
|
|
3295
|
+
if (Date.now() >= deadlineAtMs) break;
|
|
3296
|
+
const seedPath = await this.graphSeedPathRelativeToStorage(
|
|
3297
|
+
storage,
|
|
3298
|
+
result,
|
|
3299
|
+
recallNamespaces
|
|
3300
|
+
);
|
|
3301
|
+
if (Date.now() >= deadlineAtMs) break;
|
|
3302
|
+
if (seedPath) resolved.push(seedPath);
|
|
3303
|
+
}
|
|
3304
|
+
return resolved;
|
|
3305
|
+
}
|
|
3306
|
+
};
|
|
3307
|
+
|
|
3308
|
+
// src/maintenance/pattern-reinforcement.ts
|
|
3309
|
+
function patternReinforcementKey(content) {
|
|
3310
|
+
return content.trim().toLowerCase().replace(/\s+/g, " ").slice(0, 200);
|
|
3311
|
+
}
|
|
3312
|
+
function patternReinforcementClusterKey(category, content) {
|
|
3313
|
+
return `${category}::${patternReinforcementKey(content)}`;
|
|
3314
|
+
}
|
|
3315
|
+
function pickCanonical(memories) {
|
|
3316
|
+
let best = memories[0];
|
|
3317
|
+
let bestInstant = memoryInstant(best);
|
|
3318
|
+
let bestStamp = memoryStamp(best);
|
|
3319
|
+
for (let i = 1; i < memories.length; i += 1) {
|
|
3320
|
+
const candidate = memories[i];
|
|
3321
|
+
const instant = memoryInstant(candidate);
|
|
3322
|
+
const stamp = memoryStamp(candidate);
|
|
3323
|
+
let cmp;
|
|
3324
|
+
if (instant !== null && bestInstant !== null) {
|
|
3325
|
+
cmp = instant - bestInstant;
|
|
3326
|
+
} else {
|
|
3327
|
+
cmp = stamp.localeCompare(bestStamp);
|
|
3328
|
+
}
|
|
3329
|
+
if (cmp > 0 || cmp === 0 && candidate.frontmatter.id > best.frontmatter.id) {
|
|
3330
|
+
best = candidate;
|
|
3331
|
+
bestInstant = instant;
|
|
3332
|
+
bestStamp = stamp;
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
return best;
|
|
3336
|
+
}
|
|
3337
|
+
function memoryStamp(memory) {
|
|
3338
|
+
return memory.frontmatter.updated || memory.frontmatter.created || "";
|
|
3339
|
+
}
|
|
3340
|
+
function memoryInstant(memory) {
|
|
3341
|
+
const stamp = memoryStamp(memory);
|
|
3342
|
+
if (stamp.length === 0) return null;
|
|
3343
|
+
const parsed = Date.parse(stamp);
|
|
3344
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
3345
|
+
}
|
|
3346
|
+
var ACTIVE_STATUS = "active";
|
|
3347
|
+
async function runPatternReinforcement(storage, options) {
|
|
3348
|
+
const minCount = Math.max(2, Math.floor(options.minCount));
|
|
3349
|
+
const targetCategories = new Set(options.categories);
|
|
3350
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
3351
|
+
const nowIso = now().toISOString();
|
|
3352
|
+
if (targetCategories.size === 0) {
|
|
3353
|
+
return emptyResult();
|
|
3354
|
+
}
|
|
3355
|
+
const memories = await storage.readAllMemories();
|
|
3356
|
+
const eligible = memories.filter((m) => {
|
|
3357
|
+
if (!targetCategories.has(m.frontmatter.category)) return false;
|
|
3358
|
+
const status = m.frontmatter.status ?? ACTIVE_STATUS;
|
|
3359
|
+
return status === ACTIVE_STATUS || status === "superseded";
|
|
3360
|
+
});
|
|
3361
|
+
if (eligible.length === 0) return emptyResult();
|
|
3362
|
+
const clusters = clusterByKey(
|
|
3363
|
+
eligible,
|
|
3364
|
+
(m) => patternReinforcementClusterKey(m.frontmatter.category, m.content)
|
|
2702
3365
|
);
|
|
2703
3366
|
const result = {
|
|
2704
3367
|
clustersFound: 0,
|
|
@@ -2974,8 +3637,8 @@ function generateResolverDocument(taxonomy) {
|
|
|
2974
3637
|
}
|
|
2975
3638
|
|
|
2976
3639
|
// src/taxonomy/taxonomy-loader.ts
|
|
2977
|
-
import { readFile, mkdir as
|
|
2978
|
-
import
|
|
3640
|
+
import { readFile, mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
3641
|
+
import path6 from "path";
|
|
2979
3642
|
var TAXONOMY_DIR = ".taxonomy";
|
|
2980
3643
|
var TAXONOMY_FILE = "taxonomy.json";
|
|
2981
3644
|
var MAX_SLUG_LENGTH = 32;
|
|
@@ -3073,7 +3736,7 @@ function validateTaxonomy(taxonomy) {
|
|
|
3073
3736
|
}
|
|
3074
3737
|
}
|
|
3075
3738
|
async function loadTaxonomy(memoryDir) {
|
|
3076
|
-
const taxonomyPath =
|
|
3739
|
+
const taxonomyPath = path6.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
3077
3740
|
let raw;
|
|
3078
3741
|
try {
|
|
3079
3742
|
raw = await readFile(taxonomyPath, "utf-8");
|
|
@@ -3123,16 +3786,16 @@ async function loadTaxonomy(memoryDir) {
|
|
|
3123
3786
|
}
|
|
3124
3787
|
async function saveTaxonomy(memoryDir, taxonomy) {
|
|
3125
3788
|
validateTaxonomy(taxonomy);
|
|
3126
|
-
const dir =
|
|
3127
|
-
await
|
|
3128
|
-
const filePath =
|
|
3129
|
-
await
|
|
3789
|
+
const dir = path6.join(memoryDir, TAXONOMY_DIR);
|
|
3790
|
+
await mkdir3(dir, { recursive: true });
|
|
3791
|
+
const filePath = path6.join(dir, TAXONOMY_FILE);
|
|
3792
|
+
await writeFile3(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
|
|
3130
3793
|
}
|
|
3131
3794
|
function getTaxonomyDir(memoryDir) {
|
|
3132
|
-
return
|
|
3795
|
+
return path6.join(memoryDir, TAXONOMY_DIR);
|
|
3133
3796
|
}
|
|
3134
3797
|
function getTaxonomyFilePath(memoryDir) {
|
|
3135
|
-
return
|
|
3798
|
+
return path6.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
3136
3799
|
}
|
|
3137
3800
|
|
|
3138
3801
|
// src/wearables/registry.ts
|
|
@@ -4142,11 +4805,11 @@ async function qmdStartupCollectionCheckWithTimeout(promise, controller, label)
|
|
|
4142
4805
|
return await Promise.race([checkedPromise, timeoutPromise]);
|
|
4143
4806
|
}
|
|
4144
4807
|
function defaultWorkspaceDir() {
|
|
4145
|
-
return
|
|
4808
|
+
return path7.join(os2.homedir(), ".openclaw", "workspace");
|
|
4146
4809
|
}
|
|
4147
4810
|
function sanitizeSessionKeyForFilename(sessionKey) {
|
|
4148
4811
|
const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
4149
|
-
const hash =
|
|
4812
|
+
const hash = createHash3("sha256").update(sessionKey).digest("hex").slice(0, 12);
|
|
4150
4813
|
return `${readable}-${hash}`;
|
|
4151
4814
|
}
|
|
4152
4815
|
function latestSourceValidAtFromTurns(turns) {
|
|
@@ -4404,42 +5067,6 @@ function computeQmdHybridFetchLimit(recallFetchLimit, artifactsEnabled, maxArtif
|
|
|
4404
5067
|
const artifactHeadroom = Math.max(20, Math.max(0, maxArtifactRecall) * 8);
|
|
4405
5068
|
return Math.min(400, cappedRecallLimit + artifactHeadroom);
|
|
4406
5069
|
}
|
|
4407
|
-
function mergeGraphExpandedResults(primary, expanded) {
|
|
4408
|
-
const mergedByPath = /* @__PURE__ */ new Map();
|
|
4409
|
-
for (const item of [...primary, ...expanded]) {
|
|
4410
|
-
const prev = mergedByPath.get(item.path);
|
|
4411
|
-
if (!prev) {
|
|
4412
|
-
mergedByPath.set(item.path, item);
|
|
4413
|
-
continue;
|
|
4414
|
-
}
|
|
4415
|
-
const better = item.score > prev.score ? item : prev;
|
|
4416
|
-
const snippet = prev.snippet || item.snippet;
|
|
4417
|
-
mergedByPath.set(item.path, { ...better, snippet });
|
|
4418
|
-
}
|
|
4419
|
-
return Array.from(mergedByPath.values());
|
|
4420
|
-
}
|
|
4421
|
-
function graphPathRelativeToStorage(storageDir, candidatePath) {
|
|
4422
|
-
const absolutePath = path6.isAbsolute(candidatePath) ? candidatePath : path6.resolve(storageDir, candidatePath);
|
|
4423
|
-
const rel = path6.relative(storageDir, absolutePath);
|
|
4424
|
-
if (!rel || rel === ".") return null;
|
|
4425
|
-
if (rel.startsWith("..")) return null;
|
|
4426
|
-
return rel.split(path6.sep).join("/");
|
|
4427
|
-
}
|
|
4428
|
-
function normalizeGraphActivationScore(score) {
|
|
4429
|
-
const bounded = Number.isFinite(score) && score > 0 ? score : 0;
|
|
4430
|
-
return bounded / (1 + bounded);
|
|
4431
|
-
}
|
|
4432
|
-
function blendGraphExpandedRecallScore(options) {
|
|
4433
|
-
const graphNorm = normalizeGraphActivationScore(options.graphActivationScore);
|
|
4434
|
-
const seedScore = Number.isFinite(options.seedRecallScore) ? Math.min(1, Math.max(0, options.seedRecallScore)) : 0;
|
|
4435
|
-
const weight = Math.min(1, Math.max(0, options.activationWeight));
|
|
4436
|
-
const rawMin = Math.min(1, Math.max(0, options.blendMin));
|
|
4437
|
-
const rawMax = Math.min(1, Math.max(0, options.blendMax));
|
|
4438
|
-
const minBound = Math.min(rawMin, rawMax);
|
|
4439
|
-
const maxBound = Math.max(rawMin, rawMax);
|
|
4440
|
-
const blended = graphNorm * weight + seedScore * (1 - weight);
|
|
4441
|
-
return Math.max(minBound, Math.min(maxBound, blended));
|
|
4442
|
-
}
|
|
4443
5070
|
function summarizeGraphShadowComparison(baseline, merged, topN) {
|
|
4444
5071
|
const limit = Math.max(0, Math.floor(topN));
|
|
4445
5072
|
const baselineTop = limit > 0 ? baseline.slice(0, limit) : [];
|
|
@@ -4568,7 +5195,7 @@ function buildMemoryPathById(allMemsForGraph, storageDir) {
|
|
|
4568
5195
|
for (const mem of allMemsForGraph ?? []) {
|
|
4569
5196
|
const id = mem.frontmatter.id;
|
|
4570
5197
|
if (!id) continue;
|
|
4571
|
-
pathById.set(id,
|
|
5198
|
+
pathById.set(id, path7.relative(storageDir, mem.path));
|
|
4572
5199
|
}
|
|
4573
5200
|
return pathById;
|
|
4574
5201
|
}
|
|
@@ -4576,7 +5203,7 @@ function appendMemoryToGraphContext(options) {
|
|
|
4576
5203
|
if (!Array.isArray(options.allMemsForGraph)) return;
|
|
4577
5204
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4578
5205
|
options.allMemsForGraph.push({
|
|
4579
|
-
path:
|
|
5206
|
+
path: path7.join(options.storageDir, options.memoryRelPath),
|
|
4580
5207
|
content: options.content,
|
|
4581
5208
|
frontmatter: {
|
|
4582
5209
|
id: options.memoryId,
|
|
@@ -4596,16 +5223,16 @@ function resolvePersistedMemoryRelativePath(options) {
|
|
|
4596
5223
|
const persisted = options.pathById.get(options.memoryId);
|
|
4597
5224
|
if (persisted) return persisted;
|
|
4598
5225
|
if (options.category === "correction") {
|
|
4599
|
-
return
|
|
5226
|
+
return path7.join("corrections", `${options.memoryId}.md`);
|
|
4600
5227
|
}
|
|
4601
5228
|
const subtree = categoryDirName(options.category);
|
|
4602
5229
|
const idParts = options.memoryId.split("-");
|
|
4603
5230
|
const maybeTimestamp = Number(idParts[1]);
|
|
4604
5231
|
if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
|
|
4605
5232
|
const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
|
|
4606
|
-
return
|
|
5233
|
+
return path7.join(subtree, day, `${options.memoryId}.md`);
|
|
4607
5234
|
}
|
|
4608
|
-
return
|
|
5235
|
+
return path7.join(subtree, `${options.memoryId}.md`);
|
|
4609
5236
|
}
|
|
4610
5237
|
var Orchestrator = class _Orchestrator {
|
|
4611
5238
|
storage;
|
|
@@ -4767,7 +5394,10 @@ var Orchestrator = class _Orchestrator {
|
|
|
4767
5394
|
*/
|
|
4768
5395
|
conversationIndexCoordinator;
|
|
4769
5396
|
recallRerankCoordinator;
|
|
5397
|
+
recallSectionCoordinator;
|
|
4770
5398
|
qmdResultResolver;
|
|
5399
|
+
contradictionLinkingCoordinator;
|
|
5400
|
+
graphRecallCoordinator;
|
|
4771
5401
|
heartbeatObserverChains = /* @__PURE__ */ new Map();
|
|
4772
5402
|
recentExtractionFingerprints = /* @__PURE__ */ new Map();
|
|
4773
5403
|
consolidationObservers = /* @__PURE__ */ new Set();
|
|
@@ -5060,7 +5690,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5060
5690
|
const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
|
|
5061
5691
|
if (ns !== defaultNs && !isSafeRouteNamespace(ns)) return;
|
|
5062
5692
|
if (!this.storageDirMatchesNamespaceHint(ns, storageDir)) return;
|
|
5063
|
-
const resolvedStorageDir =
|
|
5693
|
+
const resolvedStorageDir = path7.resolve(storageDir);
|
|
5064
5694
|
let hints = this.namespaceStorageDirHints.get(resolvedStorageDir);
|
|
5065
5695
|
if (!hints) {
|
|
5066
5696
|
hints = /* @__PURE__ */ new Set();
|
|
@@ -5071,21 +5701,21 @@ var Orchestrator = class _Orchestrator {
|
|
|
5071
5701
|
storageDirMatchesNamespaceHint(namespace, storageDir) {
|
|
5072
5702
|
const ns = normalizeNamespaceIdentity(namespace);
|
|
5073
5703
|
if (!ns) return false;
|
|
5074
|
-
const resolvedStorageDir =
|
|
5075
|
-
const resolvedMemoryDir =
|
|
5704
|
+
const resolvedStorageDir = path7.resolve(storageDir);
|
|
5705
|
+
const resolvedMemoryDir = path7.resolve(this.config.memoryDir);
|
|
5076
5706
|
const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
|
|
5077
5707
|
if (resolvedStorageDir === resolvedMemoryDir) return ns === defaultNs;
|
|
5078
|
-
const resolvedNamespacesDir =
|
|
5708
|
+
const resolvedNamespacesDir = path7.join(resolvedMemoryDir, "namespaces");
|
|
5079
5709
|
if (!isPathInsideStorageRoot(resolvedNamespacesDir, resolvedStorageDir)) return false;
|
|
5080
|
-
const rawRoot =
|
|
5081
|
-
const tokenRoot =
|
|
5710
|
+
const rawRoot = path7.resolve(resolvedNamespacesDir, ns);
|
|
5711
|
+
const tokenRoot = path7.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));
|
|
5082
5712
|
return resolvedStorageDir === rawRoot || resolvedStorageDir === tokenRoot;
|
|
5083
5713
|
}
|
|
5084
5714
|
namespaceStorageDirHintOwnershipRank(record, resolvedStorageDir, configured) {
|
|
5085
|
-
if (resolvedStorageDir ===
|
|
5715
|
+
if (resolvedStorageDir === path7.resolve(this.config.memoryDir)) {
|
|
5086
5716
|
return record.namespace === normalizeNamespaceIdentity(this.config.defaultNamespace) ? 0 : 3;
|
|
5087
5717
|
}
|
|
5088
|
-
const leaf =
|
|
5718
|
+
const leaf = path7.basename(resolvedStorageDir);
|
|
5089
5719
|
const tokenOwnsRoot = namespaceIdentityToken(record.namespace) === leaf;
|
|
5090
5720
|
if (tokenOwnsRoot && configured.has(record.namespace)) return 0;
|
|
5091
5721
|
if (record.namespace === leaf) return 1;
|
|
@@ -5113,7 +5743,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5113
5743
|
loadNamespaceStorageDirHintsFromCatalog() {
|
|
5114
5744
|
if (this.namespaceStorageDirHintsLoaded || !this.namespaceCatalog.enabled) return;
|
|
5115
5745
|
this.namespaceStorageDirHintsLoaded = true;
|
|
5116
|
-
const catalogPath =
|
|
5746
|
+
const catalogPath = path7.join(this.config.memoryDir, "state", "namespaces.jsonl");
|
|
5117
5747
|
if (!existsSync(catalogPath)) return;
|
|
5118
5748
|
let body;
|
|
5119
5749
|
try {
|
|
@@ -5150,7 +5780,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5150
5780
|
if (!this.storageDirMatchesNamespaceHint(record.namespace, record.storageDir)) {
|
|
5151
5781
|
continue;
|
|
5152
5782
|
}
|
|
5153
|
-
const resolvedStorageDir =
|
|
5783
|
+
const resolvedStorageDir = path7.resolve(record.storageDir);
|
|
5154
5784
|
const current = preferredByStorageDir.get(resolvedStorageDir);
|
|
5155
5785
|
preferredByStorageDir.set(
|
|
5156
5786
|
resolvedStorageDir,
|
|
@@ -5414,7 +6044,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5414
6044
|
this.config = config;
|
|
5415
6045
|
this.profiler = new ProfilingCollector({
|
|
5416
6046
|
enabled: resolvePipelineProcessingCapabilities(this.config).profiling,
|
|
5417
|
-
storageDir: config.profilingStorageDir ||
|
|
6047
|
+
storageDir: config.profilingStorageDir || path7.join(config.memoryDir, "profiling"),
|
|
5418
6048
|
maxTraces: config.profilingMaxTraces
|
|
5419
6049
|
});
|
|
5420
6050
|
this.namespaceCatalog = new NamespaceCatalog(config);
|
|
@@ -5484,7 +6114,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5484
6114
|
this.compounding = resolveConsolidationCapabilities(config).compounding ? new CompoundingEngine(config, this.storage) : void 0;
|
|
5485
6115
|
this.buffer = new SmartBuffer(config, this.storage);
|
|
5486
6116
|
this.transcript = new TranscriptManager(config);
|
|
5487
|
-
this.conversationIndexDir =
|
|
6117
|
+
this.conversationIndexDir = path7.join(
|
|
5488
6118
|
config.memoryDir,
|
|
5489
6119
|
"conversation-index",
|
|
5490
6120
|
"chunks"
|
|
@@ -5500,7 +6130,30 @@ var Orchestrator = class _Orchestrator {
|
|
|
5500
6130
|
getStorage: (namespace) => this.getStorage(namespace),
|
|
5501
6131
|
readQmdResultMemory: (resultPath, fallbackStorage, recallNamespaces) => this.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces)
|
|
5502
6132
|
});
|
|
6133
|
+
this.recallSectionCoordinator = new RecallSectionCoordinator({
|
|
6134
|
+
getConfig: () => this.config,
|
|
6135
|
+
resolveSectionEnabled: (id, def) => this.isRecallSectionEnabled(id, def)
|
|
6136
|
+
});
|
|
6137
|
+
this.contradictionLinkingCoordinator = new ContradictionLinkingCoordinator({
|
|
6138
|
+
getConfig: () => this.config,
|
|
6139
|
+
isSearchAvailable: () => this.isSearchAvailableForNamespaceRouting(),
|
|
6140
|
+
searchAcrossNamespaces: (options) => this.searchAcrossNamespaces(options),
|
|
6141
|
+
extractMemoryIdsFromResults: (results) => this.extractMemoryIdsFromResults(results),
|
|
6142
|
+
namespaceFromPath: (p) => this.namespaceFromPath(p),
|
|
6143
|
+
storageForNamespace: (namespace) => this.storageRouter.storageFor(namespace),
|
|
6144
|
+
getExtraction: () => this.extraction
|
|
6145
|
+
});
|
|
5503
6146
|
this.modelRegistry = new ModelRegistry(config.memoryDir);
|
|
6147
|
+
this.graphRecallCoordinator = new GraphRecallCoordinator({
|
|
6148
|
+
getConfig: () => this.config,
|
|
6149
|
+
getStorage: () => this.storage,
|
|
6150
|
+
storageFor: (namespace) => this.storageRouter.storageFor(namespace),
|
|
6151
|
+
graphIndexFor: (storage) => this.graphIndexFor(storage),
|
|
6152
|
+
namespaceFromPath: (p) => this.namespaceFromPath(p),
|
|
6153
|
+
resolveColdQmdResultForRecall: (result, fallbackStorage, recallNamespaces) => this.resolveColdQmdResultForRecall(result, fallbackStorage, recallNamespaces),
|
|
6154
|
+
storageForAbsoluteQmdResultPath: (resultPath, fallbackStorage, recallNamespaces) => this.storageForAbsoluteQmdResultPath(resultPath, fallbackStorage, recallNamespaces),
|
|
6155
|
+
readQmdResultMemory: (resultPath, fallbackStorage, recallNamespaces) => this.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces)
|
|
6156
|
+
});
|
|
5504
6157
|
this.relevance = new RelevanceStore(config.memoryDir);
|
|
5505
6158
|
this.negatives = new NegativeExampleStore(config.memoryDir);
|
|
5506
6159
|
this.lastRecall = new LastRecallStore(config.memoryDir);
|
|
@@ -5597,7 +6250,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5597
6250
|
saveContentHashIndexes: () => this.saveContentHashIndexes()
|
|
5598
6251
|
});
|
|
5599
6252
|
this.threading = new ThreadingManager(
|
|
5600
|
-
|
|
6253
|
+
path7.join(config.memoryDir, "threads"),
|
|
5601
6254
|
config.threadingGapMinutes
|
|
5602
6255
|
);
|
|
5603
6256
|
const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);
|
|
@@ -5677,7 +6330,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5677
6330
|
utilityPromoteThresholdDelta: this.utilityRuntimeValues?.promoteThresholdDelta ?? 0,
|
|
5678
6331
|
utilityDemoteThresholdDelta: this.utilityRuntimeValues?.demoteThresholdDelta ?? 0
|
|
5679
6332
|
};
|
|
5680
|
-
return
|
|
6333
|
+
return createHash3("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 12);
|
|
5681
6334
|
}
|
|
5682
6335
|
effectiveLifecycleThresholds() {
|
|
5683
6336
|
const archiveDecayThreshold = this.config.lifecycleArchiveDecayThreshold;
|
|
@@ -5920,7 +6573,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
5920
6573
|
const files = await readdir2(wsDir).catch(() => []);
|
|
5921
6574
|
for (const f of files) {
|
|
5922
6575
|
if (!f.startsWith(".compaction-reset-signal-")) continue;
|
|
5923
|
-
const fp =
|
|
6576
|
+
const fp = path7.join(wsDir, f);
|
|
5924
6577
|
const s = await stat(fp).catch(() => null);
|
|
5925
6578
|
if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
|
|
5926
6579
|
await unlink(fp).catch(() => {
|
|
@@ -6115,7 +6768,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
6115
6768
|
if (signal.aborted) return;
|
|
6116
6769
|
if (lifecycleCaps.lifecyclePolicy && resolveQmdCapabilities(this.config).qmdTierMigration) {
|
|
6117
6770
|
try {
|
|
6118
|
-
const { runFirstStartMigration } = await import("./first-start-migration-
|
|
6771
|
+
const { runFirstStartMigration } = await import("./first-start-migration-4I3VDSYS.js");
|
|
6119
6772
|
const result = await runFirstStartMigration({
|
|
6120
6773
|
storage: this.storage,
|
|
6121
6774
|
config: this.config,
|
|
@@ -6429,15 +7082,15 @@ ${doc.content}` : doc.content,
|
|
|
6429
7082
|
this.lastFileHygieneRunAtMs = now;
|
|
6430
7083
|
if (hygiene.rotateEnabled) {
|
|
6431
7084
|
for (const rel of hygiene.rotatePaths) {
|
|
6432
|
-
const abs =
|
|
7085
|
+
const abs = path7.isAbsolute(rel) ? rel : path7.join(this.config.workspaceDir, rel);
|
|
6433
7086
|
try {
|
|
6434
7087
|
const raw = await readFile2(abs, "utf-8");
|
|
6435
7088
|
if (raw.length > hygiene.rotateMaxBytes) {
|
|
6436
|
-
const archiveDir =
|
|
7089
|
+
const archiveDir = path7.join(
|
|
6437
7090
|
this.config.workspaceDir,
|
|
6438
7091
|
hygiene.archiveDir
|
|
6439
7092
|
);
|
|
6440
|
-
const base =
|
|
7093
|
+
const base = path7.basename(abs);
|
|
6441
7094
|
const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
|
|
6442
7095
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
6443
7096
|
filePath: abs,
|
|
@@ -6445,7 +7098,7 @@ ${doc.content}` : doc.content,
|
|
|
6445
7098
|
archivePrefix: prefix,
|
|
6446
7099
|
keepTailChars: hygiene.rotateKeepTailChars
|
|
6447
7100
|
});
|
|
6448
|
-
await
|
|
7101
|
+
await writeFile4(abs, newContent, "utf-8");
|
|
6449
7102
|
}
|
|
6450
7103
|
} catch {
|
|
6451
7104
|
}
|
|
@@ -6462,8 +7115,8 @@ ${doc.content}` : doc.content,
|
|
|
6462
7115
|
log.warn(w.message);
|
|
6463
7116
|
}
|
|
6464
7117
|
if (hygiene.warningsLogEnabled && warnings.length > 0) {
|
|
6465
|
-
const fp =
|
|
6466
|
-
await
|
|
7118
|
+
const fp = path7.join(this.config.memoryDir, hygiene.warningsLogPath);
|
|
7119
|
+
await mkdir4(path7.dirname(fp), { recursive: true });
|
|
6467
7120
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
6468
7121
|
const block = `
|
|
6469
7122
|
|
|
@@ -6476,7 +7129,7 @@ ${doc.content}` : doc.content,
|
|
|
6476
7129
|
} catch {
|
|
6477
7130
|
existing = "# Engram File Hygiene Warnings\n";
|
|
6478
7131
|
}
|
|
6479
|
-
await
|
|
7132
|
+
await writeFile4(fp, existing + block, "utf-8");
|
|
6480
7133
|
}
|
|
6481
7134
|
}
|
|
6482
7135
|
}
|
|
@@ -6602,7 +7255,7 @@ ${doc.content}` : doc.content,
|
|
|
6602
7255
|
for (const categoryDir of RECALL_FALLBACK_DIRS) {
|
|
6603
7256
|
if (memoryRootReal === null) break;
|
|
6604
7257
|
for (const date of datesToScan) {
|
|
6605
|
-
const dateDir =
|
|
7258
|
+
const dateDir = path7.join(storage.dir, categoryDir, date);
|
|
6606
7259
|
try {
|
|
6607
7260
|
const dirStat = await lstat(dateDir);
|
|
6608
7261
|
if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) continue;
|
|
@@ -6611,7 +7264,7 @@ ${doc.content}` : doc.content,
|
|
|
6611
7264
|
for (const entry of entries) {
|
|
6612
7265
|
if (entry.isSymbolicLink()) continue;
|
|
6613
7266
|
if (!entry.name.endsWith(".md")) continue;
|
|
6614
|
-
const fullPath =
|
|
7267
|
+
const fullPath = path7.join(dateDir, entry.name);
|
|
6615
7268
|
try {
|
|
6616
7269
|
assertPathInsideRoot(memoryRootReal, await realpath(fullPath), fullPath);
|
|
6617
7270
|
const raw = await readFile2(fullPath, "utf-8");
|
|
@@ -6633,7 +7286,7 @@ ${doc.content}` : doc.content,
|
|
|
6633
7286
|
facts.push({
|
|
6634
7287
|
path: fullPath,
|
|
6635
7288
|
frontmatter: {
|
|
6636
|
-
id: fm.id ||
|
|
7289
|
+
id: fm.id || path7.basename(entry.name, ".md"),
|
|
6637
7290
|
category: fm.category || "fact",
|
|
6638
7291
|
created,
|
|
6639
7292
|
updated: fm.updated || created,
|
|
@@ -6656,13 +7309,13 @@ ${doc.content}` : doc.content,
|
|
|
6656
7309
|
return a.frontmatter.created < b.frontmatter.created ? -1 : 1;
|
|
6657
7310
|
});
|
|
6658
7311
|
const hourlySummaries = [];
|
|
6659
|
-
const hourlyBaseDir =
|
|
7312
|
+
const hourlyBaseDir = path7.join(storage.dir, "summaries", "hourly");
|
|
6660
7313
|
try {
|
|
6661
7314
|
const sessionKeys = await readdir2(hourlyBaseDir, { withFileTypes: true });
|
|
6662
7315
|
for (const sk of sessionKeys) {
|
|
6663
7316
|
if (!sk.isDirectory()) continue;
|
|
6664
7317
|
for (const date of datesToScan) {
|
|
6665
|
-
const summaryFile =
|
|
7318
|
+
const summaryFile = path7.join(hourlyBaseDir, sk.name, `${date}.md`);
|
|
6666
7319
|
try {
|
|
6667
7320
|
const raw = await readFile2(summaryFile, "utf-8");
|
|
6668
7321
|
const filtered = filterHourlySummaryMarkdownForLocalDay(
|
|
@@ -6766,7 +7419,7 @@ ${doc.content}` : doc.content,
|
|
|
6766
7419
|
}
|
|
6767
7420
|
async getLastGraphRecallSnapshot(namespace) {
|
|
6768
7421
|
const storage = await this.getStorage(namespace);
|
|
6769
|
-
const snapshotPath =
|
|
7422
|
+
const snapshotPath = path7.join(
|
|
6770
7423
|
storage.dir,
|
|
6771
7424
|
"state",
|
|
6772
7425
|
"last_graph_recall.json"
|
|
@@ -6805,7 +7458,7 @@ ${doc.content}` : doc.content,
|
|
|
6805
7458
|
}
|
|
6806
7459
|
async getLastIntentSnapshot(namespace) {
|
|
6807
7460
|
const storage = await this.getStorage(namespace);
|
|
6808
|
-
const snapshotPath =
|
|
7461
|
+
const snapshotPath = path7.join(storage.dir, "state", "last_intent.json");
|
|
6809
7462
|
try {
|
|
6810
7463
|
const raw = await readFile2(snapshotPath, "utf-8");
|
|
6811
7464
|
const parsed = JSON.parse(raw);
|
|
@@ -6838,7 +7491,7 @@ ${doc.content}` : doc.content,
|
|
|
6838
7491
|
}
|
|
6839
7492
|
async getLastQmdRecallSnapshot(namespace) {
|
|
6840
7493
|
const storage = await this.getStorage(namespace);
|
|
6841
|
-
const snapshotPath =
|
|
7494
|
+
const snapshotPath = path7.join(
|
|
6842
7495
|
storage.dir,
|
|
6843
7496
|
"state",
|
|
6844
7497
|
"last_qmd_recall.json"
|
|
@@ -7540,7 +8193,7 @@ ${doc.content}` : doc.content,
|
|
|
7540
8193
|
if (!options.onDebugSnapshot) return;
|
|
7541
8194
|
await options.onDebugSnapshot({
|
|
7542
8195
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7543
|
-
queryHash:
|
|
8196
|
+
queryHash: createHash3("sha256").update(prompt).digest("hex"),
|
|
7544
8197
|
queryLength: prompt.length,
|
|
7545
8198
|
collection: options.collection,
|
|
7546
8199
|
namespaces: options.recallNamespaces,
|
|
@@ -7645,259 +8298,69 @@ ${doc.content}` : doc.content,
|
|
|
7645
8298
|
if (scopedSeedResults.length > 0) {
|
|
7646
8299
|
const mergedByPath = /* @__PURE__ */ new Map();
|
|
7647
8300
|
for (const result of [...scopedSeedResults, ...mergedResults]) {
|
|
7648
|
-
const key = result.path || result.docid;
|
|
7649
|
-
const existing = mergedByPath.get(key);
|
|
7650
|
-
if (!existing || result.score > existing.score) {
|
|
7651
|
-
mergedByPath.set(key, {
|
|
7652
|
-
...result,
|
|
7653
|
-
snippet: result.snippet || existing?.snippet || ""
|
|
7654
|
-
});
|
|
7655
|
-
}
|
|
7656
|
-
}
|
|
7657
|
-
mergedResults = [...mergedByPath.values()].sort((a, b) => b.score - a.score).slice(0, fetchLimit);
|
|
7658
|
-
}
|
|
7659
|
-
const filteredResults = filterRecallCandidates(mergedResults, {
|
|
7660
|
-
namespacesEnabled: options.namespacesEnabled,
|
|
7661
|
-
recallNamespaces: options.recallNamespaces,
|
|
7662
|
-
resolveNamespace: options.resolveNamespace,
|
|
7663
|
-
limit: fetchLimit
|
|
7664
|
-
});
|
|
7665
|
-
if (filteredResults.length >= qmdFetchLimit) {
|
|
7666
|
-
const capped2 = filteredResults.slice(0, qmdFetchLimit);
|
|
7667
|
-
await emitDebugSnapshot(capped2, fetchLimit);
|
|
7668
|
-
return capped2;
|
|
7669
|
-
}
|
|
7670
|
-
if (filteredResults.length > bestFiltered.length) {
|
|
7671
|
-
bestFiltered = filteredResults;
|
|
7672
|
-
}
|
|
7673
|
-
if (mergedResults.length === 0) {
|
|
7674
|
-
await emitDebugSnapshot(filteredResults, fetchLimit);
|
|
7675
|
-
return filteredResults;
|
|
7676
|
-
}
|
|
7677
|
-
if (mergedResults.length < fetchLimit && filteredResults.length > 0) {
|
|
7678
|
-
await emitDebugSnapshot(filteredResults, fetchLimit);
|
|
7679
|
-
return filteredResults;
|
|
7680
|
-
}
|
|
7681
|
-
if (fetchLimit >= maxFetchLimit) {
|
|
7682
|
-
break;
|
|
7683
|
-
}
|
|
7684
|
-
const growth = Math.max(20, Math.floor(fetchLimit / 2));
|
|
7685
|
-
fetchLimit = Math.min(maxFetchLimit, fetchLimit + growth);
|
|
7686
|
-
}
|
|
7687
|
-
const capped = bestFiltered.slice(0, qmdFetchLimit);
|
|
7688
|
-
await emitDebugSnapshot(capped, fetchLimit);
|
|
7689
|
-
return capped;
|
|
7690
|
-
}
|
|
7691
|
-
async expandResultsViaGraph(options) {
|
|
7692
|
-
const deadlineExpired = () => typeof options.deadlineAtMs === "number" && Date.now() >= options.deadlineAtMs;
|
|
7693
|
-
const byNamespace = /* @__PURE__ */ new Map();
|
|
7694
|
-
const addResultForNamespace = (namespace, result) => {
|
|
7695
|
-
const existing = byNamespace.get(namespace);
|
|
7696
|
-
if (existing) {
|
|
7697
|
-
existing.push(result);
|
|
7698
|
-
} else {
|
|
7699
|
-
byNamespace.set(namespace, [result]);
|
|
7700
|
-
}
|
|
7701
|
-
};
|
|
7702
|
-
const resolvedAmbiguousSeeds = /* @__PURE__ */ new Map();
|
|
7703
|
-
const resolveAmbiguousSeedOwner = async (result, parts) => {
|
|
7704
|
-
const cached = resolvedAmbiguousSeeds.get(result.path);
|
|
7705
|
-
if (cached !== void 0) return cached;
|
|
7706
|
-
if (deadlineExpired()) {
|
|
7707
|
-
resolvedAmbiguousSeeds.set(result.path, null);
|
|
7708
|
-
return null;
|
|
7709
|
-
}
|
|
7710
|
-
let resolvedPath = result.path;
|
|
7711
|
-
let resolvedResult = result;
|
|
7712
|
-
if (parts) {
|
|
7713
|
-
const resolvedCold = await this.resolveColdQmdResultForRecall(
|
|
7714
|
-
result,
|
|
7715
|
-
this.storage,
|
|
7716
|
-
options.recallNamespaces
|
|
7717
|
-
);
|
|
7718
|
-
if (!resolvedCold || deadlineExpired()) {
|
|
7719
|
-
resolvedAmbiguousSeeds.set(result.path, null);
|
|
7720
|
-
return null;
|
|
7721
|
-
}
|
|
7722
|
-
resolvedPath = resolvedCold.result.path;
|
|
7723
|
-
resolvedResult = resolvedCold.result;
|
|
7724
|
-
}
|
|
7725
|
-
if (!path6.isAbsolute(resolvedPath)) {
|
|
7726
|
-
resolvedAmbiguousSeeds.set(result.path, null);
|
|
7727
|
-
return null;
|
|
7728
|
-
}
|
|
7729
|
-
const ownerStorage = await this.storageForAbsoluteQmdResultPath(
|
|
7730
|
-
resolvedPath,
|
|
7731
|
-
this.storage,
|
|
7732
|
-
options.recallNamespaces
|
|
7733
|
-
);
|
|
7734
|
-
const ownerNamespace = ownerStorage?.namespace ?? null;
|
|
7735
|
-
const resolved = ownerNamespace && options.recallNamespaces.includes(ownerNamespace) ? { namespace: ownerNamespace, result: resolvedResult } : null;
|
|
7736
|
-
resolvedAmbiguousSeeds.set(result.path, resolved);
|
|
7737
|
-
return resolved;
|
|
7738
|
-
};
|
|
7739
|
-
const coldCollection = this.config.qmdColdCollection ?? "openclaw-engram-cold";
|
|
7740
|
-
for (const result of options.memoryResults) {
|
|
7741
|
-
if (deadlineExpired()) break;
|
|
7742
|
-
const parts = qmdCollectionPathParts(result.path);
|
|
7743
|
-
if (parts?.collection === coldCollection) {
|
|
7744
|
-
const resolved = await resolveAmbiguousSeedOwner(result, parts);
|
|
7745
|
-
if (resolved) {
|
|
7746
|
-
addResultForNamespace(resolved.namespace, resolved.result);
|
|
7747
|
-
}
|
|
7748
|
-
continue;
|
|
7749
|
-
}
|
|
7750
|
-
if (path6.isAbsolute(result.path)) {
|
|
7751
|
-
const resolved = await resolveAmbiguousSeedOwner(result, null);
|
|
7752
|
-
if (resolved) {
|
|
7753
|
-
addResultForNamespace(resolved.namespace, resolved.result);
|
|
7754
|
-
}
|
|
7755
|
-
continue;
|
|
7756
|
-
}
|
|
7757
|
-
const ns = this.namespaceFromPath(result.path);
|
|
7758
|
-
if (!options.recallNamespaces.includes(ns)) continue;
|
|
7759
|
-
addResultForNamespace(ns, result);
|
|
7760
|
-
}
|
|
7761
|
-
const perNamespaceSeedCap = Math.max(3, options.recallResultLimit);
|
|
7762
|
-
const perNamespaceExpandedCap = Math.max(8, options.recallResultLimit * 2);
|
|
7763
|
-
const seedPaths = [];
|
|
7764
|
-
const seedResults = [];
|
|
7765
|
-
const expandedPaths = [];
|
|
7766
|
-
const expandedResults = [];
|
|
7767
|
-
for (const [namespace, nsResults] of byNamespace.entries()) {
|
|
7768
|
-
if (deadlineExpired()) break;
|
|
7769
|
-
const storage = await this.storageRouter.storageFor(namespace);
|
|
7770
|
-
const seedCandidates = nsResults.slice(0, perNamespaceSeedCap);
|
|
7771
|
-
seedResults.push(...seedCandidates);
|
|
7772
|
-
const seedRelativePaths = typeof options.deadlineAtMs === "number" ? await this.graphSeedPathsWithinDeadline(
|
|
7773
|
-
storage,
|
|
7774
|
-
seedCandidates,
|
|
7775
|
-
options.deadlineAtMs,
|
|
7776
|
-
[namespace]
|
|
7777
|
-
) : (await Promise.all(
|
|
7778
|
-
seedCandidates.map(
|
|
7779
|
-
(result) => this.graphSeedPathRelativeToStorage(storage, result, [
|
|
7780
|
-
namespace
|
|
7781
|
-
])
|
|
7782
|
-
)
|
|
7783
|
-
)).filter(
|
|
7784
|
-
(value) => typeof value === "string" && value.length > 0
|
|
7785
|
-
);
|
|
7786
|
-
if (deadlineExpired()) break;
|
|
7787
|
-
if (seedRelativePaths.length === 0) continue;
|
|
7788
|
-
const seedRecallScore = seedCandidates.reduce(
|
|
7789
|
-
(max, item) => Math.max(max, item.score),
|
|
7790
|
-
0
|
|
7791
|
-
);
|
|
7792
|
-
seedPaths.push(
|
|
7793
|
-
...seedRelativePaths.map((rel) => path6.join(storage.dir, rel))
|
|
7794
|
-
);
|
|
7795
|
-
const seedSet = new Set(seedRelativePaths);
|
|
7796
|
-
const expanded = await this.graphIndexFor(storage).spreadingActivation(
|
|
7797
|
-
seedRelativePaths,
|
|
7798
|
-
this.config.maxGraphTraversalSteps,
|
|
7799
|
-
{
|
|
7800
|
-
...options.includeLowConfidence === true ? { includeLowConfidence: true } : {},
|
|
7801
|
-
...typeof options.deadlineAtMs === "number" ? { deadlineAtMs: options.deadlineAtMs } : {}
|
|
7802
|
-
}
|
|
7803
|
-
);
|
|
7804
|
-
if (expanded.length === 0) continue;
|
|
7805
|
-
if (deadlineExpired()) break;
|
|
7806
|
-
for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
|
|
7807
|
-
if (deadlineExpired()) break;
|
|
7808
|
-
if (seedSet.has(candidate.path)) continue;
|
|
7809
|
-
const memoryPath = path6.resolve(storage.dir, candidate.path);
|
|
7810
|
-
const memory = await storage.readMemoryByPath(memoryPath);
|
|
7811
|
-
if (deadlineExpired()) break;
|
|
7812
|
-
if (!memory) continue;
|
|
7813
|
-
if (isArtifactMemoryPath(memory.path)) continue;
|
|
7814
|
-
if (memory.frontmatter.status && memory.frontmatter.status !== "active")
|
|
7815
|
-
continue;
|
|
7816
|
-
const snippet = memory.content.slice(0, 400);
|
|
7817
|
-
const score = blendGraphExpandedRecallScore({
|
|
7818
|
-
graphActivationScore: candidate.score,
|
|
7819
|
-
seedRecallScore,
|
|
7820
|
-
activationWeight: this.config.graphExpansionActivationWeight,
|
|
7821
|
-
blendMin: this.config.graphExpansionBlendMin,
|
|
7822
|
-
blendMax: this.config.graphExpansionBlendMax
|
|
7823
|
-
});
|
|
7824
|
-
expandedResults.push({
|
|
7825
|
-
docid: memory.frontmatter.id,
|
|
7826
|
-
path: memory.path,
|
|
7827
|
-
snippet,
|
|
7828
|
-
score
|
|
7829
|
-
});
|
|
7830
|
-
expandedPaths.push({
|
|
7831
|
-
path: memory.path,
|
|
7832
|
-
score,
|
|
7833
|
-
namespace,
|
|
7834
|
-
seed: path6.resolve(storage.dir, candidate.seed),
|
|
7835
|
-
hopDepth: candidate.hopDepth,
|
|
7836
|
-
decayedWeight: candidate.decayedWeight,
|
|
7837
|
-
graphType: candidate.graphType,
|
|
7838
|
-
// Issue #681 PR 3/3 — surface the per-edge confidence used for
|
|
7839
|
-
// PageRank weighting / floor pruning so downstream observability
|
|
7840
|
-
// (recall_xray, memory_graph_explain) can attribute ranking and
|
|
7841
|
-
// pruning decisions to specific edges.
|
|
7842
|
-
edgeConfidence: candidate.edgeConfidence
|
|
7843
|
-
});
|
|
8301
|
+
const key = result.path || result.docid;
|
|
8302
|
+
const existing = mergedByPath.get(key);
|
|
8303
|
+
if (!existing || result.score > existing.score) {
|
|
8304
|
+
mergedByPath.set(key, {
|
|
8305
|
+
...result,
|
|
8306
|
+
snippet: result.snippet || existing?.snippet || ""
|
|
8307
|
+
});
|
|
8308
|
+
}
|
|
8309
|
+
}
|
|
8310
|
+
mergedResults = [...mergedByPath.values()].sort((a, b) => b.score - a.score).slice(0, fetchLimit);
|
|
8311
|
+
}
|
|
8312
|
+
const filteredResults = filterRecallCandidates(mergedResults, {
|
|
8313
|
+
namespacesEnabled: options.namespacesEnabled,
|
|
8314
|
+
recallNamespaces: options.recallNamespaces,
|
|
8315
|
+
resolveNamespace: options.resolveNamespace,
|
|
8316
|
+
limit: fetchLimit
|
|
8317
|
+
});
|
|
8318
|
+
if (filteredResults.length >= qmdFetchLimit) {
|
|
8319
|
+
const capped2 = filteredResults.slice(0, qmdFetchLimit);
|
|
8320
|
+
await emitDebugSnapshot(capped2, fetchLimit);
|
|
8321
|
+
return capped2;
|
|
8322
|
+
}
|
|
8323
|
+
if (filteredResults.length > bestFiltered.length) {
|
|
8324
|
+
bestFiltered = filteredResults;
|
|
8325
|
+
}
|
|
8326
|
+
if (mergedResults.length === 0) {
|
|
8327
|
+
await emitDebugSnapshot(filteredResults, fetchLimit);
|
|
8328
|
+
return filteredResults;
|
|
8329
|
+
}
|
|
8330
|
+
if (mergedResults.length < fetchLimit && filteredResults.length > 0) {
|
|
8331
|
+
await emitDebugSnapshot(filteredResults, fetchLimit);
|
|
8332
|
+
return filteredResults;
|
|
7844
8333
|
}
|
|
8334
|
+
if (fetchLimit >= maxFetchLimit) {
|
|
8335
|
+
break;
|
|
8336
|
+
}
|
|
8337
|
+
const growth = Math.max(20, Math.floor(fetchLimit / 2));
|
|
8338
|
+
fetchLimit = Math.min(maxFetchLimit, fetchLimit + growth);
|
|
7845
8339
|
}
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
8340
|
+
const capped = bestFiltered.slice(0, qmdFetchLimit);
|
|
8341
|
+
await emitDebugSnapshot(capped, fetchLimit);
|
|
8342
|
+
return capped;
|
|
8343
|
+
}
|
|
8344
|
+
// Issue #1526 (seam 14): graph-recall expansion moved to
|
|
8345
|
+
// GraphRecallCoordinator. Thin delegation keeps the private API stable
|
|
8346
|
+
// for callers (recallInternal, cold-fallback pipeline) + tests.
|
|
8347
|
+
async expandResultsViaGraph(options) {
|
|
8348
|
+
return this.graphRecallCoordinator.expandResultsViaGraph(options);
|
|
7852
8349
|
}
|
|
8350
|
+
// Issue #1526 (seam 14): graph-recall snapshot moved to
|
|
8351
|
+
// GraphRecallCoordinator. Thin delegation keeps the private API stable.
|
|
7853
8352
|
async recordLastGraphRecallSnapshot(options) {
|
|
7854
|
-
|
|
7855
|
-
const snapshotPath = path6.join(
|
|
7856
|
-
options.storage.dir,
|
|
7857
|
-
"state",
|
|
7858
|
-
"last_graph_recall.json"
|
|
7859
|
-
);
|
|
7860
|
-
await mkdir3(path6.dirname(snapshotPath), { recursive: true });
|
|
7861
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7862
|
-
const totalSeedCount = options.seedPaths.length;
|
|
7863
|
-
const totalExpandedCount = options.expandedPaths.length;
|
|
7864
|
-
const seeds = options.seedPaths.slice(0, 64);
|
|
7865
|
-
const expanded = clampGraphRecallExpandedEntries(
|
|
7866
|
-
options.expandedPaths,
|
|
7867
|
-
64
|
|
7868
|
-
);
|
|
7869
|
-
const payload = {
|
|
7870
|
-
recordedAt: now,
|
|
7871
|
-
mode: options.recallMode,
|
|
7872
|
-
queryHash: createHash2("sha256").update(options.prompt).digest("hex"),
|
|
7873
|
-
queryLength: options.prompt.length,
|
|
7874
|
-
namespaces: options.recallNamespaces,
|
|
7875
|
-
seedCount: totalSeedCount,
|
|
7876
|
-
expandedCount: totalExpandedCount,
|
|
7877
|
-
seeds,
|
|
7878
|
-
expanded,
|
|
7879
|
-
status: options.status,
|
|
7880
|
-
reason: options.reason,
|
|
7881
|
-
shadowMode: options.shadowMode === true,
|
|
7882
|
-
queryIntent: options.queryIntent,
|
|
7883
|
-
seedResults: (options.seedResults ?? []).slice(0, 64),
|
|
7884
|
-
finalResults: (options.finalResults ?? []).slice(0, 64),
|
|
7885
|
-
shadowComparison: options.shadowComparison
|
|
7886
|
-
};
|
|
7887
|
-
await writeFile3(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
7888
|
-
} catch (err) {
|
|
7889
|
-
log.debug(`last graph recall write failed: ${err}`);
|
|
7890
|
-
}
|
|
8353
|
+
return this.graphRecallCoordinator.recordLastGraphRecallSnapshot(options);
|
|
7891
8354
|
}
|
|
7892
8355
|
async recordLastIntentSnapshot(options) {
|
|
7893
8356
|
try {
|
|
7894
|
-
const snapshotPath =
|
|
8357
|
+
const snapshotPath = path7.join(
|
|
7895
8358
|
options.storage.dir,
|
|
7896
8359
|
"state",
|
|
7897
8360
|
"last_intent.json"
|
|
7898
8361
|
);
|
|
7899
|
-
await
|
|
7900
|
-
await
|
|
8362
|
+
await mkdir4(path7.dirname(snapshotPath), { recursive: true });
|
|
8363
|
+
await writeFile4(
|
|
7901
8364
|
snapshotPath,
|
|
7902
8365
|
JSON.stringify(options.snapshot, null, 2),
|
|
7903
8366
|
"utf-8"
|
|
@@ -7908,233 +8371,111 @@ ${doc.content}` : doc.content,
|
|
|
7908
8371
|
}
|
|
7909
8372
|
async recordLastQmdRecallSnapshot(options) {
|
|
7910
8373
|
try {
|
|
7911
|
-
const snapshotPath =
|
|
8374
|
+
const snapshotPath = path7.join(
|
|
7912
8375
|
options.storage.dir,
|
|
7913
8376
|
"state",
|
|
7914
8377
|
"last_qmd_recall.json"
|
|
7915
8378
|
);
|
|
7916
|
-
await
|
|
7917
|
-
await
|
|
7918
|
-
snapshotPath,
|
|
7919
|
-
JSON.stringify(options.snapshot, null, 2),
|
|
7920
|
-
"utf-8"
|
|
7921
|
-
);
|
|
7922
|
-
} catch (err) {
|
|
7923
|
-
log.debug(`last qmd recall write failed: ${err}`);
|
|
7924
|
-
}
|
|
7925
|
-
}
|
|
7926
|
-
async recordLastIntentSnapshotForNamespace(options) {
|
|
7927
|
-
try {
|
|
7928
|
-
const stateDir = await this.resolveStateDirForNamespace(
|
|
7929
|
-
options.namespace
|
|
7930
|
-
);
|
|
7931
|
-
const snapshotPath = path6.join(stateDir, "last_intent.json");
|
|
7932
|
-
await mkdir3(path6.dirname(snapshotPath), { recursive: true });
|
|
7933
|
-
await writeFile3(
|
|
8379
|
+
await mkdir4(path7.dirname(snapshotPath), { recursive: true });
|
|
8380
|
+
await writeFile4(
|
|
7934
8381
|
snapshotPath,
|
|
7935
8382
|
JSON.stringify(options.snapshot, null, 2),
|
|
7936
8383
|
"utf-8"
|
|
7937
8384
|
);
|
|
7938
|
-
} catch (err) {
|
|
7939
|
-
log.debug(`last
|
|
7940
|
-
}
|
|
7941
|
-
}
|
|
7942
|
-
async
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
if (namespace !== this.config.defaultNamespace) {
|
|
7947
|
-
return path6.join(this.config.memoryDir, "namespaces", namespace, "state");
|
|
7948
|
-
}
|
|
7949
|
-
const candidate = path6.join(
|
|
7950
|
-
this.config.memoryDir,
|
|
7951
|
-
"namespaces",
|
|
7952
|
-
this.config.defaultNamespace
|
|
7953
|
-
);
|
|
7954
|
-
try {
|
|
7955
|
-
const candidateStat = await stat(candidate);
|
|
7956
|
-
if (candidateStat.isDirectory()) {
|
|
7957
|
-
return path6.join(candidate, "state");
|
|
7958
|
-
}
|
|
7959
|
-
} catch {
|
|
7960
|
-
}
|
|
7961
|
-
return path6.join(this.config.memoryDir, "state");
|
|
7962
|
-
}
|
|
7963
|
-
buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
|
|
7964
|
-
return results.slice(0, limit).map((result) => ({
|
|
7965
|
-
path: result.path,
|
|
7966
|
-
score: result.score,
|
|
7967
|
-
docid: result.docid,
|
|
7968
|
-
sourceLabels: sourceLabelResolver(result.path)
|
|
7969
|
-
}));
|
|
7970
|
-
}
|
|
7971
|
-
getRecallSectionEntry(sectionId) {
|
|
7972
|
-
const pipeline = Array.isArray(this.config.recallPipeline) ? this.config.recallPipeline : [];
|
|
7973
|
-
return pipeline.find((entry) => entry.id === sectionId);
|
|
7974
|
-
}
|
|
7975
|
-
isRecallSectionEnabled(sectionId, defaultEnabled = true) {
|
|
7976
|
-
const entry = this.getRecallSectionEntry(sectionId);
|
|
7977
|
-
if (!entry) return defaultEnabled;
|
|
7978
|
-
return entry.enabled !== false;
|
|
7979
|
-
}
|
|
7980
|
-
isSpecializedRecallSectionEnabled(sectionId, topLevelEnabled) {
|
|
7981
|
-
const entry = this.getRecallSectionEntry(sectionId);
|
|
7982
|
-
if (!entry) return topLevelEnabled;
|
|
7983
|
-
return entry.enabled === true || topLevelEnabled && entry.enabled !== false;
|
|
7984
|
-
}
|
|
7985
|
-
getRecallSectionMaxChars(sectionId) {
|
|
7986
|
-
const entry = this.getRecallSectionEntry(sectionId);
|
|
7987
|
-
if (!entry) return void 0;
|
|
7988
|
-
if (entry.maxChars === null) return null;
|
|
7989
|
-
if (typeof entry.maxChars !== "number") return void 0;
|
|
7990
|
-
return Math.max(0, Math.floor(entry.maxChars));
|
|
7991
|
-
}
|
|
7992
|
-
getRecallSectionNumber(sectionId, key) {
|
|
7993
|
-
const entry = this.getRecallSectionEntry(sectionId);
|
|
7994
|
-
if (!entry) return void 0;
|
|
7995
|
-
const value = entry[key];
|
|
7996
|
-
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
7997
|
-
return Math.max(0, Math.floor(value));
|
|
7998
|
-
}
|
|
7999
|
-
appendRecallSection(sectionBuckets, sectionId, content) {
|
|
8000
|
-
if (!this.isRecallSectionEnabled(sectionId)) return false;
|
|
8001
|
-
const trimmed = content.trim();
|
|
8002
|
-
if (trimmed.length === 0) return false;
|
|
8003
|
-
const maxChars = this.getRecallSectionMaxChars(sectionId);
|
|
8004
|
-
let finalContent = trimmed;
|
|
8005
|
-
if (maxChars === 0) return false;
|
|
8006
|
-
if (typeof maxChars === "number" && finalContent.length > maxChars) {
|
|
8007
|
-
finalContent = `${finalContent.slice(0, maxChars)}
|
|
8008
|
-
|
|
8009
|
-
...(trimmed)
|
|
8010
|
-
`;
|
|
8011
|
-
}
|
|
8012
|
-
const existing = sectionBuckets.get(sectionId) ?? [];
|
|
8013
|
-
existing.push(finalContent);
|
|
8014
|
-
sectionBuckets.set(sectionId, existing);
|
|
8015
|
-
return true;
|
|
8016
|
-
}
|
|
8017
|
-
truncateRecallSectionToBudget(content, maxChars) {
|
|
8018
|
-
if (maxChars <= 0) return "";
|
|
8019
|
-
if (content.length <= maxChars) return content;
|
|
8020
|
-
const suffix = "\n\n...(memory context trimmed)";
|
|
8021
|
-
if (maxChars <= suffix.length) {
|
|
8022
|
-
return content.slice(0, maxChars);
|
|
8023
|
-
}
|
|
8024
|
-
return `${content.slice(0, maxChars - suffix.length)}${suffix}`;
|
|
8025
|
-
}
|
|
8026
|
-
protectedRecallSectionIds(sectionBuckets) {
|
|
8027
|
-
const protectedIds = /* @__PURE__ */ new Set();
|
|
8028
|
-
if ((sectionBuckets.get("memories")?.length ?? 0) > 0) {
|
|
8029
|
-
protectedIds.add("memories");
|
|
8030
|
-
}
|
|
8031
|
-
return protectedIds;
|
|
8032
|
-
}
|
|
8033
|
-
protectedRecallReservationChars(content) {
|
|
8034
|
-
const headingBoundary = content.indexOf("\n\n");
|
|
8035
|
-
const headingChars = headingBoundary >= 0 ? headingBoundary + 2 : Math.min(content.length, 24);
|
|
8036
|
-
return Math.min(content.length, Math.max(headingChars, 24));
|
|
8037
|
-
}
|
|
8038
|
-
estimateReservedRecallBudget(entries, startIndex, protectedIds, alreadyIncludedCount) {
|
|
8039
|
-
const separatorLength = "\n\n---\n\n".length;
|
|
8040
|
-
let reserved = 0;
|
|
8041
|
-
let simulatedIncluded = alreadyIncludedCount;
|
|
8042
|
-
for (let i = startIndex; i < entries.length; i += 1) {
|
|
8043
|
-
const entry = entries[i];
|
|
8044
|
-
if (!entry || !protectedIds.has(entry.id)) continue;
|
|
8045
|
-
if (simulatedIncluded > 0) {
|
|
8046
|
-
reserved += separatorLength;
|
|
8047
|
-
}
|
|
8048
|
-
reserved += this.protectedRecallReservationChars(entry.content);
|
|
8049
|
-
simulatedIncluded += 1;
|
|
8050
|
-
}
|
|
8051
|
-
return reserved;
|
|
8052
|
-
}
|
|
8053
|
-
getRecallBudgetChars(override) {
|
|
8054
|
-
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
8055
|
-
return Math.floor(override);
|
|
8056
|
-
}
|
|
8057
|
-
const configuredBudget = this.config.recallBudgetChars;
|
|
8058
|
-
if (typeof configuredBudget === "number" && Number.isFinite(configuredBudget) && configuredBudget >= 0) {
|
|
8059
|
-
return Math.floor(configuredBudget);
|
|
8060
|
-
}
|
|
8061
|
-
const tokenBudget = this.config.maxMemoryTokens;
|
|
8062
|
-
if (typeof tokenBudget === "number" && Number.isFinite(tokenBudget) && tokenBudget >= 0) {
|
|
8063
|
-
return Math.floor(tokenBudget * 4);
|
|
8064
|
-
}
|
|
8065
|
-
return 0;
|
|
8066
|
-
}
|
|
8067
|
-
assembleRecallSections(sectionBuckets, budgetOverride) {
|
|
8068
|
-
const orderedEntries = [];
|
|
8069
|
-
const pipeline = Array.isArray(this.config.recallPipeline) ? this.config.recallPipeline : [];
|
|
8070
|
-
const orderedIds = pipeline.filter((entry) => entry.enabled !== false).map((entry) => entry.id);
|
|
8071
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8072
|
-
for (const id of orderedIds) {
|
|
8073
|
-
const chunks = sectionBuckets.get(id);
|
|
8074
|
-
if (!chunks || chunks.length === 0) continue;
|
|
8075
|
-
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
8076
|
-
seen.add(id);
|
|
8077
|
-
}
|
|
8078
|
-
for (const [id, chunks] of sectionBuckets.entries()) {
|
|
8079
|
-
if (seen.has(id)) continue;
|
|
8080
|
-
if (chunks.length === 0) continue;
|
|
8081
|
-
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
8082
|
-
}
|
|
8083
|
-
const budget = this.getRecallBudgetChars(budgetOverride);
|
|
8084
|
-
if (budget === 0) {
|
|
8085
|
-
return {
|
|
8086
|
-
sections: [],
|
|
8087
|
-
includedIds: [],
|
|
8088
|
-
omittedIds: orderedEntries.map((entry) => entry.id),
|
|
8089
|
-
truncated: orderedEntries.length > 0,
|
|
8090
|
-
finalChars: 0
|
|
8091
|
-
};
|
|
8092
|
-
}
|
|
8093
|
-
const separator = "\n\n---\n\n";
|
|
8094
|
-
const protectedIds = this.protectedRecallSectionIds(sectionBuckets);
|
|
8095
|
-
const sections = [];
|
|
8096
|
-
const includedIds = [];
|
|
8097
|
-
const omittedIds = [];
|
|
8098
|
-
let usedChars = 0;
|
|
8099
|
-
let truncated = false;
|
|
8100
|
-
for (let index = 0; index < orderedEntries.length; index += 1) {
|
|
8101
|
-
const entry = orderedEntries[index];
|
|
8102
|
-
const separatorChars = sections.length > 0 ? separator.length : 0;
|
|
8103
|
-
const reserve = protectedIds.has(entry.id) ? 0 : this.estimateReservedRecallBudget(
|
|
8104
|
-
orderedEntries,
|
|
8105
|
-
index + 1,
|
|
8106
|
-
protectedIds,
|
|
8107
|
-
sections.length + 1
|
|
8108
|
-
);
|
|
8109
|
-
const availableForEntry = budget - usedChars - separatorChars - reserve;
|
|
8110
|
-
if (availableForEntry <= 0) {
|
|
8111
|
-
omittedIds.push(entry.id);
|
|
8112
|
-
truncated = true;
|
|
8113
|
-
continue;
|
|
8114
|
-
}
|
|
8115
|
-
const finalContent = this.truncateRecallSectionToBudget(
|
|
8116
|
-
entry.content,
|
|
8117
|
-
availableForEntry
|
|
8385
|
+
} catch (err) {
|
|
8386
|
+
log.debug(`last qmd recall write failed: ${err}`);
|
|
8387
|
+
}
|
|
8388
|
+
}
|
|
8389
|
+
async recordLastIntentSnapshotForNamespace(options) {
|
|
8390
|
+
try {
|
|
8391
|
+
const stateDir = await this.resolveStateDirForNamespace(
|
|
8392
|
+
options.namespace
|
|
8118
8393
|
);
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8394
|
+
const snapshotPath = path7.join(stateDir, "last_intent.json");
|
|
8395
|
+
await mkdir4(path7.dirname(snapshotPath), { recursive: true });
|
|
8396
|
+
await writeFile4(
|
|
8397
|
+
snapshotPath,
|
|
8398
|
+
JSON.stringify(options.snapshot, null, 2),
|
|
8399
|
+
"utf-8"
|
|
8400
|
+
);
|
|
8401
|
+
} catch (err) {
|
|
8402
|
+
log.debug(`last intent write failed: ${err}`);
|
|
8403
|
+
}
|
|
8404
|
+
}
|
|
8405
|
+
async resolveStateDirForNamespace(namespace) {
|
|
8406
|
+
if (!resolveNamespaceCapabilities(this.config).namespaces) {
|
|
8407
|
+
return path7.join(this.config.memoryDir, "state");
|
|
8408
|
+
}
|
|
8409
|
+
if (namespace !== this.config.defaultNamespace) {
|
|
8410
|
+
return path7.join(this.config.memoryDir, "namespaces", namespace, "state");
|
|
8411
|
+
}
|
|
8412
|
+
const candidate = path7.join(
|
|
8413
|
+
this.config.memoryDir,
|
|
8414
|
+
"namespaces",
|
|
8415
|
+
this.config.defaultNamespace
|
|
8416
|
+
);
|
|
8417
|
+
try {
|
|
8418
|
+
const candidateStat = await stat(candidate);
|
|
8419
|
+
if (candidateStat.isDirectory()) {
|
|
8420
|
+
return path7.join(candidate, "state");
|
|
8126
8421
|
}
|
|
8127
|
-
|
|
8128
|
-
includedIds.push(entry.id);
|
|
8129
|
-
usedChars += separatorChars + finalContent.length;
|
|
8422
|
+
} catch {
|
|
8130
8423
|
}
|
|
8131
|
-
return
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8424
|
+
return path7.join(this.config.memoryDir, "state");
|
|
8425
|
+
}
|
|
8426
|
+
buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
|
|
8427
|
+
return results.slice(0, limit).map((result) => ({
|
|
8428
|
+
path: result.path,
|
|
8429
|
+
score: result.score,
|
|
8430
|
+
docid: result.docid,
|
|
8431
|
+
sourceLabels: sourceLabelResolver(result.path)
|
|
8432
|
+
}));
|
|
8433
|
+
}
|
|
8434
|
+
// Issue #1526 (seam 13): recall section budgeting/assembly moved to
|
|
8435
|
+
// RecallSectionCoordinator. Thin delegation keeps the orchestrator's
|
|
8436
|
+
// recallInternal call sites stable.
|
|
8437
|
+
getRecallSectionEntry(sectionId) {
|
|
8438
|
+
return this.recallSectionCoordinator.getRecallSectionEntry(sectionId);
|
|
8439
|
+
}
|
|
8440
|
+
isRecallSectionEnabled(sectionId, defaultEnabled = true) {
|
|
8441
|
+
return this.recallSectionCoordinator.isRecallSectionEnabled(
|
|
8442
|
+
sectionId,
|
|
8443
|
+
defaultEnabled
|
|
8444
|
+
);
|
|
8445
|
+
}
|
|
8446
|
+
isSpecializedRecallSectionEnabled(sectionId, topLevelEnabled) {
|
|
8447
|
+
return this.recallSectionCoordinator.isSpecializedRecallSectionEnabled(
|
|
8448
|
+
sectionId,
|
|
8449
|
+
topLevelEnabled
|
|
8450
|
+
);
|
|
8451
|
+
}
|
|
8452
|
+
getRecallSectionMaxChars(sectionId) {
|
|
8453
|
+
return this.recallSectionCoordinator.getRecallSectionMaxChars(sectionId);
|
|
8454
|
+
}
|
|
8455
|
+
getRecallSectionNumber(sectionId, key) {
|
|
8456
|
+
return this.recallSectionCoordinator.getRecallSectionNumber(sectionId, key);
|
|
8457
|
+
}
|
|
8458
|
+
appendRecallSection(sectionBuckets, sectionId, content) {
|
|
8459
|
+
return this.recallSectionCoordinator.appendRecallSection(
|
|
8460
|
+
sectionBuckets,
|
|
8461
|
+
sectionId,
|
|
8462
|
+
content
|
|
8463
|
+
);
|
|
8464
|
+
}
|
|
8465
|
+
truncateRecallSectionToBudget(content, maxChars) {
|
|
8466
|
+
return this.recallSectionCoordinator.truncateRecallSectionToBudget(
|
|
8467
|
+
content,
|
|
8468
|
+
maxChars
|
|
8469
|
+
);
|
|
8470
|
+
}
|
|
8471
|
+
getRecallBudgetChars(override) {
|
|
8472
|
+
return this.recallSectionCoordinator.getRecallBudgetChars(override);
|
|
8473
|
+
}
|
|
8474
|
+
assembleRecallSections(sectionBuckets, budgetOverride) {
|
|
8475
|
+
return this.recallSectionCoordinator.assembleRecallSections(
|
|
8476
|
+
sectionBuckets,
|
|
8477
|
+
budgetOverride
|
|
8478
|
+
);
|
|
8138
8479
|
}
|
|
8139
8480
|
/**
|
|
8140
8481
|
* Clock source for the shared post-retrieval assembly/enrichment budget. The
|
|
@@ -8211,8 +8552,8 @@ ${doc.content}` : doc.content,
|
|
|
8211
8552
|
timings,
|
|
8212
8553
|
logger: log
|
|
8213
8554
|
});
|
|
8214
|
-
const promptHash =
|
|
8215
|
-
const traceId =
|
|
8555
|
+
const promptHash = createHash3("sha256").update(prompt).digest("hex");
|
|
8556
|
+
const traceId = createHash3("sha256").update(`${sessionKey ?? "default"}:${recallStart}:${promptHash}`).digest("hex").slice(0, 16);
|
|
8216
8557
|
const sectionBuckets = /* @__PURE__ */ new Map();
|
|
8217
8558
|
const queryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {
|
|
8218
8559
|
cronRecallPolicyEnabled: resolveRecallAuxiliaryCapabilities(this.config).cronRecallPolicy,
|
|
@@ -8221,7 +8562,7 @@ ${doc.content}` : doc.content,
|
|
|
8221
8562
|
cronConversationRecallMode: this.config.cronConversationRecallMode
|
|
8222
8563
|
});
|
|
8223
8564
|
const retrievalQuery = queryPolicy.retrievalQuery || prompt;
|
|
8224
|
-
const retrievalQueryHash =
|
|
8565
|
+
const retrievalQueryHash = createHash3("sha256").update(retrievalQuery).digest("hex");
|
|
8225
8566
|
const policyVersion = this.currentPolicyVersion();
|
|
8226
8567
|
let impressionRecorded = false;
|
|
8227
8568
|
let recallSource = "none";
|
|
@@ -8360,7 +8701,7 @@ ${doc.content}` : doc.content,
|
|
|
8360
8701
|
const graphExpandedResultPaths = /* @__PURE__ */ new Set();
|
|
8361
8702
|
const graphSourceLabelsForPath = (resultPath) => {
|
|
8362
8703
|
const labels = [];
|
|
8363
|
-
const normalizedPath = resultPath.split(
|
|
8704
|
+
const normalizedPath = resultPath.split(path7.sep).join("/");
|
|
8364
8705
|
const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
|
|
8365
8706
|
if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
|
|
8366
8707
|
if (graphExpandedResultPaths.has(resultPath))
|
|
@@ -8510,7 +8851,7 @@ ${doc.content}` : doc.content,
|
|
|
8510
8851
|
profileStorageNamespaces.map((namespace) => this.storageRouter.storageFor(namespace))
|
|
8511
8852
|
);
|
|
8512
8853
|
const emptyProfileStorage = new Proxy(
|
|
8513
|
-
{ dir:
|
|
8854
|
+
{ dir: path7.join(this.config.memoryDir, ".empty-scope-profile") },
|
|
8514
8855
|
{
|
|
8515
8856
|
get(target, prop) {
|
|
8516
8857
|
if (prop in target) return target[prop];
|
|
@@ -9986,11 +10327,11 @@ ${formatted}`;
|
|
|
9986
10327
|
if (!resolveRecallAuxiliaryCapabilities(this.config).compactionReset) return null;
|
|
9987
10328
|
const workspaceDir = compactionWorkspaceDir || this.config.workspaceDir || defaultWorkspaceDir();
|
|
9988
10329
|
const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
|
|
9989
|
-
const signalPath =
|
|
10330
|
+
const signalPath = path7.join(
|
|
9990
10331
|
workspaceDir,
|
|
9991
10332
|
`.compaction-reset-signal-${safeSessionKey}`
|
|
9992
10333
|
);
|
|
9993
|
-
const bootPath =
|
|
10334
|
+
const bootPath = path7.join(workspaceDir, "BOOT.md");
|
|
9994
10335
|
try {
|
|
9995
10336
|
const signalStat = await stat(signalPath).catch(() => null);
|
|
9996
10337
|
if (!signalStat) return null;
|
|
@@ -12261,7 +12602,7 @@ _Context: ${topQuestion.context}_`
|
|
|
12261
12602
|
const shouldUseStableBatchKey = turns.some(
|
|
12262
12603
|
(turn) => turn.persistProcessedFingerprint === true || typeof turn.turnFingerprint === "string" && turn.turnFingerprint.length > 0
|
|
12263
12604
|
);
|
|
12264
|
-
const stableBatchFingerprint = shouldUseStableBatchKey ?
|
|
12605
|
+
const stableBatchFingerprint = shouldUseStableBatchKey ? createHash3("sha256").update(
|
|
12265
12606
|
turns.map(
|
|
12266
12607
|
(turn) => [
|
|
12267
12608
|
turn.role,
|
|
@@ -12511,7 +12852,7 @@ _Context: ${topQuestion.context}_`
|
|
|
12511
12852
|
buildExtractionFingerprint(turns, bufferKey) {
|
|
12512
12853
|
const normalized = this.normalizeExtractionFingerprintTurns(turns).join("\n");
|
|
12513
12854
|
if (!normalized) return null;
|
|
12514
|
-
return
|
|
12855
|
+
return createHash3("sha256").update(`${bufferKey}
|
|
12515
12856
|
${normalized}`).digest("hex");
|
|
12516
12857
|
}
|
|
12517
12858
|
shouldQueueExtraction(turns, options = {}) {
|
|
@@ -14592,7 +14933,7 @@ ${normalized}`).digest("hex");
|
|
|
14592
14933
|
const allMems = allMemsForGraph ?? [];
|
|
14593
14934
|
for (const m of allMems) {
|
|
14594
14935
|
if (m.frontmatter.entityRef === entityRef) {
|
|
14595
|
-
const rel =
|
|
14936
|
+
const rel = path7.relative(storage.dir, m.path);
|
|
14596
14937
|
if (rel !== memoryRelPath) entitySiblings.push(rel);
|
|
14597
14938
|
}
|
|
14598
14939
|
}
|
|
@@ -14916,7 +15257,7 @@ ${normalized}`).digest("hex");
|
|
|
14916
15257
|
}
|
|
14917
15258
|
if (resolveConsolidationCapabilities(this.config).semanticConsolidation) {
|
|
14918
15259
|
try {
|
|
14919
|
-
const stateFilePath =
|
|
15260
|
+
const stateFilePath = path7.join(
|
|
14920
15261
|
this.config.memoryDir,
|
|
14921
15262
|
"state",
|
|
14922
15263
|
"semantic-consolidation-last-run.json"
|
|
@@ -14964,9 +15305,9 @@ ${normalized}`).digest("hex");
|
|
|
14964
15305
|
);
|
|
14965
15306
|
}
|
|
14966
15307
|
if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
|
|
14967
|
-
const stateDir =
|
|
14968
|
-
await
|
|
14969
|
-
await
|
|
15308
|
+
const stateDir = path7.join(this.config.memoryDir, "state");
|
|
15309
|
+
await mkdir4(stateDir, { recursive: true });
|
|
15310
|
+
await writeFile4(
|
|
14970
15311
|
stateFilePath,
|
|
14971
15312
|
JSON.stringify({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
14972
15313
|
"utf-8"
|
|
@@ -15304,30 +15645,13 @@ ${reflectionsContent.trim()}
|
|
|
15304
15645
|
return this.recallRerankCoordinator.applyMmrToQmdResults(sectionId, results, caps);
|
|
15305
15646
|
}
|
|
15306
15647
|
buildLastRecallBudgetSummary(options) {
|
|
15307
|
-
return
|
|
15308
|
-
requestedTopK: options.requestedTopK,
|
|
15309
|
-
appliedTopK: options.recallResultLimit,
|
|
15310
|
-
recallBudgetChars: this.getRecallBudgetChars(),
|
|
15311
|
-
maxMemoryTokens: this.config.maxMemoryTokens,
|
|
15312
|
-
qmdFetchLimit: options.qmdFetchLimit,
|
|
15313
|
-
qmdHybridFetchLimit: options.qmdHybridFetchLimit,
|
|
15314
|
-
finalContextChars: options.finalContextChars,
|
|
15315
|
-
truncated: options.truncated,
|
|
15316
|
-
includedSections: [...options.includedSections ?? []],
|
|
15317
|
-
omittedSections: [...options.omittedSections ?? []]
|
|
15318
|
-
};
|
|
15648
|
+
return this.recallSectionCoordinator.buildLastRecallBudgetSummary(options);
|
|
15319
15649
|
}
|
|
15320
15650
|
collectLastRecallSources(sectionBuckets, recallSource) {
|
|
15321
|
-
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
for (const [sectionId, chunks] of sectionBuckets.entries()) {
|
|
15326
|
-
if (chunks.length > 0) {
|
|
15327
|
-
used.add(sectionId);
|
|
15328
|
-
}
|
|
15329
|
-
}
|
|
15330
|
-
return [...used];
|
|
15651
|
+
return this.recallSectionCoordinator.collectLastRecallSources(
|
|
15652
|
+
sectionBuckets,
|
|
15653
|
+
recallSource
|
|
15654
|
+
);
|
|
15331
15655
|
}
|
|
15332
15656
|
/**
|
|
15333
15657
|
* Issue #373 — nearest-neighbor lookup for the write-time semantic dedup
|
|
@@ -15377,12 +15701,12 @@ ${reflectionsContent.trim()}
|
|
|
15377
15701
|
*/
|
|
15378
15702
|
semanticDedupScopeFor(targetStorage) {
|
|
15379
15703
|
if (!resolveNamespaceCapabilities(this.config).namespaces) return {};
|
|
15380
|
-
const memoryDir =
|
|
15381
|
-
const storageDir =
|
|
15704
|
+
const memoryDir = path7.resolve(this.config.memoryDir);
|
|
15705
|
+
const storageDir = path7.resolve(targetStorage.dir);
|
|
15382
15706
|
if (storageDir === memoryDir) {
|
|
15383
15707
|
return { pathExcludePrefixes: ["namespaces/"] };
|
|
15384
15708
|
}
|
|
15385
|
-
let rel =
|
|
15709
|
+
let rel = path7.relative(memoryDir, storageDir);
|
|
15386
15710
|
if (!rel || rel.startsWith("..")) {
|
|
15387
15711
|
log.debug(
|
|
15388
15712
|
`semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
|
|
@@ -15401,7 +15725,7 @@ ${reflectionsContent.trim()}
|
|
|
15401
15725
|
if (hits.length === 0) return [];
|
|
15402
15726
|
const results = [];
|
|
15403
15727
|
for (const hit of hits) {
|
|
15404
|
-
const fullPath =
|
|
15728
|
+
const fullPath = path7.isAbsolute(hit.path) ? hit.path : path7.join(this.config.memoryDir, hit.path);
|
|
15405
15729
|
const memory = await this.storage.readMemoryByPath(fullPath);
|
|
15406
15730
|
if (!memory) continue;
|
|
15407
15731
|
results.push({
|
|
@@ -15598,7 +15922,7 @@ ${reflectionsContent.trim()}
|
|
|
15598
15922
|
const storage = await this.storageRouter.storageFor(namespace);
|
|
15599
15923
|
const storageDir = typeof storage.dir === "string" && storage.dir ? storage.dir : null;
|
|
15600
15924
|
if (!storageDir) continue;
|
|
15601
|
-
const recallRoot =
|
|
15925
|
+
const recallRoot = path7.resolve(storageDir);
|
|
15602
15926
|
if (seenRecallRoots.has(recallRoot)) continue;
|
|
15603
15927
|
seenRecallRoots.add(recallRoot);
|
|
15604
15928
|
recallRoots.push(recallRoot);
|
|
@@ -15622,8 +15946,8 @@ ${reflectionsContent.trim()}
|
|
|
15622
15946
|
if (resolvedCold) scopedResults.push(resolvedCold.result);
|
|
15623
15947
|
continue;
|
|
15624
15948
|
}
|
|
15625
|
-
if (
|
|
15626
|
-
const resolvedPath =
|
|
15949
|
+
if (path7.isAbsolute(result.path)) {
|
|
15950
|
+
const resolvedPath = path7.resolve(result.path);
|
|
15627
15951
|
if (recallRoots.some(
|
|
15628
15952
|
(recallRoot) => isPathInsideStorageRoot(recallRoot, resolvedPath)
|
|
15629
15953
|
)) {
|
|
@@ -16289,58 +16613,11 @@ ${reflectionsContent.trim()}
|
|
|
16289
16613
|
* Uses QMD to find similar memories, then LLM to verify contradiction.
|
|
16290
16614
|
*/
|
|
16291
16615
|
async checkForContradiction(content, category, namespaceScope) {
|
|
16292
|
-
|
|
16293
|
-
|
|
16294
|
-
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
mode: "search"
|
|
16298
|
-
});
|
|
16299
|
-
for (const result of results) {
|
|
16300
|
-
if (result.score < this.config.contradictionSimilarityThreshold) {
|
|
16301
|
-
continue;
|
|
16302
|
-
}
|
|
16303
|
-
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
16304
|
-
if (!memoryId) continue;
|
|
16305
|
-
const resultNamespace = this.namespaceFromPath(result.path);
|
|
16306
|
-
if (resultNamespace !== namespaceScope) continue;
|
|
16307
|
-
const resultStorage = await this.storageRouter.storageFor(resultNamespace);
|
|
16308
|
-
const existingMemory = await resultStorage.getMemoryById(memoryId);
|
|
16309
|
-
if (!existingMemory) continue;
|
|
16310
|
-
if (existingMemory.frontmatter.status === "superseded" || existingMemory.frontmatter.status === "forgotten") {
|
|
16311
|
-
continue;
|
|
16312
|
-
}
|
|
16313
|
-
const verification = await this.extraction.verifyContradiction(
|
|
16314
|
-
{ content, category },
|
|
16315
|
-
{
|
|
16316
|
-
id: existingMemory.frontmatter.id,
|
|
16317
|
-
content: existingMemory.content,
|
|
16318
|
-
category: existingMemory.frontmatter.category,
|
|
16319
|
-
created: existingMemory.frontmatter.created
|
|
16320
|
-
}
|
|
16321
|
-
);
|
|
16322
|
-
if (!verification) continue;
|
|
16323
|
-
if (verification.isContradiction && verification.confidence >= this.config.contradictionMinConfidence) {
|
|
16324
|
-
if (verification.whichIsNewer === "first") {
|
|
16325
|
-
log.info(
|
|
16326
|
-
`detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory \u2014 existing is newer, incoming fact is stale`
|
|
16327
|
-
);
|
|
16328
|
-
continue;
|
|
16329
|
-
}
|
|
16330
|
-
log.info(
|
|
16331
|
-
`detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory${this.config.contradictionAutoResolve ? " (auto-resolved)" : " (queued for manual review)"}`
|
|
16332
|
-
);
|
|
16333
|
-
return {
|
|
16334
|
-
supersededId: existingMemory.frontmatter.id,
|
|
16335
|
-
confidence: verification.confidence,
|
|
16336
|
-
reason: verification.reasoning,
|
|
16337
|
-
supersededPath: existingMemory.path,
|
|
16338
|
-
supersededCreated: existingMemory.frontmatter.created,
|
|
16339
|
-
supersededTags: existingMemory.frontmatter.tags ?? []
|
|
16340
|
-
};
|
|
16341
|
-
}
|
|
16342
|
-
}
|
|
16343
|
-
return null;
|
|
16616
|
+
return this.contradictionLinkingCoordinator.checkForContradiction(
|
|
16617
|
+
content,
|
|
16618
|
+
category,
|
|
16619
|
+
namespaceScope
|
|
16620
|
+
);
|
|
16344
16621
|
}
|
|
16345
16622
|
/**
|
|
16346
16623
|
* #1645: Complete the deferred contradiction auto-resolve after writeMemory
|
|
@@ -16351,40 +16628,12 @@ ${reflectionsContent.trim()}
|
|
|
16351
16628
|
* supersedes before tombstone status is known" defect class.
|
|
16352
16629
|
*/
|
|
16353
16630
|
async applyDeferredContradictionResolve(contradiction, storage, newMemoryId, postWriteGuard) {
|
|
16354
|
-
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
16359
|
-
|
|
16360
|
-
} catch (err) {
|
|
16361
|
-
log.warn(
|
|
16362
|
-
`contradiction auto-resolve supersedes clear failed for blocked ${newMemoryId}: ${err}`
|
|
16363
|
-
);
|
|
16364
|
-
}
|
|
16365
|
-
}
|
|
16366
|
-
if (!contradiction || !this.config.contradictionAutoResolve || postWriteGuard) {
|
|
16367
|
-
return;
|
|
16368
|
-
}
|
|
16369
|
-
try {
|
|
16370
|
-
await storage.supersedeMemory(
|
|
16371
|
-
contradiction.supersededId,
|
|
16372
|
-
newMemoryId,
|
|
16373
|
-
contradiction.reason
|
|
16374
|
-
);
|
|
16375
|
-
if (resolveIndexingCapabilities(this.config).queryAwareIndexing && contradiction.supersededPath) {
|
|
16376
|
-
deindexMemory(
|
|
16377
|
-
this.config.memoryDir,
|
|
16378
|
-
contradiction.supersededPath,
|
|
16379
|
-
contradiction.supersededCreated,
|
|
16380
|
-
contradiction.supersededTags
|
|
16381
|
-
);
|
|
16382
|
-
}
|
|
16383
|
-
} catch (err) {
|
|
16384
|
-
log.warn(
|
|
16385
|
-
`contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`
|
|
16386
|
-
);
|
|
16387
|
-
}
|
|
16631
|
+
return this.contradictionLinkingCoordinator.applyDeferredContradictionResolve(
|
|
16632
|
+
contradiction,
|
|
16633
|
+
storage,
|
|
16634
|
+
newMemoryId,
|
|
16635
|
+
postWriteGuard
|
|
16636
|
+
);
|
|
16388
16637
|
}
|
|
16389
16638
|
// ---------------------------------------------------------------------------
|
|
16390
16639
|
// Memory Linking (Phase 3A)
|
|
@@ -16393,68 +16642,11 @@ ${reflectionsContent.trim()}
|
|
|
16393
16642
|
* Suggest links for a new memory based on similar existing memories.
|
|
16394
16643
|
*/
|
|
16395
16644
|
async suggestLinksForMemory(content, category, namespaceScope) {
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
maxResults: 5,
|
|
16401
|
-
mode: "search"
|
|
16402
|
-
});
|
|
16403
|
-
if (results.length === 0) return [];
|
|
16404
|
-
const candidates = [];
|
|
16405
|
-
for (const result of results) {
|
|
16406
|
-
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
16407
|
-
if (!memoryId) continue;
|
|
16408
|
-
const resultNamespace = this.namespaceFromPath(result.path);
|
|
16409
|
-
if (resultNamespace !== namespaceScope) continue;
|
|
16410
|
-
const resultStorage = await this.storageRouter.storageFor(resultNamespace);
|
|
16411
|
-
const memory = await resultStorage.getMemoryById(memoryId);
|
|
16412
|
-
if (memory && memory.frontmatter.status !== "superseded" && memory.frontmatter.status !== "forgotten") {
|
|
16413
|
-
candidates.push({
|
|
16414
|
-
id: memory.frontmatter.id,
|
|
16415
|
-
content: memory.content,
|
|
16416
|
-
category: memory.frontmatter.category
|
|
16417
|
-
});
|
|
16418
|
-
}
|
|
16419
|
-
}
|
|
16420
|
-
if (candidates.length === 0) return [];
|
|
16421
|
-
const suggestions = await this.extraction.suggestLinks(
|
|
16422
|
-
{ content, category },
|
|
16423
|
-
candidates
|
|
16645
|
+
return this.contradictionLinkingCoordinator.suggestLinksForMemory(
|
|
16646
|
+
content,
|
|
16647
|
+
category,
|
|
16648
|
+
namespaceScope
|
|
16424
16649
|
);
|
|
16425
|
-
if (!suggestions || suggestions.links.length === 0) return [];
|
|
16426
|
-
return suggestions.links.map((link) => ({
|
|
16427
|
-
targetId: link.targetId,
|
|
16428
|
-
linkType: link.linkType,
|
|
16429
|
-
strength: link.strength,
|
|
16430
|
-
reason: link.reason || void 0
|
|
16431
|
-
}));
|
|
16432
|
-
}
|
|
16433
|
-
async graphSeedPathRelativeToStorage(storage, result, recallNamespaces = []) {
|
|
16434
|
-
const parts = qmdCollectionPathParts(result.path);
|
|
16435
|
-
if (parts) {
|
|
16436
|
-
const memory = await this.readQmdResultMemory(
|
|
16437
|
-
result.path,
|
|
16438
|
-
storage,
|
|
16439
|
-
recallNamespaces
|
|
16440
|
-
);
|
|
16441
|
-
return memory ? graphPathRelativeToStorage(storage.dir, memory.path) : null;
|
|
16442
|
-
}
|
|
16443
|
-
return graphPathRelativeToStorage(storage.dir, result.path);
|
|
16444
|
-
}
|
|
16445
|
-
async graphSeedPathsWithinDeadline(storage, results, deadlineAtMs, recallNamespaces = []) {
|
|
16446
|
-
const resolved = [];
|
|
16447
|
-
for (const result of results) {
|
|
16448
|
-
if (Date.now() >= deadlineAtMs) break;
|
|
16449
|
-
const seedPath = await this.graphSeedPathRelativeToStorage(
|
|
16450
|
-
storage,
|
|
16451
|
-
result,
|
|
16452
|
-
recallNamespaces
|
|
16453
|
-
);
|
|
16454
|
-
if (Date.now() >= deadlineAtMs) break;
|
|
16455
|
-
if (seedPath) resolved.push(seedPath);
|
|
16456
|
-
}
|
|
16457
|
-
return resolved;
|
|
16458
16650
|
}
|
|
16459
16651
|
namespaceFromPath(p) {
|
|
16460
16652
|
if (!resolveNamespaceCapabilities(this.config).namespaces) return this.config.defaultNamespace;
|
|
@@ -16515,6 +16707,9 @@ export {
|
|
|
16515
16707
|
buildProcedureRecallSection,
|
|
16516
16708
|
hasIdentityRecoveryIntent,
|
|
16517
16709
|
resolveEffectiveIdentityInjectionMode,
|
|
16710
|
+
mergeGraphExpandedResults,
|
|
16711
|
+
graphPathRelativeToStorage,
|
|
16712
|
+
blendGraphExpandedRecallScore,
|
|
16518
16713
|
decideSemanticDedup,
|
|
16519
16714
|
DEFAULT_TAXONOMY,
|
|
16520
16715
|
generateResolverDocument,
|
|
@@ -16546,9 +16741,6 @@ export {
|
|
|
16546
16741
|
resolveRecallModeDecisionAsync,
|
|
16547
16742
|
computeArtifactCandidateFetchLimit,
|
|
16548
16743
|
computeQmdHybridFetchLimit,
|
|
16549
|
-
mergeGraphExpandedResults,
|
|
16550
|
-
graphPathRelativeToStorage,
|
|
16551
|
-
blendGraphExpandedRecallScore,
|
|
16552
16744
|
summarizeGraphShadowComparison,
|
|
16553
16745
|
mergeArtifactRecallCandidates,
|
|
16554
16746
|
resolveRecentThreadMemoryPaths,
|
|
@@ -16557,4 +16749,4 @@ export {
|
|
|
16557
16749
|
resolvePersistedMemoryRelativePath,
|
|
16558
16750
|
Orchestrator
|
|
16559
16751
|
};
|
|
16560
|
-
//# sourceMappingURL=chunk-
|
|
16752
|
+
//# sourceMappingURL=chunk-SODQQCAZ.js.map
|