@remnic/core 9.65.8 → 9.66.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 +11 -12
- package/dist/access-admin-ops-surface.js +49 -46
- package/dist/access-authorization-probe.d.ts +11 -12
- package/dist/access-authorization-probe.js +50 -47
- package/dist/access-boundary.d.ts +11 -12
- package/dist/access-boundary.js +49 -46
- package/dist/access-citation-namespace.js +3 -3
- package/dist/access-cli.js +111 -106
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.d.ts +1 -2
- package/dist/access-coding-context-resolution.js +2 -2
- package/dist/access-extraction-force-flush.d.ts +11 -12
- package/dist/access-extraction-force-flush.js +49 -46
- package/dist/access-health-types.d.ts +1 -2
- package/dist/access-http-lcm-compaction.d.ts +11 -12
- package/dist/access-http-lifecycle-flush.d.ts +11 -12
- package/dist/access-http-offline-stream.d.ts +11 -12
- package/dist/access-http-query.d.ts +2 -3
- package/dist/access-http-query.js +51 -48
- package/dist/access-http.d.ts +12 -13
- package/dist/access-http.js +68 -65
- package/dist/access-identity-continuity-surface.d.ts +9 -10
- package/dist/access-identity-continuity-surface.js +49 -46
- package/dist/access-lcm-surface.d.ts +11 -12
- package/dist/access-lcm-surface.js +49 -46
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +11 -12
- package/dist/access-mcp.js +62 -59
- package/dist/access-memory-search-fanout.d.ts +2 -3
- package/dist/{access-namespace-preflight-CpAOrS-9.d.ts → access-namespace-preflight-CLWUoMyW.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -4
- package/dist/access-namespace-preflight.js +49 -46
- package/dist/access-observe-write-surface.d.ts +11 -12
- package/dist/access-observe-write-surface.js +49 -46
- package/dist/access-offline-manifest.d.ts +9 -10
- package/dist/access-offline-manifest.js +15 -15
- package/dist/access-operations-batch.js +54 -51
- package/dist/access-operations.d.ts +17 -18
- package/dist/access-operations.js +59 -56
- package/dist/access-recall-concurrency.d.ts +11 -12
- package/dist/access-recall-concurrency.js +49 -46
- package/dist/access-recall-response.d.ts +11 -12
- package/dist/access-recall-response.js +49 -46
- package/dist/access-recall-surface.d.ts +11 -12
- package/dist/access-recall-surface.js +49 -46
- package/dist/access-schema.d.ts +83 -83
- package/dist/access-schema.js +7 -7
- package/dist/{access-service-Diu61Cfv.d.ts → access-service-CEUE1Isj.d.ts} +66 -66
- package/dist/access-service-helpers.d.ts +11 -12
- package/dist/access-service.d.ts +11 -12
- package/dist/access-service.js +49 -46
- package/dist/access-surface-catalog.d.ts +11 -12
- package/dist/access-surface-catalog.js +53 -48
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-wearables-meetings-surface.d.ts +3 -4
- package/dist/action-confidence.d.ts +1 -2
- package/dist/active-memory-bridge.d.ts +1 -2
- package/dist/active-memory-bridge.js +2 -2
- package/dist/active-recall.d.ts +1 -2
- package/dist/active-recall.js +11 -11
- package/dist/ambient-provenance.d.ts +1 -2
- package/dist/artifact-search.d.ts +1 -2
- package/dist/{auto-sync-2YPITIWN.js → auto-sync-Q6Q2FVSC.js} +9 -9
- package/dist/behavior-learner.d.ts +1 -2
- package/dist/behavior-signals.d.ts +1 -2
- package/dist/bootstrap.d.ts +9 -10
- package/dist/briefing-window.d.ts +2 -3
- package/dist/briefing.d.ts +2 -3
- package/dist/briefing.js +23 -23
- package/dist/buffer-surprise-report.d.ts +1 -2
- package/dist/buffer-turn-helpers.d.ts +1 -2
- package/dist/buffer.d.ts +2 -3
- package/dist/buffer.js +20 -4
- package/dist/bulk-import/index.d.ts +3 -4
- package/dist/calibration.d.ts +1 -2
- package/dist/calibration.js +1 -1
- package/dist/capabilities.d.ts +1 -2
- package/dist/{capsule-merge-SGIVB3WA.js → capsule-merge-SEHERWWP.js} +4 -4
- package/dist/{catalog-9f-vEQLS.d.ts → catalog-D1HgugTA.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -2
- package/dist/causal-consolidation.d.ts +1 -2
- package/dist/causal-consolidation.js +24 -24
- package/dist/causal-trajectory-graph.d.ts +1 -2
- package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
- package/dist/{chunk-NPFUNWNX.js → chunk-23CVL7HS.js} +2 -2
- package/dist/{chunk-PO7NXBG2.js → chunk-2GF27PGH.js} +5 -5
- package/dist/{chunk-MY2BC6UE.js → chunk-2LBAFHOQ.js} +11 -11
- package/dist/{chunk-AZMLH5UT.js → chunk-33MFRY25.js} +2 -2
- package/dist/{chunk-UEBDCMOO.js → chunk-3TSU662L.js} +3 -3
- package/dist/{chunk-CAMNRAJF.js → chunk-4FHRZD5T.js} +2 -2
- package/dist/{chunk-FP7YTTVO.js → chunk-4OFKZAJG.js} +2 -1
- package/dist/chunk-4OFKZAJG.js.map +1 -0
- package/dist/{chunk-S5XOSTYM.js → chunk-4STAANV7.js} +3 -3
- package/dist/{chunk-LKYIOCWL.js → chunk-56IV4J5W.js} +546 -96
- package/dist/chunk-56IV4J5W.js.map +1 -0
- package/dist/{chunk-4F4AQFWL.js → chunk-6CEGSTBD.js} +10 -10
- package/dist/{chunk-JYSN42VN.js → chunk-6QDXA26G.js} +235 -181
- package/dist/chunk-6QDXA26G.js.map +1 -0
- package/dist/{chunk-MDD2RINF.js → chunk-6RUHELWR.js} +3 -3
- package/dist/{chunk-WNXYT4MK.js → chunk-72OIT7KS.js} +4 -4
- package/dist/{chunk-KQAFEZQX.js → chunk-7LCGFUMB.js} +4 -4
- package/dist/{chunk-SNOIKAHM.js → chunk-7UTDHQZ5.js} +3 -3
- package/dist/{chunk-5HK3CJAR.js → chunk-7XOG75AU.js} +3 -3
- package/dist/{chunk-7BDZTALN.js → chunk-AJTG3CP7.js} +12 -2
- package/dist/chunk-AJTG3CP7.js.map +1 -0
- package/dist/{chunk-2LWQSV6A.js → chunk-AL3UYZ5N.js} +3 -2
- package/dist/chunk-AL3UYZ5N.js.map +1 -0
- package/dist/{chunk-UPFNQJC7.js → chunk-CN4VKV3S.js} +2 -2
- package/dist/{chunk-PMVPCZJZ.js → chunk-CTCGHNWN.js} +6 -6
- package/dist/{chunk-EGBDFJ36.js → chunk-DD5JFCWM.js} +2 -2
- package/dist/{chunk-XBGHAAKR.js → chunk-DDX6KIXF.js} +2 -2
- package/dist/{chunk-JIYDRBVZ.js → chunk-DJORULH3.js} +2 -2
- package/dist/{chunk-UENKPWCS.js → chunk-DMEHOEC7.js} +6 -6
- package/dist/{chunk-7KQB4EBS.js → chunk-DUAJKRR2.js} +2 -2
- package/dist/{chunk-XDL5CYZN.js → chunk-EEOUMG3J.js} +2 -1
- package/dist/{chunk-XDL5CYZN.js.map → chunk-EEOUMG3J.js.map} +1 -1
- package/dist/{chunk-SEEJOGQX.js → chunk-EFQCDJZ2.js} +4 -4
- package/dist/{chunk-Q57GOHLF.js → chunk-EGALNSZ4.js} +3 -3
- package/dist/{chunk-KCT36JAW.js → chunk-ESNFSSO4.js} +2 -2
- package/dist/{chunk-XQ3HXAQH.js → chunk-ET2CNMLD.js} +4 -4
- package/dist/{chunk-PU56CXZA.js → chunk-EZSCW4EM.js} +2 -2
- package/dist/{chunk-HMZKGHMD.js → chunk-FESUGFIL.js} +3 -3
- package/dist/{chunk-3A2NJP2U.js → chunk-FKKGCGYL.js} +3 -3
- package/dist/{chunk-BWGCOLEL.js → chunk-FTTJRVB7.js} +2 -2
- package/dist/{chunk-ODU2CNNX.js → chunk-FYWLSFFS.js} +2 -2
- package/dist/{chunk-W2BAGGEW.js → chunk-GEJKYA7D.js} +33 -24
- package/dist/{chunk-W2BAGGEW.js.map → chunk-GEJKYA7D.js.map} +1 -1
- package/dist/chunk-GSKINLAK.js +267 -0
- package/dist/chunk-GSKINLAK.js.map +1 -0
- package/dist/{chunk-3PKAS6VL.js → chunk-GX6FTSYH.js} +2 -2
- package/dist/{chunk-76DIF5KT.js → chunk-H7VDIF2V.js} +2 -2
- package/dist/{chunk-F7XUD3PL.js → chunk-HJXA6ZM7.js} +2 -2
- package/dist/{chunk-4QEYREAV.js → chunk-HNPE66LB.js} +2 -2
- package/dist/{chunk-P36Z4JRA.js → chunk-I5VB44ZK.js} +2 -2
- package/dist/{chunk-EUYWQ7TS.js → chunk-IEZ6CGTW.js} +2 -2
- package/dist/{chunk-OXRRJXPR.js → chunk-IHGMRDEE.js} +275 -1678
- package/dist/chunk-IHGMRDEE.js.map +1 -0
- package/dist/{chunk-5DHKCO52.js → chunk-IVIAHQBR.js} +2 -2
- package/dist/{chunk-TFR3HG4K.js → chunk-J3OND5QT.js} +4 -4
- package/dist/{chunk-UW5NPZJ2.js → chunk-JALOAKSZ.js} +59 -7
- package/dist/chunk-JALOAKSZ.js.map +1 -0
- package/dist/{chunk-5ACCD4L7.js → chunk-JRRQ747T.js} +7 -7
- package/dist/{chunk-V4IDF3EZ.js → chunk-JTWZKNUH.js} +5 -5
- package/dist/chunk-K66OY4EI.js +202 -0
- package/dist/chunk-K66OY4EI.js.map +1 -0
- package/dist/{chunk-XAB6STPO.js → chunk-KODXCHXJ.js} +17 -3
- package/dist/chunk-KODXCHXJ.js.map +1 -0
- package/dist/{chunk-KZIF6XHX.js → chunk-KXIXO76C.js} +28 -15
- package/dist/chunk-KXIXO76C.js.map +1 -0
- package/dist/{chunk-5RWZH6PH.js → chunk-L4X4PJYK.js} +2 -2
- package/dist/{chunk-UTQUEHC7.js → chunk-LUDBXTBJ.js} +8 -8
- package/dist/{chunk-XNWXSGHS.js → chunk-MAH64N55.js} +28 -10
- package/dist/chunk-MAH64N55.js.map +1 -0
- package/dist/{chunk-LDKPDODJ.js → chunk-ME35HVDJ.js} +2 -2
- package/dist/{chunk-DPCXDG7G.js → chunk-MJRGVXPQ.js} +2 -2
- package/dist/{chunk-773TRRGT.js → chunk-MJUCDM3C.js} +2 -2
- package/dist/{chunk-T6ILXUAH.js → chunk-MN5NOOI7.js} +2 -2
- package/dist/{chunk-AHPIFKNG.js → chunk-N4F7ZSSG.js} +2 -2
- package/dist/{chunk-JOZUBF4A.js → chunk-NACLNNFQ.js} +2 -2
- package/dist/{chunk-LC2BDILZ.js → chunk-NBP4EX5N.js} +2 -2
- package/dist/{chunk-ZVPVTPGI.js → chunk-NNZFPYYX.js} +4 -4
- package/dist/{chunk-DA7ITC5Z.js → chunk-O57GM3FR.js} +2 -2
- package/dist/{chunk-7VZFRUQU.js → chunk-O7ERGZDA.js} +5 -5
- package/dist/{chunk-3SZD4CYO.js → chunk-OAJMQKQR.js} +3 -3
- package/dist/{chunk-HSZMX3ZJ.js → chunk-ODW5GDFE.js} +2 -2
- package/dist/{chunk-7WOWGRAU.js → chunk-PEBH5DCK.js} +10 -7
- package/dist/{chunk-7WOWGRAU.js.map → chunk-PEBH5DCK.js.map} +1 -1
- package/dist/{chunk-J2WC5LF4.js → chunk-QBC33MPY.js} +2 -1
- package/dist/{chunk-T7XP6IZE.js → chunk-QCRJMU5V.js} +2 -2
- package/dist/chunk-QJCWK2A7.js +1466 -0
- package/dist/chunk-QJCWK2A7.js.map +1 -0
- package/dist/{chunk-YEUXERJ6.js → chunk-RDGKVH6T.js} +7 -3
- package/dist/{chunk-YEUXERJ6.js.map → chunk-RDGKVH6T.js.map} +1 -1
- package/dist/{chunk-OA2O2GJ4.js → chunk-RZ3IZIJG.js} +3 -3
- package/dist/{chunk-UL4MKZHI.js → chunk-SN4JXNLL.js} +2 -2
- package/dist/chunk-TB2MJRI6.js +866 -0
- package/dist/chunk-TB2MJRI6.js.map +1 -0
- package/dist/{chunk-7PHI6GUI.js → chunk-TEZ2HTC7.js} +42 -2
- package/dist/chunk-TEZ2HTC7.js.map +1 -0
- package/dist/{chunk-CPA5NBHN.js → chunk-TNGH4ZYI.js} +2 -2
- package/dist/{chunk-F3NVYTTA.js → chunk-TNXNECAN.js} +6 -6
- package/dist/{chunk-BEC4YBNA.js → chunk-TVW4C7PV.js} +2 -2
- package/dist/{chunk-UFKPQBXH.js → chunk-U62OK7BB.js} +2 -2
- package/dist/{chunk-AX7UXCHJ.js → chunk-UYA36DQ7.js} +2 -1
- package/dist/chunk-UYA36DQ7.js.map +1 -0
- package/dist/{chunk-DEACDKE3.js → chunk-VCKWULAK.js} +112 -87
- package/dist/chunk-VCKWULAK.js.map +1 -0
- package/dist/chunk-VOSWUO3K.js +100 -0
- package/dist/chunk-VOSWUO3K.js.map +1 -0
- package/dist/{chunk-TUHBYJXL.js → chunk-VQ4AMTGZ.js} +1 -1
- package/dist/{chunk-3BCULS4U.js → chunk-VQNRICAQ.js} +145 -507
- package/dist/chunk-VQNRICAQ.js.map +1 -0
- package/dist/{chunk-H2YSH3DG.js → chunk-WKAXBXVA.js} +2 -2
- package/dist/{chunk-HRHO3ZNG.js → chunk-WKJFIMVN.js} +2 -2
- package/dist/{chunk-SXIMQLGV.js → chunk-WVGXCBOC.js} +2 -2
- package/dist/{chunk-CRML27CO.js → chunk-X5YYSAZX.js} +4 -4
- package/dist/{chunk-FZEEWOI2.js → chunk-XJJYSX6F.js} +2 -2
- package/dist/{chunk-U7EW2W4W.js → chunk-XKNHFDTT.js} +26 -6
- package/dist/chunk-XKNHFDTT.js.map +1 -0
- package/dist/{chunk-UG6VXIOK.js → chunk-XSTNGNJP.js} +2 -2
- package/dist/{chunk-YDPAE2RD.js → chunk-YFLLGRXO.js} +2 -2
- package/dist/{chunk-LPNCR4QK.js → chunk-YXFCALVT.js} +12 -12
- package/dist/{chunk-Q4WONDMJ.js → chunk-YYGZJPOK.js} +2 -2
- package/dist/{chunk-GTO56JY5.js → chunk-ZJPM7GZ3.js} +2 -2
- package/dist/{chunk-LOXHYCVS.js → chunk-ZW4VXELZ.js} +2 -2
- package/dist/{cli-O3F-ht3i.d.ts → cli-BEkm2MEf.d.ts} +5 -5
- package/dist/cli.d.ts +13 -14
- package/dist/cli.js +90 -85
- package/dist/coding/export-okf-codegraph.d.ts +56 -0
- package/dist/coding/export-okf-codegraph.js +526 -0
- package/dist/coding/export-okf-codegraph.js.map +1 -0
- package/dist/coding/pre-action-gate.d.ts +1 -2
- package/dist/compounding/engine.d.ts +2 -3
- package/dist/compounding/engine.js +24 -24
- package/dist/compounding/preference-consolidator.d.ts +1 -2
- package/dist/compression-optimizer.d.ts +1 -2
- package/dist/config.d.ts +1 -2
- package/dist/config.js +11 -11
- package/dist/connectors/codex-materialize-runner.d.ts +1 -2
- package/dist/connectors/codex-materialize-runner.js +23 -23
- package/dist/connectors/codex-materialize.d.ts +1 -2
- package/dist/connectors/index.d.ts +1 -2
- package/dist/connectors/index.js +23 -23
- package/dist/consolidation-provenance-check.d.ts +2 -3
- package/dist/consolidation-provenance-check.js +4 -4
- package/dist/consolidation-undo.d.ts +2 -3
- package/dist/consolidation-undo.js +3 -3
- package/dist/contradiction/index.d.ts +3 -4
- package/dist/contradiction/index.js +9 -9
- package/dist/{contradiction-scan-AKUWPX5N.js → contradiction-scan-NOYMFG66.js} +3 -3
- package/dist/converge-config.d.ts +1 -2
- package/dist/convergence-refresh.d.ts +2 -3
- package/dist/convergence-refresh.js +25 -25
- package/dist/conversation-index/backend.d.ts +1 -2
- package/dist/conversation-index/backend.js +2 -2
- package/dist/conversation-index/chunker.d.ts +1 -2
- package/dist/conversation-index/faiss-adapter.d.ts +1 -2
- package/dist/conversation-index/indexer.d.ts +1 -2
- package/dist/conversation-index/search.d.ts +1 -2
- package/dist/corpus-watermark.d.ts +1 -2
- package/dist/corpus-watermark.js +25 -25
- package/dist/cross-lingual-recall.d.ts +1 -2
- package/dist/day-summary.d.ts +1 -2
- package/dist/delinearize.d.ts +1 -2
- package/dist/dependency-propagation-config.d.ts +1 -2
- package/dist/{dependency-propagation-delivery-CL6RWXTA.d.ts → dependency-propagation-delivery-BCpeo14F.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -2
- package/dist/direct-answer.d.ts +1 -2
- package/dist/embedding-fallback.d.ts +1 -2
- package/dist/enrichment/index.d.ts +1 -2
- package/dist/entity-origin-fields.d.ts +1 -2
- package/dist/entity-retrieval.d.ts +2 -3
- package/dist/entity-retrieval.js +23 -23
- package/dist/entity-schema.d.ts +1 -2
- package/dist/episodic-context.d.ts +1 -2
- package/dist/eval-trajectory-contracts.d.ts +1 -2
- package/dist/eval-trajectory-store.d.ts +1 -2
- package/dist/eval-trajectory.d.ts +1 -2
- package/dist/explicit-capture.d.ts +9 -10
- package/dist/explicit-capture.js +11 -11
- package/dist/external-wiki-access.d.ts +11 -12
- package/dist/external-wiki-access.js +50 -47
- package/dist/external-wiki-collection-registration.d.ts +1 -2
- package/dist/external-wiki-collection.d.ts +1 -2
- package/dist/external-wiki-mcp-tools.d.ts +11 -12
- package/dist/extraction-error-classification.d.ts +1 -2
- package/dist/extraction-faithfulness.d.ts +1 -2
- package/dist/extraction-faithfulness.js +2 -2
- package/dist/extraction-judge-telemetry.d.ts +1 -2
- package/dist/extraction-judge-training.d.ts +1 -2
- package/dist/extraction-judge.d.ts +1 -2
- package/dist/extraction-judge.js +2 -2
- package/dist/extraction-liveness.d.ts +1 -2
- package/dist/extraction-normalization.d.ts +1 -2
- package/dist/extraction-prompt.d.ts +1 -2
- package/dist/extraction-source-grounding-rules.d.ts +1 -2
- package/dist/extraction-source-grounding.d.ts +1 -2
- package/dist/extraction.d.ts +1 -2
- package/dist/extraction.js +32 -29
- package/dist/fallback-llm.d.ts +7 -2
- package/dist/fallback-llm.js +1 -1
- package/dist/{first-start-migration-4NETATFF.js → first-start-migration-KHIMCBIC.js} +3 -3
- package/dist/graph-dashboard-diff.d.ts +1 -2
- package/dist/graph-dashboard-key.d.ts +1 -2
- package/dist/graph-dashboard-parser.d.ts +1 -2
- package/dist/graph-edge-reinforcement.d.ts +1 -2
- package/dist/graph-path-reconstruction.d.ts +1 -2
- package/dist/graph-path-scoring.d.ts +1 -2
- package/dist/graph-snapshot.d.ts +1 -2
- package/dist/graph.d.ts +1 -2
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/importance.d.ts +1 -2
- package/dist/importers/index.d.ts +1 -2
- package/dist/in-flight-reads.d.ts +1 -2
- package/dist/{index-C7Xep6S9.d.ts → index-D_pyMUaP.d.ts} +2 -2
- package/dist/index.d.ts +929 -700
- package/dist/index.js +167 -132
- package/dist/intent.d.ts +1 -2
- package/dist/lcm/engine.d.ts +1 -2
- package/dist/lcm/index.d.ts +1 -2
- package/dist/lcm/tools.d.ts +1 -2
- package/dist/lifecycle.d.ts +1 -2
- package/dist/live-connectors-runner.d.ts +1 -2
- package/dist/local-llm.d.ts +1 -2
- package/dist/local-model-endpoint.d.ts +1 -2
- package/dist/location/index.d.ts +315 -6
- package/dist/location/index.js +151 -19
- package/dist/maintenance/memory-governance.d.ts +1 -2
- package/dist/maintenance/memory-governance.js +23 -23
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +23 -23
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -3
- package/dist/maintenance/rebuild-memory-projection.js +24 -24
- package/dist/{maintenance-CJ-xqFp0.d.ts → maintenance-DDUX9d6D.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +11 -12
- package/dist/mcp-read-only-tools.js +1 -1
- package/dist/memory-action-policy.d.ts +1 -2
- package/dist/memory-cache.d.ts +1 -2
- package/dist/memory-controller.d.ts +1 -2
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -2
- package/dist/memory-projection-mutations.js +3 -3
- package/dist/memory-projection-store.d.ts +1 -2
- package/dist/memory-projection-store.js +1 -1
- package/dist/memory-provenance.d.ts +1 -2
- package/dist/memory-snapshot.d.ts +1 -2
- package/dist/memory-subject-cli.d.ts +11 -12
- package/dist/memory-subject.d.ts +11 -12
- package/dist/memory-subject.js +4 -4
- package/dist/memory-worth-outcomes.d.ts +2 -3
- package/dist/models-json.d.ts +1 -2
- package/dist/namespaces/migrate.d.ts +3 -4
- package/dist/namespaces/migrate.js +24 -24
- package/dist/namespaces/principal.d.ts +1 -2
- package/dist/namespaces/search.d.ts +1 -2
- package/dist/namespaces/search.js +5 -5
- package/dist/namespaces/storage.d.ts +3 -4
- package/dist/namespaces/storage.js +23 -23
- package/dist/native-knowledge.d.ts +1 -2
- package/dist/offline-sync-file-io.js +3 -3
- package/dist/offline-sync-impression-drain.d.ts +1 -2
- package/dist/offline-sync-impression-drain.js +9 -9
- package/dist/offline-sync.js +4 -4
- package/dist/operator-doctor-corpus.d.ts +1 -2
- package/dist/operator-doctor-corpus.js +26 -26
- package/dist/operator-doctor-replica.d.ts +1 -2
- package/dist/operator-toolkit.d.ts +3 -4
- package/dist/operator-toolkit.js +42 -42
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -3
- package/dist/orchestration/maintenance.d.ts +4 -5
- package/dist/orchestration/maintenance.js +37 -36
- package/dist/{orchestrator-BsntWxLy.d.ts → orchestrator-3F4jihCo.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -10
- package/dist/orchestrator.js +111 -106
- package/dist/page-versioning.js +3 -3
- package/dist/patterns-cli.d.ts +1 -2
- package/dist/{pipeline-CVoysPm2.d.ts → pipeline-CB1dj6Uh.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -2
- package/dist/proactive-contention.d.ts +1 -2
- package/dist/provenance.d.ts +1 -2
- package/dist/{public-http-CuOxlTC2.d.ts → public-http-34-JIAGQ.d.ts} +1 -1
- package/dist/{purge-GB7PZHT2.js → purge-OP6BEDFY.js} +2 -2
- package/dist/{qmd-DWMAGA5l.d.ts → qmd-edLLZXc5.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -3
- package/dist/qmd-recall-cache.d.ts +1 -2
- package/dist/qmd.d.ts +2 -3
- package/dist/recall-concurrency-config.d.ts +1 -2
- package/dist/recall-disclosure-escalation.d.ts +1 -2
- package/dist/recall-explain-renderer.d.ts +1 -2
- package/dist/recall-memory-map.d.ts +1 -2
- package/dist/recall-planner-llm.d.ts +1 -2
- package/dist/recall-planner-llm.js +1 -1
- package/dist/recall-state.d.ts +1 -2
- package/dist/recall-tag-filter.d.ts +1 -2
- package/dist/recall-timings.d.ts +1 -2
- package/dist/recall-xray-cli.d.ts +1 -2
- package/dist/recall-xray-renderer.d.ts +1 -2
- package/dist/recall-xray.d.ts +1 -2
- package/dist/reconcile/cursor.d.ts +1 -2
- package/dist/reconcile/manifest.d.ts +1 -2
- package/dist/reconcile/manifest.js +4 -4
- package/dist/reconcile/plan.d.ts +1 -2
- package/dist/replay/normalizers/chatgpt.d.ts +1 -2
- package/dist/replay/normalizers/claude.d.ts +1 -2
- package/dist/replay/normalizers/openclaw.d.ts +1 -2
- package/dist/replay/normalizers/shared.d.ts +1 -2
- package/dist/replay/runner.d.ts +1 -2
- package/dist/replay/types.d.ts +1 -2
- package/dist/replica-divergence.d.ts +1 -2
- package/dist/replica-peers-config.d.ts +1 -2
- package/dist/{resolution-XWBPKYFB.js → resolution-4DLI3IOR.js} +10 -10
- package/dist/resolve-auth-token.d.ts +1 -2
- package/dist/resume-bundles.js +12 -12
- package/dist/retrieval-agents.d.ts +2 -3
- package/dist/retrieval-tiers.d.ts +1 -2
- package/dist/routing/engine.d.ts +1 -2
- package/dist/routing/store.d.ts +1 -2
- package/dist/salvage-envelope.d.ts +1 -2
- package/dist/salvage-envelope.js +6 -6
- package/dist/schemas.d.ts +639 -174
- package/dist/schemas.js +3 -1
- package/dist/{scope-profiles-CPWkW_dI.d.ts → scope-profiles-BF2lu81V.d.ts} +1 -1
- package/dist/search/document-scanner.js +1 -1
- package/dist/search/embed-helper.d.ts +1 -2
- package/dist/search/factory.d.ts +1 -2
- package/dist/search/factory.js +4 -4
- package/dist/search/index.d.ts +1 -2
- package/dist/search/index.js +4 -4
- package/dist/search/lancedb-backend.d.ts +1 -2
- package/dist/search/lancedb-backend.js +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -2
- package/dist/search/meilisearch-backend.js +1 -1
- package/dist/search/noop-backend.d.ts +1 -2
- package/dist/search/orama-backend.d.ts +1 -2
- package/dist/search/orama-backend.js +1 -1
- package/dist/search/port.d.ts +1 -2
- package/dist/search/remote-backend.d.ts +1 -2
- package/dist/secure-store/index.js +3 -3
- package/dist/{semantic-consolidation-CNFVBXFc.d.ts → semantic-consolidation-5OuWXBRt.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -3
- package/dist/semantic-consolidation.js +24 -24
- package/dist/semantic-rule-promotion.js +23 -23
- package/dist/semantic-rule-verifier.d.ts +1 -2
- package/dist/semantic-rule-verifier.js +23 -23
- package/dist/{service-Bb-JIdQ0.d.ts → service-CrqEhLXD.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -2
- package/dist/session-observer-state.d.ts +1 -2
- package/dist/shared-context/manager.d.ts +7 -8
- package/dist/signal.d.ts +1 -2
- package/dist/source-agent-qualifier.d.ts +1 -2
- package/dist/source-agent-qualifier.js +30 -27
- package/dist/standup/build.d.ts +16 -0
- package/dist/standup/build.js +17 -0
- package/dist/standup/build.js.map +1 -0
- package/dist/{storage-CukrlNKk.d.ts → storage-BQn-xnxm.d.ts} +1 -1
- package/dist/storage.d.ts +2 -3
- package/dist/storage.js +22 -22
- package/dist/subject-config.d.ts +1 -2
- package/dist/subject-config.js +5 -5
- package/dist/summarizer.d.ts +1 -2
- package/dist/summarizer.js +2 -2
- package/dist/summary-snapshot.d.ts +1 -2
- package/dist/support-passport/index.d.ts +16 -17
- package/dist/support-passport/index.js +52 -49
- package/dist/temporal-supersession.d.ts +2 -3
- package/dist/temporal-timeline-recall.d.ts +1 -2
- package/dist/temporal-validity.d.ts +1 -2
- package/dist/threading.d.ts +1 -2
- package/dist/tier-migration.d.ts +2 -3
- package/dist/tier-routing.d.ts +1 -2
- package/dist/tier-routing.js +2 -2
- package/dist/{tier-stats-4B5IJ3NE.js → tier-stats-2TOW3QNL.js} +3 -3
- package/dist/topics.d.ts +1 -2
- package/dist/transcript.d.ts +1 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +5 -5
- package/dist/transfer/export-okf.d.ts +39 -0
- package/dist/transfer/export-okf.js +112 -0
- package/dist/transfer/export-okf.js.map +1 -0
- package/dist/transfer/types.d.ts +78 -78
- package/dist/trust-score-stage.d.ts +1 -2
- package/dist/trust-score.d.ts +1 -2
- package/dist/{types-djxQlxJ7.d.ts → types-BRpcNjHZ.d.ts} +117 -2
- package/dist/types.d.ts +1 -2
- package/dist/utility-runtime.d.ts +1 -2
- package/dist/verified-recall.js +23 -23
- package/dist/who-knows-cli.d.ts +11 -12
- package/dist/who-knows-cli.js +24 -24
- package/dist/who-knows.d.ts +11 -12
- package/dist/who-knows.js +23 -23
- package/dist/write-envelope.d.ts +1 -2
- package/dist/write-envelope.js +5 -5
- package/package.json +34 -3
- package/src/access-admin-ops-surface.ts +6 -1
- package/src/access-boundary.ts +1 -0
- package/src/access-http.ts +3 -1
- package/src/access-mcp-output-schemas.ts +1 -0
- package/src/access-mcp.ts +3 -3
- package/src/access-operations.ts +1 -0
- package/src/access-service-offline-file-content.test.ts +63 -0
- package/src/access-surface-catalog.ts +2 -0
- package/src/activity/config.test.ts +1 -0
- package/src/activity/config.ts +21 -1
- package/src/activity/index.ts +1 -0
- package/src/activity/timeline/build.ts +279 -0
- package/src/activity/timeline/categories.ts +111 -0
- package/src/activity/timeline/classify.ts +110 -0
- package/src/activity/timeline/corrections.ts +145 -0
- package/src/activity/timeline/index.ts +6 -0
- package/src/activity/timeline/timeline.test.ts +277 -0
- package/src/activity/timeline/types.ts +106 -0
- package/src/activity/types.ts +6 -0
- package/src/cli/okf-commands.ts +45 -0
- package/src/cli.ts +2 -2
- package/src/coding/export-okf-codegraph.test.ts +381 -0
- package/src/coding/export-okf-codegraph.ts +565 -0
- package/src/config.test.ts +1 -0
- package/src/extraction-prompt-safety.test.ts +14 -2
- package/src/extraction.ts +21 -1
- package/src/fallback-llm.test.ts +134 -0
- package/src/fallback-llm.ts +77 -5
- package/src/location/access-operations.ts +17 -8
- package/src/location/backfill.ts +137 -0
- package/src/location/config.test.ts +3 -0
- package/src/location/config.ts +46 -2
- package/src/location/http-glue.ts +1 -1
- package/src/location/index.ts +3 -0
- package/src/location/intervals.ts +1 -0
- package/src/location/matching.test.ts +65 -0
- package/src/location/matching.ts +354 -0
- package/src/location/mcp-tools.ts +2 -1
- package/src/location/surfaces.test.ts +15 -2
- package/src/location/surfaces.ts +95 -18
- package/src/location/tagging.test.ts +119 -0
- package/src/location/tagging.ts +277 -0
- package/src/location/types.ts +23 -1
- package/src/mcp-read-only-tools.ts +1 -0
- package/src/memory-projection-store.ts +3 -1
- package/src/okf/cli.ts +18 -5
- package/src/okf/config.ts +5 -0
- package/src/okf/index-files.test.ts +60 -0
- package/src/okf/index-files.ts +114 -0
- package/src/okf/render.ts +133 -0
- package/src/okf/type-mapping.test.ts +3 -0
- package/src/okf/type-mapping.ts +2 -0
- package/src/orchestration/extraction-run.ts +2 -1
- package/src/orchestration/generic-recall-paths.ts +4 -3
- package/src/schemas.ts +17 -1
- package/src/standup/access-operations.ts +14 -0
- package/src/standup/build.test.ts +34 -0
- package/src/standup/build.ts +115 -0
- package/src/standup/http-glue.ts +15 -0
- package/src/standup/mcp-tools.ts +16 -0
- package/src/support-passport/card-projection.ts +1 -0
- package/src/support-passport/card-service-commit-forwarding.test.ts +1 -0
- package/src/support-passport/card-service.test.ts +75 -1
- package/src/support-passport/card-service.ts +6 -3
- package/src/support-passport/card-state.ts +5 -1
- package/src/support-passport/offline-sync-guard.ts +14 -1
- package/src/transfer/export-okf.test.ts +164 -0
- package/src/transfer/export-okf.ts +286 -0
- package/dist/chunk-2LWQSV6A.js.map +0 -1
- package/dist/chunk-3BCULS4U.js.map +0 -1
- package/dist/chunk-7BDZTALN.js.map +0 -1
- package/dist/chunk-7PHI6GUI.js.map +0 -1
- package/dist/chunk-AX7UXCHJ.js.map +0 -1
- package/dist/chunk-DEACDKE3.js.map +0 -1
- package/dist/chunk-FP7YTTVO.js.map +0 -1
- package/dist/chunk-JYSN42VN.js.map +0 -1
- package/dist/chunk-KZIF6XHX.js.map +0 -1
- package/dist/chunk-LKYIOCWL.js.map +0 -1
- package/dist/chunk-OXRRJXPR.js.map +0 -1
- package/dist/chunk-U7EW2W4W.js.map +0 -1
- package/dist/chunk-UW5NPZJ2.js.map +0 -1
- package/dist/chunk-XAB6STPO.js.map +0 -1
- package/dist/chunk-XNWXSGHS.js.map +0 -1
- package/dist/types-CM86alG1.d.ts +0 -89
- /package/dist/{auto-sync-2YPITIWN.js.map → auto-sync-Q6Q2FVSC.js.map} +0 -0
- /package/dist/{capsule-merge-SGIVB3WA.js.map → capsule-merge-SEHERWWP.js.map} +0 -0
- /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
- /package/dist/{chunk-NPFUNWNX.js.map → chunk-23CVL7HS.js.map} +0 -0
- /package/dist/{chunk-PO7NXBG2.js.map → chunk-2GF27PGH.js.map} +0 -0
- /package/dist/{chunk-MY2BC6UE.js.map → chunk-2LBAFHOQ.js.map} +0 -0
- /package/dist/{chunk-AZMLH5UT.js.map → chunk-33MFRY25.js.map} +0 -0
- /package/dist/{chunk-UEBDCMOO.js.map → chunk-3TSU662L.js.map} +0 -0
- /package/dist/{chunk-CAMNRAJF.js.map → chunk-4FHRZD5T.js.map} +0 -0
- /package/dist/{chunk-S5XOSTYM.js.map → chunk-4STAANV7.js.map} +0 -0
- /package/dist/{chunk-4F4AQFWL.js.map → chunk-6CEGSTBD.js.map} +0 -0
- /package/dist/{chunk-MDD2RINF.js.map → chunk-6RUHELWR.js.map} +0 -0
- /package/dist/{chunk-WNXYT4MK.js.map → chunk-72OIT7KS.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-7LCGFUMB.js.map} +0 -0
- /package/dist/{chunk-SNOIKAHM.js.map → chunk-7UTDHQZ5.js.map} +0 -0
- /package/dist/{chunk-5HK3CJAR.js.map → chunk-7XOG75AU.js.map} +0 -0
- /package/dist/{chunk-UPFNQJC7.js.map → chunk-CN4VKV3S.js.map} +0 -0
- /package/dist/{chunk-PMVPCZJZ.js.map → chunk-CTCGHNWN.js.map} +0 -0
- /package/dist/{chunk-EGBDFJ36.js.map → chunk-DD5JFCWM.js.map} +0 -0
- /package/dist/{chunk-XBGHAAKR.js.map → chunk-DDX6KIXF.js.map} +0 -0
- /package/dist/{chunk-JIYDRBVZ.js.map → chunk-DJORULH3.js.map} +0 -0
- /package/dist/{chunk-UENKPWCS.js.map → chunk-DMEHOEC7.js.map} +0 -0
- /package/dist/{chunk-7KQB4EBS.js.map → chunk-DUAJKRR2.js.map} +0 -0
- /package/dist/{chunk-SEEJOGQX.js.map → chunk-EFQCDJZ2.js.map} +0 -0
- /package/dist/{chunk-Q57GOHLF.js.map → chunk-EGALNSZ4.js.map} +0 -0
- /package/dist/{chunk-KCT36JAW.js.map → chunk-ESNFSSO4.js.map} +0 -0
- /package/dist/{chunk-XQ3HXAQH.js.map → chunk-ET2CNMLD.js.map} +0 -0
- /package/dist/{chunk-PU56CXZA.js.map → chunk-EZSCW4EM.js.map} +0 -0
- /package/dist/{chunk-HMZKGHMD.js.map → chunk-FESUGFIL.js.map} +0 -0
- /package/dist/{chunk-3A2NJP2U.js.map → chunk-FKKGCGYL.js.map} +0 -0
- /package/dist/{chunk-BWGCOLEL.js.map → chunk-FTTJRVB7.js.map} +0 -0
- /package/dist/{chunk-ODU2CNNX.js.map → chunk-FYWLSFFS.js.map} +0 -0
- /package/dist/{chunk-3PKAS6VL.js.map → chunk-GX6FTSYH.js.map} +0 -0
- /package/dist/{chunk-76DIF5KT.js.map → chunk-H7VDIF2V.js.map} +0 -0
- /package/dist/{chunk-F7XUD3PL.js.map → chunk-HJXA6ZM7.js.map} +0 -0
- /package/dist/{chunk-4QEYREAV.js.map → chunk-HNPE66LB.js.map} +0 -0
- /package/dist/{chunk-P36Z4JRA.js.map → chunk-I5VB44ZK.js.map} +0 -0
- /package/dist/{chunk-EUYWQ7TS.js.map → chunk-IEZ6CGTW.js.map} +0 -0
- /package/dist/{chunk-5DHKCO52.js.map → chunk-IVIAHQBR.js.map} +0 -0
- /package/dist/{chunk-TFR3HG4K.js.map → chunk-J3OND5QT.js.map} +0 -0
- /package/dist/{chunk-5ACCD4L7.js.map → chunk-JRRQ747T.js.map} +0 -0
- /package/dist/{chunk-V4IDF3EZ.js.map → chunk-JTWZKNUH.js.map} +0 -0
- /package/dist/{chunk-5RWZH6PH.js.map → chunk-L4X4PJYK.js.map} +0 -0
- /package/dist/{chunk-UTQUEHC7.js.map → chunk-LUDBXTBJ.js.map} +0 -0
- /package/dist/{chunk-LDKPDODJ.js.map → chunk-ME35HVDJ.js.map} +0 -0
- /package/dist/{chunk-DPCXDG7G.js.map → chunk-MJRGVXPQ.js.map} +0 -0
- /package/dist/{chunk-773TRRGT.js.map → chunk-MJUCDM3C.js.map} +0 -0
- /package/dist/{chunk-T6ILXUAH.js.map → chunk-MN5NOOI7.js.map} +0 -0
- /package/dist/{chunk-AHPIFKNG.js.map → chunk-N4F7ZSSG.js.map} +0 -0
- /package/dist/{chunk-JOZUBF4A.js.map → chunk-NACLNNFQ.js.map} +0 -0
- /package/dist/{chunk-LC2BDILZ.js.map → chunk-NBP4EX5N.js.map} +0 -0
- /package/dist/{chunk-ZVPVTPGI.js.map → chunk-NNZFPYYX.js.map} +0 -0
- /package/dist/{chunk-DA7ITC5Z.js.map → chunk-O57GM3FR.js.map} +0 -0
- /package/dist/{chunk-7VZFRUQU.js.map → chunk-O7ERGZDA.js.map} +0 -0
- /package/dist/{chunk-3SZD4CYO.js.map → chunk-OAJMQKQR.js.map} +0 -0
- /package/dist/{chunk-HSZMX3ZJ.js.map → chunk-ODW5GDFE.js.map} +0 -0
- /package/dist/{chunk-J2WC5LF4.js.map → chunk-QBC33MPY.js.map} +0 -0
- /package/dist/{chunk-T7XP6IZE.js.map → chunk-QCRJMU5V.js.map} +0 -0
- /package/dist/{chunk-OA2O2GJ4.js.map → chunk-RZ3IZIJG.js.map} +0 -0
- /package/dist/{chunk-UL4MKZHI.js.map → chunk-SN4JXNLL.js.map} +0 -0
- /package/dist/{chunk-CPA5NBHN.js.map → chunk-TNGH4ZYI.js.map} +0 -0
- /package/dist/{chunk-F3NVYTTA.js.map → chunk-TNXNECAN.js.map} +0 -0
- /package/dist/{chunk-BEC4YBNA.js.map → chunk-TVW4C7PV.js.map} +0 -0
- /package/dist/{chunk-UFKPQBXH.js.map → chunk-U62OK7BB.js.map} +0 -0
- /package/dist/{chunk-TUHBYJXL.js.map → chunk-VQ4AMTGZ.js.map} +0 -0
- /package/dist/{chunk-H2YSH3DG.js.map → chunk-WKAXBXVA.js.map} +0 -0
- /package/dist/{chunk-HRHO3ZNG.js.map → chunk-WKJFIMVN.js.map} +0 -0
- /package/dist/{chunk-SXIMQLGV.js.map → chunk-WVGXCBOC.js.map} +0 -0
- /package/dist/{chunk-CRML27CO.js.map → chunk-X5YYSAZX.js.map} +0 -0
- /package/dist/{chunk-FZEEWOI2.js.map → chunk-XJJYSX6F.js.map} +0 -0
- /package/dist/{chunk-UG6VXIOK.js.map → chunk-XSTNGNJP.js.map} +0 -0
- /package/dist/{chunk-YDPAE2RD.js.map → chunk-YFLLGRXO.js.map} +0 -0
- /package/dist/{chunk-LPNCR4QK.js.map → chunk-YXFCALVT.js.map} +0 -0
- /package/dist/{chunk-Q4WONDMJ.js.map → chunk-YYGZJPOK.js.map} +0 -0
- /package/dist/{chunk-GTO56JY5.js.map → chunk-ZJPM7GZ3.js.map} +0 -0
- /package/dist/{chunk-LOXHYCVS.js.map → chunk-ZW4VXELZ.js.map} +0 -0
- /package/dist/{contradiction-scan-AKUWPX5N.js.map → contradiction-scan-NOYMFG66.js.map} +0 -0
- /package/dist/{first-start-migration-4NETATFF.js.map → first-start-migration-KHIMCBIC.js.map} +0 -0
- /package/dist/{purge-GB7PZHT2.js.map → purge-OP6BEDFY.js.map} +0 -0
- /package/dist/{resolution-XWBPKYFB.js.map → resolution-4DLI3IOR.js.map} +0 -0
- /package/dist/{tier-stats-4B5IJ3NE.js.map → tier-stats-2TOW3QNL.js.map} +0 -0
package/src/fallback-llm.test.ts
CHANGED
|
@@ -12,6 +12,70 @@ import {
|
|
|
12
12
|
clearSecretCache,
|
|
13
13
|
} from "./resolve-provider-secret.js";
|
|
14
14
|
|
|
15
|
+
test("fallback llm sends native JSON schema to chat completions", { concurrency: false }, async () => {
|
|
16
|
+
clearModelsJsonCache();
|
|
17
|
+
clearSecretCache();
|
|
18
|
+
const llm = new FallbackLlmClient({
|
|
19
|
+
agents: { defaults: { model: { primary: "openai/test-model" } } },
|
|
20
|
+
models: { providers: { openai: { baseUrl: "https://openai.example/v1", api: "openai-completions", apiKey: "key", models: [] } } },
|
|
21
|
+
});
|
|
22
|
+
const originalFetch = globalThis.fetch;
|
|
23
|
+
let captured: Record<string, unknown> = {};
|
|
24
|
+
globalThis.fetch = (async (_url, init) => {
|
|
25
|
+
captured = JSON.parse(String(init?.body ?? "{}")) as Record<string, unknown>;
|
|
26
|
+
return new Response(JSON.stringify({ choices: [{ message: { content: '{"ok":true}' } }] }), { status: 200 });
|
|
27
|
+
}) as typeof fetch;
|
|
28
|
+
try {
|
|
29
|
+
await llm.chatCompletion([{ role: "user", content: "test" }], {
|
|
30
|
+
jsonSchema: { name: "test_result", schema: { type: "object", properties: { ok: { type: "boolean" } } }, strict: false },
|
|
31
|
+
});
|
|
32
|
+
assert.deepEqual(captured.response_format, {
|
|
33
|
+
type: "json_schema",
|
|
34
|
+
json_schema: {
|
|
35
|
+
name: "test_result",
|
|
36
|
+
strict: false,
|
|
37
|
+
schema: { type: "object", properties: { ok: { type: "boolean" } } },
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
} finally {
|
|
41
|
+
globalThis.fetch = originalFetch;
|
|
42
|
+
clearModelsJsonCache();
|
|
43
|
+
clearSecretCache();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("fallback llm retries without native schema when the provider rejects it", { concurrency: false }, async () => {
|
|
48
|
+
clearModelsJsonCache();
|
|
49
|
+
clearSecretCache();
|
|
50
|
+
const llm = new FallbackLlmClient({
|
|
51
|
+
agents: { defaults: { model: { primary: "openai/test-model" } } },
|
|
52
|
+
models: { providers: { openai: { baseUrl: "https://openai.example/v1", api: "openai-completions", apiKey: "key", models: [] } } },
|
|
53
|
+
});
|
|
54
|
+
const originalFetch = globalThis.fetch;
|
|
55
|
+
const bodies: Array<Record<string, unknown>> = [];
|
|
56
|
+
globalThis.fetch = (async (_url, init) => {
|
|
57
|
+
const body = JSON.parse(String(init?.body ?? "{}")) as Record<string, unknown>;
|
|
58
|
+
bodies.push(body);
|
|
59
|
+
if (body.response_format) {
|
|
60
|
+
return new Response('response_format json_schema is unsupported', { status: 400 });
|
|
61
|
+
}
|
|
62
|
+
return new Response(JSON.stringify({ choices: [{ message: { content: '{"ok":true}' } }] }), { status: 200 });
|
|
63
|
+
}) as typeof fetch;
|
|
64
|
+
try {
|
|
65
|
+
const response = await llm.chatCompletion([{ role: "user", content: "test" }], {
|
|
66
|
+
jsonSchema: { name: "test_result", schema: { type: "object" } },
|
|
67
|
+
});
|
|
68
|
+
assert.equal(response?.content, '{"ok":true}');
|
|
69
|
+
assert.equal(bodies.length, 2);
|
|
70
|
+
assert.ok(bodies[0]?.response_format);
|
|
71
|
+
assert.equal(bodies[1]?.response_format, undefined);
|
|
72
|
+
} finally {
|
|
73
|
+
globalThis.fetch = originalFetch;
|
|
74
|
+
clearModelsJsonCache();
|
|
75
|
+
clearSecretCache();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
15
79
|
test("fallback llm prefers the active gateway provider config over models.json", { concurrency: false }, async () => {
|
|
16
80
|
__setModelsJsonForTest({
|
|
17
81
|
"custom-provider": {
|
|
@@ -1711,3 +1775,73 @@ test("fallback llm redacts provider error bodies for sensitive calls", { concurr
|
|
|
1711
1775
|
function disableGatewaySecretResolverForTest(): void {
|
|
1712
1776
|
__setGatewayResolverForTest(async () => null);
|
|
1713
1777
|
}
|
|
1778
|
+
|
|
1779
|
+
test("fallback llm does not retry schema-stripping for unrelated unsupported errors", { concurrency: false }, async () => {
|
|
1780
|
+
clearModelsJsonCache();
|
|
1781
|
+
clearSecretCache();
|
|
1782
|
+
const llm = new FallbackLlmClient({
|
|
1783
|
+
agents: { defaults: { model: { primary: "openai/test-model" } } },
|
|
1784
|
+
models: { providers: { openai: { baseUrl: "https://openai.example/v1", api: "openai-completions", apiKey: "key", models: [] } } },
|
|
1785
|
+
});
|
|
1786
|
+
const originalFetch = globalThis.fetch;
|
|
1787
|
+
const bodies: Array<Record<string, unknown>> = [];
|
|
1788
|
+
globalThis.fetch = (async (_url, init) => {
|
|
1789
|
+
const body = JSON.parse(String(init?.body ?? "{}")) as Record<string, unknown>;
|
|
1790
|
+
bodies.push(body);
|
|
1791
|
+
// Unrelated provider error: "unsupported" without schema/format context.
|
|
1792
|
+
return new Response(JSON.stringify({ error: { message: "'temperature' is unsupported with this model" } }), { status: 400 });
|
|
1793
|
+
}) as typeof fetch;
|
|
1794
|
+
try {
|
|
1795
|
+
const response = await llm.chatCompletion([{ role: "user", content: "test" }], {
|
|
1796
|
+
jsonSchema: { name: "test_result", schema: { type: "object" } },
|
|
1797
|
+
});
|
|
1798
|
+
assert.equal(response, null);
|
|
1799
|
+
// Exactly one request: no schema-stripping duplicate for unrelated errors.
|
|
1800
|
+
assert.equal(bodies.length, 1);
|
|
1801
|
+
} finally {
|
|
1802
|
+
globalThis.fetch = originalFetch;
|
|
1803
|
+
clearModelsJsonCache();
|
|
1804
|
+
clearSecretCache();
|
|
1805
|
+
}
|
|
1806
|
+
});
|
|
1807
|
+
|
|
1808
|
+
test("fallback llm retries without responsesJsonSchema when the Responses API rejects it and degrades the rest of the chain", { concurrency: false }, async () => {
|
|
1809
|
+
clearModelsJsonCache();
|
|
1810
|
+
clearSecretCache();
|
|
1811
|
+
const llm = new FallbackLlmClient({
|
|
1812
|
+
agents: { defaults: { model: { primary: "openai/test-model", fallbacks: ["openai/test-model-2"] } } },
|
|
1813
|
+
models: { providers: { openai: { baseUrl: "https://openai.example/v1", api: "openai-responses", apiKey: "key", models: [] } } },
|
|
1814
|
+
});
|
|
1815
|
+
const originalFetch = globalThis.fetch;
|
|
1816
|
+
const bodies: Array<Record<string, unknown>> = [];
|
|
1817
|
+
globalThis.fetch = (async (_url, init) => {
|
|
1818
|
+
const body = JSON.parse(String(init?.body ?? "{}")) as Record<string, unknown>;
|
|
1819
|
+
bodies.push(body);
|
|
1820
|
+
if ((body as { text?: { format?: unknown } }).text?.format) {
|
|
1821
|
+
return new Response('text.format json_schema is unsupported', { status: 400 });
|
|
1822
|
+
}
|
|
1823
|
+
// Model 1 always fails content-wise; model 2 succeeds.
|
|
1824
|
+
const model = String(body.model ?? "");
|
|
1825
|
+
if (model.endsWith("test-model")) {
|
|
1826
|
+
return new Response(JSON.stringify({ output_text: "not json" }), { status: 200 });
|
|
1827
|
+
}
|
|
1828
|
+
return new Response(JSON.stringify({ output_text: '{"ok":true}' }), { status: 200 });
|
|
1829
|
+
}) as typeof fetch;
|
|
1830
|
+
try {
|
|
1831
|
+
const response = await llm.chatCompletion([{ role: "user", content: "test" }], {
|
|
1832
|
+
responsesJsonSchema: { name: "test_result", schema: { type: "object" } },
|
|
1833
|
+
acceptResponse: (r) => r.content.includes("ok"),
|
|
1834
|
+
});
|
|
1835
|
+
assert.ok(response?.content.includes("ok"));
|
|
1836
|
+
// model1: schema attempt (rejected) + unstructured retry (bad output)
|
|
1837
|
+
// model2: unstructured only — the schema must NOT be re-sent chain-wide.
|
|
1838
|
+
assert.equal(bodies.length, 3);
|
|
1839
|
+
assert.ok((bodies[0] as { text?: { format?: unknown } }).text?.format);
|
|
1840
|
+
assert.equal((bodies[1] as { text?: { format?: unknown } }).text?.format, undefined);
|
|
1841
|
+
assert.equal((bodies[2] as { text?: { format?: unknown } }).text?.format, undefined);
|
|
1842
|
+
} finally {
|
|
1843
|
+
globalThis.fetch = originalFetch;
|
|
1844
|
+
clearModelsJsonCache();
|
|
1845
|
+
clearSecretCache();
|
|
1846
|
+
}
|
|
1847
|
+
});
|
package/src/fallback-llm.ts
CHANGED
|
@@ -27,6 +27,8 @@ export interface FallbackLlmOptions {
|
|
|
27
27
|
store?: boolean;
|
|
28
28
|
/** Request strict JSON output when a route uses the Responses API. */
|
|
29
29
|
responsesJsonSchema?: { name: string; schema: Record<string, unknown> };
|
|
30
|
+
/** Request provider-native structured output on supported JSON transports. */
|
|
31
|
+
jsonSchema?: { name: string; schema: Record<string, unknown>; strict?: boolean };
|
|
30
32
|
/** Hide provider error details that could echo private request content. */
|
|
31
33
|
redactProviderErrors?: boolean;
|
|
32
34
|
/** Explicit "provider/model" override to try before the configured chain. */
|
|
@@ -108,6 +110,22 @@ interface ModelRef {
|
|
|
108
110
|
modelString: string;
|
|
109
111
|
}
|
|
110
112
|
|
|
113
|
+
function isUnsupportedJsonSchemaError(error: unknown): boolean {
|
|
114
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
115
|
+
// Require an HTTP status plus explicit schema/format context. A bare
|
|
116
|
+
// "unsupported" (e.g. "'temperature' is unsupported with this model") must
|
|
117
|
+
// NOT trigger the schema-stripping retry, or we pay a duplicate request
|
|
118
|
+
// for unrelated provider errors.
|
|
119
|
+
if (!/\b(?:400|404|422)\b/.test(message)) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if (/(?:response[_ ]?format|json[_ ]?schema|structured[_ ]?output)/i.test(message)) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
// "unsupported" only counts when adjacent to schema/format terminology.
|
|
126
|
+
return /\bunsupported\b[\s\S]{0,40}\b(?:schema|format)\b/i.test(message);
|
|
127
|
+
}
|
|
128
|
+
|
|
111
129
|
const PROVIDER_ALIASES: Record<string, readonly string[]> = {
|
|
112
130
|
"openai-codex": ["codex"],
|
|
113
131
|
codex: ["openai-codex"],
|
|
@@ -199,8 +217,9 @@ export class FallbackLlmClient {
|
|
|
199
217
|
}
|
|
200
218
|
|
|
201
219
|
const runChain = async (
|
|
202
|
-
|
|
220
|
+
initialOptions: FallbackLlmOptions,
|
|
203
221
|
): Promise<FallbackLlmResponse | null> => {
|
|
222
|
+
let runOptions = initialOptions;
|
|
204
223
|
let lastRejectedResponse: FallbackLlmResponse | null = null;
|
|
205
224
|
// Try each model in the chain
|
|
206
225
|
for (let i = 0; i < models.length; i++) {
|
|
@@ -232,6 +251,47 @@ export class FallbackLlmClient {
|
|
|
232
251
|
if (runOptions.signal?.aborted) {
|
|
233
252
|
throw abortReason(runOptions.signal);
|
|
234
253
|
}
|
|
254
|
+
if (
|
|
255
|
+
(runOptions.jsonSchema || runOptions.responsesJsonSchema) &&
|
|
256
|
+
isUnsupportedJsonSchemaError(err)
|
|
257
|
+
) {
|
|
258
|
+
log.debug(`fallback LLM: ${model.modelString} rejected native JSON schema; retrying without it`);
|
|
259
|
+
// Degrade to prompt-only for the REST of the chain too, so an
|
|
260
|
+
// N-model chain where every provider rejects structured output
|
|
261
|
+
// costs N+1 requests instead of 2N.
|
|
262
|
+
runOptions = {
|
|
263
|
+
...runOptions,
|
|
264
|
+
jsonSchema: undefined,
|
|
265
|
+
responsesJsonSchema: undefined,
|
|
266
|
+
};
|
|
267
|
+
try {
|
|
268
|
+
const result = await this.tryModel(model, messages, runOptions);
|
|
269
|
+
if (result) {
|
|
270
|
+
const response = {
|
|
271
|
+
content: result.content,
|
|
272
|
+
modelUsed: model.modelString,
|
|
273
|
+
usage: result.usage,
|
|
274
|
+
};
|
|
275
|
+
if (!runOptions.acceptResponse || runOptions.acceptResponse(response)) {
|
|
276
|
+
return response;
|
|
277
|
+
}
|
|
278
|
+
lastRejectedResponse = response;
|
|
279
|
+
log.debug(`fallback LLM: ${model.modelString} unstructured retry output rejected by acceptResponse, trying next model...`);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
} catch (retryError) {
|
|
283
|
+
if (runOptions.signal?.aborted) throw abortReason(runOptions.signal);
|
|
284
|
+
const retryErrorMsg = runOptions.redactProviderErrors
|
|
285
|
+
? "provider error details redacted"
|
|
286
|
+
: retryError instanceof Error
|
|
287
|
+
? retryError.message
|
|
288
|
+
: String(retryError);
|
|
289
|
+
log.debug(
|
|
290
|
+
`fallback LLM: ${model.modelString} unstructured retry failed (${retryErrorMsg})`,
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
235
295
|
const errorMsg = runOptions.redactProviderErrors
|
|
236
296
|
? "provider error details redacted"
|
|
237
297
|
: err instanceof Error
|
|
@@ -736,6 +796,18 @@ export class FallbackLlmClient {
|
|
|
736
796
|
...buildChatCompletionTokenLimit(modelId, options.maxTokens ?? 4096, {
|
|
737
797
|
assumeOpenAI,
|
|
738
798
|
}),
|
|
799
|
+
...(options.jsonSchema
|
|
800
|
+
? {
|
|
801
|
+
response_format: {
|
|
802
|
+
type: "json_schema",
|
|
803
|
+
json_schema: {
|
|
804
|
+
name: options.jsonSchema.name,
|
|
805
|
+
strict: options.jsonSchema.strict ?? false,
|
|
806
|
+
schema: options.jsonSchema.schema,
|
|
807
|
+
},
|
|
808
|
+
},
|
|
809
|
+
}
|
|
810
|
+
: {}),
|
|
739
811
|
};
|
|
740
812
|
|
|
741
813
|
const response = await fetch(url, {
|
|
@@ -891,14 +963,14 @@ export class FallbackLlmClient {
|
|
|
891
963
|
assumeOpenAI: shouldAssumeOpenAiChatCompletions(config.baseUrl),
|
|
892
964
|
}),
|
|
893
965
|
...(options.store === undefined ? {} : { store: options.store }),
|
|
894
|
-
...(options.responsesJsonSchema
|
|
966
|
+
...(options.jsonSchema || options.responsesJsonSchema
|
|
895
967
|
? {
|
|
896
968
|
text: {
|
|
897
969
|
format: {
|
|
898
970
|
type: "json_schema",
|
|
899
|
-
name: options.responsesJsonSchema
|
|
900
|
-
strict: true,
|
|
901
|
-
schema: options.responsesJsonSchema
|
|
971
|
+
name: (options.jsonSchema ?? options.responsesJsonSchema)!.name,
|
|
972
|
+
strict: (options.jsonSchema?.strict ?? (options.responsesJsonSchema ? true : false)),
|
|
973
|
+
schema: (options.jsonSchema ?? options.responsesJsonSchema)!.schema,
|
|
902
974
|
},
|
|
903
975
|
},
|
|
904
976
|
}
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
import { defineOperation } from "../access-boundary.js";
|
|
11
11
|
import type { EngramAccessService } from "../access-service.js";
|
|
12
|
+
import { backfillMemoryStorage } from "./backfill.js";
|
|
12
13
|
import {
|
|
13
|
-
|
|
14
|
+
runLocationBackfill,
|
|
14
15
|
runLocationCheck,
|
|
15
16
|
runLocationDay,
|
|
16
17
|
runLocationStatus,
|
|
@@ -21,9 +22,14 @@ import {
|
|
|
21
22
|
/** Zod shape shared by the location operations (null-for-absent tolerant). */
|
|
22
23
|
const dateField = z.union([z.string(), z.null()]).optional();
|
|
23
24
|
const daysField = z.union([z.number(), z.string(), z.null()]).optional();
|
|
25
|
+
const dryRunField = z.union([z.boolean(), z.null()]).optional();
|
|
24
26
|
|
|
25
27
|
function locationDeps(service: EngramAccessService): LocationSurfaceDeps {
|
|
26
|
-
return {
|
|
28
|
+
return {
|
|
29
|
+
config: service.configRef.location,
|
|
30
|
+
memoryDir: service.memoryDir,
|
|
31
|
+
getMemoryStorage: () => backfillMemoryStorage(service.configRef),
|
|
32
|
+
};
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
defineOperation({
|
|
@@ -63,13 +69,16 @@ defineOperation({
|
|
|
63
69
|
|
|
64
70
|
defineOperation({
|
|
65
71
|
name: "location_backfill",
|
|
66
|
-
description: "Sync an explicit historical day range (≤ 90 days).",
|
|
72
|
+
description: "Sync an explicit historical day range (≤ 90 days) and re-tag overlapping memories (issue #2046).",
|
|
67
73
|
fleetWide: true,
|
|
68
|
-
schema: z.object({ from: dateField, to: dateField }).passthrough(),
|
|
69
|
-
handler: async (input, ctx) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
schema: z.object({ from: dateField, to: dateField, dryRun: dryRunField }).passthrough(),
|
|
75
|
+
handler: async (input, ctx) => ({
|
|
76
|
+
result: await runLocationBackfill(locationDeps(ctx.service), {
|
|
77
|
+
from: input.from ?? null,
|
|
78
|
+
to: input.to ?? null,
|
|
79
|
+
dryRun: input.dryRun === true,
|
|
80
|
+
}),
|
|
81
|
+
}),
|
|
73
82
|
});
|
|
74
83
|
|
|
75
84
|
defineOperation({
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Location tag backfill (issue #2046) — idempotent, bounded, LLM-free.
|
|
3
|
+
*
|
|
4
|
+
* For each local day in an explicit [from, to] range, find the memories whose
|
|
5
|
+
* own bi-temporal window touches that day and re-run the shared tagging core
|
|
6
|
+
* over the stored location segments. Provider-owned fields update or remove
|
|
7
|
+
* as the (corrected) observations dictate; manual metadata, unrelated tags,
|
|
8
|
+
* supersession, corrections, and content hashes are untouched by the plan
|
|
9
|
+
* core in `matching.ts`.
|
|
10
|
+
*
|
|
11
|
+
* Failure isolation: one bad day is reported as `failed` and the run
|
|
12
|
+
* continues; one bad memory inside a day counts into `failed` without
|
|
13
|
+
* blocking its neighbors. A day with no stored segments is `emptyDay`, never
|
|
14
|
+
* an error (distinct from a failed day). Re-running the same range yields
|
|
15
|
+
* `unchanged` everywhere and writes nothing.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { StorageManager } from "../index.js";
|
|
19
|
+
import type { MemoryFile, PluginConfig } from "../types.js";
|
|
20
|
+
import { resolveNamespaceCapabilities } from "../capabilities.js";
|
|
21
|
+
import { resolveDefaultNamespaceRoot } from "../namespaces/storage.js";
|
|
22
|
+
import { StorageManager as StorageManagerClass } from "../storage.js";
|
|
23
|
+
import { localDayKey } from "./intervals.js";
|
|
24
|
+
import { memoryLocationWindow } from "./matching.js";
|
|
25
|
+
import {
|
|
26
|
+
emptyEnrichmentCounts,
|
|
27
|
+
enrichMemoriesWithLocation,
|
|
28
|
+
loadDaySegmentIndex,
|
|
29
|
+
locationTaggingEnabled,
|
|
30
|
+
type DaySegmentIndex,
|
|
31
|
+
type LocationEnrichmentCounts,
|
|
32
|
+
} from "./tagging.js";
|
|
33
|
+
import type { LocationConfig } from "./types.js";
|
|
34
|
+
|
|
35
|
+
export interface LocationBackfillDayReport {
|
|
36
|
+
date: string;
|
|
37
|
+
/** No stored segments for any source on this day. */
|
|
38
|
+
emptyDay: boolean;
|
|
39
|
+
failed?: string;
|
|
40
|
+
counts: LocationEnrichmentCounts;
|
|
41
|
+
/** Memories whose window touched the day (empty days report 0). */
|
|
42
|
+
considered: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface LocationBackfillReport {
|
|
46
|
+
from: string;
|
|
47
|
+
to: string;
|
|
48
|
+
dryRun: boolean;
|
|
49
|
+
days: LocationBackfillDayReport[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface BackfillLocationTagsOptions {
|
|
53
|
+
storage: Pick<StorageManager, "readAllMemories" | "getMemoryById" | "writeMemoryFrontmatter">;
|
|
54
|
+
memoryDir: string;
|
|
55
|
+
config: LocationConfig;
|
|
56
|
+
from: string;
|
|
57
|
+
to: string;
|
|
58
|
+
dryRun?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type BackfillMemoryStorage = Pick<StorageManager, "readAllMemories" | "getMemoryById" | "writeMemoryFrontmatter">;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The memory store tag backfill patches: the default-namespace store — the
|
|
65
|
+
* root memory dir when namespaces are off, the resolved default-namespace
|
|
66
|
+
* root when they are on.
|
|
67
|
+
*/
|
|
68
|
+
export async function backfillMemoryStorage(config: PluginConfig): Promise<StorageManager> {
|
|
69
|
+
const root = resolveNamespaceCapabilities(config).namespaces
|
|
70
|
+
? await resolveDefaultNamespaceRoot(config)
|
|
71
|
+
: config.memoryDir;
|
|
72
|
+
return new StorageManagerClass(root);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
/** Memories whose own window touches `day`, in deterministic id order. */
|
|
77
|
+
function memoriesTouchingDay(memories: readonly MemoryFile[], day: string, config: LocationConfig): MemoryFile[] {
|
|
78
|
+
const touched: MemoryFile[] = [];
|
|
79
|
+
for (const memory of memories) {
|
|
80
|
+
const result = memoryLocationWindow(memory.frontmatter, (instant) => localDayKey(instant, config.timezone));
|
|
81
|
+
if (result.days !== undefined && result.days.includes(day)) touched.push(memory);
|
|
82
|
+
}
|
|
83
|
+
touched.sort((a, b) => (a.frontmatter.id < b.frontmatter.id ? -1 : a.frontmatter.id > b.frontmatter.id ? 1 : 0));
|
|
84
|
+
return touched;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Run the bounded backfill. Requires both tagging gates (`location.enabled`
|
|
89
|
+
* and `location.tagging.enabled`); the caller surfaces a clear error for a
|
|
90
|
+
* gated-off run so no surface silently no-ops.
|
|
91
|
+
*/
|
|
92
|
+
export async function backfillLocationTags(
|
|
93
|
+
options: BackfillLocationTagsOptions,
|
|
94
|
+
): Promise<LocationBackfillReport> {
|
|
95
|
+
if (!locationTaggingEnabled(options.config)) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
"location backfill requires location.enabled and location.tagging.enabled (and location.tagging.backfillEnabled for the command surface)",
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
const index: DaySegmentIndex = await loadDaySegmentIndex(options.memoryDir);
|
|
101
|
+
const memories = await options.storage.readAllMemories();
|
|
102
|
+
|
|
103
|
+
const days: LocationBackfillDayReport[] = [];
|
|
104
|
+
const cursor = new Date(`${options.from}T00:00:00Z`);
|
|
105
|
+
const end = new Date(`${options.to}T00:00:00Z`);
|
|
106
|
+
while (cursor <= end) {
|
|
107
|
+
const date = cursor.toISOString().slice(0, 10);
|
|
108
|
+
try {
|
|
109
|
+
const daySegments = index.get(date);
|
|
110
|
+
if (daySegments === undefined || daySegments.every((entry) => entry.segments.length === 0)) {
|
|
111
|
+
days.push({ date, emptyDay: true, counts: emptyEnrichmentCounts(), considered: 0 });
|
|
112
|
+
} else {
|
|
113
|
+
const touching = memoriesTouchingDay(memories, date, options.config);
|
|
114
|
+
const counts = await enrichMemoriesWithLocation({
|
|
115
|
+
storage: options.storage,
|
|
116
|
+
memoryDir: options.memoryDir,
|
|
117
|
+
config: options.config,
|
|
118
|
+
memories: touching,
|
|
119
|
+
index,
|
|
120
|
+
dryRun: options.dryRun === true,
|
|
121
|
+
});
|
|
122
|
+
days.push({ date, emptyDay: false, counts, considered: touching.length });
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
// One failed day never blocks the rest of the range.
|
|
126
|
+
days.push({
|
|
127
|
+
date,
|
|
128
|
+
emptyDay: false,
|
|
129
|
+
failed: error instanceof Error ? error.message : String(error),
|
|
130
|
+
counts: emptyEnrichmentCounts(),
|
|
131
|
+
considered: 0,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
cursor.setUTCDate(cursor.getUTCDate() + 1);
|
|
135
|
+
}
|
|
136
|
+
return { from: options.from, to: options.to, dryRun: options.dryRun === true, days };
|
|
137
|
+
}
|
|
@@ -9,6 +9,9 @@ test("parseLocationConfig defaults to an inert configuration", () => {
|
|
|
9
9
|
timezone: "UTC",
|
|
10
10
|
syncDays: 1,
|
|
11
11
|
retainCoordinates: false,
|
|
12
|
+
minimumOverlapSeconds: 300,
|
|
13
|
+
minimumConfidence: 0.7,
|
|
14
|
+
tagging: { enabled: false, backfillEnabled: false },
|
|
12
15
|
sources: [],
|
|
13
16
|
});
|
|
14
17
|
assert.deepEqual(parseLocationConfig(undefined), defaultLocationConfig());
|
package/src/location/config.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { coerceBooleanLike, coerceNumber } from "../connectors/coerce.js";
|
|
2
2
|
import { assertValidTimezone } from "../activity/digest.js";
|
|
3
|
-
import type { LocationConfig, LocationSourceConfig } from "./types.js";
|
|
3
|
+
import type { LocationConfig, LocationSourceConfig, LocationTaggingConfig } from "./types.js";
|
|
4
4
|
|
|
5
5
|
const PROVIDER_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
6
6
|
|
|
@@ -11,6 +11,9 @@ export function defaultLocationConfig(): LocationConfig {
|
|
|
11
11
|
timezone: "UTC",
|
|
12
12
|
syncDays: 1,
|
|
13
13
|
retainCoordinates: false,
|
|
14
|
+
minimumOverlapSeconds: 300,
|
|
15
|
+
minimumConfidence: 0.7,
|
|
16
|
+
tagging: { enabled: false, backfillEnabled: false },
|
|
14
17
|
sources: [],
|
|
15
18
|
};
|
|
16
19
|
}
|
|
@@ -101,5 +104,46 @@ export function parseLocationConfig(raw: unknown): LocationConfig {
|
|
|
101
104
|
throw new RangeError("location.enabled requires at least one source");
|
|
102
105
|
}
|
|
103
106
|
|
|
104
|
-
|
|
107
|
+
const overlapValue = coerceNumber(config.minimumOverlapSeconds, "location.minimumOverlapSeconds");
|
|
108
|
+
if (config.minimumOverlapSeconds !== undefined && overlapValue === undefined) {
|
|
109
|
+
throw new TypeError("location.minimumOverlapSeconds must be a finite number");
|
|
110
|
+
}
|
|
111
|
+
const minimumOverlapSeconds = overlapValue ?? 300;
|
|
112
|
+
if (!Number.isInteger(minimumOverlapSeconds) || minimumOverlapSeconds < 0) {
|
|
113
|
+
throw new RangeError("location.minimumOverlapSeconds must be an integer >= 0 (0 disables the floor)");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const confidenceValue = coerceNumber(config.minimumConfidence, "location.minimumConfidence");
|
|
117
|
+
if (config.minimumConfidence !== undefined && confidenceValue === undefined) {
|
|
118
|
+
throw new TypeError("location.minimumConfidence must be a finite number");
|
|
119
|
+
}
|
|
120
|
+
const minimumConfidence = confidenceValue ?? 0.7;
|
|
121
|
+
if (minimumConfidence < 0 || minimumConfidence > 1) {
|
|
122
|
+
throw new RangeError("location.minimumConfidence must be within [0, 1]");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const tagging = parseLocationTagging(config.tagging, enabled);
|
|
126
|
+
|
|
127
|
+
return { enabled, timezone, syncDays, retainCoordinates, minimumOverlapSeconds, minimumConfidence, tagging, sources };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function parseLocationTagging(raw: unknown, masterEnabled: boolean): LocationTaggingConfig {
|
|
131
|
+
if (raw === undefined || raw === null) return { enabled: false, backfillEnabled: false };
|
|
132
|
+
const tagging = asRecord(raw, "location.tagging");
|
|
133
|
+
const enabledValue = coerceBooleanLike(tagging.enabled, "location.tagging.enabled");
|
|
134
|
+
if (tagging.enabled !== undefined && enabledValue === undefined) {
|
|
135
|
+
throw new TypeError("location.tagging.enabled must be a boolean");
|
|
136
|
+
}
|
|
137
|
+
const backfillValue = coerceBooleanLike(tagging.backfillEnabled, "location.tagging.backfillEnabled");
|
|
138
|
+
if (tagging.backfillEnabled !== undefined && backfillValue === undefined) {
|
|
139
|
+
throw new TypeError("location.tagging.backfillEnabled must be a boolean");
|
|
140
|
+
}
|
|
141
|
+
const backfillEnabled = backfillValue ?? false;
|
|
142
|
+
if (enabledValue === true && !masterEnabled) {
|
|
143
|
+
throw new RangeError("location.tagging.enabled requires location.enabled");
|
|
144
|
+
}
|
|
145
|
+
if (backfillEnabled && !(enabledValue ?? false)) {
|
|
146
|
+
throw new RangeError("location.tagging.backfillEnabled requires location.tagging.enabled");
|
|
147
|
+
}
|
|
148
|
+
return { enabled: enabledValue ?? false, backfillEnabled };
|
|
105
149
|
}
|
|
@@ -65,7 +65,7 @@ export async function respondLocationBackfill(
|
|
|
65
65
|
service: EngramAccessService,
|
|
66
66
|
): Promise<void> {
|
|
67
67
|
const output = (await requireLocationOperation("location_backfill").run(
|
|
68
|
-
{ from: body.from ?? null, to: body.to ?? null },
|
|
68
|
+
{ from: body.from ?? null, to: body.to ?? null, dryRun: body.dryRun === true },
|
|
69
69
|
{ service },
|
|
70
70
|
)) as { result: unknown };
|
|
71
71
|
respondJson(res, 200, output.result);
|
package/src/location/index.ts
CHANGED
|
@@ -127,6 +127,7 @@ export function observationSegments(
|
|
|
127
127
|
startUtc: new Date(currentMs).toISOString(),
|
|
128
128
|
endUtc: new Date(segmentEndMs).toISOString(),
|
|
129
129
|
place: placeForSegment(current.place, options.retainCoordinates),
|
|
130
|
+
...(current.confidence !== undefined ? { confidence: current.confidence } : {}),
|
|
130
131
|
});
|
|
131
132
|
}
|
|
132
133
|
return segments;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { matchDominantPlace, memoryLocationWindow, type LocationTagPolicy } from "./matching.js";
|
|
5
|
+
import type { LocationPlace, LocationSegment } from "./types.js";
|
|
6
|
+
|
|
7
|
+
const policy: LocationTagPolicy = {
|
|
8
|
+
minimumOverlapSeconds: 60,
|
|
9
|
+
minimumConfidence: 0.4,
|
|
10
|
+
retainCoordinates: false,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const home: LocationPlace = { id: "home", label: "Home", kind: "home" };
|
|
14
|
+
const work: LocationPlace = { id: "work", label: "Work", kind: "work" };
|
|
15
|
+
|
|
16
|
+
function segment(place: LocationPlace, start: string, end: string, confidence = 0.9): LocationSegment {
|
|
17
|
+
return { startUtc: start, endUtc: end, place, confidence };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
test("untimed and over-long memories stay untagged", () => {
|
|
21
|
+
const day = (iso: string) => iso.slice(0, 10);
|
|
22
|
+
assert.equal(memoryLocationWindow({}, day).rejected, "untimed");
|
|
23
|
+
assert.equal(
|
|
24
|
+
memoryLocationWindow(
|
|
25
|
+
{ valid_at: "2026-08-01T00:00:00.000Z", invalid_at: "2026-08-03T00:00:00.000Z" },
|
|
26
|
+
day,
|
|
27
|
+
).rejected,
|
|
28
|
+
"span-too-long",
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("dominant named place wins; ties stay unmatched", () => {
|
|
33
|
+
const window = { kind: "interval" as const, startUtc: "2026-08-01T12:00:00.000Z", endUtc: "2026-08-01T14:00:00.000Z" };
|
|
34
|
+
const matched = matchDominantPlace(
|
|
35
|
+
window,
|
|
36
|
+
[
|
|
37
|
+
{
|
|
38
|
+
sourceId: "reitti",
|
|
39
|
+
segments: [
|
|
40
|
+
segment(home, "2026-08-01T11:00:00.000Z", "2026-08-01T13:30:00.000Z"),
|
|
41
|
+
segment(work, "2026-08-01T13:30:00.000Z", "2026-08-01T14:00:00.000Z"),
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
policy,
|
|
46
|
+
);
|
|
47
|
+
assert.equal(matched.status, "matched");
|
|
48
|
+
if (matched.status === "matched") assert.equal(matched.match.place.id, "home");
|
|
49
|
+
|
|
50
|
+
const tied = matchDominantPlace(
|
|
51
|
+
window,
|
|
52
|
+
[
|
|
53
|
+
{
|
|
54
|
+
sourceId: "reitti",
|
|
55
|
+
segments: [
|
|
56
|
+
segment(home, "2026-08-01T12:00:00.000Z", "2026-08-01T13:00:00.000Z"),
|
|
57
|
+
segment(work, "2026-08-01T13:00:00.000Z", "2026-08-01T14:00:00.000Z"),
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
policy,
|
|
62
|
+
);
|
|
63
|
+
assert.equal(tied.status, "unmatched");
|
|
64
|
+
if (tied.status === "unmatched") assert.equal(tied.reason, "ambiguous");
|
|
65
|
+
});
|