@remnic/core 10.0.33 → 10.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abort-error.d.ts +2 -0
- package/dist/abort-error.d.ts.map +1 -1
- package/dist/abort-error.js +5 -1
- package/dist/access-admin-ops-surface.js +82 -82
- package/dist/access-authorization-probe.js +83 -83
- package/dist/access-boundary.js +82 -82
- package/dist/access-cli.js +142 -142
- package/dist/access-coding-context-resolution.js +3 -3
- package/dist/access-extraction-force-flush.js +82 -82
- package/dist/access-http-briefing.js +83 -83
- package/dist/access-http-query.js +84 -84
- package/dist/access-http.js +102 -102
- package/dist/access-idempotency.js +3 -3
- package/dist/access-identity-continuity-surface.js +82 -82
- package/dist/access-lcm-surface.js +82 -82
- package/dist/access-mcp.js +94 -94
- package/dist/access-namespace-preflight.js +82 -82
- package/dist/access-observe-helpers.d.ts +3 -2
- package/dist/access-observe-helpers.d.ts.map +1 -1
- package/dist/access-observe-helpers.js +2 -1
- package/dist/access-observe-transcript.js +3 -3
- package/dist/access-observe-write-category.js +15 -15
- package/dist/access-observe-write-surface.d.ts +2 -2
- package/dist/access-observe-write-surface.d.ts.map +1 -1
- package/dist/access-observe-write-surface.js +82 -82
- package/dist/access-offline-manifest.js +17 -17
- package/dist/access-operations-batch.js +86 -86
- package/dist/access-operations.js +93 -93
- package/dist/access-recall-concurrency.js +82 -82
- package/dist/access-recall-response.js +82 -82
- package/dist/access-recall-surface.js +82 -82
- package/dist/access-schema.js +10 -10
- package/dist/access-service.d.ts +1 -1
- package/dist/access-service.d.ts.map +1 -1
- package/dist/access-service.js +82 -82
- package/dist/access-surface-catalog.js +84 -84
- package/dist/active-recall.js +41 -41
- package/dist/artifact-search.js +3 -3
- package/dist/{auto-sync-MX2AHVPQ.js → auto-sync-VPHR3FBI.js} +12 -12
- package/dist/briefing-window.js +2 -2
- package/dist/briefing.js +33 -33
- package/dist/buffer.js +16 -16
- package/dist/calibration.js +4 -4
- package/dist/{capsule-merge-LGYZAMO4.js → capsule-merge-RNQUP2VL.js} +6 -6
- package/dist/capture-write-lock.js +4 -4
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +35 -35
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.js +5 -5
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-UBBZFODO.js → chunk-23VGZ65V.js} +2 -2
- package/dist/{chunk-3CZRBTJK.js → chunk-2NLCDNGA.js} +3 -3
- package/dist/{chunk-7WWITD3H.js → chunk-2ZYIAUYU.js} +2 -2
- package/dist/{chunk-2FIJQNL7.js → chunk-3ODEGTVV.js} +2 -2
- package/dist/{chunk-A54E2ZTD.js → chunk-4AHKNZW7.js} +2 -2
- package/dist/{chunk-NU247WVX.js → chunk-4ISHIPOC.js} +3 -3
- package/dist/{chunk-K6RQ2KOX.js → chunk-4Z7O2QVJ.js} +2 -2
- package/dist/{chunk-FLI6DEIU.js → chunk-53OWLEAD.js} +2 -2
- package/dist/{chunk-EPOYPPOW.js → chunk-5EILJ6W2.js} +2 -2
- package/dist/{chunk-VY47VI2T.js → chunk-5IIQU4JZ.js} +2 -2
- package/dist/{chunk-RBGRQEW3.js → chunk-5KBIOI4G.js} +2 -2
- package/dist/{chunk-NQV6G6MU.js → chunk-5LWODP5R.js} +2 -2
- package/dist/{chunk-3Q3N35W7.js → chunk-63E37JCN.js} +2 -2
- package/dist/{chunk-Z3XTS4TD.js → chunk-66NLI5NK.js} +30 -30
- package/dist/{chunk-C2AOL6MK.js → chunk-6FIFEXFF.js} +4 -4
- package/dist/{chunk-DP3TSAYT.js → chunk-6NXHX6MI.js} +2 -2
- package/dist/{chunk-HOSJESKO.js → chunk-6VYY2XFK.js} +6 -6
- package/dist/{chunk-XD5YSVP5.js → chunk-6WR4UGJN.js} +2 -2
- package/dist/{chunk-IWUFKS4J.js → chunk-77IXBNV6.js} +2 -2
- package/dist/{chunk-O6S5FLZB.js → chunk-77ZK533I.js} +2 -2
- package/dist/{chunk-KJZKO2M6.js → chunk-7EPY3IQL.js} +2 -2
- package/dist/{chunk-MGKH5KO3.js → chunk-7FG2JSU6.js} +2 -2
- package/dist/{chunk-LGR54NYT.js → chunk-7VJEZQYF.js} +9 -7
- package/dist/chunk-7VJEZQYF.js.map +1 -0
- package/dist/{chunk-F5FZ7DB4.js → chunk-7WTTE5FW.js} +2 -2
- package/dist/{chunk-PL26BCRN.js → chunk-A2D3WICT.js} +2 -2
- package/dist/{chunk-DNZ2CWPG.js → chunk-A4B7WL5N.js} +2 -2
- package/dist/{chunk-YYEOR4XN.js → chunk-AAANTXCQ.js} +3 -3
- package/dist/{chunk-TPSLVZHS.js → chunk-AF2XMJKD.js} +2 -2
- package/dist/{chunk-5JI3XWI2.js → chunk-AHS3QEEA.js} +2 -2
- package/dist/{chunk-NKW27NU3.js → chunk-AI2VXOSO.js} +3 -3
- package/dist/{chunk-YHLWPYHT.js → chunk-APYY5CX3.js} +3 -3
- package/dist/{chunk-4ZTVOECF.js → chunk-B6L7BKA7.js} +2 -2
- package/dist/{chunk-AN3G5DZH.js → chunk-BBDASWNT.js} +2 -2
- package/dist/{chunk-KXRX7YC2.js → chunk-BCCG7VWM.js} +2 -2
- package/dist/{chunk-OIKLZCJD.js → chunk-BRZRP5WD.js} +2 -2
- package/dist/{chunk-OCWNT322.js → chunk-C6S2Y7HE.js} +2 -2
- package/dist/{chunk-GDPTMK5V.js → chunk-CIJRM6SQ.js} +2 -2
- package/dist/{chunk-LVU7FP27.js → chunk-CJKHLACF.js} +3 -3
- package/dist/{chunk-QLDZJEJC.js → chunk-D75ET36O.js} +5 -5
- package/dist/{chunk-BDHYRMJC.js → chunk-DFP37GUN.js} +2 -2
- package/dist/{chunk-RN7HPFYS.js → chunk-DG5UKN2Y.js} +2 -2
- package/dist/{chunk-VAPVRDC4.js → chunk-DJMC4W6N.js} +2 -2
- package/dist/{chunk-TRMJ6BYC.js → chunk-DM5QZ3YU.js} +2 -2
- package/dist/{chunk-2XYXESKN.js → chunk-DMLCETTO.js} +6 -6
- package/dist/{chunk-EUCYTCFP.js → chunk-DZPTR2XQ.js} +2 -2
- package/dist/{chunk-5B5WYAHQ.js → chunk-EBRG7ZIK.js} +2 -2
- package/dist/{chunk-3CRE3UZI.js → chunk-EH6KLYIE.js} +4 -4
- package/dist/{chunk-DMDWFQMR.js → chunk-ERMT5WQM.js} +2 -2
- package/dist/{chunk-VOKHZRHW.js → chunk-EXYT52NR.js} +3 -3
- package/dist/{chunk-CBH2Z4UA.js → chunk-F5GVIPC7.js} +2 -2
- package/dist/{chunk-KW5B533Q.js → chunk-FOTV6L22.js} +205 -169
- package/dist/chunk-FOTV6L22.js.map +1 -0
- package/dist/{chunk-APRGEZQN.js → chunk-FQ52AJXX.js} +3 -3
- package/dist/{chunk-6JMQR72P.js → chunk-FRXS6SC7.js} +2 -2
- package/dist/{chunk-5GT4ESLR.js → chunk-FXO43NBW.js} +3 -3
- package/dist/{chunk-KW4AJ7T3.js → chunk-G22A6WJQ.js} +2 -2
- package/dist/{chunk-TEUPXKC5.js → chunk-G5UR4DXQ.js} +2 -2
- package/dist/{chunk-ZY4S5WMQ.js → chunk-G7XAZU2L.js} +2 -2
- package/dist/{chunk-AQ5XLA36.js → chunk-GAARPWMN.js} +2 -2
- package/dist/{chunk-5GX5457J.js → chunk-GDYLZ6FR.js} +4 -4
- package/dist/{chunk-32WCMGIF.js → chunk-GK56GNNS.js} +7 -7
- package/dist/{chunk-7SXUGYPE.js → chunk-GKNX4QO3.js} +3 -3
- package/dist/{chunk-UIDWASOS.js → chunk-GMMZ45C4.js} +2 -2
- package/dist/{chunk-IRBXNULW.js → chunk-GSN77SST.js} +53 -51
- package/dist/chunk-GSN77SST.js.map +1 -0
- package/dist/{chunk-MND4YJSX.js → chunk-GY4R4P2A.js} +2 -2
- package/dist/{chunk-2VBDSZ7U.js → chunk-H6SKBCNI.js} +2 -2
- package/dist/{chunk-SGII36L6.js → chunk-H7QC7WCU.js} +4 -4
- package/dist/{chunk-Z7L72ZHL.js → chunk-HADD45AR.js} +3 -3
- package/dist/{chunk-K6YJGWJP.js → chunk-HJM23E65.js} +4 -4
- package/dist/{chunk-GEHIRZXF.js → chunk-HRT2SJPC.js} +3 -3
- package/dist/{chunk-DLH3ECZP.js → chunk-HTTZ3GJ6.js} +2 -2
- package/dist/{chunk-YRULQW5J.js → chunk-HXFIILGF.js} +2 -2
- package/dist/{chunk-53GYS3GG.js → chunk-I6QGI65T.js} +3 -3
- package/dist/{chunk-BDLOEODO.js → chunk-IHTKBQBS.js} +2 -2
- package/dist/{chunk-AHCELJMH.js → chunk-IS4HKNWP.js} +2 -2
- package/dist/{chunk-BXCKME3Q.js → chunk-IV2HEXK3.js} +2 -2
- package/dist/{chunk-6MC7UQ6D.js → chunk-IVYAPAHG.js} +2 -2
- package/dist/{chunk-UXWO5L7B.js → chunk-JKJTXIDI.js} +7 -7
- package/dist/{chunk-3BOQPLCF.js → chunk-JNELS2TW.js} +2 -2
- package/dist/{chunk-YIN6Y2I4.js → chunk-JPQCHBTK.js} +2 -2
- package/dist/{chunk-3VYNGM5A.js → chunk-K567EIW3.js} +2 -2
- package/dist/{chunk-4IYIGN53.js → chunk-KRAMCBIW.js} +2 -2
- package/dist/{chunk-TI6EN3PF.js → chunk-KRH4KQGP.js} +17 -17
- package/dist/{chunk-KFR343VH.js → chunk-LO775P3S.js} +2 -2
- package/dist/{chunk-VXWOJPSY.js → chunk-LWRIGKFM.js} +2 -2
- package/dist/{chunk-U4BNX4R2.js → chunk-M3GKSCFN.js} +4 -4
- package/dist/{chunk-3JYHSXYS.js → chunk-MWJ25UMW.js} +3 -3
- package/dist/{chunk-YVGXH72Y.js → chunk-NGHDW6UU.js} +2 -2
- package/dist/{chunk-D3EXT5KG.js → chunk-NHB4RC3G.js} +3 -3
- package/dist/{chunk-ZGP2XB4S.js → chunk-O3VKQMWC.js} +16 -16
- package/dist/{chunk-MCLZM5G7.js → chunk-OOOX5C4X.js} +2 -2
- package/dist/{chunk-SIGAGKNE.js → chunk-OR42ZI54.js} +2 -2
- package/dist/{chunk-RU6WB55E.js → chunk-ORWDCX5Q.js} +4 -4
- package/dist/{chunk-6MKLMEBE.js → chunk-P4GUQSK3.js} +2 -2
- package/dist/{chunk-JTACUJP3.js → chunk-PCIIKQXW.js} +2 -2
- package/dist/{chunk-IDPZCHET.js → chunk-PH33R7GN.js} +3 -3
- package/dist/{chunk-JAYNUYSJ.js → chunk-PTQZPVRQ.js} +2 -2
- package/dist/{chunk-RRYN5FFC.js → chunk-QISYYK4L.js} +4 -4
- package/dist/{chunk-M3VACAD2.js → chunk-QJFNB6Z5.js} +2 -2
- package/dist/{chunk-HNTB7NIE.js → chunk-QQ4T622E.js} +2 -2
- package/dist/{chunk-3GOPAWA7.js → chunk-QZP3RMYP.js} +5 -5
- package/dist/{chunk-BTTPKDIL.js → chunk-R2MBW2S4.js} +10 -1
- package/dist/chunk-R2MBW2S4.js.map +1 -0
- package/dist/{chunk-UAAAXSKQ.js → chunk-R4SATHCV.js} +2 -2
- package/dist/{chunk-4O4TKIXQ.js → chunk-RNFMFC37.js} +2 -2
- package/dist/{chunk-C2RW36YR.js → chunk-S2PDFSXS.js} +1 -1
- package/dist/{chunk-PZWW6MDE.js → chunk-S2S4U4G3.js} +4 -4
- package/dist/{chunk-H6Z3RNW3.js → chunk-S57QBPTA.js} +2 -2
- package/dist/{chunk-GZXXPCWJ.js → chunk-SE3JAD22.js} +2 -2
- package/dist/{chunk-ZJGTJAB3.js → chunk-SGLEHJ4P.js} +2 -2
- package/dist/{chunk-5SMHQW45.js → chunk-SIIWHIBK.js} +2 -2
- package/dist/{chunk-6FOKJ423.js → chunk-SQ554O3K.js} +2 -2
- package/dist/{chunk-ISMZ5UNE.js → chunk-STM4T335.js} +3 -3
- package/dist/{chunk-QNDOTDJK.js → chunk-TGAXRT7N.js} +2 -2
- package/dist/{chunk-LLHZZOIB.js → chunk-TRSKATZQ.js} +2 -2
- package/dist/{chunk-5CIKBKU6.js → chunk-TVM47JQB.js} +6 -6
- package/dist/{chunk-HMON55NJ.js → chunk-UAYA4NJN.js} +3 -3
- package/dist/{chunk-LNEWDF2A.js → chunk-UKQFCOGT.js} +34 -8
- package/dist/chunk-UKQFCOGT.js.map +1 -0
- package/dist/{chunk-PGHYQMKZ.js → chunk-UR25IQVT.js} +6 -6
- package/dist/{chunk-5ARKPBLS.js → chunk-UTMVZPAV.js} +2 -2
- package/dist/{chunk-6EDW54SQ.js → chunk-UUZ7KZAO.js} +4 -4
- package/dist/{chunk-66BCOVW2.js → chunk-V44DWTFA.js} +5 -5
- package/dist/{chunk-SWWHIJUJ.js → chunk-VILPVT4S.js} +3 -3
- package/dist/{chunk-DZBMASSI.js → chunk-VNAIUNXI.js} +11 -11
- package/dist/{chunk-DNIG3JME.js → chunk-VY6BD5KB.js} +3 -3
- package/dist/{chunk-UZRSI6NX.js → chunk-WI6MIJYK.js} +2 -2
- package/dist/{chunk-5AUY5Z5E.js → chunk-WJ6S54ES.js} +3 -3
- package/dist/{chunk-IEGJFQPG.js → chunk-WRFXSJGW.js} +2 -2
- package/dist/{chunk-MGCKZWAE.js → chunk-X3IFRQKS.js} +2 -2
- package/dist/{chunk-PGRZ3FYC.js → chunk-X4OZMANG.js} +2 -2
- package/dist/{chunk-5GPHJ333.js → chunk-X73SCHKR.js} +2 -2
- package/dist/{chunk-YXWLQHAW.js → chunk-XA32GZ6B.js} +3 -3
- package/dist/{chunk-XVZIBMSY.js → chunk-XFDHL252.js} +4 -4
- package/dist/{chunk-MZZEMPCI.js → chunk-XUB4I2N6.js} +2 -2
- package/dist/{chunk-GUMZC2BO.js → chunk-Y5NLBXPV.js} +2 -2
- package/dist/{chunk-CU5TILGD.js → chunk-YIJECSIX.js} +2 -2
- package/dist/{chunk-QNQNFRIZ.js → chunk-YIMDCBNV.js} +2 -2
- package/dist/{chunk-HPWJ5B7D.js → chunk-YK7ZJPQM.js} +2 -2
- package/dist/{chunk-ZEMBRSKK.js → chunk-YLF42JQ7.js} +2 -2
- package/dist/{chunk-T2JSUEH6.js → chunk-YLXETSAH.js} +2 -2
- package/dist/{chunk-WKVL2G7X.js → chunk-YOL56HY5.js} +5 -5
- package/dist/{chunk-5B4UQF6K.js → chunk-YXNVNMHB.js} +7 -7
- package/dist/{chunk-RXFCU3CY.js → chunk-YXW4KXCV.js} +2 -2
- package/dist/{chunk-NYPQHFC3.js → chunk-ZABEDRGQ.js} +2 -2
- package/dist/{chunk-ASBDON6P.js → chunk-ZRU7636R.js} +11 -11
- package/dist/cli.js +118 -118
- package/dist/coding/export-okf-codegraph.js +33 -33
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.js +35 -35
- package/dist/config.js +41 -41
- package/dist/connectors/codex-materialize-runner.js +32 -32
- package/dist/connectors/index.js +32 -32
- package/dist/consolidation-provenance-check.js +6 -6
- package/dist/consolidation-undo.js +5 -5
- package/dist/contradiction/index.js +7 -7
- package/dist/convergence-refresh.js +34 -34
- package/dist/corpus-read-cancellation.js +2 -2
- package/dist/corpus-watermark.js +34 -34
- package/dist/deep-recall-http-glue.js +11 -11
- package/dist/deep-recall-policy-llm.js +4 -4
- package/dist/deep-recall.js +2 -2
- package/dist/direct-answer-wiring.js +2 -2
- package/dist/embedding-fallback.js +5 -5
- package/dist/embedding-generation-lock.js +4 -4
- package/dist/{entity-canonical-id-migration-GD5MPFUF.js → entity-canonical-id-migration-2YOLMOFC.js} +6 -6
- package/dist/entity-mention-index-cache.js +2 -2
- package/dist/entity-recall-cancellation.js +3 -3
- package/dist/entity-retrieval.js +34 -34
- package/dist/explicit-capture.js +10 -10
- package/dist/external-wiki-access.js +83 -83
- package/dist/extraction-faithfulness.js +4 -4
- package/dist/extraction-judge.js +4 -4
- package/dist/extraction.js +40 -40
- package/dist/fallback-llm-codex-subscription.js +2 -2
- package/dist/fallback-llm.js +3 -3
- package/dist/{forget-GXBWFKRC.js → forget-E6ZTUKEC.js} +5 -5
- package/dist/{graph-edge-decay-BYPZVJT4.js → graph-edge-decay-IU75NV42.js} +8 -8
- package/dist/graph-jsonl.js +6 -6
- package/dist/graph-snapshot.js +6 -6
- package/dist/graph-write-lock.js +4 -4
- package/dist/graph.js +5 -5
- package/dist/harmonic-retrieval.js +33 -33
- package/dist/harmonic-source-lookup.js +2 -2
- package/dist/http-retry.js +2 -2
- package/dist/index.js +142 -142
- package/dist/live-connectors-runner.js +3 -3
- package/dist/local-llm.js +3 -3
- package/dist/location/index.js +35 -35
- package/dist/maintenance/memory-governance.js +32 -32
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +32 -32
- package/dist/maintenance/rebuild-memory-projection-runner.js +34 -34
- package/dist/maintenance/rebuild-memory-projection.js +33 -33
- package/dist/memory-browse-operations.js +83 -83
- package/dist/memory-browse.js +9 -9
- package/dist/memory-subject.js +5 -5
- package/dist/namespaces/migrate.js +33 -33
- package/dist/namespaces/search.js +13 -13
- package/dist/namespaces/storage.js +32 -32
- package/dist/offline-sync-changeset-generations.js +6 -6
- package/dist/offline-sync-embedding-generation.js +5 -5
- package/dist/offline-sync-file-io.js +2 -2
- package/dist/offline-sync-impression-drain.js +8 -8
- package/dist/offline-sync-snapshot-stream.js +10 -10
- package/dist/offline-sync-upload-staging.js +3 -3
- package/dist/offline-sync.js +9 -9
- package/dist/operator-doctor-corpus.js +35 -35
- package/dist/operator-toolkit.js +56 -56
- package/dist/orchestration/extraction-queue-coordinator.d.ts +9 -1
- package/dist/orchestration/extraction-queue-coordinator.d.ts.map +1 -1
- package/dist/orchestration/extraction-run.d.ts +3 -5
- package/dist/orchestration/extraction-run.d.ts.map +1 -1
- package/dist/orchestration/maintenance.js +49 -49
- package/dist/orchestration/session-context.d.ts +2 -7
- package/dist/orchestration/session-context.d.ts.map +1 -1
- package/dist/orchestration/turn-ingestion.d.ts +6 -14
- package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +142 -142
- package/dist/page-versioning.js +5 -5
- package/dist/qmd-daemon-session.js +3 -3
- package/dist/qmd-mcp-cancel.js +2 -2
- package/dist/qmd-preflight.js +2 -2
- package/dist/qmd.js +6 -6
- package/dist/recall-composition-decision.js +2 -2
- package/dist/recall-navigation-operations.js +83 -83
- package/dist/recall-navigation.js +82 -82
- package/dist/recall-planner-llm.js +3 -3
- package/dist/recall-qos.js +2 -2
- package/dist/recall-state-view-admission.js +9 -9
- package/dist/recall-state.js +4 -4
- package/dist/recall-why-service.js +9 -9
- package/dist/reconcile/manifest.js +5 -5
- package/dist/{resolution-AMYTPT5X.js → resolution-V6JBMW7U.js} +8 -8
- package/dist/resume-bundles.js +42 -42
- package/dist/retrieval-agents.js +2 -2
- package/dist/salvage-envelope.js +7 -7
- package/dist/search/embed-helper.js +3 -3
- package/dist/search/factory.js +12 -12
- package/dist/search/index.js +12 -12
- package/dist/search/lancedb-backend.js +3 -3
- package/dist/search/meilisearch-backend.js +3 -3
- package/dist/search/orama-backend.js +3 -3
- package/dist/semantic-consolidation.js +33 -33
- package/dist/semantic-rule-promotion.js +32 -32
- package/dist/semantic-rule-verifier.js +32 -32
- package/dist/shared-context/manager.js +2 -2
- package/dist/source-agent-qualifier.js +38 -38
- package/dist/standup/build.js +32 -32
- package/dist/storage.js +31 -31
- package/dist/subject-config.js +6 -6
- package/dist/summarizer.js +8 -8
- package/dist/summary-snapshot.js +4 -4
- package/dist/support-passport/index.js +85 -85
- package/dist/{trace-QBQVS5BC.js → trace-LQOA3HKD.js} +3 -3
- package/dist/transfer/capsule-import.js +6 -6
- package/dist/transfer/export-okf.js +32 -32
- package/dist/utils/serialize-mutations.js +3 -3
- package/dist/verified-recall.js +32 -32
- package/dist/who-knows-cli.js +33 -33
- package/dist/who-knows.js +32 -32
- package/dist/write-envelope.js +6 -6
- package/package.json +2 -2
- package/src/abort-error.ts +10 -0
- package/src/access-observe-helpers.ts +40 -6
- package/src/access-observe-write-surface.ts +7 -4
- package/src/access-service-observe-lcm-parity.test.ts +1 -12
- package/src/access-service-observe-scope.test.ts +74 -0
- package/src/access-service.ts +3 -2
- package/src/orchestration/extraction-queue-coordinator.ts +37 -3
- package/src/orchestration/extraction-run.ts +7 -7
- package/src/orchestration/session-context.ts +4 -7
- package/src/orchestration/turn-ingestion.ts +22 -23
- package/src/orchestrator-extraction-queue.test.ts +48 -0
- package/src/orchestrator-flush.test.ts +2 -0
- package/src/orchestrator.ts +2 -7
- package/dist/chunk-BTTPKDIL.js.map +0 -1
- package/dist/chunk-IRBXNULW.js.map +0 -1
- package/dist/chunk-KW5B533Q.js.map +0 -1
- package/dist/chunk-LGR54NYT.js.map +0 -1
- package/dist/chunk-LNEWDF2A.js.map +0 -1
- /package/dist/{auto-sync-MX2AHVPQ.js.map → auto-sync-VPHR3FBI.js.map} +0 -0
- /package/dist/{capsule-merge-LGYZAMO4.js.map → capsule-merge-RNQUP2VL.js.map} +0 -0
- /package/dist/{chunk-UBBZFODO.js.map → chunk-23VGZ65V.js.map} +0 -0
- /package/dist/{chunk-3CZRBTJK.js.map → chunk-2NLCDNGA.js.map} +0 -0
- /package/dist/{chunk-7WWITD3H.js.map → chunk-2ZYIAUYU.js.map} +0 -0
- /package/dist/{chunk-2FIJQNL7.js.map → chunk-3ODEGTVV.js.map} +0 -0
- /package/dist/{chunk-A54E2ZTD.js.map → chunk-4AHKNZW7.js.map} +0 -0
- /package/dist/{chunk-NU247WVX.js.map → chunk-4ISHIPOC.js.map} +0 -0
- /package/dist/{chunk-K6RQ2KOX.js.map → chunk-4Z7O2QVJ.js.map} +0 -0
- /package/dist/{chunk-FLI6DEIU.js.map → chunk-53OWLEAD.js.map} +0 -0
- /package/dist/{chunk-EPOYPPOW.js.map → chunk-5EILJ6W2.js.map} +0 -0
- /package/dist/{chunk-VY47VI2T.js.map → chunk-5IIQU4JZ.js.map} +0 -0
- /package/dist/{chunk-RBGRQEW3.js.map → chunk-5KBIOI4G.js.map} +0 -0
- /package/dist/{chunk-NQV6G6MU.js.map → chunk-5LWODP5R.js.map} +0 -0
- /package/dist/{chunk-3Q3N35W7.js.map → chunk-63E37JCN.js.map} +0 -0
- /package/dist/{chunk-Z3XTS4TD.js.map → chunk-66NLI5NK.js.map} +0 -0
- /package/dist/{chunk-C2AOL6MK.js.map → chunk-6FIFEXFF.js.map} +0 -0
- /package/dist/{chunk-DP3TSAYT.js.map → chunk-6NXHX6MI.js.map} +0 -0
- /package/dist/{chunk-HOSJESKO.js.map → chunk-6VYY2XFK.js.map} +0 -0
- /package/dist/{chunk-XD5YSVP5.js.map → chunk-6WR4UGJN.js.map} +0 -0
- /package/dist/{chunk-IWUFKS4J.js.map → chunk-77IXBNV6.js.map} +0 -0
- /package/dist/{chunk-O6S5FLZB.js.map → chunk-77ZK533I.js.map} +0 -0
- /package/dist/{chunk-KJZKO2M6.js.map → chunk-7EPY3IQL.js.map} +0 -0
- /package/dist/{chunk-MGKH5KO3.js.map → chunk-7FG2JSU6.js.map} +0 -0
- /package/dist/{chunk-F5FZ7DB4.js.map → chunk-7WTTE5FW.js.map} +0 -0
- /package/dist/{chunk-PL26BCRN.js.map → chunk-A2D3WICT.js.map} +0 -0
- /package/dist/{chunk-DNZ2CWPG.js.map → chunk-A4B7WL5N.js.map} +0 -0
- /package/dist/{chunk-YYEOR4XN.js.map → chunk-AAANTXCQ.js.map} +0 -0
- /package/dist/{chunk-TPSLVZHS.js.map → chunk-AF2XMJKD.js.map} +0 -0
- /package/dist/{chunk-5JI3XWI2.js.map → chunk-AHS3QEEA.js.map} +0 -0
- /package/dist/{chunk-NKW27NU3.js.map → chunk-AI2VXOSO.js.map} +0 -0
- /package/dist/{chunk-YHLWPYHT.js.map → chunk-APYY5CX3.js.map} +0 -0
- /package/dist/{chunk-4ZTVOECF.js.map → chunk-B6L7BKA7.js.map} +0 -0
- /package/dist/{chunk-AN3G5DZH.js.map → chunk-BBDASWNT.js.map} +0 -0
- /package/dist/{chunk-KXRX7YC2.js.map → chunk-BCCG7VWM.js.map} +0 -0
- /package/dist/{chunk-OIKLZCJD.js.map → chunk-BRZRP5WD.js.map} +0 -0
- /package/dist/{chunk-OCWNT322.js.map → chunk-C6S2Y7HE.js.map} +0 -0
- /package/dist/{chunk-GDPTMK5V.js.map → chunk-CIJRM6SQ.js.map} +0 -0
- /package/dist/{chunk-LVU7FP27.js.map → chunk-CJKHLACF.js.map} +0 -0
- /package/dist/{chunk-QLDZJEJC.js.map → chunk-D75ET36O.js.map} +0 -0
- /package/dist/{chunk-BDHYRMJC.js.map → chunk-DFP37GUN.js.map} +0 -0
- /package/dist/{chunk-RN7HPFYS.js.map → chunk-DG5UKN2Y.js.map} +0 -0
- /package/dist/{chunk-VAPVRDC4.js.map → chunk-DJMC4W6N.js.map} +0 -0
- /package/dist/{chunk-TRMJ6BYC.js.map → chunk-DM5QZ3YU.js.map} +0 -0
- /package/dist/{chunk-2XYXESKN.js.map → chunk-DMLCETTO.js.map} +0 -0
- /package/dist/{chunk-EUCYTCFP.js.map → chunk-DZPTR2XQ.js.map} +0 -0
- /package/dist/{chunk-5B5WYAHQ.js.map → chunk-EBRG7ZIK.js.map} +0 -0
- /package/dist/{chunk-3CRE3UZI.js.map → chunk-EH6KLYIE.js.map} +0 -0
- /package/dist/{chunk-DMDWFQMR.js.map → chunk-ERMT5WQM.js.map} +0 -0
- /package/dist/{chunk-VOKHZRHW.js.map → chunk-EXYT52NR.js.map} +0 -0
- /package/dist/{chunk-CBH2Z4UA.js.map → chunk-F5GVIPC7.js.map} +0 -0
- /package/dist/{chunk-APRGEZQN.js.map → chunk-FQ52AJXX.js.map} +0 -0
- /package/dist/{chunk-6JMQR72P.js.map → chunk-FRXS6SC7.js.map} +0 -0
- /package/dist/{chunk-5GT4ESLR.js.map → chunk-FXO43NBW.js.map} +0 -0
- /package/dist/{chunk-KW4AJ7T3.js.map → chunk-G22A6WJQ.js.map} +0 -0
- /package/dist/{chunk-TEUPXKC5.js.map → chunk-G5UR4DXQ.js.map} +0 -0
- /package/dist/{chunk-ZY4S5WMQ.js.map → chunk-G7XAZU2L.js.map} +0 -0
- /package/dist/{chunk-AQ5XLA36.js.map → chunk-GAARPWMN.js.map} +0 -0
- /package/dist/{chunk-5GX5457J.js.map → chunk-GDYLZ6FR.js.map} +0 -0
- /package/dist/{chunk-32WCMGIF.js.map → chunk-GK56GNNS.js.map} +0 -0
- /package/dist/{chunk-7SXUGYPE.js.map → chunk-GKNX4QO3.js.map} +0 -0
- /package/dist/{chunk-UIDWASOS.js.map → chunk-GMMZ45C4.js.map} +0 -0
- /package/dist/{chunk-MND4YJSX.js.map → chunk-GY4R4P2A.js.map} +0 -0
- /package/dist/{chunk-2VBDSZ7U.js.map → chunk-H6SKBCNI.js.map} +0 -0
- /package/dist/{chunk-SGII36L6.js.map → chunk-H7QC7WCU.js.map} +0 -0
- /package/dist/{chunk-Z7L72ZHL.js.map → chunk-HADD45AR.js.map} +0 -0
- /package/dist/{chunk-K6YJGWJP.js.map → chunk-HJM23E65.js.map} +0 -0
- /package/dist/{chunk-GEHIRZXF.js.map → chunk-HRT2SJPC.js.map} +0 -0
- /package/dist/{chunk-DLH3ECZP.js.map → chunk-HTTZ3GJ6.js.map} +0 -0
- /package/dist/{chunk-YRULQW5J.js.map → chunk-HXFIILGF.js.map} +0 -0
- /package/dist/{chunk-53GYS3GG.js.map → chunk-I6QGI65T.js.map} +0 -0
- /package/dist/{chunk-BDLOEODO.js.map → chunk-IHTKBQBS.js.map} +0 -0
- /package/dist/{chunk-AHCELJMH.js.map → chunk-IS4HKNWP.js.map} +0 -0
- /package/dist/{chunk-BXCKME3Q.js.map → chunk-IV2HEXK3.js.map} +0 -0
- /package/dist/{chunk-6MC7UQ6D.js.map → chunk-IVYAPAHG.js.map} +0 -0
- /package/dist/{chunk-UXWO5L7B.js.map → chunk-JKJTXIDI.js.map} +0 -0
- /package/dist/{chunk-3BOQPLCF.js.map → chunk-JNELS2TW.js.map} +0 -0
- /package/dist/{chunk-YIN6Y2I4.js.map → chunk-JPQCHBTK.js.map} +0 -0
- /package/dist/{chunk-3VYNGM5A.js.map → chunk-K567EIW3.js.map} +0 -0
- /package/dist/{chunk-4IYIGN53.js.map → chunk-KRAMCBIW.js.map} +0 -0
- /package/dist/{chunk-TI6EN3PF.js.map → chunk-KRH4KQGP.js.map} +0 -0
- /package/dist/{chunk-KFR343VH.js.map → chunk-LO775P3S.js.map} +0 -0
- /package/dist/{chunk-VXWOJPSY.js.map → chunk-LWRIGKFM.js.map} +0 -0
- /package/dist/{chunk-U4BNX4R2.js.map → chunk-M3GKSCFN.js.map} +0 -0
- /package/dist/{chunk-3JYHSXYS.js.map → chunk-MWJ25UMW.js.map} +0 -0
- /package/dist/{chunk-YVGXH72Y.js.map → chunk-NGHDW6UU.js.map} +0 -0
- /package/dist/{chunk-D3EXT5KG.js.map → chunk-NHB4RC3G.js.map} +0 -0
- /package/dist/{chunk-ZGP2XB4S.js.map → chunk-O3VKQMWC.js.map} +0 -0
- /package/dist/{chunk-MCLZM5G7.js.map → chunk-OOOX5C4X.js.map} +0 -0
- /package/dist/{chunk-SIGAGKNE.js.map → chunk-OR42ZI54.js.map} +0 -0
- /package/dist/{chunk-RU6WB55E.js.map → chunk-ORWDCX5Q.js.map} +0 -0
- /package/dist/{chunk-6MKLMEBE.js.map → chunk-P4GUQSK3.js.map} +0 -0
- /package/dist/{chunk-JTACUJP3.js.map → chunk-PCIIKQXW.js.map} +0 -0
- /package/dist/{chunk-IDPZCHET.js.map → chunk-PH33R7GN.js.map} +0 -0
- /package/dist/{chunk-JAYNUYSJ.js.map → chunk-PTQZPVRQ.js.map} +0 -0
- /package/dist/{chunk-RRYN5FFC.js.map → chunk-QISYYK4L.js.map} +0 -0
- /package/dist/{chunk-M3VACAD2.js.map → chunk-QJFNB6Z5.js.map} +0 -0
- /package/dist/{chunk-HNTB7NIE.js.map → chunk-QQ4T622E.js.map} +0 -0
- /package/dist/{chunk-3GOPAWA7.js.map → chunk-QZP3RMYP.js.map} +0 -0
- /package/dist/{chunk-UAAAXSKQ.js.map → chunk-R4SATHCV.js.map} +0 -0
- /package/dist/{chunk-4O4TKIXQ.js.map → chunk-RNFMFC37.js.map} +0 -0
- /package/dist/{chunk-C2RW36YR.js.map → chunk-S2PDFSXS.js.map} +0 -0
- /package/dist/{chunk-PZWW6MDE.js.map → chunk-S2S4U4G3.js.map} +0 -0
- /package/dist/{chunk-H6Z3RNW3.js.map → chunk-S57QBPTA.js.map} +0 -0
- /package/dist/{chunk-GZXXPCWJ.js.map → chunk-SE3JAD22.js.map} +0 -0
- /package/dist/{chunk-ZJGTJAB3.js.map → chunk-SGLEHJ4P.js.map} +0 -0
- /package/dist/{chunk-5SMHQW45.js.map → chunk-SIIWHIBK.js.map} +0 -0
- /package/dist/{chunk-6FOKJ423.js.map → chunk-SQ554O3K.js.map} +0 -0
- /package/dist/{chunk-ISMZ5UNE.js.map → chunk-STM4T335.js.map} +0 -0
- /package/dist/{chunk-QNDOTDJK.js.map → chunk-TGAXRT7N.js.map} +0 -0
- /package/dist/{chunk-LLHZZOIB.js.map → chunk-TRSKATZQ.js.map} +0 -0
- /package/dist/{chunk-5CIKBKU6.js.map → chunk-TVM47JQB.js.map} +0 -0
- /package/dist/{chunk-HMON55NJ.js.map → chunk-UAYA4NJN.js.map} +0 -0
- /package/dist/{chunk-PGHYQMKZ.js.map → chunk-UR25IQVT.js.map} +0 -0
- /package/dist/{chunk-5ARKPBLS.js.map → chunk-UTMVZPAV.js.map} +0 -0
- /package/dist/{chunk-6EDW54SQ.js.map → chunk-UUZ7KZAO.js.map} +0 -0
- /package/dist/{chunk-66BCOVW2.js.map → chunk-V44DWTFA.js.map} +0 -0
- /package/dist/{chunk-SWWHIJUJ.js.map → chunk-VILPVT4S.js.map} +0 -0
- /package/dist/{chunk-DZBMASSI.js.map → chunk-VNAIUNXI.js.map} +0 -0
- /package/dist/{chunk-DNIG3JME.js.map → chunk-VY6BD5KB.js.map} +0 -0
- /package/dist/{chunk-UZRSI6NX.js.map → chunk-WI6MIJYK.js.map} +0 -0
- /package/dist/{chunk-5AUY5Z5E.js.map → chunk-WJ6S54ES.js.map} +0 -0
- /package/dist/{chunk-IEGJFQPG.js.map → chunk-WRFXSJGW.js.map} +0 -0
- /package/dist/{chunk-MGCKZWAE.js.map → chunk-X3IFRQKS.js.map} +0 -0
- /package/dist/{chunk-PGRZ3FYC.js.map → chunk-X4OZMANG.js.map} +0 -0
- /package/dist/{chunk-5GPHJ333.js.map → chunk-X73SCHKR.js.map} +0 -0
- /package/dist/{chunk-YXWLQHAW.js.map → chunk-XA32GZ6B.js.map} +0 -0
- /package/dist/{chunk-XVZIBMSY.js.map → chunk-XFDHL252.js.map} +0 -0
- /package/dist/{chunk-MZZEMPCI.js.map → chunk-XUB4I2N6.js.map} +0 -0
- /package/dist/{chunk-GUMZC2BO.js.map → chunk-Y5NLBXPV.js.map} +0 -0
- /package/dist/{chunk-CU5TILGD.js.map → chunk-YIJECSIX.js.map} +0 -0
- /package/dist/{chunk-QNQNFRIZ.js.map → chunk-YIMDCBNV.js.map} +0 -0
- /package/dist/{chunk-HPWJ5B7D.js.map → chunk-YK7ZJPQM.js.map} +0 -0
- /package/dist/{chunk-ZEMBRSKK.js.map → chunk-YLF42JQ7.js.map} +0 -0
- /package/dist/{chunk-T2JSUEH6.js.map → chunk-YLXETSAH.js.map} +0 -0
- /package/dist/{chunk-WKVL2G7X.js.map → chunk-YOL56HY5.js.map} +0 -0
- /package/dist/{chunk-5B4UQF6K.js.map → chunk-YXNVNMHB.js.map} +0 -0
- /package/dist/{chunk-RXFCU3CY.js.map → chunk-YXW4KXCV.js.map} +0 -0
- /package/dist/{chunk-NYPQHFC3.js.map → chunk-ZABEDRGQ.js.map} +0 -0
- /package/dist/{chunk-ASBDON6P.js.map → chunk-ZRU7636R.js.map} +0 -0
- /package/dist/{entity-canonical-id-migration-GD5MPFUF.js.map → entity-canonical-id-migration-2YOLMOFC.js.map} +0 -0
- /package/dist/{forget-GXBWFKRC.js.map → forget-E6ZTUKEC.js.map} +0 -0
- /package/dist/{graph-edge-decay-BYPZVJT4.js.map → graph-edge-decay-IU75NV42.js.map} +0 -0
- /package/dist/{resolution-AMYTPT5X.js.map → resolution-V6JBMW7U.js.map} +0 -0
- /package/dist/{trace-QBQVS5BC.js.map → trace-LQOA3HKD.js.map} +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isPreemptedExtraction } from "./abort-error.js";
|
|
2
|
+
|
|
1
3
|
type PendingObservePreparation = {
|
|
2
4
|
cancelled: boolean;
|
|
3
5
|
scopeHint?: string;
|
|
@@ -49,6 +51,7 @@ export function pendingObserveScopeHint(options: {
|
|
|
49
51
|
|
|
50
52
|
type PendingObserveExtraction = {
|
|
51
53
|
promise: Promise<void>;
|
|
54
|
+
running: Promise<void>;
|
|
52
55
|
controllers: Set<AbortController>;
|
|
53
56
|
};
|
|
54
57
|
|
|
@@ -131,12 +134,17 @@ export class PendingObserveExtractionTracker {
|
|
|
131
134
|
const previous = this.entries.get(key);
|
|
132
135
|
const promise = previous
|
|
133
136
|
? Promise.allSettled([previous.promise, extraction]).then((results) => {
|
|
134
|
-
const rejected = results.find(
|
|
137
|
+
const rejected = results.find(
|
|
138
|
+
(result): result is PromiseRejectedResult =>
|
|
139
|
+
result.status === "rejected" &&
|
|
140
|
+
!(result.reason instanceof Error && isPreemptedExtraction(result.reason)),
|
|
141
|
+
);
|
|
135
142
|
if (rejected) throw rejected.reason;
|
|
136
143
|
})
|
|
137
144
|
: extraction;
|
|
138
145
|
const entry = {
|
|
139
146
|
promise,
|
|
147
|
+
running: previous?.running ?? extraction,
|
|
140
148
|
controllers: new Set(previous ? [...previous.controllers, controller] : [controller]),
|
|
141
149
|
};
|
|
142
150
|
this.entries.set(key, entry);
|
|
@@ -144,8 +152,8 @@ export class PendingObserveExtractionTracker {
|
|
|
144
152
|
.then(() => {
|
|
145
153
|
if (this.entries.get(key) === entry) this.entries.delete(key);
|
|
146
154
|
})
|
|
147
|
-
.catch(() => {
|
|
148
|
-
|
|
155
|
+
.catch((error) => {
|
|
156
|
+
if (error instanceof Error && isPreemptedExtraction(error) && this.entries.get(key) === entry) this.entries.delete(key);
|
|
149
157
|
});
|
|
150
158
|
}
|
|
151
159
|
|
|
@@ -167,21 +175,30 @@ export class PendingObserveExtractionTracker {
|
|
|
167
175
|
principal?: string,
|
|
168
176
|
namespace?: string,
|
|
169
177
|
scopeHint?: string,
|
|
178
|
+
reason?: Error,
|
|
170
179
|
): void {
|
|
171
180
|
for (const reservation of this.preparations.get(sessionKey) ?? []) {
|
|
172
181
|
if (!preparationMatchesScope(reservation, principal, namespace, scopeHint)) continue;
|
|
173
182
|
reservation.cancelled = true;
|
|
174
183
|
}
|
|
175
184
|
|
|
185
|
+
this.abortTracked(sessionKey, principal, namespace, reason);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private abortTracked(
|
|
189
|
+
sessionKey: string,
|
|
190
|
+
principal: string | undefined,
|
|
191
|
+
namespace: string | undefined,
|
|
192
|
+
reason?: Error,
|
|
193
|
+
): void {
|
|
176
194
|
for (const [key, entry] of this.entries) {
|
|
177
195
|
const [entrySessionKey, entryPrincipal, entryNamespace] = key.split("\u0000");
|
|
178
196
|
if (
|
|
179
197
|
entrySessionKey !== sessionKey ||
|
|
180
198
|
(principal !== undefined && entryPrincipal !== (principal ?? "")) ||
|
|
181
199
|
(namespace !== undefined && entryNamespace !== (namespace ?? ""))
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
for (const controller of entry.controllers) controller.abort();
|
|
200
|
+
) continue;
|
|
201
|
+
for (const controller of entry.controllers) controller.abort(reason);
|
|
185
202
|
}
|
|
186
203
|
}
|
|
187
204
|
|
|
@@ -192,15 +209,31 @@ export class PendingObserveExtractionTracker {
|
|
|
192
209
|
abortSignal?: AbortSignal,
|
|
193
210
|
registerCancellation?: (cancel: () => void) => void,
|
|
194
211
|
scopeHint?: string,
|
|
212
|
+
preemptAfterAdmission?: () => void,
|
|
195
213
|
): Promise<void> {
|
|
196
214
|
const key = this.key(sessionKey, principal, namespace);
|
|
215
|
+
let cancelled = abortSignal?.aborted === true;
|
|
197
216
|
const abortTracked = (): void => {
|
|
217
|
+
cancelled = true;
|
|
198
218
|
this.cancel(sessionKey, principal, namespace, scopeHint);
|
|
199
219
|
};
|
|
200
220
|
registerCancellation?.(abortTracked);
|
|
201
221
|
abortSignal?.addEventListener("abort", abortTracked, { once: true });
|
|
202
222
|
try {
|
|
203
223
|
await this.waitForPreparations(sessionKey, principal, namespace, scopeHint);
|
|
224
|
+
if (cancelled || abortSignal?.aborted) return;
|
|
225
|
+
if (preemptAfterAdmission) {
|
|
226
|
+
preemptAfterAdmission();
|
|
227
|
+
const running = this.entries.get(key)?.running;
|
|
228
|
+
if (!running) return;
|
|
229
|
+
try {
|
|
230
|
+
await running;
|
|
231
|
+
} catch (error) {
|
|
232
|
+
if (this.entries.get(key)?.running === running) this.entries.delete(key);
|
|
233
|
+
if (!(error instanceof Error && isPreemptedExtraction(error))) throw error;
|
|
234
|
+
}
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
204
237
|
while (true) {
|
|
205
238
|
const entry = this.entries.get(key);
|
|
206
239
|
if (!entry) return;
|
|
@@ -209,6 +242,7 @@ export class PendingObserveExtractionTracker {
|
|
|
209
242
|
} catch (error) {
|
|
210
243
|
if (this.entries.get(key) !== entry) continue;
|
|
211
244
|
this.entries.delete(key);
|
|
245
|
+
if (error instanceof Error && isPreemptedExtraction(error)) return;
|
|
212
246
|
throw error;
|
|
213
247
|
}
|
|
214
248
|
if (this.entries.get(key) !== entry) continue;
|
|
@@ -119,7 +119,8 @@ export interface AccessObserveWriteSurfaceDeps {
|
|
|
119
119
|
sessionKey: string,
|
|
120
120
|
principal?: string,
|
|
121
121
|
namespace?: string,
|
|
122
|
-
scopeHint?: string
|
|
122
|
+
scopeHint?: string,
|
|
123
|
+
reason?: Error,
|
|
123
124
|
): void;
|
|
124
125
|
resolveReadableNamespace(namespace: string | undefined, principal?: string): string;
|
|
125
126
|
validateWriteCandidate(
|
|
@@ -146,9 +147,10 @@ export class AccessObserveWriteSurface {
|
|
|
146
147
|
sessionKey: string,
|
|
147
148
|
principal?: string,
|
|
148
149
|
namespace?: string,
|
|
149
|
-
scopeHint?: string
|
|
150
|
+
scopeHint?: string,
|
|
151
|
+
reason?: Error,
|
|
150
152
|
): void {
|
|
151
|
-
this.pendingObserveExtractions.cancel(sessionKey, principal, namespace, scopeHint);
|
|
153
|
+
this.pendingObserveExtractions.cancel(sessionKey, principal, namespace, scopeHint, reason);
|
|
152
154
|
}
|
|
153
155
|
constructor(private readonly deps: AccessObserveWriteSurfaceDeps) {}
|
|
154
156
|
|
|
@@ -935,7 +937,8 @@ export class AccessObserveWriteSurface {
|
|
|
935
937
|
namespace,
|
|
936
938
|
abortSignal,
|
|
937
939
|
registerCancellation,
|
|
938
|
-
scopeHint
|
|
940
|
+
scopeHint,
|
|
941
|
+
() => this.deps.orchestrator.extractionQueueCoordinator?.preemptRunning(),
|
|
939
942
|
)
|
|
940
943
|
);
|
|
941
944
|
}
|
|
@@ -614,20 +614,9 @@ test("#2128: chained observes remain behind one force-flush barrier", async () =
|
|
|
614
614
|
await service.observe(observeRequest({ sessionKey, skipExtraction: false }));
|
|
615
615
|
assert.equal(resolvers.length, 2);
|
|
616
616
|
|
|
617
|
-
let settled = false;
|
|
618
|
-
void flushPromise.then(
|
|
619
|
-
() => {
|
|
620
|
-
settled = true;
|
|
621
|
-
},
|
|
622
|
-
() => {
|
|
623
|
-
settled = true;
|
|
624
|
-
},
|
|
625
|
-
);
|
|
626
617
|
resolvers[0]?.();
|
|
627
|
-
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
628
|
-
assert.equal(settled, false);
|
|
629
|
-
resolvers[1]?.();
|
|
630
618
|
assert.equal((await flushPromise).flushed, true);
|
|
619
|
+
assert.equal(resolvers.length, 2);
|
|
631
620
|
});
|
|
632
621
|
|
|
633
622
|
test("#2128: a failed observe extraction is consumed after force-flush reports it", async () => {
|
|
@@ -34,6 +34,7 @@ import test from "node:test";
|
|
|
34
34
|
|
|
35
35
|
import { EngramAccessService } from "./access-service.js";
|
|
36
36
|
import { PendingObserveExtractionTracker } from "./access-observe-helpers.js";
|
|
37
|
+
import { preemptedExtractionError } from "./abort-error.js";
|
|
37
38
|
|
|
38
39
|
import { tokenCapabilityStore } from "./access-token-capabilities.js";
|
|
39
40
|
import { resolveAuthorizedNamespaceWritablePreflight } from "./access-namespace-preflight.js";
|
|
@@ -250,6 +251,79 @@ test("#2128 pending observe preparation is a force-flush barrier", async () => {
|
|
|
250
251
|
assert.equal(waited, true);
|
|
251
252
|
});
|
|
252
253
|
|
|
254
|
+
test("a preempted observe extraction does not block the next force-flush", async () => {
|
|
255
|
+
const tracker = new PendingObserveExtractionTracker();
|
|
256
|
+
const key = tracker.key("session-a", "alice", "default");
|
|
257
|
+
tracker.track(key, Promise.reject(preemptedExtractionError()), new AbortController());
|
|
258
|
+
await tracker.wait("session-a", "alice", "default");
|
|
259
|
+
tracker.track(key, Promise.reject(new Error("extraction failed")), new AbortController());
|
|
260
|
+
await assert.rejects(() => tracker.wait("session-a", "alice", "default"), /extraction failed/);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("cancelling a tracked extraction with a preemption reason does not block the next flush", async () => {
|
|
264
|
+
const tracker = new PendingObserveExtractionTracker();
|
|
265
|
+
const controller = new AbortController();
|
|
266
|
+
const extraction = new Promise<void>((_resolve, reject) => {
|
|
267
|
+
controller.signal.addEventListener("abort", () => reject(controller.signal.reason), { once: true });
|
|
268
|
+
});
|
|
269
|
+
tracker.track(tracker.key("session-a", "alice", "default"), extraction, controller);
|
|
270
|
+
tracker.cancel("session-a", "alice", "default", undefined, preemptedExtractionError());
|
|
271
|
+
await tracker.wait("session-a", "alice", "default");
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("flush preemption waits for admission and does not cancel the preparation", async () => {
|
|
275
|
+
const tracker = new PendingObserveExtractionTracker();
|
|
276
|
+
const preparation = tracker.reserve("session-a");
|
|
277
|
+
const controller = new AbortController();
|
|
278
|
+
const extraction = new Promise<void>((_resolve, reject) => {
|
|
279
|
+
controller.signal.addEventListener("abort", () => reject(controller.signal.reason), { once: true });
|
|
280
|
+
});
|
|
281
|
+
tracker.track(tracker.key("session-a", "alice", "default"), extraction, controller);
|
|
282
|
+
let waited = false;
|
|
283
|
+
const pending = tracker.wait(
|
|
284
|
+
"session-a", "alice", "default", undefined, undefined, undefined,
|
|
285
|
+
() => controller.abort(preemptedExtractionError()),
|
|
286
|
+
).then(() => { waited = true; });
|
|
287
|
+
await Promise.resolve();
|
|
288
|
+
assert.equal(waited, false);
|
|
289
|
+
assert.equal(preparation.isCancelled(), false);
|
|
290
|
+
preparation.release();
|
|
291
|
+
await pending;
|
|
292
|
+
assert.equal(waited, true);
|
|
293
|
+
assert.equal(preparation.isCancelled(), false);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
test("a cancelled flush does not preempt after admission", async () => {
|
|
297
|
+
const tracker = new PendingObserveExtractionTracker();
|
|
298
|
+
const preparation = tracker.reserve("session-a");
|
|
299
|
+
let preempted = false;
|
|
300
|
+
let cancel: (() => void) | undefined;
|
|
301
|
+
const pending = tracker.wait(
|
|
302
|
+
"session-a", "alice", "default", undefined, (fn) => { cancel = fn; }, undefined, () => { preempted = true; },
|
|
303
|
+
);
|
|
304
|
+
await Promise.resolve();
|
|
305
|
+
cancel?.();
|
|
306
|
+
preparation.release();
|
|
307
|
+
await pending;
|
|
308
|
+
assert.equal(preempted, false);
|
|
309
|
+
assert.equal(preparation.isCancelled(), true);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test("flush preemption does not wait for a second queued extraction", async () => {
|
|
313
|
+
const tracker = new PendingObserveExtractionTracker();
|
|
314
|
+
const first = new AbortController();
|
|
315
|
+
const firstPromise = new Promise<void>((_resolve, reject) => {
|
|
316
|
+
first.signal.addEventListener("abort", () => reject(first.signal.reason), { once: true });
|
|
317
|
+
});
|
|
318
|
+
const secondPromise = new Promise<void>(() => {});
|
|
319
|
+
const key = tracker.key("session-a", "alice", "default");
|
|
320
|
+
tracker.track(key, firstPromise, first);
|
|
321
|
+
tracker.track(key, secondPromise, new AbortController());
|
|
322
|
+
await tracker.wait("session-a", "alice", "default", undefined, undefined, undefined, () => {
|
|
323
|
+
first.abort(preemptedExtractionError());
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
|
|
253
327
|
test("#2206 scoped wait ignores unresolved preparations with a different hint", async () => {
|
|
254
328
|
const tracker = new PendingObserveExtractionTracker();
|
|
255
329
|
const target = tracker.reserve("opaque-session", "projectTag:project-a");
|
package/src/access-service.ts
CHANGED
|
@@ -4396,9 +4396,10 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
4396
4396
|
sessionKey: string,
|
|
4397
4397
|
principal?: string,
|
|
4398
4398
|
namespace?: string,
|
|
4399
|
-
scopeHint?: string
|
|
4399
|
+
scopeHint?: string,
|
|
4400
|
+
reason?: Error,
|
|
4400
4401
|
): void {
|
|
4401
|
-
this.accessObserveWriteSurface.cancelPendingObserveExtractions(sessionKey, principal, namespace, scopeHint);
|
|
4402
|
+
this.accessObserveWriteSurface.cancelPendingObserveExtractions(sessionKey, principal, namespace, scopeHint, reason);
|
|
4402
4403
|
}
|
|
4403
4404
|
async lcmCompactionRecord(
|
|
4404
4405
|
request: EngramAccessLcmCompactionRecordRequest
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* `queueBufferedExtraction` builder delegates push+scheduling here.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import { isAbortError } from "../abort-error.js";
|
|
27
|
+
import { isAbortError, preemptedExtractionError } from "../abort-error.js";
|
|
28
28
|
import { log } from "../logger.js";
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -40,6 +40,7 @@ export class ExtractionQueueCoordinator {
|
|
|
40
40
|
/** Whether the serial drain loop is currently running. */
|
|
41
41
|
private processing = false;
|
|
42
42
|
private accepting = true;
|
|
43
|
+
private runningPreempt: (() => void) | undefined;
|
|
43
44
|
|
|
44
45
|
/** Current queue depth (idle-wait + test seam). */
|
|
45
46
|
get length(): number {
|
|
@@ -56,9 +57,14 @@ export class ExtractionQueueCoordinator {
|
|
|
56
57
|
* the production entry point — the orchestrator's `queueBufferedExtraction`
|
|
57
58
|
* builds each task closure and hands it here.
|
|
58
59
|
*/
|
|
59
|
-
enqueue(task: () => Promise<void
|
|
60
|
+
enqueue(task: () => Promise<void>, options?: { front?: boolean }): boolean {
|
|
60
61
|
if (!this.accepting) return false;
|
|
61
|
-
|
|
62
|
+
if (options?.front) {
|
|
63
|
+
this.preemptRunning();
|
|
64
|
+
this.queue.unshift(task);
|
|
65
|
+
} else {
|
|
66
|
+
this.queue.push(task);
|
|
67
|
+
}
|
|
62
68
|
if (!this.processing) {
|
|
63
69
|
this.processing = true;
|
|
64
70
|
this.processQueue().catch((err) => {
|
|
@@ -69,6 +75,34 @@ export class ExtractionQueueCoordinator {
|
|
|
69
75
|
return true;
|
|
70
76
|
}
|
|
71
77
|
|
|
78
|
+
/** Automatic extraction registers this so a fail-closed flush can abort it. */
|
|
79
|
+
beginPreemptable(abort: () => void): void {
|
|
80
|
+
this.runningPreempt = abort;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
endPreemptable(): void {
|
|
84
|
+
this.runningPreempt = undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
preemptRunning(): void {
|
|
88
|
+
const abort = this.runningPreempt;
|
|
89
|
+
this.runningPreempt = undefined;
|
|
90
|
+
abort?.();
|
|
91
|
+
}
|
|
92
|
+
runPreemptable<T>(
|
|
93
|
+
preemptable: boolean,
|
|
94
|
+
parent: AbortSignal | undefined,
|
|
95
|
+
run: (signal: AbortSignal) => Promise<T>,
|
|
96
|
+
): Promise<T> {
|
|
97
|
+
const preempt = new AbortController();
|
|
98
|
+
if (preemptable) this.beginPreemptable(() => preempt.abort(preemptedExtractionError()));
|
|
99
|
+
const signal = parent ? AbortSignal.any([parent, preempt.signal]) : preempt.signal;
|
|
100
|
+
return Promise.resolve(run(signal)).finally(() => {
|
|
101
|
+
if (preemptable) this.endPreemptable();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
72
106
|
/** Stop new producers from entering the queue. */
|
|
73
107
|
stopAccepting(): void {
|
|
74
108
|
this.accepting = false;
|
|
@@ -446,12 +446,10 @@ export class ExtractionRunCoordinator {
|
|
|
446
446
|
bufferKey?: string;
|
|
447
447
|
abortSignal?: AbortSignal;
|
|
448
448
|
failOnExtractionFailure?: boolean;
|
|
449
|
-
/**
|
|
450
|
-
* Called immediately after durable extraction persistence returns, before
|
|
451
|
-
* any metadata, retention, or helper work. Lifecycle callers use this
|
|
452
|
-
* as the write-rate-limit commit boundary.
|
|
453
|
-
*/
|
|
449
|
+
/** Write-rate commit boundary, after persistence returns. */
|
|
454
450
|
onDurableCommit?: () => void;
|
|
451
|
+
/** Disarm preemption once persistence can no longer be aborted. */
|
|
452
|
+
onBeforePersist?: () => void;
|
|
455
453
|
/**
|
|
456
454
|
* Explicit namespace override for the write path (#460). When set, this
|
|
457
455
|
* is the namespace where extraction writes go instead of the one derived
|
|
@@ -550,8 +548,9 @@ export class ExtractionRunCoordinator {
|
|
|
550
548
|
if (deadlineTimer) clearTimeout(deadlineTimer);
|
|
551
549
|
}
|
|
552
550
|
};
|
|
553
|
-
const clearBuffer = async (
|
|
554
|
-
|
|
551
|
+
const clearBuffer = async (clearOptions?: { ignoreAbort?: boolean }) => {
|
|
552
|
+
options.onBeforePersist?.();
|
|
553
|
+
if (clearOptions?.ignoreAbort !== true) {
|
|
555
554
|
throwIfDeadlineExceeded("before_clear_buffer");
|
|
556
555
|
throwIfAborted("before_clear_buffer");
|
|
557
556
|
}
|
|
@@ -1063,6 +1062,7 @@ export class ExtractionRunCoordinator {
|
|
|
1063
1062
|
}
|
|
1064
1063
|
}
|
|
1065
1064
|
const originContext = deriveExtractionOriginContext(targetTurns, result.sourceConnector);
|
|
1065
|
+
options.onBeforePersist?.();
|
|
1066
1066
|
throwIfDeadlineExceeded("before_persist");
|
|
1067
1067
|
throwIfAborted("before_persist");
|
|
1068
1068
|
|
|
@@ -66,13 +66,8 @@ export interface SessionContextDeps {
|
|
|
66
66
|
) => void;
|
|
67
67
|
bufferKey?: string;
|
|
68
68
|
abortSignal?: AbortSignal;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
* `runExtraction` writes to this namespace instead of deriving one
|
|
72
|
-
* from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.
|
|
73
|
-
* Used by bulk-import to pin writes to a deterministic namespace
|
|
74
|
-
* regardless of user-configured principal routing rules.
|
|
75
|
-
*/
|
|
69
|
+
preemptable?: boolean;
|
|
70
|
+
preemptRunning?: boolean;
|
|
76
71
|
writeNamespaceOverride?: string;
|
|
77
72
|
/**
|
|
78
73
|
* Pin the provenance principal (#1495 thread 1). Forwarded to
|
|
@@ -605,6 +600,8 @@ export class SessionContextCoordinator {
|
|
|
605
600
|
skipCharThreshold: true,
|
|
606
601
|
skipUserTurnThreshold: true,
|
|
607
602
|
failOnExtractionFailure: options.failOnExtractionFailure === true,
|
|
603
|
+
preemptRunning:
|
|
604
|
+
options.reason === "access_force_flush" && options.failOnExtractionFailure === true,
|
|
608
605
|
forceExtractionAttempt: true,
|
|
609
606
|
abortSignal: options.abortSignal,
|
|
610
607
|
extractionDeadlineMs: options.extractionDeadlineMs,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { createHash, randomBytes } from "node:crypto";
|
|
20
|
-
import { abortError } from "../abort-error.js";
|
|
20
|
+
import { abortError, isPreemptedExtraction } from "../abort-error.js";
|
|
21
21
|
import { SmartBuffer } from "../buffer.js";
|
|
22
22
|
import type { ImportTurn } from "../bulk-import/types.js";
|
|
23
23
|
import { resolveNamespaceCapabilities, resolvePipelineProcessingCapabilities, resolveRecallAuxiliaryCapabilities } from "../capabilities.js";
|
|
@@ -101,13 +101,8 @@ export interface TurnIngestionDeps {
|
|
|
101
101
|
) => void;
|
|
102
102
|
bufferKey?: string;
|
|
103
103
|
abortSignal?: AbortSignal;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
* `runExtraction` writes to this namespace instead of deriving one
|
|
107
|
-
* from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.
|
|
108
|
-
* Used by bulk-import to pin writes to a deterministic namespace
|
|
109
|
-
* regardless of user-configured principal routing rules.
|
|
110
|
-
*/
|
|
104
|
+
preemptable?: boolean;
|
|
105
|
+
preemptRunning?: boolean;
|
|
111
106
|
writeNamespaceOverride?: string;
|
|
112
107
|
/**
|
|
113
108
|
* Pin the provenance principal (#1495 thread 1). Forwarded to
|
|
@@ -230,7 +225,7 @@ export class TurnIngestionCoordinator {
|
|
|
230
225
|
await this.deps.queueBufferedExtraction(
|
|
231
226
|
outcome.extractionTurns,
|
|
232
227
|
"trigger_mode",
|
|
233
|
-
{ bufferKey },
|
|
228
|
+
{ bufferKey, preemptable: true },
|
|
234
229
|
);
|
|
235
230
|
}
|
|
236
231
|
|
|
@@ -496,6 +491,7 @@ export class TurnIngestionCoordinator {
|
|
|
496
491
|
void this.deps.queueBufferedExtraction(group.turns, "trigger_mode", {
|
|
497
492
|
bufferKey,
|
|
498
493
|
clearMatchingTurns: true,
|
|
494
|
+
preemptable: true,
|
|
499
495
|
}).catch((err) => log.error(`native trigger extraction failed: ${err}`));
|
|
500
496
|
continue;
|
|
501
497
|
}
|
|
@@ -513,9 +509,8 @@ export class TurnIngestionCoordinator {
|
|
|
513
509
|
extractionDeadlineMs: options.deadlineMs,
|
|
514
510
|
writeNamespaceOverride: group.writeNamespaceOverride,
|
|
515
511
|
principalOverride: group.principalOverride,
|
|
516
|
-
// #3251: accepted groups with no plan pin dispatch null (explicit
|
|
517
|
-
// none) — not undefined which would re-resolve the CURRENT profile.
|
|
518
512
|
scopeProfileWritePlan: group.scopeProfileWritePlan ?? null,
|
|
513
|
+
preemptable: true,
|
|
519
514
|
onTaskSettled: (err) => (err ? reject(err) : resolve()),
|
|
520
515
|
}).catch(reject);
|
|
521
516
|
});
|
|
@@ -807,6 +802,7 @@ export class TurnIngestionCoordinator {
|
|
|
807
802
|
}
|
|
808
803
|
await this.deps.queueBufferedExtraction(turns, "heartbeat_observer", {
|
|
809
804
|
bufferKey,
|
|
805
|
+
preemptable: true,
|
|
810
806
|
});
|
|
811
807
|
});
|
|
812
808
|
|
|
@@ -839,13 +835,10 @@ export class TurnIngestionCoordinator {
|
|
|
839
835
|
) => void;
|
|
840
836
|
bufferKey?: string;
|
|
841
837
|
abortSignal?: AbortSignal;
|
|
842
|
-
/**
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
* Used by bulk-import to pin writes to a deterministic namespace
|
|
847
|
-
* regardless of user-configured principal routing rules.
|
|
848
|
-
*/
|
|
838
|
+
/** Automatic buffered work only. Replay and import must not set this. */
|
|
839
|
+
preemptable?: boolean;
|
|
840
|
+
/** Fail-closed force-flush only. Not implied by failOnExtractionFailure. */
|
|
841
|
+
preemptRunning?: boolean;
|
|
849
842
|
writeNamespaceOverride?: string;
|
|
850
843
|
/**
|
|
851
844
|
* Pin the provenance principal (#1495 thread 1). Forwarded to
|
|
@@ -931,8 +924,10 @@ export class TurnIngestionCoordinator {
|
|
|
931
924
|
};
|
|
932
925
|
scheduleQueueWaitTimeout();
|
|
933
926
|
}
|
|
934
|
-
|
|
927
|
+
if (settled) return;
|
|
928
|
+
const preemptable = options.preemptable === true && options.preemptRunning !== true;
|
|
935
929
|
const accepted = this.deps.extractionQueueCoordinator.enqueue(async () => {
|
|
930
|
+
await this.deps.extractionQueueCoordinator.runPreemptable(preemptable, options.abortSignal, async (abortSignal) => {
|
|
936
931
|
if (settled) return;
|
|
937
932
|
if (
|
|
938
933
|
typeof extractionDeadlineMs === "number" &&
|
|
@@ -1081,7 +1076,8 @@ export class TurnIngestionCoordinator {
|
|
|
1081
1076
|
deadlineMs: extractionDeadlineMs,
|
|
1082
1077
|
bufferKey,
|
|
1083
1078
|
onDurableCommit: options.onDurableCommit,
|
|
1084
|
-
|
|
1079
|
+
onBeforePersist: () => this.deps.extractionQueueCoordinator.endPreemptable(),
|
|
1080
|
+
abortSignal,
|
|
1085
1081
|
failOnExtractionFailure: options.failOnExtractionFailure === true,
|
|
1086
1082
|
writeNamespaceOverride: options.writeNamespaceOverride,
|
|
1087
1083
|
principalOverride: options.principalOverride,
|
|
@@ -1090,11 +1086,14 @@ export class TurnIngestionCoordinator {
|
|
|
1090
1086
|
});
|
|
1091
1087
|
settleTask(undefined, result);
|
|
1092
1088
|
} catch (err) {
|
|
1093
|
-
|
|
1094
|
-
|
|
1089
|
+
const reason = abortSignal.reason;
|
|
1090
|
+
const settledError = reason instanceof Error && isPreemptedExtraction(reason) ? reason : err;
|
|
1091
|
+
if (settleTask(settledError)) {
|
|
1092
|
+
throw settledError;
|
|
1095
1093
|
}
|
|
1096
1094
|
}
|
|
1097
|
-
|
|
1095
|
+
});
|
|
1096
|
+
}, { front: options.preemptRunning === true });
|
|
1098
1097
|
if (!accepted) {
|
|
1099
1098
|
settleTask(new Error("extraction queue is stopped"));
|
|
1100
1099
|
return;
|
|
@@ -222,3 +222,51 @@ test("stopAccepting rejects new producers until resume", async () => {
|
|
|
222
222
|
assert.equal(coordinator.enqueue(async () => {}), true);
|
|
223
223
|
assert.equal(await coordinator.pauseAndDrain(), true);
|
|
224
224
|
});
|
|
225
|
+
|
|
226
|
+
test("a front enqueue aborts the running automatic task and runs before queued work", async () => {
|
|
227
|
+
const coordinator = createCoordinator();
|
|
228
|
+
const order: string[] = [];
|
|
229
|
+
const started = Promise.withResolvers<void>();
|
|
230
|
+
coordinator.enqueue(async () => {
|
|
231
|
+
const preempt = new AbortController();
|
|
232
|
+
coordinator.beginPreemptable(() => preempt.abort());
|
|
233
|
+
started.resolve();
|
|
234
|
+
try {
|
|
235
|
+
await new Promise<void>((_resolve, reject) => {
|
|
236
|
+
preempt.signal.addEventListener("abort", () => reject(abortError("preempted")), { once: true });
|
|
237
|
+
});
|
|
238
|
+
order.push("automatic-finished");
|
|
239
|
+
} finally {
|
|
240
|
+
coordinator.endPreemptable();
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
await started.promise;
|
|
244
|
+
coordinator.enqueue(async () => {
|
|
245
|
+
order.push("queued");
|
|
246
|
+
});
|
|
247
|
+
coordinator.enqueue(async () => {
|
|
248
|
+
order.push("flush");
|
|
249
|
+
}, { front: true });
|
|
250
|
+
await coordinator.waitForIdle();
|
|
251
|
+
assert.deepEqual(order, ["flush", "queued"]);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test("a front enqueue does not abort a task that did not register as preemptable", async () => {
|
|
255
|
+
const coordinator = createCoordinator();
|
|
256
|
+
const order: string[] = [];
|
|
257
|
+
const started = Promise.withResolvers<void>();
|
|
258
|
+
const release = Promise.withResolvers<void>();
|
|
259
|
+
coordinator.enqueue(async () => {
|
|
260
|
+
started.resolve();
|
|
261
|
+
await release.promise;
|
|
262
|
+
order.push("protected");
|
|
263
|
+
});
|
|
264
|
+
await started.promise;
|
|
265
|
+
coordinator.enqueue(async () => {
|
|
266
|
+
order.push("flush");
|
|
267
|
+
}, { front: true });
|
|
268
|
+
release.resolve();
|
|
269
|
+
await coordinator.waitForIdle();
|
|
270
|
+
assert.deepEqual(order, ["protected", "flush"]);
|
|
271
|
+
});
|
|
272
|
+
|
|
@@ -112,6 +112,8 @@ test("flushSession queues extraction for the targeted buffered session", async (
|
|
|
112
112
|
assert.equal(queuedCall.options?.clearBufferAfterExtraction, true);
|
|
113
113
|
assert.equal(queuedCall.options?.skipDedupeCheck, true);
|
|
114
114
|
assert.equal(queuedCall.options?.failOnExtractionFailure, true);
|
|
115
|
+
assert.equal(queuedCall.options?.preemptRunning, true);
|
|
116
|
+
assert.equal(queuedCall.options?.preemptable, undefined);
|
|
115
117
|
assert.equal(queuedCall.options?.abortSignal, undefined);
|
|
116
118
|
assert.equal(committed, 1);
|
|
117
119
|
});
|
package/src/orchestrator.ts
CHANGED
|
@@ -3043,13 +3043,8 @@ export class Orchestrator {
|
|
|
3043
3043
|
) => void;
|
|
3044
3044
|
bufferKey?: string;
|
|
3045
3045
|
abortSignal?: AbortSignal;
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
* `runExtraction` writes to this namespace instead of deriving one
|
|
3049
|
-
* from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.
|
|
3050
|
-
* Used by bulk-import to pin writes to a deterministic namespace
|
|
3051
|
-
* regardless of user-configured principal routing rules.
|
|
3052
|
-
*/
|
|
3046
|
+
preemptable?: boolean;
|
|
3047
|
+
preemptRunning?: boolean;
|
|
3053
3048
|
writeNamespaceOverride?: string;
|
|
3054
3049
|
/**
|
|
3055
3050
|
* Pin the provenance principal (#1495 thread 1). Forwarded to
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/abort-error.ts"],"sourcesContent":["/**\n * Shared abort-error helpers.\n *\n * Consolidates the `throwIfAborted` / `abortError` / `isAbortError`\n * patterns that were independently implemented across\n * `direct-answer-wiring.ts`, `harmonic-retrieval.ts`, and `qmd.ts`\n * (plus a private pair in `orchestrator.ts`). A single helper\n * means future changes to the abort-error convention are applied\n * consistently across the codebase.\n *\n * The convention (matching Web / Node): throw a standard `Error`\n * with `name === \"AbortError\"`. Callers dispatch on name rather\n * than a specific class so error propagation across async\n * boundaries continues to classify correctly.\n */\n\n/**\n * Build an Error whose `name` is `\"AbortError\"`. Uses\n * `Object.defineProperty` so the name is non-enumerable and\n * mirrors the shape of `DOMException(\"AbortError\")` where that\n * is available.\n */\nexport function abortError(message: string): Error {\n const err = new Error(message);\n Object.defineProperty(err, \"name\", { value: \"AbortError\" });\n return err;\n}\n\n/** Return true iff `err` is an Error whose `name` is `\"AbortError\"`. */\nexport function isAbortError(err: unknown): boolean {\n return err instanceof Error && err.name === \"AbortError\";\n}\n\n/**\n * Throw an AbortError when the given signal has fired. No-op\n * when the signal is absent or not yet aborted. The default\n * message matches the prior in-module implementations.\n */\nexport function throwIfAborted(\n signal?: AbortSignal,\n message = \"operation aborted\",\n): void {\n if (signal?.aborted) {\n throw abortError(message);\n }\n}\n\nexport function raceAbort<T>(\n promise: Promise<T>,\n signal?: AbortSignal,\n message = \"operation aborted\",\n): Promise<T> {\n if (!signal) return promise;\n if (signal.aborted) return Promise.reject(abortError(message));\n let onAbort: (() => void) | undefined;\n const aborted = new Promise<never>((_resolve, reject) => {\n onAbort = () => reject(abortError(message));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n return Promise.race([promise, aborted]).finally(() => {\n if (onAbort) signal.removeEventListener(\"abort\", onAbort);\n });\n}\n"],"mappings":";AAsBO,SAAS,WAAW,SAAwB;AACjD,QAAM,MAAM,IAAI,MAAM,OAAO;AAC7B,SAAO,eAAe,KAAK,QAAQ,EAAE,OAAO,aAAa,CAAC;AAC1D,SAAO;AACT;AAGO,SAAS,aAAa,KAAuB;AAClD,SAAO,eAAe,SAAS,IAAI,SAAS;AAC9C;AAOO,SAAS,eACd,QACA,UAAU,qBACJ;AACN,MAAI,QAAQ,SAAS;AACnB,UAAM,WAAW,OAAO;AAAA,EAC1B;AACF;AAEO,SAAS,UACd,SACA,QACA,UAAU,qBACE;AACZ,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,QAAS,QAAO,QAAQ,OAAO,WAAW,OAAO,CAAC;AAC7D,MAAI;AACJ,QAAM,UAAU,IAAI,QAAe,CAAC,UAAU,WAAW;AACvD,cAAU,MAAM,OAAO,WAAW,OAAO,CAAC;AAC1C,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC1D,CAAC;AACD,SAAO,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC,EAAE,QAAQ,MAAM;AACpD,QAAI,QAAS,QAAO,oBAAoB,SAAS,OAAO;AAAA,EAC1D,CAAC;AACH;","names":[]}
|