@remnic/core 9.63.0 → 9.63.2
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 +1 -1
- package/dist/access-admin-ops-surface.js +34 -33
- package/dist/access-audit.js +2 -2
- package/dist/access-authorization-probe.d.ts +1 -1
- package/dist/access-authorization-probe.js +35 -34
- package/dist/access-boundary.d.ts +1 -1
- package/dist/access-boundary.js +34 -33
- package/dist/access-cli.js +99 -97
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +1 -1
- package/dist/access-extraction-force-flush.js +34 -33
- package/dist/access-http-lcm-compaction.d.ts +1 -1
- package/dist/access-http-lifecycle-flush.d.ts +1 -1
- package/dist/access-http-offline-stream.d.ts +1 -1
- package/dist/access-http-query.js +34 -33
- package/dist/access-http.d.ts +2 -2
- package/dist/access-http.js +47 -46
- package/dist/access-identity-continuity-surface.js +34 -33
- package/dist/access-lcm-surface.d.ts +1 -1
- package/dist/access-lcm-surface.js +34 -33
- package/dist/access-mcp.d.ts +1 -1
- package/dist/access-mcp.js +40 -39
- package/dist/access-namespace-preflight.js +34 -33
- package/dist/access-observe-write-surface.d.ts +1 -1
- package/dist/access-observe-write-surface.js +34 -33
- package/dist/access-operations-batch.js +35 -34
- package/dist/access-operations.d.ts +4 -4
- package/dist/access-operations.js +39 -38
- package/dist/access-recall-concurrency.d.ts +1 -1
- package/dist/access-recall-concurrency.js +34 -33
- package/dist/access-recall-response.d.ts +1 -1
- package/dist/access-recall-response.js +34 -33
- package/dist/access-recall-surface.d.ts +1 -1
- package/dist/access-recall-surface.js +34 -33
- package/dist/access-schema.d.ts +88 -88
- package/dist/access-schema.js +3 -3
- package/dist/access-service-helpers.d.ts +1 -1
- package/dist/access-service.d.ts +1 -1
- package/dist/access-service.js +34 -33
- package/dist/access-surface-catalog.d.ts +1 -1
- package/dist/access-surface-catalog.js +36 -35
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/registry.js +3 -3
- package/dist/{auto-sync-Z52VWMNC.js → auto-sync-BKRJDMKX.js} +3 -3
- package/dist/behavior-learner.js +2 -2
- package/dist/briefing.js +15 -15
- package/dist/buffer.js +5 -4
- package/dist/causal-behavior.js +3 -3
- package/dist/causal-chain.js +3 -3
- package/dist/causal-consolidation.js +18 -18
- package/dist/causal-retrieval.js +3 -3
- package/dist/causal-trajectory.js +2 -2
- package/dist/{chunk-5F6HMNMZ.js → chunk-2LA3H54D.js} +2 -2
- package/dist/{chunk-IRLH4NM2.js → chunk-2PSX5BJU.js} +3 -3
- package/dist/{chunk-JBPKEARU.js → chunk-2QSZNTDO.js} +7 -7
- package/dist/{chunk-IZRNVNPV.js → chunk-3LJ2L3T3.js} +2 -2
- package/dist/{chunk-CLJ5QS6J.js → chunk-44KHFMCM.js} +72 -64
- package/dist/{chunk-CLJ5QS6J.js.map → chunk-44KHFMCM.js.map} +1 -1
- package/dist/{chunk-JDI7G6EA.js → chunk-4NMVX5U7.js} +2 -2
- package/dist/{chunk-WFLBP5GC.js → chunk-4NZHHGVL.js} +25 -6
- package/dist/chunk-4NZHHGVL.js.map +1 -0
- package/dist/{chunk-ANMIOQPU.js → chunk-4XN35YQD.js} +478 -164
- package/dist/chunk-4XN35YQD.js.map +1 -0
- package/dist/{chunk-LJOIZPJH.js → chunk-5QZR2RA3.js} +2 -2
- package/dist/{chunk-FF6E6HOT.js → chunk-5UFQCU6M.js} +32 -32
- package/dist/{chunk-4HO3542O.js → chunk-5W5N7XJZ.js} +2 -2
- package/dist/{chunk-4Y2RHVCV.js → chunk-5W62VEFH.js} +4 -4
- package/dist/{chunk-DEOYTFA6.js → chunk-645WOU5I.js} +4 -52
- package/dist/chunk-645WOU5I.js.map +1 -0
- package/dist/{chunk-LTJTP5YQ.js → chunk-6D7PZKCJ.js} +10 -10
- package/dist/{chunk-BBHFAVMP.js → chunk-6F2UMP4H.js} +7 -7
- package/dist/{chunk-IIPJKCZB.js → chunk-6NAPOLRO.js} +3 -3
- package/dist/{chunk-CK3NQUSQ.js → chunk-6UZR7KEK.js} +2 -2
- package/dist/{chunk-2TYIAKU5.js → chunk-6YMEU6OQ.js} +2 -2
- package/dist/{chunk-H23GIXJC.js → chunk-A73QHOZP.js} +2 -2
- package/dist/{chunk-LLGDVG52.js → chunk-AJSZ2EK6.js} +3 -3
- package/dist/{chunk-HVKMJAEF.js → chunk-B2OOJCUX.js} +2 -2
- package/dist/chunk-BUYVPUEM.js +66 -0
- package/dist/chunk-BUYVPUEM.js.map +1 -0
- package/dist/{chunk-YTHQHH5U.js → chunk-C6WMSXCJ.js} +2 -2
- package/dist/{chunk-JKW663ZN.js → chunk-CIAI24TQ.js} +2 -2
- package/dist/{chunk-PD6O7AXF.js → chunk-CSAKJVXW.js} +14 -17
- package/dist/chunk-CSAKJVXW.js.map +1 -0
- package/dist/{chunk-EFWHCTYJ.js → chunk-DNRTKO2U.js} +2 -2
- package/dist/{chunk-QCECHYZL.js → chunk-E2GYBTSP.js} +24 -4
- package/dist/chunk-E2GYBTSP.js.map +1 -0
- package/dist/{chunk-4IZ2IT7D.js → chunk-EJLTNPRY.js} +3 -3
- package/dist/{chunk-JCJGYNIS.js → chunk-EJQXDKYK.js} +4 -4
- package/dist/{chunk-347ZR6D4.js → chunk-FKJVEW6O.js} +2 -2
- package/dist/{chunk-DROAPP6N.js → chunk-GFNS3BHV.js} +3 -3
- package/dist/{chunk-ALNZEWGN.js → chunk-GPFZFCRN.js} +2 -2
- package/dist/{chunk-KPML4Q3M.js → chunk-GTRGH4ZT.js} +3 -3
- package/dist/{chunk-TIRJV2LW.js → chunk-I6OQCT3Y.js} +2 -2
- package/dist/{chunk-CH627RRV.js → chunk-IKXUG6KC.js} +8 -8
- package/dist/{chunk-HSBQJRV2.js → chunk-IM56VPKO.js} +3 -3
- package/dist/{chunk-KQAFEZQX.js → chunk-IPLYGWQF.js} +5 -5
- package/dist/{chunk-BP6WMYLP.js → chunk-ITYAXU4S.js} +3 -3
- package/dist/{chunk-4FFROSFG.js → chunk-JJ7JW62R.js} +23 -23
- package/dist/{chunk-RFH7U5LT.js → chunk-JJX5XEIG.js} +2 -2
- package/dist/{chunk-CALURYWR.js → chunk-JWPG65LH.js} +14 -14
- package/dist/chunk-K2XUWZBM.js +417 -0
- package/dist/chunk-K2XUWZBM.js.map +1 -0
- package/dist/{chunk-G2FCSILA.js → chunk-KWIGDKM2.js} +2 -2
- package/dist/{chunk-WR2YKUIW.js → chunk-KWN6NOHQ.js} +2 -2
- package/dist/{chunk-227UFSEQ.js → chunk-LEPOP46W.js} +4 -4
- package/dist/{chunk-WMOJIOIG.js → chunk-LZCSOUJ7.js} +2 -2
- package/dist/{chunk-256FBCVX.js → chunk-M4AHBM72.js} +7 -7
- package/dist/{chunk-5PFGMO33.js → chunk-MEW53VQJ.js} +2 -2
- package/dist/{chunk-DCUMFQYM.js → chunk-ML3U4KPR.js} +2 -2
- package/dist/{chunk-X6E7TT3A.js → chunk-MR5HWQHS.js} +2 -2
- package/dist/{chunk-H7PRHUBD.js → chunk-NRLELHAY.js} +2 -2
- package/dist/{chunk-ZS4JADYY.js → chunk-OW7NVMGQ.js} +2 -2
- package/dist/{chunk-TGSMU3F2.js → chunk-PADG72LJ.js} +3 -3
- package/dist/{chunk-6GGTATZF.js → chunk-PYIR4SSB.js} +4 -4
- package/dist/chunk-PYIR4SSB.js.map +1 -0
- package/dist/{chunk-UDTME32W.js → chunk-Q35XGIEM.js} +2 -2
- package/dist/{chunk-XPRJSHNI.js → chunk-QJ622LTI.js} +6 -3
- package/dist/chunk-QJ622LTI.js.map +1 -0
- package/dist/{chunk-AYIHDC5S.js → chunk-QSIQVC32.js} +2 -2
- package/dist/{chunk-3MA7JVXN.js → chunk-R74NCKEY.js} +4 -4
- package/dist/{chunk-QCI73Z7C.js → chunk-RYGJGXL6.js} +2 -2
- package/dist/{chunk-4OW2T32G.js → chunk-SQ3EGGII.js} +2 -2
- package/dist/{chunk-ZPGHA7EO.js → chunk-TRPX6F2G.js} +10 -10
- package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
- package/dist/{chunk-7BJYTX6Q.js → chunk-VAMQU4W7.js} +2 -2
- package/dist/{chunk-YSR3DXGC.js → chunk-VN7IIQGS.js} +2 -2
- package/dist/{chunk-DTLF2SLZ.js → chunk-WDUG2CH3.js} +2 -2
- package/dist/{chunk-YIIC5IDU.js → chunk-X4MGNVOO.js} +2 -2
- package/dist/{chunk-BHO6RHE5.js → chunk-XFCQIQQU.js} +3 -3
- package/dist/{chunk-PSNN25DW.js → chunk-XZPSBGHA.js} +2 -2
- package/dist/{chunk-PMRUMGK6.js → chunk-Y7COCXY2.js} +2 -2
- package/dist/{chunk-DJ7HMNSL.js → chunk-YCVB7X56.js} +4 -2
- package/dist/chunk-YCVB7X56.js.map +1 -0
- package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
- package/dist/{chunk-JFLKSD5V.js → chunk-Z334TJRB.js} +2 -2
- package/dist/{cli-Bw9z-KqX.d.ts → cli-DJwNNDL1.d.ts} +1 -1
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +68 -67
- package/dist/coding/pre-action-gate.js +3 -3
- package/dist/compounding/engine.js +15 -15
- package/dist/connectors/codex-materialize-runner.js +15 -15
- package/dist/connectors/index.d.ts +45 -1
- package/dist/connectors/index.js +24 -16
- package/dist/convergence-refresh.js +17 -17
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +17 -17
- package/dist/dashboard-runtime.js +2 -2
- package/dist/direct-answer-wiring.js +3 -3
- package/dist/direct-answer.js +2 -2
- package/dist/entity-retrieval.js +15 -15
- package/dist/event-order-query.d.ts +3 -0
- package/dist/event-order-query.js +9 -0
- package/dist/event-order-query.js.map +1 -0
- package/dist/event-order-recall.d.ts +2 -2
- package/dist/event-order-recall.js +5 -2
- package/dist/external-wiki-access.d.ts +1 -1
- package/dist/external-wiki-access.js +35 -34
- package/dist/external-wiki-mcp-tools.d.ts +1 -1
- package/dist/extraction-normalization.js +2 -2
- package/dist/extraction.js +25 -24
- package/dist/harmonic-construction.js +2 -2
- package/dist/harmonic-retrieval.js +2 -2
- package/dist/index.d.ts +683 -682
- package/dist/index.js +108 -105
- package/dist/intent.js +2 -1
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.js +6 -6
- package/dist/maintenance/memory-governance.js +15 -15
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +15 -15
- package/dist/maintenance/rebuild-memory-projection.js +16 -16
- package/dist/mcp-memory-inspector-app.d.ts +1 -1
- package/dist/namespaces/migrate.js +16 -16
- package/dist/namespaces/search.js +10 -10
- package/dist/namespaces/storage.js +15 -15
- package/dist/operator-doctor-corpus.js +18 -18
- package/dist/operator-toolkit.js +22 -22
- package/dist/orchestration/maintenance.js +20 -20
- package/dist/orchestrator.js +101 -99
- package/dist/policy-runtime.js +3 -3
- package/dist/{public-http-DK-QwaBu.d.ts → public-http-43z1YT-k.d.ts} +1 -1
- package/dist/{qmd-D_62bYNl.d.ts → qmd-CBSxevyb.d.ts} +12 -1
- package/dist/qmd-preflight.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/qmd.js +3 -1
- package/dist/recall-planner-i18n.d.ts +31 -0
- package/dist/recall-planner-i18n.js +30 -0
- package/dist/recall-planner-i18n.js.map +1 -0
- package/dist/recall-planner-llm.js +2 -1
- package/dist/recall-planner-llm.js.map +1 -1
- package/dist/recall-query-policy.js +2 -2
- package/dist/recall-tokenization.js +1 -1
- package/dist/resume-bundles.js +3 -3
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-agents.js +2 -1
- package/dist/schemas.d.ts +117 -434
- package/dist/schemas.js +1 -1
- package/dist/search/factory.js +9 -9
- package/dist/search/index.js +15 -15
- package/dist/search/orama-backend.js +2 -2
- package/dist/semantic-consolidation.js +16 -16
- package/dist/semantic-rule-promotion.js +15 -15
- package/dist/semantic-rule-verifier.js +15 -15
- package/dist/shared-context/manager.d.ts +8 -8
- package/dist/source-agent-qualifier.js +21 -20
- package/dist/storage.js +14 -14
- package/dist/support-passport/index.d.ts +4 -4
- package/dist/support-passport/index.js +37 -36
- package/dist/transfer/autodetect.js +1 -1
- package/dist/transfer/backup.js +1 -1
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/types.d.ts +66 -66
- package/dist/trust-zones.js +2 -2
- package/dist/verified-recall.js +15 -15
- package/dist/work-product-ledger.js +2 -2
- package/package.json +2 -2
- package/src/connectors/droid-mcp.ts +434 -0
- package/src/connectors/index.ts +70 -0
- package/src/direct-answer.ts +6 -3
- package/src/event-order-query.ts +78 -0
- package/src/event-order-recall.ts +4 -90
- package/src/intent.ts +19 -19
- package/src/orchestration/turn-ingestion.ts +24 -1
- package/src/orchestrator-flush.test.ts +142 -1
- package/src/qmd-process-group.test.ts +125 -0
- package/src/qmd.ts +30 -2
- package/src/recall-planner-i18n.ts +193 -0
- package/src/recall-tokenization.ts +3 -1
- package/src/retrieval-agents.ts +6 -10
- package/src/schemas.test.ts +158 -0
- package/src/schemas.ts +45 -22
- package/dist/chunk-6GGTATZF.js.map +0 -1
- package/dist/chunk-ANMIOQPU.js.map +0 -1
- package/dist/chunk-DEOYTFA6.js.map +0 -1
- package/dist/chunk-DJ7HMNSL.js.map +0 -1
- package/dist/chunk-PD6O7AXF.js.map +0 -1
- package/dist/chunk-QCECHYZL.js.map +0 -1
- package/dist/chunk-WFLBP5GC.js.map +0 -1
- package/dist/chunk-XPRJSHNI.js.map +0 -1
- package/dist/{access-service-M4LgO141.d.ts → access-service-DBpEnlzA.d.ts} +64 -64
- /package/dist/{auto-sync-Z52VWMNC.js.map → auto-sync-BKRJDMKX.js.map} +0 -0
- /package/dist/{chunk-5F6HMNMZ.js.map → chunk-2LA3H54D.js.map} +0 -0
- /package/dist/{chunk-IRLH4NM2.js.map → chunk-2PSX5BJU.js.map} +0 -0
- /package/dist/{chunk-JBPKEARU.js.map → chunk-2QSZNTDO.js.map} +0 -0
- /package/dist/{chunk-IZRNVNPV.js.map → chunk-3LJ2L3T3.js.map} +0 -0
- /package/dist/{chunk-JDI7G6EA.js.map → chunk-4NMVX5U7.js.map} +0 -0
- /package/dist/{chunk-LJOIZPJH.js.map → chunk-5QZR2RA3.js.map} +0 -0
- /package/dist/{chunk-FF6E6HOT.js.map → chunk-5UFQCU6M.js.map} +0 -0
- /package/dist/{chunk-4HO3542O.js.map → chunk-5W5N7XJZ.js.map} +0 -0
- /package/dist/{chunk-4Y2RHVCV.js.map → chunk-5W62VEFH.js.map} +0 -0
- /package/dist/{chunk-LTJTP5YQ.js.map → chunk-6D7PZKCJ.js.map} +0 -0
- /package/dist/{chunk-BBHFAVMP.js.map → chunk-6F2UMP4H.js.map} +0 -0
- /package/dist/{chunk-IIPJKCZB.js.map → chunk-6NAPOLRO.js.map} +0 -0
- /package/dist/{chunk-CK3NQUSQ.js.map → chunk-6UZR7KEK.js.map} +0 -0
- /package/dist/{chunk-2TYIAKU5.js.map → chunk-6YMEU6OQ.js.map} +0 -0
- /package/dist/{chunk-H23GIXJC.js.map → chunk-A73QHOZP.js.map} +0 -0
- /package/dist/{chunk-LLGDVG52.js.map → chunk-AJSZ2EK6.js.map} +0 -0
- /package/dist/{chunk-HVKMJAEF.js.map → chunk-B2OOJCUX.js.map} +0 -0
- /package/dist/{chunk-YTHQHH5U.js.map → chunk-C6WMSXCJ.js.map} +0 -0
- /package/dist/{chunk-JKW663ZN.js.map → chunk-CIAI24TQ.js.map} +0 -0
- /package/dist/{chunk-EFWHCTYJ.js.map → chunk-DNRTKO2U.js.map} +0 -0
- /package/dist/{chunk-4IZ2IT7D.js.map → chunk-EJLTNPRY.js.map} +0 -0
- /package/dist/{chunk-JCJGYNIS.js.map → chunk-EJQXDKYK.js.map} +0 -0
- /package/dist/{chunk-347ZR6D4.js.map → chunk-FKJVEW6O.js.map} +0 -0
- /package/dist/{chunk-DROAPP6N.js.map → chunk-GFNS3BHV.js.map} +0 -0
- /package/dist/{chunk-ALNZEWGN.js.map → chunk-GPFZFCRN.js.map} +0 -0
- /package/dist/{chunk-KPML4Q3M.js.map → chunk-GTRGH4ZT.js.map} +0 -0
- /package/dist/{chunk-TIRJV2LW.js.map → chunk-I6OQCT3Y.js.map} +0 -0
- /package/dist/{chunk-CH627RRV.js.map → chunk-IKXUG6KC.js.map} +0 -0
- /package/dist/{chunk-HSBQJRV2.js.map → chunk-IM56VPKO.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-IPLYGWQF.js.map} +0 -0
- /package/dist/{chunk-BP6WMYLP.js.map → chunk-ITYAXU4S.js.map} +0 -0
- /package/dist/{chunk-4FFROSFG.js.map → chunk-JJ7JW62R.js.map} +0 -0
- /package/dist/{chunk-RFH7U5LT.js.map → chunk-JJX5XEIG.js.map} +0 -0
- /package/dist/{chunk-CALURYWR.js.map → chunk-JWPG65LH.js.map} +0 -0
- /package/dist/{chunk-G2FCSILA.js.map → chunk-KWIGDKM2.js.map} +0 -0
- /package/dist/{chunk-WR2YKUIW.js.map → chunk-KWN6NOHQ.js.map} +0 -0
- /package/dist/{chunk-227UFSEQ.js.map → chunk-LEPOP46W.js.map} +0 -0
- /package/dist/{chunk-WMOJIOIG.js.map → chunk-LZCSOUJ7.js.map} +0 -0
- /package/dist/{chunk-256FBCVX.js.map → chunk-M4AHBM72.js.map} +0 -0
- /package/dist/{chunk-5PFGMO33.js.map → chunk-MEW53VQJ.js.map} +0 -0
- /package/dist/{chunk-DCUMFQYM.js.map → chunk-ML3U4KPR.js.map} +0 -0
- /package/dist/{chunk-X6E7TT3A.js.map → chunk-MR5HWQHS.js.map} +0 -0
- /package/dist/{chunk-H7PRHUBD.js.map → chunk-NRLELHAY.js.map} +0 -0
- /package/dist/{chunk-ZS4JADYY.js.map → chunk-OW7NVMGQ.js.map} +0 -0
- /package/dist/{chunk-TGSMU3F2.js.map → chunk-PADG72LJ.js.map} +0 -0
- /package/dist/{chunk-UDTME32W.js.map → chunk-Q35XGIEM.js.map} +0 -0
- /package/dist/{chunk-AYIHDC5S.js.map → chunk-QSIQVC32.js.map} +0 -0
- /package/dist/{chunk-3MA7JVXN.js.map → chunk-R74NCKEY.js.map} +0 -0
- /package/dist/{chunk-QCI73Z7C.js.map → chunk-RYGJGXL6.js.map} +0 -0
- /package/dist/{chunk-4OW2T32G.js.map → chunk-SQ3EGGII.js.map} +0 -0
- /package/dist/{chunk-ZPGHA7EO.js.map → chunk-TRPX6F2G.js.map} +0 -0
- /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
- /package/dist/{chunk-7BJYTX6Q.js.map → chunk-VAMQU4W7.js.map} +0 -0
- /package/dist/{chunk-YSR3DXGC.js.map → chunk-VN7IIQGS.js.map} +0 -0
- /package/dist/{chunk-DTLF2SLZ.js.map → chunk-WDUG2CH3.js.map} +0 -0
- /package/dist/{chunk-YIIC5IDU.js.map → chunk-X4MGNVOO.js.map} +0 -0
- /package/dist/{chunk-BHO6RHE5.js.map → chunk-XFCQIQQU.js.map} +0 -0
- /package/dist/{chunk-PSNN25DW.js.map → chunk-XZPSBGHA.js.map} +0 -0
- /package/dist/{chunk-PMRUMGK6.js.map → chunk-Y7COCXY2.js.map} +0 -0
- /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
- /package/dist/{chunk-JFLKSD5V.js.map → chunk-Z334TJRB.js.map} +0 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-script closed-class cue tables and script-agnostic signal helpers
|
|
3
|
+
* shared by the recall planner heuristics (issue #2191).
|
|
4
|
+
*
|
|
5
|
+
* English keyword regexes stay in their consumers. These tables seed the
|
|
6
|
+
* top ~10 languages so non-English prompts route to the same recall modes
|
|
7
|
+
* as their English equivalents. Substring cues are curated so pure-ASCII
|
|
8
|
+
* entries are multi-word phrases (or non-English single words) that cannot
|
|
9
|
+
* occur in English text — the English corpus behavior is unchanged.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const ASCII_CHARS = /[\u0000-\u007f]/g;
|
|
13
|
+
const LETTER_RE = /\p{L}/u;
|
|
14
|
+
const WORDISH_RE = /[\p{L}\p{N}]/u;
|
|
15
|
+
const QUESTION_MARK_END_RE = /[??؟]$/u;
|
|
16
|
+
const COLON_TERMINATED_RE = /[::]\s*$/u;
|
|
17
|
+
|
|
18
|
+
/** True when the text contains a letter outside ASCII — the English keyword
|
|
19
|
+
* tables cannot be assumed to apply. */
|
|
20
|
+
export function hasNonAsciiLetter(text: string): boolean {
|
|
21
|
+
return LETTER_RE.test(text.replace(ASCII_CHARS, ""));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Strip trailing punctuation/symbols/emojis (Unicode-aware) so exact-match
|
|
25
|
+
* ack detection works for "はい。", "merci !", "شكرا" etc. */
|
|
26
|
+
export function stripTrailingRecallNoise(text: string): string {
|
|
27
|
+
let candidate = text;
|
|
28
|
+
while (candidate.length > 0) {
|
|
29
|
+
const last = candidate.at(-1) ?? "";
|
|
30
|
+
if (WORDISH_RE.test(last)) break;
|
|
31
|
+
candidate = candidate.slice(0, -1);
|
|
32
|
+
}
|
|
33
|
+
return candidate.trim();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** True when the text ends with an ASCII, fullwidth, or Arabic question mark. */
|
|
37
|
+
export function endsWithQuestionMark(text: string): boolean {
|
|
38
|
+
return QUESTION_MARK_END_RE.test(text.trimEnd());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function containsRecallCue(text: string, cues: readonly string[]): boolean {
|
|
42
|
+
const normalized = text.toLowerCase();
|
|
43
|
+
return cues.some((cue) => normalized.includes(cue));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Exact-match acknowledgements (lowercased, trailing noise stripped).
|
|
47
|
+
const ACK_CANDIDATES = new Set([
|
|
48
|
+
// English (membership identical to the previous regex alternation)
|
|
49
|
+
"ok", "okay", "kk", "thanks", "thx", "got it", "sounds good", "yep", "yes",
|
|
50
|
+
"nope", "no", "done", "cool", "works",
|
|
51
|
+
// Japanese
|
|
52
|
+
"はい", "うん", "わかった", "わかりました", "了解", "承知", "ありがとう",
|
|
53
|
+
"どうも", "おけー", "オッケー", "りょうかい",
|
|
54
|
+
// Chinese
|
|
55
|
+
"好", "好的", "嗯", "对", "行", "可以", "收到", "明白", "明白了", "知道了",
|
|
56
|
+
"谢谢", "没问题",
|
|
57
|
+
// Korean
|
|
58
|
+
"네", "응", "알겠어", "알겠습니다", "고마워", "감사합니다", "좋아",
|
|
59
|
+
// Spanish
|
|
60
|
+
"sí", "si", "gracias", "vale", "de acuerdo", "perfecto", "claro", "listo",
|
|
61
|
+
// French
|
|
62
|
+
"oui", "merci", "d'accord", "bien", "parfait", "compris", "ça marche",
|
|
63
|
+
// German
|
|
64
|
+
"ja", "danke", "gut", "verstanden", "alles klar", "passt", "einverstanden",
|
|
65
|
+
// Portuguese
|
|
66
|
+
"sim", "obrigado", "obrigada", "certo", "combinado", "beleza",
|
|
67
|
+
// Russian
|
|
68
|
+
"да", "спасибо", "ок", "хорошо", "понял", "поняла", "ясно", "угу", "принято",
|
|
69
|
+
// Arabic
|
|
70
|
+
"نعم", "شكرا", "حسنا", "تمام", "طيب", "موافق", "أوكي",
|
|
71
|
+
// Hindi
|
|
72
|
+
"हाँ", "ठीक", "अच्छा", "धन्यवाद", "समझ गया", "मंज़ूर",
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
export function isMultilingualAck(candidate: string): boolean {
|
|
76
|
+
return ACK_CANDIDATES.has(candidate.trim().toLowerCase());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Timeline / sequence / what-happened cues → graph_mode parity.
|
|
80
|
+
export const GRAPH_MODE_CUES: readonly string[] = [
|
|
81
|
+
// Japanese
|
|
82
|
+
"タイムライン", "時系列", "時の流れ", "順序", "経緯", "変遷", "何があった", "どうなった",
|
|
83
|
+
// Chinese
|
|
84
|
+
"时间线", "时间轴", "时间顺序", "先后顺序", "来龙去脉", "变迁", "发生了什么", "怎么演变",
|
|
85
|
+
// Korean
|
|
86
|
+
"타임라인", "시간순", "경위", "변천", "무슨 일이 있었", "어떻게 됐", "어떻게 변했",
|
|
87
|
+
// Spanish
|
|
88
|
+
"línea de tiempo", "cronología", "cronologia", "qué pasó", "qué ocurrió", "historial",
|
|
89
|
+
// French
|
|
90
|
+
"chronologie", "frise chronologique", "qu'est-il passé", "historique",
|
|
91
|
+
// German
|
|
92
|
+
"zeitleiste", "abfolge", "ereignisfolge", "was ist passiert", "verlauf",
|
|
93
|
+
// Portuguese
|
|
94
|
+
"linha do tempo", "sequência de eventos", "o que aconteceu",
|
|
95
|
+
// Russian
|
|
96
|
+
"хронология", "последовательность событий", "что произошло", "таймлайн",
|
|
97
|
+
// Arabic
|
|
98
|
+
"الجدول الزمني", "التسلسل الزمني", "تسلسل الأحداث", "ماذا حدث",
|
|
99
|
+
// Hindi
|
|
100
|
+
"टाइमलाइन", "कालक्रम", "घटनाक्रम", "क्या हुआ",
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
// Causal-chain cues (broad graph intent).
|
|
104
|
+
export const CAUSAL_CHAIN_CUES: readonly string[] = [
|
|
105
|
+
"原因", "因果", "根本原因", "怎么会",
|
|
106
|
+
"原因は", "なぜそうなった", "因果関係",
|
|
107
|
+
"원인이", "왜 이렇게", "인과",
|
|
108
|
+
"por qué pasó", "causa raíz", "cadena de causas",
|
|
109
|
+
"pourquoi c'est arrivé", "cause racine",
|
|
110
|
+
"wieso ist das passiert", "ursachenkette",
|
|
111
|
+
"por que aconteceu", "cadeia de causas",
|
|
112
|
+
"почему это произошло", "первопричина", "причинно",
|
|
113
|
+
"لماذا حدث هذا", "سلسلة الأسباب",
|
|
114
|
+
"ऐसा क्यों हुआ", "मूल कारण",
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
// Temporal-ordering markers → chronological evidence tier parity.
|
|
118
|
+
export const EVENT_ORDER_CUES: readonly string[] = [
|
|
119
|
+
// Japanese
|
|
120
|
+
"最初", "初めて", "いつ", "何日", "何ヶ月", "何か月", "前に", "後で", "以降",
|
|
121
|
+
"順番", "順に", "前回", "さかのぼ", "最近",
|
|
122
|
+
// Chinese
|
|
123
|
+
"第一", "最早", "最后一次", "上次", "什么时候", "几月", "几天", "几个月",
|
|
124
|
+
"之前", "之后", "顺序", "按时间", "最近",
|
|
125
|
+
// Korean
|
|
126
|
+
"처음", "언제", "며칠", "몇 달", "몇 개월", "전에", "후에", "순서대로", "지난번",
|
|
127
|
+
// Spanish
|
|
128
|
+
"cuándo", "cuando fue", "cuántos días", "cuántos meses", "primero", "última vez",
|
|
129
|
+
"por orden", "orden cronológico",
|
|
130
|
+
// French
|
|
131
|
+
"quand ", "combien de jours", "combien de mois", "la première fois",
|
|
132
|
+
"la dernière fois", "dans l'ordre",
|
|
133
|
+
// German
|
|
134
|
+
"wann ", "wie viele tage", "wie viele monate", "zum ersten", "das letzte mal",
|
|
135
|
+
// Portuguese
|
|
136
|
+
"quando foi", "quantos dias", "quantos meses", "primeira vez", "última vez",
|
|
137
|
+
// Russian
|
|
138
|
+
"когда", "сколько дней", "сколько месяцев", "впервые", "последний раз", "по порядку",
|
|
139
|
+
// Arabic
|
|
140
|
+
"متى", "كم يوم", "كم شهر", "أول مرة", "آخر مرة", "بالترتيب",
|
|
141
|
+
// Hindi
|
|
142
|
+
"कब", "कितने दिन", "कितने महीने", "पहली बार", "आख़िरी बार",
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
// Timing/detail question cues for the response-guidance dates intent.
|
|
146
|
+
export const TIMING_DETAIL_CUES: readonly string[] = [
|
|
147
|
+
"いつ", "日時", "期日", "締め切り", "締切",
|
|
148
|
+
"什么时候", "几点", "日期", "截止",
|
|
149
|
+
"언제", "날짜", "마감",
|
|
150
|
+
"qué día", "qué fecha", "fecha límite", "cuándo",
|
|
151
|
+
"quelle date", "date limite",
|
|
152
|
+
"welches datum", "frist",
|
|
153
|
+
"que dia", "que data", "prazo",
|
|
154
|
+
"какого числа", "дедлайн",
|
|
155
|
+
"تاريخ الموعد", "متى الموعد",
|
|
156
|
+
"तारीख",
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
// Contradiction-resolution cues for the response-guidance tier.
|
|
160
|
+
export const CONTRADICTION_CUES: readonly string[] = [
|
|
161
|
+
"矛盾", "食い違", "前と違う", "一貫して",
|
|
162
|
+
"不一致", "之前说的", "前后矛盾",
|
|
163
|
+
"모순", "일관되",
|
|
164
|
+
"contradice", "inconsistente", "antes dijiste",
|
|
165
|
+
"contredit", "incohérent", "tu avais dit",
|
|
166
|
+
"widerspricht", "widersprüchlich",
|
|
167
|
+
"contradiz",
|
|
168
|
+
"противореч", "непоследовательн",
|
|
169
|
+
"يناقض", "تعارض",
|
|
170
|
+
"विरोधाभास",
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
// Prompt-filler words (recall verbs in other languages) that must not count
|
|
174
|
+
// as content discriminators in the direct-answer gate.
|
|
175
|
+
export const MULTILINGUAL_PROMPT_RECALL_WORDS: readonly string[] = [
|
|
176
|
+
"教えて", "見せて", "探して", "一覧",
|
|
177
|
+
"告诉我", "显示", "查找",
|
|
178
|
+
"보여줘", "알려줘", "찾아줘",
|
|
179
|
+
"muestra", "busca", "encuentra",
|
|
180
|
+
"montre", "cherche",
|
|
181
|
+
"zeige", "suche",
|
|
182
|
+
"покажи",
|
|
183
|
+
"أظهر", "ابحث",
|
|
184
|
+
"दिखाओ", "खोजो",
|
|
185
|
+
];
|
|
186
|
+
|
|
187
|
+
/** Structural heading line for non-Latin scripts: colon-terminated, short,
|
|
188
|
+
* and containing a non-ASCII letter. English prompts are unaffected. */
|
|
189
|
+
export function isNonLatinHeadingLine(line: string): boolean {
|
|
190
|
+
if (line.length > 80) return false;
|
|
191
|
+
if (!COLON_TERMINATED_RE.test(line)) return false;
|
|
192
|
+
return hasNonAsciiLetter(line);
|
|
193
|
+
}
|
|
@@ -6,7 +6,9 @@ const DEFAULT_RECALL_STOP_WORDS = ["the", "and", "for", "with", "from", "into",
|
|
|
6
6
|
|
|
7
7
|
export function isUnsegmentableRecallChar(char: string): boolean {
|
|
8
8
|
if (char === "ー" || char === "ー") return true;
|
|
9
|
-
return /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u.test(
|
|
9
|
+
return /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Thai}\p{Script=Khmer}\p{Script=Lao}\p{Script=Myanmar}]/u.test(
|
|
10
|
+
char,
|
|
11
|
+
);
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
function isRecallCombiningMark(char: string): boolean {
|
package/src/retrieval-agents.ts
CHANGED
|
@@ -24,6 +24,8 @@ import type { QmdSearchResult } from "./types.js";
|
|
|
24
24
|
import type { QmdClient } from "./qmd.js";
|
|
25
25
|
import { isTemporalQuery, recencyWindowBoundsFromPrompt } from "./temporal-index.js";
|
|
26
26
|
import { isAbortError } from "./abort-error.js";
|
|
27
|
+
import { normalizeRecallTokens } from "./recall-tokenization.js";
|
|
28
|
+
|
|
27
29
|
|
|
28
30
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
29
31
|
|
|
@@ -56,10 +58,9 @@ export function shouldRunAgent(
|
|
|
56
58
|
): boolean {
|
|
57
59
|
switch (agent) {
|
|
58
60
|
case "direct":
|
|
59
|
-
// Skip only if query has no
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
return knownEntityCount > 0 || /\b\w{2,}/.test(query);
|
|
61
|
+
// Skip only if the query has no letter/number tokens. `\w` and `\b` are
|
|
62
|
+
// ASCII-only, so CJK entity names would never start the direct agent.
|
|
63
|
+
return knownEntityCount > 0 || /[\p{L}\p{N}]{2,}/u.test(query);
|
|
63
64
|
case "temporal":
|
|
64
65
|
// Only run temporal agent when the query actually asks about a time window.
|
|
65
66
|
// Running it for every query injects recency bias into semantic searches.
|
|
@@ -74,12 +75,7 @@ export function shouldRunAgent(
|
|
|
74
75
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
75
76
|
|
|
76
77
|
function tokenize(value: string): string[] {
|
|
77
|
-
return value
|
|
78
|
-
.toLowerCase()
|
|
79
|
-
.replace(/[^a-z0-9]+/g, " ")
|
|
80
|
-
.trim()
|
|
81
|
-
.split(/\s+/)
|
|
82
|
-
.filter((t) => t.length >= 2);
|
|
78
|
+
return normalizeRecallTokens(value).filter((t) => t.length >= 2);
|
|
83
79
|
}
|
|
84
80
|
|
|
85
81
|
function overlapScore(queryTokens: string[], candidateTokens: string[]): number {
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { ConsolidationResultSchema, ExtractionResultSchema } from "./schemas.js";
|
|
5
|
+
|
|
6
|
+
// Synthetic fixtures only — no real memory content (public repo).
|
|
7
|
+
const validFact = {
|
|
8
|
+
category: "fact",
|
|
9
|
+
content: "The API rate limit is 1000 requests per minute.",
|
|
10
|
+
confidence: 0.8,
|
|
11
|
+
tags: ["api"],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const validEntity = {
|
|
15
|
+
name: "acme-corp",
|
|
16
|
+
type: "company",
|
|
17
|
+
facts: ["Uses PostgreSQL for the main database."],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const validQuestion = {
|
|
21
|
+
question: "Which service enforces the rate limit?",
|
|
22
|
+
context: "The limit shape suggests an upstream gateway.",
|
|
23
|
+
priority: 0.4,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const validRelationship = {
|
|
27
|
+
source: "person-jane-doe",
|
|
28
|
+
target: "acme-corp",
|
|
29
|
+
label: "works at",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function baseResult() {
|
|
33
|
+
return {
|
|
34
|
+
facts: [validFact],
|
|
35
|
+
profileUpdates: ["Prefers concise status updates."],
|
|
36
|
+
entities: [validEntity],
|
|
37
|
+
questions: [validQuestion],
|
|
38
|
+
relationships: [validRelationship],
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
test("ExtractionResultSchema salvages valid facts from a mixed-invalid array (#2455)", () => {
|
|
43
|
+
const parsed = ExtractionResultSchema.safeParse({
|
|
44
|
+
...baseResult(),
|
|
45
|
+
facts: [
|
|
46
|
+
validFact,
|
|
47
|
+
{ category: "not-a-category", content: "x", confidence: 0.5, tags: [] },
|
|
48
|
+
{ category: "fact", content: "missing confidence", tags: [] },
|
|
49
|
+
// procedure facts without steps fail the superRefine — salvage must
|
|
50
|
+
// respect refinement issues, not just base-shape issues
|
|
51
|
+
{ category: "procedure", content: "Deploy the service.", confidence: 0.9, tags: ["deploy"] },
|
|
52
|
+
"bare string is not a fact",
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
assert.equal(parsed.success, true);
|
|
57
|
+
assert.deepEqual(parsed.data?.facts, [validFact]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("ExtractionResultSchema fails when a non-empty facts array is wholly invalid (#2455)", () => {
|
|
61
|
+
const parsed = ExtractionResultSchema.safeParse({
|
|
62
|
+
...baseResult(),
|
|
63
|
+
facts: [
|
|
64
|
+
{ category: "not-a-category", content: "x", confidence: 0.5, tags: [] },
|
|
65
|
+
42,
|
|
66
|
+
],
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
assert.equal(parsed.success, false);
|
|
70
|
+
assert.ok(
|
|
71
|
+
parsed.error.issues.some((issue) => issue.message.includes("no items matching the schema")),
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("ExtractionResultSchema keeps explicitly empty arrays valid (#2455)", () => {
|
|
76
|
+
const parsed = ExtractionResultSchema.safeParse({
|
|
77
|
+
facts: [],
|
|
78
|
+
profileUpdates: [],
|
|
79
|
+
entities: [],
|
|
80
|
+
questions: [],
|
|
81
|
+
relationships: [],
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
assert.equal(parsed.success, true);
|
|
85
|
+
assert.deepEqual(parsed.data?.facts, []);
|
|
86
|
+
assert.deepEqual(parsed.data?.questions, []);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("ExtractionResultSchema salvages valid entities from a mixed-invalid array (#2455)", () => {
|
|
90
|
+
const parsed = ExtractionResultSchema.safeParse({
|
|
91
|
+
...baseResult(),
|
|
92
|
+
entities: [
|
|
93
|
+
validEntity,
|
|
94
|
+
{ name: "bad-type", type: "organization", facts: ["nope"] },
|
|
95
|
+
{ name: "bad-facts", type: "person", facts: [17] },
|
|
96
|
+
null,
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
assert.equal(parsed.success, true);
|
|
101
|
+
assert.deepEqual(parsed.data?.entities, [validEntity]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("ExtractionResultSchema fails when a non-empty entities array is wholly invalid (#2455)", () => {
|
|
105
|
+
const parsed = ExtractionResultSchema.safeParse({
|
|
106
|
+
...baseResult(),
|
|
107
|
+
entities: [{ name: "bad-type", type: "organization", facts: ["nope"] }],
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
assert.equal(parsed.success, false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("ExtractionResultSchema salvages valid questions from a mixed-invalid array (#2455)", () => {
|
|
114
|
+
const parsed = ExtractionResultSchema.safeParse({
|
|
115
|
+
...baseResult(),
|
|
116
|
+
questions: [
|
|
117
|
+
validQuestion,
|
|
118
|
+
{ question: "no context", priority: 0.3 },
|
|
119
|
+
{ question: "bad priority", context: "out of range", priority: 5 },
|
|
120
|
+
],
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
assert.equal(parsed.success, true);
|
|
124
|
+
assert.deepEqual(parsed.data?.questions, [validQuestion]);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("ExtractionResultSchema salvages valid profileUpdates and relationships (#2455)", () => {
|
|
128
|
+
const parsed = ExtractionResultSchema.safeParse({
|
|
129
|
+
...baseResult(),
|
|
130
|
+
profileUpdates: ["Prefers concise status updates.", 42, null],
|
|
131
|
+
relationships: [validRelationship, { source: "jane-doe", label: "missing target" }],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
assert.equal(parsed.success, true);
|
|
135
|
+
assert.deepEqual(parsed.data?.profileUpdates, ["Prefers concise status updates."]);
|
|
136
|
+
assert.deepEqual(parsed.data?.relationships, [validRelationship]);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("ExtractionResultSchema still accepts null/omitted relationships (#2455)", () => {
|
|
140
|
+
const nullParsed = ExtractionResultSchema.safeParse({ ...baseResult(), relationships: null });
|
|
141
|
+
assert.equal(nullParsed.success, true);
|
|
142
|
+
|
|
143
|
+
const omitted: Record<string, unknown> = { ...baseResult() };
|
|
144
|
+
delete omitted.relationships;
|
|
145
|
+
const omittedParsed = ExtractionResultSchema.safeParse(omitted);
|
|
146
|
+
assert.equal(omittedParsed.success, true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("ConsolidationResultSchema stays strict on mixed-invalid arrays (#2455)", () => {
|
|
150
|
+
const validItem = { existingId: "fact-1", action: "SKIP", reason: "still accurate" };
|
|
151
|
+
const parsed = ConsolidationResultSchema.safeParse({
|
|
152
|
+
items: [validItem, { existingId: "fact-2", action: "DESTROY", reason: "bad enum" }],
|
|
153
|
+
profileUpdates: [],
|
|
154
|
+
entityUpdates: [],
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
assert.equal(parsed.success, false);
|
|
158
|
+
});
|
package/src/schemas.ts
CHANGED
|
@@ -278,27 +278,51 @@ export const ProactiveExtractionResultSchema = z.object({
|
|
|
278
278
|
),
|
|
279
279
|
});
|
|
280
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Salvage array for model-produced extraction output (issue #2455).
|
|
283
|
+
*
|
|
284
|
+
* Mixed valid+invalid items parse to the valid subset so one malformed
|
|
285
|
+
* element no longer discards the whole extraction. A non-empty array with
|
|
286
|
+
* zero valid items still fails, so bounded retry stays effective and wholly
|
|
287
|
+
* malformed output is never silently accepted as empty. Empty arrays stay
|
|
288
|
+
* valid. Consolidation schemas intentionally stay strict — do not use this
|
|
289
|
+
* for them.
|
|
290
|
+
*/
|
|
291
|
+
function salvageArray<T extends z.ZodTypeAny>(itemSchema: T) {
|
|
292
|
+
return z
|
|
293
|
+
.array(z.unknown())
|
|
294
|
+
.transform((items, ctx) => {
|
|
295
|
+
const valid: z.infer<T>[] = [];
|
|
296
|
+
for (const raw of items) {
|
|
297
|
+
const parsed = itemSchema.safeParse(raw);
|
|
298
|
+
if (parsed.success) {
|
|
299
|
+
valid.push(parsed.data);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (items.length > 0 && valid.length === 0) {
|
|
303
|
+
ctx.addIssue({
|
|
304
|
+
code: z.ZodIssueCode.custom,
|
|
305
|
+
message: "array contains no items matching the schema",
|
|
306
|
+
});
|
|
307
|
+
return z.NEVER;
|
|
308
|
+
}
|
|
309
|
+
return valid;
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
281
313
|
export const ExtractionResultSchema = z.object({
|
|
282
|
-
facts:
|
|
283
|
-
.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
.describe(
|
|
295
|
-
"Entities mentioned in the conversation with new facts about them.",
|
|
296
|
-
),
|
|
297
|
-
questions: z
|
|
298
|
-
.array(ExtractedQuestionSchema)
|
|
299
|
-
.describe(
|
|
300
|
-
"Zero to three source-grounded questions useful in future sessions. Return an empty array when the conversation supports none.",
|
|
301
|
-
),
|
|
314
|
+
facts: salvageArray(ExtractedFactSchema).describe(
|
|
315
|
+
"Extracted memories from the conversation. Include facts, preferences, corrections, and decisions. Only extract genuinely new, durable information — skip transient task state.",
|
|
316
|
+
),
|
|
317
|
+
profileUpdates: salvageArray(z.string()).describe(
|
|
318
|
+
"Updates to the user's behavioral profile. Each string is a standalone statement about the user's preferences, habits, or personality. Only include genuinely new insights.",
|
|
319
|
+
),
|
|
320
|
+
entities: salvageArray(EntityMentionSchema).describe(
|
|
321
|
+
"Entities mentioned in the conversation with new facts about them.",
|
|
322
|
+
),
|
|
323
|
+
questions: salvageArray(ExtractedQuestionSchema).describe(
|
|
324
|
+
"Zero to three source-grounded questions useful in future sessions. Return an empty array when the conversation supports none.",
|
|
325
|
+
),
|
|
302
326
|
identityReflection: z
|
|
303
327
|
.string()
|
|
304
328
|
.optional()
|
|
@@ -311,8 +335,7 @@ export const ExtractionResultSchema = z.object({
|
|
|
311
335
|
.optional()
|
|
312
336
|
.nullable()
|
|
313
337
|
.describe("A six-to-eight word title for this conversation segment."),
|
|
314
|
-
relationships:
|
|
315
|
-
.array(ExtractedRelationshipSchema)
|
|
338
|
+
relationships: salvageArray(ExtractedRelationshipSchema)
|
|
316
339
|
.optional()
|
|
317
340
|
.nullable()
|
|
318
341
|
.describe(
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/direct-answer.ts"],"sourcesContent":["/**\n * Direct-answer retrieval tier eligibility (issue #518 slice 2).\n *\n * This module is a pure decision layer. It takes a query, a set of\n * caller-resolved candidates (each already decorated with trust-zone,\n * taxonomy-bucket, and importance information), and the direct-answer\n * config, then returns an eligibility verdict.\n *\n * Keeping the module pure means:\n *\n * - Tests do not need a trust-zones store, taxonomy resolver, or importance\n * scorer on disk.\n * - Slice 3 (retrieval.ts wiring) is responsible for resolving those signals\n * before calling in; the wiring layer decides where candidates come from\n * (entity index, token prefilter, etc.). This module only decides\n * whether the surfaced candidates add up to a confident direct answer.\n *\n * Not wired into retrieval yet — see slice 3.\n */\n\nimport { normalizeRecallTokenSet, normalizeRecallTokens } from \"./recall-tokenization.js\";\nimport type { TrustZoneName } from \"./trust-zones.js\";\nimport type { MemoryFile, MemoryStatus } from \"./types.js\";\n\n/**\n * Caller-supplied candidate.\n *\n * `trustZone`, `taxonomyBucket`, and `importanceScore` are resolved outside\n * this module because each comes from a different subsystem. Passing them\n * as inputs keeps the function deterministic and easy to unit-test.\n *\n * `matchScore` is optional; if omitted, candidates are ranked by\n * token-overlap ratio. Callers that already computed a better ranking\n * score (e.g. BM25, vector similarity) can supply it to drive the\n * ambiguity check.\n */\nexport interface DirectAnswerCandidate {\n memory: MemoryFile;\n trustZone: TrustZoneName | null;\n taxonomyBucket: string | null;\n importanceScore: number;\n matchScore?: number;\n}\n\nexport interface DirectAnswerConfig {\n enabled: boolean;\n tokenOverlapFloor: number;\n importanceFloor: number;\n ambiguityMargin: number;\n eligibleTaxonomyBuckets: string[];\n}\n\nexport interface DirectAnswerInput {\n query: string;\n candidates: DirectAnswerCandidate[];\n config: DirectAnswerConfig;\n /**\n * Optional entity-ref hints resolved from the query upstream. When\n * supplied, a candidate with a set `entityRef` must match one of these\n * (case-insensitive) to remain eligible. Candidates without an\n * `entityRef` are allowed through regardless.\n */\n queryEntityRefs?: string[];\n}\n\nexport type DirectAnswerReason =\n | \"disabled\"\n | \"empty-query\"\n | \"no-candidates\"\n | \"no-eligible-candidates\"\n | \"below-token-overlap-floor\"\n | \"ambiguous\"\n | \"eligible\";\n\nexport interface DirectAnswerResult {\n eligible: boolean;\n reason: DirectAnswerReason;\n /** Winning candidate when eligible. */\n winner?: DirectAnswerCandidate;\n /** Computed token-overlap ratio (0..1) of the winner. */\n tokenOverlap?: number;\n /**\n * Human-readable summary suitable for\n * `RecallTierExplain.tierReason`.\n */\n narrative: string;\n /**\n * Filter labels that eliminated at least one candidate along the way.\n * Populated regardless of eligibility so the caller can surface the\n * narrowing steps in `RecallTierExplain.filteredBy`.\n */\n filteredBy: string[];\n}\n\n/** Filter labels — exported so callers and tests can match them structurally. */\nexport const FILTER_LABELS = {\n nonActiveStatus: \"non-active-status\",\n notTrustedZone: \"not-trusted-zone\",\n ineligibleTaxonomyBucket: \"ineligible-taxonomy-bucket\",\n belowImportanceFloor: \"below-importance-floor\",\n entityRefMismatch: \"entity-ref-mismatch\",\n belowTokenOverlapFloor: \"below-token-overlap-floor\",\n} as const;\n\nconst PROMPT_RECALL_WORDS = new Set([\n \"what\",\n \"who\",\n \"where\",\n \"when\",\n \"why\",\n \"how\",\n \"is\",\n \"are\",\n \"was\",\n \"were\",\n \"do\",\n \"does\",\n \"did\",\n \"find\",\n \"get\",\n \"show\",\n \"search\",\n \"lookup\",\n \"recall\",\n \"remember\",\n \"list\",\n \"status\",\n \"include\",\n \"tell\",\n \"me\",\n \"give\",\n \"about\",\n \"please\",\n \"the\",\n \"and\",\n \"for\",\n \"with\",\n \"from\",\n \"into\",\n \"that\",\n \"this\",\n \"найди\",\n \"найти\",\n \"поиск\",\n \"покажи\",\n \"статус\",\n \"включи\",\n]);\n\ninterface ScoredCandidate {\n candidate: DirectAnswerCandidate;\n tokenOverlap: number;\n requiredTokenMismatch: boolean;\n}\n\nfunction hasUnsegmentableRecallChar(token: string): boolean {\n if (token.includes(\"ー\") || token.includes(\"ー\")) return true;\n return /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}]/u.test(token);\n}\n\nfunction requiredCjkPhraseTokens(query: string): string[] {\n const phrases = new Set<string>();\n let segment = \"\";\n\n const addPhrase = (phrase: string) => {\n if ([...phrase].length >= 4) {\n phrases.add(phrase);\n }\n };\n\n const flushSegment = () => {\n let buffered = \"\";\n for (const run of segment.split(/\\s+/)) {\n if (!run) continue;\n if ([...run].length >= 4) {\n addPhrase(buffered);\n buffered = \"\";\n addPhrase(run);\n continue;\n }\n buffered += run;\n }\n addPhrase(buffered);\n segment = \"\";\n };\n\n for (const ch of query.toLowerCase().normalize(\"NFC\")) {\n if (hasUnsegmentableRecallChar(ch)) {\n segment += ch;\n continue;\n }\n if (/\\p{M}/u.test(ch) && segment.length > 0 && !/\\s$/u.test(segment)) {\n segment += ch;\n continue;\n }\n if (/\\s/u.test(ch)) {\n segment += \" \";\n continue;\n }\n flushSegment();\n }\n flushSegment();\n\n return [...phrases];\n}\n\nfunction requiredMixedScriptTokens(query: string): string[] {\n const required = new Set<string>();\n const parts: string[] = [];\n let segment = \"\";\n\n const flushSegment = () => {\n if (segment) {\n parts.push(segment);\n }\n segment = \"\";\n };\n\n const segmentableRecallTokens = (value: string) => {\n const tokens = new Set<string>();\n let segment = \"\";\n const flushSegmentableSegment = () => {\n for (const token of normalizeRecallTokenSet(segment, [], { minTokenLength: 1 })) {\n tokens.add(token);\n }\n segment = \"\";\n };\n\n for (const ch of value) {\n if (/[\\p{L}\\p{N}]/u.test(ch) && !hasUnsegmentableRecallChar(ch)) {\n segment += ch;\n continue;\n }\n if (/\\p{M}/u.test(ch) && segment.length > 0) {\n segment += ch;\n continue;\n }\n flushSegmentableSegment();\n }\n flushSegmentableSegment();\n return tokens;\n };\n\n const hasRequiredSegmentableToken = (value: string) => {\n return segmentableRecallTokens(value).size > 0;\n };\n\n const hasBoundarySegmentableToken = (value: string) => {\n for (const token of segmentableRecallTokens(value)) {\n if (PROMPT_RECALL_WORDS.has(token)) {\n continue;\n }\n const hasNonAsciiCodepoint = [...token].some((ch) => (ch.codePointAt(0) ?? 0) > 0x7f);\n if (token.length >= 3 || /\\p{N}/u.test(token) || hasNonAsciiCodepoint) {\n return true;\n }\n }\n return false;\n };\n\n const addRequiredTokens = (value: string) => {\n for (const token of normalizeRecallTokenSet(value, [], { minTokenLength: 1 })) {\n required.add(token);\n }\n };\n\n for (const ch of query.toLowerCase().normalize(\"NFC\")) {\n if (/[\\p{L}\\p{N}\\p{M}]/u.test(ch) || hasUnsegmentableRecallChar(ch)) {\n segment += ch;\n continue;\n }\n flushSegment();\n }\n flushSegment();\n\n for (const part of parts) {\n if (hasUnsegmentableRecallChar(part) && hasRequiredSegmentableToken(part)) {\n addRequiredTokens(part);\n }\n }\n\n for (let i = 0; i < parts.length - 1; i += 1) {\n const current = parts[i];\n const next = parts[i + 1];\n const currentHasUnsegmentable = hasUnsegmentableRecallChar(current);\n const nextHasUnsegmentable = hasUnsegmentableRecallChar(next);\n if (currentHasUnsegmentable === nextHasUnsegmentable) {\n continue;\n }\n const segmentablePart = currentHasUnsegmentable ? next : current;\n if (!hasBoundarySegmentableToken(segmentablePart)) {\n continue;\n }\n addRequiredTokens(current);\n addRequiredTokens(next);\n }\n\n for (let i = 1; i < parts.length - 1; i += 1) {\n const prev = parts[i - 1];\n const current = parts[i];\n const next = parts[i + 1];\n if (!hasUnsegmentableRecallChar(prev) || hasUnsegmentableRecallChar(current) || !hasUnsegmentableRecallChar(next)) {\n continue;\n }\n if (!hasRequiredSegmentableToken(current)) {\n continue;\n }\n addRequiredTokens(prev);\n addRequiredTokens(current);\n addRequiredTokens(next);\n }\n\n return [...required];\n}\n\nfunction requiredSegmentableUnicodeTokens(queryTokens: Set<string>): string[] {\n const segmentableTokens = [...queryTokens].filter((token) => !hasUnsegmentableRecallChar(token));\n const hasSegmentableUnicodeToken = segmentableTokens.some((token) =>\n [...token].some((ch) => (ch.codePointAt(0) ?? 0) > 0x7f)\n );\n if (!hasSegmentableUnicodeToken) {\n return [];\n }\n return segmentableTokens.filter((token) => {\n if (PROMPT_RECALL_WORDS.has(token)) {\n return false;\n }\n const hasNonAsciiCodepoint = [...token].some((ch) => (ch.codePointAt(0) ?? 0) > 0x7f);\n if (hasNonAsciiCodepoint) {\n return true;\n }\n if (!/^[a-z0-9]+$/u.test(token)) {\n return false;\n }\n return token.length >= 3 || /\\p{N}/u.test(token);\n });\n}\n\nfunction countTokenOverlap(queryTokens: Set<string>, valueTokens: Set<string>): number {\n let matches = 0;\n for (const token of queryTokens) {\n if (valueTokens.has(token)) matches += 1;\n }\n return matches;\n}\n\n/**\n * Determine whether a query can be served by the direct-answer tier.\n *\n * Decision ladder, in order:\n *\n * 1. config.enabled === false → \"disabled\"\n * 2. empty query tokens → \"empty-query\"\n * 3. empty candidates → \"no-candidates\"\n * 4. hard filters drop all candidates → \"no-eligible-candidates\"\n * 5. token-overlap floor drops all → \"below-token-overlap-floor\"\n * 6. top two candidates within ambiguityMargin → \"ambiguous\"\n * 7. otherwise → \"eligible\"\n */\nexport function isDirectAnswerEligible(input: DirectAnswerInput): DirectAnswerResult {\n const { query, candidates, config, queryEntityRefs } = input;\n\n if (!config.enabled) {\n return {\n eligible: false,\n reason: \"disabled\",\n narrative: \"direct-answer tier is disabled\",\n filteredBy: [],\n };\n }\n\n const queryTokens = new Set(normalizeRecallTokens(query));\n if (queryTokens.size === 0) {\n return {\n eligible: false,\n reason: \"empty-query\",\n narrative: \"query has no searchable tokens after normalization\",\n filteredBy: [],\n };\n }\n\n if (candidates.length === 0) {\n return {\n eligible: false,\n reason: \"no-candidates\",\n narrative: \"no candidates supplied\",\n filteredBy: [],\n };\n }\n\n const filteredBy: string[] = [];\n let working: DirectAnswerCandidate[] = candidates;\n\n working = applyFilter(working, filteredBy, FILTER_LABELS.nonActiveStatus, (c) => {\n const status: MemoryStatus = c.memory.frontmatter.status ?? \"active\";\n return status === \"active\";\n });\n\n working = applyFilter(working, filteredBy, FILTER_LABELS.notTrustedZone, (c) => c.trustZone === \"trusted\");\n\n working = applyFilter(\n working,\n filteredBy,\n FILTER_LABELS.ineligibleTaxonomyBucket,\n (c) => c.taxonomyBucket !== null && config.eligibleTaxonomyBuckets.includes(c.taxonomyBucket)\n );\n\n working = applyFilter(working, filteredBy, FILTER_LABELS.belowImportanceFloor, (c) => {\n if (c.memory.frontmatter.verificationState === \"user_confirmed\") return true;\n return c.importanceScore >= config.importanceFloor;\n });\n\n if (queryEntityRefs && queryEntityRefs.length > 0) {\n const normRefs = new Set(queryEntityRefs.map((r) => r.toLowerCase()));\n working = applyFilter(working, filteredBy, FILTER_LABELS.entityRefMismatch, (c) => {\n const ref = c.memory.frontmatter.entityRef;\n if (!ref) return true;\n return normRefs.has(ref.toLowerCase());\n });\n }\n\n if (working.length === 0) {\n return {\n eligible: false,\n reason: \"no-eligible-candidates\",\n narrative: \"no candidates survived eligibility filters\",\n filteredBy,\n };\n }\n\n const scored: ScoredCandidate[] = working.map((candidate) => {\n const searchable = `${candidate.memory.frontmatter.tags?.join(\" \") ?? \"\"} ${candidate.memory.content}`.trim();\n const searchableTokens = normalizeRecallTokenSet(searchable);\n const requiredSearchableTokens = normalizeRecallTokenSet(searchable, [], { minTokenLength: 1 });\n const requiredPhrases = requiredCjkPhraseTokens(query);\n const requiredMixedTokens = requiredMixedScriptTokens(query);\n const requiredUnicodeTokens = requiredSegmentableUnicodeTokens(queryTokens);\n const hasRequiredPhrase =\n requiredPhrases.length === 0 || requiredPhrases.every((token) => searchableTokens.has(token));\n const hasRequiredMixedTokens =\n requiredMixedTokens.length === 0 || requiredMixedTokens.every((token) => requiredSearchableTokens.has(token));\n const hasRequiredUnicodeTokens =\n requiredUnicodeTokens.length === 0 || requiredUnicodeTokens.every((token) => searchableTokens.has(token));\n const requiredTokenMismatch = !hasRequiredPhrase || !hasRequiredMixedTokens || !hasRequiredUnicodeTokens;\n const matches = requiredTokenMismatch ? 0 : countTokenOverlap(queryTokens, searchableTokens);\n return { candidate, tokenOverlap: matches / queryTokens.size, requiredTokenMismatch };\n });\n\n const overlapSurvivors = scored.filter((s) => !s.requiredTokenMismatch && s.tokenOverlap >= config.tokenOverlapFloor);\n if (overlapSurvivors.length < scored.length) {\n filteredBy.push(FILTER_LABELS.belowTokenOverlapFloor);\n }\n\n if (overlapSurvivors.length === 0) {\n return {\n eligible: false,\n reason: \"below-token-overlap-floor\",\n narrative: `no candidate met token-overlap floor ${config.tokenOverlapFloor}`,\n filteredBy,\n };\n }\n\n overlapSurvivors.sort(compareScored);\n\n if (overlapSurvivors.length >= 2) {\n const topScore = scoreFor(overlapSurvivors[0]);\n const secondScore = scoreFor(overlapSurvivors[1]);\n if (topScore - secondScore < config.ambiguityMargin) {\n return {\n eligible: false,\n reason: \"ambiguous\",\n narrative: `top two candidates within ambiguityMargin ${config.ambiguityMargin}`,\n filteredBy,\n };\n }\n }\n\n const winner = overlapSurvivors[0];\n const bucket = winner.candidate.taxonomyBucket ?? \"unknown\";\n return {\n eligible: true,\n reason: \"eligible\",\n winner: winner.candidate,\n tokenOverlap: winner.tokenOverlap,\n narrative: `trusted ${bucket}, unambiguous, token-overlap ${winner.tokenOverlap.toFixed(2)}`,\n filteredBy,\n };\n}\n\nfunction applyFilter(\n working: DirectAnswerCandidate[],\n filteredBy: string[],\n label: string,\n keep: (c: DirectAnswerCandidate) => boolean\n): DirectAnswerCandidate[] {\n const before = working.length;\n const next = working.filter(keep);\n if (next.length < before) filteredBy.push(label);\n return next;\n}\n\nfunction scoreFor(s: ScoredCandidate): number {\n return s.candidate.matchScore ?? s.tokenOverlap;\n}\n\nfunction compareScored(a: ScoredCandidate, b: ScoredCandidate): number {\n const diff = scoreFor(b) - scoreFor(a);\n if (diff !== 0) return diff;\n // Stable secondary key on path so the comparator returns 0 only for equal\n // entries (CLAUDE.md rule 19).\n return a.candidate.memory.path.localeCompare(b.candidate.memory.path);\n}\n"],"mappings":"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","names":["segment"]}
|