@remnic/core 9.30.1 → 9.32.0
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-admin-ops-surface.d.ts +10 -10
- package/dist/access-admin-ops-surface.js +55 -44
- package/dist/access-authorization-probe.d.ts +10 -10
- package/dist/access-authorization-probe.js +56 -45
- package/dist/access-boundary.d.ts +13 -11
- package/dist/access-boundary.js +55 -44
- package/dist/access-cli.js +170 -126
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +119 -0
- package/dist/access-extraction-force-flush.js +171 -0
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +47 -13
- package/dist/access-http-lcm-compaction.js +7 -3
- package/dist/access-http-lifecycle-flush.d.ts +132 -0
- package/dist/access-http-lifecycle-flush.js +9 -0
- package/dist/access-http-lifecycle-flush.js.map +1 -0
- package/dist/access-http.d.ts +11 -10
- package/dist/access-http.js +71 -59
- package/dist/access-identity-continuity-surface.d.ts +8 -8
- package/dist/access-identity-continuity-surface.js +55 -44
- package/dist/access-lcm-surface.d.ts +10 -10
- package/dist/access-lcm-surface.js +55 -44
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +16 -10
- package/dist/access-mcp.js +63 -52
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-VfXssvoI.d.ts → access-namespace-preflight-COhbXBqS.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +55 -44
- package/dist/access-observe-helpers.d.ts +22 -0
- package/dist/access-observe-helpers.js +10 -0
- package/dist/access-observe-helpers.js.map +1 -0
- package/dist/access-observe-write-surface.d.ts +51 -47
- package/dist/access-observe-write-surface.js +55 -44
- package/dist/access-operations-batch.js +58 -47
- package/dist/access-operations.d.ts +11 -11
- package/dist/access-operations.js +60 -49
- package/dist/access-recall-concurrency.d.ts +10 -10
- package/dist/access-recall-concurrency.js +55 -44
- package/dist/access-recall-response.d.ts +10 -10
- package/dist/access-recall-response.js +55 -44
- package/dist/access-recall-surface.d.ts +10 -10
- package/dist/access-recall-surface.js +55 -44
- package/dist/access-schema.d.ts +37 -7
- package/dist/access-schema.js +5 -3
- package/dist/{access-service-B5RwVsTV.d.ts → access-service-BmBTtEKO.d.ts} +44 -20
- package/dist/access-service-helpers.d.ts +113 -0
- package/dist/access-service-helpers.js +8 -0
- package/dist/access-service-helpers.js.map +1 -0
- package/dist/access-service.d.ts +10 -10
- package/dist/access-service.js +55 -44
- package/dist/access-surface-catalog.d.ts +10 -10
- package/dist/access-surface-catalog.js +2 -0
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-wearables-meetings-surface.d.ts +3 -3
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +2 -2
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/registry.js +3 -3
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +8 -8
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +14 -14
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +5 -0
- package/dist/buffer-turn-helpers.js +24 -0
- package/dist/buffer-turn-helpers.js.map +1 -0
- package/dist/buffer.d.ts +17 -4
- package/dist/buffer.js +21 -1
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/capsule-crypto-7FJQINUR.js.map +1 -0
- package/dist/{capsule-merge-5KKJQBWQ.js → capsule-merge-2H2IUTBT.js} +4 -4
- package/dist/{catalog-V7inUQdp.d.ts → catalog-Dm-DvNBY.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +21 -22
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
- package/dist/{chunk-I5NLEENJ.js → chunk-27HHNYSQ.js} +3 -3
- package/dist/{chunk-2SA56WMI.js → chunk-2LTDWSR6.js} +4 -4
- package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-SPJXKAVF.js → chunk-2NTGBZLZ.js} +14 -13
- package/dist/chunk-2NTGBZLZ.js.map +1 -0
- package/dist/{chunk-P5PXWTW7.js → chunk-2Q4JJ3FZ.js} +3 -3
- package/dist/{chunk-G5R3D5UP.js → chunk-2QIMTVEJ.js} +6 -5
- package/dist/chunk-2QIMTVEJ.js.map +1 -0
- package/dist/{chunk-H5CPS5JP.js → chunk-35IVNNRK.js} +3 -3
- package/dist/{chunk-LBOD4U5B.js → chunk-3EQ2XB3W.js} +6 -6
- package/dist/{chunk-YTSNAUXN.js → chunk-3F2LKUMU.js} +22 -8
- package/dist/chunk-3F2LKUMU.js.map +1 -0
- package/dist/chunk-3QL24R5Y.js +9 -0
- package/dist/chunk-3QL24R5Y.js.map +1 -0
- package/dist/chunk-4RNZMRAV.js +60 -0
- package/dist/chunk-4RNZMRAV.js.map +1 -0
- package/dist/chunk-5IVLTFOV.js +65 -0
- package/dist/chunk-5IVLTFOV.js.map +1 -0
- package/dist/{chunk-2EUVEDF5.js → chunk-5WZVQRHV.js} +2 -2
- package/dist/{chunk-ALSGMEJR.js → chunk-65ZPVYTA.js} +7 -7
- package/dist/{chunk-GIBMDSJ2.js → chunk-6P7MTSU5.js} +2 -2
- package/dist/{chunk-5VQJBH2G.js → chunk-6TAUHL33.js} +2 -2
- package/dist/{chunk-WVO4G37W.js → chunk-7TEZUUGM.js} +3 -3
- package/dist/{chunk-MJCGLM25.js → chunk-7VUAG236.js} +5 -5
- package/dist/{chunk-CZRYLSSW.js → chunk-AJL6NNX6.js} +2 -2
- package/dist/{chunk-LGHKJABJ.js → chunk-AQEJE3WO.js} +40 -18
- package/dist/chunk-AQEJE3WO.js.map +1 -0
- package/dist/{chunk-66772WBP.js → chunk-AQWVJURR.js} +5 -5
- package/dist/{chunk-RKNJBZ55.js → chunk-AU7Q3LSC.js} +7 -7
- package/dist/{chunk-IYZ5K7MU.js → chunk-BUE5E2HL.js} +4 -187
- package/dist/chunk-BUE5E2HL.js.map +1 -0
- package/dist/{chunk-NHWB6HG2.js → chunk-CE5355TT.js} +21 -5
- package/dist/chunk-CE5355TT.js.map +1 -0
- package/dist/{chunk-M3C2V3PV.js → chunk-CJDNT45S.js} +12 -12
- package/dist/{chunk-D2ANTDGO.js → chunk-E6BMSH7U.js} +2 -2
- package/dist/{chunk-CKMO4RDY.js → chunk-EMDLM3LW.js} +4 -4
- package/dist/chunk-ER7W6H4T.js +112 -0
- package/dist/chunk-ER7W6H4T.js.map +1 -0
- package/dist/{chunk-RGIWINDN.js → chunk-FHBITMRY.js} +30 -30
- package/dist/{chunk-6FUPCJUL.js → chunk-FMFLGS5Z.js} +54 -54
- package/dist/chunk-FMFLGS5Z.js.map +1 -0
- package/dist/{chunk-FDAMS4PK.js → chunk-G2YQ57YO.js} +4 -4
- package/dist/{chunk-6U7F52DE.js → chunk-HFQQWAMS.js} +62 -62
- package/dist/{chunk-5W4ZLBEZ.js → chunk-HKPJPOW7.js} +2 -2
- package/dist/{chunk-JCBWCYEJ.js → chunk-IGWFKW4B.js} +2 -2
- package/dist/{chunk-AITCS2RC.js → chunk-IJ7HK452.js} +4 -4
- package/dist/{chunk-4WKA6I65.js → chunk-J3ZGPYXB.js} +1135 -311
- package/dist/chunk-J3ZGPYXB.js.map +1 -0
- package/dist/{chunk-D3LMYTBV.js → chunk-J7WZUL2K.js} +9 -9
- package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
- package/dist/{chunk-YNQBRLC5.js → chunk-LUQ443JP.js} +520 -2011
- package/dist/chunk-LUQ443JP.js.map +1 -0
- package/dist/{chunk-Z54EM5YZ.js → chunk-MAXVH44E.js} +7 -7
- package/dist/{chunk-WZFAPHIK.js → chunk-MU7ZHSZE.js} +2 -2
- package/dist/chunk-N5Z4EVOR.js +123 -0
- package/dist/chunk-N5Z4EVOR.js.map +1 -0
- package/dist/{chunk-AZ5BTEKX.js → chunk-NQUF7XKR.js} +2 -2
- package/dist/{chunk-W4FBGYGK.js → chunk-NRV4Y3PM.js} +1 -1
- package/dist/{chunk-62U4J2GN.js → chunk-ODGOP7P2.js} +2 -2
- package/dist/{chunk-QJAQNXWI.js → chunk-ONHRRJZM.js} +6 -6
- package/dist/{chunk-ACXPX4AG.js → chunk-OPBTPRGY.js} +2 -2
- package/dist/{chunk-XOZ4ALGB.js → chunk-QDTZ2HF7.js} +3 -3
- package/dist/{chunk-GBJ4RDFR.js → chunk-QIHIHZYC.js} +66 -91
- package/dist/chunk-QIHIHZYC.js.map +1 -0
- package/dist/{chunk-ZPSVBSOF.js → chunk-QMWFQBIL.js} +3 -3
- package/dist/{chunk-W5EG6LE3.js → chunk-THCPRMRF.js} +3 -3
- package/dist/{chunk-4A6YGWQN.js → chunk-TL4TO3EA.js} +115 -120
- package/dist/chunk-TL4TO3EA.js.map +1 -0
- package/dist/{chunk-VI2JQPNQ.js → chunk-U7QYBSQJ.js} +2 -2
- package/dist/chunk-ULARSG5Z.js +203 -0
- package/dist/chunk-ULARSG5Z.js.map +1 -0
- package/dist/{chunk-TH2LSRMG.js → chunk-UORKJ34C.js} +2 -2
- package/dist/{chunk-4Z4XNEWZ.js → chunk-VCD4PSK2.js} +56 -12
- package/dist/chunk-VCD4PSK2.js.map +1 -0
- package/dist/{chunk-K5GB36ME.js → chunk-VMZ56EE3.js} +2 -2
- package/dist/{chunk-HUHX2OCX.js → chunk-VVDPPDDF.js} +1 -1
- package/dist/chunk-VVDPPDDF.js.map +1 -0
- package/dist/{chunk-RMMVQQA6.js → chunk-WDISJRMG.js} +2 -2
- package/dist/{chunk-B6JDYXL7.js → chunk-WWUVONGW.js} +7 -1
- package/dist/chunk-WWUVONGW.js.map +1 -0
- package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-CVILPI77.js → chunk-XOQSEF7X.js} +6 -6
- package/dist/{chunk-RPW2NOU6.js → chunk-YIAA2X3D.js} +41 -1
- package/dist/chunk-YIAA2X3D.js.map +1 -0
- package/dist/chunk-YPC7W6GA.js +1604 -0
- package/dist/chunk-YPC7W6GA.js.map +1 -0
- package/dist/{chunk-YTQNQ4KB.js → chunk-YX5LN6JR.js} +3 -3
- package/dist/{chunk-IC6CBHCA.js → chunk-Z7XKUWYS.js} +2 -2
- package/dist/{chunk-PHWUFPCO.js → chunk-ZCPP5OW6.js} +61 -53
- package/dist/chunk-ZCPP5OW6.js.map +1 -0
- package/dist/{cli-C4GbETPC.d.ts → cli-DRJLv1Xt.d.ts} +5 -5
- package/dist/cli.d.ts +12 -12
- package/dist/cli.js +96 -86
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +14 -14
- 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/config.js +2 -2
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +14 -15
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +3 -2
- package/dist/connectors/index.js +24 -23
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-provenance-check.js +5 -5
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/consolidation-undo.js +3 -3
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/contradiction/index.js +4 -4
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/backend.js +2 -2
- 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/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +26 -26
- package/dist/day-summary.d.ts +1 -1
- 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/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +14 -14
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +8 -8
- package/dist/extraction-error-classification.d.ts +1 -1
- 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-liveness.d.ts +1 -1
- package/dist/extraction-source-grounding-rules.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts +15 -2
- package/dist/extraction-source-grounding.js +10 -1
- package/dist/extraction.d.ts +2 -15
- package/dist/extraction.js +5 -4
- package/dist/fallback-llm.d.ts +1 -1
- 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/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +19 -19
- package/dist/index.js +253 -246
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +6 -6
- 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-helpers.d.ts +7 -0
- package/dist/local-llm-helpers.js +16 -0
- package/dist/local-llm-helpers.js.map +1 -0
- package/dist/local-llm.d.ts +3 -6
- package/dist/local-llm.js +2 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +14 -14
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -14
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +15 -15
- package/dist/{maintenance-CL30NWtc.d.ts → maintenance-C6Pffz30.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +10 -10
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-corpus-version.js +2 -2
- 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 +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +24 -24
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +14 -14
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/offline-sync-impression-drain.js +6 -5
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +29 -29
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-doctor-replica.js +3 -3
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +39 -38
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +22 -21
- package/dist/{orchestrator-CKTCRwWV.d.ts → orchestrator-eQlmasno.d.ts} +72 -34
- package/dist/orchestrator.d.ts +8 -8
- package/dist/orchestrator.js +169 -162
- package/dist/page-versioning.js +3 -3
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-B7wj4rRZ.d.ts → pipeline-CZGmAMQ2.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{qmd-q9tg4dHp.d.ts → qmd-DBj4MF8T.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/qmd.js +4 -4
- package/dist/recall-concurrency-config.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-explain-renderer.js +3 -3
- package/dist/recall-memory-map.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-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/replica-divergence.d.ts +1 -1
- package/dist/replica-divergence.js +2 -2
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +2 -2
- 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/salvage-envelope.d.ts +1 -1
- package/dist/{scope-profiles-CWDyglPM.d.ts → scope-profiles-S85lrsUn.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +8 -8
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +12 -12
- 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-BUE3deLn.d.ts → semantic-consolidation-DVzDcV6x.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +17 -18
- package/dist/semantic-rule-promotion.js +14 -14
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +14 -14
- package/dist/{service-CXgM0bQG.d.ts → service-C2M-wD4W.d.ts} +2 -2
- 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/signal.d.ts +1 -1
- package/dist/{storage-DysJq-XH.d.ts → storage-dyBC3Q84.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +13 -13
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -2
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.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 +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/tokens.js +2 -2
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +5 -5
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-aPPzhnjT.d.ts → types-D63ZI--P.d.ts} +23 -2
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +14 -14
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-boundary.ts +3 -0
- package/src/access-cli.test.ts +93 -0
- package/src/access-cli.ts +56 -2
- package/src/access-extraction-force-flush.ts +177 -0
- package/src/access-http-extraction-force-flush.test.ts +132 -0
- package/src/access-http-lcm-compaction.ts +99 -22
- package/src/access-http-lifecycle-flush.ts +81 -0
- package/src/access-http.test.ts +227 -0
- package/src/access-http.ts +33 -40
- package/src/access-mcp-output-schemas.ts +6 -0
- package/src/access-mcp.test.ts +40 -0
- package/src/access-mcp.ts +32 -1
- package/src/access-observe-helpers.ts +180 -0
- package/src/access-observe-write-surface.ts +78 -19
- package/src/access-operations-batch.ts +2 -1
- package/src/access-schema-pi.test.ts +17 -0
- package/src/access-schema.ts +28 -11
- package/src/access-service-helpers.ts +46 -0
- package/src/access-service-observe-lcm-parity.test.ts +781 -31
- package/src/access-service-observe-scope.test.ts +88 -0
- package/src/access-service.ts +46 -128
- package/src/access-surface-catalog.test.ts +32 -0
- package/src/access-surface-catalog.ts +2 -0
- package/src/buffer-session.test.ts +148 -0
- package/src/buffer-turn-helpers.ts +152 -0
- package/src/buffer.ts +126 -201
- package/src/connectors/index.ts +1 -1
- package/src/connectors/label.ts +18 -0
- package/src/correction/correction-access-wiring.ts +79 -27
- package/src/correction/correction-executor.test.ts +542 -1
- package/src/correction/correction-executor.ts +309 -89
- package/src/correction/correction-planner.test.ts +35 -1
- package/src/correction/correction-planner.ts +50 -3
- package/src/correction/correction-service.ts +12 -7
- package/src/correction/correction-storage-integration.test.ts +172 -1
- package/src/correction/passive-capture.test.ts +35 -0
- package/src/correction/passive-capture.ts +17 -3
- package/src/extraction-source-grounding.ts +55 -1
- package/src/extraction-timeout.test.ts +51 -0
- package/src/extraction.ts +64 -90
- package/src/local-llm-headers-timeout.test.ts +48 -0
- package/src/local-llm-helpers.ts +58 -0
- package/src/local-llm.ts +62 -58
- package/src/orchestration/extraction-run-helpers.ts +309 -0
- package/src/orchestration/extraction-run.test.ts +350 -7
- package/src/orchestration/extraction-run.ts +327 -250
- package/src/orchestration/recall-result-formatter.ts +21 -2
- package/src/orchestration/recall-search-pipeline.test.ts +34 -0
- package/src/orchestration/recall-search-pipeline.ts +9 -1
- package/src/orchestration/session-context.ts +193 -18
- package/src/orchestration/turn-ingestion.ts +61 -11
- package/src/orchestrator-flush.test.ts +511 -5
- package/src/orchestrator.ts +8 -6
- package/src/recall-source-connector-label.test.ts +300 -0
- package/src/types.ts +3 -3
- package/dist/chunk-3UXOZBHV.js +0 -20
- package/dist/chunk-3UXOZBHV.js.map +0 -1
- package/dist/chunk-4A6YGWQN.js.map +0 -1
- package/dist/chunk-4WKA6I65.js.map +0 -1
- package/dist/chunk-4Z4XNEWZ.js.map +0 -1
- package/dist/chunk-6FUPCJUL.js.map +0 -1
- package/dist/chunk-B6JDYXL7.js.map +0 -1
- package/dist/chunk-G5R3D5UP.js.map +0 -1
- package/dist/chunk-GBJ4RDFR.js.map +0 -1
- package/dist/chunk-HUHX2OCX.js.map +0 -1
- package/dist/chunk-IYZ5K7MU.js.map +0 -1
- package/dist/chunk-LGHKJABJ.js.map +0 -1
- package/dist/chunk-NHWB6HG2.js.map +0 -1
- package/dist/chunk-PHWUFPCO.js.map +0 -1
- package/dist/chunk-RPW2NOU6.js.map +0 -1
- package/dist/chunk-SPJXKAVF.js.map +0 -1
- package/dist/chunk-YNQBRLC5.js.map +0 -1
- package/dist/chunk-YTSNAUXN.js.map +0 -1
- /package/dist/{capsule-crypto-GWVG7LGC.js.map → access-extraction-force-flush.js.map} +0 -0
- /package/dist/{capsule-merge-5KKJQBWQ.js.map → capsule-merge-2H2IUTBT.js.map} +0 -0
- /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
- /package/dist/{chunk-I5NLEENJ.js.map → chunk-27HHNYSQ.js.map} +0 -0
- /package/dist/{chunk-2SA56WMI.js.map → chunk-2LTDWSR6.js.map} +0 -0
- /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-P5PXWTW7.js.map → chunk-2Q4JJ3FZ.js.map} +0 -0
- /package/dist/{chunk-H5CPS5JP.js.map → chunk-35IVNNRK.js.map} +0 -0
- /package/dist/{chunk-LBOD4U5B.js.map → chunk-3EQ2XB3W.js.map} +0 -0
- /package/dist/{chunk-2EUVEDF5.js.map → chunk-5WZVQRHV.js.map} +0 -0
- /package/dist/{chunk-ALSGMEJR.js.map → chunk-65ZPVYTA.js.map} +0 -0
- /package/dist/{chunk-GIBMDSJ2.js.map → chunk-6P7MTSU5.js.map} +0 -0
- /package/dist/{chunk-5VQJBH2G.js.map → chunk-6TAUHL33.js.map} +0 -0
- /package/dist/{chunk-WVO4G37W.js.map → chunk-7TEZUUGM.js.map} +0 -0
- /package/dist/{chunk-MJCGLM25.js.map → chunk-7VUAG236.js.map} +0 -0
- /package/dist/{chunk-CZRYLSSW.js.map → chunk-AJL6NNX6.js.map} +0 -0
- /package/dist/{chunk-66772WBP.js.map → chunk-AQWVJURR.js.map} +0 -0
- /package/dist/{chunk-RKNJBZ55.js.map → chunk-AU7Q3LSC.js.map} +0 -0
- /package/dist/{chunk-M3C2V3PV.js.map → chunk-CJDNT45S.js.map} +0 -0
- /package/dist/{chunk-D2ANTDGO.js.map → chunk-E6BMSH7U.js.map} +0 -0
- /package/dist/{chunk-CKMO4RDY.js.map → chunk-EMDLM3LW.js.map} +0 -0
- /package/dist/{chunk-RGIWINDN.js.map → chunk-FHBITMRY.js.map} +0 -0
- /package/dist/{chunk-FDAMS4PK.js.map → chunk-G2YQ57YO.js.map} +0 -0
- /package/dist/{chunk-6U7F52DE.js.map → chunk-HFQQWAMS.js.map} +0 -0
- /package/dist/{chunk-5W4ZLBEZ.js.map → chunk-HKPJPOW7.js.map} +0 -0
- /package/dist/{chunk-JCBWCYEJ.js.map → chunk-IGWFKW4B.js.map} +0 -0
- /package/dist/{chunk-AITCS2RC.js.map → chunk-IJ7HK452.js.map} +0 -0
- /package/dist/{chunk-D3LMYTBV.js.map → chunk-J7WZUL2K.js.map} +0 -0
- /package/dist/{chunk-5W7CTZ2E.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-Z54EM5YZ.js.map → chunk-MAXVH44E.js.map} +0 -0
- /package/dist/{chunk-WZFAPHIK.js.map → chunk-MU7ZHSZE.js.map} +0 -0
- /package/dist/{chunk-AZ5BTEKX.js.map → chunk-NQUF7XKR.js.map} +0 -0
- /package/dist/{chunk-W4FBGYGK.js.map → chunk-NRV4Y3PM.js.map} +0 -0
- /package/dist/{chunk-62U4J2GN.js.map → chunk-ODGOP7P2.js.map} +0 -0
- /package/dist/{chunk-QJAQNXWI.js.map → chunk-ONHRRJZM.js.map} +0 -0
- /package/dist/{chunk-ACXPX4AG.js.map → chunk-OPBTPRGY.js.map} +0 -0
- /package/dist/{chunk-XOZ4ALGB.js.map → chunk-QDTZ2HF7.js.map} +0 -0
- /package/dist/{chunk-ZPSVBSOF.js.map → chunk-QMWFQBIL.js.map} +0 -0
- /package/dist/{chunk-W5EG6LE3.js.map → chunk-THCPRMRF.js.map} +0 -0
- /package/dist/{chunk-VI2JQPNQ.js.map → chunk-U7QYBSQJ.js.map} +0 -0
- /package/dist/{chunk-TH2LSRMG.js.map → chunk-UORKJ34C.js.map} +0 -0
- /package/dist/{chunk-K5GB36ME.js.map → chunk-VMZ56EE3.js.map} +0 -0
- /package/dist/{chunk-RMMVQQA6.js.map → chunk-WDISJRMG.js.map} +0 -0
- /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-CVILPI77.js.map → chunk-XOQSEF7X.js.map} +0 -0
- /package/dist/{chunk-YTQNQ4KB.js.map → chunk-YX5LN6JR.js.map} +0 -0
- /package/dist/{chunk-IC6CBHCA.js.map → chunk-Z7XKUWYS.js.map} +0 -0
|
@@ -7,22 +7,22 @@ import {
|
|
|
7
7
|
syncWearableSource,
|
|
8
8
|
wearableSourceLabel
|
|
9
9
|
} from "./chunk-UV72DEZD.js";
|
|
10
|
-
import {
|
|
11
|
-
runPeerProfileReasoner
|
|
12
|
-
} from "./chunk-I74SUMNI.js";
|
|
13
10
|
import {
|
|
14
11
|
CompressionGuidelineCoordinator
|
|
15
12
|
} from "./chunk-6LKEUCEM.js";
|
|
16
13
|
import {
|
|
17
14
|
ActivityStore,
|
|
18
15
|
MaintenanceScheduler
|
|
19
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3EQ2XB3W.js";
|
|
17
|
+
import {
|
|
18
|
+
runPeerProfileReasoner
|
|
19
|
+
} from "./chunk-I74SUMNI.js";
|
|
20
20
|
import {
|
|
21
21
|
migrateFromEngram
|
|
22
22
|
} from "./chunk-7HYPN2GC.js";
|
|
23
23
|
import {
|
|
24
24
|
LcmEngine
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-MAXVH44E.js";
|
|
26
26
|
import {
|
|
27
27
|
chunkTranscriptEntries
|
|
28
28
|
} from "./chunk-TECVW3JP.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
import {
|
|
33
33
|
CompoundingEngine,
|
|
34
34
|
defaultTierMigrationCycleBudget
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-U7QYBSQJ.js";
|
|
36
36
|
import {
|
|
37
37
|
SharedContextManager
|
|
38
38
|
} from "./chunk-AS7YMSL6.js";
|
|
@@ -41,9 +41,6 @@ import {
|
|
|
41
41
|
applyUtilityRankingRuntimeDelta,
|
|
42
42
|
loadUtilityRuntimeValues
|
|
43
43
|
} from "./chunk-LXOM6IQU.js";
|
|
44
|
-
import {
|
|
45
|
-
CODEX_THREAD_KEY_PREFIX
|
|
46
|
-
} from "./chunk-4EX5WZ4M.js";
|
|
47
44
|
import {
|
|
48
45
|
TierMigrationExecutor
|
|
49
46
|
} from "./chunk-VOUOLGIP.js";
|
|
@@ -56,16 +53,19 @@ import {
|
|
|
56
53
|
import {
|
|
57
54
|
extractTopics
|
|
58
55
|
} from "./chunk-UHGBNIOS.js";
|
|
59
|
-
import {
|
|
60
|
-
buildTargetedFactRecallSection,
|
|
61
|
-
shouldRecallTargetedFactEvidence
|
|
62
|
-
} from "./chunk-T67LUYCR.js";
|
|
63
56
|
import {
|
|
64
57
|
buildTemporalTimelineRecallSection
|
|
65
58
|
} from "./chunk-I6WYQSX4.js";
|
|
59
|
+
import {
|
|
60
|
+
CODEX_THREAD_KEY_PREFIX
|
|
61
|
+
} from "./chunk-4EX5WZ4M.js";
|
|
66
62
|
import {
|
|
67
63
|
HourlySummarizer
|
|
68
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-NQUF7XKR.js";
|
|
65
|
+
import {
|
|
66
|
+
buildTargetedFactRecallSection,
|
|
67
|
+
shouldRecallTargetedFactEvidence
|
|
68
|
+
} from "./chunk-T67LUYCR.js";
|
|
69
69
|
import {
|
|
70
70
|
SessionObserverState
|
|
71
71
|
} from "./chunk-QFN4U7AG.js";
|
|
@@ -108,9 +108,6 @@ import {
|
|
|
108
108
|
reorderByRankedKeys,
|
|
109
109
|
rerankLocalOrNoop
|
|
110
110
|
} from "./chunk-LUDXM7MD.js";
|
|
111
|
-
import {
|
|
112
|
-
createRecallSectionMetricRecorder
|
|
113
|
-
} from "./chunk-C3AKM55W.js";
|
|
114
111
|
import {
|
|
115
112
|
LastRecallStore,
|
|
116
113
|
RecallHandleHistoryStore,
|
|
@@ -128,6 +125,9 @@ import {
|
|
|
128
125
|
import {
|
|
129
126
|
reorderRecallResultsWithMmr
|
|
130
127
|
} from "./chunk-YDBIWGNI.js";
|
|
128
|
+
import {
|
|
129
|
+
createRecallSectionMetricRecorder
|
|
130
|
+
} from "./chunk-C3AKM55W.js";
|
|
131
131
|
import {
|
|
132
132
|
applyReasoningTraceBoost
|
|
133
133
|
} from "./chunk-ZZTOURJI.js";
|
|
@@ -147,35 +147,13 @@ import {
|
|
|
147
147
|
import {
|
|
148
148
|
runLiveConnectorsOnce
|
|
149
149
|
} from "./chunk-HTIIXNJQ.js";
|
|
150
|
-
import {
|
|
151
|
-
hasBroadGraphIntent,
|
|
152
|
-
inferIntentFromText,
|
|
153
|
-
intentCompatibilityScore,
|
|
154
|
-
isTaskInitiationIntent,
|
|
155
|
-
planRecallMode
|
|
156
|
-
} from "./chunk-PD6O7AXF.js";
|
|
157
150
|
import {
|
|
158
151
|
classifyMemoryKind
|
|
159
152
|
} from "./chunk-YAZNBMNF.js";
|
|
160
|
-
import {
|
|
161
|
-
ExtractionEngine
|
|
162
|
-
} from "./chunk-GBJ4RDFR.js";
|
|
163
|
-
import {
|
|
164
|
-
parseMemoryActionEligibilityContext
|
|
165
|
-
} from "./chunk-TGTTESJS.js";
|
|
166
|
-
import {
|
|
167
|
-
ModelRegistry
|
|
168
|
-
} from "./chunk-WLZYGLJ4.js";
|
|
169
|
-
import {
|
|
170
|
-
LocalLlmClient
|
|
171
|
-
} from "./chunk-PHWUFPCO.js";
|
|
172
153
|
import {
|
|
173
154
|
buildFocusedListRecallSection,
|
|
174
155
|
shouldRecallFocusedListEvidence
|
|
175
156
|
} from "./chunk-OH7QLI6W.js";
|
|
176
|
-
import {
|
|
177
|
-
recordJudgeTrainingPair
|
|
178
|
-
} from "./chunk-PWFCHOB3.js";
|
|
179
157
|
import {
|
|
180
158
|
createDeferCountMap,
|
|
181
159
|
createVerdictCache,
|
|
@@ -188,9 +166,17 @@ import {
|
|
|
188
166
|
loadRedactionRules
|
|
189
167
|
} from "./chunk-LTHVM4XN.js";
|
|
190
168
|
import {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
169
|
+
ExtractionEngine
|
|
170
|
+
} from "./chunk-QIHIHZYC.js";
|
|
171
|
+
import {
|
|
172
|
+
parseMemoryActionEligibilityContext
|
|
173
|
+
} from "./chunk-TGTTESJS.js";
|
|
174
|
+
import {
|
|
175
|
+
ModelRegistry
|
|
176
|
+
} from "./chunk-WLZYGLJ4.js";
|
|
177
|
+
import {
|
|
178
|
+
LocalLlmClient
|
|
179
|
+
} from "./chunk-ZCPP5OW6.js";
|
|
194
180
|
import {
|
|
195
181
|
pickFactEventTimeAnchor,
|
|
196
182
|
resolveFactEventTime
|
|
@@ -199,8 +185,8 @@ import {
|
|
|
199
185
|
buildExplicitCueRecallSection
|
|
200
186
|
} from "./chunk-TVIVY7KU.js";
|
|
201
187
|
import {
|
|
202
|
-
|
|
203
|
-
} from "./chunk-
|
|
188
|
+
recordJudgeTrainingPair
|
|
189
|
+
} from "./chunk-PWFCHOB3.js";
|
|
204
190
|
import {
|
|
205
191
|
EmbeddingFallback
|
|
206
192
|
} from "./chunk-E6EE5B67.js";
|
|
@@ -208,33 +194,40 @@ import {
|
|
|
208
194
|
buildEntityRecallSection,
|
|
209
195
|
entityRecentTranscriptLookbackHours,
|
|
210
196
|
readRecentEntityTranscriptEntries
|
|
211
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-AQWVJURR.js";
|
|
198
|
+
import {
|
|
199
|
+
buildEventOrderRecallSection,
|
|
200
|
+
shouldRecallEventOrderEvidence
|
|
201
|
+
} from "./chunk-DEOYTFA6.js";
|
|
212
202
|
import {
|
|
213
203
|
formatDaySummaryMemories
|
|
214
204
|
} from "./chunk-RPSYDM6C.js";
|
|
205
|
+
import {
|
|
206
|
+
tryDirectAnswer
|
|
207
|
+
} from "./chunk-Q6IP2ARR.js";
|
|
215
208
|
import {
|
|
216
209
|
builtInConnectorPackageSpecifier,
|
|
217
210
|
ensureBuiltInWearableConnectors,
|
|
218
211
|
getWearableConnector,
|
|
219
212
|
listWearableConnectors
|
|
220
|
-
} from "./chunk-
|
|
221
|
-
import {
|
|
222
|
-
normalizeReplaySessionKey
|
|
223
|
-
} from "./chunk-AJVLDJU6.js";
|
|
213
|
+
} from "./chunk-HFQQWAMS.js";
|
|
224
214
|
import {
|
|
225
215
|
RoutingRulesStore
|
|
226
216
|
} from "./chunk-XL24QQ63.js";
|
|
217
|
+
import {
|
|
218
|
+
normalizeReplaySessionKey
|
|
219
|
+
} from "./chunk-AJVLDJU6.js";
|
|
227
220
|
import {
|
|
228
221
|
compareVerifiedEpisodeResults,
|
|
229
222
|
searchVerifiedEpisodes
|
|
230
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-5WZVQRHV.js";
|
|
231
224
|
import {
|
|
232
225
|
ThreadingManager
|
|
233
226
|
} from "./chunk-OJP3N7UK.js";
|
|
234
227
|
import {
|
|
235
228
|
compareVerifiedSemanticRuleResults,
|
|
236
229
|
searchVerifiedSemanticRules
|
|
237
|
-
} from "./chunk-
|
|
230
|
+
} from "./chunk-UORKJ34C.js";
|
|
238
231
|
import {
|
|
239
232
|
searchWorkProductLedgerEntries
|
|
240
233
|
} from "./chunk-ZRWB5D4H.js";
|
|
@@ -247,11 +240,11 @@ import {
|
|
|
247
240
|
import {
|
|
248
241
|
runNamespaceMaintenanceFanout,
|
|
249
242
|
summarizeNamespaceMaintenanceHealth
|
|
250
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-CJDNT45S.js";
|
|
251
244
|
import {
|
|
252
245
|
NamespaceCatalog,
|
|
253
246
|
planNamespaceMaintenance
|
|
254
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-35IVNNRK.js";
|
|
255
248
|
import {
|
|
256
249
|
isAboveImportanceThreshold,
|
|
257
250
|
scoreImportance
|
|
@@ -263,20 +256,20 @@ import {
|
|
|
263
256
|
EXTRACTION_JUDGE_VERDICT_CATEGORY,
|
|
264
257
|
recordJudgeVerdict
|
|
265
258
|
} from "./chunk-OZKOPQCM.js";
|
|
266
|
-
import {
|
|
267
|
-
recordEvalShadowRecall
|
|
268
|
-
} from "./chunk-3PY7VHV7.js";
|
|
269
259
|
import {
|
|
270
260
|
collectNativeKnowledgeChunks,
|
|
271
261
|
formatNativeKnowledgeSection,
|
|
272
262
|
searchNativeKnowledge
|
|
273
263
|
} from "./chunk-2DQ2XREU.js";
|
|
264
|
+
import {
|
|
265
|
+
recordEvalShadowRecall
|
|
266
|
+
} from "./chunk-3PY7VHV7.js";
|
|
274
267
|
import {
|
|
275
268
|
applyCommitmentLedgerLifecycle
|
|
276
269
|
} from "./chunk-LMDRGRJ2.js";
|
|
277
270
|
import {
|
|
278
|
-
|
|
279
|
-
} from "./chunk-
|
|
271
|
+
SmartBuffer
|
|
272
|
+
} from "./chunk-TL4TO3EA.js";
|
|
280
273
|
import {
|
|
281
274
|
buildConsolidationPrompt,
|
|
282
275
|
buildExtensionsBlockForConsolidation,
|
|
@@ -286,16 +279,26 @@ import {
|
|
|
286
279
|
materializeAfterSemanticConsolidation,
|
|
287
280
|
parseConsolidationResponse,
|
|
288
281
|
parseOperatorAwareConsolidationResponse
|
|
289
|
-
} from "./chunk-
|
|
282
|
+
} from "./chunk-G2YQ57YO.js";
|
|
283
|
+
import {
|
|
284
|
+
buildBehaviorSignalsForMemory,
|
|
285
|
+
dedupeBehaviorSignalsByMemoryAndHash
|
|
286
|
+
} from "./chunk-KD3QD3A5.js";
|
|
287
|
+
import {
|
|
288
|
+
BootstrapEngine
|
|
289
|
+
} from "./chunk-MYVPLJOO.js";
|
|
290
|
+
import {
|
|
291
|
+
isDisagreementPrompt
|
|
292
|
+
} from "./chunk-H3FZVNRN.js";
|
|
293
|
+
import {
|
|
294
|
+
BoxBuilder
|
|
295
|
+
} from "./chunk-B7RWBZXW.js";
|
|
290
296
|
import {
|
|
291
297
|
semanticChunkContent
|
|
292
298
|
} from "./chunk-P4BC54KI.js";
|
|
293
299
|
import {
|
|
294
300
|
chunkContent
|
|
295
301
|
} from "./chunk-UQ7RN5HK.js";
|
|
296
|
-
import {
|
|
297
|
-
SmartBuffer
|
|
298
|
-
} from "./chunk-4A6YGWQN.js";
|
|
299
302
|
import {
|
|
300
303
|
detectMeetings
|
|
301
304
|
} from "./chunk-IB26HVAJ.js";
|
|
@@ -313,22 +316,9 @@ import {
|
|
|
313
316
|
import {
|
|
314
317
|
buildRecallQueryPolicy
|
|
315
318
|
} from "./chunk-LBJBNWS2.js";
|
|
316
|
-
import {
|
|
317
|
-
buildBehaviorSignalsForMemory,
|
|
318
|
-
dedupeBehaviorSignalsByMemoryAndHash
|
|
319
|
-
} from "./chunk-KD3QD3A5.js";
|
|
320
|
-
import {
|
|
321
|
-
BootstrapEngine
|
|
322
|
-
} from "./chunk-MYVPLJOO.js";
|
|
323
|
-
import {
|
|
324
|
-
isDisagreementPrompt
|
|
325
|
-
} from "./chunk-H3FZVNRN.js";
|
|
326
|
-
import {
|
|
327
|
-
BoxBuilder
|
|
328
|
-
} from "./chunk-B7RWBZXW.js";
|
|
329
319
|
import {
|
|
330
320
|
MeetingsInputError
|
|
331
|
-
} from "./chunk-
|
|
321
|
+
} from "./chunk-FMFLGS5Z.js";
|
|
332
322
|
import {
|
|
333
323
|
WearablesInputError,
|
|
334
324
|
describeErrorForOperator
|
|
@@ -342,17 +332,21 @@ import {
|
|
|
342
332
|
} from "./chunk-CEN6DW6X.js";
|
|
343
333
|
import {
|
|
344
334
|
RecallResultFormatter,
|
|
335
|
+
SessionContextCoordinator,
|
|
345
336
|
capturePassiveCorrections,
|
|
346
337
|
clusterByKey,
|
|
347
|
-
createCorrectionService,
|
|
348
338
|
detectPassiveCorrections
|
|
349
|
-
} from "./chunk-
|
|
339
|
+
} from "./chunk-J3ZGPYXB.js";
|
|
350
340
|
import {
|
|
351
341
|
importCapsule
|
|
352
|
-
} from "./chunk-
|
|
342
|
+
} from "./chunk-65ZPVYTA.js";
|
|
353
343
|
import {
|
|
354
344
|
isCodingGraphInstalled
|
|
355
345
|
} from "./chunk-VQ7B2Q6M.js";
|
|
346
|
+
import {
|
|
347
|
+
listTrustZoneRecords,
|
|
348
|
+
searchTrustZoneRecords
|
|
349
|
+
} from "./chunk-JGSKJHF7.js";
|
|
356
350
|
import {
|
|
357
351
|
applyTrustScoreStage,
|
|
358
352
|
buildTrustSignalsForRerank,
|
|
@@ -361,9 +355,8 @@ import {
|
|
|
361
355
|
trustResultKey
|
|
362
356
|
} from "./chunk-GNVZQ5JN.js";
|
|
363
357
|
import {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
} from "./chunk-JGSKJHF7.js";
|
|
358
|
+
buildXraySnapshot
|
|
359
|
+
} from "./chunk-OPBTPRGY.js";
|
|
367
360
|
import {
|
|
368
361
|
boundRecallContextComposition,
|
|
369
362
|
composeRecallContext,
|
|
@@ -371,21 +364,15 @@ import {
|
|
|
371
364
|
formatCuriosityFooter,
|
|
372
365
|
selectCuriosityQuestion
|
|
373
366
|
} from "./chunk-AHVEHR6K.js";
|
|
374
|
-
import {
|
|
375
|
-
buildXraySnapshot
|
|
376
|
-
} from "./chunk-ACXPX4AG.js";
|
|
377
367
|
import {
|
|
378
368
|
objectiveStateStoreOverrideForNamespace,
|
|
379
369
|
searchObjectiveStateSnapshots
|
|
380
370
|
} from "./chunk-6HMYUWXR.js";
|
|
381
371
|
import {
|
|
382
|
-
combineNamespaces,
|
|
383
372
|
getConfiguredNamespaces,
|
|
384
|
-
resolveCodingNamespaceOverlay,
|
|
385
373
|
resolveNamespaceFromStorageDir,
|
|
386
|
-
resolveScopePlan
|
|
387
|
-
|
|
388
|
-
} from "./chunk-IYZ5K7MU.js";
|
|
374
|
+
resolveScopePlan
|
|
375
|
+
} from "./chunk-ULARSG5Z.js";
|
|
389
376
|
import {
|
|
390
377
|
ProfilingCollector
|
|
391
378
|
} from "./chunk-NLE6TSLG.js";
|
|
@@ -398,29 +385,80 @@ import {
|
|
|
398
385
|
import {
|
|
399
386
|
NamespaceSearchRouter,
|
|
400
387
|
namespaceCollectionName
|
|
401
|
-
} from "./chunk-
|
|
388
|
+
} from "./chunk-E6BMSH7U.js";
|
|
402
389
|
import {
|
|
403
390
|
createConversationIndexRuntime,
|
|
404
391
|
createSearchBackend
|
|
405
|
-
} from "./chunk-
|
|
392
|
+
} from "./chunk-J7WZUL2K.js";
|
|
406
393
|
import {
|
|
407
394
|
NoopSearchBackend
|
|
408
395
|
} from "./chunk-CYEPCZN5.js";
|
|
409
396
|
import {
|
|
410
397
|
NamespaceStorageRouter
|
|
411
|
-
} from "./chunk-
|
|
398
|
+
} from "./chunk-Z7XKUWYS.js";
|
|
412
399
|
import {
|
|
413
400
|
writeConversationChunks
|
|
414
401
|
} from "./chunk-72A4L5JJ.js";
|
|
415
|
-
import {
|
|
416
|
-
parseQmdExplain
|
|
417
|
-
} from "./chunk-QJAQNXWI.js";
|
|
418
402
|
import {
|
|
419
403
|
GraphIndex
|
|
420
404
|
} from "./chunk-L2DPF4DF.js";
|
|
405
|
+
import {
|
|
406
|
+
BulkImportBatchPartialFailureError,
|
|
407
|
+
COMPACTION_SIGNAL_MAX_AGE_MS,
|
|
408
|
+
ExtractionDeadlineError,
|
|
409
|
+
ExtractionRunCoordinator,
|
|
410
|
+
abortRecallError,
|
|
411
|
+
appendMemoryToGraphContext,
|
|
412
|
+
applyQueryAwareCandidateFilter,
|
|
413
|
+
buildMemoryPathById,
|
|
414
|
+
buildQmdIntentHint,
|
|
415
|
+
computeArtifactCandidateFetchLimit,
|
|
416
|
+
computeArtifactRecallLimit,
|
|
417
|
+
computeQmdHybridFetchLimit,
|
|
418
|
+
defaultWorkspaceDir,
|
|
419
|
+
filterHourlySummaryMarkdownForLocalDay,
|
|
420
|
+
formatDateInTimeZone,
|
|
421
|
+
isActivityDigestPath,
|
|
422
|
+
isArtifactMemoryPath,
|
|
423
|
+
isMeetingRecordPath,
|
|
424
|
+
lifecycleRecallScoreAdjustment,
|
|
425
|
+
mapRecallSourceToXrayServedBy,
|
|
426
|
+
mergeArtifactRecallCandidates,
|
|
427
|
+
normalizeIanaTimeZone,
|
|
428
|
+
parseFiniteDate,
|
|
429
|
+
parseGraphRecallRankedResults,
|
|
430
|
+
parseMemoryIntentSnapshot,
|
|
431
|
+
parseQmdRecallResults,
|
|
432
|
+
qmdStartupCollectionCheckWithTimeout,
|
|
433
|
+
raceRecallAbort,
|
|
434
|
+
resolvePersistedMemoryRelativePath,
|
|
435
|
+
resolveRecallModeDecision,
|
|
436
|
+
resolveRecallModeDecisionAsync,
|
|
437
|
+
resolveRecentThreadMemoryPaths,
|
|
438
|
+
sanitizeSessionKeyForFilename,
|
|
439
|
+
shouldFilterLifecycleRecallCandidate,
|
|
440
|
+
splitTurnsBySourceValidAt,
|
|
441
|
+
summarizeGraphShadowComparison,
|
|
442
|
+
targetSourceValidAtSortMs,
|
|
443
|
+
throwIfRecallAborted,
|
|
444
|
+
tokenizeRecallQuery,
|
|
445
|
+
utcDateKeysForLocalDay
|
|
446
|
+
} from "./chunk-YPC7W6GA.js";
|
|
447
|
+
import {
|
|
448
|
+
resolveCodingNamespaceOverlay
|
|
449
|
+
} from "./chunk-BUE5E2HL.js";
|
|
450
|
+
import {
|
|
451
|
+
inferIntentFromText,
|
|
452
|
+
intentCompatibilityScore,
|
|
453
|
+
isTaskInitiationIntent,
|
|
454
|
+
planRecallMode
|
|
455
|
+
} from "./chunk-PD6O7AXF.js";
|
|
456
|
+
import {
|
|
457
|
+
searchCausalTrajectories
|
|
458
|
+
} from "./chunk-NRV4Y3PM.js";
|
|
421
459
|
import {
|
|
422
460
|
buildChainFollowupGenerator
|
|
423
|
-
} from "./chunk-
|
|
461
|
+
} from "./chunk-AJL6NNX6.js";
|
|
424
462
|
import {
|
|
425
463
|
QmdResultResolver,
|
|
426
464
|
StorageManager,
|
|
@@ -439,7 +477,7 @@ import {
|
|
|
439
477
|
reconstructFusionInputs,
|
|
440
478
|
selfDeps,
|
|
441
479
|
serializeFusionDay
|
|
442
|
-
} from "./chunk-
|
|
480
|
+
} from "./chunk-FHBITMRY.js";
|
|
443
481
|
import {
|
|
444
482
|
bodyIsEscaped,
|
|
445
483
|
decodeTranscriptBody,
|
|
@@ -470,28 +508,23 @@ import {
|
|
|
470
508
|
} from "./chunk-J6A3CX5N.js";
|
|
471
509
|
import {
|
|
472
510
|
confidenceTier
|
|
473
|
-
} from "./chunk-
|
|
511
|
+
} from "./chunk-VVDPPDDF.js";
|
|
474
512
|
import {
|
|
475
513
|
namespaceIdentityFromToken,
|
|
476
514
|
namespaceIdentityToken,
|
|
477
515
|
normalizeNamespaceIdentity
|
|
478
516
|
} from "./chunk-EGGE52UU.js";
|
|
479
|
-
import {
|
|
480
|
-
assertPathInsideRoot
|
|
481
|
-
} from "./chunk-GCASGYIO.js";
|
|
482
517
|
import {
|
|
483
518
|
inferMemoryStatus,
|
|
484
519
|
isActiveMemoryStatus
|
|
485
520
|
} from "./chunk-ILGC6JH6.js";
|
|
521
|
+
import {
|
|
522
|
+
assertPathInsideRoot
|
|
523
|
+
} from "./chunk-GCASGYIO.js";
|
|
486
524
|
import {
|
|
487
525
|
lintWorkspaceFiles,
|
|
488
526
|
rotateMarkdownFileToArchive
|
|
489
527
|
} from "./chunk-DM2T26WE.js";
|
|
490
|
-
import {
|
|
491
|
-
applyFaithfulnessVerdict,
|
|
492
|
-
createFaithfulnessCounters,
|
|
493
|
-
runFaithfulnessGateBatch
|
|
494
|
-
} from "./chunk-JYIJNNN3.js";
|
|
495
528
|
import {
|
|
496
529
|
ContentHashIndex
|
|
497
530
|
} from "./chunk-FBUE6PD3.js";
|
|
@@ -507,9 +540,14 @@ import {
|
|
|
507
540
|
import {
|
|
508
541
|
normalizeTags
|
|
509
542
|
} from "./chunk-BT7NVCML.js";
|
|
543
|
+
import {
|
|
544
|
+
applyFaithfulnessVerdict,
|
|
545
|
+
createFaithfulnessCounters,
|
|
546
|
+
runFaithfulnessGateBatch
|
|
547
|
+
} from "./chunk-JYIJNNN3.js";
|
|
510
548
|
import {
|
|
511
549
|
bumpMemoryCorpusVersionForDir
|
|
512
|
-
} from "./chunk-
|
|
550
|
+
} from "./chunk-IJ7HK452.js";
|
|
513
551
|
import {
|
|
514
552
|
buildQmdRecallCacheKey,
|
|
515
553
|
getCachedQmdRecall,
|
|
@@ -520,9 +558,6 @@ import {
|
|
|
520
558
|
fallbackLlmRuntimeContextFromConfig,
|
|
521
559
|
gatewayTaskChainOptions
|
|
522
560
|
} from "./chunk-C23BYTJV.js";
|
|
523
|
-
import {
|
|
524
|
-
searchCausalTrajectories
|
|
525
|
-
} from "./chunk-W4FBGYGK.js";
|
|
526
561
|
import {
|
|
527
562
|
sanitizeMemoryContent
|
|
528
563
|
} from "./chunk-5GKPFL3S.js";
|
|
@@ -557,14 +592,9 @@ import {
|
|
|
557
592
|
assertIsDirectoryNotSymlink,
|
|
558
593
|
assertRealpathInsideRoot
|
|
559
594
|
} from "./chunk-GCGJW34D.js";
|
|
560
|
-
import {
|
|
561
|
-
parseFlexibleIsoTimestamp
|
|
562
|
-
} from "./chunk-P7FMDTKL.js";
|
|
563
595
|
import {
|
|
564
596
|
canReadNamespace,
|
|
565
|
-
canWriteNamespace,
|
|
566
597
|
defaultNamespaceForPrincipal,
|
|
567
|
-
recallNamespacesForPrincipal,
|
|
568
598
|
resolvePrincipal
|
|
569
599
|
} from "./chunk-3GD2HFR6.js";
|
|
570
600
|
import {
|
|
@@ -608,7 +638,6 @@ import {
|
|
|
608
638
|
ALL_CATEGORY_DIRS,
|
|
609
639
|
ALL_CATEGORY_KEYS,
|
|
610
640
|
RECALL_FALLBACK_DIRS,
|
|
611
|
-
categoryDirName,
|
|
612
641
|
getCategoryDir
|
|
613
642
|
} from "./chunk-VS2IYZRU.js";
|
|
614
643
|
import {
|
|
@@ -616,8 +645,8 @@ import {
|
|
|
616
645
|
} from "./chunk-3WCASNQZ.js";
|
|
617
646
|
|
|
618
647
|
// src/orchestrator.ts
|
|
619
|
-
import
|
|
620
|
-
import { createHash as
|
|
648
|
+
import path16 from "path";
|
|
649
|
+
import { createHash as createHash6 } from "crypto";
|
|
621
650
|
|
|
622
651
|
// src/orchestration/tier-migration-coordinator.ts
|
|
623
652
|
import path from "path";
|
|
@@ -2108,7 +2137,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2108
2137
|
namespaces,
|
|
2109
2138
|
{
|
|
2110
2139
|
readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),
|
|
2111
|
-
readMemoryFrontmatter: async (
|
|
2140
|
+
readMemoryFrontmatter: async (path31, preferredNamespace) => {
|
|
2112
2141
|
if (!fallbackReader) {
|
|
2113
2142
|
for (const ns of namespaces) {
|
|
2114
2143
|
try {
|
|
@@ -2120,7 +2149,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2120
2149
|
}
|
|
2121
2150
|
if (!fallbackReader) return null;
|
|
2122
2151
|
const memory = await this.readQmdResultMemory(
|
|
2123
|
-
|
|
2152
|
+
path31,
|
|
2124
2153
|
fallbackReader,
|
|
2125
2154
|
namespaces,
|
|
2126
2155
|
preferredNamespace
|
|
@@ -2721,1313 +2750,60 @@ var ContradictionLinkingCoordinator = class {
|
|
|
2721
2750
|
);
|
|
2722
2751
|
}
|
|
2723
2752
|
} catch (err) {
|
|
2724
|
-
log.warn(
|
|
2725
|
-
`contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`
|
|
2726
|
-
);
|
|
2727
|
-
}
|
|
2728
|
-
}
|
|
2729
|
-
// ---------------------------------------------------------------------------
|
|
2730
|
-
// Memory Linking (Phase 3A)
|
|
2731
|
-
// ---------------------------------------------------------------------------
|
|
2732
|
-
/**
|
|
2733
|
-
* Suggest links for a new memory based on similar existing memories.
|
|
2734
|
-
*/
|
|
2735
|
-
async suggestLinksForMemory(content, category, namespaceScope) {
|
|
2736
|
-
if (!this.isSearchAvailable()) return [];
|
|
2737
|
-
const results = await this.searchAcrossNamespaces({
|
|
2738
|
-
query: content,
|
|
2739
|
-
namespaces: [namespaceScope],
|
|
2740
|
-
maxResults: 5,
|
|
2741
|
-
mode: "search"
|
|
2742
|
-
});
|
|
2743
|
-
if (results.length === 0) return [];
|
|
2744
|
-
const candidates = [];
|
|
2745
|
-
for (const result of results) {
|
|
2746
|
-
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
2747
|
-
if (!memoryId) continue;
|
|
2748
|
-
const resultNamespace = this.namespaceFromPath(result.path);
|
|
2749
|
-
if (resultNamespace !== namespaceScope) continue;
|
|
2750
|
-
const resultStorage = await this.storageForNamespace(resultNamespace);
|
|
2751
|
-
const memory = await resultStorage.getMemoryById(memoryId);
|
|
2752
|
-
if (memory && memory.frontmatter.status !== "superseded" && memory.frontmatter.status !== "forgotten") {
|
|
2753
|
-
candidates.push({
|
|
2754
|
-
id: memory.frontmatter.id,
|
|
2755
|
-
content: memory.content,
|
|
2756
|
-
category: memory.frontmatter.category
|
|
2757
|
-
});
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
if (candidates.length === 0) return [];
|
|
2761
|
-
const extraction = this.getExtraction();
|
|
2762
|
-
const suggestions = await extraction.suggestLinks(
|
|
2763
|
-
{ content, category },
|
|
2764
|
-
candidates
|
|
2765
|
-
);
|
|
2766
|
-
if (!suggestions || suggestions.links.length === 0) return [];
|
|
2767
|
-
return suggestions.links.map((link) => ({
|
|
2768
|
-
targetId: link.targetId,
|
|
2769
|
-
linkType: link.linkType,
|
|
2770
|
-
strength: link.strength,
|
|
2771
|
-
reason: link.reason || void 0
|
|
2772
|
-
}));
|
|
2773
|
-
}
|
|
2774
|
-
};
|
|
2775
|
-
|
|
2776
|
-
// src/orchestration/extraction-run.ts
|
|
2777
|
-
import { createHash as createHash3 } from "crypto";
|
|
2778
|
-
|
|
2779
|
-
// src/orchestration/orchestrator-helpers.ts
|
|
2780
|
-
import { createHash as createHash2 } from "crypto";
|
|
2781
|
-
import os from "os";
|
|
2782
|
-
import path4 from "path";
|
|
2783
|
-
var BulkImportBatchPartialFailureError = class extends Error {
|
|
2784
|
-
partialResult;
|
|
2785
|
-
originalError;
|
|
2786
|
-
constructor(message, partialResult, originalError) {
|
|
2787
|
-
super(message);
|
|
2788
|
-
this.name = "BulkImportBatchPartialFailureError";
|
|
2789
|
-
this.partialResult = partialResult;
|
|
2790
|
-
this.originalError = originalError;
|
|
2791
|
-
}
|
|
2792
|
-
};
|
|
2793
|
-
function mapRecallSourceToXrayServedBy(source) {
|
|
2794
|
-
switch (source) {
|
|
2795
|
-
case "recent_scan":
|
|
2796
|
-
return "recent-scan";
|
|
2797
|
-
case "hot_qmd":
|
|
2798
|
-
case "hot_embedding":
|
|
2799
|
-
case "cold_fallback":
|
|
2800
|
-
case "none":
|
|
2801
|
-
return "hybrid";
|
|
2802
|
-
}
|
|
2803
|
-
const _exhaustive = source;
|
|
2804
|
-
void _exhaustive;
|
|
2805
|
-
return "hybrid";
|
|
2806
|
-
}
|
|
2807
|
-
var abortRecallError = abortError;
|
|
2808
|
-
function throwIfRecallAborted(signal, message = "recall aborted") {
|
|
2809
|
-
throwIfAborted(signal, message);
|
|
2810
|
-
}
|
|
2811
|
-
async function raceRecallAbort(promise, signal, message = "recall aborted") {
|
|
2812
|
-
throwIfRecallAborted(signal, message);
|
|
2813
|
-
if (!signal) return promise;
|
|
2814
|
-
let onAbort = null;
|
|
2815
|
-
const abortPromise = new Promise((_resolve, reject) => {
|
|
2816
|
-
onAbort = () => reject(abortRecallError(message));
|
|
2817
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
2818
|
-
});
|
|
2819
|
-
try {
|
|
2820
|
-
return await Promise.race([promise, abortPromise]);
|
|
2821
|
-
} finally {
|
|
2822
|
-
if (onAbort) {
|
|
2823
|
-
signal.removeEventListener("abort", onAbort);
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
}
|
|
2827
|
-
var COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
2828
|
-
var DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS = 1e4;
|
|
2829
|
-
function normalizeIanaTimeZone(value) {
|
|
2830
|
-
if (typeof value !== "string") return void 0;
|
|
2831
|
-
const trimmed = value.trim();
|
|
2832
|
-
if (!trimmed) return void 0;
|
|
2833
|
-
try {
|
|
2834
|
-
Intl.DateTimeFormat(void 0, { timeZone: trimmed });
|
|
2835
|
-
return trimmed;
|
|
2836
|
-
} catch {
|
|
2837
|
-
return void 0;
|
|
2838
|
-
}
|
|
2839
|
-
}
|
|
2840
|
-
function formatDateInTimeZone(date, timeZone) {
|
|
2841
|
-
const parts = new Intl.DateTimeFormat("en-US", {
|
|
2842
|
-
timeZone,
|
|
2843
|
-
year: "numeric",
|
|
2844
|
-
month: "2-digit",
|
|
2845
|
-
day: "2-digit"
|
|
2846
|
-
}).formatToParts(date);
|
|
2847
|
-
const get = (type) => parts.find((part) => part.type === type)?.value ?? "";
|
|
2848
|
-
return `${get("year")}-${get("month")}-${get("day")}`;
|
|
2849
|
-
}
|
|
2850
|
-
function utcDateKey(date) {
|
|
2851
|
-
return date.toISOString().slice(0, 10);
|
|
2852
|
-
}
|
|
2853
|
-
function utcDateKeysAround(date) {
|
|
2854
|
-
const dayMs = 864e5;
|
|
2855
|
-
const keys = [
|
|
2856
|
-
utcDateKey(new Date(date.getTime() - dayMs)),
|
|
2857
|
-
utcDateKey(date),
|
|
2858
|
-
utcDateKey(new Date(date.getTime() + dayMs))
|
|
2859
|
-
];
|
|
2860
|
-
return keys.filter((value, index, array) => array.indexOf(value) === index);
|
|
2861
|
-
}
|
|
2862
|
-
function utcDateKeysForLocalDay(date, timeZone) {
|
|
2863
|
-
const targetLocalDate = formatDateInTimeZone(date, timeZone);
|
|
2864
|
-
const keys = /* @__PURE__ */ new Set();
|
|
2865
|
-
const hourMs = 36e5;
|
|
2866
|
-
const scanStart = date.getTime() - 48 * hourMs;
|
|
2867
|
-
const scanEnd = date.getTime() + 48 * hourMs;
|
|
2868
|
-
for (let ms = scanStart; ms <= scanEnd; ms += hourMs) {
|
|
2869
|
-
const candidate = new Date(ms);
|
|
2870
|
-
if (formatDateInTimeZone(candidate, timeZone) === targetLocalDate) {
|
|
2871
|
-
keys.add(utcDateKey(candidate));
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
return keys.size > 0 ? [...keys].sort() : utcDateKeysAround(date);
|
|
2875
|
-
}
|
|
2876
|
-
function parseFiniteDate(value) {
|
|
2877
|
-
if (typeof value !== "string" || value.trim().length === 0) return null;
|
|
2878
|
-
const parsed = new Date(value);
|
|
2879
|
-
return Number.isFinite(parsed.getTime()) ? parsed : null;
|
|
2880
|
-
}
|
|
2881
|
-
function filterHourlySummaryMarkdownForLocalDay(raw, utcDate, timeZone, targetLocalDate) {
|
|
2882
|
-
const hourHeaderPattern = /^## ([01]\d|2[0-3]):00[ \t]*$/gm;
|
|
2883
|
-
const matches = Array.from(raw.matchAll(hourHeaderPattern));
|
|
2884
|
-
if (matches.length === 0) return null;
|
|
2885
|
-
const firstSectionStart = matches[0]?.index ?? 0;
|
|
2886
|
-
const preamble = raw.slice(0, firstSectionStart).trim();
|
|
2887
|
-
const sections = [];
|
|
2888
|
-
for (let index = 0; index < matches.length; index += 1) {
|
|
2889
|
-
const match = matches[index];
|
|
2890
|
-
const hour = match[1];
|
|
2891
|
-
if (!hour) continue;
|
|
2892
|
-
const sectionTimestamp = parseFiniteDate(`${utcDate}T${hour}:00:00.000Z`);
|
|
2893
|
-
if (!sectionTimestamp || formatDateInTimeZone(sectionTimestamp, timeZone) !== targetLocalDate) {
|
|
2894
|
-
continue;
|
|
2895
|
-
}
|
|
2896
|
-
const sectionStart = match.index ?? 0;
|
|
2897
|
-
const sectionEnd = matches[index + 1]?.index ?? raw.length;
|
|
2898
|
-
const section = raw.slice(sectionStart, sectionEnd).trim();
|
|
2899
|
-
if (section.length > 0) sections.push(section);
|
|
2900
|
-
}
|
|
2901
|
-
if (sections.length === 0) return null;
|
|
2902
|
-
return [preamble, ...sections].filter((section) => section.length > 0).join("\n\n");
|
|
2903
|
-
}
|
|
2904
|
-
function qmdStartupCollectionCheckTimeoutMs() {
|
|
2905
|
-
const raw = process.env.REMNIC_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS ?? process.env.ENGRAM_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS;
|
|
2906
|
-
if (raw === void 0) return DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS;
|
|
2907
|
-
const parsed = Number(raw);
|
|
2908
|
-
return Number.isFinite(parsed) && parsed >= 1e3 ? Math.floor(parsed) : DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS;
|
|
2909
|
-
}
|
|
2910
|
-
async function qmdStartupCollectionCheckWithTimeout(promise, controller, label) {
|
|
2911
|
-
const timeoutMs = qmdStartupCollectionCheckTimeoutMs();
|
|
2912
|
-
let timer;
|
|
2913
|
-
let settled = false;
|
|
2914
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
2915
|
-
timer = setTimeout(() => {
|
|
2916
|
-
if (settled) return;
|
|
2917
|
-
controller.abort();
|
|
2918
|
-
log.warn(
|
|
2919
|
-
`QMD startup collection check for ${label} timed out after ${timeoutMs}ms; keeping search enabled fail-open`
|
|
2920
|
-
);
|
|
2921
|
-
resolve("unknown");
|
|
2922
|
-
}, timeoutMs);
|
|
2923
|
-
timer.unref?.();
|
|
2924
|
-
});
|
|
2925
|
-
const checkedPromise = promise.catch((err) => {
|
|
2926
|
-
log.warn(
|
|
2927
|
-
`QMD startup collection check for ${label} failed; keeping search enabled fail-open: ${err}`
|
|
2928
|
-
);
|
|
2929
|
-
return "unknown";
|
|
2930
|
-
}).finally(() => {
|
|
2931
|
-
settled = true;
|
|
2932
|
-
if (timer) clearTimeout(timer);
|
|
2933
|
-
});
|
|
2934
|
-
return await Promise.race([checkedPromise, timeoutPromise]);
|
|
2935
|
-
}
|
|
2936
|
-
function defaultWorkspaceDir() {
|
|
2937
|
-
return path4.join(os.homedir(), ".openclaw", "workspace");
|
|
2938
|
-
}
|
|
2939
|
-
function sanitizeSessionKeyForFilename(sessionKey) {
|
|
2940
|
-
const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
2941
|
-
const hash = createHash2("sha256").update(sessionKey).digest("hex").slice(0, 12);
|
|
2942
|
-
return `${readable}-${hash}`;
|
|
2943
|
-
}
|
|
2944
|
-
function sourceValidAtMs(turn) {
|
|
2945
|
-
if (typeof turn.sourceValidAt !== "string") return null;
|
|
2946
|
-
return parseFlexibleIsoTimestamp(turn.sourceValidAt.trim());
|
|
2947
|
-
}
|
|
2948
|
-
var SOURCE_VALID_AT_CONTEXT_TURNS = 2;
|
|
2949
|
-
function sourceValidAtSliceKey(turn, index) {
|
|
2950
|
-
const validAtMs = sourceValidAtMs(turn);
|
|
2951
|
-
return validAtMs === null ? `unknown:${index}` : String(validAtMs);
|
|
2952
|
-
}
|
|
2953
|
-
function asExtractionContextTurn(turn) {
|
|
2954
|
-
return { ...turn, extractionContextOnly: true };
|
|
2955
|
-
}
|
|
2956
|
-
function asExtractionTargetTurn(turn) {
|
|
2957
|
-
const { extractionContextOnly: _contextOnly, ...targetTurn } = turn;
|
|
2958
|
-
return targetTurn;
|
|
2959
|
-
}
|
|
2960
|
-
function sourceValidAtContextTurns(turns, targetStart, targetEnd, targetValidAtMs) {
|
|
2961
|
-
if (targetValidAtMs === null) return [];
|
|
2962
|
-
return turns.flatMap((turn, index) => {
|
|
2963
|
-
if (index >= targetStart && index < targetEnd) return [];
|
|
2964
|
-
const contextValidAtMs = sourceValidAtMs(turn);
|
|
2965
|
-
if (contextValidAtMs === null || contextValidAtMs > targetValidAtMs) {
|
|
2966
|
-
return [];
|
|
2967
|
-
}
|
|
2968
|
-
return [{ turn, index, validAtMs: contextValidAtMs }];
|
|
2969
|
-
}).sort((a, b) => {
|
|
2970
|
-
if (a.validAtMs < b.validAtMs) return -1;
|
|
2971
|
-
if (a.validAtMs > b.validAtMs) return 1;
|
|
2972
|
-
if (a.index === b.index) return 0;
|
|
2973
|
-
return a.index < b.index ? -1 : 1;
|
|
2974
|
-
}).slice(-SOURCE_VALID_AT_CONTEXT_TURNS).map(({ turn }) => asExtractionContextTurn(turn));
|
|
2975
|
-
}
|
|
2976
|
-
function targetSourceValidAtSortMs(turns) {
|
|
2977
|
-
let latestMs = null;
|
|
2978
|
-
for (const turn of turns) {
|
|
2979
|
-
if (turn.extractionContextOnly === true) continue;
|
|
2980
|
-
const validAtMs = sourceValidAtMs(turn);
|
|
2981
|
-
if (validAtMs === null) continue;
|
|
2982
|
-
if (latestMs === null || validAtMs > latestMs) {
|
|
2983
|
-
latestMs = validAtMs;
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
2986
|
-
return latestMs ?? Number.POSITIVE_INFINITY;
|
|
2987
|
-
}
|
|
2988
|
-
function sortSourceValidAtSlicesChronologically(slices) {
|
|
2989
|
-
return slices.map((turns, order) => ({
|
|
2990
|
-
turns,
|
|
2991
|
-
order,
|
|
2992
|
-
targetValidAtMs: targetSourceValidAtSortMs(turns)
|
|
2993
|
-
})).sort((a, b) => {
|
|
2994
|
-
if (a.targetValidAtMs < b.targetValidAtMs) return -1;
|
|
2995
|
-
if (a.targetValidAtMs > b.targetValidAtMs) return 1;
|
|
2996
|
-
if (a.order === b.order) return 0;
|
|
2997
|
-
return a.order < b.order ? -1 : 1;
|
|
2998
|
-
}).map((slice) => slice.turns);
|
|
2999
|
-
}
|
|
3000
|
-
function splitTurnsBySourceValidAt(turns, options = {}) {
|
|
3001
|
-
if (turns.length === 0) return [];
|
|
3002
|
-
if (!turns.some((turn) => sourceValidAtMs(turn) !== null)) {
|
|
3003
|
-
return [[...turns]];
|
|
3004
|
-
}
|
|
3005
|
-
const slices = [];
|
|
3006
|
-
let start = 0;
|
|
3007
|
-
while (start < turns.length) {
|
|
3008
|
-
const targetValidAtMs = sourceValidAtMs(turns[start]);
|
|
3009
|
-
const activeKey = sourceValidAtSliceKey(turns[start], start);
|
|
3010
|
-
let end = start + 1;
|
|
3011
|
-
while (end < turns.length && sourceValidAtSliceKey(turns[end], end) === activeKey) {
|
|
3012
|
-
end += 1;
|
|
3013
|
-
}
|
|
3014
|
-
const contextTurns = options.includeContext === false ? [] : sourceValidAtContextTurns(turns, start, end, targetValidAtMs);
|
|
3015
|
-
slices.push([
|
|
3016
|
-
...contextTurns,
|
|
3017
|
-
...turns.slice(start, end).map(asExtractionTargetTurn)
|
|
3018
|
-
]);
|
|
3019
|
-
start = end;
|
|
3020
|
-
}
|
|
3021
|
-
return sortSourceValidAtSlicesChronologically(slices);
|
|
3022
|
-
}
|
|
3023
|
-
function isArtifactMemoryPath(filePath) {
|
|
3024
|
-
return /(?:^|[\\/])artifacts(?:[\\/]|$)/i.test(filePath);
|
|
3025
|
-
}
|
|
3026
|
-
function isMeetingRecordPath(filePath) {
|
|
3027
|
-
return /(?:^|[\\/])meetings[\\/]\d{4}-\d{2}-\d{2}[\\/]mtg-\d{4}-\d{2}-\d{2}-[0-9a-f]{8}\.md$/i.test(filePath);
|
|
3028
|
-
}
|
|
3029
|
-
var ACTIVITY_DIGEST_TOPLEVEL = /^activity[\\/]\d{4}-\d{2}-\d{2}\.md$/i;
|
|
3030
|
-
var ACTIVITY_DIGEST_ANYWHERE = /(?:^|[\\/])activity[\\/]\d{4}-\d{2}-\d{2}\.md$/i;
|
|
3031
|
-
function isActivityDigestPath(filePath, memoryRoot) {
|
|
3032
|
-
if (memoryRoot !== void 0 && memoryRoot.length > 0) {
|
|
3033
|
-
const relative = path4.relative(memoryRoot, path4.resolve(memoryRoot, filePath));
|
|
3034
|
-
return ACTIVITY_DIGEST_TOPLEVEL.test(relative);
|
|
3035
|
-
}
|
|
3036
|
-
return ACTIVITY_DIGEST_ANYWHERE.test(filePath);
|
|
3037
|
-
}
|
|
3038
|
-
function buildCompressionGuidelinesMarkdown2(events, generatedAtIso = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
3039
|
-
return buildCompressionGuidelinesMarkdown(events, generatedAtIso);
|
|
3040
|
-
}
|
|
3041
|
-
function applyQueryAwareCandidateFilter(candidates, candidatePaths) {
|
|
3042
|
-
if (!candidatePaths) return candidates;
|
|
3043
|
-
if (candidatePaths.size === 0) return [];
|
|
3044
|
-
const filtered = candidates.filter(
|
|
3045
|
-
(candidate) => candidatePaths.has(candidate.path)
|
|
3046
|
-
);
|
|
3047
|
-
return filtered.length > 0 ? filtered : candidates;
|
|
3048
|
-
}
|
|
3049
|
-
function tokenizeRecallQuery(prompt) {
|
|
3050
|
-
return prompt.toLowerCase().split(/[^a-z0-9]+/i).map((t) => t.trim()).filter((t) => t.length >= 3);
|
|
3051
|
-
}
|
|
3052
|
-
function hasLifecycleMetadata(frontmatter) {
|
|
3053
|
-
return frontmatter.lifecycleState !== void 0 || frontmatter.verificationState !== void 0 || frontmatter.policyClass !== void 0 || frontmatter.lastValidatedAt !== void 0 || frontmatter.decayScore !== void 0 || frontmatter.heatScore !== void 0;
|
|
3054
|
-
}
|
|
3055
|
-
function shouldFilterLifecycleRecallCandidate(frontmatter, options) {
|
|
3056
|
-
if (!options.lifecyclePolicyEnabled || !options.lifecycleFilterStaleEnabled)
|
|
3057
|
-
return false;
|
|
3058
|
-
if (!hasLifecycleMetadata(frontmatter)) return false;
|
|
3059
|
-
const lifecycleState = resolveLifecycleState(frontmatter);
|
|
3060
|
-
return lifecycleState === "stale" || lifecycleState === "archived";
|
|
3061
|
-
}
|
|
3062
|
-
function lifecycleRecallScoreAdjustment(frontmatter, options) {
|
|
3063
|
-
if (!options.lifecyclePolicyEnabled) return 0;
|
|
3064
|
-
if (!hasLifecycleMetadata(frontmatter)) return 0;
|
|
3065
|
-
let delta = 0;
|
|
3066
|
-
const lifecycleState = resolveLifecycleState(frontmatter);
|
|
3067
|
-
switch (lifecycleState) {
|
|
3068
|
-
case "active":
|
|
3069
|
-
delta += 0.05;
|
|
3070
|
-
break;
|
|
3071
|
-
case "validated":
|
|
3072
|
-
delta += 0.03;
|
|
3073
|
-
break;
|
|
3074
|
-
case "candidate":
|
|
3075
|
-
delta -= 0.01;
|
|
3076
|
-
break;
|
|
3077
|
-
case "stale":
|
|
3078
|
-
delta -= 0.06;
|
|
3079
|
-
break;
|
|
3080
|
-
case "archived":
|
|
3081
|
-
delta -= 0.08;
|
|
3082
|
-
break;
|
|
3083
|
-
}
|
|
3084
|
-
if (frontmatter.verificationState === "disputed") {
|
|
3085
|
-
delta -= 0.12;
|
|
3086
|
-
}
|
|
3087
|
-
return delta;
|
|
3088
|
-
}
|
|
3089
|
-
function computeArtifactRecallLimit(recallMode, recallResultLimit, verbatimArtifactsMaxRecall) {
|
|
3090
|
-
if (recallMode === "no_recall") return 0;
|
|
3091
|
-
if (Math.max(0, recallResultLimit) === 0) return 0;
|
|
3092
|
-
const base = Math.max(0, verbatimArtifactsMaxRecall);
|
|
3093
|
-
if (recallMode === "minimal") {
|
|
3094
|
-
return Math.min(base, Math.max(0, recallResultLimit));
|
|
3095
|
-
}
|
|
3096
|
-
return base;
|
|
3097
|
-
}
|
|
3098
|
-
function resolveEffectiveRecallMode(options) {
|
|
3099
|
-
return resolveRecallModeDecision(options).effectiveMode;
|
|
3100
|
-
}
|
|
3101
|
-
function finalizeRecallModeDecision(plannedModeRaw, options) {
|
|
3102
|
-
let plannedMode = plannedModeRaw;
|
|
3103
|
-
const graphExpandedIntentDetected = options.plannerEnabled && options.graphExpandedIntentEnabled === true && hasBroadGraphIntent(options.prompt);
|
|
3104
|
-
if (plannedMode !== "graph_mode" && graphExpandedIntentDetected) {
|
|
3105
|
-
plannedMode = "graph_mode";
|
|
3106
|
-
}
|
|
3107
|
-
if (plannedMode === "graph_mode" && (!options.graphRecallEnabled || !options.multiGraphMemoryEnabled)) {
|
|
3108
|
-
return {
|
|
3109
|
-
plannedMode,
|
|
3110
|
-
effectiveMode: "full",
|
|
3111
|
-
graphExpandedIntentDetected,
|
|
3112
|
-
graphReason: !options.graphRecallEnabled ? "graph recall disabled by config" : "multi-graph memory disabled by config"
|
|
3113
|
-
};
|
|
3114
|
-
}
|
|
3115
|
-
return {
|
|
3116
|
-
plannedMode,
|
|
3117
|
-
effectiveMode: plannedMode,
|
|
3118
|
-
graphExpandedIntentDetected
|
|
3119
|
-
};
|
|
3120
|
-
}
|
|
3121
|
-
function resolveRecallModeDecision(options) {
|
|
3122
|
-
const plannedMode = options.plannerEnabled ? planRecallMode(options.prompt) : "full";
|
|
3123
|
-
return finalizeRecallModeDecision(plannedMode, options);
|
|
3124
|
-
}
|
|
3125
|
-
async function resolveRecallModeDecisionAsync(options) {
|
|
3126
|
-
const heuristicDecision = resolveRecallModeDecision(options);
|
|
3127
|
-
const plannerLlmEnabled = options.caps.recallPlannerLlm;
|
|
3128
|
-
if (!options.plannerEnabled || !plannerLlmEnabled) {
|
|
3129
|
-
return heuristicDecision;
|
|
3130
|
-
}
|
|
3131
|
-
const { planRecallModeLLM } = await import("./recall-planner-llm.js");
|
|
3132
|
-
const planned = await planRecallModeLLM(
|
|
3133
|
-
options.prompt,
|
|
3134
|
-
options.hints,
|
|
3135
|
-
options.config,
|
|
3136
|
-
options.caps,
|
|
3137
|
-
options.llm,
|
|
3138
|
-
options.signal
|
|
3139
|
-
);
|
|
3140
|
-
if (options.config.recallPlannerShadowMode) {
|
|
3141
|
-
return {
|
|
3142
|
-
...heuristicDecision,
|
|
3143
|
-
plannerSource: planned.source,
|
|
3144
|
-
plannerReason: `shadow:${planned.reason}`,
|
|
3145
|
-
plannerLatencyMs: planned.latencyMs,
|
|
3146
|
-
plannerFallbackUsed: planned.fallbackUsed,
|
|
3147
|
-
plannerModelUsed: planned.modelUsed,
|
|
3148
|
-
plannerHeuristicMode: planned.heuristicMode,
|
|
3149
|
-
shadowLlmMode: planned.mode
|
|
3150
|
-
};
|
|
3151
|
-
}
|
|
3152
|
-
const llmDecision = finalizeRecallModeDecision(planned.mode, options);
|
|
3153
|
-
return {
|
|
3154
|
-
...llmDecision,
|
|
3155
|
-
plannerSource: planned.source,
|
|
3156
|
-
plannerReason: planned.reason,
|
|
3157
|
-
plannerLatencyMs: planned.latencyMs,
|
|
3158
|
-
plannerFallbackUsed: planned.fallbackUsed,
|
|
3159
|
-
plannerModelUsed: planned.modelUsed,
|
|
3160
|
-
plannerHeuristicMode: planned.heuristicMode
|
|
3161
|
-
};
|
|
3162
|
-
}
|
|
3163
|
-
function computeArtifactCandidateFetchLimit(targetCount) {
|
|
3164
|
-
const cappedTarget = Math.max(0, targetCount);
|
|
3165
|
-
if (cappedTarget === 0) return 0;
|
|
3166
|
-
const headroom = Math.max(8, cappedTarget * 4);
|
|
3167
|
-
return Math.min(200, cappedTarget + headroom);
|
|
3168
|
-
}
|
|
3169
|
-
function computeQmdHybridFetchLimit(recallFetchLimit, artifactsEnabled, maxArtifactRecall) {
|
|
3170
|
-
const cappedRecallLimit = Math.max(0, recallFetchLimit);
|
|
3171
|
-
if (cappedRecallLimit === 0) return 0;
|
|
3172
|
-
if (!artifactsEnabled) return cappedRecallLimit;
|
|
3173
|
-
const artifactHeadroom = Math.max(20, Math.max(0, maxArtifactRecall) * 8);
|
|
3174
|
-
return Math.min(400, cappedRecallLimit + artifactHeadroom);
|
|
3175
|
-
}
|
|
3176
|
-
function summarizeGraphShadowComparison(baseline, merged, topN) {
|
|
3177
|
-
const limit = Math.max(0, Math.floor(topN));
|
|
3178
|
-
const baselineTop = limit > 0 ? baseline.slice(0, limit) : [];
|
|
3179
|
-
const graphTop = limit > 0 ? merged.slice(0, limit) : [];
|
|
3180
|
-
const baselineByPath = new Map(
|
|
3181
|
-
baselineTop.map((item) => [item.path, item.score])
|
|
3182
|
-
);
|
|
3183
|
-
const graphByPath = new Map(graphTop.map((item) => [item.path, item.score]));
|
|
3184
|
-
let overlapCount = 0;
|
|
3185
|
-
let overlapDeltaSum = 0;
|
|
3186
|
-
for (const [p, baselineScore] of baselineByPath.entries()) {
|
|
3187
|
-
const graphScore = graphByPath.get(p);
|
|
3188
|
-
if (typeof graphScore !== "number") continue;
|
|
3189
|
-
overlapCount += 1;
|
|
3190
|
-
overlapDeltaSum += graphScore - baselineScore;
|
|
3191
|
-
}
|
|
3192
|
-
const baselineCount = baselineTop.length;
|
|
3193
|
-
return {
|
|
3194
|
-
baselineCount,
|
|
3195
|
-
graphCount: graphTop.length,
|
|
3196
|
-
overlapCount,
|
|
3197
|
-
overlapRatio: baselineCount > 0 ? overlapCount / baselineCount : 0,
|
|
3198
|
-
averageOverlapDelta: overlapCount > 0 ? overlapDeltaSum / overlapCount : 0
|
|
3199
|
-
};
|
|
3200
|
-
}
|
|
3201
|
-
function parseGraphRecallRankedResults(value) {
|
|
3202
|
-
if (!Array.isArray(value)) return [];
|
|
3203
|
-
const parsed = [];
|
|
3204
|
-
for (const entry of value) {
|
|
3205
|
-
if (!entry || typeof entry !== "object") continue;
|
|
3206
|
-
const candidate = entry;
|
|
3207
|
-
if (typeof candidate.path !== "string" || typeof candidate.score !== "number")
|
|
3208
|
-
continue;
|
|
3209
|
-
parsed.push({
|
|
3210
|
-
path: candidate.path,
|
|
3211
|
-
score: candidate.score,
|
|
3212
|
-
docid: typeof candidate.docid === "string" ? candidate.docid : void 0,
|
|
3213
|
-
sourceLabels: Array.isArray(candidate.sourceLabels) ? candidate.sourceLabels.filter(
|
|
3214
|
-
(item) => typeof item === "string"
|
|
3215
|
-
) : []
|
|
3216
|
-
});
|
|
3217
|
-
}
|
|
3218
|
-
return parsed.slice(0, 64);
|
|
3219
|
-
}
|
|
3220
|
-
function parseMemoryIntentSnapshot(value) {
|
|
3221
|
-
const candidate = value && typeof value === "object" ? value : {};
|
|
3222
|
-
return {
|
|
3223
|
-
goal: typeof candidate.goal === "string" ? candidate.goal : "unknown",
|
|
3224
|
-
actionType: typeof candidate.actionType === "string" ? candidate.actionType : "unknown",
|
|
3225
|
-
entityTypes: Array.isArray(candidate.entityTypes) ? candidate.entityTypes.filter(
|
|
3226
|
-
(item) => typeof item === "string"
|
|
3227
|
-
) : [],
|
|
3228
|
-
taskInitiation: candidate.taskInitiation === true
|
|
3229
|
-
};
|
|
3230
|
-
}
|
|
3231
|
-
function buildQmdIntentHint(intent) {
|
|
3232
|
-
const parts = [];
|
|
3233
|
-
if (intent.goal !== "unknown") {
|
|
3234
|
-
parts.push(`goal:${intent.goal.replace(/_/g, " ")}`);
|
|
3235
|
-
}
|
|
3236
|
-
if (intent.actionType !== "unknown") {
|
|
3237
|
-
parts.push(`action:${intent.actionType.replace(/_/g, " ")}`);
|
|
3238
|
-
}
|
|
3239
|
-
if (intent.entityTypes.length > 0) {
|
|
3240
|
-
parts.push(`entities:${intent.entityTypes.join(",")}`);
|
|
3241
|
-
}
|
|
3242
|
-
if (intent.taskInitiation === true) {
|
|
3243
|
-
parts.push("task_initiation");
|
|
3244
|
-
}
|
|
3245
|
-
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
3246
|
-
}
|
|
3247
|
-
function parseQmdRecallResults(value) {
|
|
3248
|
-
if (!Array.isArray(value)) return [];
|
|
3249
|
-
const parsed = [];
|
|
3250
|
-
for (const entry of value) {
|
|
3251
|
-
if (!entry || typeof entry !== "object") continue;
|
|
3252
|
-
const candidate = entry;
|
|
3253
|
-
if (typeof candidate.path !== "string" || typeof candidate.score !== "number")
|
|
3254
|
-
continue;
|
|
3255
|
-
parsed.push({
|
|
3256
|
-
docid: typeof candidate.docid === "string" ? candidate.docid : "",
|
|
3257
|
-
path: candidate.path,
|
|
3258
|
-
snippet: typeof candidate.snippet === "string" ? candidate.snippet : "",
|
|
3259
|
-
score: candidate.score,
|
|
3260
|
-
explain: parseQmdExplain(candidate.explain),
|
|
3261
|
-
transport: candidate.transport === "daemon" || candidate.transport === "subprocess" || candidate.transport === "hybrid" || candidate.transport === "scoped_prefilter" ? candidate.transport : void 0
|
|
3262
|
-
});
|
|
3263
|
-
}
|
|
3264
|
-
return parsed.slice(0, 32);
|
|
3265
|
-
}
|
|
3266
|
-
function mergeArtifactRecallCandidates(candidatesByNamespace, limit) {
|
|
3267
|
-
const cappedLimit = Math.max(0, limit);
|
|
3268
|
-
if (cappedLimit === 0) return [];
|
|
3269
|
-
const out = [];
|
|
3270
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3271
|
-
let offset = 0;
|
|
3272
|
-
while (out.length < cappedLimit) {
|
|
3273
|
-
let hasAnyCandidateAtOffset = false;
|
|
3274
|
-
for (const list of candidatesByNamespace) {
|
|
3275
|
-
if (offset >= list.length) continue;
|
|
3276
|
-
hasAnyCandidateAtOffset = true;
|
|
3277
|
-
const item = list[offset];
|
|
3278
|
-
const dedupeKey = `${item.frontmatter.id}:${item.frontmatter.sourceMemoryId ?? ""}:${item.content}`;
|
|
3279
|
-
if (seen.has(dedupeKey)) continue;
|
|
3280
|
-
seen.add(dedupeKey);
|
|
3281
|
-
out.push(item);
|
|
3282
|
-
if (out.length >= cappedLimit) break;
|
|
3283
|
-
}
|
|
3284
|
-
if (!hasAnyCandidateAtOffset) break;
|
|
3285
|
-
offset += 1;
|
|
3286
|
-
}
|
|
3287
|
-
return out;
|
|
3288
|
-
}
|
|
3289
|
-
function resolveRecentThreadMemoryPaths(options) {
|
|
3290
|
-
const maxRecent = Math.max(0, options.maxRecent);
|
|
3291
|
-
if (options.threadEpisodeIds.length === 0 || maxRecent === 0) return [];
|
|
3292
|
-
const pathById = options.pathById ?? buildMemoryPathById(options.allMemsForGraph, options.storageDir);
|
|
3293
|
-
if (pathById.size === 0) return [];
|
|
3294
|
-
const pendingReviewIds = new Set(
|
|
3295
|
-
(options.allMemsForGraph ?? []).filter((m) => m.frontmatter.status === "pending_review" && m.frontmatter.id).map((m) => m.frontmatter.id)
|
|
3296
|
-
);
|
|
3297
|
-
return options.threadEpisodeIds.filter((id) => id !== options.currentMemoryId).filter((id) => !pendingReviewIds.has(id)).slice(-maxRecent).map((id) => pathById.get(id)).filter((p) => typeof p === "string" && p.length > 0);
|
|
3298
|
-
}
|
|
3299
|
-
function buildMemoryPathById(allMemsForGraph, storageDir) {
|
|
3300
|
-
const pathById = /* @__PURE__ */ new Map();
|
|
3301
|
-
for (const mem of allMemsForGraph ?? []) {
|
|
3302
|
-
const id = mem.frontmatter.id;
|
|
3303
|
-
if (!id) continue;
|
|
3304
|
-
pathById.set(id, path4.relative(storageDir, mem.path));
|
|
3305
|
-
}
|
|
3306
|
-
return pathById;
|
|
3307
|
-
}
|
|
3308
|
-
function appendMemoryToGraphContext(options) {
|
|
3309
|
-
if (!Array.isArray(options.allMemsForGraph)) return;
|
|
3310
|
-
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
3311
|
-
options.allMemsForGraph.push({
|
|
3312
|
-
path: path4.join(options.storageDir, options.memoryRelPath),
|
|
3313
|
-
content: options.content,
|
|
3314
|
-
frontmatter: {
|
|
3315
|
-
id: options.memoryId,
|
|
3316
|
-
category: options.category,
|
|
3317
|
-
created: nowIso,
|
|
3318
|
-
updated: nowIso,
|
|
3319
|
-
source: "extraction",
|
|
3320
|
-
confidence: 0.8,
|
|
3321
|
-
confidenceTier: "implied",
|
|
3322
|
-
tags: [],
|
|
3323
|
-
entityRef: options.entityRef,
|
|
3324
|
-
status: "active"
|
|
3325
|
-
}
|
|
3326
|
-
});
|
|
3327
|
-
}
|
|
3328
|
-
function resolvePersistedMemoryRelativePath(options) {
|
|
3329
|
-
const persisted = options.pathById.get(options.memoryId);
|
|
3330
|
-
if (persisted) return persisted;
|
|
3331
|
-
if (options.category === "correction") {
|
|
3332
|
-
return path4.join("corrections", `${options.memoryId}.md`);
|
|
3333
|
-
}
|
|
3334
|
-
const subtree = categoryDirName(options.category);
|
|
3335
|
-
const idParts = options.memoryId.split("-");
|
|
3336
|
-
const maybeTimestamp = Number(idParts[1]);
|
|
3337
|
-
if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
|
|
3338
|
-
const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
|
|
3339
|
-
return path4.join(subtree, day, `${options.memoryId}.md`);
|
|
3340
|
-
}
|
|
3341
|
-
return path4.join(subtree, `${options.memoryId}.md`);
|
|
3342
|
-
}
|
|
3343
|
-
|
|
3344
|
-
// src/orchestration/extraction-run.ts
|
|
3345
|
-
function deriveTopicsFromExtraction(result) {
|
|
3346
|
-
const topics = /* @__PURE__ */ new Set();
|
|
3347
|
-
for (const fact of result.facts ?? []) {
|
|
3348
|
-
for (const tag of fact.tags ?? []) {
|
|
3349
|
-
if (tag && tag.length >= 2) topics.add(tag.toLowerCase());
|
|
3350
|
-
}
|
|
3351
|
-
if (fact.entityRef) topics.add(fact.entityRef.toLowerCase());
|
|
3352
|
-
if (fact.category) topics.add(fact.category);
|
|
3353
|
-
}
|
|
3354
|
-
for (const entity of result.entities ?? []) {
|
|
3355
|
-
if (typeof entity.name === "string" && entity.name.length >= 2) {
|
|
3356
|
-
topics.add(entity.name.toLowerCase());
|
|
3357
|
-
}
|
|
3358
|
-
}
|
|
3359
|
-
return [...topics].slice(0, 16);
|
|
3360
|
-
}
|
|
3361
|
-
var EXTRACTION_RETRY_STATE_MAX_ENTRIES = 500;
|
|
3362
|
-
function computeExtractionRetryNextEligibleMs(attempts, scheduleMs, maxBackoffMs, jitterRatio, now, rng = Math.random) {
|
|
3363
|
-
const cap = Number.isFinite(maxBackoffMs) && maxBackoffMs > 0 ? maxBackoffMs : 0;
|
|
3364
|
-
if (!Array.isArray(scheduleMs) || scheduleMs.length === 0) {
|
|
3365
|
-
return now + cap;
|
|
3366
|
-
}
|
|
3367
|
-
const idx = Math.min(Math.max(attempts - 1, 0), scheduleMs.length - 1);
|
|
3368
|
-
const step = scheduleMs[idx];
|
|
3369
|
-
const base = Math.min(typeof step === "number" && step > 0 ? step : cap, cap);
|
|
3370
|
-
const jitter = 1 + (rng() * 2 - 1) * jitterRatio;
|
|
3371
|
-
return now + Math.max(0, Math.round(base * jitter));
|
|
3372
|
-
}
|
|
3373
|
-
function capExtractionRetryStateEntries(entries, maxEntries) {
|
|
3374
|
-
if (maxEntries <= 0) return [];
|
|
3375
|
-
const sorted = [...entries].sort((a, b) => a.firstFailedAt.localeCompare(b.firstFailedAt));
|
|
3376
|
-
return sorted.slice(-maxEntries);
|
|
3377
|
-
}
|
|
3378
|
-
var ExtractionRunCoordinator = class {
|
|
3379
|
-
constructor(deps) {
|
|
3380
|
-
this.deps = deps;
|
|
3381
|
-
}
|
|
3382
|
-
deps;
|
|
3383
|
-
recentExtractionFingerprints = /* @__PURE__ */ new Map();
|
|
3384
|
-
// Per-fingerprint extraction retry/backoff state (extraction hot-loop
|
|
3385
|
-
// hardening). Outer key = namespace, inner key = fingerprint. Hydrated lazily
|
|
3386
|
-
// from namespace-scoped meta so the hot path is a Map lookup; persisted back
|
|
3387
|
-
// to meta on change (restart-safe, cross-process coherent via the shared
|
|
3388
|
-
// meta.json). The breaker below is intentionally per-process in-memory
|
|
3389
|
-
// (mirrors local-llm.cooldownUntilMs); a restart clears it but the persisted
|
|
3390
|
-
// backoff still throttles, so a restart can't resurrect the hot loop.
|
|
3391
|
-
extractionRetryState = /* @__PURE__ */ new Map();
|
|
3392
|
-
hydratedRetryNamespaces = /* @__PURE__ */ new Set();
|
|
3393
|
-
providerBreaker = { consecutiveFailures: 0, openUntilMs: 0, state: "closed", lastReason: "" };
|
|
3394
|
-
get config() {
|
|
3395
|
-
return this.deps.config;
|
|
3396
|
-
}
|
|
3397
|
-
// -------------------------------------------------------------------------
|
|
3398
|
-
// Source-valid-at helpers (moved from orchestrator.ts module scope)
|
|
3399
|
-
// -------------------------------------------------------------------------
|
|
3400
|
-
latestSourceValidAtFromTurns(turns) {
|
|
3401
|
-
let latestMs = null;
|
|
3402
|
-
for (const turn of turns) {
|
|
3403
|
-
if (turn.extractionContextOnly === true) continue;
|
|
3404
|
-
if (typeof turn.sourceValidAt !== "string") continue;
|
|
3405
|
-
const parsed = parseFlexibleIsoTimestamp(turn.sourceValidAt.trim());
|
|
3406
|
-
if (parsed === null) continue;
|
|
3407
|
-
if (latestMs === null || parsed > latestMs) {
|
|
3408
|
-
latestMs = parsed;
|
|
3409
|
-
}
|
|
3410
|
-
}
|
|
3411
|
-
return latestMs === null ? void 0 : new Date(latestMs).toISOString();
|
|
3412
|
-
}
|
|
3413
|
-
// -------------------------------------------------------------------------
|
|
3414
|
-
// Extraction dedupe fingerprint helpers
|
|
3415
|
-
// -------------------------------------------------------------------------
|
|
3416
|
-
normalizeExtractionFingerprintTurns(turns) {
|
|
3417
|
-
if (!Array.isArray(turns) || turns.length === 0) return [];
|
|
3418
|
-
return turns.filter((turn) => turn.role === "user" || turn.role === "assistant").map((turn) => {
|
|
3419
|
-
if (typeof turn.turnFingerprint === "string" && turn.turnFingerprint.length > 0) {
|
|
3420
|
-
return `fp:${turn.turnFingerprint}`;
|
|
3421
|
-
}
|
|
3422
|
-
return `${turn.role}:${(turn.content ?? "").replace(/\s+/g, " ").trim().slice(0, this.config.extractionMaxTurnChars)}`;
|
|
3423
|
-
}).filter((value) => value.length > 0);
|
|
3424
|
-
}
|
|
3425
|
-
buildExtractionFingerprint(turns, bufferKey) {
|
|
3426
|
-
const normalized = this.normalizeExtractionFingerprintTurns(turns).join("\n");
|
|
3427
|
-
if (!normalized) return null;
|
|
3428
|
-
return createHash3("sha256").update(`${bufferKey}
|
|
3429
|
-
${normalized}`).digest("hex");
|
|
3430
|
-
}
|
|
3431
|
-
shouldQueueExtraction(turns, options = {}) {
|
|
3432
|
-
const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
|
|
3433
|
-
if (!lifecycleCaps.extractionDedupe) return true;
|
|
3434
|
-
if (!Array.isArray(turns) || turns.length === 0) return false;
|
|
3435
|
-
const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? "default";
|
|
3436
|
-
const fingerprint = this.buildExtractionFingerprint(turns, bufferKey);
|
|
3437
|
-
if (!fingerprint) return false;
|
|
3438
|
-
const now = Date.now();
|
|
3439
|
-
const seenAt = this.recentExtractionFingerprints.get(fingerprint);
|
|
3440
|
-
if (seenAt && now - seenAt < this.config.extractionDedupeWindowMs) {
|
|
3441
|
-
log.debug("extraction dedupe: skipped duplicate buffered turn set");
|
|
3442
|
-
return false;
|
|
3443
|
-
}
|
|
3444
|
-
if (options.commit !== false) {
|
|
3445
|
-
this.recentExtractionFingerprints.set(fingerprint, now);
|
|
3446
|
-
}
|
|
3447
|
-
if (options.commit !== false && this.recentExtractionFingerprints.size > 200) {
|
|
3448
|
-
const entries = Array.from(this.recentExtractionFingerprints.entries()).sort((a, b) => a[1] - b[1]);
|
|
3449
|
-
for (const [key] of entries.slice(0, entries.length - 200)) {
|
|
3450
|
-
this.recentExtractionFingerprints.delete(key);
|
|
3451
|
-
}
|
|
3452
|
-
}
|
|
3453
|
-
return true;
|
|
3454
|
-
}
|
|
3455
|
-
// -------------------------------------------------------------------------
|
|
3456
|
-
// Processed-fingerprint recording
|
|
3457
|
-
// -------------------------------------------------------------------------
|
|
3458
|
-
async recordProcessedExtractionFingerprint(storage, fingerprint, preloadedMeta) {
|
|
3459
|
-
const meta = preloadedMeta ?? await storage.loadMeta();
|
|
3460
|
-
const observedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3461
|
-
const seen = new Map(
|
|
3462
|
-
(meta.processedExtractionFingerprints ?? []).map((entry) => [entry.fingerprint, entry.observedAt])
|
|
3463
|
-
);
|
|
3464
|
-
seen.set(fingerprint, observedAt);
|
|
3465
|
-
meta.processedExtractionFingerprints = Array.from(seen.entries()).map(([value, at2]) => ({ fingerprint: value, observedAt: at2 })).sort((left, right) => left.observedAt.localeCompare(right.observedAt)).slice(-500);
|
|
3466
|
-
if (!preloadedMeta) {
|
|
3467
|
-
await storage.saveMeta(meta);
|
|
3468
|
-
}
|
|
3469
|
-
}
|
|
3470
|
-
// -------------------------------------------------------------------------
|
|
3471
|
-
// Extraction retry/backoff + circuit breaker (extraction hot-loop hardening)
|
|
3472
|
-
// -------------------------------------------------------------------------
|
|
3473
|
-
/** Lazily hydrate the in-memory retry-state mirror for a namespace from meta.
|
|
3474
|
-
* One-time per namespace per coordinator; the hot path is then a Map lookup.
|
|
3475
|
-
* Cross-process coherence: a fresh coordinator hydrates from the shared
|
|
3476
|
-
* meta.json, so a failure persisted by another process is honored here. */
|
|
3477
|
-
hydrateRetryStateFromMeta(namespace, meta) {
|
|
3478
|
-
if (this.hydratedRetryNamespaces.has(namespace)) return;
|
|
3479
|
-
this.hydratedRetryNamespaces.add(namespace);
|
|
3480
|
-
const nsMap = this.extractionRetryState.get(namespace) ?? /* @__PURE__ */ new Map();
|
|
3481
|
-
for (const entry of meta.extractionRetryState ?? []) {
|
|
3482
|
-
const nextEligibleAtMs = Date.parse(entry.nextEligibleAt);
|
|
3483
|
-
const firstFailedAtMs = Date.parse(entry.firstFailedAt);
|
|
3484
|
-
nsMap.set(entry.fingerprint, {
|
|
3485
|
-
attempts: entry.attempts,
|
|
3486
|
-
nextEligibleAtMs: Number.isFinite(nextEligibleAtMs) ? nextEligibleAtMs : 0,
|
|
3487
|
-
firstFailedAtMs: Number.isFinite(firstFailedAtMs) ? firstFailedAtMs : Date.now(),
|
|
3488
|
-
lastFailureClass: entry.lastFailureClass
|
|
3489
|
-
});
|
|
3490
|
-
}
|
|
3491
|
-
this.extractionRetryState.set(namespace, nsMap);
|
|
3492
|
-
}
|
|
3493
|
-
logBreakerTransition(state) {
|
|
3494
|
-
log.warn("extraction: provider circuit breaker transition", {
|
|
3495
|
-
state,
|
|
3496
|
-
consecutiveFailures: this.providerBreaker.consecutiveFailures,
|
|
3497
|
-
lastReason: this.providerBreaker.lastReason,
|
|
3498
|
-
openUntilMs: this.providerBreaker.openUntilMs
|
|
3499
|
-
});
|
|
3500
|
-
}
|
|
3501
|
-
/** True while the breaker suppresses non-forced attempts. Flips an expired
|
|
3502
|
-
* `open` breaker to `half_open`, which allows exactly one probe (the next
|
|
3503
|
-
* non-forced attempt) because the extraction queue is a serial drain. */
|
|
3504
|
-
isProviderBreakerOpen(now) {
|
|
3505
|
-
if (now < this.providerBreaker.openUntilMs) return true;
|
|
3506
|
-
if (this.providerBreaker.state === "open") {
|
|
3507
|
-
this.providerBreaker.state = "half_open";
|
|
3508
|
-
this.logBreakerTransition("half_open");
|
|
3509
|
-
}
|
|
3510
|
-
return false;
|
|
3511
|
-
}
|
|
3512
|
-
onProviderFailure(cls, now) {
|
|
3513
|
-
this.providerBreaker.consecutiveFailures += 1;
|
|
3514
|
-
const trip = cls === "auth_config" || // A failed half-open probe re-opens immediately (standard breaker
|
|
3515
|
-
// semantics). Without this, an auth_config-opened breaker (which trips
|
|
3516
|
-
// below the threshold) would get stuck half_open after a transient
|
|
3517
|
-
// probe failure and stop suppressing (cursor review).
|
|
3518
|
-
this.providerBreaker.state === "half_open" || this.providerBreaker.consecutiveFailures >= this.config.extractionBreakerFailureThreshold;
|
|
3519
|
-
if (!trip) return;
|
|
3520
|
-
const cooldown = cls === "auth_config" ? this.config.extractionBreakerAuthCooldownMs : this.config.extractionBreakerCooldownMs;
|
|
3521
|
-
this.providerBreaker.openUntilMs = now + Math.max(0, cooldown);
|
|
3522
|
-
this.providerBreaker.lastReason = cls;
|
|
3523
|
-
if (this.providerBreaker.state !== "open") {
|
|
3524
|
-
this.providerBreaker.state = "open";
|
|
3525
|
-
this.logBreakerTransition("open");
|
|
3526
|
-
}
|
|
3527
|
-
}
|
|
3528
|
-
resetProviderBreakerOnSuccess() {
|
|
3529
|
-
const wasDisturbed = this.providerBreaker.state !== "closed" || this.providerBreaker.consecutiveFailures > 0 || this.providerBreaker.openUntilMs > 0;
|
|
3530
|
-
if (!wasDisturbed) return;
|
|
3531
|
-
const wasOpen = this.providerBreaker.state !== "closed";
|
|
3532
|
-
this.providerBreaker.consecutiveFailures = 0;
|
|
3533
|
-
this.providerBreaker.openUntilMs = 0;
|
|
3534
|
-
this.providerBreaker.lastReason = "";
|
|
3535
|
-
this.providerBreaker.state = "closed";
|
|
3536
|
-
if (wasOpen) this.logBreakerTransition("closed");
|
|
3537
|
-
}
|
|
3538
|
-
/** Rebuild `meta.extractionRetryState` from the in-memory namespace mirror,
|
|
3539
|
-
* bounded to the newest entries, and prune the mirror to match. */
|
|
3540
|
-
persistRetryStateToMeta(namespace, meta) {
|
|
3541
|
-
const nsMap = this.extractionRetryState.get(namespace);
|
|
3542
|
-
const entries = nsMap ? Array.from(nsMap.entries()).map(([fingerprint, st]) => ({
|
|
3543
|
-
fingerprint,
|
|
3544
|
-
attempts: st.attempts,
|
|
3545
|
-
nextEligibleAt: new Date(st.nextEligibleAtMs).toISOString(),
|
|
3546
|
-
firstFailedAt: new Date(st.firstFailedAtMs).toISOString(),
|
|
3547
|
-
lastFailureClass: st.lastFailureClass
|
|
3548
|
-
})) : [];
|
|
3549
|
-
const capped = capExtractionRetryStateEntries(entries, EXTRACTION_RETRY_STATE_MAX_ENTRIES);
|
|
3550
|
-
meta.extractionRetryState = capped;
|
|
3551
|
-
if (nsMap && capped.length < nsMap.size) {
|
|
3552
|
-
const kept = new Set(capped.map((e) => e.fingerprint));
|
|
3553
|
-
for (const key of Array.from(nsMap.keys())) {
|
|
3554
|
-
if (!kept.has(key)) nsMap.delete(key);
|
|
3555
|
-
}
|
|
3556
|
-
}
|
|
3557
|
-
}
|
|
3558
|
-
/** Record an extraction failure into per-fingerprint backoff state + breaker,
|
|
3559
|
-
* persisting to namespace meta. Fail-open: never throws upward. */
|
|
3560
|
-
async recordExtractionFailure(storage, namespace, fingerprint, cls, meta, now) {
|
|
3561
|
-
try {
|
|
3562
|
-
this.hydrateRetryStateFromMeta(namespace, meta);
|
|
3563
|
-
const nsMap = this.extractionRetryState.get(namespace) ?? /* @__PURE__ */ new Map();
|
|
3564
|
-
const prev = nsMap.get(fingerprint);
|
|
3565
|
-
const attempts = (prev?.attempts ?? 0) + 1;
|
|
3566
|
-
const firstFailedAtMs = prev?.firstFailedAtMs ?? now;
|
|
3567
|
-
let nextEligibleAtMs;
|
|
3568
|
-
if (cls === "parse_empty" && attempts > this.config.extractionParseEmptyMaxAttempts) {
|
|
3569
|
-
nextEligibleAtMs = now + Math.max(0, this.config.extractionRetryMaxBackoffMs);
|
|
3570
|
-
} else {
|
|
3571
|
-
nextEligibleAtMs = computeExtractionRetryNextEligibleMs(
|
|
3572
|
-
attempts,
|
|
3573
|
-
this.config.extractionRetryScheduleMs,
|
|
3574
|
-
this.config.extractionRetryMaxBackoffMs,
|
|
3575
|
-
this.config.extractionRetryJitterRatio,
|
|
3576
|
-
now
|
|
3577
|
-
);
|
|
3578
|
-
}
|
|
3579
|
-
nsMap.set(fingerprint, { attempts, nextEligibleAtMs, firstFailedAtMs, lastFailureClass: cls });
|
|
3580
|
-
this.extractionRetryState.set(namespace, nsMap);
|
|
3581
|
-
this.onProviderFailure(cls, now);
|
|
3582
|
-
this.persistRetryStateToMeta(namespace, meta);
|
|
3583
|
-
await storage.saveMeta(meta);
|
|
3584
|
-
} catch (err) {
|
|
3585
|
-
log.warn("runExtraction: failed to record extraction retry state (non-fatal)", err);
|
|
3586
|
-
}
|
|
3587
|
-
}
|
|
3588
|
-
/** Delete a fingerprint's retry entry from the mirror + meta. Returns whether
|
|
3589
|
-
* meta changed (so the caller can decide to persist). Does not touch the
|
|
3590
|
-
* breaker — callers pair this with `resetProviderBreakerOnSuccess`. */
|
|
3591
|
-
clearExtractionRetryEntry(namespace, fingerprint, meta) {
|
|
3592
|
-
const nsMap = this.extractionRetryState.get(namespace);
|
|
3593
|
-
if (!nsMap?.has(fingerprint)) return false;
|
|
3594
|
-
nsMap.delete(fingerprint);
|
|
3595
|
-
this.persistRetryStateToMeta(namespace, meta);
|
|
3596
|
-
return true;
|
|
3597
|
-
}
|
|
3598
|
-
/** Live in-process resilience snapshot (breaker + backoff population). */
|
|
3599
|
-
getExtractionResilienceStatus() {
|
|
3600
|
-
let backoffFingerprintCount = 0;
|
|
3601
|
-
for (const nsMap of this.extractionRetryState.values()) {
|
|
3602
|
-
backoffFingerprintCount += nsMap.size;
|
|
3603
|
-
}
|
|
3604
|
-
return {
|
|
3605
|
-
breaker: {
|
|
3606
|
-
state: this.providerBreaker.state,
|
|
3607
|
-
openUntilMs: this.providerBreaker.openUntilMs,
|
|
3608
|
-
consecutiveFailures: this.providerBreaker.consecutiveFailures,
|
|
3609
|
-
lastReason: this.providerBreaker.lastReason
|
|
3610
|
-
},
|
|
3611
|
-
backoffFingerprintCount
|
|
3612
|
-
};
|
|
3613
|
-
}
|
|
3614
|
-
// -------------------------------------------------------------------------
|
|
3615
|
-
// Main extraction pipeline
|
|
3616
|
-
// -------------------------------------------------------------------------
|
|
3617
|
-
async runExtraction(turns, options = {}) {
|
|
3618
|
-
log.debug(`running extraction on ${turns.length} turns`);
|
|
3619
|
-
const clearBufferAfterExtraction = options.clearBufferAfterExtraction ?? true;
|
|
3620
|
-
const skipCharThreshold = options.skipCharThreshold ?? false;
|
|
3621
|
-
const skipUserTurnThreshold = options.skipUserTurnThreshold ?? false;
|
|
3622
|
-
const deadlineMs = typeof options.deadlineMs === "number" && Number.isFinite(options.deadlineMs) ? options.deadlineMs : void 0;
|
|
3623
|
-
const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? "default";
|
|
3624
|
-
const throwIfDeadlineExceeded = (stage) => {
|
|
3625
|
-
if (typeof deadlineMs === "number" && Date.now() > deadlineMs) {
|
|
3626
|
-
throw new Error(`replay extraction deadline exceeded (${stage})`);
|
|
3627
|
-
}
|
|
3628
|
-
};
|
|
3629
|
-
const throwIfAborted2 = (stage) => {
|
|
3630
|
-
throwIfRecallAborted(options.abortSignal, `extraction aborted (${stage})`);
|
|
3631
|
-
};
|
|
3632
|
-
const clearBuffer = async (options2) => {
|
|
3633
|
-
if (options2?.ignoreAbort !== true) {
|
|
3634
|
-
throwIfAborted2("before_clear_buffer");
|
|
3635
|
-
}
|
|
3636
|
-
if (clearBufferAfterExtraction) {
|
|
3637
|
-
await this.deps.getBuffer().clearAfterExtraction(bufferKey, turns);
|
|
3638
|
-
}
|
|
3639
|
-
};
|
|
3640
|
-
const sessionKey = turns[0]?.sessionKey ?? "";
|
|
3641
|
-
if (sessionKey.includes(":cron:")) {
|
|
3642
|
-
log.debug(`skipping extraction for cron session: ${sessionKey}`);
|
|
3643
|
-
await clearBuffer();
|
|
3644
|
-
return {
|
|
3645
|
-
status: "skipped",
|
|
3646
|
-
reason: "cron_session",
|
|
3647
|
-
persistedCount: 0,
|
|
3648
|
-
durableOutputCount: 0
|
|
3649
|
-
};
|
|
3650
|
-
}
|
|
3651
|
-
const normalizedTurns = turns.filter((t) => (t.role === "user" || t.role === "assistant") && typeof t.content === "string").map((t) => ({
|
|
3652
|
-
...t,
|
|
3653
|
-
content: t.content.trim().slice(0, this.config.extractionMaxTurnChars)
|
|
3654
|
-
})).filter((t) => t.content.length > 0);
|
|
3655
|
-
const targetTurns = normalizedTurns.filter((turn) => turn.extractionContextOnly !== true);
|
|
3656
|
-
if (targetTurns.length === 0) {
|
|
3657
|
-
log.debug("skipping extraction: no non-context turns after normalization");
|
|
3658
|
-
if (normalizedTurns.length > 0) {
|
|
3659
|
-
await this.deps.maybeCapturePassiveCorrections(normalizedTurns, {
|
|
3660
|
-
sessionKey,
|
|
3661
|
-
principal: resolvePrincipal(sessionKey, this.config),
|
|
3662
|
-
namespace: this.deps.resolveSelfNamespace(sessionKey),
|
|
3663
|
-
bufferKey,
|
|
3664
|
-
isLiveSession: clearBufferAfterExtraction
|
|
3665
|
-
});
|
|
3666
|
-
}
|
|
3667
|
-
await clearBuffer();
|
|
3668
|
-
return { status: "skipped", reason: "empty_normalized_turns", persistedCount: 0, durableOutputCount: 0 };
|
|
3669
|
-
}
|
|
3670
|
-
const sourceValidAt = this.latestSourceValidAtFromTurns(targetTurns);
|
|
3671
|
-
throwIfDeadlineExceeded("before_extract");
|
|
3672
|
-
throwIfAborted2("before_extract");
|
|
3673
|
-
const userTurns = targetTurns.filter((t) => t.role === "user");
|
|
3674
|
-
const totalChars = targetTurns.reduce((sum, t) => sum + t.content.length, 0);
|
|
3675
|
-
const belowCharThreshold = totalChars < this.config.extractionMinChars;
|
|
3676
|
-
const belowUserTurnThreshold = !skipUserTurnThreshold && userTurns.length < this.config.extractionMinUserTurns;
|
|
3677
|
-
if (!skipCharThreshold && belowCharThreshold || belowUserTurnThreshold) {
|
|
3678
|
-
log.debug(`skipping extraction: below threshold (totalChars=${totalChars}, userTurns=${userTurns.length})`);
|
|
3679
|
-
await clearBuffer();
|
|
3680
|
-
{
|
|
3681
|
-
const capturePrincipal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
|
|
3682
|
-
const captureWO = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : void 0;
|
|
3683
|
-
const captureCodingCtx = sessionKey ? this.deps.getCodingContextForSession(sessionKey) : null;
|
|
3684
|
-
const captureCodingOv = resolveCodingNamespaceOverlay(
|
|
3685
|
-
captureCodingCtx,
|
|
3686
|
-
this.config.codingMode,
|
|
3687
|
-
this.config.defaultNamespace
|
|
3688
|
-
);
|
|
3689
|
-
const captureScopePlan = resolveScopeProfilePlan({
|
|
3690
|
-
config: this.config,
|
|
3691
|
-
principal: capturePrincipal,
|
|
3692
|
-
codingContext: captureCodingCtx,
|
|
3693
|
-
codingOverlay: captureCodingOv
|
|
3694
|
-
});
|
|
3695
|
-
const captureNamespace = captureWO ?? captureScopePlan?.writeNamespace ?? this.deps.resolveSelfNamespace(sessionKey);
|
|
3696
|
-
await this.deps.maybeCapturePassiveCorrections(normalizedTurns, {
|
|
3697
|
-
sessionKey,
|
|
3698
|
-
principal: capturePrincipal,
|
|
3699
|
-
namespace: captureNamespace,
|
|
3700
|
-
bufferKey,
|
|
3701
|
-
isLiveSession: clearBufferAfterExtraction
|
|
3702
|
-
});
|
|
3703
|
-
}
|
|
3704
|
-
return {
|
|
3705
|
-
status: "skipped",
|
|
3706
|
-
reason: "below_threshold",
|
|
3707
|
-
persistedCount: 0,
|
|
3708
|
-
durableOutputCount: 0
|
|
3709
|
-
};
|
|
3710
|
-
}
|
|
3711
|
-
const principal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
|
|
3712
|
-
const explicitWriteNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : void 0;
|
|
3713
|
-
const codingContextForWrite = sessionKey ? this.deps.getCodingContextForSession(sessionKey) : null;
|
|
3714
|
-
const codingOverlayForWrite = resolveCodingNamespaceOverlay(
|
|
3715
|
-
codingContextForWrite,
|
|
3716
|
-
this.config.codingMode,
|
|
3717
|
-
this.config.defaultNamespace
|
|
3718
|
-
);
|
|
3719
|
-
const scopeProfileGatePlan = resolveScopeProfilePlan({
|
|
3720
|
-
config: this.config,
|
|
3721
|
-
principal,
|
|
3722
|
-
codingContext: codingContextForWrite,
|
|
3723
|
-
codingOverlay: codingOverlayForWrite
|
|
3724
|
-
});
|
|
3725
|
-
const scopeProfileWritePlan = explicitWriteNamespace ? null : scopeProfileGatePlan;
|
|
3726
|
-
if (scopeProfileWritePlan) {
|
|
3727
|
-
const selectedLayer = scopeProfileWritePlan.layers.find((layer) => layer.id === scopeProfileWritePlan.writeLayer);
|
|
3728
|
-
const writeNamespaceReadable = scopeProfileWritePlan.readNamespaces.includes(
|
|
3729
|
-
scopeProfileWritePlan.writeNamespace
|
|
3730
|
-
);
|
|
3731
|
-
if (!selectedLayer?.writable || !writeNamespaceReadable) {
|
|
3732
|
-
log.warn(
|
|
3733
|
-
`runExtraction: skipping scope profile ${scopeProfileWritePlan.profileId} because write layer ${scopeProfileWritePlan.writeLayer} is not writable inside the profile read stack`
|
|
3734
|
-
);
|
|
3735
|
-
await clearBuffer();
|
|
3736
|
-
return {
|
|
3737
|
-
status: "skipped",
|
|
3738
|
-
reason: "scope_profile_no_writable_layer",
|
|
3739
|
-
persistedCount: 0,
|
|
3740
|
-
durableOutputCount: 0
|
|
3741
|
-
};
|
|
3742
|
-
}
|
|
3743
|
-
}
|
|
3744
|
-
const selfNamespace = explicitWriteNamespace ?? scopeProfileWritePlan?.writeNamespace ?? this.deps.applyCodingNamespaceOverlay(sessionKey, defaultNamespaceForPrincipal(principal, this.config));
|
|
3745
|
-
const storage = await this.deps.getStorageRouter().storageFor(selfNamespace);
|
|
3746
|
-
const shouldPersistProcessedFingerprint = targetTurns.some((turn) => turn.persistProcessedFingerprint === true);
|
|
3747
|
-
const extractionFingerprint = this.buildExtractionFingerprint(targetTurns, bufferKey);
|
|
3748
|
-
let meta = extractionFingerprint && shouldPersistProcessedFingerprint ? await storage.loadMeta() : null;
|
|
3749
|
-
if (extractionFingerprint && shouldPersistProcessedFingerprint && (meta?.processedExtractionFingerprints ?? []).some((entry) => entry.fingerprint === extractionFingerprint)) {
|
|
3750
|
-
log.debug(`runExtraction: skipping already-processed extraction fingerprint for ${bufferKey}`);
|
|
3751
|
-
await clearBuffer();
|
|
3752
|
-
return {
|
|
3753
|
-
status: "skipped",
|
|
3754
|
-
reason: "processed_fingerprint",
|
|
3755
|
-
persistedCount: 0,
|
|
3756
|
-
durableOutputCount: 0
|
|
3757
|
-
};
|
|
3758
|
-
}
|
|
3759
|
-
const forcedExtractionAttempt = options.failOnExtractionFailure === true || options.forceExtractionAttempt === true;
|
|
3760
|
-
const extractionRetryEnabled = resolveMemoryLifecycleCapabilities(this.config).extractionRetry;
|
|
3761
|
-
if (extractionFingerprint && !forcedExtractionAttempt && extractionRetryEnabled) {
|
|
3762
|
-
try {
|
|
3763
|
-
meta ??= await storage.loadMeta();
|
|
3764
|
-
this.hydrateRetryStateFromMeta(selfNamespace, meta);
|
|
3765
|
-
const nowMs = Date.now();
|
|
3766
|
-
let suppressReason = null;
|
|
3767
|
-
if (this.isProviderBreakerOpen(nowMs)) {
|
|
3768
|
-
suppressReason = "provider_circuit_open";
|
|
3769
|
-
} else {
|
|
3770
|
-
const st = this.extractionRetryState.get(selfNamespace)?.get(extractionFingerprint);
|
|
3771
|
-
if (st && nowMs < st.nextEligibleAtMs) suppressReason = "extraction_backoff";
|
|
3772
|
-
}
|
|
3773
|
-
if (suppressReason) {
|
|
3774
|
-
try {
|
|
3775
|
-
await this.deps.maybeCapturePassiveCorrections(normalizedTurns, {
|
|
3776
|
-
sessionKey,
|
|
3777
|
-
principal,
|
|
3778
|
-
namespace: selfNamespace,
|
|
3779
|
-
bufferKey,
|
|
3780
|
-
isLiveSession: clearBufferAfterExtraction
|
|
3781
|
-
});
|
|
3782
|
-
} catch (captureErr) {
|
|
3783
|
-
log.warn("runExtraction: passive correction capture failed on suppressed attempt (non-fatal)", captureErr);
|
|
3784
|
-
}
|
|
3785
|
-
return { status: "skipped", reason: suppressReason, persistedCount: 0, durableOutputCount: 0 };
|
|
3786
|
-
}
|
|
3787
|
-
} catch (err) {
|
|
3788
|
-
log.warn("runExtraction: extraction retry gate check failed; proceeding (fail-open)", err);
|
|
3789
|
-
}
|
|
3790
|
-
}
|
|
3791
|
-
const existingEntities = await storage.listEntityNames();
|
|
3792
|
-
const result = await raceRecallAbort(
|
|
3793
|
-
this.deps.getExtraction().extract(normalizedTurns, existingEntities),
|
|
3794
|
-
options.abortSignal,
|
|
3795
|
-
"extraction aborted (during_extract)"
|
|
3796
|
-
);
|
|
3797
|
-
throwIfDeadlineExceeded("before_persist");
|
|
3798
|
-
throwIfAborted2("before_persist");
|
|
3799
|
-
if (!result) {
|
|
3800
|
-
log.warn("runExtraction: extraction returned null/undefined");
|
|
3801
|
-
if (options.failOnExtractionFailure) {
|
|
3802
|
-
throw new Error("extraction failed: invalid_extraction_result");
|
|
3803
|
-
}
|
|
3804
|
-
await clearBuffer();
|
|
3805
|
-
return {
|
|
3806
|
-
status: "skipped",
|
|
3807
|
-
reason: "invalid_extraction_result",
|
|
3808
|
-
persistedCount: 0,
|
|
3809
|
-
durableOutputCount: 0
|
|
3810
|
-
};
|
|
3811
|
-
}
|
|
3812
|
-
const invalidExtractionResultFields = [
|
|
3813
|
-
["facts", result.facts],
|
|
3814
|
-
["entities", result.entities],
|
|
3815
|
-
["questions", result.questions],
|
|
3816
|
-
["profileUpdates", result.profileUpdates]
|
|
3817
|
-
].filter(([, value]) => !Array.isArray(value)).map(([field]) => field);
|
|
3818
|
-
if (invalidExtractionResultFields.length > 0) {
|
|
3819
|
-
log.warn("runExtraction: extraction returned invalid collection fields", {
|
|
3820
|
-
invalidFields: invalidExtractionResultFields,
|
|
3821
|
-
resultKeys: typeof result === "object" && result !== null ? Object.keys(result) : []
|
|
3822
|
-
});
|
|
3823
|
-
if (options.failOnExtractionFailure) {
|
|
3824
|
-
throw new Error("extraction failed: invalid_extraction_result");
|
|
3825
|
-
}
|
|
3826
|
-
await clearBuffer();
|
|
3827
|
-
return {
|
|
3828
|
-
status: "skipped",
|
|
3829
|
-
reason: "invalid_extraction_result",
|
|
3830
|
-
persistedCount: 0,
|
|
3831
|
-
durableOutputCount: 0
|
|
3832
|
-
};
|
|
3833
|
-
}
|
|
3834
|
-
const extractionFailure = typeof result.extractionFailure === "string" && result.extractionFailure.trim().length > 0 ? result.extractionFailure : void 0;
|
|
3835
|
-
let recordedRetryFailure = false;
|
|
3836
|
-
if (extractionFingerprint && extractionRetryEnabled) {
|
|
3837
|
-
if (extractionFailure) {
|
|
3838
|
-
try {
|
|
3839
|
-
meta ??= await storage.loadMeta();
|
|
3840
|
-
await this.recordExtractionFailure(
|
|
3841
|
-
storage,
|
|
3842
|
-
selfNamespace,
|
|
3843
|
-
extractionFingerprint,
|
|
3844
|
-
result.extractionFailureClass ?? "provider_retryable",
|
|
3845
|
-
meta,
|
|
3846
|
-
Date.now()
|
|
3847
|
-
);
|
|
3848
|
-
recordedRetryFailure = true;
|
|
3849
|
-
} catch (err) {
|
|
3850
|
-
log.warn("runExtraction: failed to load meta for retry bookkeeping (non-fatal)", err);
|
|
3851
|
-
}
|
|
3852
|
-
} else {
|
|
3853
|
-
this.resetProviderBreakerOnSuccess();
|
|
3854
|
-
try {
|
|
3855
|
-
meta ??= await storage.loadMeta();
|
|
3856
|
-
this.hydrateRetryStateFromMeta(selfNamespace, meta);
|
|
3857
|
-
if (this.clearExtractionRetryEntry(selfNamespace, extractionFingerprint, meta)) {
|
|
3858
|
-
await storage.saveMeta(meta);
|
|
3859
|
-
}
|
|
3860
|
-
} catch (err) {
|
|
3861
|
-
log.warn("runExtraction: failed to persist cleared retry state (non-fatal)", err);
|
|
3862
|
-
}
|
|
3863
|
-
}
|
|
3864
|
-
}
|
|
3865
|
-
if (options.failOnExtractionFailure && extractionFailure) {
|
|
3866
|
-
throw new Error(`extraction failed: ${extractionFailure}`);
|
|
3867
|
-
}
|
|
3868
|
-
if (result.facts.length === 0 && result.entities.length === 0 && result.questions.length === 0 && result.profileUpdates.length === 0) {
|
|
3869
|
-
log.debug("runExtraction: extraction produced no durable outputs; skipping persistence");
|
|
3870
|
-
if (extractionFailure) {
|
|
3871
|
-
log.warn(
|
|
3872
|
-
"runExtraction: extraction reported failure with no durable outputs; not marking fingerprint processed",
|
|
3873
|
-
{ extractionFailure }
|
|
3874
|
-
);
|
|
3875
|
-
}
|
|
3876
|
-
if (extractionFingerprint && shouldPersistProcessedFingerprint && !extractionFailure) {
|
|
3877
|
-
meta ??= await storage.loadMeta();
|
|
3878
|
-
await this.deps.recordProcessedExtractionFingerprint(storage, extractionFingerprint, meta);
|
|
3879
|
-
meta.extractionCount += 1;
|
|
3880
|
-
meta.lastExtractionAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3881
|
-
await storage.saveMeta(meta);
|
|
3882
|
-
}
|
|
3883
|
-
await this.deps.maybeCapturePassiveCorrections(normalizedTurns, {
|
|
3884
|
-
sessionKey,
|
|
3885
|
-
principal,
|
|
3886
|
-
namespace: selfNamespace,
|
|
3887
|
-
bufferKey,
|
|
3888
|
-
isLiveSession: clearBufferAfterExtraction
|
|
3889
|
-
});
|
|
3890
|
-
if (recordedRetryFailure) {
|
|
3891
|
-
log.debug("runExtraction: retaining buffer for backoff retry after failure");
|
|
3892
|
-
} else {
|
|
3893
|
-
await clearBuffer();
|
|
3894
|
-
}
|
|
3895
|
-
return { status: "skipped", reason: "empty_extraction_result", persistedCount: 0, durableOutputCount: 0 };
|
|
3896
|
-
}
|
|
3897
|
-
let threadIdForExtraction = null;
|
|
3898
|
-
if (resolvePresentationCapabilities(this.config).threading && turns.length > 0) {
|
|
3899
|
-
const lastTurn = turns[turns.length - 1];
|
|
3900
|
-
try {
|
|
3901
|
-
threadIdForExtraction = await this.deps.getThreading().processTurn(lastTurn, []);
|
|
3902
|
-
} catch (err) {
|
|
3903
|
-
log.warn("[threading] processTurn failed before persistence (non-fatal)", err);
|
|
3904
|
-
}
|
|
3905
|
-
}
|
|
3906
|
-
const { persistedIds } = await this.deps.persistExtraction(
|
|
3907
|
-
result,
|
|
3908
|
-
storage,
|
|
3909
|
-
threadIdForExtraction,
|
|
3910
|
-
{ sessionKey, principal, validAt: sourceValidAt, sourceConnector: deriveSourceConnector(targetTurns) },
|
|
3911
|
-
// Pass the KNOWN base namespace (NHIdx) so the catalog write touch records the
|
|
3912
|
-
// real namespace rather than a guess decoded from the storage dir.
|
|
3913
|
-
selfNamespace,
|
|
3914
|
-
scopeProfileGatePlan,
|
|
3915
|
-
// Verbatim source turns for the faithfulness gate (#1576) so it can
|
|
3916
|
-
// locate a quote per fact when #1575 spans are absent.
|
|
3917
|
-
normalizedTurns.map((t) => t.content).join("\n\n")
|
|
3918
|
-
);
|
|
3919
|
-
let postPersistMetadataFailed = false;
|
|
3920
|
-
meta ??= await storage.loadMeta();
|
|
3921
|
-
if (extractionFingerprint && shouldPersistProcessedFingerprint) {
|
|
3922
|
-
try {
|
|
3923
|
-
await this.deps.recordProcessedExtractionFingerprint(storage, extractionFingerprint, meta);
|
|
3924
|
-
} catch (error) {
|
|
3925
|
-
log.warn(
|
|
3926
|
-
"runExtraction: failed to persist processed extraction fingerprint; continuing with buffer clear",
|
|
3927
|
-
error
|
|
3928
|
-
);
|
|
3929
|
-
postPersistMetadataFailed = true;
|
|
3930
|
-
}
|
|
3931
|
-
}
|
|
3932
|
-
meta.extractionCount += 1;
|
|
3933
|
-
meta.lastExtractionAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3934
|
-
meta.totalMemories += Array.isArray(result?.facts) ? result.facts.length : 0;
|
|
3935
|
-
meta.totalEntities += Array.isArray(result?.entities) ? result.entities.length : 0;
|
|
3936
|
-
try {
|
|
3937
|
-
await storage.saveMeta(meta);
|
|
3938
|
-
} catch (error) {
|
|
3939
|
-
log.warn(
|
|
3940
|
-
"runExtraction: failed to save extraction metadata after durable persistence; continuing with buffer clear",
|
|
3941
|
-
error
|
|
3942
|
-
);
|
|
3943
|
-
postPersistMetadataFailed = true;
|
|
3944
|
-
}
|
|
3945
|
-
const durableOutputCount = result.facts.length + result.entities.length + result.questions.length + result.profileUpdates.length;
|
|
3946
|
-
try {
|
|
3947
|
-
if (clearBufferAfterExtraction && !this.config.extractionJudgeShadow) {
|
|
3948
|
-
const deferredCount = this.deps.getLastPersistExtractionDeferredCount();
|
|
3949
|
-
if (deferredCount > 0 && normalizedTurns.length > 0) {
|
|
3950
|
-
await this.deps.getBuffer().retainDeferredTurns(bufferKey, normalizedTurns, 10);
|
|
3951
|
-
} else {
|
|
3952
|
-
await this.deps.getBuffer().retainDeferredTurns(bufferKey, [], 0);
|
|
3953
|
-
}
|
|
3954
|
-
}
|
|
3955
|
-
} catch (err) {
|
|
3956
|
-
log.debug(
|
|
3957
|
-
`extraction-judge: defer retention failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
|
|
3958
|
-
);
|
|
3959
|
-
}
|
|
3960
|
-
await clearBuffer({ ignoreAbort: true });
|
|
3961
|
-
await this.deps.maybeCapturePassiveCorrections(normalizedTurns, {
|
|
3962
|
-
sessionKey,
|
|
3963
|
-
principal,
|
|
3964
|
-
namespace: selfNamespace,
|
|
3965
|
-
bufferKey,
|
|
3966
|
-
isLiveSession: clearBufferAfterExtraction
|
|
3967
|
-
});
|
|
3968
|
-
if (resolvePresentationCapabilities(this.config).memoryBoxes && persistedIds.length > 0) {
|
|
3969
|
-
const extractionTopics = deriveTopicsFromExtraction(result);
|
|
3970
|
-
const firstUserTurn = turns.find((t) => t.role === "user");
|
|
3971
|
-
const boxGoal = firstUserTurn?.content?.slice(0, 100)?.trim() || void 0;
|
|
3972
|
-
await this.deps.boxBuilderFor(storage).onExtraction({
|
|
3973
|
-
topics: extractionTopics,
|
|
3974
|
-
memoryIds: persistedIds,
|
|
3975
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3976
|
-
goal: boxGoal
|
|
3977
|
-
}).catch((err) => log.warn("[boxes] onExtraction failed (non-fatal)", err));
|
|
3978
|
-
}
|
|
3979
|
-
if (resolvePresentationCapabilities(this.config).threading && threadIdForExtraction && persistedIds.length > 0) {
|
|
3980
|
-
await this.deps.appendPersistedThreadEpisodes(threadIdForExtraction, persistedIds);
|
|
3981
|
-
}
|
|
3982
|
-
if (resolvePresentationCapabilities(this.config).threading && threadIdForExtraction) {
|
|
3983
|
-
const conversationContent = turns.map((t) => t.content).join(" ");
|
|
3984
|
-
try {
|
|
3985
|
-
await this.deps.getThreading().updateThreadTitle(threadIdForExtraction, conversationContent);
|
|
3986
|
-
} catch (err) {
|
|
3987
|
-
log.warn("[threading] updateThreadTitle failed after persistence (non-fatal)", err);
|
|
3988
|
-
}
|
|
3989
|
-
}
|
|
3990
|
-
const nonZeroExtraction = durableOutputCount > 0;
|
|
3991
|
-
try {
|
|
3992
|
-
this.deps.maybeScheduleConsolidation(nonZeroExtraction);
|
|
3993
|
-
} catch (err) {
|
|
3994
|
-
log.warn("runExtraction: consolidation scheduling failed after persistence (non-fatal)", err);
|
|
3995
|
-
}
|
|
3996
|
-
try {
|
|
3997
|
-
this.deps.requestQmdMaintenance();
|
|
3998
|
-
} catch (err) {
|
|
3999
|
-
log.warn("runExtraction: QMD maintenance scheduling failed after persistence (non-fatal)", err);
|
|
4000
|
-
}
|
|
4001
|
-
try {
|
|
4002
|
-
await this.deps.runTierMigrationCycle(storage, "extraction");
|
|
4003
|
-
} catch (err) {
|
|
4004
|
-
log.warn("runExtraction: tier migration failed after persistence (non-fatal)", err);
|
|
2753
|
+
log.warn(
|
|
2754
|
+
`contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`
|
|
2755
|
+
);
|
|
4005
2756
|
}
|
|
4006
|
-
return {
|
|
4007
|
-
status: "completed",
|
|
4008
|
-
persistedCount: persistedIds.length,
|
|
4009
|
-
durableOutputCount,
|
|
4010
|
-
postPersistMetadataFailed
|
|
4011
|
-
};
|
|
4012
2757
|
}
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
2758
|
+
// ---------------------------------------------------------------------------
|
|
2759
|
+
// Memory Linking (Phase 3A)
|
|
2760
|
+
// ---------------------------------------------------------------------------
|
|
2761
|
+
/**
|
|
2762
|
+
* Suggest links for a new memory based on similar existing memories.
|
|
2763
|
+
*/
|
|
2764
|
+
async suggestLinksForMemory(content, category, namespaceScope) {
|
|
2765
|
+
if (!this.isSearchAvailable()) return [];
|
|
2766
|
+
const results = await this.searchAcrossNamespaces({
|
|
2767
|
+
query: content,
|
|
2768
|
+
namespaces: [namespaceScope],
|
|
2769
|
+
maxResults: 5,
|
|
2770
|
+
mode: "search"
|
|
2771
|
+
});
|
|
2772
|
+
if (results.length === 0) return [];
|
|
2773
|
+
const candidates = [];
|
|
2774
|
+
for (const result of results) {
|
|
2775
|
+
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
2776
|
+
if (!memoryId) continue;
|
|
2777
|
+
const resultNamespace = this.namespaceFromPath(result.path);
|
|
2778
|
+
if (resultNamespace !== namespaceScope) continue;
|
|
2779
|
+
const resultStorage = await this.storageForNamespace(resultNamespace);
|
|
2780
|
+
const memory = await resultStorage.getMemoryById(memoryId);
|
|
2781
|
+
if (memory && memory.frontmatter.status !== "superseded" && memory.frontmatter.status !== "forgotten") {
|
|
2782
|
+
candidates.push({
|
|
2783
|
+
id: memory.frontmatter.id,
|
|
2784
|
+
content: memory.content,
|
|
2785
|
+
category: memory.frontmatter.category
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
4023
2788
|
}
|
|
2789
|
+
if (candidates.length === 0) return [];
|
|
2790
|
+
const extraction = this.getExtraction();
|
|
2791
|
+
const suggestions = await extraction.suggestLinks(
|
|
2792
|
+
{ content, category },
|
|
2793
|
+
candidates
|
|
2794
|
+
);
|
|
2795
|
+
if (!suggestions || suggestions.links.length === 0) return [];
|
|
2796
|
+
return suggestions.links.map((link) => ({
|
|
2797
|
+
targetId: link.targetId,
|
|
2798
|
+
linkType: link.linkType,
|
|
2799
|
+
strength: link.strength,
|
|
2800
|
+
reason: link.reason || void 0
|
|
2801
|
+
}));
|
|
4024
2802
|
}
|
|
4025
|
-
|
|
4026
|
-
return connectors.size === 1 ? [...connectors][0] : void 0;
|
|
4027
|
-
}
|
|
2803
|
+
};
|
|
4028
2804
|
|
|
4029
2805
|
// src/orchestration/consolidation-run.ts
|
|
4030
|
-
import
|
|
2806
|
+
import path4 from "path";
|
|
4031
2807
|
import { mkdir as mkdir2, readFile, writeFile as writeFile2 } from "fs/promises";
|
|
4032
2808
|
var ConsolidationRunCoordinator = class {
|
|
4033
2809
|
constructor(deps) {
|
|
@@ -4258,7 +3034,7 @@ var ConsolidationRunCoordinator = class {
|
|
|
4258
3034
|
}
|
|
4259
3035
|
if (resolveConsolidationCapabilities(config).semanticConsolidation) {
|
|
4260
3036
|
try {
|
|
4261
|
-
const stateFilePath =
|
|
3037
|
+
const stateFilePath = path4.join(
|
|
4262
3038
|
config.memoryDir,
|
|
4263
3039
|
"state",
|
|
4264
3040
|
"semantic-consolidation-last-run.json"
|
|
@@ -4306,7 +3082,7 @@ var ConsolidationRunCoordinator = class {
|
|
|
4306
3082
|
);
|
|
4307
3083
|
}
|
|
4308
3084
|
if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
|
|
4309
|
-
const stateDir =
|
|
3085
|
+
const stateDir = path4.join(config.memoryDir, "state");
|
|
4310
3086
|
await mkdir2(stateDir, { recursive: true });
|
|
4311
3087
|
await writeFile2(
|
|
4312
3088
|
stateFilePath,
|
|
@@ -6229,14 +5005,14 @@ var ExtractionPersistCoordinator = class {
|
|
|
6229
5005
|
};
|
|
6230
5006
|
|
|
6231
5007
|
// src/orchestration/recall-internal.ts
|
|
6232
|
-
import { createHash as
|
|
5008
|
+
import { createHash as createHash3 } from "crypto";
|
|
6233
5009
|
import { readFile as readFile2, stat, unlink } from "fs/promises";
|
|
6234
|
-
import
|
|
5010
|
+
import path7 from "path";
|
|
6235
5011
|
|
|
6236
5012
|
// src/orchestration/graph-recall-coordinator.ts
|
|
6237
|
-
import { createHash as
|
|
5013
|
+
import { createHash as createHash2 } from "crypto";
|
|
6238
5014
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
6239
|
-
import
|
|
5015
|
+
import path5 from "path";
|
|
6240
5016
|
function mergeGraphExpandedResults(primary, expanded) {
|
|
6241
5017
|
const mergedByNamespaceAndPath = /* @__PURE__ */ new Map();
|
|
6242
5018
|
for (const item of [...primary, ...expanded]) {
|
|
@@ -6253,11 +5029,11 @@ function mergeGraphExpandedResults(primary, expanded) {
|
|
|
6253
5029
|
return Array.from(mergedByNamespaceAndPath.values());
|
|
6254
5030
|
}
|
|
6255
5031
|
function graphPathRelativeToStorage(storageDir, candidatePath) {
|
|
6256
|
-
const absolutePath =
|
|
6257
|
-
const rel =
|
|
5032
|
+
const absolutePath = path5.isAbsolute(candidatePath) ? candidatePath : path5.resolve(storageDir, candidatePath);
|
|
5033
|
+
const rel = path5.relative(storageDir, absolutePath);
|
|
6258
5034
|
if (!rel || rel === ".") return null;
|
|
6259
5035
|
if (rel.startsWith("..")) return null;
|
|
6260
|
-
return rel.split(
|
|
5036
|
+
return rel.split(path5.sep).join("/");
|
|
6261
5037
|
}
|
|
6262
5038
|
function normalizeGraphActivationScore(score) {
|
|
6263
5039
|
const bounded = Number.isFinite(score) && score > 0 ? score : 0;
|
|
@@ -6328,7 +5104,7 @@ var GraphRecallCoordinator = class {
|
|
|
6328
5104
|
resolvedPath = resolvedCold.result.path;
|
|
6329
5105
|
resolvedResult = resolvedCold.result;
|
|
6330
5106
|
}
|
|
6331
|
-
if (!
|
|
5107
|
+
if (!path5.isAbsolute(resolvedPath)) {
|
|
6332
5108
|
resolvedAmbiguousSeeds.set(result.path, null);
|
|
6333
5109
|
return null;
|
|
6334
5110
|
}
|
|
@@ -6353,7 +5129,7 @@ var GraphRecallCoordinator = class {
|
|
|
6353
5129
|
}
|
|
6354
5130
|
continue;
|
|
6355
5131
|
}
|
|
6356
|
-
if (
|
|
5132
|
+
if (path5.isAbsolute(result.path)) {
|
|
6357
5133
|
const resolved = await resolveAmbiguousSeedOwner(result, null);
|
|
6358
5134
|
if (resolved) {
|
|
6359
5135
|
addResultForNamespace(resolved.namespace, resolved.result);
|
|
@@ -6396,7 +5172,7 @@ var GraphRecallCoordinator = class {
|
|
|
6396
5172
|
0
|
|
6397
5173
|
);
|
|
6398
5174
|
seedPaths.push(
|
|
6399
|
-
...seedRelativePaths.map((rel) =>
|
|
5175
|
+
...seedRelativePaths.map((rel) => path5.join(storage.dir, rel))
|
|
6400
5176
|
);
|
|
6401
5177
|
const seedSet = new Set(seedRelativePaths);
|
|
6402
5178
|
const expanded = await this.graphIndexFor(storage).spreadingActivation(
|
|
@@ -6412,7 +5188,7 @@ var GraphRecallCoordinator = class {
|
|
|
6412
5188
|
for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
|
|
6413
5189
|
if (deadlineExpired()) break;
|
|
6414
5190
|
if (seedSet.has(candidate.path)) continue;
|
|
6415
|
-
const memoryPath =
|
|
5191
|
+
const memoryPath = path5.resolve(storage.dir, candidate.path);
|
|
6416
5192
|
const memory = await storage.readMemoryByPath(memoryPath);
|
|
6417
5193
|
if (deadlineExpired()) break;
|
|
6418
5194
|
if (!memory) continue;
|
|
@@ -6440,7 +5216,7 @@ var GraphRecallCoordinator = class {
|
|
|
6440
5216
|
path: memory.path,
|
|
6441
5217
|
score,
|
|
6442
5218
|
namespace,
|
|
6443
|
-
seed:
|
|
5219
|
+
seed: path5.resolve(storage.dir, candidate.seed),
|
|
6444
5220
|
hopDepth: candidate.hopDepth,
|
|
6445
5221
|
decayedWeight: candidate.decayedWeight,
|
|
6446
5222
|
graphType: candidate.graphType,
|
|
@@ -6464,12 +5240,12 @@ var GraphRecallCoordinator = class {
|
|
|
6464
5240
|
}
|
|
6465
5241
|
async recordLastGraphRecallSnapshot(options) {
|
|
6466
5242
|
try {
|
|
6467
|
-
const snapshotPath =
|
|
5243
|
+
const snapshotPath = path5.join(
|
|
6468
5244
|
options.storage.dir,
|
|
6469
5245
|
"state",
|
|
6470
5246
|
"last_graph_recall.json"
|
|
6471
5247
|
);
|
|
6472
|
-
await mkdir3(
|
|
5248
|
+
await mkdir3(path5.dirname(snapshotPath), { recursive: true });
|
|
6473
5249
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6474
5250
|
const totalSeedCount = options.seedPaths.length;
|
|
6475
5251
|
const totalExpandedCount = options.expandedPaths.length;
|
|
@@ -6481,7 +5257,7 @@ var GraphRecallCoordinator = class {
|
|
|
6481
5257
|
const payload = {
|
|
6482
5258
|
recordedAt: now,
|
|
6483
5259
|
mode: options.recallMode,
|
|
6484
|
-
queryHash:
|
|
5260
|
+
queryHash: createHash2("sha256").update(options.prompt).digest("hex"),
|
|
6485
5261
|
queryLength: options.prompt.length,
|
|
6486
5262
|
namespaces: options.recallNamespaces,
|
|
6487
5263
|
seedCount: totalSeedCount,
|
|
@@ -6584,7 +5360,7 @@ ${blocks.join("\n\n")}`;
|
|
|
6584
5360
|
}
|
|
6585
5361
|
|
|
6586
5362
|
// src/orchestration/generic-recall-paths.ts
|
|
6587
|
-
import
|
|
5363
|
+
import path6 from "path";
|
|
6588
5364
|
var CATEGORY_MEMORY_ROOTS = Object.fromEntries(
|
|
6589
5365
|
ALL_CATEGORY_DIRS.map((directory) => [directory, true])
|
|
6590
5366
|
);
|
|
@@ -6609,7 +5385,7 @@ function normalizeQmdUriPath(relativePath, source) {
|
|
|
6609
5385
|
}
|
|
6610
5386
|
}
|
|
6611
5387
|
function stripQmdCollectionPrefix(relativePath, policy, source) {
|
|
6612
|
-
const normalized =
|
|
5388
|
+
const normalized = path6.posix.normalize(normalizeQmdUriPath(relativePath, source).replace(/\\/g, "/"));
|
|
6613
5389
|
const slashIndex = normalized.indexOf("/");
|
|
6614
5390
|
if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return normalized;
|
|
6615
5391
|
const prefix = normalized.slice(0, slashIndex);
|
|
@@ -6618,8 +5394,8 @@ function stripQmdCollectionPrefix(relativePath, policy, source) {
|
|
|
6618
5394
|
return matchesHotCollection || matchesColdCollection ? normalized.slice(slashIndex + 1) : normalized;
|
|
6619
5395
|
}
|
|
6620
5396
|
function isTopLevelArchivePath(filePath, policy = {}, source = "filesystem") {
|
|
6621
|
-
const isAbsolutePath =
|
|
6622
|
-
const relative = policy.memoryDir && isAbsolutePath ?
|
|
5397
|
+
const isAbsolutePath = path6.isAbsolute(filePath);
|
|
5398
|
+
const relative = policy.memoryDir && isAbsolutePath ? path6.relative(policy.memoryDir, path6.resolve(filePath)) : filePath;
|
|
6623
5399
|
const normalized = !isAbsolutePath ? stripQmdCollectionPrefix(relative, policy, source) : relative;
|
|
6624
5400
|
return /^(?:archive|namespaces[\\/][^\\/]+[\\/]archive)(?:[\\/]|$)/i.test(normalized);
|
|
6625
5401
|
}
|
|
@@ -6705,8 +5481,8 @@ var RecallInternalCoordinator = class {
|
|
|
6705
5481
|
timings,
|
|
6706
5482
|
logger: log
|
|
6707
5483
|
});
|
|
6708
|
-
const promptHash =
|
|
6709
|
-
const traceId =
|
|
5484
|
+
const promptHash = createHash3("sha256").update(prompt).digest("hex");
|
|
5485
|
+
const traceId = createHash3("sha256").update(`${sessionKey ?? "default"}:${recallStart}:${promptHash}`).digest("hex").slice(0, 16);
|
|
6710
5486
|
const sectionBuckets = /* @__PURE__ */ new Map();
|
|
6711
5487
|
const queryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {
|
|
6712
5488
|
cronRecallPolicyEnabled: resolveRecallAuxiliaryCapabilities(this.deps.config).cronRecallPolicy,
|
|
@@ -6715,7 +5491,7 @@ var RecallInternalCoordinator = class {
|
|
|
6715
5491
|
cronConversationRecallMode: this.deps.config.cronConversationRecallMode
|
|
6716
5492
|
});
|
|
6717
5493
|
const retrievalQuery = queryPolicy.retrievalQuery || prompt;
|
|
6718
|
-
const retrievalQueryHash =
|
|
5494
|
+
const retrievalQueryHash = createHash3("sha256").update(retrievalQuery).digest("hex");
|
|
6719
5495
|
const policyVersion = this.deps.currentPolicyVersion();
|
|
6720
5496
|
let recallSource = "none";
|
|
6721
5497
|
let recalledMemoryCount = 0;
|
|
@@ -6855,7 +5631,7 @@ var RecallInternalCoordinator = class {
|
|
|
6855
5631
|
const graphExpandedResultPaths = /* @__PURE__ */ new Set();
|
|
6856
5632
|
const graphSourceLabelsForPath = (resultPath) => {
|
|
6857
5633
|
const labels = [];
|
|
6858
|
-
const normalizedPath = resultPath.split(
|
|
5634
|
+
const normalizedPath = resultPath.split(path7.sep).join("/");
|
|
6859
5635
|
const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
|
|
6860
5636
|
if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
|
|
6861
5637
|
if (graphExpandedResultPaths.has(resultPath))
|
|
@@ -7016,7 +5792,7 @@ var RecallInternalCoordinator = class {
|
|
|
7016
5792
|
profileStorageNamespaces.map((namespace) => this.deps.storageRouter.storageFor(namespace))
|
|
7017
5793
|
);
|
|
7018
5794
|
const emptyProfileStorage = new Proxy(
|
|
7019
|
-
{ dir:
|
|
5795
|
+
{ dir: path7.join(this.deps.config.memoryDir, ".empty-scope-profile") },
|
|
7020
5796
|
{
|
|
7021
5797
|
get(target, prop) {
|
|
7022
5798
|
if (prop in target) return target[prop];
|
|
@@ -8498,11 +7274,11 @@ ${formatted}`;
|
|
|
8498
7274
|
if (!resolveRecallAuxiliaryCapabilities(this.deps.config).compactionReset) return null;
|
|
8499
7275
|
const workspaceDir = compactionWorkspaceDir || this.deps.config.workspaceDir || defaultWorkspaceDir();
|
|
8500
7276
|
const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
|
|
8501
|
-
const signalPath =
|
|
7277
|
+
const signalPath = path7.join(
|
|
8502
7278
|
workspaceDir,
|
|
8503
7279
|
`.compaction-reset-signal-${safeSessionKey}`
|
|
8504
7280
|
);
|
|
8505
|
-
const bootPath =
|
|
7281
|
+
const bootPath = path7.join(workspaceDir, "BOOT.md");
|
|
8506
7282
|
try {
|
|
8507
7283
|
const signalStat = await stat(signalPath).catch(() => null);
|
|
8508
7284
|
if (!signalStat) return null;
|
|
@@ -10655,8 +9431,8 @@ ${tmtNode.summary}`
|
|
|
10655
9431
|
};
|
|
10656
9432
|
|
|
10657
9433
|
// src/orchestration/recall-search-pipeline.ts
|
|
10658
|
-
import { createHash as
|
|
10659
|
-
import
|
|
9434
|
+
import { createHash as createHash4 } from "crypto";
|
|
9435
|
+
import path8 from "path";
|
|
10660
9436
|
var RecallSearchPipelineCoordinator = class {
|
|
10661
9437
|
constructor(deps) {
|
|
10662
9438
|
this.deps = deps;
|
|
@@ -10821,7 +9597,7 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
10821
9597
|
if (!options.onDebugSnapshot) return;
|
|
10822
9598
|
await options.onDebugSnapshot({
|
|
10823
9599
|
recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10824
|
-
queryHash:
|
|
9600
|
+
queryHash: createHash4("sha256").update(prompt).digest("hex"),
|
|
10825
9601
|
queryLength: prompt.length,
|
|
10826
9602
|
collection: options.collection,
|
|
10827
9603
|
namespaces: options.recallNamespaces,
|
|
@@ -10964,7 +9740,7 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
10964
9740
|
if (hits.length === 0) return [];
|
|
10965
9741
|
const results = [];
|
|
10966
9742
|
for (const hit of hits) {
|
|
10967
|
-
const fullPath =
|
|
9743
|
+
const fullPath = path8.isAbsolute(hit.path) ? hit.path : path8.join(this.deps.config.memoryDir, hit.path);
|
|
10968
9744
|
const memory = await this.deps.storage.readMemoryByPath(fullPath);
|
|
10969
9745
|
if (!memory) continue;
|
|
10970
9746
|
results.push({
|
|
@@ -11127,7 +9903,7 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11127
9903
|
const storage = await this.deps.storageRouter.storageFor(namespace);
|
|
11128
9904
|
const storageDir = typeof storage.dir === "string" && storage.dir ? storage.dir : null;
|
|
11129
9905
|
if (!storageDir) continue;
|
|
11130
|
-
const recallRoot =
|
|
9906
|
+
const recallRoot = path8.resolve(storageDir);
|
|
11131
9907
|
if (seenRecallRoots.has(recallRoot)) continue;
|
|
11132
9908
|
seenRecallRoots.add(recallRoot);
|
|
11133
9909
|
recallRoots.push(recallRoot);
|
|
@@ -11151,8 +9927,8 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11151
9927
|
if (resolvedCold) scopedResults.push(resolvedCold.result);
|
|
11152
9928
|
continue;
|
|
11153
9929
|
}
|
|
11154
|
-
if (
|
|
11155
|
-
if (recallRoots.some((recallRoot) => isPathInsideStorageRoot(recallRoot,
|
|
9930
|
+
if (path8.isAbsolute(result.path)) {
|
|
9931
|
+
if (recallRoots.some((recallRoot) => isPathInsideStorageRoot(recallRoot, path8.resolve(result.path)))) {
|
|
11156
9932
|
scopedResults.push(result);
|
|
11157
9933
|
}
|
|
11158
9934
|
continue;
|
|
@@ -11436,7 +10212,10 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11436
10212
|
continue;
|
|
11437
10213
|
}
|
|
11438
10214
|
}
|
|
11439
|
-
filtered.push(
|
|
10215
|
+
filtered.push({
|
|
10216
|
+
...r,
|
|
10217
|
+
sourceConnector: memory ? memory.frontmatter.sourceConnector : void 0
|
|
10218
|
+
});
|
|
11440
10219
|
}
|
|
11441
10220
|
if (lifecycleFilteredCount > 0) {
|
|
11442
10221
|
log.debug(
|
|
@@ -11679,7 +10458,7 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11679
10458
|
};
|
|
11680
10459
|
|
|
11681
10460
|
// src/orchestration/turn-ingestion.ts
|
|
11682
|
-
import { createHash as
|
|
10461
|
+
import { createHash as createHash5, randomBytes } from "crypto";
|
|
11683
10462
|
var TurnIngestionCoordinator = class {
|
|
11684
10463
|
constructor(deps) {
|
|
11685
10464
|
this.deps = deps;
|
|
@@ -11742,6 +10521,7 @@ var TurnIngestionCoordinator = class {
|
|
|
11742
10521
|
timestamp: turn.timestamp,
|
|
11743
10522
|
sourceValidAt: turn.sourceValidAt,
|
|
11744
10523
|
sessionKey: key,
|
|
10524
|
+
...options.sessionOwnerPrincipal ? { sessionOwnerPrincipal: options.sessionOwnerPrincipal } : {},
|
|
11745
10525
|
parts: turn.parts,
|
|
11746
10526
|
rawContent: turn.rawContent,
|
|
11747
10527
|
sourceFormat: turn.sourceFormat,
|
|
@@ -11863,7 +10643,7 @@ var TurnIngestionCoordinator = class {
|
|
|
11863
10643
|
const shouldUseStableBatchKey = turns.some(
|
|
11864
10644
|
(turn) => turn.persistProcessedFingerprint === true || typeof turn.turnFingerprint === "string" && turn.turnFingerprint.length > 0
|
|
11865
10645
|
);
|
|
11866
|
-
const stableBatchFingerprint = shouldUseStableBatchKey ?
|
|
10646
|
+
const stableBatchFingerprint = shouldUseStableBatchKey ? createHash5("sha256").update(
|
|
11867
10647
|
turns.map(
|
|
11868
10648
|
(turn) => [
|
|
11869
10649
|
turn.role,
|
|
@@ -12058,41 +10838,70 @@ var TurnIngestionCoordinator = class {
|
|
|
12058
10838
|
timeout = void 0;
|
|
12059
10839
|
}
|
|
12060
10840
|
};
|
|
10841
|
+
let abortHandler;
|
|
10842
|
+
const clearAbortListener = () => {
|
|
10843
|
+
if (abortHandler && options.abortSignal) {
|
|
10844
|
+
options.abortSignal.removeEventListener("abort", abortHandler);
|
|
10845
|
+
abortHandler = void 0;
|
|
10846
|
+
}
|
|
10847
|
+
};
|
|
12061
10848
|
const settleTask = (error, result) => {
|
|
12062
10849
|
if (settled) return false;
|
|
12063
10850
|
settled = true;
|
|
12064
10851
|
clearQueueWaitTimer();
|
|
10852
|
+
clearAbortListener();
|
|
12065
10853
|
options.onTaskSettled?.(error, result);
|
|
12066
10854
|
return true;
|
|
12067
10855
|
};
|
|
12068
|
-
if (
|
|
12069
|
-
const
|
|
12070
|
-
|
|
12071
|
-
|
|
10856
|
+
if (options.abortSignal) {
|
|
10857
|
+
const signal = options.abortSignal;
|
|
10858
|
+
abortHandler = () => settleTask(signal.reason ?? abortError("extraction aborted (queue_wait)"));
|
|
10859
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
10860
|
+
if (signal.aborted) {
|
|
10861
|
+
settleTask(signal.reason ?? abortError("extraction aborted (queue_wait)"));
|
|
12072
10862
|
return;
|
|
12073
10863
|
}
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
10864
|
+
}
|
|
10865
|
+
if (typeof extractionDeadlineMs === "number") {
|
|
10866
|
+
const deadline = extractionDeadlineMs;
|
|
10867
|
+
const maxTimerDelayMs = 2147483647;
|
|
10868
|
+
const scheduleQueueWaitTimeout = () => {
|
|
10869
|
+
const remainingMs = deadline - Date.now();
|
|
10870
|
+
if (remainingMs <= 0) {
|
|
10871
|
+
settleTask(new ExtractionDeadlineError("queue_wait"));
|
|
10872
|
+
return;
|
|
10873
|
+
}
|
|
10874
|
+
timeout = setTimeout(() => {
|
|
10875
|
+
if (Date.now() >= deadline) {
|
|
10876
|
+
settleTask(new ExtractionDeadlineError("queue_wait"));
|
|
10877
|
+
} else {
|
|
10878
|
+
scheduleQueueWaitTimeout();
|
|
10879
|
+
}
|
|
10880
|
+
}, Math.min(remainingMs, maxTimerDelayMs));
|
|
10881
|
+
};
|
|
10882
|
+
scheduleQueueWaitTimeout();
|
|
12077
10883
|
}
|
|
12078
10884
|
this.deps.extractionQueueCoordinator.enqueue(async () => {
|
|
12079
10885
|
if (settled) return;
|
|
12080
10886
|
if (typeof extractionDeadlineMs === "number" && extractionDeadlineMs <= Date.now()) {
|
|
12081
|
-
settleTask(new
|
|
10887
|
+
settleTask(new ExtractionDeadlineError("queue_wait"));
|
|
12082
10888
|
return;
|
|
12083
10889
|
}
|
|
12084
10890
|
clearQueueWaitTimer();
|
|
12085
10891
|
try {
|
|
12086
10892
|
const result = await this.deps.runExtraction(turnsToExtract, {
|
|
12087
10893
|
clearBufferAfterExtraction: options.clearBufferAfterExtraction ?? true,
|
|
10894
|
+
clearMatchingTurns: options.clearMatchingTurns === true,
|
|
12088
10895
|
skipCharThreshold: options.skipCharThreshold ?? false,
|
|
12089
10896
|
skipUserTurnThreshold: options.skipUserTurnThreshold ?? false,
|
|
12090
10897
|
deadlineMs: extractionDeadlineMs,
|
|
12091
10898
|
bufferKey,
|
|
10899
|
+
onDurableCommit: options.onDurableCommit,
|
|
12092
10900
|
abortSignal: options.abortSignal,
|
|
12093
10901
|
failOnExtractionFailure: options.failOnExtractionFailure === true,
|
|
12094
10902
|
writeNamespaceOverride: options.writeNamespaceOverride,
|
|
12095
10903
|
principalOverride: options.principalOverride,
|
|
10904
|
+
scopeProfileWritePlan: options.scopeProfileWritePlan,
|
|
12096
10905
|
forceExtractionAttempt: options.forceExtractionAttempt === true
|
|
12097
10906
|
});
|
|
12098
10907
|
settleTask(void 0, result);
|
|
@@ -12138,11 +10947,12 @@ var TurnIngestionCoordinator = class {
|
|
|
12138
10947
|
bufferKey: opts.bufferKey,
|
|
12139
10948
|
sessionKey: opts.sessionKey,
|
|
12140
10949
|
principal: opts.principal,
|
|
12141
|
-
namespace: opts.namespace
|
|
10950
|
+
namespace: opts.namespace,
|
|
10951
|
+
abortSignal: opts.abortSignal
|
|
12142
10952
|
},
|
|
12143
10953
|
captureConfig,
|
|
12144
10954
|
{
|
|
12145
|
-
planCorrection: (req) => service.plan(req),
|
|
10955
|
+
planCorrection: (req, planOpts) => service.plan(req, planOpts),
|
|
12146
10956
|
applyCorrection: (planId, applyOpts) => service.apply(planId, applyOpts),
|
|
12147
10957
|
storageDir: async (ns) => (await this.deps.getStorage(ns)).dir,
|
|
12148
10958
|
// Resolve `[m:xxxx]` handles to concrete memory ids via the single
|
|
@@ -12175,7 +10985,7 @@ var TurnIngestionCoordinator = class {
|
|
|
12175
10985
|
|
|
12176
10986
|
// src/orchestration/recall-introspection.ts
|
|
12177
10987
|
import { mkdir as mkdir5, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
12178
|
-
import
|
|
10988
|
+
import path10 from "path";
|
|
12179
10989
|
|
|
12180
10990
|
// src/taxonomy/default-taxonomy.ts
|
|
12181
10991
|
var DEFAULT_TAXONOMY = {
|
|
@@ -12298,7 +11108,7 @@ function generateResolverDocument(taxonomy) {
|
|
|
12298
11108
|
|
|
12299
11109
|
// src/taxonomy/taxonomy-loader.ts
|
|
12300
11110
|
import { readFile as readFile3, mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
|
|
12301
|
-
import
|
|
11111
|
+
import path9 from "path";
|
|
12302
11112
|
var TAXONOMY_DIR = ".taxonomy";
|
|
12303
11113
|
var TAXONOMY_FILE = "taxonomy.json";
|
|
12304
11114
|
var MAX_SLUG_LENGTH = 32;
|
|
@@ -12396,7 +11206,7 @@ function validateTaxonomy(taxonomy) {
|
|
|
12396
11206
|
}
|
|
12397
11207
|
}
|
|
12398
11208
|
async function loadTaxonomy(memoryDir) {
|
|
12399
|
-
const taxonomyPath =
|
|
11209
|
+
const taxonomyPath = path9.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
12400
11210
|
let raw;
|
|
12401
11211
|
try {
|
|
12402
11212
|
raw = await readFile3(taxonomyPath, "utf-8");
|
|
@@ -12446,16 +11256,16 @@ async function loadTaxonomy(memoryDir) {
|
|
|
12446
11256
|
}
|
|
12447
11257
|
async function saveTaxonomy(memoryDir, taxonomy) {
|
|
12448
11258
|
validateTaxonomy(taxonomy);
|
|
12449
|
-
const dir =
|
|
11259
|
+
const dir = path9.join(memoryDir, TAXONOMY_DIR);
|
|
12450
11260
|
await mkdir4(dir, { recursive: true });
|
|
12451
|
-
const filePath =
|
|
11261
|
+
const filePath = path9.join(dir, TAXONOMY_FILE);
|
|
12452
11262
|
await writeFile4(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
|
|
12453
11263
|
}
|
|
12454
11264
|
function getTaxonomyDir(memoryDir) {
|
|
12455
|
-
return
|
|
11265
|
+
return path9.join(memoryDir, TAXONOMY_DIR);
|
|
12456
11266
|
}
|
|
12457
11267
|
function getTaxonomyFilePath(memoryDir) {
|
|
12458
|
-
return
|
|
11268
|
+
return path9.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
12459
11269
|
}
|
|
12460
11270
|
|
|
12461
11271
|
// src/orchestration/recall-introspection.ts
|
|
@@ -12479,7 +11289,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12479
11289
|
}
|
|
12480
11290
|
async getLastGraphRecallSnapshot(namespace) {
|
|
12481
11291
|
const storage = await this.deps.getStorage(namespace);
|
|
12482
|
-
const snapshotPath =
|
|
11292
|
+
const snapshotPath = path10.join(
|
|
12483
11293
|
storage.dir,
|
|
12484
11294
|
"state",
|
|
12485
11295
|
"last_graph_recall.json"
|
|
@@ -12518,7 +11328,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12518
11328
|
}
|
|
12519
11329
|
async getLastIntentSnapshot(namespace) {
|
|
12520
11330
|
const storage = await this.deps.getStorage(namespace);
|
|
12521
|
-
const snapshotPath =
|
|
11331
|
+
const snapshotPath = path10.join(storage.dir, "state", "last_intent.json");
|
|
12522
11332
|
try {
|
|
12523
11333
|
const raw = await readFile4(snapshotPath, "utf-8");
|
|
12524
11334
|
const parsed = JSON.parse(raw);
|
|
@@ -12551,7 +11361,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12551
11361
|
}
|
|
12552
11362
|
async getLastQmdRecallSnapshot(namespace) {
|
|
12553
11363
|
const storage = await this.deps.getStorage(namespace);
|
|
12554
|
-
const snapshotPath =
|
|
11364
|
+
const snapshotPath = path10.join(
|
|
12555
11365
|
storage.dir,
|
|
12556
11366
|
"state",
|
|
12557
11367
|
"last_qmd_recall.json"
|
|
@@ -12841,12 +11651,12 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12841
11651
|
}
|
|
12842
11652
|
async recordLastIntentSnapshot(options) {
|
|
12843
11653
|
try {
|
|
12844
|
-
const snapshotPath =
|
|
11654
|
+
const snapshotPath = path10.join(
|
|
12845
11655
|
options.storage.dir,
|
|
12846
11656
|
"state",
|
|
12847
11657
|
"last_intent.json"
|
|
12848
11658
|
);
|
|
12849
|
-
await mkdir5(
|
|
11659
|
+
await mkdir5(path10.dirname(snapshotPath), { recursive: true });
|
|
12850
11660
|
await writeFile5(
|
|
12851
11661
|
snapshotPath,
|
|
12852
11662
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -12858,12 +11668,12 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12858
11668
|
}
|
|
12859
11669
|
async recordLastQmdRecallSnapshot(options) {
|
|
12860
11670
|
try {
|
|
12861
|
-
const snapshotPath =
|
|
11671
|
+
const snapshotPath = path10.join(
|
|
12862
11672
|
options.storage.dir,
|
|
12863
11673
|
"state",
|
|
12864
11674
|
"last_qmd_recall.json"
|
|
12865
11675
|
);
|
|
12866
|
-
await mkdir5(
|
|
11676
|
+
await mkdir5(path10.dirname(snapshotPath), { recursive: true });
|
|
12867
11677
|
await writeFile5(
|
|
12868
11678
|
snapshotPath,
|
|
12869
11679
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -12878,8 +11688,8 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12878
11688
|
const stateDir = await this.deps.resolveStateDirForNamespace(
|
|
12879
11689
|
options.namespace
|
|
12880
11690
|
);
|
|
12881
|
-
const snapshotPath =
|
|
12882
|
-
await mkdir5(
|
|
11691
|
+
const snapshotPath = path10.join(stateDir, "last_intent.json");
|
|
11692
|
+
await mkdir5(path10.dirname(snapshotPath), { recursive: true });
|
|
12883
11693
|
await writeFile5(
|
|
12884
11694
|
snapshotPath,
|
|
12885
11695
|
JSON.stringify(options.snapshot, null, 2),
|
|
@@ -12893,7 +11703,7 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12893
11703
|
|
|
12894
11704
|
// src/orchestration/orchestrator-init.ts
|
|
12895
11705
|
import { readdir as readdir2, stat as stat2, unlink as unlink2 } from "fs/promises";
|
|
12896
|
-
import
|
|
11706
|
+
import path11 from "path";
|
|
12897
11707
|
var OrchestratorInitCoordinator = class {
|
|
12898
11708
|
constructor(deps) {
|
|
12899
11709
|
this.deps = deps;
|
|
@@ -12989,7 +11799,7 @@ var OrchestratorInitCoordinator = class {
|
|
|
12989
11799
|
const files = await readdir2(wsDir).catch(() => []);
|
|
12990
11800
|
for (const f of files) {
|
|
12991
11801
|
if (!f.startsWith(".compaction-reset-signal-")) continue;
|
|
12992
|
-
const fp =
|
|
11802
|
+
const fp = path11.join(wsDir, f);
|
|
12993
11803
|
const s = await stat2(fp).catch(() => null);
|
|
12994
11804
|
if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
|
|
12995
11805
|
await unlink2(fp).catch(() => {
|
|
@@ -13341,7 +12151,7 @@ var OrchestratorInitCoordinator = class {
|
|
|
13341
12151
|
};
|
|
13342
12152
|
|
|
13343
12153
|
// src/orchestration/persistence-index.ts
|
|
13344
|
-
import
|
|
12154
|
+
import path12 from "path";
|
|
13345
12155
|
var PersistenceIndexCoordinator = class {
|
|
13346
12156
|
constructor(deps) {
|
|
13347
12157
|
this.deps = deps;
|
|
@@ -13527,7 +12337,7 @@ var PersistenceIndexCoordinator = class {
|
|
|
13527
12337
|
const allMems = allMemsForGraph ?? [];
|
|
13528
12338
|
for (const m of allMems) {
|
|
13529
12339
|
if (m.frontmatter.entityRef === entityRef) {
|
|
13530
|
-
const rel =
|
|
12340
|
+
const rel = path12.relative(storage.dir, m.path);
|
|
13531
12341
|
if (rel !== memoryRelPath) entitySiblings.push(rel);
|
|
13532
12342
|
}
|
|
13533
12343
|
}
|
|
@@ -13676,7 +12486,7 @@ var PersistenceIndexCoordinator = class {
|
|
|
13676
12486
|
|
|
13677
12487
|
// src/orchestration/workspace-ops.ts
|
|
13678
12488
|
import { lstat, mkdir as mkdir6, readFile as readFile5, readdir as readdir3, realpath, writeFile as writeFile6 } from "fs/promises";
|
|
13679
|
-
import
|
|
12489
|
+
import path13 from "path";
|
|
13680
12490
|
|
|
13681
12491
|
// src/maintenance/pattern-reinforcement.ts
|
|
13682
12492
|
function patternReinforcementKey(content) {
|
|
@@ -15575,8 +14385,8 @@ var MeetingsService = class {
|
|
|
15575
14385
|
// src/orchestration/workspace-ops.ts
|
|
15576
14386
|
var MEETINGS_BUILD_DEBOUNCE_MS = 5e3;
|
|
15577
14387
|
function matchesMemoryPath(candidatePath, requestedPath, memoryDir) {
|
|
15578
|
-
const normalizedCandidate =
|
|
15579
|
-
return normalizedCandidate ===
|
|
14388
|
+
const normalizedCandidate = path13.resolve(candidatePath);
|
|
14389
|
+
return normalizedCandidate === path13.resolve(requestedPath) || normalizedCandidate === path13.resolve(memoryDir, requestedPath);
|
|
15580
14390
|
}
|
|
15581
14391
|
function accessTrackingPathCandidates(storageDir, memoryPath) {
|
|
15582
14392
|
const candidates = qmdResultPathCandidates(storageDir, memoryPath);
|
|
@@ -15584,12 +14394,12 @@ function accessTrackingPathCandidates(storageDir, memoryPath) {
|
|
|
15584
14394
|
if (!parts) return candidates;
|
|
15585
14395
|
candidates.push(
|
|
15586
14396
|
...qmdResultPathCandidates(storageDir, parts.relativePath),
|
|
15587
|
-
...qmdResultPathCandidates(
|
|
14397
|
+
...qmdResultPathCandidates(path13.join(storageDir, "cold"), parts.relativePath)
|
|
15588
14398
|
);
|
|
15589
14399
|
return [...new Set(candidates)];
|
|
15590
14400
|
}
|
|
15591
14401
|
function canonicalMemoryPath(memoryPath, memoryDir) {
|
|
15592
|
-
return
|
|
14402
|
+
return path13.resolve(path13.isAbsolute(memoryPath) ? memoryPath : path13.resolve(memoryDir, memoryPath));
|
|
15593
14403
|
}
|
|
15594
14404
|
var WorkspaceOpsCoordinator = class {
|
|
15595
14405
|
constructor(deps) {
|
|
@@ -15671,15 +14481,15 @@ var WorkspaceOpsCoordinator = class {
|
|
|
15671
14481
|
this.deps.lastFileHygieneRunAtMs = now;
|
|
15672
14482
|
if (hygiene.rotateEnabled) {
|
|
15673
14483
|
for (const rel of hygiene.rotatePaths) {
|
|
15674
|
-
const abs =
|
|
14484
|
+
const abs = path13.isAbsolute(rel) ? rel : path13.join(this.deps.config.workspaceDir, rel);
|
|
15675
14485
|
try {
|
|
15676
14486
|
const raw = await readFile5(abs, "utf-8");
|
|
15677
14487
|
if (raw.length > hygiene.rotateMaxBytes) {
|
|
15678
|
-
const archiveDir =
|
|
14488
|
+
const archiveDir = path13.join(
|
|
15679
14489
|
this.deps.config.workspaceDir,
|
|
15680
14490
|
hygiene.archiveDir
|
|
15681
14491
|
);
|
|
15682
|
-
const base =
|
|
14492
|
+
const base = path13.basename(abs);
|
|
15683
14493
|
const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
|
|
15684
14494
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
15685
14495
|
filePath: abs,
|
|
@@ -15704,8 +14514,8 @@ var WorkspaceOpsCoordinator = class {
|
|
|
15704
14514
|
log.warn(w.message);
|
|
15705
14515
|
}
|
|
15706
14516
|
if (hygiene.warningsLogEnabled && warnings.length > 0) {
|
|
15707
|
-
const fp =
|
|
15708
|
-
await mkdir6(
|
|
14517
|
+
const fp = path13.join(this.deps.config.memoryDir, hygiene.warningsLogPath);
|
|
14518
|
+
await mkdir6(path13.dirname(fp), { recursive: true });
|
|
15709
14519
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
15710
14520
|
const block = `
|
|
15711
14521
|
|
|
@@ -15745,7 +14555,7 @@ var WorkspaceOpsCoordinator = class {
|
|
|
15745
14555
|
for (const categoryDir of RECALL_FALLBACK_DIRS) {
|
|
15746
14556
|
if (memoryRootReal === null) break;
|
|
15747
14557
|
for (const date of datesToScan) {
|
|
15748
|
-
const dateDir =
|
|
14558
|
+
const dateDir = path13.join(storage.dir, categoryDir, date);
|
|
15749
14559
|
try {
|
|
15750
14560
|
const dirStat = await lstat(dateDir);
|
|
15751
14561
|
if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) continue;
|
|
@@ -15754,7 +14564,7 @@ var WorkspaceOpsCoordinator = class {
|
|
|
15754
14564
|
for (const entry of entries) {
|
|
15755
14565
|
if (entry.isSymbolicLink()) continue;
|
|
15756
14566
|
if (!entry.name.endsWith(".md")) continue;
|
|
15757
|
-
const fullPath =
|
|
14567
|
+
const fullPath = path13.join(dateDir, entry.name);
|
|
15758
14568
|
try {
|
|
15759
14569
|
assertPathInsideRoot(memoryRootReal, await realpath(fullPath), fullPath);
|
|
15760
14570
|
const raw = await readFile5(fullPath, "utf-8");
|
|
@@ -15776,7 +14586,7 @@ var WorkspaceOpsCoordinator = class {
|
|
|
15776
14586
|
facts.push({
|
|
15777
14587
|
path: fullPath,
|
|
15778
14588
|
frontmatter: {
|
|
15779
|
-
id: fm.id ||
|
|
14589
|
+
id: fm.id || path13.basename(entry.name, ".md"),
|
|
15780
14590
|
category: fm.category || "fact",
|
|
15781
14591
|
created,
|
|
15782
14592
|
updated: fm.updated || created,
|
|
@@ -15799,13 +14609,13 @@ var WorkspaceOpsCoordinator = class {
|
|
|
15799
14609
|
return a.frontmatter.created < b.frontmatter.created ? -1 : 1;
|
|
15800
14610
|
});
|
|
15801
14611
|
const hourlySummaries = [];
|
|
15802
|
-
const hourlyBaseDir =
|
|
14612
|
+
const hourlyBaseDir = path13.join(storage.dir, "summaries", "hourly");
|
|
15803
14613
|
try {
|
|
15804
14614
|
const sessionKeys = await readdir3(hourlyBaseDir, { withFileTypes: true });
|
|
15805
14615
|
for (const sk of sessionKeys) {
|
|
15806
14616
|
if (!sk.isDirectory()) continue;
|
|
15807
14617
|
for (const date of datesToScan) {
|
|
15808
|
-
const summaryFile =
|
|
14618
|
+
const summaryFile = path13.join(hourlyBaseDir, sk.name, `${date}.md`);
|
|
15809
14619
|
try {
|
|
15810
14620
|
const raw = await readFile5(summaryFile, "utf-8");
|
|
15811
14621
|
const filtered = filterHourlySummaryMarkdownForLocalDay(
|
|
@@ -16269,18 +15079,18 @@ ${reflectionsContent.trim()}
|
|
|
16269
15079
|
// src/orchestration/namespace-read-fanout.ts
|
|
16270
15080
|
import { existsSync, readFileSync } from "fs";
|
|
16271
15081
|
import { stat as stat3 } from "fs/promises";
|
|
16272
|
-
import
|
|
15082
|
+
import path15 from "path";
|
|
16273
15083
|
|
|
16274
15084
|
// src/orchestration/orchestrator-namespace-scope.ts
|
|
16275
|
-
import
|
|
15085
|
+
import path14 from "path";
|
|
16276
15086
|
function computeSemanticDedupScope(targetStorage, config) {
|
|
16277
15087
|
if (!resolveNamespaceCapabilities(config).namespaces) return {};
|
|
16278
|
-
const memoryDir =
|
|
16279
|
-
const storageDir =
|
|
15088
|
+
const memoryDir = path14.resolve(config.memoryDir);
|
|
15089
|
+
const storageDir = path14.resolve(targetStorage.dir);
|
|
16280
15090
|
if (storageDir === memoryDir) {
|
|
16281
15091
|
return { pathExcludePrefixes: ["namespaces/"] };
|
|
16282
15092
|
}
|
|
16283
|
-
let rel =
|
|
15093
|
+
let rel = path14.relative(memoryDir, storageDir);
|
|
16284
15094
|
if (!rel || rel.startsWith("..")) {
|
|
16285
15095
|
log.debug(
|
|
16286
15096
|
`semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
|
|
@@ -16333,7 +15143,7 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
16333
15143
|
loadNamespaceStorageDirHintsFromCatalog() {
|
|
16334
15144
|
if (this.deps.namespaceStorageDirHintsLoaded || !this.deps.namespaceCatalog.enabled) return;
|
|
16335
15145
|
this.deps.namespaceStorageDirHintsLoaded = true;
|
|
16336
|
-
const catalogPath =
|
|
15146
|
+
const catalogPath = path15.join(this.deps.config.memoryDir, "state", "namespaces.jsonl");
|
|
16337
15147
|
if (!existsSync(catalogPath)) return;
|
|
16338
15148
|
let body;
|
|
16339
15149
|
try {
|
|
@@ -16370,7 +15180,7 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
16370
15180
|
if (!this.deps.storageDirMatchesNamespaceHint(record.namespace, record.storageDir)) {
|
|
16371
15181
|
continue;
|
|
16372
15182
|
}
|
|
16373
|
-
const resolvedStorageDir =
|
|
15183
|
+
const resolvedStorageDir = path15.resolve(record.storageDir);
|
|
16374
15184
|
const current = preferredByStorageDir.get(resolvedStorageDir);
|
|
16375
15185
|
preferredByStorageDir.set(
|
|
16376
15186
|
resolvedStorageDir,
|
|
@@ -16551,12 +15361,12 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
16551
15361
|
}
|
|
16552
15362
|
async resolveStateDirForNamespace(namespace) {
|
|
16553
15363
|
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) {
|
|
16554
|
-
return
|
|
15364
|
+
return path15.join(this.deps.config.memoryDir, "state");
|
|
16555
15365
|
}
|
|
16556
15366
|
if (namespace !== this.deps.config.defaultNamespace) {
|
|
16557
|
-
return
|
|
15367
|
+
return path15.join(this.deps.config.memoryDir, "namespaces", namespace, "state");
|
|
16558
15368
|
}
|
|
16559
|
-
const candidate =
|
|
15369
|
+
const candidate = path15.join(
|
|
16560
15370
|
this.deps.config.memoryDir,
|
|
16561
15371
|
"namespaces",
|
|
16562
15372
|
this.deps.config.defaultNamespace
|
|
@@ -16564,11 +15374,11 @@ var NamespaceReadFanoutCoordinator = class {
|
|
|
16564
15374
|
try {
|
|
16565
15375
|
const candidateStat = await stat3(candidate);
|
|
16566
15376
|
if (candidateStat.isDirectory()) {
|
|
16567
|
-
return
|
|
15377
|
+
return path15.join(candidate, "state");
|
|
16568
15378
|
}
|
|
16569
15379
|
} catch {
|
|
16570
15380
|
}
|
|
16571
|
-
return
|
|
15381
|
+
return path15.join(this.deps.config.memoryDir, "state");
|
|
16572
15382
|
}
|
|
16573
15383
|
namespaceFromPath(p) {
|
|
16574
15384
|
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) return this.deps.config.defaultNamespace;
|
|
@@ -16781,270 +15591,6 @@ var RecallEntryCoordinator = class {
|
|
|
16781
15591
|
}
|
|
16782
15592
|
};
|
|
16783
15593
|
|
|
16784
|
-
// src/orchestration/session-context.ts
|
|
16785
|
-
var SessionContextCoordinator = class {
|
|
16786
|
-
constructor(deps) {
|
|
16787
|
-
this.deps = deps;
|
|
16788
|
-
}
|
|
16789
|
-
deps;
|
|
16790
|
-
/**
|
|
16791
|
-
* Effective namespace a same-session LCM/structured-history READER must use
|
|
16792
|
-
* to find what the access `observe` surface WROTE (#1495 thread 2).
|
|
16793
|
-
*
|
|
16794
|
-
* This MUST mirror the `observe` scope plan's write-namespace resolution, NOT
|
|
16795
|
-
* `resolveSelfNamespace`: when no coding overlay applies, `observe` archives
|
|
16796
|
-
* under `config.defaultNamespace` (an unqualified observed turn is NOT moved
|
|
16797
|
-
* to the principal self namespace — identical to
|
|
16798
|
-
* `resolveCodingScopedWriteNamespace`/`memory_store`, rule 39). Only when a
|
|
16799
|
-
* coding overlay actually changes the namespace does the writer (and so the
|
|
16800
|
-
* reader) use the overlaid `project-*` namespace. Returning the self base for
|
|
16801
|
-
* the no-overlay case would prefix the read key with a namespace the writer
|
|
16802
|
-
* never used, so the reader would miss its own evidence.
|
|
16803
|
-
*
|
|
16804
|
-
* Honours the access-surface `principalOverride` (#1505 thread 2, codex): when
|
|
16805
|
-
* a recall supplies an authenticated principal NOT encoded in the raw
|
|
16806
|
-
* `sessionKey`, `observe` archived LCM under THAT principal's base namespace.
|
|
16807
|
-
* Deriving the base from `resolvePrincipal(sessionKey)` alone could fall back
|
|
16808
|
-
* to `default`, so principal `alice` observing `sess-1` would write under
|
|
16809
|
-
* `alice` but READ under `default`. Threading the override here keeps the read
|
|
16810
|
-
* base identical to the write base.
|
|
16811
|
-
*
|
|
16812
|
-
* READ-AUTHORIZATION gate (#1505 round 3, codex P2 "Gate LCM recall keys by
|
|
16813
|
-
* readable namespaces"): the overlay LCM read key is a `<principal>-project-*`
|
|
16814
|
-
* sub-namespace of the principal SELF base. The normal recall namespace set
|
|
16815
|
-
* below only substitutes the coding overlay when the principal SELF base is
|
|
16816
|
-
* actually in the readable recall set (`recallNamespacesForPrincipal` — gated
|
|
16817
|
-
* by `defaultRecallNamespaces.includes("self")` AND `canReadNamespace`). If a
|
|
16818
|
-
* principal can WRITE but not READ its self namespace (or `defaultRecall-
|
|
16819
|
-
* Namespaces` omits `self`), QMD/file recall never touches those overlay rows,
|
|
16820
|
-
* so neither may the LCM read key. When the self base is NOT readable, fall
|
|
16821
|
-
* back to the default store — exactly what an unqualified, unauthorized recall
|
|
16822
|
-
* resolves to — rather than injecting overlay rows the rest of recall excludes
|
|
16823
|
-
* (rule 42 read/write parity; rule 48 least-privilege).
|
|
16824
|
-
*/
|
|
16825
|
-
lcmReadNamespaceForSession(sessionKey, principalOverride) {
|
|
16826
|
-
const principal = typeof principalOverride === "string" && principalOverride.length > 0 ? principalOverride : this.deps.resolvePrincipal(sessionKey);
|
|
16827
|
-
const base = defaultNamespaceForPrincipal(principal, this.deps.config);
|
|
16828
|
-
const overlaid = this.deps.applyCodingNamespaceOverlay(sessionKey, base);
|
|
16829
|
-
if (overlaid === base) return this.deps.config.defaultNamespace;
|
|
16830
|
-
const selfReadableInRecall = recallNamespacesForPrincipal(
|
|
16831
|
-
principal,
|
|
16832
|
-
this.deps.config
|
|
16833
|
-
).includes(base);
|
|
16834
|
-
return selfReadableInRecall ? overlaid : this.deps.config.defaultNamespace;
|
|
16835
|
-
}
|
|
16836
|
-
/**
|
|
16837
|
-
* Attach a coding-agent context to a session (issue #569). Called by the
|
|
16838
|
-
* Claude Code / Codex / Cursor connectors at session start after
|
|
16839
|
-
* `resolveGitContext(cwd)`. The context is consulted by the recall path
|
|
16840
|
-
* and the write path so that memories route to a project- (and optionally
|
|
16841
|
-
* branch-) scoped namespace.
|
|
16842
|
-
*
|
|
16843
|
-
* Pass `null` to clear.
|
|
16844
|
-
*/
|
|
16845
|
-
setCodingContextForSession(sessionKey, codingContext) {
|
|
16846
|
-
if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
|
|
16847
|
-
this.deps.ensureSessionBindingMaps();
|
|
16848
|
-
if (codingContext === null) {
|
|
16849
|
-
this.deps._codingContextBySession.delete(sessionKey);
|
|
16850
|
-
return;
|
|
16851
|
-
}
|
|
16852
|
-
this.deps._codingContextBySession.set(sessionKey, codingContext);
|
|
16853
|
-
}
|
|
16854
|
-
/**
|
|
16855
|
-
* Read-only accessor for the coding context attached to a session. Returns
|
|
16856
|
-
* `null` when none is set. Used by `remnic doctor` and by tests.
|
|
16857
|
-
*
|
|
16858
|
-
* Defensive `_codingContextBySession` lookup — legacy orchestrator-flush
|
|
16859
|
-
* tests use `Object.create(Orchestrator.prototype)` which does not run
|
|
16860
|
-
* class-field initializers, so the Map may be undefined on stubs.
|
|
16861
|
-
*/
|
|
16862
|
-
getCodingContextForSession(sessionKey) {
|
|
16863
|
-
if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
|
|
16864
|
-
return this.deps._codingContextBySession?.get(sessionKey) ?? null;
|
|
16865
|
-
}
|
|
16866
|
-
/**
|
|
16867
|
-
* Shared helper used by both the recall path and the write path (rule 42).
|
|
16868
|
-
*
|
|
16869
|
-
* Given a base namespace computed from the principal, returns the overlaid
|
|
16870
|
-
* coding namespace when the session has a coding context AND
|
|
16871
|
-
* `codingMode.projectScope` is true AND `namespacesEnabled` is true.
|
|
16872
|
-
* Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.
|
|
16873
|
-
*
|
|
16874
|
-
* Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with
|
|
16875
|
-
* the principal-derived `baseNamespace` rather than replacing it, so two
|
|
16876
|
-
* principals working in the same repository do not share memories through
|
|
16877
|
-
* a common `project-*` namespace.
|
|
16878
|
-
*
|
|
16879
|
-
* Namespaces-disabled gate: when `namespacesEnabled` is false, the
|
|
16880
|
-
* storage router maps every namespace to the same `memoryDir`. Returning
|
|
16881
|
-
* `project-*` in that mode would create apparent route separation with
|
|
16882
|
-
* no actual storage isolation — a false-isolation trap. In that mode we
|
|
16883
|
-
* return `baseNamespace` unchanged so coding mode degrades to the existing
|
|
16884
|
-
* unscoped behavior.
|
|
16885
|
-
*
|
|
16886
|
-
* @internal
|
|
16887
|
-
*/
|
|
16888
|
-
applyCodingNamespaceOverlay(sessionKey, baseNamespace) {
|
|
16889
|
-
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) return baseNamespace;
|
|
16890
|
-
const codingContext = this.deps.getCodingContextForSession(sessionKey);
|
|
16891
|
-
const overlay = resolveCodingNamespaceOverlay(codingContext, this.deps.config.codingMode, this.deps.config.defaultNamespace);
|
|
16892
|
-
if (!overlay) return baseNamespace;
|
|
16893
|
-
return combineNamespaces(baseNamespace, overlay.namespace);
|
|
16894
|
-
}
|
|
16895
|
-
/**
|
|
16896
|
-
* Register a peer ID for a session so recall can inject the peer's
|
|
16897
|
-
* profile into context (issue #679 PR 3/5). Pass `null` to clear.
|
|
16898
|
-
*
|
|
16899
|
-
* Connectors and the `before_agent_start` hook call this when the
|
|
16900
|
-
* session's counter-party is known. The ID is validated against
|
|
16901
|
-
* `PEER_ID_PATTERN` before storing.
|
|
16902
|
-
*
|
|
16903
|
-
* Fail-closed (Codex P1 review): an invalid peerId clears any
|
|
16904
|
-
* previously registered mapping for the session rather than silently
|
|
16905
|
-
* keeping stale data. This prevents a malformed metadata update from
|
|
16906
|
-
* mixing one peer's profile context into another session.
|
|
16907
|
-
*
|
|
16908
|
-
* Defensive init (Cursor review + rule 16): `Object.create(
|
|
16909
|
-
* Orchestrator.prototype)` stubs in legacy tests skip class-field
|
|
16910
|
-
* initializers, so `_peerIdBySession` may be undefined. Mirror the
|
|
16911
|
-
* same guard used by `setCodingContextForSession`.
|
|
16912
|
-
*/
|
|
16913
|
-
setPeerIdForSession(sessionKey, peerId) {
|
|
16914
|
-
if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
|
|
16915
|
-
this.deps.ensureSessionBindingMaps();
|
|
16916
|
-
if (peerId === null) {
|
|
16917
|
-
this.deps._peerIdBySession.delete(sessionKey);
|
|
16918
|
-
return;
|
|
16919
|
-
}
|
|
16920
|
-
if (typeof peerId !== "string" || peerId.length === 0 || peerId.length > 64 || !/^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$/.test(peerId)) {
|
|
16921
|
-
log.warn(`setPeerIdForSession: invalid peerId \u2014 clearing session mapping`);
|
|
16922
|
-
this.deps._peerIdBySession.delete(sessionKey);
|
|
16923
|
-
return;
|
|
16924
|
-
}
|
|
16925
|
-
this.deps._peerIdBySession.set(sessionKey, peerId);
|
|
16926
|
-
}
|
|
16927
|
-
/**
|
|
16928
|
-
* Return the peer ID registered for a session, or `null` when none
|
|
16929
|
-
* is set. Used by `recallInternal` to inject the peer profile section.
|
|
16930
|
-
* Defensive `_peerIdBySession` lookup — legacy orchestrator-flush tests
|
|
16931
|
-
* use `Object.create(Orchestrator.prototype)` which skips class-field
|
|
16932
|
-
* initializers, so the Map may be undefined on stubs.
|
|
16933
|
-
*/
|
|
16934
|
-
getPeerIdForSession(sessionKey) {
|
|
16935
|
-
if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
|
|
16936
|
-
return this.deps._peerIdBySession?.get(sessionKey) ?? null;
|
|
16937
|
-
}
|
|
16938
|
-
async runDeepSleepGovernanceNow(options) {
|
|
16939
|
-
const targetStorage = options?.storage ?? this.deps.storage;
|
|
16940
|
-
const { runMemoryGovernance } = await import("./maintenance/memory-governance.js");
|
|
16941
|
-
const { summarizeGovernanceResultForDreams } = await import("./dreams-ledger-567VKVOU.js");
|
|
16942
|
-
const govResult = await runMemoryGovernance({
|
|
16943
|
-
memoryDir: targetStorage.dir,
|
|
16944
|
-
mode: options?.dryRun === true ? "shadow" : "apply"
|
|
16945
|
-
});
|
|
16946
|
-
if (options?.dryRun !== true) {
|
|
16947
|
-
try {
|
|
16948
|
-
await this.deps.entitySynthesisCoordinator.processQueue(
|
|
16949
|
-
this.deps.storageDirNamespace(targetStorage.dir),
|
|
16950
|
-
5
|
|
16951
|
-
);
|
|
16952
|
-
} catch (error) {
|
|
16953
|
-
log.debug(`deep-sleep governance: entity synthesis refresh failed after apply: ${error}`);
|
|
16954
|
-
}
|
|
16955
|
-
}
|
|
16956
|
-
return summarizeGovernanceResultForDreams(govResult, options?.dryRun === true);
|
|
16957
|
-
}
|
|
16958
|
-
async generateDaySummary(memories) {
|
|
16959
|
-
if (this.deps.initPromise) {
|
|
16960
|
-
let initGateTimeoutHandle;
|
|
16961
|
-
try {
|
|
16962
|
-
await Promise.race([
|
|
16963
|
-
this.deps.initPromise.catch(() => void 0),
|
|
16964
|
-
new Promise((resolve) => {
|
|
16965
|
-
initGateTimeoutHandle = setTimeout(
|
|
16966
|
-
resolve,
|
|
16967
|
-
this.deps.config.initGateTimeoutMs
|
|
16968
|
-
);
|
|
16969
|
-
})
|
|
16970
|
-
]);
|
|
16971
|
-
} finally {
|
|
16972
|
-
if (initGateTimeoutHandle) clearTimeout(initGateTimeoutHandle);
|
|
16973
|
-
}
|
|
16974
|
-
}
|
|
16975
|
-
return this.deps.extraction.generateDaySummary(memories);
|
|
16976
|
-
}
|
|
16977
|
-
async flushSession(sessionKey, options) {
|
|
16978
|
-
if (typeof this.deps.buffer.flushPendingSave === "function") {
|
|
16979
|
-
await this.deps.buffer.flushPendingSave({ throwOnFailure: true });
|
|
16980
|
-
}
|
|
16981
|
-
const explicitBufferKey = typeof options.bufferKey === "string" && options.bufferKey.length > 0 ? options.bufferKey : null;
|
|
16982
|
-
const discoveredBufferKeys = explicitBufferKey || typeof sessionKey !== "string" || sessionKey.length === 0 || typeof this.deps.buffer.findBufferKeysForSession !== "function" ? [] : await this.deps.buffer.findBufferKeysForSession(sessionKey);
|
|
16983
|
-
const bufferKeys = explicitBufferKey ? [explicitBufferKey] : discoveredBufferKeys.length > 0 ? discoveredBufferKeys : typeof sessionKey === "string" && sessionKey.length > 0 ? [sessionKey] : ["default"];
|
|
16984
|
-
for (const bufferKey of bufferKeys) {
|
|
16985
|
-
const turns = this.deps.buffer.getTurns(bufferKey);
|
|
16986
|
-
if (turns.length === 0) continue;
|
|
16987
|
-
await new Promise((resolve, reject) => {
|
|
16988
|
-
void this.deps.queueBufferedExtraction(turns, "trigger_mode", {
|
|
16989
|
-
bufferKey,
|
|
16990
|
-
clearBufferAfterExtraction: true,
|
|
16991
|
-
skipDedupeCheck: true,
|
|
16992
|
-
forceExtractionAttempt: true,
|
|
16993
|
-
abortSignal: options.abortSignal,
|
|
16994
|
-
onTaskSettled: (error) => error ? reject(error) : resolve()
|
|
16995
|
-
}).catch(reject);
|
|
16996
|
-
});
|
|
16997
|
-
}
|
|
16998
|
-
}
|
|
16999
|
-
/** Lazily construct the CorrectionService for passive capture. Stateless
|
|
17000
|
-
* across requests (per #1580 design); cached for the orchestrator's life. */
|
|
17001
|
-
passiveCorrectionService() {
|
|
17002
|
-
if (this.deps._passiveCorrectionService) return this.deps._passiveCorrectionService;
|
|
17003
|
-
this.deps._passiveCorrectionService = createCorrectionService({
|
|
17004
|
-
orchestrator: this.deps.orchestratorSelf,
|
|
17005
|
-
// Session-scoped write ACL (review: "passive capture bypasses write
|
|
17006
|
-
// ACL"). A correction detected in session S plans only against S readable
|
|
17007
|
-
// namespaces and applies only to writable ones (rule 42) — passive
|
|
17008
|
-
// capture never becomes a cross-tenant mutation vector. Mirrors the
|
|
17009
|
-
// access-service createCorrectionService wiring rather than bypassing it.
|
|
17010
|
-
resolveAuthorizedNamespace: async (req) => {
|
|
17011
|
-
const principal = req.principal || resolvePrincipal(req.sessionKey, this.deps.config);
|
|
17012
|
-
const ns = req.namespace ?? defaultNamespaceForPrincipal(principal, this.deps.config);
|
|
17013
|
-
if (!canWriteNamespace(principal, ns, this.deps.config)) {
|
|
17014
|
-
throw new Error(
|
|
17015
|
-
`passive correction: namespace "${ns}" is not writable for principal ${principal ?? "(none)"}`
|
|
17016
|
-
);
|
|
17017
|
-
}
|
|
17018
|
-
return ns;
|
|
17019
|
-
},
|
|
17020
|
-
resolveReadableNamespaces: (req) => {
|
|
17021
|
-
const principal = req.principal || resolvePrincipal(req.sessionKey, this.deps.config);
|
|
17022
|
-
return recallNamespacesForPrincipal(principal, this.deps.config);
|
|
17023
|
-
},
|
|
17024
|
-
canWriteNamespace: async (req) => {
|
|
17025
|
-
const principal = req.principal || resolvePrincipal(req.sessionKey, this.deps.config);
|
|
17026
|
-
return canWriteNamespace(principal, req.namespace, this.deps.config);
|
|
17027
|
-
},
|
|
17028
|
-
llmComplete: async ({ system, user }) => {
|
|
17029
|
-
const llmResult = await this.deps.localLlm.chatCompletion(
|
|
17030
|
-
[
|
|
17031
|
-
{ role: "system", content: system },
|
|
17032
|
-
{ role: "user", content: user }
|
|
17033
|
-
],
|
|
17034
|
-
{ operation: "correction-classify", priority: "background" }
|
|
17035
|
-
);
|
|
17036
|
-
if (!llmResult) {
|
|
17037
|
-
throw new Error(
|
|
17038
|
-
"passive correction classify+draft: local LLM unavailable (disabled or in cooldown)"
|
|
17039
|
-
);
|
|
17040
|
-
}
|
|
17041
|
-
return llmResult.content;
|
|
17042
|
-
}
|
|
17043
|
-
});
|
|
17044
|
-
return this.deps._passiveCorrectionService;
|
|
17045
|
-
}
|
|
17046
|
-
};
|
|
17047
|
-
|
|
17048
15594
|
// src/orchestration/recall-background-writes.ts
|
|
17049
15595
|
var pendingWritesByOwner = /* @__PURE__ */ new WeakMap();
|
|
17050
15596
|
function trackRecallWrite(owner, promise, label) {
|
|
@@ -17611,7 +16157,7 @@ var Orchestrator = class {
|
|
|
17611
16157
|
const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
|
|
17612
16158
|
if (ns !== defaultNs && !isSafeRouteNamespace(ns)) return;
|
|
17613
16159
|
if (!this.storageDirMatchesNamespaceHint(ns, storageDir)) return;
|
|
17614
|
-
const resolvedStorageDir =
|
|
16160
|
+
const resolvedStorageDir = path16.resolve(storageDir);
|
|
17615
16161
|
let hints = this.namespaceStorageDirHints.get(resolvedStorageDir);
|
|
17616
16162
|
if (!hints) {
|
|
17617
16163
|
hints = /* @__PURE__ */ new Set();
|
|
@@ -17622,21 +16168,21 @@ var Orchestrator = class {
|
|
|
17622
16168
|
storageDirMatchesNamespaceHint(namespace, storageDir) {
|
|
17623
16169
|
const ns = normalizeNamespaceIdentity(namespace);
|
|
17624
16170
|
if (!ns) return false;
|
|
17625
|
-
const resolvedStorageDir =
|
|
17626
|
-
const resolvedMemoryDir =
|
|
16171
|
+
const resolvedStorageDir = path16.resolve(storageDir);
|
|
16172
|
+
const resolvedMemoryDir = path16.resolve(this.config.memoryDir);
|
|
17627
16173
|
const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
|
|
17628
16174
|
if (resolvedStorageDir === resolvedMemoryDir) return ns === defaultNs;
|
|
17629
|
-
const resolvedNamespacesDir =
|
|
16175
|
+
const resolvedNamespacesDir = path16.join(resolvedMemoryDir, "namespaces");
|
|
17630
16176
|
if (!isPathInsideStorageRoot(resolvedNamespacesDir, resolvedStorageDir)) return false;
|
|
17631
|
-
const rawRoot =
|
|
17632
|
-
const tokenRoot =
|
|
16177
|
+
const rawRoot = path16.resolve(resolvedNamespacesDir, ns);
|
|
16178
|
+
const tokenRoot = path16.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));
|
|
17633
16179
|
return resolvedStorageDir === rawRoot || resolvedStorageDir === tokenRoot;
|
|
17634
16180
|
}
|
|
17635
16181
|
namespaceStorageDirHintOwnershipRank(record, resolvedStorageDir, configured) {
|
|
17636
|
-
if (resolvedStorageDir ===
|
|
16182
|
+
if (resolvedStorageDir === path16.resolve(this.config.memoryDir)) {
|
|
17637
16183
|
return record.namespace === normalizeNamespaceIdentity(this.config.defaultNamespace) ? 0 : 3;
|
|
17638
16184
|
}
|
|
17639
|
-
const leaf =
|
|
16185
|
+
const leaf = path16.basename(resolvedStorageDir);
|
|
17640
16186
|
const tokenOwnsRoot = namespaceIdentityToken(record.namespace) === leaf;
|
|
17641
16187
|
if (tokenOwnsRoot && configured.has(record.namespace)) return 0;
|
|
17642
16188
|
if (record.namespace === leaf) return 1;
|
|
@@ -17772,7 +16318,7 @@ var Orchestrator = class {
|
|
|
17772
16318
|
StorageManager.setScopedCacheInvalidationDefault(config.memoryDir, scopedCacheInvalidationEnabled);
|
|
17773
16319
|
this.profiler = new ProfilingCollector({
|
|
17774
16320
|
enabled: resolvePipelineProcessingCapabilities(this.config).profiling,
|
|
17775
|
-
storageDir: config.profilingStorageDir ||
|
|
16321
|
+
storageDir: config.profilingStorageDir || path16.join(config.memoryDir, "profiling"),
|
|
17776
16322
|
maxTraces: config.profilingMaxTraces
|
|
17777
16323
|
});
|
|
17778
16324
|
this.namespaceCatalog = new NamespaceCatalog(config);
|
|
@@ -17859,7 +16405,7 @@ var Orchestrator = class {
|
|
|
17859
16405
|
this.compounding = resolveConsolidationCapabilities(config).compounding ? new CompoundingEngine(config, this.storage) : void 0;
|
|
17860
16406
|
this.buffer = new SmartBuffer(config, this.storage);
|
|
17861
16407
|
this.transcript = new TranscriptManager(config);
|
|
17862
|
-
this.conversationIndexDir =
|
|
16408
|
+
this.conversationIndexDir = path16.join(
|
|
17863
16409
|
config.memoryDir,
|
|
17864
16410
|
"conversation-index",
|
|
17865
16411
|
"chunks"
|
|
@@ -18006,7 +16552,7 @@ var Orchestrator = class {
|
|
|
18006
16552
|
saveContentHashIndexes: () => this.saveContentHashIndexes()
|
|
18007
16553
|
});
|
|
18008
16554
|
this.threading = new ThreadingManager(
|
|
18009
|
-
|
|
16555
|
+
path16.join(config.memoryDir, "threads"),
|
|
18010
16556
|
config.threadingGapMinutes
|
|
18011
16557
|
);
|
|
18012
16558
|
const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);
|
|
@@ -18086,7 +16632,7 @@ var Orchestrator = class {
|
|
|
18086
16632
|
utilityPromoteThresholdDelta: this.utilityRuntimeValues?.promoteThresholdDelta ?? 0,
|
|
18087
16633
|
utilityDemoteThresholdDelta: this.utilityRuntimeValues?.demoteThresholdDelta ?? 0
|
|
18088
16634
|
};
|
|
18089
|
-
return
|
|
16635
|
+
return createHash6("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 12);
|
|
18090
16636
|
}
|
|
18091
16637
|
effectiveLifecycleThresholds() {
|
|
18092
16638
|
const archiveDecayThreshold = this.config.lifecycleArchiveDecayThreshold;
|
|
@@ -20112,9 +18658,9 @@ function readStructuralSymbol(entry) {
|
|
|
20112
18658
|
const rec = entry;
|
|
20113
18659
|
const symbol = typeof rec.symbol === "string" ? rec.symbol.trim() : "";
|
|
20114
18660
|
if (!symbol) return null;
|
|
20115
|
-
const
|
|
18661
|
+
const path31 = typeof rec.path === "string" && rec.path.length > 0 ? rec.path : void 0;
|
|
20116
18662
|
const kind = typeof rec.kind === "string" && rec.kind.length > 0 ? rec.kind : void 0;
|
|
20117
|
-
const item =
|
|
18663
|
+
const item = path31 !== void 0 && kind !== void 0 ? { symbol, path: path31, kind } : path31 !== void 0 ? { symbol, path: path31 } : kind !== void 0 ? { symbol, kind } : { symbol };
|
|
20118
18664
|
return item;
|
|
20119
18665
|
}
|
|
20120
18666
|
function classifySpawnError(err) {
|
|
@@ -20188,7 +18734,7 @@ var DEFAULT_GRACE_PERIOD_DAYS = 7;
|
|
|
20188
18734
|
|
|
20189
18735
|
// src/binary-lifecycle/backend.ts
|
|
20190
18736
|
import fsp from "fs/promises";
|
|
20191
|
-
import
|
|
18737
|
+
import path17 from "path";
|
|
20192
18738
|
var FilesystemBackend = class {
|
|
20193
18739
|
type = "filesystem";
|
|
20194
18740
|
basePath;
|
|
@@ -20196,19 +18742,19 @@ var FilesystemBackend = class {
|
|
|
20196
18742
|
if (!basePath || basePath.trim().length === 0) {
|
|
20197
18743
|
throw new Error("FilesystemBackend requires a non-empty basePath");
|
|
20198
18744
|
}
|
|
20199
|
-
this.basePath =
|
|
18745
|
+
this.basePath = path17.resolve(basePath);
|
|
20200
18746
|
}
|
|
20201
18747
|
resolveRemotePath(remotePath) {
|
|
20202
|
-
const resolved =
|
|
20203
|
-
const relative =
|
|
20204
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
18748
|
+
const resolved = path17.isAbsolute(remotePath) ? path17.resolve(remotePath) : path17.resolve(this.basePath, remotePath);
|
|
18749
|
+
const relative = path17.relative(this.basePath, resolved);
|
|
18750
|
+
if (relative === ".." || relative.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative)) {
|
|
20205
18751
|
throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);
|
|
20206
18752
|
}
|
|
20207
18753
|
return resolved;
|
|
20208
18754
|
}
|
|
20209
18755
|
isInsideBase(candidate, realBase) {
|
|
20210
|
-
const relative =
|
|
20211
|
-
return relative === "" || relative !== ".." && !relative.startsWith(`..${
|
|
18756
|
+
const relative = path17.relative(realBase, candidate);
|
|
18757
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${path17.sep}`) && !path17.isAbsolute(relative);
|
|
20212
18758
|
}
|
|
20213
18759
|
async realBasePathIfExists() {
|
|
20214
18760
|
try {
|
|
@@ -20237,13 +18783,13 @@ var FilesystemBackend = class {
|
|
|
20237
18783
|
}
|
|
20238
18784
|
async ensureSafeParentDirectory(dest) {
|
|
20239
18785
|
const realBase = await this.ensureBaseDirectory();
|
|
20240
|
-
const destDir =
|
|
20241
|
-
const relativeDir =
|
|
20242
|
-
const segments = relativeDir === "" ? [] : relativeDir.split(
|
|
18786
|
+
const destDir = path17.dirname(dest);
|
|
18787
|
+
const relativeDir = path17.relative(this.basePath, destDir);
|
|
18788
|
+
const segments = relativeDir === "" ? [] : relativeDir.split(path17.sep);
|
|
20243
18789
|
let current = this.basePath;
|
|
20244
18790
|
for (const segment of segments) {
|
|
20245
18791
|
if (segment === "." || segment === "") continue;
|
|
20246
|
-
current =
|
|
18792
|
+
current = path17.join(current, segment);
|
|
20247
18793
|
try {
|
|
20248
18794
|
const stat5 = await fsp.lstat(current);
|
|
20249
18795
|
if (stat5.isSymbolicLink()) {
|
|
@@ -20271,13 +18817,13 @@ var FilesystemBackend = class {
|
|
|
20271
18817
|
if (realBase === null) {
|
|
20272
18818
|
return null;
|
|
20273
18819
|
}
|
|
20274
|
-
const destDir =
|
|
20275
|
-
const relativeDir =
|
|
20276
|
-
const segments = relativeDir === "" ? [] : relativeDir.split(
|
|
18820
|
+
const destDir = path17.dirname(dest);
|
|
18821
|
+
const relativeDir = path17.relative(this.basePath, destDir);
|
|
18822
|
+
const segments = relativeDir === "" ? [] : relativeDir.split(path17.sep);
|
|
20277
18823
|
let current = this.basePath;
|
|
20278
18824
|
for (const segment of segments) {
|
|
20279
18825
|
if (segment === "." || segment === "") continue;
|
|
20280
|
-
current =
|
|
18826
|
+
current = path17.join(current, segment);
|
|
20281
18827
|
let stat5;
|
|
20282
18828
|
try {
|
|
20283
18829
|
stat5 = await fsp.lstat(current);
|
|
@@ -20325,7 +18871,7 @@ var FilesystemBackend = class {
|
|
|
20325
18871
|
return dest;
|
|
20326
18872
|
}
|
|
20327
18873
|
async upload(localPath, remotePath) {
|
|
20328
|
-
if (
|
|
18874
|
+
if (path17.isAbsolute(remotePath)) {
|
|
20329
18875
|
throw new Error(`FilesystemBackend upload remotePath must be relative: ${JSON.stringify(remotePath)}`);
|
|
20330
18876
|
}
|
|
20331
18877
|
const dest = this.resolveRemotePath(remotePath);
|
|
@@ -20398,7 +18944,7 @@ function createBackend(cfg) {
|
|
|
20398
18944
|
|
|
20399
18945
|
// src/binary-lifecycle/scanner.ts
|
|
20400
18946
|
import fsp2 from "fs/promises";
|
|
20401
|
-
import
|
|
18947
|
+
import path18 from "path";
|
|
20402
18948
|
import crypto from "crypto";
|
|
20403
18949
|
function matchesPatterns(filename, patterns) {
|
|
20404
18950
|
const lower = filename.toLowerCase();
|
|
@@ -20423,8 +18969,8 @@ async function scanForBinaries(memoryDir, config, manifest) {
|
|
|
20423
18969
|
return;
|
|
20424
18970
|
}
|
|
20425
18971
|
for (const entry of entries) {
|
|
20426
|
-
const fullPath =
|
|
20427
|
-
const relativePath =
|
|
18972
|
+
const fullPath = path18.join(dir, entry.name);
|
|
18973
|
+
const relativePath = path18.relative(memoryDir, fullPath).split(path18.sep).join("/");
|
|
20428
18974
|
if (entry.isDirectory()) {
|
|
20429
18975
|
if (entry.name === ".binary-lifecycle") continue;
|
|
20430
18976
|
await walk(fullPath);
|
|
@@ -20464,15 +19010,15 @@ async function hashFile(filePath) {
|
|
|
20464
19010
|
|
|
20465
19011
|
// src/binary-lifecycle/manifest.ts
|
|
20466
19012
|
import fsp3 from "fs/promises";
|
|
20467
|
-
import
|
|
19013
|
+
import path19 from "path";
|
|
20468
19014
|
import crypto2 from "crypto";
|
|
20469
19015
|
var MANIFEST_DIR = ".binary-lifecycle";
|
|
20470
19016
|
var MANIFEST_FILE = "manifest.json";
|
|
20471
19017
|
function manifestDir(memoryDir) {
|
|
20472
|
-
return
|
|
19018
|
+
return path19.join(memoryDir, MANIFEST_DIR);
|
|
20473
19019
|
}
|
|
20474
19020
|
function manifestPath(memoryDir) {
|
|
20475
|
-
return
|
|
19021
|
+
return path19.join(memoryDir, MANIFEST_DIR, MANIFEST_FILE);
|
|
20476
19022
|
}
|
|
20477
19023
|
async function readManifest(memoryDir) {
|
|
20478
19024
|
const filePath = manifestPath(memoryDir);
|
|
@@ -20524,12 +19070,12 @@ function emptyManifest() {
|
|
|
20524
19070
|
|
|
20525
19071
|
// src/binary-lifecycle/pipeline.ts
|
|
20526
19072
|
import fsp4 from "fs/promises";
|
|
20527
|
-
import
|
|
19073
|
+
import path20 from "path";
|
|
20528
19074
|
import crypto3 from "crypto";
|
|
20529
19075
|
function isRecallCorpusMarkdown(mdPath, memoryDir) {
|
|
20530
|
-
const rel =
|
|
20531
|
-
if (rel.startsWith("..") ||
|
|
20532
|
-
const top = rel.split(
|
|
19076
|
+
const rel = path20.relative(memoryDir, mdPath);
|
|
19077
|
+
if (rel.startsWith("..") || path20.isAbsolute(rel)) return false;
|
|
19078
|
+
const top = rel.split(path20.sep)[0];
|
|
20533
19079
|
return RECALL_FALLBACK_DIRS.includes(top);
|
|
20534
19080
|
}
|
|
20535
19081
|
async function hashFile2(filePath) {
|
|
@@ -20553,13 +19099,13 @@ function escapeRegex(s) {
|
|
|
20553
19099
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
20554
19100
|
}
|
|
20555
19101
|
function resolveManifestAssetPath(memoryDir, originalPath) {
|
|
20556
|
-
if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") ||
|
|
19102
|
+
if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") || path20.isAbsolute(originalPath) || path20.win32.isAbsolute(originalPath)) {
|
|
20557
19103
|
return null;
|
|
20558
19104
|
}
|
|
20559
|
-
const memoryRoot =
|
|
20560
|
-
const fullPath =
|
|
20561
|
-
const relative =
|
|
20562
|
-
if (relative === "" || relative === ".." || relative.startsWith(`..${
|
|
19105
|
+
const memoryRoot = path20.resolve(memoryDir);
|
|
19106
|
+
const fullPath = path20.resolve(memoryRoot, originalPath);
|
|
19107
|
+
const relative = path20.relative(memoryRoot, fullPath);
|
|
19108
|
+
if (relative === "" || relative === ".." || relative.startsWith(`..${path20.sep}`) || path20.isAbsolute(relative)) {
|
|
20563
19109
|
return null;
|
|
20564
19110
|
}
|
|
20565
19111
|
return fullPath;
|
|
@@ -20570,7 +19116,7 @@ function validateBinaryLifecycleConfig(config) {
|
|
|
20570
19116
|
}
|
|
20571
19117
|
}
|
|
20572
19118
|
function remotePathForAsset(backend, relPath) {
|
|
20573
|
-
const normalized = relPath.split(
|
|
19119
|
+
const normalized = relPath.split(path20.sep).join("/");
|
|
20574
19120
|
if (backend.type === "filesystem") {
|
|
20575
19121
|
return `.binary-lifecycle/mirrors/${normalized}`;
|
|
20576
19122
|
}
|
|
@@ -20583,11 +19129,11 @@ async function stageMirror(memoryDir, newPaths, backend, assets, log2, dryRun) {
|
|
|
20583
19129
|
let mirrored = 0;
|
|
20584
19130
|
const errors = [];
|
|
20585
19131
|
for (const relPath of newPaths) {
|
|
20586
|
-
const fullPath =
|
|
19132
|
+
const fullPath = path20.join(memoryDir, relPath);
|
|
20587
19133
|
try {
|
|
20588
19134
|
const stat5 = await fsp4.stat(fullPath);
|
|
20589
19135
|
const contentHash = await hashFile2(fullPath);
|
|
20590
|
-
const ext =
|
|
19136
|
+
const ext = path20.extname(relPath);
|
|
20591
19137
|
const mimeType = guessMimeType(ext);
|
|
20592
19138
|
const remotePath = remotePathForAsset(backend, relPath);
|
|
20593
19139
|
let backendLocation = remotePath;
|
|
@@ -20790,10 +19336,10 @@ async function countRemainingLocalReferences(memoryDir, asset, assetAbsolute, md
|
|
|
20790
19336
|
return { remaining, errors };
|
|
20791
19337
|
}
|
|
20792
19338
|
function markdownReferencePattern(asset, assetAbsolute, mdPath) {
|
|
20793
|
-
const mdDir =
|
|
19339
|
+
const mdDir = path20.dirname(mdPath);
|
|
20794
19340
|
const candidates = /* @__PURE__ */ new Set();
|
|
20795
19341
|
const addCandidate = (candidate) => {
|
|
20796
|
-
const normalized = candidate.split(
|
|
19342
|
+
const normalized = candidate.split(path20.sep).join("/");
|
|
20797
19343
|
if (normalized.length === 0) return;
|
|
20798
19344
|
candidates.add(normalized);
|
|
20799
19345
|
const isParentTraversal = normalized === ".." || normalized.startsWith("../");
|
|
@@ -20801,10 +19347,10 @@ function markdownReferencePattern(asset, assetAbsolute, mdPath) {
|
|
|
20801
19347
|
candidates.add(`./${normalized}`);
|
|
20802
19348
|
}
|
|
20803
19349
|
};
|
|
20804
|
-
addCandidate(
|
|
20805
|
-
const originalPath = asset.originalPath.split(
|
|
20806
|
-
const originalAsFileRelative =
|
|
20807
|
-
if (
|
|
19350
|
+
addCandidate(path20.relative(mdDir, assetAbsolute));
|
|
19351
|
+
const originalPath = asset.originalPath.split(path20.sep).join("/");
|
|
19352
|
+
const originalAsFileRelative = path20.resolve(mdDir, ...originalPath.split("/"));
|
|
19353
|
+
if (path20.resolve(originalAsFileRelative) === path20.resolve(assetAbsolute)) {
|
|
20808
19354
|
addCandidate(originalPath);
|
|
20809
19355
|
}
|
|
20810
19356
|
addCandidate(`/${originalPath}`);
|
|
@@ -20900,7 +19446,7 @@ async function findMarkdownFiles(dir) {
|
|
|
20900
19446
|
return;
|
|
20901
19447
|
}
|
|
20902
19448
|
for (const entry of entries) {
|
|
20903
|
-
const full =
|
|
19449
|
+
const full = path20.join(current, entry.name);
|
|
20904
19450
|
if (entry.isDirectory()) {
|
|
20905
19451
|
if (entry.name === ".binary-lifecycle") continue;
|
|
20906
19452
|
await walk(full);
|
|
@@ -20975,7 +19521,7 @@ async function runBinaryLifecyclePipeline(memoryDir, config, backend, log2, opts
|
|
|
20975
19521
|
|
|
20976
19522
|
// src/projection/index.ts
|
|
20977
19523
|
import fs from "fs";
|
|
20978
|
-
import
|
|
19524
|
+
import path21 from "path";
|
|
20979
19525
|
var VALID_PROJECTION_CATEGORIES = new Set(ALL_CATEGORY_KEYS);
|
|
20980
19526
|
async function generateContextTree(options) {
|
|
20981
19527
|
const startTime = Date.now();
|
|
@@ -20990,8 +19536,8 @@ async function generateContextTree(options) {
|
|
|
20990
19536
|
let nodesGenerated = 0;
|
|
20991
19537
|
let nodesSkipped = 0;
|
|
20992
19538
|
const categoryCounts = {};
|
|
20993
|
-
const resolvedMemoryDir =
|
|
20994
|
-
const resolvedOutputDir =
|
|
19539
|
+
const resolvedMemoryDir = path21.resolve(memoryDir);
|
|
19540
|
+
const resolvedOutputDir = path21.resolve(outputDir);
|
|
20995
19541
|
const requestedCategories = validateProjectionCategories(filterCategories);
|
|
20996
19542
|
const realMemoryDir = assertSafeMemoryRoot(resolvedMemoryDir);
|
|
20997
19543
|
assertNotSymlink(resolvedOutputDir, "context tree outputDir");
|
|
@@ -21029,7 +19575,7 @@ async function generateContextTree(options) {
|
|
|
21029
19575
|
}
|
|
21030
19576
|
}
|
|
21031
19577
|
if (includeEntities) {
|
|
21032
|
-
const entitiesDir =
|
|
19578
|
+
const entitiesDir = path21.join(memoryDir, "entities");
|
|
21033
19579
|
if (fs.existsSync(entitiesDir)) {
|
|
21034
19580
|
assertSafeInputRoot(realMemoryDir, entitiesDir, "entities root");
|
|
21035
19581
|
categoryCounts["entity"] = 0;
|
|
@@ -21041,7 +19587,7 @@ async function generateContextTree(options) {
|
|
|
21041
19587
|
continue;
|
|
21042
19588
|
}
|
|
21043
19589
|
const content = fs.readFileSync(filePath, "utf8");
|
|
21044
|
-
const fileName =
|
|
19590
|
+
const fileName = path21.basename(filePath, ".md");
|
|
21045
19591
|
const node = projectEntityNode(fileName, content);
|
|
21046
19592
|
const outputPath = resolveContainedOutputPath(realOutputDir, "entities", `${fileName}.md`);
|
|
21047
19593
|
writeProjectedContent(realOutputDir, outputPath, node.content);
|
|
@@ -21053,7 +19599,7 @@ async function generateContextTree(options) {
|
|
|
21053
19599
|
}
|
|
21054
19600
|
const shouldIncludeQuestions = includeQuestions && (requestedCategories === void 0 || requestedCategories.includes("question"));
|
|
21055
19601
|
if (shouldIncludeQuestions) {
|
|
21056
|
-
const questionsDir =
|
|
19602
|
+
const questionsDir = path21.join(memoryDir, "questions");
|
|
21057
19603
|
if (fs.existsSync(questionsDir)) {
|
|
21058
19604
|
assertSafeInputRoot(realMemoryDir, questionsDir, "questions root");
|
|
21059
19605
|
categoryCounts["question"] = 0;
|
|
@@ -21094,8 +19640,8 @@ async function generateContextTree(options) {
|
|
|
21094
19640
|
};
|
|
21095
19641
|
}
|
|
21096
19642
|
function isPathInside(root, candidate) {
|
|
21097
|
-
const relative =
|
|
21098
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
19643
|
+
const relative = path21.relative(root, candidate);
|
|
19644
|
+
return relative === "" || !relative.startsWith("..") && !path21.isAbsolute(relative);
|
|
21099
19645
|
}
|
|
21100
19646
|
function assertNotSymlink(targetPath, label) {
|
|
21101
19647
|
try {
|
|
@@ -21132,12 +19678,12 @@ function assertSafeInputRoot(realMemoryDir, targetPath, label) {
|
|
|
21132
19678
|
}
|
|
21133
19679
|
function assertSafeOutputTarget(realOutputDir, outputPath) {
|
|
21134
19680
|
let current = realOutputDir;
|
|
21135
|
-
const relative =
|
|
21136
|
-
if (relative.startsWith("..") ||
|
|
19681
|
+
const relative = path21.relative(realOutputDir, outputPath);
|
|
19682
|
+
if (relative.startsWith("..") || path21.isAbsolute(relative)) {
|
|
21137
19683
|
throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
|
|
21138
19684
|
}
|
|
21139
|
-
for (const segment of relative.split(
|
|
21140
|
-
current =
|
|
19685
|
+
for (const segment of relative.split(path21.sep).filter(Boolean)) {
|
|
19686
|
+
current = path21.join(current, segment);
|
|
21141
19687
|
try {
|
|
21142
19688
|
const stat5 = fs.lstatSync(current);
|
|
21143
19689
|
if (stat5.isSymbolicLink()) {
|
|
@@ -21167,17 +19713,17 @@ function validateProjectionCategories(categories) {
|
|
|
21167
19713
|
return validated;
|
|
21168
19714
|
}
|
|
21169
19715
|
function resolveContainedOutputPath(outputRoot, ...segments) {
|
|
21170
|
-
const resolved =
|
|
21171
|
-
const relative =
|
|
21172
|
-
if (relative === "" || !relative.startsWith("..") && !
|
|
19716
|
+
const resolved = path21.resolve(outputRoot, ...segments);
|
|
19717
|
+
const relative = path21.relative(outputRoot, resolved);
|
|
19718
|
+
if (relative === "" || !relative.startsWith("..") && !path21.isAbsolute(relative)) {
|
|
21173
19719
|
return resolved;
|
|
21174
19720
|
}
|
|
21175
19721
|
throw new Error(`context tree output path escapes outputDir: ${segments.join("/")}`);
|
|
21176
19722
|
}
|
|
21177
19723
|
function writeProjectedContent(realOutputDir, outputPath, generatedContent) {
|
|
21178
19724
|
assertSafeOutputTarget(realOutputDir, outputPath);
|
|
21179
|
-
fs.mkdirSync(
|
|
21180
|
-
const realParent = fs.realpathSync(
|
|
19725
|
+
fs.mkdirSync(path21.dirname(outputPath), { recursive: true });
|
|
19726
|
+
const realParent = fs.realpathSync(path21.dirname(outputPath));
|
|
21181
19727
|
if (!isPathInside(realOutputDir, realParent)) {
|
|
21182
19728
|
throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
|
|
21183
19729
|
}
|
|
@@ -21216,7 +19762,7 @@ function walkR(dir, realMemoryDir) {
|
|
|
21216
19762
|
const results = [];
|
|
21217
19763
|
function walk(directory) {
|
|
21218
19764
|
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
21219
|
-
const fullPath =
|
|
19765
|
+
const fullPath = path21.join(directory, entry.name);
|
|
21220
19766
|
if (entry.isSymbolicLink()) {
|
|
21221
19767
|
throw new Error(`context tree input path contains symlink: ${fullPath}`);
|
|
21222
19768
|
}
|
|
@@ -21269,13 +19815,13 @@ function extractBody(content) {
|
|
|
21269
19815
|
}
|
|
21270
19816
|
function projectNode(filePath, category, fm, rawContent) {
|
|
21271
19817
|
const body = extractBody(rawContent);
|
|
21272
|
-
const fileName =
|
|
21273
|
-
const dateDir =
|
|
19818
|
+
const fileName = path21.basename(filePath, ".md");
|
|
19819
|
+
const dateDir = path21.basename(path21.dirname(filePath));
|
|
21274
19820
|
let relPath;
|
|
21275
19821
|
if (/^\d{4}-\d{2}-\d{2}$/.test(dateDir)) {
|
|
21276
|
-
relPath =
|
|
19822
|
+
relPath = path21.join(category, dateDir, `${fileName}.md`);
|
|
21277
19823
|
} else {
|
|
21278
|
-
relPath =
|
|
19824
|
+
relPath = path21.join(category, `${fileName}.md`);
|
|
21279
19825
|
}
|
|
21280
19826
|
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21281
19827
|
const md = `# ${fm.id}
|
|
@@ -21321,7 +19867,7 @@ function projectEntityNode(fileName, content) {
|
|
|
21321
19867
|
${content}
|
|
21322
19868
|
`;
|
|
21323
19869
|
return {
|
|
21324
|
-
path:
|
|
19870
|
+
path: path21.join("entities", `${fileName}.md`),
|
|
21325
19871
|
category: "entity",
|
|
21326
19872
|
title: fileName,
|
|
21327
19873
|
content: md,
|
|
@@ -21374,7 +19920,7 @@ function generateIndex(categoryCounts, outputDir) {
|
|
|
21374
19920
|
|
|
21375
19921
|
// src/onboarding/index.ts
|
|
21376
19922
|
import fs2 from "fs";
|
|
21377
|
-
import
|
|
19923
|
+
import path22 from "path";
|
|
21378
19924
|
var LANGUAGE_RULES = [
|
|
21379
19925
|
{
|
|
21380
19926
|
language: "TypeScript",
|
|
@@ -21476,7 +20022,7 @@ function onboard(options) {
|
|
|
21476
20022
|
maxDepth = 6,
|
|
21477
20023
|
excludeDirs = []
|
|
21478
20024
|
} = options;
|
|
21479
|
-
const directory =
|
|
20025
|
+
const directory = path22.resolve(options.directory ?? process.cwd());
|
|
21480
20026
|
let rootStat;
|
|
21481
20027
|
try {
|
|
21482
20028
|
rootStat = fs2.statSync(directory);
|
|
@@ -21518,7 +20064,7 @@ function walkDir(root, exclude, maxDepth) {
|
|
|
21518
20064
|
}
|
|
21519
20065
|
for (const entry of entries) {
|
|
21520
20066
|
if (exclude.has(entry.name)) continue;
|
|
21521
|
-
const fullPath =
|
|
20067
|
+
const fullPath = path22.join(dir, entry.name);
|
|
21522
20068
|
if (entry.isDirectory()) {
|
|
21523
20069
|
walk(fullPath, depth + 1);
|
|
21524
20070
|
} else if (entry.isFile()) {
|
|
@@ -21533,11 +20079,11 @@ function detectLanguages(files, root) {
|
|
|
21533
20079
|
const results = [];
|
|
21534
20080
|
const extCounts = /* @__PURE__ */ new Map();
|
|
21535
20081
|
for (const f of files) {
|
|
21536
|
-
const ext =
|
|
20082
|
+
const ext = path22.extname(f).toLowerCase();
|
|
21537
20083
|
if (ext) extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
|
|
21538
20084
|
}
|
|
21539
20085
|
const rootFiles = new Set(
|
|
21540
|
-
files.filter((f) =>
|
|
20086
|
+
files.filter((f) => path22.dirname(f) === root).map((f) => path22.basename(f))
|
|
21541
20087
|
);
|
|
21542
20088
|
for (const rule of LANGUAGE_RULES) {
|
|
21543
20089
|
const evidence = [];
|
|
@@ -21581,7 +20127,7 @@ function detectLanguages(files, root) {
|
|
|
21581
20127
|
}
|
|
21582
20128
|
function detectShape(files, root) {
|
|
21583
20129
|
const rootFiles = new Set(
|
|
21584
|
-
files.filter((f) =>
|
|
20130
|
+
files.filter((f) => path22.dirname(f) === root).map((f) => path22.basename(f))
|
|
21585
20131
|
);
|
|
21586
20132
|
const rootDirs = /* @__PURE__ */ new Set();
|
|
21587
20133
|
try {
|
|
@@ -21592,7 +20138,7 @@ function detectShape(files, root) {
|
|
|
21592
20138
|
}
|
|
21593
20139
|
const evidence = [];
|
|
21594
20140
|
if (rootFiles.has("package.json")) {
|
|
21595
|
-
const pkg = readJsonSafe(
|
|
20141
|
+
const pkg = readJsonSafe(path22.join(root, "package.json"));
|
|
21596
20142
|
if (pkg?.workspaces) {
|
|
21597
20143
|
evidence.push("package.json has workspaces");
|
|
21598
20144
|
return { shape: "monorepo", evidence };
|
|
@@ -21606,13 +20152,13 @@ function detectShape(files, root) {
|
|
|
21606
20152
|
evidence.push("workspace manifest found");
|
|
21607
20153
|
return { shape: "workspace", evidence };
|
|
21608
20154
|
}
|
|
21609
|
-
const cargoToml = readTomlWorkspace(
|
|
20155
|
+
const cargoToml = readTomlWorkspace(path22.join(root, "Cargo.toml"));
|
|
21610
20156
|
if (cargoToml) {
|
|
21611
20157
|
evidence.push("Cargo.toml has workspace");
|
|
21612
20158
|
return { shape: "workspace", evidence };
|
|
21613
20159
|
}
|
|
21614
20160
|
if (rootFiles.has("package.json")) {
|
|
21615
|
-
const pkg = readJsonSafe(
|
|
20161
|
+
const pkg = readJsonSafe(path22.join(root, "package.json"));
|
|
21616
20162
|
if (pkg?.exports || pkg?.main) {
|
|
21617
20163
|
if (pkg?.bin) {
|
|
21618
20164
|
evidence.push("package.json has bin");
|
|
@@ -21646,8 +20192,8 @@ function discoverDocs(files, root) {
|
|
|
21646
20192
|
{ pattern: /^\.editorconfig$/i, kind: "config" }
|
|
21647
20193
|
];
|
|
21648
20194
|
for (const filePath of files) {
|
|
21649
|
-
const basename =
|
|
21650
|
-
const relPath =
|
|
20195
|
+
const basename = path22.basename(filePath).toLowerCase();
|
|
20196
|
+
const relPath = path22.relative(root, filePath);
|
|
21651
20197
|
let kind;
|
|
21652
20198
|
for (const { pattern, kind: k } of docPatterns) {
|
|
21653
20199
|
if (pattern.test(basename)) {
|
|
@@ -21659,7 +20205,7 @@ function discoverDocs(files, root) {
|
|
|
21659
20205
|
kind = "docs";
|
|
21660
20206
|
}
|
|
21661
20207
|
if (!kind && (basename.endsWith(".md") || basename.endsWith(".mdx"))) {
|
|
21662
|
-
if (
|
|
20208
|
+
if (path22.dirname(relPath) === "." || isUnderDocsDir(relPath)) {
|
|
21663
20209
|
kind = "docs";
|
|
21664
20210
|
}
|
|
21665
20211
|
}
|
|
@@ -21680,7 +20226,7 @@ function discoverDocs(files, root) {
|
|
|
21680
20226
|
return docs;
|
|
21681
20227
|
}
|
|
21682
20228
|
function isUnderDocsDir(relPath) {
|
|
21683
|
-
const parts = relPath.split(
|
|
20229
|
+
const parts = relPath.split(path22.sep);
|
|
21684
20230
|
return parts[0] === "docs" || parts[0] === "doc" || parts[0] === "documentation";
|
|
21685
20231
|
}
|
|
21686
20232
|
function buildPlan(languages, shape, docs, _root) {
|
|
@@ -21724,7 +20270,7 @@ function readTomlWorkspace(filePath) {
|
|
|
21724
20270
|
|
|
21725
20271
|
// src/curation/index.ts
|
|
21726
20272
|
import fs3 from "fs";
|
|
21727
|
-
import
|
|
20273
|
+
import path23 from "path";
|
|
21728
20274
|
import crypto4 from "crypto";
|
|
21729
20275
|
async function curate(options) {
|
|
21730
20276
|
const startTime = Date.now();
|
|
@@ -21815,12 +20361,12 @@ function resolveTargets(targetPath) {
|
|
|
21815
20361
|
const extensions = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
|
|
21816
20362
|
function walk(dir) {
|
|
21817
20363
|
for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
21818
|
-
const fullPath =
|
|
20364
|
+
const fullPath = path23.join(dir, entry.name);
|
|
21819
20365
|
if (entry.isDirectory()) {
|
|
21820
20366
|
if (entry.name !== "node_modules" && entry.name !== ".git") {
|
|
21821
20367
|
walk(fullPath);
|
|
21822
20368
|
}
|
|
21823
|
-
} else if (extensions.has(
|
|
20369
|
+
} else if (extensions.has(path23.extname(entry.name).toLowerCase())) {
|
|
21824
20370
|
results.push(fullPath);
|
|
21825
20371
|
}
|
|
21826
20372
|
}
|
|
@@ -21829,12 +20375,12 @@ function resolveTargets(targetPath) {
|
|
|
21829
20375
|
return results;
|
|
21830
20376
|
}
|
|
21831
20377
|
function resolveProvenanceRoot(targetPath) {
|
|
21832
|
-
const resolvedTarget =
|
|
20378
|
+
const resolvedTarget = path23.resolve(targetPath);
|
|
21833
20379
|
const stat5 = fs3.statSync(resolvedTarget);
|
|
21834
|
-
return stat5.isFile() ?
|
|
20380
|
+
return stat5.isFile() ? path23.dirname(resolvedTarget) : resolvedTarget;
|
|
21835
20381
|
}
|
|
21836
20382
|
function extractStatements(content, filePath, projectRoot, source, sourceFileHash, categoryOverride, confidence, entityRef, tags) {
|
|
21837
|
-
const relativePath =
|
|
20383
|
+
const relativePath = path23.relative(projectRoot, path23.resolve(filePath)) || path23.basename(filePath);
|
|
21838
20384
|
const statements = [];
|
|
21839
20385
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21840
20386
|
const paragraphs = content.split(/\n{2,}/).map((p) => p.trim()).filter((p) => p.length > 20 && p.length < 2e3);
|
|
@@ -21928,7 +20474,7 @@ function loadExistingMemories(memoryDir) {
|
|
|
21928
20474
|
if (!fs3.existsSync(memoryDir)) return result;
|
|
21929
20475
|
const dirs = ALL_CATEGORY_DIRS;
|
|
21930
20476
|
for (const dir of dirs) {
|
|
21931
|
-
const fullDir =
|
|
20477
|
+
const fullDir = path23.join(memoryDir, dir);
|
|
21932
20478
|
if (!fs3.existsSync(fullDir)) continue;
|
|
21933
20479
|
walkFiles(fullDir, (filePath) => {
|
|
21934
20480
|
const content = readFileSafe(filePath);
|
|
@@ -21950,10 +20496,10 @@ function writeStatement(stmt, memoryDir) {
|
|
|
21950
20496
|
const now = /* @__PURE__ */ new Date();
|
|
21951
20497
|
const dateDir = now.toISOString().split("T")[0];
|
|
21952
20498
|
const categoryDir = getCategoryDir(memoryDir, stmt.category);
|
|
21953
|
-
const dir =
|
|
20499
|
+
const dir = path23.join(categoryDir, dateDir);
|
|
21954
20500
|
fs3.mkdirSync(dir, { recursive: true });
|
|
21955
20501
|
const fileName = `${stmt.category}-${Date.now()}-${stmt.id.slice(0, 8)}.md`;
|
|
21956
|
-
const filePath =
|
|
20502
|
+
const filePath = path23.join(dir, fileName);
|
|
21957
20503
|
const frontmatter = [
|
|
21958
20504
|
"---",
|
|
21959
20505
|
`id: ${stmt.id}`,
|
|
@@ -22021,7 +20567,7 @@ function extractBody2(content) {
|
|
|
22021
20567
|
}
|
|
22022
20568
|
function walkFiles(dir, callback) {
|
|
22023
20569
|
for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
|
|
22024
|
-
const fullPath =
|
|
20570
|
+
const fullPath = path23.join(dir, entry.name);
|
|
22025
20571
|
if (entry.isDirectory()) {
|
|
22026
20572
|
walkFiles(fullPath, callback);
|
|
22027
20573
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -22032,7 +20578,7 @@ function walkFiles(dir, callback) {
|
|
|
22032
20578
|
|
|
22033
20579
|
// src/dedup/index.ts
|
|
22034
20580
|
import fs4 from "fs";
|
|
22035
|
-
import
|
|
20581
|
+
import path24 from "path";
|
|
22036
20582
|
import crypto5 from "crypto";
|
|
22037
20583
|
var DEFAULT_DEDUP_THRESHOLD = 0.85;
|
|
22038
20584
|
var DEFAULT_MAX_LOAD = 1e4;
|
|
@@ -22174,7 +20720,7 @@ function loadMemories(memoryDir, categories, maxLoad = 1e4) {
|
|
|
22174
20720
|
const memoryRootReal = fs4.realpathSync(memoryDir);
|
|
22175
20721
|
for (const category of allCategories) {
|
|
22176
20722
|
if (result.length >= maxLoad) break;
|
|
22177
|
-
const dir =
|
|
20723
|
+
const dir = path24.join(memoryDir, category);
|
|
22178
20724
|
if (!fs4.existsSync(dir)) continue;
|
|
22179
20725
|
const categoryStat = fs4.lstatSync(dir);
|
|
22180
20726
|
if (categoryStat.isSymbolicLink()) {
|
|
@@ -22235,15 +20781,15 @@ function extractBody3(content) {
|
|
|
22235
20781
|
return match ? match[1].trim() : content.trim();
|
|
22236
20782
|
}
|
|
22237
20783
|
function assertPathInsideRoot2(rootReal, targetReal, sourcePath) {
|
|
22238
|
-
const rel =
|
|
22239
|
-
if (rel === "" || !rel.startsWith("..") && !
|
|
20784
|
+
const rel = path24.relative(rootReal, targetReal);
|
|
20785
|
+
if (rel === "" || !rel.startsWith("..") && !path24.isAbsolute(rel)) {
|
|
22240
20786
|
return;
|
|
22241
20787
|
}
|
|
22242
20788
|
throw new Error(`Refusing to scan memory path outside root: ${sourcePath}`);
|
|
22243
20789
|
}
|
|
22244
20790
|
function walkMdFiles(dir, memoryRootReal, categoryRootReal, callback) {
|
|
22245
20791
|
for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
|
|
22246
|
-
const fullPath =
|
|
20792
|
+
const fullPath = path24.join(dir, entry.name);
|
|
22247
20793
|
const entryStat = fs4.lstatSync(fullPath);
|
|
22248
20794
|
if (entryStat.isSymbolicLink()) {
|
|
22249
20795
|
throw new Error(`Refusing to scan symlinked memory path: ${fullPath}`);
|
|
@@ -22261,7 +20807,7 @@ function walkMdFiles(dir, memoryRootReal, categoryRootReal, callback) {
|
|
|
22261
20807
|
|
|
22262
20808
|
// src/review/index.ts
|
|
22263
20809
|
import fs5 from "fs";
|
|
22264
|
-
import
|
|
20810
|
+
import path25 from "path";
|
|
22265
20811
|
var DEFAULT_CONFIDENCE_THRESHOLD = 0.7;
|
|
22266
20812
|
function realMemoryRoot(memoryDir) {
|
|
22267
20813
|
try {
|
|
@@ -22273,8 +20819,8 @@ function realMemoryRoot(memoryDir) {
|
|
|
22273
20819
|
}
|
|
22274
20820
|
}
|
|
22275
20821
|
function isPathInside2(rootReal, candidateReal) {
|
|
22276
|
-
const relative =
|
|
22277
|
-
return relative === "" || !!relative && !relative.startsWith("..") && !
|
|
20822
|
+
const relative = path25.relative(rootReal, candidateReal);
|
|
20823
|
+
return relative === "" || !!relative && !relative.startsWith("..") && !path25.isAbsolute(relative);
|
|
22278
20824
|
}
|
|
22279
20825
|
function isSafeDirectory(rootReal, dir) {
|
|
22280
20826
|
try {
|
|
@@ -22317,7 +20863,7 @@ function listReviewItems(options) {
|
|
|
22317
20863
|
if (filterReason && item.reviewReason !== filterReason) return;
|
|
22318
20864
|
items.push(item);
|
|
22319
20865
|
};
|
|
22320
|
-
const suggestionsDir =
|
|
20866
|
+
const suggestionsDir = path25.join(memoryDir, "suggestions");
|
|
22321
20867
|
if (!isLimitReached() && fs5.existsSync(suggestionsDir) && isSafeDirectory(rootReal, suggestionsDir)) {
|
|
22322
20868
|
walkMd(rootReal, suggestionsDir, (filePath, content) => {
|
|
22323
20869
|
if (isLimitReached()) return true;
|
|
@@ -22338,7 +20884,7 @@ function listReviewItems(options) {
|
|
|
22338
20884
|
return isLimitReached();
|
|
22339
20885
|
});
|
|
22340
20886
|
}
|
|
22341
|
-
const reviewDir =
|
|
20887
|
+
const reviewDir = path25.join(memoryDir, "review");
|
|
22342
20888
|
if (!isLimitReached() && fs5.existsSync(reviewDir) && isSafeDirectory(rootReal, reviewDir)) {
|
|
22343
20889
|
walkMd(rootReal, reviewDir, (filePath, content) => {
|
|
22344
20890
|
if (isLimitReached()) return true;
|
|
@@ -22363,7 +20909,7 @@ function listReviewItems(options) {
|
|
|
22363
20909
|
const categories = ALL_CATEGORY_DIRS;
|
|
22364
20910
|
for (const category of categories) {
|
|
22365
20911
|
if (isLimitReached()) break;
|
|
22366
|
-
const dir =
|
|
20912
|
+
const dir = path25.join(memoryDir, category);
|
|
22367
20913
|
if (!fs5.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
|
|
22368
20914
|
walkMd(rootReal, dir, (filePath, content) => {
|
|
22369
20915
|
if (isLimitReached()) return true;
|
|
@@ -22443,8 +20989,8 @@ function approveItem(memoryDir, itemId, options) {
|
|
|
22443
20989
|
const targetDir = getCategoryDir(memoryDir, category);
|
|
22444
20990
|
const dateDir = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
22445
20991
|
ensureSafeDirectory(rootReal, targetDir);
|
|
22446
|
-
const outputPath =
|
|
22447
|
-
ensureSafeDirectory(rootReal,
|
|
20992
|
+
const outputPath = path25.join(targetDir, dateDir, path25.basename(found.filePath));
|
|
20993
|
+
ensureSafeDirectory(rootReal, path25.dirname(outputPath));
|
|
22448
20994
|
const promotedPath = writeFileWithoutClobber(outputPath, updatedContent, itemId);
|
|
22449
20995
|
fs5.unlinkSync(found.filePath);
|
|
22450
20996
|
return {
|
|
@@ -22502,13 +21048,13 @@ function findReviewFileById(memoryDir, id, options = {}) {
|
|
|
22502
21048
|
const rootReal = realMemoryRoot(memoryDir);
|
|
22503
21049
|
if (!rootReal) return null;
|
|
22504
21050
|
for (const loc of ["suggestions", "review"]) {
|
|
22505
|
-
const dir =
|
|
21051
|
+
const dir = path25.join(memoryDir, loc);
|
|
22506
21052
|
if (!fs5.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
|
|
22507
21053
|
const found = findFileById(rootReal, dir, id);
|
|
22508
21054
|
if (found) return { filePath: found, location: "queue" };
|
|
22509
21055
|
}
|
|
22510
21056
|
for (const category of ALL_CATEGORY_DIRS) {
|
|
22511
|
-
const dir =
|
|
21057
|
+
const dir = path25.join(memoryDir, category);
|
|
22512
21058
|
if (!fs5.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;
|
|
22513
21059
|
const found = findFileById(rootReal, dir, id, (fm) => isLowConfidenceReviewCandidate(fm, options));
|
|
22514
21060
|
if (found) return { filePath: found, location: "category" };
|
|
@@ -22584,10 +21130,10 @@ function readFileSafe3(filePath) {
|
|
|
22584
21130
|
}
|
|
22585
21131
|
}
|
|
22586
21132
|
function writeFileWithoutClobber(basePath, content, discriminator) {
|
|
22587
|
-
const parsed =
|
|
21133
|
+
const parsed = path25.parse(basePath);
|
|
22588
21134
|
const safeDiscriminator = sanitizeFilePart(discriminator);
|
|
22589
21135
|
for (let attempt = 0; attempt < 1e3; attempt++) {
|
|
22590
|
-
const candidate = attempt === 0 ? basePath :
|
|
21136
|
+
const candidate = attempt === 0 ? basePath : path25.join(
|
|
22591
21137
|
parsed.dir,
|
|
22592
21138
|
`${parsed.name}-${safeDiscriminator}${attempt === 1 ? "" : `-${attempt}`}${parsed.ext || ".md"}`
|
|
22593
21139
|
);
|
|
@@ -22643,7 +21189,7 @@ function extractBody4(content) {
|
|
|
22643
21189
|
function walkMd(rootReal, dir, callback) {
|
|
22644
21190
|
if (!isSafeDirectory(rootReal, dir)) return false;
|
|
22645
21191
|
for (const entry of fs5.readdirSync(dir, { withFileTypes: true })) {
|
|
22646
|
-
const fullPath =
|
|
21192
|
+
const fullPath = path25.join(dir, entry.name);
|
|
22647
21193
|
if (entry.isSymbolicLink()) continue;
|
|
22648
21194
|
if (entry.isDirectory()) {
|
|
22649
21195
|
if (walkMd(rootReal, fullPath, callback)) return true;
|
|
@@ -22658,7 +21204,7 @@ function walkMdPaths(rootReal, dir) {
|
|
|
22658
21204
|
const results = [];
|
|
22659
21205
|
if (!isSafeDirectory(rootReal, dir)) return results;
|
|
22660
21206
|
for (const entry of fs5.readdirSync(dir, { withFileTypes: true })) {
|
|
22661
|
-
const fullPath =
|
|
21207
|
+
const fullPath = path25.join(dir, entry.name);
|
|
22662
21208
|
if (entry.isSymbolicLink()) continue;
|
|
22663
21209
|
if (entry.isDirectory()) {
|
|
22664
21210
|
results.push(...walkMdPaths(rootReal, fullPath));
|
|
@@ -22671,7 +21217,7 @@ function walkMdPaths(rootReal, dir) {
|
|
|
22671
21217
|
|
|
22672
21218
|
// src/sync/index.ts
|
|
22673
21219
|
import fs6 from "fs";
|
|
22674
|
-
import
|
|
21220
|
+
import path26 from "path";
|
|
22675
21221
|
import crypto6 from "crypto";
|
|
22676
21222
|
var DEFAULT_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
|
|
22677
21223
|
var DEFAULT_EXCLUDE2 = /* @__PURE__ */ new Set([
|
|
@@ -22693,7 +21239,7 @@ function syncChanges(options) {
|
|
|
22693
21239
|
} = options;
|
|
22694
21240
|
const extSet = new Set(extensions);
|
|
22695
21241
|
const excludeSet = /* @__PURE__ */ new Set([...DEFAULT_EXCLUDE2, ...excludeDirs]);
|
|
22696
|
-
const stateFilePath = options.stateFile ??
|
|
21242
|
+
const stateFilePath = options.stateFile ?? path26.join(memoryDir, ".sync-state.json");
|
|
22697
21243
|
const prevState = loadState(stateFilePath);
|
|
22698
21244
|
const currentFiles = scanFiles(sourceDir, extSet, excludeSet);
|
|
22699
21245
|
const changes = computeDiff(currentFiles, prevState.fileHashes, sourceDir);
|
|
@@ -22709,7 +21255,7 @@ function syncChanges(options) {
|
|
|
22709
21255
|
for (const [relPath, hash] of Object.entries(currentFiles)) {
|
|
22710
21256
|
newState.fileHashes[relPath] = hash;
|
|
22711
21257
|
}
|
|
22712
|
-
fs6.mkdirSync(
|
|
21258
|
+
fs6.mkdirSync(path26.dirname(stateFilePath), { recursive: true });
|
|
22713
21259
|
fs6.writeFileSync(stateFilePath, JSON.stringify(newState, null, 2));
|
|
22714
21260
|
}
|
|
22715
21261
|
return {
|
|
@@ -22775,13 +21321,13 @@ function scanFiles(root, extensions, exclude) {
|
|
|
22775
21321
|
}
|
|
22776
21322
|
for (const entry of entries) {
|
|
22777
21323
|
if (exclude.has(entry.name)) continue;
|
|
22778
|
-
const fullPath =
|
|
21324
|
+
const fullPath = path26.join(dir, entry.name);
|
|
22779
21325
|
if (entry.isDirectory()) {
|
|
22780
21326
|
walk(fullPath);
|
|
22781
21327
|
} else if (entry.isFile()) {
|
|
22782
|
-
const ext =
|
|
21328
|
+
const ext = path26.extname(entry.name).toLowerCase();
|
|
22783
21329
|
if (!extensions.has(ext)) continue;
|
|
22784
|
-
const relPath =
|
|
21330
|
+
const relPath = path26.relative(root, fullPath);
|
|
22785
21331
|
try {
|
|
22786
21332
|
const content = fs6.readFileSync(fullPath, "utf8");
|
|
22787
21333
|
result[relPath] = hashContent3(content);
|
|
@@ -22796,7 +21342,7 @@ function scanFiles(root, extensions, exclude) {
|
|
|
22796
21342
|
function computeDiff(current, previous, sourceDir) {
|
|
22797
21343
|
const changes = [];
|
|
22798
21344
|
for (const [relPath, hash] of Object.entries(current)) {
|
|
22799
|
-
const fullPath =
|
|
21345
|
+
const fullPath = path26.join(sourceDir, relPath);
|
|
22800
21346
|
if (!(relPath in previous)) {
|
|
22801
21347
|
let size = 0;
|
|
22802
21348
|
try {
|
|
@@ -22829,7 +21375,7 @@ function computeDiff(current, previous, sourceDir) {
|
|
|
22829
21375
|
for (const relPath of Object.keys(previous)) {
|
|
22830
21376
|
if (!(relPath in current)) {
|
|
22831
21377
|
changes.push({
|
|
22832
|
-
filePath:
|
|
21378
|
+
filePath: path26.join(sourceDir, relPath),
|
|
22833
21379
|
relativePath: relPath,
|
|
22834
21380
|
type: "deleted",
|
|
22835
21381
|
currentHash: "",
|
|
@@ -22859,20 +21405,20 @@ function hashContent3(content) {
|
|
|
22859
21405
|
import { spawnSync } from "child_process";
|
|
22860
21406
|
import crypto7 from "crypto";
|
|
22861
21407
|
import fs7 from "fs";
|
|
22862
|
-
import
|
|
21408
|
+
import path27 from "path";
|
|
22863
21409
|
var MANIFEST_VERSION = 1;
|
|
22864
21410
|
var MANIFEST_LOCK_STALE_MS = 3e4;
|
|
22865
21411
|
var MANIFEST_LOCK_TIMEOUT_MS = MANIFEST_LOCK_STALE_MS + 1e4;
|
|
22866
21412
|
var MANIFEST_LOCK_SLEEP_MS = 20;
|
|
22867
21413
|
function normalizeSpaceMemoryDir(memoryDir) {
|
|
22868
|
-
return
|
|
21414
|
+
return path27.resolve(memoryDir);
|
|
22869
21415
|
}
|
|
22870
21416
|
function getSpacesDir(baseDir) {
|
|
22871
21417
|
const homeDir = baseDir ?? resolveHomeDir();
|
|
22872
|
-
return
|
|
21418
|
+
return path27.join(homeDir, ".config", "engram", "spaces");
|
|
22873
21419
|
}
|
|
22874
21420
|
function getManifestPath(baseDir) {
|
|
22875
|
-
return
|
|
21421
|
+
return path27.join(getSpacesDir(baseDir), "manifest.json");
|
|
22876
21422
|
}
|
|
22877
21423
|
function loadManifest(baseDir, memoryDirOverride) {
|
|
22878
21424
|
if (fs7.existsSync(getManifestPath(baseDir))) {
|
|
@@ -22919,9 +21465,9 @@ function readManifestUnlocked(baseDir, memoryDirOverride, options = {}) {
|
|
|
22919
21465
|
}
|
|
22920
21466
|
function saveManifestUnlocked(manifest, baseDir) {
|
|
22921
21467
|
const manifestPath2 = getManifestPath(baseDir);
|
|
22922
|
-
const manifestDir2 =
|
|
21468
|
+
const manifestDir2 = path27.dirname(manifestPath2);
|
|
22923
21469
|
fs7.mkdirSync(manifestDir2, { recursive: true });
|
|
22924
|
-
const tempPath =
|
|
21470
|
+
const tempPath = path27.join(manifestDir2, `.manifest.${process.pid}.${Date.now()}.${crypto7.randomUUID()}.tmp`);
|
|
22925
21471
|
try {
|
|
22926
21472
|
fs7.writeFileSync(tempPath, `${JSON.stringify(manifest, null, 2)}
|
|
22927
21473
|
`, { flag: "wx" });
|
|
@@ -22936,7 +21482,7 @@ function saveManifestUnlocked(manifest, baseDir) {
|
|
|
22936
21482
|
}
|
|
22937
21483
|
function withManifestLock(baseDir, operation) {
|
|
22938
21484
|
const lockDir = `${getManifestPath(baseDir)}.lock`;
|
|
22939
|
-
fs7.mkdirSync(
|
|
21485
|
+
fs7.mkdirSync(path27.dirname(lockDir), { recursive: true });
|
|
22940
21486
|
const lockOwner = acquireManifestLock(lockDir);
|
|
22941
21487
|
try {
|
|
22942
21488
|
return operation();
|
|
@@ -22962,7 +21508,7 @@ function acquireManifestLock(lockDir) {
|
|
|
22962
21508
|
try {
|
|
22963
21509
|
fs7.mkdirSync(lockDir, { recursive: false });
|
|
22964
21510
|
try {
|
|
22965
|
-
fs7.writeFileSync(
|
|
21511
|
+
fs7.writeFileSync(path27.join(lockDir, "owner"), `${owner}
|
|
22966
21512
|
`, { flag: "wx" });
|
|
22967
21513
|
} catch (error) {
|
|
22968
21514
|
fs7.rmSync(lockDir, { recursive: true, force: true });
|
|
@@ -22992,7 +21538,7 @@ function acquireManifestLock(lockDir) {
|
|
|
22992
21538
|
}
|
|
22993
21539
|
function releaseManifestLock(lockDir, owner) {
|
|
22994
21540
|
try {
|
|
22995
|
-
const ownerPath =
|
|
21541
|
+
const ownerPath = path27.join(lockDir, "owner");
|
|
22996
21542
|
if (fs7.readFileSync(ownerPath, "utf8").trim() === owner) {
|
|
22997
21543
|
fs7.rmSync(lockDir, { recursive: true, force: true });
|
|
22998
21544
|
}
|
|
@@ -23008,7 +21554,7 @@ function removeStaleManifestLock(lockDir) {
|
|
|
23008
21554
|
try {
|
|
23009
21555
|
fs7.mkdirSync(reclaimDir, { recursive: false });
|
|
23010
21556
|
try {
|
|
23011
|
-
fs7.writeFileSync(
|
|
21557
|
+
fs7.writeFileSync(path27.join(reclaimDir, "owner"), `${reclaimOwner}
|
|
23012
21558
|
`, { flag: "wx" });
|
|
23013
21559
|
} catch (error) {
|
|
23014
21560
|
fs7.rmSync(reclaimDir, { recursive: true, force: true });
|
|
@@ -23083,7 +21629,7 @@ function readManifestLockSnapshot(lockDir) {
|
|
|
23083
21629
|
throw error;
|
|
23084
21630
|
}
|
|
23085
21631
|
try {
|
|
23086
|
-
const owner = fs7.readFileSync(
|
|
21632
|
+
const owner = fs7.readFileSync(path27.join(lockDir, "owner"), "utf8").trim();
|
|
23087
21633
|
return { mtimeMs: stat5.mtimeMs, owner };
|
|
23088
21634
|
} catch (error) {
|
|
23089
21635
|
if (error.code === "ENOENT") {
|
|
@@ -23155,8 +21701,8 @@ function sleepSync(ms) {
|
|
|
23155
21701
|
}
|
|
23156
21702
|
function createPersonalSpace(baseDir, memoryDirOverride) {
|
|
23157
21703
|
const homeDir = baseDir ?? resolveHomeDir();
|
|
23158
|
-
const standalonePath =
|
|
23159
|
-
const openclawPath =
|
|
21704
|
+
const standalonePath = path27.join(homeDir, ".engram", "memory");
|
|
21705
|
+
const openclawPath = path27.join(homeDir, ".openclaw", "workspace", "memory", "local");
|
|
23160
21706
|
const memoryDir = memoryDirOverride ?? readEnvVar("REMNIC_MEMORY_DIR") ?? readEnvVar("ENGRAM_MEMORY_DIR") ?? (fs7.existsSync(standalonePath) ? standalonePath : fs7.existsSync(openclawPath) ? openclawPath : standalonePath);
|
|
23161
21707
|
const normalizedMemoryDir = normalizeSpaceMemoryDir(memoryDir);
|
|
23162
21708
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -23185,7 +21731,7 @@ function createSpace(options) {
|
|
|
23185
21731
|
const id = options.name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-");
|
|
23186
21732
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23187
21733
|
const memoryDir = normalizeSpaceMemoryDir(
|
|
23188
|
-
options.memoryDir ??
|
|
21734
|
+
options.memoryDir ?? path27.join(getSpacesDir(options.baseDir), id, "memory")
|
|
23189
21735
|
);
|
|
23190
21736
|
const space = updateManifest(options.baseDir, (manifest) => {
|
|
23191
21737
|
if (manifest.spaces.some((s) => s.id === id)) {
|
|
@@ -23406,14 +21952,14 @@ function mergeSpaces(sourceSpaceId, targetSpaceId, options) {
|
|
|
23406
21952
|
};
|
|
23407
21953
|
}
|
|
23408
21954
|
function getAuditLog(baseDir) {
|
|
23409
|
-
const auditPath =
|
|
21955
|
+
const auditPath = path27.join(getSpacesDir(baseDir), "audit.jsonl");
|
|
23410
21956
|
if (!fs7.existsSync(auditPath)) return [];
|
|
23411
21957
|
const lines = fs7.readFileSync(auditPath, "utf8").trim().split("\n");
|
|
23412
21958
|
return lines.filter((l) => l.trim()).map((l) => JSON.parse(l));
|
|
23413
21959
|
}
|
|
23414
21960
|
function appendAudit(entry, baseDir) {
|
|
23415
|
-
const auditPath =
|
|
23416
|
-
fs7.mkdirSync(
|
|
21961
|
+
const auditPath = path27.join(getSpacesDir(baseDir), "audit.jsonl");
|
|
21962
|
+
fs7.mkdirSync(path27.dirname(auditPath), { recursive: true });
|
|
23417
21963
|
const full = {
|
|
23418
21964
|
id: crypto7.randomUUID(),
|
|
23419
21965
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -23445,8 +21991,8 @@ function copyMemories(sourceDir, targetDir, options) {
|
|
|
23445
21991
|
continue;
|
|
23446
21992
|
}
|
|
23447
21993
|
const content = fs7.readFileSync(sourcePath, "utf8");
|
|
23448
|
-
const relativePath =
|
|
23449
|
-
const targetPath =
|
|
21994
|
+
const relativePath = path27.relative(sourceRoot, sourceRealPath);
|
|
21995
|
+
const targetPath = path27.resolve(targetRoot, relativePath);
|
|
23450
21996
|
if (!isPathInsideRoot(targetPath, targetRoot)) {
|
|
23451
21997
|
skipped++;
|
|
23452
21998
|
continue;
|
|
@@ -23488,8 +22034,8 @@ function copyMemories(sourceDir, targetDir, options) {
|
|
|
23488
22034
|
skipped++;
|
|
23489
22035
|
continue;
|
|
23490
22036
|
}
|
|
23491
|
-
fs7.mkdirSync(
|
|
23492
|
-
const targetParentRealPath = safeRealpath(
|
|
22037
|
+
fs7.mkdirSync(path27.dirname(targetPath), { recursive: true });
|
|
22038
|
+
const targetParentRealPath = safeRealpath(path27.dirname(targetPath));
|
|
23493
22039
|
if (!targetParentRealPath || !isPathInsideRoot(targetParentRealPath, targetRoot)) {
|
|
23494
22040
|
skipped++;
|
|
23495
22041
|
continue;
|
|
@@ -23507,7 +22053,7 @@ function walkMd2(dir) {
|
|
|
23507
22053
|
const results = [];
|
|
23508
22054
|
function walk(d) {
|
|
23509
22055
|
for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
23510
|
-
const fullPath =
|
|
22056
|
+
const fullPath = path27.join(d, entry.name);
|
|
23511
22057
|
if (entry.isSymbolicLink()) {
|
|
23512
22058
|
continue;
|
|
23513
22059
|
}
|
|
@@ -23536,8 +22082,8 @@ function safeRealpath(filePath) {
|
|
|
23536
22082
|
}
|
|
23537
22083
|
}
|
|
23538
22084
|
function isPathInsideRoot(candidatePath, rootPath) {
|
|
23539
|
-
const relative =
|
|
23540
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
22085
|
+
const relative = path27.relative(rootPath, candidatePath);
|
|
22086
|
+
return relative === "" || !relative.startsWith("..") && !path27.isAbsolute(relative);
|
|
23541
22087
|
}
|
|
23542
22088
|
function parseSimpleFrontmatter(content) {
|
|
23543
22089
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -23657,22 +22203,22 @@ var REMNIC_RECALL_DECISION_RULES = `## When to Use Recall vs Direct Read
|
|
|
23657
22203
|
|
|
23658
22204
|
// src/memory-extension/codex-publisher.ts
|
|
23659
22205
|
import fs8 from "fs";
|
|
23660
|
-
import
|
|
23661
|
-
import
|
|
22206
|
+
import os from "os";
|
|
22207
|
+
import path28 from "path";
|
|
23662
22208
|
var REMNIC_EXTENSION_DIR_NAME = "remnic";
|
|
23663
22209
|
function resolveEnvHome(env) {
|
|
23664
22210
|
if (env === void 0) return resolveHomeDir();
|
|
23665
|
-
return env.HOME?.trim() || env.USERPROFILE?.trim() ||
|
|
22211
|
+
return env.HOME?.trim() || env.USERPROFILE?.trim() || os.homedir();
|
|
23666
22212
|
}
|
|
23667
22213
|
function expandTildeWithHome(input, homeDir) {
|
|
23668
22214
|
if (input === "~") return homeDir;
|
|
23669
22215
|
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
23670
|
-
return
|
|
22216
|
+
return path28.join(homeDir, input.slice(2));
|
|
23671
22217
|
}
|
|
23672
22218
|
return input;
|
|
23673
22219
|
}
|
|
23674
22220
|
function normalizeHostRoot(input, homeDir) {
|
|
23675
|
-
return
|
|
22221
|
+
return path28.resolve(expandTildeWithHome(input.trim(), homeDir));
|
|
23676
22222
|
}
|
|
23677
22223
|
var CodexMemoryExtensionPublisher = class {
|
|
23678
22224
|
hostId = "codex";
|
|
@@ -23686,12 +22232,12 @@ var CodexMemoryExtensionPublisher = class {
|
|
|
23686
22232
|
async resolveExtensionRoot(env) {
|
|
23687
22233
|
const homeDir = resolveEnvHome(env);
|
|
23688
22234
|
const codexHomeInput = env === void 0 ? readEnvVar("CODEX_HOME")?.trim() : env.CODEX_HOME?.trim();
|
|
23689
|
-
const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) :
|
|
23690
|
-
return
|
|
22235
|
+
const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) : path28.resolve(homeDir, ".codex");
|
|
22236
|
+
return path28.join(codexHome, "memories_extensions", REMNIC_EXTENSION_DIR_NAME);
|
|
23691
22237
|
}
|
|
23692
22238
|
async isHostAvailable() {
|
|
23693
22239
|
try {
|
|
23694
|
-
const home = readEnvVar("CODEX_HOME")?.trim() ||
|
|
22240
|
+
const home = readEnvVar("CODEX_HOME")?.trim() || path28.join(resolveHomeDir(), ".codex");
|
|
23695
22241
|
return fs8.existsSync(home);
|
|
23696
22242
|
} catch {
|
|
23697
22243
|
return false;
|
|
@@ -23742,7 +22288,7 @@ When running inside the Codex phase-2 consolidation sandbox:
|
|
|
23742
22288
|
}
|
|
23743
22289
|
async publish(ctx) {
|
|
23744
22290
|
const extensionRoot = await this.resolveExtensionRoot();
|
|
23745
|
-
const instructionsPath =
|
|
22291
|
+
const instructionsPath = path28.join(extensionRoot, "instructions.md");
|
|
23746
22292
|
const filesWritten = [];
|
|
23747
22293
|
const skipped = [];
|
|
23748
22294
|
ctx.log.info(`Publishing Codex memory extension to ${extensionRoot}`);
|
|
@@ -24116,9 +22662,9 @@ async function generateActivityMemories(date, digestBody, config, deps) {
|
|
|
24116
22662
|
}
|
|
24117
22663
|
|
|
24118
22664
|
// src/session-summaries/index.ts
|
|
24119
|
-
import { createHash as
|
|
22665
|
+
import { createHash as createHash7 } from "crypto";
|
|
24120
22666
|
import { lstat as lstat2, mkdir as mkdir7, readFile as readFile6, readdir as readdir4, rename, rm, stat as stat4, writeFile as writeFile7 } from "fs/promises";
|
|
24121
|
-
import
|
|
22667
|
+
import path29 from "path";
|
|
24122
22668
|
|
|
24123
22669
|
// src/session-summaries/adapters.ts
|
|
24124
22670
|
var VALID_ROLES = /* @__PURE__ */ new Set(["user", "assistant", "tool", "system", "other"]);
|
|
@@ -24618,12 +23164,12 @@ var DEFAULT_MAX_FILES = 5e3;
|
|
|
24618
23164
|
var DEFAULT_MAX_SESSIONS = 500;
|
|
24619
23165
|
var SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".jsonl"]);
|
|
24620
23166
|
function shortHash(value, length = 16) {
|
|
24621
|
-
return
|
|
23167
|
+
return createHash7("sha256").update(value).digest("hex").slice(0, length);
|
|
24622
23168
|
}
|
|
24623
23169
|
async function listTranscriptFiles(root, maxFiles) {
|
|
24624
23170
|
const out = [];
|
|
24625
23171
|
let truncated = false;
|
|
24626
|
-
const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${
|
|
23172
|
+
const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${path29.sep}` : entryName;
|
|
24627
23173
|
async function visit(dir) {
|
|
24628
23174
|
if (truncated) return;
|
|
24629
23175
|
const entries = (await readdir4(dir, { withFileTypes: true })).sort(
|
|
@@ -24633,13 +23179,13 @@ async function listTranscriptFiles(root, maxFiles) {
|
|
|
24633
23179
|
if (truncated) return;
|
|
24634
23180
|
if (entry.name.startsWith(".")) continue;
|
|
24635
23181
|
if (entry.isSymbolicLink()) continue;
|
|
24636
|
-
const fullPath =
|
|
23182
|
+
const fullPath = path29.join(dir, entry.name);
|
|
24637
23183
|
if (entry.isDirectory()) {
|
|
24638
23184
|
await visit(fullPath);
|
|
24639
23185
|
continue;
|
|
24640
23186
|
}
|
|
24641
23187
|
if (!entry.isFile()) continue;
|
|
24642
|
-
const ext =
|
|
23188
|
+
const ext = path29.extname(entry.name).toLowerCase();
|
|
24643
23189
|
if (!SUPPORTED_EXTENSIONS.has(ext)) continue;
|
|
24644
23190
|
out.push(fullPath);
|
|
24645
23191
|
if (out.length > maxFiles) {
|
|
@@ -24666,7 +23212,7 @@ function normalizeInputDir(inputDir) {
|
|
|
24666
23212
|
if (typeof inputDir !== "string" || inputDir.trim().length === 0) {
|
|
24667
23213
|
throw new Error("inputDir must be a non-empty string");
|
|
24668
23214
|
}
|
|
24669
|
-
return
|
|
23215
|
+
return path29.resolve(expandTildePath(inputDir.trim()));
|
|
24670
23216
|
}
|
|
24671
23217
|
function initRoleCounts() {
|
|
24672
23218
|
return {
|
|
@@ -24823,11 +23369,11 @@ async function collectLocalSessionSummaries(options) {
|
|
|
24823
23369
|
continue;
|
|
24824
23370
|
}
|
|
24825
23371
|
seenFileHashes.add(fileHash);
|
|
24826
|
-
const fileExtension =
|
|
23372
|
+
const fileExtension = path29.extname(filePath).toLowerCase();
|
|
24827
23373
|
const parsed = await adapter.parseFile(
|
|
24828
23374
|
{
|
|
24829
23375
|
content,
|
|
24830
|
-
fileName:
|
|
23376
|
+
fileName: path29.basename(filePath),
|
|
24831
23377
|
fileExtension,
|
|
24832
23378
|
fileRef: fileHash
|
|
24833
23379
|
},
|
|
@@ -24883,7 +23429,7 @@ async function collectLocalSessionSummaries(options) {
|
|
|
24883
23429
|
}
|
|
24884
23430
|
async function readRedactionConfig(pathLike) {
|
|
24885
23431
|
if (!pathLike) return void 0;
|
|
24886
|
-
const raw = await readFile6(
|
|
23432
|
+
const raw = await readFile6(path29.resolve(expandTildePath(pathLike)), "utf-8");
|
|
24887
23433
|
const parsed = JSON.parse(raw);
|
|
24888
23434
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
24889
23435
|
throw new Error("redaction config must be a JSON object");
|
|
@@ -24896,15 +23442,15 @@ function toJsonl(drafts) {
|
|
|
24896
23442
|
}
|
|
24897
23443
|
function defaultDraftOutputPath(memoryDir, generatedAt) {
|
|
24898
23444
|
const stamp = generatedAt.replace(/[:.]/g, "-");
|
|
24899
|
-
return
|
|
24900
|
-
|
|
23445
|
+
return path29.join(
|
|
23446
|
+
path29.resolve(expandTildePath(memoryDir)),
|
|
24901
23447
|
"state",
|
|
24902
23448
|
"session-summary-drafts",
|
|
24903
23449
|
`session-summaries-${stamp}.jsonl`
|
|
24904
23450
|
);
|
|
24905
23451
|
}
|
|
24906
23452
|
async function writeDrafts(filePath, drafts) {
|
|
24907
|
-
await mkdir7(
|
|
23453
|
+
await mkdir7(path29.dirname(filePath), { recursive: true });
|
|
24908
23454
|
const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
24909
23455
|
try {
|
|
24910
23456
|
await writeFile7(tempPath, toJsonl(drafts), "utf-8");
|
|
@@ -24922,7 +23468,7 @@ async function runLocalSessionSummaryCliCommand(options) {
|
|
|
24922
23468
|
});
|
|
24923
23469
|
const wroteFiles = [];
|
|
24924
23470
|
if (options.output) {
|
|
24925
|
-
const outputPath =
|
|
23471
|
+
const outputPath = path29.resolve(expandTildePath(options.output));
|
|
24926
23472
|
await writeDrafts(outputPath, report.drafts);
|
|
24927
23473
|
wroteFiles.push(outputPath);
|
|
24928
23474
|
}
|
|
@@ -24957,19 +23503,19 @@ async function runLocalSessionSummaryCliCommand(options) {
|
|
|
24957
23503
|
|
|
24958
23504
|
// src/transfer/capsule-fork.ts
|
|
24959
23505
|
import { lstat as lstat3, mkdir as mkdir8, readFile as readFile7, realpath as realpath2, writeFile as writeFile8 } from "fs/promises";
|
|
24960
|
-
import
|
|
23506
|
+
import path30 from "path";
|
|
24961
23507
|
async function forkCapsule(opts) {
|
|
24962
23508
|
validateForkId(opts.forkId);
|
|
24963
|
-
const rootAbs =
|
|
23509
|
+
const rootAbs = path30.resolve(opts.targetRoot);
|
|
24964
23510
|
await assertIsDirectoryNotSymlink(rootAbs, "forkCapsule", "targetRoot");
|
|
24965
|
-
const forkDirAbs =
|
|
23511
|
+
const forkDirAbs = path30.join(rootAbs, "forks", opts.forkId);
|
|
24966
23512
|
const forkEntryExists = await pathEntryExists(forkDirAbs);
|
|
24967
23513
|
if (forkEntryExists) {
|
|
24968
23514
|
throw new Error(
|
|
24969
23515
|
`forkCapsule: fork path already exists \u2014 forkId "${opts.forkId}" is already in use at: ${forkDirAbs}`
|
|
24970
23516
|
);
|
|
24971
23517
|
}
|
|
24972
|
-
const archiveAbs =
|
|
23518
|
+
const archiveAbs = path30.resolve(opts.sourceArchive);
|
|
24973
23519
|
const importResult = await importCapsule({
|
|
24974
23520
|
archivePath: archiveAbs,
|
|
24975
23521
|
root: rootAbs,
|
|
@@ -24991,10 +23537,10 @@ async function forkCapsule(opts) {
|
|
|
24991
23537
|
importedRecords: importResult.imported.length,
|
|
24992
23538
|
skippedRecords: importResult.skipped.length
|
|
24993
23539
|
};
|
|
24994
|
-
const lineagePath =
|
|
23540
|
+
const lineagePath = path30.join(forkDirAbs, "lineage.json");
|
|
24995
23541
|
const rootReal = await realpath2(rootAbs);
|
|
24996
23542
|
await assertRealpathInsideRoot(rootReal, lineagePath, `forks/${opts.forkId}/lineage.json`, "forkCapsule");
|
|
24997
|
-
await mkdir8(
|
|
23543
|
+
await mkdir8(path30.dirname(lineagePath), { recursive: true });
|
|
24998
23544
|
await writeFile8(lineagePath, JSON.stringify(lineage, null, 2) + "\n", "utf-8");
|
|
24999
23545
|
return {
|
|
25000
23546
|
archivePath: archiveAbs,
|
|
@@ -25008,11 +23554,11 @@ async function readForkLineage(targetRoot, forkId) {
|
|
|
25008
23554
|
if (typeof forkId !== "string" || forkId.length === 0 || forkId.length > 64 || !CAPSULE_ID_PATTERN.test(forkId)) {
|
|
25009
23555
|
return null;
|
|
25010
23556
|
}
|
|
25011
|
-
const rootAbs =
|
|
23557
|
+
const rootAbs = path30.resolve(targetRoot);
|
|
25012
23558
|
const rootReal = await realpath2(rootAbs).catch(() => rootAbs);
|
|
25013
|
-
const lineagePath =
|
|
25014
|
-
const rel =
|
|
25015
|
-
if (rel.startsWith("..") ||
|
|
23559
|
+
const lineagePath = path30.join(rootReal, "forks", forkId, "lineage.json");
|
|
23560
|
+
const rel = path30.relative(rootReal, lineagePath);
|
|
23561
|
+
if (rel.startsWith("..") || path30.isAbsolute(rel)) {
|
|
25016
23562
|
return null;
|
|
25017
23563
|
}
|
|
25018
23564
|
if (!await isLineagePathContained(rootReal, lineagePath)) {
|
|
@@ -25053,60 +23599,23 @@ async function pathEntryExists(absPath) {
|
|
|
25053
23599
|
async function isLineagePathContained(rootReal, lineagePath) {
|
|
25054
23600
|
let existing = lineagePath;
|
|
25055
23601
|
const suffix = [];
|
|
25056
|
-
while (existing !==
|
|
23602
|
+
while (existing !== path30.dirname(existing)) {
|
|
25057
23603
|
const st = await lstat3(existing).catch(() => null);
|
|
25058
23604
|
if (st !== null) break;
|
|
25059
|
-
suffix.unshift(
|
|
25060
|
-
existing =
|
|
23605
|
+
suffix.unshift(path30.basename(existing));
|
|
23606
|
+
existing = path30.dirname(existing);
|
|
25061
23607
|
}
|
|
25062
23608
|
const existingReal = await realpath2(existing).catch(() => existing);
|
|
25063
|
-
const targetReal = suffix.length > 0 ?
|
|
25064
|
-
const rel =
|
|
23609
|
+
const targetReal = suffix.length > 0 ? path30.join(existingReal, ...suffix) : existingReal;
|
|
23610
|
+
const rel = path30.relative(rootReal, targetReal);
|
|
25065
23611
|
if (rel === "") return true;
|
|
25066
23612
|
if (rel === "..") return false;
|
|
25067
|
-
if (rel.startsWith(`..${
|
|
25068
|
-
if (
|
|
23613
|
+
if (rel.startsWith(`..${path30.sep}`)) return false;
|
|
23614
|
+
if (path30.isAbsolute(rel)) return false;
|
|
25069
23615
|
return true;
|
|
25070
23616
|
}
|
|
25071
23617
|
|
|
25072
23618
|
export {
|
|
25073
|
-
BulkImportBatchPartialFailureError,
|
|
25074
|
-
mapRecallSourceToXrayServedBy,
|
|
25075
|
-
throwIfRecallAborted,
|
|
25076
|
-
raceRecallAbort,
|
|
25077
|
-
COMPACTION_SIGNAL_MAX_AGE_MS,
|
|
25078
|
-
normalizeIanaTimeZone,
|
|
25079
|
-
formatDateInTimeZone,
|
|
25080
|
-
utcDateKeysForLocalDay,
|
|
25081
|
-
parseFiniteDate,
|
|
25082
|
-
filterHourlySummaryMarkdownForLocalDay,
|
|
25083
|
-
qmdStartupCollectionCheckWithTimeout,
|
|
25084
|
-
defaultWorkspaceDir,
|
|
25085
|
-
sanitizeSessionKeyForFilename,
|
|
25086
|
-
targetSourceValidAtSortMs,
|
|
25087
|
-
splitTurnsBySourceValidAt,
|
|
25088
|
-
isArtifactMemoryPath,
|
|
25089
|
-
buildCompressionGuidelinesMarkdown2 as buildCompressionGuidelinesMarkdown,
|
|
25090
|
-
applyQueryAwareCandidateFilter,
|
|
25091
|
-
tokenizeRecallQuery,
|
|
25092
|
-
shouldFilterLifecycleRecallCandidate,
|
|
25093
|
-
lifecycleRecallScoreAdjustment,
|
|
25094
|
-
computeArtifactRecallLimit,
|
|
25095
|
-
resolveEffectiveRecallMode,
|
|
25096
|
-
resolveRecallModeDecision,
|
|
25097
|
-
resolveRecallModeDecisionAsync,
|
|
25098
|
-
computeArtifactCandidateFetchLimit,
|
|
25099
|
-
computeQmdHybridFetchLimit,
|
|
25100
|
-
summarizeGraphShadowComparison,
|
|
25101
|
-
parseGraphRecallRankedResults,
|
|
25102
|
-
parseMemoryIntentSnapshot,
|
|
25103
|
-
parseQmdRecallResults,
|
|
25104
|
-
mergeArtifactRecallCandidates,
|
|
25105
|
-
resolveRecentThreadMemoryPaths,
|
|
25106
|
-
buildMemoryPathById,
|
|
25107
|
-
appendMemoryToGraphContext,
|
|
25108
|
-
resolvePersistedMemoryRelativePath,
|
|
25109
|
-
deriveTopicsFromExtraction,
|
|
25110
23619
|
buildProcedureRecallSection,
|
|
25111
23620
|
RELAY_DEMO_MISSION_ID,
|
|
25112
23621
|
RELAY_DEMO_NAMESPACE,
|
|
@@ -25222,4 +23731,4 @@ export {
|
|
|
25222
23731
|
filterRecallCandidates,
|
|
25223
23732
|
Orchestrator
|
|
25224
23733
|
};
|
|
25225
|
-
//# sourceMappingURL=chunk-
|
|
23734
|
+
//# sourceMappingURL=chunk-LUQ443JP.js.map
|