@remnic/core 9.63.9 → 9.63.10
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 -11
- package/dist/access-admin-ops-surface.js +23 -23
- package/dist/access-authorization-probe.d.ts +11 -11
- package/dist/access-authorization-probe.js +24 -24
- package/dist/access-boundary.d.ts +11 -11
- package/dist/access-boundary.js +23 -23
- package/dist/access-cli.js +84 -82
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.d.ts +1 -1
- package/dist/access-extraction-force-flush.d.ts +11 -11
- package/dist/access-extraction-force-flush.js +23 -23
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +11 -11
- package/dist/access-http-lifecycle-flush.d.ts +11 -11
- package/dist/access-http-offline-stream.d.ts +11 -11
- package/dist/access-http-query.d.ts +2 -2
- package/dist/access-http-query.js +25 -25
- package/dist/access-http.d.ts +12 -12
- package/dist/access-http.js +36 -36
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +23 -23
- package/dist/access-lcm-surface.d.ts +11 -11
- package/dist/access-lcm-surface.js +23 -23
- package/dist/access-mcp.d.ts +11 -11
- package/dist/access-mcp.js +30 -30
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-DB0zXFek.d.ts → access-namespace-preflight-CrF0FKaz.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +23 -23
- package/dist/access-observe-write-surface.d.ts +11 -11
- package/dist/access-observe-write-surface.js +23 -23
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-operations-batch.js +25 -25
- package/dist/access-operations.d.ts +11 -11
- package/dist/access-operations.js +29 -29
- package/dist/access-recall-concurrency.d.ts +11 -11
- package/dist/access-recall-concurrency.js +23 -23
- package/dist/access-recall-response.d.ts +11 -11
- package/dist/access-recall-response.js +23 -23
- package/dist/access-recall-surface.d.ts +11 -11
- package/dist/access-recall-surface.js +23 -23
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-DwfdjqkZ.d.ts → access-service-C0AE0jLs.d.ts} +7 -7
- package/dist/access-service-helpers.d.ts +11 -11
- package/dist/access-service.d.ts +11 -11
- package/dist/access-service.js +23 -23
- package/dist/access-surface-catalog.d.ts +11 -11
- package/dist/access-surface-catalog.js +25 -25
- package/dist/access-wearables-meetings-surface.d.ts +3 -3
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/{auto-sync-3SHMZVQS.js → auto-sync-5L7EUZ27.js} +4 -3
- package/dist/{auto-sync-3SHMZVQS.js.map → auto-sync-5L7EUZ27.js.map} +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +9 -9
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +5 -3
- package/dist/briefing.js +11 -9
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-GWVG7LGC.js} +2 -2
- package/dist/{catalog-CCzmf8IH.d.ts → catalog-C0KIwZqR.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +10 -10
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-4POAMKV6.js → chunk-27IOSH2W.js} +5 -2
- package/dist/chunk-27IOSH2W.js.map +1 -0
- package/dist/{chunk-OQIRBGUU.js → chunk-2Q4UAPLD.js} +4 -4
- package/dist/{chunk-3IMYRX3W.js → chunk-34E5NBQI.js} +2 -2
- package/dist/{chunk-BRHKW7GY.js → chunk-4IIDTPSK.js} +2 -2
- package/dist/{chunk-Q5XKKDFQ.js → chunk-5SZ6CLGJ.js} +2 -2
- package/dist/{chunk-VDX2J7OX.js → chunk-5W7CTZ2E.js} +4 -4
- package/dist/{chunk-EUYWQ7TS.js → chunk-652S5A5D.js} +2 -2
- package/dist/{chunk-ULZFZL7K.js → chunk-6IKXAAJI.js} +17 -28
- package/dist/chunk-6IKXAAJI.js.map +1 -0
- package/dist/{chunk-3TDAA7VA.js → chunk-6NMZXEJ7.js} +2 -2
- package/dist/{chunk-ZOAAY2OE.js → chunk-77E7LLMV.js} +7 -7
- package/dist/{chunk-MIUL6AUZ.js → chunk-7ML7STOD.js} +3 -3
- package/dist/{chunk-5SCFDQEJ.js → chunk-BPLPGOUJ.js} +2 -2
- package/dist/{chunk-RWMSMTQP.js → chunk-BS75WJBH.js} +2 -2
- package/dist/{chunk-XE2QCCT2.js → chunk-BTBAHTQ5.js} +2 -2
- package/dist/{chunk-42TIIO2M.js → chunk-BTUIHRRR.js} +2 -2
- package/dist/chunk-CIO7GCWE.js +29 -0
- package/dist/chunk-CIO7GCWE.js.map +1 -0
- package/dist/{chunk-SNEUAZ6B.js → chunk-CK3DZ6OE.js} +2 -2
- package/dist/{chunk-AJRJDXYR.js → chunk-E7MYSCSL.js} +2 -2
- package/dist/{chunk-3T6HIIKA.js → chunk-EHC3FIJ4.js} +2 -2
- package/dist/{chunk-EDZNW3HE.js → chunk-EPRBTGLM.js} +6 -6
- package/dist/{chunk-YTXNDEUS.js → chunk-FEP45MYY.js} +4 -3
- package/dist/{chunk-YTXNDEUS.js.map → chunk-FEP45MYY.js.map} +1 -1
- package/dist/{chunk-KFB4YNXM.js → chunk-G5F4MXXC.js} +2 -2
- package/dist/{chunk-VANZKHTN.js → chunk-G5OB4XZX.js} +4 -4
- package/dist/{chunk-N7V3P4V5.js → chunk-H5VDBZLZ.js} +2 -2
- package/dist/{chunk-645WOU5I.js → chunk-H7BZBSP6.js} +4 -4
- package/dist/{chunk-SZ4HFZKB.js → chunk-HMKPFW7R.js} +2 -2
- package/dist/{chunk-VFZQXYN5.js → chunk-HZXO2CJ6.js} +2 -2
- package/dist/{chunk-KXWE62IH.js → chunk-IOE75NA4.js} +2 -2
- package/dist/{chunk-PQHNZ63P.js → chunk-JJ45UTNT.js} +18 -5
- package/dist/chunk-JJ45UTNT.js.map +1 -0
- package/dist/{chunk-5TF5STAV.js → chunk-K477BTF4.js} +4 -4
- package/dist/{chunk-ML3U4KPR.js → chunk-K547KS3X.js} +4 -4
- package/dist/{chunk-UHGBNIOS.js → chunk-KVDUKH5E.js} +7 -2
- package/dist/chunk-KVDUKH5E.js.map +1 -0
- package/dist/{chunk-XTMYB2HY.js → chunk-LJQGQUNS.js} +2 -2
- package/dist/{chunk-WAS4HV46.js → chunk-LNH76ZJX.js} +87 -3
- package/dist/chunk-LNH76ZJX.js.map +1 -0
- package/dist/{chunk-VYMICVRA.js → chunk-LQNBQEMC.js} +2 -2
- package/dist/{chunk-J6QIAYNR.js → chunk-LVXBC6YB.js} +7 -2
- package/dist/{chunk-J6QIAYNR.js.map → chunk-LVXBC6YB.js.map} +1 -1
- package/dist/{chunk-IVKIODHO.js → chunk-MB6GLPRY.js} +4 -4
- package/dist/{chunk-BPQ7L27U.js → chunk-MIM7QT6H.js} +16 -16
- package/dist/chunk-MKYRCCSN.js +145 -0
- package/dist/chunk-MKYRCCSN.js.map +1 -0
- package/dist/{chunk-WBPD6SBZ.js → chunk-MNI7KB4Q.js} +54 -54
- package/dist/{chunk-6433HV72.js → chunk-MVIYRRVJ.js} +5 -5
- package/dist/{chunk-BXLOS5AJ.js → chunk-OWHERGF2.js} +2 -2
- package/dist/{chunk-QQYHYW2N.js → chunk-PQODT53H.js} +3 -3
- package/dist/{chunk-PHKU6BZ2.js → chunk-R7FQQQ23.js} +2 -2
- package/dist/{chunk-TOP3FSDW.js → chunk-RFFCBYBD.js} +11 -11
- package/dist/{chunk-O52TB5SL.js → chunk-SAWGVTCE.js} +2 -2
- package/dist/{chunk-LTYH2L6E.js → chunk-SILX74CP.js} +9 -9
- package/dist/{chunk-MYI3RKI6.js → chunk-SYU5JOBQ.js} +2 -2
- package/dist/{chunk-SY5JUJ2X.js → chunk-U5XC6DIS.js} +39 -39
- package/dist/{chunk-JXS5PDQ7.js → chunk-UOBPK2OS.js} +25 -7
- package/dist/chunk-UOBPK2OS.js.map +1 -0
- package/dist/{chunk-BOSIHHOH.js → chunk-UUYQWKHO.js} +2 -2
- package/dist/{chunk-DQEMWVMT.js → chunk-UVYI6VIX.js} +1 -1
- package/dist/{chunk-M4AHBM72.js → chunk-VCBG52MM.js} +4 -4
- package/dist/{chunk-62Y5AGCM.js → chunk-VENMDW4U.js} +10 -10
- package/dist/{chunk-6NAPOLRO.js → chunk-VY47VI2T.js} +6 -4
- package/dist/chunk-VY47VI2T.js.map +1 -0
- package/dist/{chunk-QTXNS3HB.js → chunk-WCWIV2JH.js} +2 -2
- package/dist/{chunk-6UKSOXAO.js → chunk-WQ6TRWAE.js} +3 -3
- package/dist/{chunk-CBY54QYW.js → chunk-X6HNXVXS.js} +4 -4
- package/dist/{chunk-DGUVXXAU.js → chunk-XFJUPJD7.js} +2 -2
- package/dist/{chunk-JPWSYHLB.js → chunk-YGSDWO3U.js} +2 -2
- package/dist/{chunk-GBVRVYF4.js → chunk-YINSSARY.js} +1 -1
- package/dist/{chunk-Q6OL23WM.js → chunk-Z4UPRZR6.js} +2 -2
- package/dist/{chunk-4F67JJPG.js → chunk-ZPN7W3OP.js} +2 -2
- package/dist/{cli-kcUqoV4E.d.ts → cli-xoJTOdMQ.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +55 -54
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +9 -9
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +9 -9
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +9 -9
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/contradiction/index.js +4 -4
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +11 -11
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +11 -11
- package/dist/day-summary.d.ts +1 -1
- package/dist/day-summary.js +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-DiY5T63p.d.ts → dependency-propagation-delivery-Cph4PnBe.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer-wiring.js +2 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-origin-fields.d.ts +1 -1
- package/dist/entity-retrieval-i18n.d.ts +34 -0
- package/dist/entity-retrieval-i18n.js +13 -0
- package/dist/entity-retrieval-i18n.js.map +1 -0
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +10 -9
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/event-order-recall.js +2 -2
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/external-wiki-access.d.ts +11 -11
- package/dist/external-wiki-access.js +24 -24
- package/dist/external-wiki-collection-registration.d.ts +1 -1
- package/dist/external-wiki-collection.d.ts +1 -1
- package/dist/external-wiki-mcp-tools.d.ts +11 -11
- package/dist/extraction-error-classification.d.ts +1 -1
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction-liveness.d.ts +1 -1
- package/dist/extraction-normalization.d.ts +1 -1
- package/dist/extraction-prompt.d.ts +1 -1
- package/dist/extraction-source-grounding-helpers.d.ts +10 -1
- package/dist/extraction-source-grounding-helpers.js +3 -1
- package/dist/extraction-source-grounding-rules.d.ts +1 -1
- package/dist/extraction-source-grounding-rules.js +2 -2
- package/dist/extraction-source-grounding.d.ts +1 -1
- package/dist/extraction-source-grounding.js +3 -3
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +18 -18
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-path-reconstruction.d.ts +1 -1
- package/dist/graph-path-scoring.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importance.js +2 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +21 -21
- package/dist/index.js +98 -96
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +4 -4
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +9 -9
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +9 -9
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +10 -10
- package/dist/{maintenance-CaqA4z7V.d.ts → maintenance-BNq31xpo.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +11 -11
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-snapshot.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +10 -10
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +7 -7
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +9 -9
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +12 -12
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +17 -17
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +15 -15
- package/dist/{orchestrator-Bay_AofR.d.ts → orchestrator-CBuUOP2J.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +84 -82
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-X606GdRJ.d.ts → pipeline-CW_Q4WvX.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{public-http-DscQtnCx.d.ts → public-http-DR3sHfwk.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/{qmd-DCKeR-GX.d.ts → qmd-q-cAzYuC.d.ts} +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +1 -1
- package/dist/reconcile/plan.d.ts +1 -1
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/replica-divergence.d.ts +1 -1
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/salvage-envelope.d.ts +1 -1
- package/dist/{scope-profiles-_Y_RHCeE.d.ts → scope-profiles-CIr4mXgp.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +6 -6
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +11 -11
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/orama-backend.js +2 -2
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-DT2VSrU0.d.ts → semantic-consolidation-BZ6J46j-.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +10 -10
- package/dist/semantic-rule-promotion.js +9 -9
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +9 -9
- package/dist/{service-BMo-gwDE.d.ts → service-CCl4iyyY.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +13 -13
- package/dist/{storage-CGzJGUUu.d.ts → storage-BPXmJKIt.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +8 -8
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +14 -14
- package/dist/support-passport/index.js +26 -26
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/topics.js +2 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CBEAYU76.d.ts → types-CltSWcND.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +9 -9
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/briefing.test.ts +50 -0
- package/src/briefing.ts +3 -2
- package/src/chat/chat-engine.test.ts +15 -0
- package/src/chat/chat-engine.ts +13 -2
- package/src/day-summary.test.ts +63 -0
- package/src/day-summary.ts +13 -1
- package/src/entity-retrieval-i18n.test.ts +115 -0
- package/src/entity-retrieval-i18n.ts +161 -0
- package/src/entity-retrieval.ts +34 -34
- package/src/extraction-source-grounding-helpers.ts +112 -2
- package/src/extraction-source-grounding-rules.ts +3 -1
- package/src/extraction-source-grounding.test.ts +52 -0
- package/src/importance.ts +32 -22
- package/src/taxonomy/resolver.ts +7 -7
- package/src/topics.ts +5 -2
- package/src/utils/script-aware-text.ts +52 -0
- package/src/write-classifiers-cjk.test.ts +115 -0
- package/dist/chunk-4POAMKV6.js.map +0 -1
- package/dist/chunk-6NAPOLRO.js.map +0 -1
- package/dist/chunk-JXS5PDQ7.js.map +0 -1
- package/dist/chunk-PQHNZ63P.js.map +0 -1
- package/dist/chunk-UHGBNIOS.js.map +0 -1
- package/dist/chunk-ULZFZL7K.js.map +0 -1
- package/dist/chunk-WAS4HV46.js.map +0 -1
- /package/dist/{capsule-crypto-YO5QJ6L3.js.map → capsule-crypto-GWVG7LGC.js.map} +0 -0
- /package/dist/{chunk-OQIRBGUU.js.map → chunk-2Q4UAPLD.js.map} +0 -0
- /package/dist/{chunk-3IMYRX3W.js.map → chunk-34E5NBQI.js.map} +0 -0
- /package/dist/{chunk-BRHKW7GY.js.map → chunk-4IIDTPSK.js.map} +0 -0
- /package/dist/{chunk-Q5XKKDFQ.js.map → chunk-5SZ6CLGJ.js.map} +0 -0
- /package/dist/{chunk-VDX2J7OX.js.map → chunk-5W7CTZ2E.js.map} +0 -0
- /package/dist/{chunk-EUYWQ7TS.js.map → chunk-652S5A5D.js.map} +0 -0
- /package/dist/{chunk-3TDAA7VA.js.map → chunk-6NMZXEJ7.js.map} +0 -0
- /package/dist/{chunk-ZOAAY2OE.js.map → chunk-77E7LLMV.js.map} +0 -0
- /package/dist/{chunk-MIUL6AUZ.js.map → chunk-7ML7STOD.js.map} +0 -0
- /package/dist/{chunk-5SCFDQEJ.js.map → chunk-BPLPGOUJ.js.map} +0 -0
- /package/dist/{chunk-RWMSMTQP.js.map → chunk-BS75WJBH.js.map} +0 -0
- /package/dist/{chunk-XE2QCCT2.js.map → chunk-BTBAHTQ5.js.map} +0 -0
- /package/dist/{chunk-42TIIO2M.js.map → chunk-BTUIHRRR.js.map} +0 -0
- /package/dist/{chunk-SNEUAZ6B.js.map → chunk-CK3DZ6OE.js.map} +0 -0
- /package/dist/{chunk-AJRJDXYR.js.map → chunk-E7MYSCSL.js.map} +0 -0
- /package/dist/{chunk-3T6HIIKA.js.map → chunk-EHC3FIJ4.js.map} +0 -0
- /package/dist/{chunk-EDZNW3HE.js.map → chunk-EPRBTGLM.js.map} +0 -0
- /package/dist/{chunk-KFB4YNXM.js.map → chunk-G5F4MXXC.js.map} +0 -0
- /package/dist/{chunk-VANZKHTN.js.map → chunk-G5OB4XZX.js.map} +0 -0
- /package/dist/{chunk-N7V3P4V5.js.map → chunk-H5VDBZLZ.js.map} +0 -0
- /package/dist/{chunk-645WOU5I.js.map → chunk-H7BZBSP6.js.map} +0 -0
- /package/dist/{chunk-SZ4HFZKB.js.map → chunk-HMKPFW7R.js.map} +0 -0
- /package/dist/{chunk-VFZQXYN5.js.map → chunk-HZXO2CJ6.js.map} +0 -0
- /package/dist/{chunk-KXWE62IH.js.map → chunk-IOE75NA4.js.map} +0 -0
- /package/dist/{chunk-5TF5STAV.js.map → chunk-K477BTF4.js.map} +0 -0
- /package/dist/{chunk-ML3U4KPR.js.map → chunk-K547KS3X.js.map} +0 -0
- /package/dist/{chunk-XTMYB2HY.js.map → chunk-LJQGQUNS.js.map} +0 -0
- /package/dist/{chunk-VYMICVRA.js.map → chunk-LQNBQEMC.js.map} +0 -0
- /package/dist/{chunk-IVKIODHO.js.map → chunk-MB6GLPRY.js.map} +0 -0
- /package/dist/{chunk-BPQ7L27U.js.map → chunk-MIM7QT6H.js.map} +0 -0
- /package/dist/{chunk-WBPD6SBZ.js.map → chunk-MNI7KB4Q.js.map} +0 -0
- /package/dist/{chunk-6433HV72.js.map → chunk-MVIYRRVJ.js.map} +0 -0
- /package/dist/{chunk-BXLOS5AJ.js.map → chunk-OWHERGF2.js.map} +0 -0
- /package/dist/{chunk-QQYHYW2N.js.map → chunk-PQODT53H.js.map} +0 -0
- /package/dist/{chunk-PHKU6BZ2.js.map → chunk-R7FQQQ23.js.map} +0 -0
- /package/dist/{chunk-TOP3FSDW.js.map → chunk-RFFCBYBD.js.map} +0 -0
- /package/dist/{chunk-O52TB5SL.js.map → chunk-SAWGVTCE.js.map} +0 -0
- /package/dist/{chunk-LTYH2L6E.js.map → chunk-SILX74CP.js.map} +0 -0
- /package/dist/{chunk-MYI3RKI6.js.map → chunk-SYU5JOBQ.js.map} +0 -0
- /package/dist/{chunk-SY5JUJ2X.js.map → chunk-U5XC6DIS.js.map} +0 -0
- /package/dist/{chunk-BOSIHHOH.js.map → chunk-UUYQWKHO.js.map} +0 -0
- /package/dist/{chunk-DQEMWVMT.js.map → chunk-UVYI6VIX.js.map} +0 -0
- /package/dist/{chunk-M4AHBM72.js.map → chunk-VCBG52MM.js.map} +0 -0
- /package/dist/{chunk-62Y5AGCM.js.map → chunk-VENMDW4U.js.map} +0 -0
- /package/dist/{chunk-QTXNS3HB.js.map → chunk-WCWIV2JH.js.map} +0 -0
- /package/dist/{chunk-6UKSOXAO.js.map → chunk-WQ6TRWAE.js.map} +0 -0
- /package/dist/{chunk-CBY54QYW.js.map → chunk-X6HNXVXS.js.map} +0 -0
- /package/dist/{chunk-DGUVXXAU.js.map → chunk-XFJUPJD7.js.map} +0 -0
- /package/dist/{chunk-JPWSYHLB.js.map → chunk-YGSDWO3U.js.map} +0 -0
- /package/dist/{chunk-GBVRVYF4.js.map → chunk-YINSSARY.js.map} +0 -0
- /package/dist/{chunk-Q6OL23WM.js.map → chunk-Z4UPRZR6.js.map} +0 -0
- /package/dist/{chunk-4F67JJPG.js.map → chunk-ZPN7W3OP.js.map} +0 -0
package/src/chat/chat-engine.ts
CHANGED
|
@@ -85,10 +85,21 @@ export interface ChatEngineOptions {
|
|
|
85
85
|
// Confirmation keywords — deterministic, not LLM-interpreted
|
|
86
86
|
// ---------------------------------------------------------------------------
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
// Exact-match confirmations. Unrecognized text keeps the conservative
|
|
89
|
+
// no-apply default, so this stays a small fixed set (issue #2198).
|
|
90
|
+
const CONFIRMATION_KEYWORDS: Record<string, true> = {
|
|
91
|
+
yes: true,
|
|
92
|
+
y: true,
|
|
93
|
+
apply: true,
|
|
94
|
+
confirm: true,
|
|
95
|
+
"はい": true, // Japanese
|
|
96
|
+
"sí": true, // Spanish
|
|
97
|
+
ja: true, // German/Dutch
|
|
98
|
+
"نعم": true, // Arabic
|
|
99
|
+
};
|
|
89
100
|
|
|
90
101
|
export function isConfirmationMessage(text: string): boolean {
|
|
91
|
-
return CONFIRMATION_KEYWORDS
|
|
102
|
+
return CONFIRMATION_KEYWORDS[text.trim().toLowerCase()] === true;
|
|
92
103
|
}
|
|
93
104
|
|
|
94
105
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Day-summary composition tests — bidi isolation of user content (issue #2198).
|
|
3
|
+
* All fixtures are synthetic — no real user data.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import test from "node:test";
|
|
8
|
+
|
|
9
|
+
import { formatDaySummaryMemories } from "./day-summary.js";
|
|
10
|
+
import type { MemoryFile } from "./types.js";
|
|
11
|
+
|
|
12
|
+
const FSI = "\u2068";
|
|
13
|
+
const PDI = "\u2069";
|
|
14
|
+
|
|
15
|
+
function makeMemory(content: string): MemoryFile {
|
|
16
|
+
return {
|
|
17
|
+
path: "/synthetic/mem.md",
|
|
18
|
+
frontmatter: {
|
|
19
|
+
id: "synthetic-mem",
|
|
20
|
+
category: "fact",
|
|
21
|
+
created: "2026-08-17T00:00:00.000Z",
|
|
22
|
+
updated: "2026-08-17T00:00:00.000Z",
|
|
23
|
+
source: "test",
|
|
24
|
+
confidence: 0.9,
|
|
25
|
+
confidenceTier: "explicit",
|
|
26
|
+
tags: [],
|
|
27
|
+
},
|
|
28
|
+
content,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
test("formatDaySummaryMemories wraps RTL content in FSI/PDI isolates (issue #2198)", () => {
|
|
33
|
+
const rtl = makeMemory("اجتماع الفريق غدا في العاشرة");
|
|
34
|
+
const out = formatDaySummaryMemories([rtl]);
|
|
35
|
+
|
|
36
|
+
const expected = `[synthetic-mem] (fact, 2026-08-17T00:00:00.000Z)\n${FSI}اجتماع الفريق غدا في العاشرة${PDI}`;
|
|
37
|
+
assert.equal(out, expected);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("formatDaySummaryMemories isolates LTR content too — labels stay outside the isolate", () => {
|
|
41
|
+
const out = formatDaySummaryMemories([makeMemory("standup at ten")]);
|
|
42
|
+
|
|
43
|
+
assert.ok(out.includes(`${FSI}standup at ten${PDI}`), "content wrapped in FSI/PDI");
|
|
44
|
+
assert.ok(out.startsWith("[synthetic-mem] (fact,"), "Latin label precedes the isolate");
|
|
45
|
+
assert.ok(!out.includes(`${PDI}[`), "label not inside the isolate");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("formatDaySummaryMemories isolates each memory's content independently", () => {
|
|
49
|
+
const out = formatDaySummaryMemories([
|
|
50
|
+
makeMemory("first item"),
|
|
51
|
+
makeMemory("عنصر ثان"),
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
const parts = out.split("\n\n");
|
|
55
|
+
assert.equal(parts.length, 2);
|
|
56
|
+
assert.ok(parts[0]!.includes(`${FSI}first item${PDI}`));
|
|
57
|
+
assert.ok(parts[1]!.includes(`${FSI}عنصر ثان${PDI}`));
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("formatDaySummaryMemories raw-string passthrough is not wrapped", () => {
|
|
61
|
+
const out = formatDaySummaryMemories(" plain string input ");
|
|
62
|
+
assert.equal(out, "plain string input");
|
|
63
|
+
});
|
package/src/day-summary.ts
CHANGED
|
@@ -93,6 +93,18 @@ export async function loadDaySummaryPrompt(): Promise<string> {
|
|
|
93
93
|
return EMBEDDED_DAY_SUMMARY_PROMPT;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
const FSI = "\u2068"; // FIRST STRONG ISOLATE
|
|
97
|
+
const PDI = "\u2069"; // POP DIRECTIONAL ISOLATE
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Wrap user content in Unicode bidi isolates so RTL text (Arabic, Hebrew)
|
|
101
|
+
* cannot reorder the surrounding Latin labels on the same composed line.
|
|
102
|
+
* No visible change for LTR content (issue #2198).
|
|
103
|
+
*/
|
|
104
|
+
function bidiIsolate(text: string): string {
|
|
105
|
+
return `${FSI}${text}${PDI}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
96
108
|
export function formatDaySummaryMemories(memories: string | MemoryFile[]): string {
|
|
97
109
|
if (typeof memories === "string") {
|
|
98
110
|
return memories.trim();
|
|
@@ -102,7 +114,7 @@ export function formatDaySummaryMemories(memories: string | MemoryFile[]): strin
|
|
|
102
114
|
.map((memory) => {
|
|
103
115
|
const category = memory.frontmatter.category || "fact";
|
|
104
116
|
const created = memory.frontmatter.created || "unknown";
|
|
105
|
-
return `[${memory.frontmatter.id}] (${category}, ${created})\n${memory.content}`;
|
|
117
|
+
return `[${memory.frontmatter.id}] (${category}, ${created})\n${bidiIsolate(memory.content)}`;
|
|
106
118
|
})
|
|
107
119
|
.join("\n\n")
|
|
108
120
|
.trim();
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
|
|
7
|
+
import { parseConfig } from "./config.js";
|
|
8
|
+
import { normalizeEntityText } from "./entity-schema.js";
|
|
9
|
+
import { buildEntityRecallSection } from "./entity-retrieval.js";
|
|
10
|
+
import { detectNonEnglishEntityQueryMode } from "./entity-retrieval-i18n.js";
|
|
11
|
+
import { StorageManager } from "./storage.js";
|
|
12
|
+
import type { PluginConfig, TranscriptEntry } from "./types.js";
|
|
13
|
+
|
|
14
|
+
function dialogueTurn(content: string): TranscriptEntry[] {
|
|
15
|
+
return [{
|
|
16
|
+
timestamp: new Date().toISOString(),
|
|
17
|
+
role: "user",
|
|
18
|
+
content,
|
|
19
|
+
sessionKey: "test-session",
|
|
20
|
+
turnId: "test-turn-1",
|
|
21
|
+
}];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function recallBase(
|
|
25
|
+
config: PluginConfig,
|
|
26
|
+
storage: StorageManager,
|
|
27
|
+
transcriptEntries: TranscriptEntry[],
|
|
28
|
+
): Parameters<typeof buildEntityRecallSection>[0] {
|
|
29
|
+
return {
|
|
30
|
+
config,
|
|
31
|
+
storage,
|
|
32
|
+
query: "",
|
|
33
|
+
recentTurns: 2,
|
|
34
|
+
maxHints: 2,
|
|
35
|
+
maxSupportingFacts: 2,
|
|
36
|
+
maxRelatedEntities: 2,
|
|
37
|
+
maxChars: 10_000,
|
|
38
|
+
transcriptEntries,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
test("non-English follow-ups resolve the recently discussed entity like the English pronoun follow-up (#2193)", async () => {
|
|
43
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-entity-i18n-"));
|
|
44
|
+
try {
|
|
45
|
+
const storage = new StorageManager(memoryDir);
|
|
46
|
+
const entityRef = await storage.writeEntity("Alice", "person", []);
|
|
47
|
+
await storage.writeMemory("fact", "Alice leads the platform launch review.", {
|
|
48
|
+
source: "test",
|
|
49
|
+
entityRef,
|
|
50
|
+
});
|
|
51
|
+
const config = parseConfig({
|
|
52
|
+
openaiApiKey: "sk-test",
|
|
53
|
+
memoryDir,
|
|
54
|
+
workspaceDir: path.join(memoryDir, "workspace"),
|
|
55
|
+
});
|
|
56
|
+
const dialogue = dialogueTurn("I spoke with Alice about the launch review yesterday.");
|
|
57
|
+
|
|
58
|
+
// English pronoun follow-up and its Japanese/Chinese equivalents must
|
|
59
|
+
// resolve to the same recently-discussed entity.
|
|
60
|
+
for (const query of ["What about her?", "それで、どうなった?", "彼はどうなった?", "然后呢?"]) {
|
|
61
|
+
const section = await buildEntityRecallSection({
|
|
62
|
+
...recallBase(config, storage, dialogue),
|
|
63
|
+
query,
|
|
64
|
+
});
|
|
65
|
+
assert.ok(section, `expected an entity hint section for query: ${query}`);
|
|
66
|
+
assert.match(section, /alice/i);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Without recent dialogue both decline identically — no entity to carry.
|
|
70
|
+
for (const query of ["What about him?", "それで、どうなった?"]) {
|
|
71
|
+
const section = await buildEntityRecallSection({
|
|
72
|
+
...recallBase(config, storage, []),
|
|
73
|
+
query,
|
|
74
|
+
});
|
|
75
|
+
assert.equal(section, null, `expected no entity section without dialogue: ${query}`);
|
|
76
|
+
}
|
|
77
|
+
} finally {
|
|
78
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("zero-pronoun Japanese follow-up retrieves a CJK entity from a particle-bound mention (#2193)", async () => {
|
|
83
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-entity-i18n-cjk-"));
|
|
84
|
+
try {
|
|
85
|
+
const storage = new StorageManager(memoryDir);
|
|
86
|
+
const entityRef = await storage.writeEntity("田中", "person", []);
|
|
87
|
+
await storage.writeMemory("fact", "田中は来週の発表を準備している。", {
|
|
88
|
+
source: "test",
|
|
89
|
+
entityRef,
|
|
90
|
+
});
|
|
91
|
+
const config = parseConfig({
|
|
92
|
+
openaiApiKey: "sk-test",
|
|
93
|
+
memoryDir,
|
|
94
|
+
workspaceDir: path.join(memoryDir, "workspace"),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
for (const query of ["それで、どうなった?", "彼女はどうなった?"]) {
|
|
98
|
+
const section = await buildEntityRecallSection({
|
|
99
|
+
...recallBase(config, storage, dialogueTurn("田中とは昨日打ち合わせをした。")),
|
|
100
|
+
query,
|
|
101
|
+
});
|
|
102
|
+
assert.ok(section, `expected an entity hint section for query: ${query}`);
|
|
103
|
+
assert.match(section, /田中/);
|
|
104
|
+
}
|
|
105
|
+
} finally {
|
|
106
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("non-English query-mode cue table classification (#2193)", () => {
|
|
111
|
+
assert.equal(detectNonEnglishEntityQueryMode(normalizeEntityText("彼はどうなった")), "follow_up");
|
|
112
|
+
assert.equal(detectNonEnglishEntityQueryMode(normalizeEntityText("¿y ella?")), "follow_up");
|
|
113
|
+
assert.equal(detectNonEnglishEntityQueryMode(normalizeEntityText("田中さんの最近の状況")), "timeline");
|
|
114
|
+
assert.equal(detectNonEnglishEntityQueryMode(normalizeEntityText("了解しました")), null);
|
|
115
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { normalizeEntityText } from "./entity-schema.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Non-English query-mode cues for entity retrieval (#2193).
|
|
5
|
+
*
|
|
6
|
+
* #2161 made explicit entity mentions language-independent, but follow-up /
|
|
7
|
+
* pronoun coreference and timeline phrasing still classify through English
|
|
8
|
+
* word lists in `detectEntityQueryMode`. These cue tables plus the structural
|
|
9
|
+
* follow-up signal below close that gap without building a full coreference
|
|
10
|
+
* engine: the structural layer covers zero-pronoun scripts (Japanese,
|
|
11
|
+
* Chinese, Korean — languages that omit the subject entirely and can never
|
|
12
|
+
* trip a pronoun word list), and the tables add precision for other scripts,
|
|
13
|
+
* including Latin-script languages whose pronoun follow-ups carry their
|
|
14
|
+
* pronoun explicitly. Latin-script queries never use the structural layer:
|
|
15
|
+
* their generic technical questions ("what does this error mean?") are
|
|
16
|
+
* indistinguishable from subject-less follow-ups by shape alone.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export type EntityQueryMode = "direct" | "timeline" | "follow_up";
|
|
20
|
+
|
|
21
|
+
/** Shared short-question bound. Whitespace tokens are a poor length proxy
|
|
22
|
+
* for unspaced scripts, so bound graphemes too (48 graphemes ≈ 8 words). */
|
|
23
|
+
const FOLLOW_UP_MAX_TOKENS = 8;
|
|
24
|
+
const FOLLOW_UP_MAX_GRAPHEMES = 48;
|
|
25
|
+
|
|
26
|
+
/** Latin letters mark a script with explicit pronouns; structural fallback
|
|
27
|
+
* never applies there (English "what does this error mean?" and its
|
|
28
|
+
* relatives keep the technical-question guard in detectEntityQueryMode). */
|
|
29
|
+
const LATIN_LETTER_RE = /\p{Script=Latin}/u;
|
|
30
|
+
|
|
31
|
+
/** Latin / question marks: ASCII `?`, fullwidth `?` (CJK), Arabic `؟`. */
|
|
32
|
+
const QUESTION_MARK_RE = /[??؟]/;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* CJK cues and normalized multi-word phrases match by containment; single
|
|
36
|
+
* Latin/Cyrillic/Arabic words match with a script-agnostic letter boundary
|
|
37
|
+
* so `él` never matches `el` and `il` never matches `famille`.
|
|
38
|
+
*/
|
|
39
|
+
const FOLLOW_UP_CONTAINS_CUES = [
|
|
40
|
+
// ja
|
|
41
|
+
"彼", "彼女", "あの人", "その人", "それで", "ちなみに",
|
|
42
|
+
// zh (simplified + traditional)
|
|
43
|
+
"他", "她", "它", "他们", "她们", "他們", "她們", "然后呢", "然後呢",
|
|
44
|
+
// ko
|
|
45
|
+
"그녀", "그 사람", "걔",
|
|
46
|
+
] as const;
|
|
47
|
+
|
|
48
|
+
const FOLLOW_UP_WORD_CUES = [
|
|
49
|
+
// es
|
|
50
|
+
"él", "ella", "ellos", "ellas",
|
|
51
|
+
// fr
|
|
52
|
+
"elle", "eux",
|
|
53
|
+
// de
|
|
54
|
+
"sie",
|
|
55
|
+
// pt
|
|
56
|
+
"ele", "ela",
|
|
57
|
+
// it
|
|
58
|
+
"lui", "lei",
|
|
59
|
+
// ru
|
|
60
|
+
"он", "она", "они",
|
|
61
|
+
// ar
|
|
62
|
+
"هو", "هي", "هم",
|
|
63
|
+
] as const;
|
|
64
|
+
|
|
65
|
+
const TIMELINE_CONTAINS_CUES = [
|
|
66
|
+
// ja
|
|
67
|
+
"最近", "その後", "どうなった", "何があった",
|
|
68
|
+
// zh (simplified + traditional)
|
|
69
|
+
"怎么样了", "怎麼樣了", "后来", "後來", "最新", "近况", "近況", "什么情况", "什麼情況",
|
|
70
|
+
// ko
|
|
71
|
+
"요즘", "요새", "최근",
|
|
72
|
+
// multi-word phrases, already in normalized form (punctuation → space)
|
|
73
|
+
"qué hay de nuevo", "qué pasó con", "quoi de neuf", "что нового",
|
|
74
|
+
"что случилось", "ما الجديد", "ماذا حدث", "was gibt s neues",
|
|
75
|
+
] as const;
|
|
76
|
+
|
|
77
|
+
function wordCueRegex(cues: readonly string[]): RegExp {
|
|
78
|
+
const alternation = cues
|
|
79
|
+
.map((cue) => cue.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
|
|
80
|
+
.join("|");
|
|
81
|
+
return new RegExp(`(?<![\\p{L}\\p{N}])(?:${alternation})(?![\\p{L}\\p{N}])`, "u");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const FOLLOW_UP_WORD_RE = wordCueRegex(FOLLOW_UP_WORD_CUES);
|
|
85
|
+
|
|
86
|
+
function isShortFollowUpShaped(normalized: string): boolean {
|
|
87
|
+
if (!normalized) return false;
|
|
88
|
+
const tokens = normalized.split(/\s+/).filter(Boolean);
|
|
89
|
+
if (tokens.length > FOLLOW_UP_MAX_TOKENS) return false;
|
|
90
|
+
return Array.from(normalized).length <= FOLLOW_UP_MAX_GRAPHEMES;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Classify already-normalized non-English queries. Returns null when no
|
|
95
|
+
* table cue matches; callers keep their English rules untouched.
|
|
96
|
+
*/
|
|
97
|
+
export function detectNonEnglishEntityQueryMode(normalizedQuery: string): EntityQueryMode | null {
|
|
98
|
+
if (!normalizedQuery) return null;
|
|
99
|
+
if (
|
|
100
|
+
isShortFollowUpShaped(normalizedQuery)
|
|
101
|
+
&& (
|
|
102
|
+
FOLLOW_UP_CONTAINS_CUES.some((cue) => normalizedQuery.includes(cue))
|
|
103
|
+
|| FOLLOW_UP_WORD_RE.test(normalizedQuery)
|
|
104
|
+
)
|
|
105
|
+
) {
|
|
106
|
+
return "follow_up";
|
|
107
|
+
}
|
|
108
|
+
if (TIMELINE_CONTAINS_CUES.some((cue) => normalizedQuery.includes(cue))) {
|
|
109
|
+
return "timeline";
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Structural follow-up signal, independent of pronoun vocabulary: a short
|
|
116
|
+
* question carrying no entity name, asked while recent dialogue exists, is a
|
|
117
|
+
* coreference cue in zero-pronoun scripts (Latin-script queries are excluded
|
|
118
|
+
* above — their follow-ups carry pronouns that the cue tables and English
|
|
119
|
+
* rules classify). Recent-turn candidate resolution (and its empty result →
|
|
120
|
+
* section absent) remains the real gate, so this only routes the query into
|
|
121
|
+
* the follow-up path; it never invents an entity.
|
|
122
|
+
*/
|
|
123
|
+
export function isStructuralEntityFollowUpQuery(query: string, hasRecentDialogue: boolean): boolean {
|
|
124
|
+
if (!hasRecentDialogue) return false;
|
|
125
|
+
if (LATIN_LETTER_RE.test(query)) return false;
|
|
126
|
+
const normalized = normalizeEntityText(query);
|
|
127
|
+
return isShortFollowUpShaped(normalized) && QUESTION_MARK_RE.test(query);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const ENTITY_PRONOUN_RE = /\b(he|him|his|she|her|they|them|their|it|its)\b/i;
|
|
131
|
+
|
|
132
|
+
export function detectEntityQueryMode(query: string): EntityQueryMode | null {
|
|
133
|
+
const normalized = normalizeEntityText(query);
|
|
134
|
+
if (!normalized) return null;
|
|
135
|
+
if (
|
|
136
|
+
/^(what about|and what about|how about|what happened (with|to) (he|him|his|she|her|they|them|their|it|its)|did (he|she|they|it)|is (he|she|they|it)|was (he|she|they|it))\b/.test(normalized)
|
|
137
|
+
) {
|
|
138
|
+
return "follow_up";
|
|
139
|
+
}
|
|
140
|
+
if (
|
|
141
|
+
/^(who is|who s|what do we know about|what does|tell me about|what can you tell me about|what s new with|what happened with|what happened to|status of|where is|how is)\b/.test(normalized)
|
|
142
|
+
) {
|
|
143
|
+
if (/^what does\b/.test(normalized)) {
|
|
144
|
+
if (/^what does (?:this|that|it|the|a|an|my|our|your|their)\b/.test(normalized)) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
if (
|
|
148
|
+
/^what does [a-z0-9-]+ (?:error|warning|exception|failure|stack|trace|code|message|log)\b/.test(normalized)
|
|
149
|
+
&& /\b(mean|means|indicate|indicates|imply|implies)\b/.test(normalized)
|
|
150
|
+
) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return /what happened|what s new|status of|how is|where is/.test(normalized) ? "timeline" : "direct";
|
|
155
|
+
}
|
|
156
|
+
if (ENTITY_PRONOUN_RE.test(normalized) && normalized.split(/\s+/).length <= 8) {
|
|
157
|
+
return "follow_up";
|
|
158
|
+
}
|
|
159
|
+
return detectNonEnglishEntityQueryMode(normalized);
|
|
160
|
+
}
|
|
161
|
+
|
package/src/entity-retrieval.ts
CHANGED
|
@@ -10,6 +10,11 @@ import { normalizeEntityText, resolveRequestedEntitySectionKeys } from "./entity
|
|
|
10
10
|
import type { EntityStructuredSection, MemoryFile, PluginConfig, TranscriptEntry } from "./types.js";
|
|
11
11
|
import { truncateGraphemeSafe } from "./whitespace.js";
|
|
12
12
|
import { containsPhrase } from "./entity-retrieval-boundaries.js";
|
|
13
|
+
import {
|
|
14
|
+
detectEntityQueryMode,
|
|
15
|
+
isStructuralEntityFollowUpQuery,
|
|
16
|
+
type EntityQueryMode,
|
|
17
|
+
} from "./entity-retrieval-i18n.js";
|
|
13
18
|
import { buildOriginStructuredSections, sanitizeOriginatedFacts, type EntityOriginStructuredSection } from "./entity-origin-fields.js";
|
|
14
19
|
import {
|
|
15
20
|
checkEntityRecallAbort,
|
|
@@ -21,10 +26,8 @@ const ENTITY_INDEX_VERSION = 3;
|
|
|
21
26
|
const RECENT_TRANSCRIPT_LOOKBACK_HOURS = 24;
|
|
22
27
|
const INSTRUCTION_LIKE_RE = /\b(always|never|must|should|remember to|do not|don't|process|workflow|template|checklist|instruction)\b/i;
|
|
23
28
|
const METADATA_WRAPPER_RE = /^(source|context|metadata|notes?):/i;
|
|
24
|
-
const ENTITY_PRONOUN_RE = /\b(he|him|his|she|her|they|them|their|it|its)\b/i;
|
|
25
29
|
const BELIEF_LEDGER_SECTION_KEY = "belief_ledger";
|
|
26
30
|
const BELIEF_LEDGER_FACT_RE = /^claim=([^;]+);\s*status=([^;]+);\s*updatedAt=([^;]+);\s*(.+)$/;
|
|
27
|
-
type EntityQueryMode = "direct" | "timeline" | "follow_up";
|
|
28
31
|
type EntityMentionIndexEntry = {
|
|
29
32
|
canonicalId: string;
|
|
30
33
|
name: string;
|
|
@@ -171,35 +174,6 @@ function relationLine(entry: EntityMentionIndexEntry, relationship: { target: st
|
|
|
171
174
|
if (normalizedLabel.length === 0) return `${entry.name} is connected to ${relationship.target}`;
|
|
172
175
|
return `${entry.name} ${normalizedLabel} ${relationship.target}`;
|
|
173
176
|
}
|
|
174
|
-
function detectEntityQueryMode(query: string): EntityQueryMode | null {
|
|
175
|
-
const normalized = normalizeEntityText(query);
|
|
176
|
-
if (!normalized) return null;
|
|
177
|
-
if (
|
|
178
|
-
/^(what about|and what about|how about|what happened (with|to) (he|him|his|she|her|they|them|their|it|its)|did (he|she|they|it)|is (he|she|they|it)|was (he|she|they|it))\b/.test(normalized)
|
|
179
|
-
) {
|
|
180
|
-
return "follow_up";
|
|
181
|
-
}
|
|
182
|
-
if (
|
|
183
|
-
/^(who is|who s|what do we know about|what does|tell me about|what can you tell me about|what s new with|what happened with|what happened to|status of|where is|how is)\b/.test(normalized)
|
|
184
|
-
) {
|
|
185
|
-
if (/^what does\b/.test(normalized)) {
|
|
186
|
-
if (/^what does (?:this|that|it|the|a|an|my|our|your|their)\b/.test(normalized)) {
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
189
|
-
if (
|
|
190
|
-
/^what does [a-z0-9-]+ (?:error|warning|exception|failure|stack|trace|code|message|log)\b/.test(normalized)
|
|
191
|
-
&& /\b(mean|means|indicate|indicates|imply|implies)\b/.test(normalized)
|
|
192
|
-
) {
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return /what happened|what s new|status of|how is|where is/.test(normalized) ? "timeline" : "direct";
|
|
197
|
-
}
|
|
198
|
-
if (ENTITY_PRONOUN_RE.test(normalized) && normalized.split(/\s+/).length <= 8) {
|
|
199
|
-
return "follow_up";
|
|
200
|
-
}
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
177
|
function scoreAliasMatch(query: string, alias: string): number {
|
|
204
178
|
const normalizedQuery = normalizeEntityText(query);
|
|
205
179
|
const normalizedAlias = normalizeEntityText(alias);
|
|
@@ -1061,7 +1035,18 @@ export async function buildEntityRecallSection(options: BuildEntityRecallSection
|
|
|
1061
1035
|
// during a scan is observed here (issue #2291).
|
|
1062
1036
|
checkEntityRecallAbort(options.abortSignal);
|
|
1063
1037
|
const prefixedMode = detectEntityQueryMode(options.query);
|
|
1064
|
-
|
|
1038
|
+
// #2193: in zero-pronoun scripts a short question with no entity name
|
|
1039
|
+
// never trips a pronoun word list, so the structural signal routes it
|
|
1040
|
+
// into the same coreference path as an English "what about him?".
|
|
1041
|
+
// Latin-script queries stay on the cue tables / English rules so the
|
|
1042
|
+
// generic technical-question guard keeps working. Resolution gates.
|
|
1043
|
+
const structuralFollowUp = prefixedMode === null
|
|
1044
|
+
&& isStructuralEntityFollowUpQuery(
|
|
1045
|
+
options.query,
|
|
1046
|
+
options.recentTurns > 0 && options.transcriptEntries.length > 0,
|
|
1047
|
+
);
|
|
1048
|
+
const earlyMode = prefixedMode ?? (structuralFollowUp ? "follow_up" : null);
|
|
1049
|
+
const persistedIndex = earlyMode
|
|
1065
1050
|
? null
|
|
1066
1051
|
: await readCurrentPersistedEntityIndex(
|
|
1067
1052
|
options.storage,
|
|
@@ -1072,7 +1057,7 @@ export async function buildEntityRecallSection(options: BuildEntityRecallSection
|
|
|
1072
1057
|
checkEntityRecallAbort(options.abortSignal);
|
|
1073
1058
|
let nativeChunks: NativeKnowledgeChunk[] | undefined;
|
|
1074
1059
|
if (
|
|
1075
|
-
!
|
|
1060
|
+
!earlyMode &&
|
|
1076
1061
|
persistedIndex &&
|
|
1077
1062
|
resolveLanguageIndependentExplicitCandidates(persistedIndex, options.query).length === 0
|
|
1078
1063
|
) {
|
|
@@ -1129,7 +1114,22 @@ export async function buildEntityRecallSection(options: BuildEntityRecallSection
|
|
|
1129
1114
|
const queryCandidates = prefixedMode
|
|
1130
1115
|
? explicitCandidates
|
|
1131
1116
|
: resolveLanguageIndependentExplicitCandidates(index, options.query);
|
|
1132
|
-
|
|
1117
|
+
if (
|
|
1118
|
+
queryCandidates.length === 0
|
|
1119
|
+
&& /^what does (?:this|that|it|the|a|an|my|our|your|their)\b/i.test(normalizeEntityText(options.query))
|
|
1120
|
+
) {
|
|
1121
|
+
return entityRecallSectionAbsent(options.abortSignal);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// Explicit mentions keep #2161 behavior (direct mode) even when the
|
|
1125
|
+
// structural follow-up signal also fired; only name-less short questions
|
|
1126
|
+
// fall through to coreference.
|
|
1127
|
+
const mode = prefixedMode
|
|
1128
|
+
?? (queryCandidates.length > 0
|
|
1129
|
+
? "direct"
|
|
1130
|
+
: structuralFollowUp
|
|
1131
|
+
? "follow_up"
|
|
1132
|
+
: null);
|
|
1133
1133
|
if (!mode) return entityRecallSectionAbsent(options.abortSignal);
|
|
1134
1134
|
|
|
1135
1135
|
const candidates = queryCandidates.length > 0
|
|
@@ -334,9 +334,9 @@ export interface GroundingLexeme {
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
export function groundingLexemes(text: string): GroundingLexeme[] {
|
|
337
|
-
const rawTokens = text.normalize("NFKC").match(
|
|
337
|
+
const rawTokens = (text.normalize("NFKC").match(
|
|
338
338
|
/[\p{L}\p{N}]+(?:['’][\p{L}\p{N}]+)?(?:\+\+[\p{L}\p{N}]*|#[\p{L}\p{N}]*)?/gu,
|
|
339
|
-
) ?? [];
|
|
339
|
+
) ?? []).flatMap(splitSpacelessScriptToken);
|
|
340
340
|
const tokens = rawTokens.map((rawToken) =>
|
|
341
341
|
rawToken.replaceAll("’", "'").toLocaleLowerCase());
|
|
342
342
|
let predicateIndex = tokens.findIndex((token, index) => {
|
|
@@ -500,6 +500,116 @@ export function tokenize(text: string): Set<string> {
|
|
|
500
500
|
return tokens;
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
+
const SPACELESS_SCRIPT_CHARACTER_PATTERN = new RegExp(
|
|
504
|
+
"[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}"
|
|
505
|
+
+ "\\p{Script=Thai}\\p{Script=Lao}\\p{Script=Khmer}\\p{Script=Myanmar}]",
|
|
506
|
+
"u",
|
|
507
|
+
);
|
|
508
|
+
const SPACELESS_SCRIPT_LCS_SOURCE_LIMIT = 4096;
|
|
509
|
+
|
|
510
|
+
function containsSpacelessScriptCharacter(text: string): boolean {
|
|
511
|
+
return SPACELESS_SCRIPT_CHARACTER_PATTERN.test(text);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Scripts without word separators (CJK, Hangul, Thai, ...) must not become one
|
|
516
|
+
* whitespace-delimited token: a paraphrase never matches a whole-run token, so
|
|
517
|
+
* grounded CJK facts and entity names were dropped. Split those runs into
|
|
518
|
+
* per-character lexemes so contiguous-token matching behaves as substring
|
|
519
|
+
* matching for these scripts.
|
|
520
|
+
*/
|
|
521
|
+
function splitSpacelessScriptToken(rawToken: string): string[] {
|
|
522
|
+
if (!containsSpacelessScriptCharacter(rawToken)) return [rawToken];
|
|
523
|
+
const parts: string[] = [];
|
|
524
|
+
let otherScriptRun = "";
|
|
525
|
+
for (const character of rawToken) {
|
|
526
|
+
if (containsSpacelessScriptCharacter(character)) {
|
|
527
|
+
if (otherScriptRun.length > 0) {
|
|
528
|
+
parts.push(otherScriptRun);
|
|
529
|
+
otherScriptRun = "";
|
|
530
|
+
}
|
|
531
|
+
parts.push(character);
|
|
532
|
+
} else {
|
|
533
|
+
otherScriptRun += character;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (otherScriptRun.length > 0) parts.push(otherScriptRun);
|
|
537
|
+
return parts;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function spacelessScriptCharacterSequence(text: string): string[] {
|
|
541
|
+
const characters: string[] = [];
|
|
542
|
+
for (const character of text.normalize("NFKC")) {
|
|
543
|
+
if (containsSpacelessScriptCharacter(character)) characters.push(character);
|
|
544
|
+
}
|
|
545
|
+
return characters;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
function spacelessScriptCharacterNgrams(text: string): Set<string> {
|
|
549
|
+
const grams = new Set<string>();
|
|
550
|
+
let previousCharacter = "";
|
|
551
|
+
for (const character of spacelessScriptCharacterSequence(text)) {
|
|
552
|
+
if (previousCharacter !== "") grams.add(previousCharacter + character);
|
|
553
|
+
previousCharacter = character;
|
|
554
|
+
}
|
|
555
|
+
return grams;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
function longestCommonSubstringLength(
|
|
559
|
+
left: ReadonlyArray<string>,
|
|
560
|
+
right: ReadonlyArray<string>,
|
|
561
|
+
): number {
|
|
562
|
+
if (left.length === 0 || right.length === 0) return 0;
|
|
563
|
+
let longest = 0;
|
|
564
|
+
let previousRow = new Array<number>(right.length).fill(0);
|
|
565
|
+
for (const leftCharacter of left) {
|
|
566
|
+
const currentRow = new Array<number>(right.length).fill(0);
|
|
567
|
+
for (let index = 0; index < right.length; index += 1) {
|
|
568
|
+
if (leftCharacter !== right[index]) continue;
|
|
569
|
+
currentRow[index] = (index > 0 ? previousRow[index - 1] : 0) + 1;
|
|
570
|
+
if (currentRow[index] > longest) longest = currentRow[index];
|
|
571
|
+
}
|
|
572
|
+
previousRow = currentRow;
|
|
573
|
+
}
|
|
574
|
+
return longest;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Script-aware grounding score for candidates written in scripts without word
|
|
579
|
+
* separators. Returns null when the candidate has no such characters, so
|
|
580
|
+
* whitespace-delimited candidates keep the default scorer. The longest-common-
|
|
581
|
+
* span gate rejects topical overlap that shares mostly function characters.
|
|
582
|
+
* ponytail: n-grams and the common-span gate ignore argument order; swap in a
|
|
583
|
+
* segmentation-aware matcher if CJK role confusion surfaces.
|
|
584
|
+
*/
|
|
585
|
+
export function spacelessScriptGroundedTokenScore(candidate: string, source: string): number | null {
|
|
586
|
+
const candidateGrams = spacelessScriptCharacterNgrams(candidate);
|
|
587
|
+
if (candidateGrams.size === 0) return null;
|
|
588
|
+
const sourceGrams = spacelessScriptCharacterNgrams(source);
|
|
589
|
+
let sharedGrams = 0;
|
|
590
|
+
for (const gram of candidateGrams) {
|
|
591
|
+
if (sourceGrams.has(gram)) sharedGrams += 1;
|
|
592
|
+
}
|
|
593
|
+
if (sharedGrams < GROUNDING_MIN_SHARED_TOKENS) return 0;
|
|
594
|
+
const coverage = sharedGrams / candidateGrams.size;
|
|
595
|
+
if (coverage < GROUNDING_MIN_COVERAGE) return 0;
|
|
596
|
+
const candidateCharacters = spacelessScriptCharacterSequence(candidate);
|
|
597
|
+
const sourceCharacters = spacelessScriptCharacterSequence(source);
|
|
598
|
+
if (sourceCharacters.length <= SPACELESS_SCRIPT_LCS_SOURCE_LIMIT) {
|
|
599
|
+
const anchoredFraction = longestCommonSubstringLength(candidateCharacters, sourceCharacters)
|
|
600
|
+
/ candidateCharacters.length;
|
|
601
|
+
if (anchoredFraction < GROUNDING_MIN_COVERAGE) return 0;
|
|
602
|
+
}
|
|
603
|
+
const sourceTokens = tokenize(source);
|
|
604
|
+
for (const token of tokenize(candidate)) {
|
|
605
|
+
if (containsSpacelessScriptCharacter(token)) continue;
|
|
606
|
+
if (![...sourceTokens].some((sourceToken) => areGroundingTokensCompatible(token, sourceToken))) {
|
|
607
|
+
return 0;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return coverage;
|
|
611
|
+
}
|
|
612
|
+
|
|
503
613
|
export function normalizeForExactMatch(text: string): string {
|
|
504
614
|
return text.normalize("NFKC").toLocaleLowerCase().replace(/\s+/gu, " ").trim();
|
|
505
615
|
}
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
groundingTokenSequence,
|
|
15
15
|
hasContradictoryPolarity,
|
|
16
16
|
hasExplicitRoleSubjectToken,
|
|
17
|
-
isAttachedNegatedAuxiliary,
|
|
18
17
|
isInterrogativeSourceSentence,
|
|
19
18
|
normalizeForExactMatch,
|
|
20
19
|
normalizedGroundingAlignmentTokenSequence,
|
|
21
20
|
normalizedGroundingTokenSequence,
|
|
22
21
|
sourceSentences,
|
|
22
|
+
spacelessScriptGroundedTokenScore,
|
|
23
23
|
splitGroundingClauses,
|
|
24
24
|
stemToken,
|
|
25
25
|
tokenize,
|
|
@@ -229,6 +229,8 @@ function groundedTokenScore(
|
|
|
229
229
|
requireAlignedArguments = true,
|
|
230
230
|
requireAllCandidateTokensGrounded = true,
|
|
231
231
|
): number {
|
|
232
|
+
const scriptAwareScore = spacelessScriptGroundedTokenScore(candidate, source);
|
|
233
|
+
if (scriptAwareScore !== null) return scriptAwareScore;
|
|
232
234
|
const candidateTokens = tokenize(candidate);
|
|
233
235
|
if (candidateTokens.size === 0) return 0;
|
|
234
236
|
const sourceTokens = tokenize(source);
|