@remnic/core 9.30.1 → 9.31.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 +50 -44
- package/dist/access-authorization-probe.d.ts +10 -10
- package/dist/access-authorization-probe.js +51 -45
- package/dist/access-boundary.d.ts +13 -11
- package/dist/access-boundary.js +50 -44
- package/dist/access-cli.js +168 -123
- 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 +166 -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 +66 -59
- package/dist/access-identity-continuity-surface.d.ts +8 -8
- package/dist/access-identity-continuity-surface.js +50 -44
- package/dist/access-lcm-surface.d.ts +10 -10
- package/dist/access-lcm-surface.js +50 -44
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +16 -10
- package/dist/access-mcp.js +58 -52
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-VfXssvoI.d.ts → access-namespace-preflight-D4vW97H1.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +50 -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 +50 -44
- package/dist/access-operations-batch.js +53 -47
- package/dist/access-operations.d.ts +11 -11
- package/dist/access-operations.js +55 -49
- package/dist/access-recall-concurrency.d.ts +10 -10
- package/dist/access-recall-concurrency.js +50 -44
- package/dist/access-recall-response.d.ts +10 -10
- package/dist/access-recall-response.js +50 -44
- package/dist/access-recall-surface.d.ts +10 -10
- package/dist/access-recall-surface.js +50 -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-B6PZ_xUL.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 +50 -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 +1 -1
- 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-CGFYmTT8.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 +19 -19
- 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-GIBMDSJ2.js → chunk-27P5YVDU.js} +2 -2
- package/dist/{chunk-2SA56WMI.js → chunk-2LTDWSR6.js} +4 -4
- package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
- 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-6U7F52DE.js → chunk-4XHR3I67.js} +60 -60
- package/dist/chunk-5IVLTFOV.js +65 -0
- package/dist/chunk-5IVLTFOV.js.map +1 -0
- package/dist/{chunk-2EUVEDF5.js → chunk-5XA7PQ5I.js} +2 -2
- package/dist/{chunk-ALSGMEJR.js → chunk-65ZPVYTA.js} +7 -7
- package/dist/{chunk-5VQJBH2G.js → chunk-6TAUHL33.js} +2 -2
- package/dist/{chunk-HUHX2OCX.js → chunk-7DRETLP5.js} +1 -1
- package/dist/chunk-7DRETLP5.js.map +1 -0
- package/dist/{chunk-RGIWINDN.js → chunk-7G5MH4NT.js} +30 -30
- package/dist/{chunk-WVO4G37W.js → chunk-7TEZUUGM.js} +3 -3
- package/dist/{chunk-MJCGLM25.js → chunk-7VUAG236.js} +5 -5
- package/dist/{chunk-M3C2V3PV.js → chunk-AJEMDQNA.js} +12 -12
- package/dist/{chunk-RKNJBZ55.js → chunk-AU7Q3LSC.js} +7 -7
- package/dist/{chunk-ACXPX4AG.js → chunk-BR2K43MK.js} +2 -2
- package/dist/{chunk-IYZ5K7MU.js → chunk-BUE5E2HL.js} +4 -187
- package/dist/chunk-BUE5E2HL.js.map +1 -0
- package/dist/{chunk-CZRYLSSW.js → chunk-BUGVGH4N.js} +2 -2
- package/dist/{chunk-YTQNQ4KB.js → chunk-C4VQMFVM.js} +3 -3
- package/dist/{chunk-ZPSVBSOF.js → chunk-CIVDJD6P.js} +3 -3
- package/dist/{chunk-K5GB36ME.js → chunk-CZDOT5I2.js} +2 -2
- package/dist/{chunk-VI2JQPNQ.js → chunk-E4PWACUN.js} +2 -2
- package/dist/{chunk-D2ANTDGO.js → chunk-E6BMSH7U.js} +2 -2
- package/dist/{chunk-P5PXWTW7.js → chunk-EJCAV3QZ.js} +3 -3
- 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-6FUPCJUL.js → chunk-FI4F5X2V.js} +54 -54
- package/dist/chunk-FI4F5X2V.js.map +1 -0
- package/dist/{chunk-LGHKJABJ.js → chunk-GOUILH55.js} +40 -18
- package/dist/chunk-GOUILH55.js.map +1 -0
- package/dist/{chunk-G5R3D5UP.js → chunk-GTTAHHD3.js} +2 -2
- package/dist/{chunk-H5CPS5JP.js → chunk-H36LJIPD.js} +3 -3
- package/dist/{chunk-AITCS2RC.js → chunk-IJ7HK452.js} +4 -4
- package/dist/{chunk-D3LMYTBV.js → chunk-J7WZUL2K.js} +9 -9
- package/dist/{chunk-5W4ZLBEZ.js → chunk-JCFTIQBR.js} +2 -2
- package/dist/{chunk-XOZ4ALGB.js → chunk-KE353EWI.js} +3 -3
- package/dist/{chunk-W5EG6LE3.js → chunk-KIT6M7EB.js} +3 -3
- package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
- 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-66772WBP.js → chunk-NFXQJHJD.js} +5 -5
- package/dist/{chunk-AZ5BTEKX.js → chunk-NQUF7XKR.js} +2 -2
- package/dist/{chunk-W4FBGYGK.js → chunk-NRV4Y3PM.js} +1 -1
- package/dist/{chunk-NHWB6HG2.js → chunk-NYCGIQRA.js} +2 -2
- package/dist/{chunk-4WKA6I65.js → chunk-OGCNZPKX.js} +1119 -309
- package/dist/chunk-OGCNZPKX.js.map +1 -0
- package/dist/{chunk-QJAQNXWI.js → chunk-ONHRRJZM.js} +6 -6
- package/dist/{chunk-FDAMS4PK.js → chunk-PNPOWBGC.js} +2 -2
- package/dist/{chunk-IC6CBHCA.js → chunk-QGENAYVS.js} +2 -2
- package/dist/{chunk-GBJ4RDFR.js → chunk-QIHIHZYC.js} +66 -91
- package/dist/chunk-QIHIHZYC.js.map +1 -0
- package/dist/{chunk-YNQBRLC5.js → chunk-RUYJ7TWU.js} +517 -2011
- package/dist/chunk-RUYJ7TWU.js.map +1 -0
- package/dist/{chunk-4A6YGWQN.js → chunk-TL4TO3EA.js} +115 -120
- package/dist/chunk-TL4TO3EA.js.map +1 -0
- package/dist/{chunk-SPJXKAVF.js → chunk-U52AKICI.js} +14 -13
- package/dist/chunk-U52AKICI.js.map +1 -0
- package/dist/chunk-ULARSG5Z.js +203 -0
- package/dist/chunk-ULARSG5Z.js.map +1 -0
- package/dist/{chunk-62U4J2GN.js → chunk-UR77VKF7.js} +2 -2
- package/dist/{chunk-JCBWCYEJ.js → chunk-VANLTS5F.js} +2 -2
- package/dist/{chunk-4Z4XNEWZ.js → chunk-VCD4PSK2.js} +56 -12
- package/dist/chunk-VCD4PSK2.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-TH2LSRMG.js → chunk-XHDIB4T4.js} +2 -2
- package/dist/{chunk-CVILPI77.js → chunk-XOQSEF7X.js} +6 -6
- package/dist/{chunk-LBOD4U5B.js → chunk-YFOMN2II.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-I5NLEENJ.js → chunk-Z4SWV4VW.js} +3 -3
- 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-BptUDTtp.d.ts} +5 -5
- package/dist/cli.d.ts +12 -12
- package/dist/cli.js +91 -84
- 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 +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +14 -14
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +17 -17
- 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 +215 -207
- 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-b6f92bRz.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 +38 -37
- 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-3uGxC1qO.d.ts} +72 -34
- package/dist/orchestrator.d.ts +8 -8
- package/dist/orchestrator.js +167 -159
- package/dist/page-versioning.js +3 -3
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-B7wj4rRZ.d.ts → pipeline-DepuNr-m.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-Dalr3Jby.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 +1 -1
- 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-BpiM5hTU.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-CMtVrf9f.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +16 -16
- 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-DuAxwSgg.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-CF0Ih8GP.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-BpaYvJ6v.d.ts} +22 -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/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/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/types.ts +2 -2
- 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-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-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-GIBMDSJ2.js.map → chunk-27P5YVDU.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-6U7F52DE.js.map → chunk-4XHR3I67.js.map} +0 -0
- /package/dist/{chunk-2EUVEDF5.js.map → chunk-5XA7PQ5I.js.map} +0 -0
- /package/dist/{chunk-ALSGMEJR.js.map → chunk-65ZPVYTA.js.map} +0 -0
- /package/dist/{chunk-5VQJBH2G.js.map → chunk-6TAUHL33.js.map} +0 -0
- /package/dist/{chunk-RGIWINDN.js.map → chunk-7G5MH4NT.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-M3C2V3PV.js.map → chunk-AJEMDQNA.js.map} +0 -0
- /package/dist/{chunk-RKNJBZ55.js.map → chunk-AU7Q3LSC.js.map} +0 -0
- /package/dist/{chunk-ACXPX4AG.js.map → chunk-BR2K43MK.js.map} +0 -0
- /package/dist/{chunk-CZRYLSSW.js.map → chunk-BUGVGH4N.js.map} +0 -0
- /package/dist/{chunk-YTQNQ4KB.js.map → chunk-C4VQMFVM.js.map} +0 -0
- /package/dist/{chunk-ZPSVBSOF.js.map → chunk-CIVDJD6P.js.map} +0 -0
- /package/dist/{chunk-K5GB36ME.js.map → chunk-CZDOT5I2.js.map} +0 -0
- /package/dist/{chunk-VI2JQPNQ.js.map → chunk-E4PWACUN.js.map} +0 -0
- /package/dist/{chunk-D2ANTDGO.js.map → chunk-E6BMSH7U.js.map} +0 -0
- /package/dist/{chunk-P5PXWTW7.js.map → chunk-EJCAV3QZ.js.map} +0 -0
- /package/dist/{chunk-CKMO4RDY.js.map → chunk-EMDLM3LW.js.map} +0 -0
- /package/dist/{chunk-G5R3D5UP.js.map → chunk-GTTAHHD3.js.map} +0 -0
- /package/dist/{chunk-H5CPS5JP.js.map → chunk-H36LJIPD.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-5W4ZLBEZ.js.map → chunk-JCFTIQBR.js.map} +0 -0
- /package/dist/{chunk-XOZ4ALGB.js.map → chunk-KE353EWI.js.map} +0 -0
- /package/dist/{chunk-W5EG6LE3.js.map → chunk-KIT6M7EB.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-66772WBP.js.map → chunk-NFXQJHJD.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-NHWB6HG2.js.map → chunk-NYCGIQRA.js.map} +0 -0
- /package/dist/{chunk-QJAQNXWI.js.map → chunk-ONHRRJZM.js.map} +0 -0
- /package/dist/{chunk-FDAMS4PK.js.map → chunk-PNPOWBGC.js.map} +0 -0
- /package/dist/{chunk-IC6CBHCA.js.map → chunk-QGENAYVS.js.map} +0 -0
- /package/dist/{chunk-62U4J2GN.js.map → chunk-UR77VKF7.js.map} +0 -0
- /package/dist/{chunk-JCBWCYEJ.js.map → chunk-VANLTS5F.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-TH2LSRMG.js.map → chunk-XHDIB4T4.js.map} +0 -0
- /package/dist/{chunk-CVILPI77.js.map → chunk-XOQSEF7X.js.map} +0 -0
- /package/dist/{chunk-LBOD4U5B.js.map → chunk-YFOMN2II.js.map} +0 -0
- /package/dist/{chunk-I5NLEENJ.js.map → chunk-Z4SWV4VW.js.map} +0 -0
package/src/local-llm.ts
CHANGED
|
@@ -8,6 +8,13 @@ import { mergeEnv, readEnvVar } from "./runtime/env.js";
|
|
|
8
8
|
import { resolveLocalLlmCapabilities } from "./capabilities.js";
|
|
9
9
|
import { resolvePipelineProcessingCapabilities } from "./capabilities.js";
|
|
10
10
|
import { ChatTransport } from "./local-llm-transport.js";
|
|
11
|
+
import {
|
|
12
|
+
extractNonRecoverableBackendReason,
|
|
13
|
+
extractNonRecoverableBackendReasonFromErrorText,
|
|
14
|
+
isAbortError,
|
|
15
|
+
normalizeBackendTripReason,
|
|
16
|
+
waitForRetryBackoff,
|
|
17
|
+
} from "./local-llm-helpers.js";
|
|
11
18
|
|
|
12
19
|
/** Trim trailing slash characters without backtracking regex. */
|
|
13
20
|
function trimTrailingSlashes(s: string): string {
|
|
@@ -223,6 +230,7 @@ interface LocalLlmChatCompletionOptions {
|
|
|
223
230
|
forceDisableThinking?: boolean;
|
|
224
231
|
disableThinking?: boolean;
|
|
225
232
|
priority?: LocalLlmRequestPriority;
|
|
233
|
+
signal?: AbortSignal;
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
interface LocalLlmQueuedRequest {
|
|
@@ -304,15 +312,6 @@ export class LocalLlmClient {
|
|
|
304
312
|
return headers;
|
|
305
313
|
}
|
|
306
314
|
|
|
307
|
-
private isAbortError(err: unknown): boolean {
|
|
308
|
-
if (!err || typeof err !== "object") return false;
|
|
309
|
-
const maybe = err as { name?: string; message?: string };
|
|
310
|
-
return (
|
|
311
|
-
maybe.name === "AbortError" ||
|
|
312
|
-
maybe.message === "This operation was aborted" ||
|
|
313
|
-
maybe.message === "The operation was aborted"
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
315
|
|
|
317
316
|
/**
|
|
318
317
|
* Set the ModelRegistry for caching detected capabilities
|
|
@@ -356,7 +355,7 @@ export class LocalLlmClient {
|
|
|
356
355
|
}
|
|
357
356
|
|
|
358
357
|
private markBackendUnavailable(reason: string, durationMs: number): void {
|
|
359
|
-
const normalizedReason =
|
|
358
|
+
const normalizedReason = normalizeBackendTripReason(reason);
|
|
360
359
|
if (durationMs > 0) {
|
|
361
360
|
const untilMs = Date.now() + durationMs;
|
|
362
361
|
this.getGlobalBackendState().set(this.getBackendKey(), { untilMs, reason: normalizedReason });
|
|
@@ -370,29 +369,6 @@ export class LocalLlmClient {
|
|
|
370
369
|
);
|
|
371
370
|
}
|
|
372
371
|
|
|
373
|
-
private extractNonRecoverableBackendReason(reason: string): string | null {
|
|
374
|
-
const match = reason.match(
|
|
375
|
-
/Failed to load model|Library not loaded|different Team IDs|code signature|llm_engine_mlx_amphibian/i,
|
|
376
|
-
);
|
|
377
|
-
return match?.[0] ?? null;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
private extractNonRecoverableBackendReasonFromErrorText(errorText: string): string | null {
|
|
381
|
-
const directReason = this.extractNonRecoverableBackendReason(errorText);
|
|
382
|
-
if (directReason) return directReason;
|
|
383
|
-
try {
|
|
384
|
-
const parsed = JSON.parse(errorText) as { error?: { message?: string } };
|
|
385
|
-
return this.extractNonRecoverableBackendReason(parsed?.error?.message ?? "");
|
|
386
|
-
} catch {
|
|
387
|
-
return null;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
private normalizeBackendTripReason(reason: string): string {
|
|
392
|
-
const cleaned = reason.replace(/\s+/g, " ").replace(/^[-:–—\s]+/, "").trim();
|
|
393
|
-
if (!cleaned) return "unknown local backend failure";
|
|
394
|
-
return cleaned.length > 160 ? `${cleaned.slice(0, 157)}...` : cleaned;
|
|
395
|
-
}
|
|
396
372
|
|
|
397
373
|
/**
|
|
398
374
|
* Fetch with timeout for health checks
|
|
@@ -401,13 +377,15 @@ export class LocalLlmClient {
|
|
|
401
377
|
url: string,
|
|
402
378
|
timeoutMs: number = 2000,
|
|
403
379
|
headers?: Record<string, string>,
|
|
380
|
+
signal?: AbortSignal,
|
|
404
381
|
): Promise<{ ok: boolean; data: unknown; status: number | null }> {
|
|
405
382
|
const controller = new AbortController();
|
|
383
|
+
const requestSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
|
|
406
384
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
407
385
|
|
|
408
386
|
try {
|
|
409
387
|
const response = await fetch(url, {
|
|
410
|
-
signal:
|
|
388
|
+
signal: requestSignal,
|
|
411
389
|
headers: this.buildRequestHeaders({ Accept: "application/json", ...(headers ?? {}) }),
|
|
412
390
|
});
|
|
413
391
|
clearTimeout(timeout);
|
|
@@ -430,10 +408,13 @@ export class LocalLlmClient {
|
|
|
430
408
|
|
|
431
409
|
private async probeLmStudioNativeModels(
|
|
432
410
|
probeBaseUrl: string,
|
|
411
|
+
signal?: AbortSignal,
|
|
433
412
|
): Promise<{ matched: boolean; unauthorized: boolean }> {
|
|
434
413
|
let unauthorized = false;
|
|
435
414
|
for (const endpoint of ["/api/v1/models", "/api/v0/models"]) {
|
|
436
|
-
|
|
415
|
+
if (signal?.aborted) return { matched: false, unauthorized };
|
|
416
|
+
const probe = await this.fetchWithTimeout(`${probeBaseUrl}${endpoint}`, 2000, undefined, signal);
|
|
417
|
+
if (signal?.aborted) return { matched: false, unauthorized };
|
|
437
418
|
if (probe.ok && isLmStudioNativeModelsResponse(probe.data)) {
|
|
438
419
|
return { matched: true, unauthorized };
|
|
439
420
|
}
|
|
@@ -448,7 +429,8 @@ export class LocalLlmClient {
|
|
|
448
429
|
* Check if local LLM is available
|
|
449
430
|
* Uses 127.0.0.1 instead of localhost to avoid DNS issues (consistent with tactician)
|
|
450
431
|
*/
|
|
451
|
-
async checkAvailability(): Promise<boolean> {
|
|
432
|
+
async checkAvailability(signal?: AbortSignal): Promise<boolean> {
|
|
433
|
+
if (signal?.aborted) return false;
|
|
452
434
|
// Cache health check results for 1 minute
|
|
453
435
|
const now = Date.now();
|
|
454
436
|
const trippedState = this.getTrippedBackendState(now);
|
|
@@ -474,14 +456,17 @@ export class LocalLlmClient {
|
|
|
474
456
|
let sawUnauthorizedProbe = false;
|
|
475
457
|
|
|
476
458
|
// Try to detect which server type is running
|
|
459
|
+
if (signal?.aborted) return false;
|
|
477
460
|
for (const serverConfig of orderedLocalServers(configuredBaseUrl)) {
|
|
478
461
|
const healthUrl = `${probeBaseUrl}${serverConfig.healthEndpoint}`;
|
|
479
462
|
log.debug(`checking ${serverConfig.type} at ${healthUrl}`);
|
|
480
463
|
|
|
481
|
-
const result = await this.fetchWithTimeout(healthUrl);
|
|
464
|
+
const result = await this.fetchWithTimeout(healthUrl, 2000, undefined, signal);
|
|
465
|
+
if (signal?.aborted) return false;
|
|
482
466
|
if (result.ok && serverConfig.detectFn(result.data)) {
|
|
483
467
|
if (serverConfig.type === "mlx") {
|
|
484
|
-
const lmStudioProbe = await this.probeLmStudioNativeModels(probeBaseUrl);
|
|
468
|
+
const lmStudioProbe = await this.probeLmStudioNativeModels(probeBaseUrl, signal);
|
|
469
|
+
if (signal?.aborted) return false;
|
|
485
470
|
if (lmStudioProbe.unauthorized) {
|
|
486
471
|
sawUnauthorizedProbe = true;
|
|
487
472
|
}
|
|
@@ -495,7 +480,8 @@ export class LocalLlmClient {
|
|
|
495
480
|
}
|
|
496
481
|
if (serverConfig.type === "llamacpp") {
|
|
497
482
|
let sawLlamaCppSignal = false;
|
|
498
|
-
const propsProbe = await this.fetchWithTimeout(`${probeBaseUrl}/props
|
|
483
|
+
const propsProbe = await this.fetchWithTimeout(`${probeBaseUrl}/props`, 2000, undefined, signal);
|
|
484
|
+
if (signal?.aborted) return false;
|
|
499
485
|
if (propsProbe.ok && isLlamaCppPropsResponse(propsProbe.data)) {
|
|
500
486
|
sawLlamaCppSignal = true;
|
|
501
487
|
}
|
|
@@ -504,7 +490,8 @@ export class LocalLlmClient {
|
|
|
504
490
|
}
|
|
505
491
|
|
|
506
492
|
const modelsUrl = `${probeBaseUrl}${serverConfig.modelsEndpoint}`;
|
|
507
|
-
const modelsProbe = await this.fetchWithTimeout(modelsUrl);
|
|
493
|
+
const modelsProbe = await this.fetchWithTimeout(modelsUrl, 2000, undefined, signal);
|
|
494
|
+
if (signal?.aborted) return false;
|
|
508
495
|
if (modelsProbe.ok && isLlamaCppModelsResponse(modelsProbe.data)) {
|
|
509
496
|
sawLlamaCppSignal = true;
|
|
510
497
|
}
|
|
@@ -530,11 +517,13 @@ export class LocalLlmClient {
|
|
|
530
517
|
sawUnauthorizedProbe = true;
|
|
531
518
|
}
|
|
532
519
|
}
|
|
520
|
+
if (signal?.aborted) return false;
|
|
533
521
|
|
|
534
522
|
// Generic check if specific detection failed
|
|
535
523
|
try {
|
|
536
524
|
const modelsUrl = `${probeBaseUrl}/v1/models`;
|
|
537
|
-
const result = await this.fetchWithTimeout(modelsUrl);
|
|
525
|
+
const result = await this.fetchWithTimeout(modelsUrl, 2000, undefined, signal);
|
|
526
|
+
if (signal?.aborted) return false;
|
|
538
527
|
if (result.ok) {
|
|
539
528
|
this.isAvailable = true;
|
|
540
529
|
this.detectedType = "generic";
|
|
@@ -903,6 +892,10 @@ export class LocalLlmClient {
|
|
|
903
892
|
|
|
904
893
|
private async runQueuedRequest(next: LocalLlmQueuedRequest): Promise<void> {
|
|
905
894
|
try {
|
|
895
|
+
if (next.options.signal?.aborted) {
|
|
896
|
+
next.resolve(null);
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
906
899
|
const remainingCooldownMs = this.remainingCooldownMs();
|
|
907
900
|
if (remainingCooldownMs > 0) {
|
|
908
901
|
const additionalDropped = this.failOpenQueuedRequestsForCooldown();
|
|
@@ -949,7 +942,8 @@ export class LocalLlmClient {
|
|
|
949
942
|
}
|
|
950
943
|
|
|
951
944
|
try {
|
|
952
|
-
|
|
945
|
+
if (options.signal?.aborted) return null;
|
|
946
|
+
const isAvailable = await this.checkAvailability(options.signal);
|
|
953
947
|
if (!isAvailable) {
|
|
954
948
|
log.debug(
|
|
955
949
|
`local LLM: checkAvailability returned false for ${this.config.localLlmUrl}`,
|
|
@@ -1040,6 +1034,16 @@ export class LocalLlmClient {
|
|
|
1040
1034
|
let lastAbortError: Error | null = null;
|
|
1041
1035
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
1042
1036
|
const attemptAbort = new AbortController();
|
|
1037
|
+
const onCallerAbort = (): void => {
|
|
1038
|
+
attemptAbort.abort(options.signal?.reason);
|
|
1039
|
+
};
|
|
1040
|
+
if (options.signal) {
|
|
1041
|
+
if (options.signal.aborted) {
|
|
1042
|
+
onCallerAbort();
|
|
1043
|
+
} else {
|
|
1044
|
+
options.signal.addEventListener("abort", onCallerAbort, { once: true });
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1043
1047
|
const attemptTimeout = setTimeout(() => attemptAbort.abort(), effectiveTimeoutMs);
|
|
1044
1048
|
try {
|
|
1045
1049
|
response = await this.chatTransport.post({
|
|
@@ -1052,19 +1056,20 @@ export class LocalLlmClient {
|
|
|
1052
1056
|
budgetMs: this.config.localLlmTimeoutMs,
|
|
1053
1057
|
});
|
|
1054
1058
|
} catch (err) {
|
|
1055
|
-
if (!
|
|
1059
|
+
if (!isAbortError(err)) throw err;
|
|
1056
1060
|
lastAbortError = err instanceof Error ? err : new Error(String(err));
|
|
1057
|
-
if (attempt
|
|
1058
|
-
|
|
1059
|
-
log.warn(
|
|
1060
|
-
`local LLM request aborted: op=${operation} attempt=${attempt}/${maxAttempts} timeoutMs=${effectiveTimeoutMs} model=${this.config.localLlmModel}; retrying after ${backoffMs}ms`,
|
|
1061
|
-
);
|
|
1062
|
-
await new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
1063
|
-
continue;
|
|
1061
|
+
if (options.signal?.aborted || attempt >= maxAttempts) {
|
|
1062
|
+
break;
|
|
1064
1063
|
}
|
|
1065
|
-
|
|
1064
|
+
const backoffMs = this.config.localLlmRetryBackoffMs * attempt;
|
|
1065
|
+
log.warn(
|
|
1066
|
+
`local LLM request aborted: op=${operation} attempt=${attempt}/${maxAttempts} timeoutMs=${effectiveTimeoutMs} model=${this.config.localLlmModel}; retrying after ${backoffMs}ms`,
|
|
1067
|
+
);
|
|
1068
|
+
if (!(await waitForRetryBackoff(backoffMs, options.signal))) return null;
|
|
1069
|
+
continue;
|
|
1066
1070
|
} finally {
|
|
1067
1071
|
clearTimeout(attemptTimeout);
|
|
1072
|
+
options.signal?.removeEventListener("abort", onCallerAbort);
|
|
1068
1073
|
}
|
|
1069
1074
|
|
|
1070
1075
|
if (response.ok) break;
|
|
@@ -1072,7 +1077,7 @@ export class LocalLlmClient {
|
|
|
1072
1077
|
try {
|
|
1073
1078
|
const errorText = await response.clone().text();
|
|
1074
1079
|
const nonRecoverableReason =
|
|
1075
|
-
|
|
1080
|
+
extractNonRecoverableBackendReasonFromErrorText(errorText);
|
|
1076
1081
|
if (nonRecoverableReason) {
|
|
1077
1082
|
this.markBackendUnavailable(
|
|
1078
1083
|
nonRecoverableReason,
|
|
@@ -1091,12 +1096,11 @@ export class LocalLlmClient {
|
|
|
1091
1096
|
log.warn(
|
|
1092
1097
|
`local LLM request got ${response.status}; retrying (attempt ${attempt + 1}/${maxAttempts}) after ${backoffMs}ms`,
|
|
1093
1098
|
);
|
|
1094
|
-
|
|
1099
|
+
if (!(await waitForRetryBackoff(backoffMs, options.signal))) return null;
|
|
1095
1100
|
}
|
|
1096
1101
|
log.debug(
|
|
1097
1102
|
`local LLM: received response, status=${response?.status}, ok=${response?.ok}`,
|
|
1098
1103
|
);
|
|
1099
|
-
|
|
1100
1104
|
if (!response) {
|
|
1101
1105
|
if (lastAbortError) {
|
|
1102
1106
|
log.warn(
|
|
@@ -1131,8 +1135,8 @@ export class LocalLlmClient {
|
|
|
1131
1135
|
`(op=${operation}, model=${this.config.localLlmModel}, url=${chatUrl}, promptChars=${promptChars}, maxTokens=${requestBody.max_tokens as number})`,
|
|
1132
1136
|
);
|
|
1133
1137
|
const nonRecoverableReason =
|
|
1134
|
-
|
|
1135
|
-
|
|
1138
|
+
extractNonRecoverableBackendReason(reason) ??
|
|
1139
|
+
extractNonRecoverableBackendReasonFromErrorText(errorText);
|
|
1136
1140
|
if (nonRecoverableReason) {
|
|
1137
1141
|
this.markBackendUnavailable(
|
|
1138
1142
|
nonRecoverableReason,
|
|
@@ -1206,7 +1210,7 @@ export class LocalLlmClient {
|
|
|
1206
1210
|
} catch (err) {
|
|
1207
1211
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1208
1212
|
const durationMs = Date.now() - startedAtMs;
|
|
1209
|
-
if (
|
|
1213
|
+
if (isAbortError(err)) {
|
|
1210
1214
|
log.warn(
|
|
1211
1215
|
`local LLM request aborted: op=${operation} timeoutMs=${options.timeoutMs ?? this.config.localLlmTimeoutMs} model=${this.config.localLlmModel} durationMs=${durationMs} error=${errMsg}`,
|
|
1212
1216
|
);
|
|
@@ -1214,7 +1218,7 @@ export class LocalLlmClient {
|
|
|
1214
1218
|
}
|
|
1215
1219
|
log.warn(`local LLM request error: op=${operation} error=${errMsg}`);
|
|
1216
1220
|
this.isAvailable = false; // Mark as unavailable on non-abort errors
|
|
1217
|
-
const nonRecoverableReason =
|
|
1221
|
+
const nonRecoverableReason = extractNonRecoverableBackendReason(errMsg);
|
|
1218
1222
|
if (nonRecoverableReason) {
|
|
1219
1223
|
this.markBackendUnavailable(
|
|
1220
1224
|
nonRecoverableReason,
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import type { BufferTurn, ExtractionFailureClass, ExtractionResult, MetaState } from "../types.js";
|
|
2
|
+
import type { StorageManager } from "../index.js";
|
|
3
|
+
import { log } from "../logger.js";
|
|
4
|
+
|
|
5
|
+
export function combineExtractionAbortSignals(
|
|
6
|
+
primary: AbortSignal | undefined,
|
|
7
|
+
deadlineController: AbortController | undefined,
|
|
8
|
+
): AbortSignal | undefined {
|
|
9
|
+
if (!deadlineController) return primary;
|
|
10
|
+
return primary ? AbortSignal.any([primary, deadlineController.signal]) : deadlineController.signal;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
15
|
+
return typeof value === "object" && value !== null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function deriveTopicsFromExtraction(result: ExtractionResult): string[] {
|
|
19
|
+
if (!isRecord(result)) return [];
|
|
20
|
+
const topics = new Set<string>();
|
|
21
|
+
const facts = Array.isArray(result.facts) ? result.facts : [];
|
|
22
|
+
for (const rawFact of facts) {
|
|
23
|
+
if (!isRecord(rawFact)) continue;
|
|
24
|
+
const tags = Array.isArray(rawFact.tags) ? rawFact.tags : [];
|
|
25
|
+
for (const tag of tags) {
|
|
26
|
+
if (typeof tag === "string" && tag.length >= 2) topics.add(tag.toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
if (typeof rawFact.entityRef === "string" && rawFact.entityRef.length >= 2) {
|
|
29
|
+
topics.add(rawFact.entityRef.toLowerCase());
|
|
30
|
+
}
|
|
31
|
+
if (typeof rawFact.category === "string" && rawFact.category.length > 0) {
|
|
32
|
+
topics.add(rawFact.category);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const entities = Array.isArray(result.entities) ? result.entities : [];
|
|
36
|
+
for (const rawEntity of entities) {
|
|
37
|
+
if (!isRecord(rawEntity)) continue;
|
|
38
|
+
if (typeof rawEntity.name === "string" && rawEntity.name.length >= 2) {
|
|
39
|
+
topics.add(rawEntity.name.toLowerCase());
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return [...topics].slice(0, 16);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Bounded cap on persisted per-fingerprint retry-state entries (per namespace meta). */
|
|
46
|
+
export const EXTRACTION_RETRY_STATE_MAX_ENTRIES = 500;
|
|
47
|
+
|
|
48
|
+
export interface ExtractionRetryStateEntry {
|
|
49
|
+
attempts: number;
|
|
50
|
+
nextEligibleAtMs: number;
|
|
51
|
+
firstFailedAtMs: number;
|
|
52
|
+
lastFailureClass: ExtractionFailureClass;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ExtractionResilienceStatus {
|
|
56
|
+
breaker: {
|
|
57
|
+
state: "closed" | "open" | "half_open";
|
|
58
|
+
openUntilMs: number;
|
|
59
|
+
consecutiveFailures: number;
|
|
60
|
+
lastReason: string;
|
|
61
|
+
};
|
|
62
|
+
backoffFingerprintCount: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Pure backoff scheduler. Returns the absolute ms timestamp at which a
|
|
67
|
+
* fingerprint that has failed `attempts` times becomes eligible again:
|
|
68
|
+
* exponential via the configured schedule, clamped to `maxBackoffMs`, with
|
|
69
|
+
* ±`jitterRatio` multiplicative jitter. `rng` is injectable for deterministic
|
|
70
|
+
* tests. Never returns a timestamp before `now`.
|
|
71
|
+
*/
|
|
72
|
+
export function computeExtractionRetryNextEligibleMs(
|
|
73
|
+
attempts: number,
|
|
74
|
+
scheduleMs: readonly number[],
|
|
75
|
+
maxBackoffMs: number,
|
|
76
|
+
jitterRatio: number,
|
|
77
|
+
now: number,
|
|
78
|
+
rng: () => number = Math.random,
|
|
79
|
+
): number {
|
|
80
|
+
if (!Number.isFinite(attempts) || !Number.isInteger(attempts) || attempts < 1) {
|
|
81
|
+
throw new RangeError("attempts must be a finite integer >= 1");
|
|
82
|
+
}
|
|
83
|
+
if (!Number.isFinite(maxBackoffMs) || maxBackoffMs < 0) {
|
|
84
|
+
throw new RangeError("maxBackoffMs must be a finite number >= 0");
|
|
85
|
+
}
|
|
86
|
+
if (!Number.isFinite(jitterRatio) || jitterRatio < 0 || jitterRatio > 1) {
|
|
87
|
+
throw new RangeError("jitterRatio must be a finite number in [0, 1]");
|
|
88
|
+
}
|
|
89
|
+
const safeNow = Number.isFinite(now) ? now : 0;
|
|
90
|
+
const cap = maxBackoffMs;
|
|
91
|
+
if (!Array.isArray(scheduleMs) || scheduleMs.length === 0) {
|
|
92
|
+
return safeNow + cap;
|
|
93
|
+
}
|
|
94
|
+
const idx = Math.min(attempts - 1, scheduleMs.length - 1);
|
|
95
|
+
const step = scheduleMs[idx];
|
|
96
|
+
const base = Math.min(typeof step === "number" && Number.isFinite(step) && step > 0 ? step : cap, cap);
|
|
97
|
+
const randomValue = rng();
|
|
98
|
+
if (!Number.isFinite(randomValue) || randomValue < 0 || randomValue > 1) {
|
|
99
|
+
throw new RangeError("rng() must return a finite number in [0, 1]");
|
|
100
|
+
}
|
|
101
|
+
const jitter = 1 + (randomValue * 2 - 1) * jitterRatio;
|
|
102
|
+
return safeNow + Math.max(0, Math.round(base * jitter));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Cap the persisted retry-state array to the newest `maxEntries` by
|
|
107
|
+
* firstFailedAt. Guards invalid caps so they cannot turn `slice(-maxEntries)`
|
|
108
|
+
* into an unbounded copy (AGENTS.md rule 17).
|
|
109
|
+
*/
|
|
110
|
+
export function capExtractionRetryStateEntries<T extends { firstFailedAt: string }>(
|
|
111
|
+
entries: readonly T[],
|
|
112
|
+
maxEntries: number,
|
|
113
|
+
): T[] {
|
|
114
|
+
if (!Number.isFinite(maxEntries) || !Number.isInteger(maxEntries) || maxEntries <= 0) return [];
|
|
115
|
+
const sorted = [...entries].sort((a, b) => a.firstFailedAt.localeCompare(b.firstFailedAt));
|
|
116
|
+
return sorted.slice(-maxEntries);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Derive a single `sourceConnector` from a batch of turns.
|
|
121
|
+
* Returns the connector ONLY when ALL turns carry the same connector.
|
|
122
|
+
* Mixed tagged/untagged batches return undefined — extraction facts are
|
|
123
|
+
* persisted at batch level, so attributing them to the single tagged
|
|
124
|
+
* connector would falsely label facts from untagged turns.
|
|
125
|
+
* Conflicting connectors (different values) also return undefined.
|
|
126
|
+
*/
|
|
127
|
+
export function deriveSourceConnector(turns: readonly BufferTurn[]): string | undefined {
|
|
128
|
+
if (turns.length === 0) return undefined;
|
|
129
|
+
const connectors = new Set<string>();
|
|
130
|
+
let untaggedCount = 0;
|
|
131
|
+
for (const turn of turns) {
|
|
132
|
+
if (typeof turn.sourceConnector === "string" && turn.sourceConnector.length > 0) {
|
|
133
|
+
connectors.add(turn.sourceConnector);
|
|
134
|
+
} else {
|
|
135
|
+
untaggedCount += 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// All turns must agree on the same connector — no untagged turns mixed in.
|
|
139
|
+
if (untaggedCount > 0) return undefined;
|
|
140
|
+
return connectors.size === 1 ? [...connectors][0] : undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export async function runExtractionPostPersistBestEffort(
|
|
144
|
+
runDeadlineAware: (
|
|
145
|
+
operation: () => Promise<unknown>,
|
|
146
|
+
phase: string,
|
|
147
|
+
clearTimerOnError?: boolean,
|
|
148
|
+
options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean },
|
|
149
|
+
) => Promise<unknown>,
|
|
150
|
+
stage: string,
|
|
151
|
+
operation: () => Promise<unknown>,
|
|
152
|
+
options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean; propagateErrors?: boolean },
|
|
153
|
+
): Promise<void> {
|
|
154
|
+
try {
|
|
155
|
+
await runDeadlineAware(operation, stage, false, {
|
|
156
|
+
ignoreAbort: options?.ignoreAbort,
|
|
157
|
+
ignoreDeadline: options?.ignoreDeadline,
|
|
158
|
+
});
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (options?.propagateErrors) throw error;
|
|
161
|
+
log.warn(`runExtraction: ${stage} failed after persistence (non-fatal)`, error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Applies deferred-judge retention only to live, non-shadow extraction runs.
|
|
167
|
+
* Replay/import paths must not synthesize live-buffer entries after persistence.
|
|
168
|
+
*/
|
|
169
|
+
export interface ExtractionDeferRetentionOptions {
|
|
170
|
+
clearBufferAfterExtraction: boolean;
|
|
171
|
+
extractionJudgeShadow: boolean;
|
|
172
|
+
getDeferredCount: () => number;
|
|
173
|
+
normalizedTurns: BufferTurn[];
|
|
174
|
+
bufferKey: string;
|
|
175
|
+
retainDeferredTurns: (bufferKey: string, turns: BufferTurn[], max: number) => Promise<void>;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function runExtractionDeferRetention(
|
|
179
|
+
runPostPersistBestEffort: (
|
|
180
|
+
stage: string,
|
|
181
|
+
operation: () => Promise<unknown>,
|
|
182
|
+
options?: { ignoreAbort?: boolean },
|
|
183
|
+
) => Promise<void>,
|
|
184
|
+
options: ExtractionDeferRetentionOptions,
|
|
185
|
+
): Promise<void> {
|
|
186
|
+
await runPostPersistBestEffort("during_defer_retention", async () => {
|
|
187
|
+
if (options.clearBufferAfterExtraction && !options.extractionJudgeShadow) {
|
|
188
|
+
const deferredCount = options.getDeferredCount();
|
|
189
|
+
if (deferredCount > 0 && options.normalizedTurns.length > 0) {
|
|
190
|
+
await options.retainDeferredTurns(options.bufferKey, options.normalizedTurns, 10);
|
|
191
|
+
} else {
|
|
192
|
+
await options.retainDeferredTurns(options.bufferKey, [], 0);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface ExtractionPostPersistOptions {
|
|
199
|
+
result: ExtractionResult;
|
|
200
|
+
storage: StorageManager;
|
|
201
|
+
meta?: MetaState;
|
|
202
|
+
extractionFingerprint?: string;
|
|
203
|
+
shouldPersistProcessedFingerprint: boolean;
|
|
204
|
+
recordProcessedExtractionFingerprint: (
|
|
205
|
+
storage: StorageManager,
|
|
206
|
+
fingerprint: string,
|
|
207
|
+
meta: MetaState,
|
|
208
|
+
) => Promise<void>;
|
|
209
|
+
runDeadlineAware: (
|
|
210
|
+
operation: () => Promise<unknown>,
|
|
211
|
+
phase: string,
|
|
212
|
+
clearTimerOnError?: boolean,
|
|
213
|
+
options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean },
|
|
214
|
+
) => Promise<unknown>;
|
|
215
|
+
isDeadlineError: (error: unknown) => boolean;
|
|
216
|
+
createDeadlineError: (stage: string) => Error;
|
|
217
|
+
deadlineMs?: number;
|
|
218
|
+
clearBufferAfterExtraction: boolean;
|
|
219
|
+
runPostPersistBestEffort: (
|
|
220
|
+
stage: string,
|
|
221
|
+
operation: () => Promise<unknown>,
|
|
222
|
+
options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean; propagateErrors?: boolean },
|
|
223
|
+
) => Promise<void>;
|
|
224
|
+
extractionJudgeShadow: boolean;
|
|
225
|
+
getDeferredCount: () => number;
|
|
226
|
+
normalizedTurns: BufferTurn[];
|
|
227
|
+
bufferKey: string;
|
|
228
|
+
retainDeferredTurns: (bufferKey: string, turns: BufferTurn[], max: number) => Promise<void>;
|
|
229
|
+
clearBuffer: (options?: { ignoreAbort?: boolean }) => Promise<void>;
|
|
230
|
+
failOnExtractionFailure: boolean;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface ExtractionPostPersistResult {
|
|
234
|
+
meta?: MetaState;
|
|
235
|
+
metadataFailed: boolean;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export async function runExtractionPostPersist(
|
|
239
|
+
options: ExtractionPostPersistOptions,
|
|
240
|
+
): Promise<ExtractionPostPersistResult> {
|
|
241
|
+
let metadataFailed = false;
|
|
242
|
+
let deadlineError: Error | undefined;
|
|
243
|
+
const recordFailure = (stage: string, error: unknown): void => {
|
|
244
|
+
metadataFailed = true;
|
|
245
|
+
if (options.isDeadlineError(error) && deadlineError === undefined) {
|
|
246
|
+
deadlineError = error as Error;
|
|
247
|
+
}
|
|
248
|
+
log.warn(`runExtraction: ${stage} failed after durable persistence; continuing with buffer clear`, error);
|
|
249
|
+
};
|
|
250
|
+
let meta = options.meta;
|
|
251
|
+
try {
|
|
252
|
+
meta ??= (await options.runDeadlineAware(
|
|
253
|
+
() => options.storage.loadMeta(),
|
|
254
|
+
"during_post_persist_load_meta",
|
|
255
|
+
false,
|
|
256
|
+
)) as MetaState;
|
|
257
|
+
} catch (error) {
|
|
258
|
+
recordFailure("metadata load", error);
|
|
259
|
+
}
|
|
260
|
+
if (meta && options.extractionFingerprint && options.shouldPersistProcessedFingerprint) {
|
|
261
|
+
try {
|
|
262
|
+
await options.runDeadlineAware(
|
|
263
|
+
() => options.recordProcessedExtractionFingerprint(options.storage, options.extractionFingerprint!, meta!),
|
|
264
|
+
"during_post_persist_fingerprint",
|
|
265
|
+
false,
|
|
266
|
+
);
|
|
267
|
+
} catch (error) {
|
|
268
|
+
recordFailure("processed fingerprint", error);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (meta) {
|
|
272
|
+
meta.extractionCount += 1;
|
|
273
|
+
meta.lastExtractionAt = new Date().toISOString();
|
|
274
|
+
meta.totalMemories += Array.isArray(options.result.facts) ? options.result.facts.length : 0;
|
|
275
|
+
meta.totalEntities += Array.isArray(options.result.entities) ? options.result.entities.length : 0;
|
|
276
|
+
try {
|
|
277
|
+
await options.runDeadlineAware(
|
|
278
|
+
() => options.storage.saveMeta(meta!),
|
|
279
|
+
"during_post_persist_meta_save",
|
|
280
|
+
false,
|
|
281
|
+
);
|
|
282
|
+
} catch (error) {
|
|
283
|
+
recordFailure("metadata save", error);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const runBestEffort = options.runPostPersistBestEffort;
|
|
287
|
+
await runExtractionDeferRetention(runBestEffort, {
|
|
288
|
+
clearBufferAfterExtraction: options.clearBufferAfterExtraction,
|
|
289
|
+
extractionJudgeShadow: options.extractionJudgeShadow,
|
|
290
|
+
getDeferredCount: options.getDeferredCount,
|
|
291
|
+
normalizedTurns: options.normalizedTurns,
|
|
292
|
+
bufferKey: options.bufferKey,
|
|
293
|
+
retainDeferredTurns: options.retainDeferredTurns,
|
|
294
|
+
});
|
|
295
|
+
await runBestEffort(
|
|
296
|
+
"during_buffer_clear",
|
|
297
|
+
() => options.clearBuffer({ ignoreAbort: true }),
|
|
298
|
+
{
|
|
299
|
+
ignoreAbort: true,
|
|
300
|
+
ignoreDeadline: options.failOnExtractionFailure,
|
|
301
|
+
propagateErrors: options.failOnExtractionFailure,
|
|
302
|
+
},
|
|
303
|
+
);
|
|
304
|
+
if (options.failOnExtractionFailure && typeof options.deadlineMs === "number" && Date.now() >= options.deadlineMs) {
|
|
305
|
+
throw options.createDeadlineError("during_buffer_clear");
|
|
306
|
+
}
|
|
307
|
+
if (deadlineError) throw deadlineError;
|
|
308
|
+
return { meta, metadataFailed };
|
|
309
|
+
}
|