@remnic/core 9.4.0 → 9.4.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 +5 -5
- package/dist/access-admin-ops-surface.js +22 -21
- package/dist/access-boundary.d.ts +5 -5
- package/dist/access-boundary.js +23 -22
- package/dist/access-cli.js +63 -62
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +5 -5
- package/dist/access-http.js +31 -30
- package/dist/access-identity-continuity-surface.d.ts +4 -4
- package/dist/access-identity-continuity-surface.js +22 -21
- package/dist/access-lcm-surface.d.ts +5 -5
- package/dist/access-lcm-surface.js +22 -21
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +27 -26
- package/dist/access-observe-write-surface.d.ts +5 -5
- package/dist/access-observe-write-surface.js +22 -21
- package/dist/access-operations-batch.js +24 -23
- package/dist/access-operations.d.ts +9 -9
- package/dist/access-operations.js +26 -25
- package/dist/access-recall-surface.d.ts +5 -5
- package/dist/access-recall-surface.js +22 -21
- package/dist/access-schema.d.ts +68 -68
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-CdW6B2qQ.d.ts → access-service-m-2VO_Ig.d.ts} +3 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +22 -21
- package/dist/access-surface-catalog.d.ts +5 -5
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/{auto-sync-M47VTCFI.js → auto-sync-HMHQHUAG.js} +4 -4
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +5 -5
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-bflYNWsM.d.ts → catalog-BxWokdC2.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 +6 -6
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-TKUQSXU4.js → chunk-27FLVMDC.js} +12 -12
- package/dist/{chunk-XXEOGY77.js → chunk-2FOD2YY3.js} +7 -7
- package/dist/{chunk-6Y4JTNX7.js → chunk-2MR3MFQB.js} +2 -2
- package/dist/{chunk-AU7Q3LSC.js → chunk-2QSZNTDO.js} +4 -4
- package/dist/{chunk-64ZYXSCO.js → chunk-2U2A5HF4.js} +10 -4
- package/dist/chunk-2U2A5HF4.js.map +1 -0
- package/dist/{chunk-RBGL4MKQ.js → chunk-3F4N4WDH.js} +75 -110
- package/dist/chunk-3F4N4WDH.js.map +1 -0
- package/dist/{chunk-4NMATTXV.js → chunk-4BFRBP45.js} +2 -2
- package/dist/{chunk-L4UZBJNM.js → chunk-4P4626RY.js} +4 -4
- package/dist/{chunk-XZJMIJLW.js → chunk-5QZDMSSN.js} +29 -29
- package/dist/chunk-64UDOIMI.js +121 -0
- package/dist/chunk-64UDOIMI.js.map +1 -0
- package/dist/{chunk-H2EJNV2Z.js → chunk-66FLU5BT.js} +2 -2
- package/dist/{chunk-MWH5MAFP.js → chunk-6BISDEN6.js} +5 -5
- package/dist/{chunk-VBVSN2TV.js → chunk-6ZIETXZ2.js} +2 -2
- package/dist/{chunk-42BBIR33.js → chunk-7N2RUBAP.js} +2 -2
- package/dist/{chunk-UQI2NHTY.js → chunk-7QWMTOIF.js} +37 -37
- package/dist/{chunk-QICQ35K5.js → chunk-7Z2DZNWN.js} +17 -8
- package/dist/{chunk-QICQ35K5.js.map → chunk-7Z2DZNWN.js.map} +1 -1
- package/dist/{chunk-JI5AVXYO.js → chunk-AKUCU7CI.js} +5 -5
- package/dist/{chunk-FT37KV7R.js → chunk-BGTAL46Y.js} +2 -2
- package/dist/{chunk-7VFZTJ7K.js → chunk-BV2TIZ4F.js} +2 -2
- package/dist/{chunk-FWPHPN3V.js → chunk-CLX5VDNY.js} +5 -5
- package/dist/{chunk-TH2KIPP7.js → chunk-CZAA5N5S.js} +2 -2
- package/dist/{chunk-7BAJAXGB.js → chunk-CZAZX7JP.js} +4 -4
- package/dist/{chunk-APMGGGTY.js → chunk-DGYCWCQ7.js} +2 -2
- package/dist/{chunk-GEVIE5NV.js → chunk-DR6PEJU3.js} +4 -4
- package/dist/{chunk-2TCZE3C2.js → chunk-EPGWWCZF.js} +2 -2
- package/dist/{chunk-OUXPVWTZ.js → chunk-FLVL4L3L.js} +5 -5
- package/dist/{chunk-YPL66L3U.js → chunk-FZGGZAAU.js} +2 -2
- package/dist/{chunk-XOE5DYQL.js → chunk-HRCACVHL.js} +2 -2
- package/dist/{chunk-KS4PRHRD.js → chunk-IC6QX5TC.js} +2 -2
- package/dist/{chunk-H25TAODC.js → chunk-ILFJ7AVS.js} +4 -4
- package/dist/{chunk-UQMCR5RW.js → chunk-JLR3JSTL.js} +3 -3
- package/dist/{chunk-5H56JAHW.js → chunk-KCJ5H6XQ.js} +2 -2
- package/dist/{chunk-H5IT5JL7.js → chunk-LOR6ZM5R.js} +3 -3
- package/dist/{chunk-VBBMTSOV.js → chunk-M7GGMGMZ.js} +6 -6
- package/dist/{chunk-G47FEGGK.js → chunk-NG7YBCJO.js} +4 -4
- package/dist/{chunk-QGS7Z7YU.js → chunk-OHDJ34CC.js} +2 -2
- package/dist/{chunk-UAOZJX5J.js → chunk-P6SYWE4G.js} +53 -6
- package/dist/chunk-P6SYWE4G.js.map +1 -0
- package/dist/{chunk-LLMZK53N.js → chunk-PUBTHW5O.js} +2 -2
- package/dist/{chunk-AGNBY3VG.js → chunk-PYHOAXTI.js} +2 -2
- package/dist/{chunk-SXN3LCUT.js → chunk-RHOZ5LLO.js} +100 -4
- package/dist/chunk-RHOZ5LLO.js.map +1 -0
- package/dist/{chunk-6KYMPV2O.js → chunk-RL6NEVXT.js} +45 -2
- package/dist/chunk-RL6NEVXT.js.map +1 -0
- package/dist/{chunk-7WV3F5DQ.js → chunk-V7IZKJI3.js} +2 -2
- package/dist/{chunk-IGF4DII6.js → chunk-X4A62ET7.js} +9 -9
- package/dist/{chunk-OH6BKCPB.js → chunk-XN3TUUX2.js} +2 -2
- package/dist/{chunk-5K5VEDFY.js → chunk-YDSWRD33.js} +4 -4
- package/dist/{chunk-ABGDGBDT.js → chunk-YPEMNNNY.js} +2 -2
- package/dist/{chunk-YM7IEUO7.js → chunk-ZPOROUTX.js} +2 -2
- package/dist/{cli-Dfnc66gs.d.ts → cli-EiBBOt3r.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +51 -50
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +5 -5
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +5 -5
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +5 -5
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/backend.js +2 -2
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +5 -5
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -4
- 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.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +17 -12
- package/dist/index.js +79 -78
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +4 -4
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +6 -6
- package/dist/lcm/schema.js +2 -2
- 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-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +5 -5
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +5 -5
- package/dist/maintenance/rebuild-memory-projection.js +6 -6
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- 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 +23 -3
- package/dist/memory-projection-store.js +9 -2
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +17 -16
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +11 -10
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +5 -5
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +11 -2
- package/dist/operator-toolkit.js +23 -20
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +7 -7
- package/dist/{orchestrator-Y9wyG4jK.d.ts → orchestrator-B2Y28Z9t.d.ts} +3 -3
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +63 -62
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{purge-IHRX4Z7X.js → purge-NDWV6WYD.js} +4 -3
- package/dist/{purge-IHRX4Z7X.js.map → purge-NDWV6WYD.js.map} +1 -1
- package/dist/qmd-Db9mOkzB.d.ts +330 -0
- package/dist/qmd-preflight.d.ts +5 -0
- package/dist/qmd-preflight.js +31 -0
- package/dist/qmd-preflight.js.map +1 -0
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +3 -305
- package/dist/qmd.js +10 -8
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.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/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- 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/runtime/better-sqlite.d.ts +17 -1
- package/dist/runtime/better-sqlite.js +5 -3
- package/dist/schemas.d.ts +84 -84
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +10 -9
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +15 -14
- 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-bfXJNKVf.d.ts → semantic-consolidation-BDVIbLRw.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +6 -6
- package/dist/semantic-rule-promotion.js +5 -5
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +5 -5
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/session-transcript-migration.js +2 -2
- package/dist/shared-context/manager.d.ts +9 -9
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +4 -4
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.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 +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- 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/export-sqlite.js +2 -2
- package/dist/transfer/import-sqlite.js +2 -2
- package/dist/transfer/types.d.ts +66 -66
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-D1iBqhJA.d.ts → types-ljkd82rn.d.ts} +13 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +5 -5
- package/package.json +2 -2
- package/src/memory-projection-open-failure.test.ts +322 -0
- package/src/memory-projection-store.ts +179 -2
- package/src/operator-toolkit.ts +64 -0
- package/src/qmd-preflight.test.ts +197 -0
- package/src/qmd-preflight.ts +167 -0
- package/src/qmd.ts +115 -129
- package/src/runtime/better-sqlite.test.ts +54 -0
- package/src/runtime/better-sqlite.ts +83 -3
- package/src/wearables/cleanup.test.ts +56 -0
- package/src/wearables/cleanup.ts +22 -1
- package/src/wearables/config.test.ts +25 -0
- package/src/wearables/config.ts +31 -4
- package/src/wearables/types.ts +12 -1
- package/dist/chunk-64ZYXSCO.js.map +0 -1
- package/dist/chunk-6KYMPV2O.js.map +0 -1
- package/dist/chunk-RBGL4MKQ.js.map +0 -1
- package/dist/chunk-SXN3LCUT.js.map +0 -1
- package/dist/chunk-UAOZJX5J.js.map +0 -1
- /package/dist/{auto-sync-M47VTCFI.js.map → auto-sync-HMHQHUAG.js.map} +0 -0
- /package/dist/{chunk-TKUQSXU4.js.map → chunk-27FLVMDC.js.map} +0 -0
- /package/dist/{chunk-XXEOGY77.js.map → chunk-2FOD2YY3.js.map} +0 -0
- /package/dist/{chunk-6Y4JTNX7.js.map → chunk-2MR3MFQB.js.map} +0 -0
- /package/dist/{chunk-AU7Q3LSC.js.map → chunk-2QSZNTDO.js.map} +0 -0
- /package/dist/{chunk-4NMATTXV.js.map → chunk-4BFRBP45.js.map} +0 -0
- /package/dist/{chunk-L4UZBJNM.js.map → chunk-4P4626RY.js.map} +0 -0
- /package/dist/{chunk-XZJMIJLW.js.map → chunk-5QZDMSSN.js.map} +0 -0
- /package/dist/{chunk-H2EJNV2Z.js.map → chunk-66FLU5BT.js.map} +0 -0
- /package/dist/{chunk-MWH5MAFP.js.map → chunk-6BISDEN6.js.map} +0 -0
- /package/dist/{chunk-VBVSN2TV.js.map → chunk-6ZIETXZ2.js.map} +0 -0
- /package/dist/{chunk-42BBIR33.js.map → chunk-7N2RUBAP.js.map} +0 -0
- /package/dist/{chunk-UQI2NHTY.js.map → chunk-7QWMTOIF.js.map} +0 -0
- /package/dist/{chunk-JI5AVXYO.js.map → chunk-AKUCU7CI.js.map} +0 -0
- /package/dist/{chunk-FT37KV7R.js.map → chunk-BGTAL46Y.js.map} +0 -0
- /package/dist/{chunk-7VFZTJ7K.js.map → chunk-BV2TIZ4F.js.map} +0 -0
- /package/dist/{chunk-FWPHPN3V.js.map → chunk-CLX5VDNY.js.map} +0 -0
- /package/dist/{chunk-TH2KIPP7.js.map → chunk-CZAA5N5S.js.map} +0 -0
- /package/dist/{chunk-7BAJAXGB.js.map → chunk-CZAZX7JP.js.map} +0 -0
- /package/dist/{chunk-APMGGGTY.js.map → chunk-DGYCWCQ7.js.map} +0 -0
- /package/dist/{chunk-GEVIE5NV.js.map → chunk-DR6PEJU3.js.map} +0 -0
- /package/dist/{chunk-2TCZE3C2.js.map → chunk-EPGWWCZF.js.map} +0 -0
- /package/dist/{chunk-OUXPVWTZ.js.map → chunk-FLVL4L3L.js.map} +0 -0
- /package/dist/{chunk-YPL66L3U.js.map → chunk-FZGGZAAU.js.map} +0 -0
- /package/dist/{chunk-XOE5DYQL.js.map → chunk-HRCACVHL.js.map} +0 -0
- /package/dist/{chunk-KS4PRHRD.js.map → chunk-IC6QX5TC.js.map} +0 -0
- /package/dist/{chunk-H25TAODC.js.map → chunk-ILFJ7AVS.js.map} +0 -0
- /package/dist/{chunk-UQMCR5RW.js.map → chunk-JLR3JSTL.js.map} +0 -0
- /package/dist/{chunk-5H56JAHW.js.map → chunk-KCJ5H6XQ.js.map} +0 -0
- /package/dist/{chunk-H5IT5JL7.js.map → chunk-LOR6ZM5R.js.map} +0 -0
- /package/dist/{chunk-VBBMTSOV.js.map → chunk-M7GGMGMZ.js.map} +0 -0
- /package/dist/{chunk-G47FEGGK.js.map → chunk-NG7YBCJO.js.map} +0 -0
- /package/dist/{chunk-QGS7Z7YU.js.map → chunk-OHDJ34CC.js.map} +0 -0
- /package/dist/{chunk-LLMZK53N.js.map → chunk-PUBTHW5O.js.map} +0 -0
- /package/dist/{chunk-AGNBY3VG.js.map → chunk-PYHOAXTI.js.map} +0 -0
- /package/dist/{chunk-7WV3F5DQ.js.map → chunk-V7IZKJI3.js.map} +0 -0
- /package/dist/{chunk-IGF4DII6.js.map → chunk-X4A62ET7.js.map} +0 -0
- /package/dist/{chunk-OH6BKCPB.js.map → chunk-XN3TUUX2.js.map} +0 -0
- /package/dist/{chunk-5K5VEDFY.js.map → chunk-YDSWRD33.js.map} +0 -0
- /package/dist/{chunk-ABGDGBDT.js.map → chunk-YPEMNNNY.js.map} +0 -0
- /package/dist/{chunk-YM7IEUO7.js.map → chunk-ZPOROUTX.js.map} +0 -0
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
displayErrorDetail,
|
|
5
5
|
isLikelyBetterSqlite3NativeBindingError,
|
|
6
6
|
openBetterSqlite3,
|
|
7
|
+
probeBetterSqlite3Driver,
|
|
7
8
|
} from "./better-sqlite.js";
|
|
8
9
|
|
|
9
10
|
test("isLikelyBetterSqlite3NativeBindingError recognizes missing and mismatched native bindings", () => {
|
|
@@ -22,6 +23,50 @@ test("isLikelyBetterSqlite3NativeBindingError recognizes missing and mismatched
|
|
|
22
23
|
assert.equal(isLikelyBetterSqlite3NativeBindingError(new Error("SQLITE_BUSY: database is locked")), false);
|
|
23
24
|
});
|
|
24
25
|
|
|
26
|
+
test("isLikelyBetterSqlite3NativeBindingError walks the cause chain of a sanitized wrapper (issue #1848)", () => {
|
|
27
|
+
// Production path: loadBetterSqlite3() catches the ABI error and re-throws a
|
|
28
|
+
// sanitized unavailableError WRAPPER whose message drops the ABI markers. The
|
|
29
|
+
// original error survives only on .cause — the classifier must walk it, or
|
|
30
|
+
// the startup probe / projection doctor / browse warn all MISS the hint.
|
|
31
|
+
const abiCause = new Error(
|
|
32
|
+
"The module was compiled against a different Node.js version using NODE_MODULE_VERSION 127",
|
|
33
|
+
);
|
|
34
|
+
const wrapper = new Error(
|
|
35
|
+
"better-sqlite3 is unavailable. Remnic attempted to load the native SQLite binding and could not.",
|
|
36
|
+
{ cause: abiCause },
|
|
37
|
+
);
|
|
38
|
+
assert.equal(isLikelyBetterSqlite3NativeBindingError(wrapper), true);
|
|
39
|
+
|
|
40
|
+
// Deeply nested wrapper (wrapper.cause.cause = ABI error) is still found.
|
|
41
|
+
const deepWrapper = new Error("outer sanitized layer", { cause: wrapper });
|
|
42
|
+
assert.equal(isLikelyBetterSqlite3NativeBindingError(deepWrapper), true);
|
|
43
|
+
|
|
44
|
+
// A wrapper whose cause is NOT a native-binding failure stays negative.
|
|
45
|
+
const benignWrapper = new Error("better-sqlite3 is unavailable.", {
|
|
46
|
+
cause: new Error("SQLITE_BUSY: database is locked"),
|
|
47
|
+
});
|
|
48
|
+
assert.equal(isLikelyBetterSqlite3NativeBindingError(benignWrapper), false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("isLikelyBetterSqlite3NativeBindingError inspects AggregateError.errors siblings", () => {
|
|
52
|
+
// Module loaders can surface failures as an AggregateError; the ABI mismatch
|
|
53
|
+
// may live in a sibling rather than the aggregate's own message.
|
|
54
|
+
const agg = new AggregateError([
|
|
55
|
+
new Error("some unrelated loader step"),
|
|
56
|
+
new Error("Could not locate the bindings file. Tried: better_sqlite3.node"),
|
|
57
|
+
]);
|
|
58
|
+
assert.equal(isLikelyBetterSqlite3NativeBindingError(agg), true);
|
|
59
|
+
|
|
60
|
+
const benignAgg = new AggregateError([new Error("unrelated"), new Error("SQLITE_BUSY")]);
|
|
61
|
+
assert.equal(isLikelyBetterSqlite3NativeBindingError(benignAgg), false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("isLikelyBetterSqlite3NativeBindingError is cycle-safe on a self-referential cause", () => {
|
|
65
|
+
const cyclic = new Error("SQLITE_BUSY: database is locked");
|
|
66
|
+
cyclic.cause = cyclic; // would loop forever without a visited set
|
|
67
|
+
assert.equal(isLikelyBetterSqlite3NativeBindingError(cyclic), false);
|
|
68
|
+
});
|
|
69
|
+
|
|
25
70
|
test("displayErrorDetail surfaces only error class + code, never the raw message (CodeQL js/stack-trace-exposure)", () => {
|
|
26
71
|
// MODULE_NOT_FOUND messages embed an absolute "Require stack:" path block.
|
|
27
72
|
const moduleNotFound = Object.assign(
|
|
@@ -59,3 +104,12 @@ test("openBetterSqlite3 can open an in-memory database after install verificatio
|
|
|
59
104
|
db.close();
|
|
60
105
|
}
|
|
61
106
|
});
|
|
107
|
+
|
|
108
|
+
test("probeBetterSqlite3Driver succeeds (ok=true) under the verified process and warms the ctor cache", () => {
|
|
109
|
+
const probe = probeBetterSqlite3Driver();
|
|
110
|
+
assert.equal(probe.ok, true);
|
|
111
|
+
assert.equal(probe.detail, "");
|
|
112
|
+
assert.equal(probe.nativeBindingMismatch, false);
|
|
113
|
+
// A second probe reuses the warmed cache (no re-load); still ok.
|
|
114
|
+
assert.equal(probeBetterSqlite3Driver().ok, true);
|
|
115
|
+
});
|
|
@@ -28,6 +28,35 @@ export function openBetterSqlite3(
|
|
|
28
28
|
return new Database(file, options);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export interface BetterSqlite3DriverProbe {
|
|
32
|
+
/** true when the native binding loaded successfully under this process. */
|
|
33
|
+
ok: boolean;
|
|
34
|
+
/** Path-free detail string (class + code) from `displayErrorDetail`; "" when ok. */
|
|
35
|
+
detail: string;
|
|
36
|
+
/** true when the failure is classified as a native-binding ABI mismatch. */
|
|
37
|
+
nativeBindingMismatch: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Attempt to load the better-sqlite3 native driver under the running process
|
|
42
|
+
* WITHOUT opening a database. Used by the server startup check (issue #1829)
|
|
43
|
+
* to surface a wrong-ABI build loudly instead of letting each memory browse
|
|
44
|
+
* silently fall back to a full-corpus scan. Never throws — callers log the
|
|
45
|
+
* result. A successful probe also warms the ctor cache for later opens.
|
|
46
|
+
*/
|
|
47
|
+
export function probeBetterSqlite3Driver(): BetterSqlite3DriverProbe {
|
|
48
|
+
try {
|
|
49
|
+
loadBetterSqlite3();
|
|
50
|
+
return { ok: true, detail: "", nativeBindingMismatch: false };
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return {
|
|
53
|
+
ok: false,
|
|
54
|
+
detail: displayErrorDetail(error),
|
|
55
|
+
nativeBindingMismatch: isLikelyBetterSqlite3NativeBindingError(error),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
31
60
|
function requireBetterSqlite3Ctor(require: RuntimeRequire): BetterSqlite3Ctor {
|
|
32
61
|
const loaded = require("better-sqlite3") as
|
|
33
62
|
| BetterSqlite3Ctor
|
|
@@ -50,9 +79,49 @@ function rawErrorMessage(error: unknown): string {
|
|
|
50
79
|
return error instanceof Error ? error.message : String(error ?? "");
|
|
51
80
|
}
|
|
52
81
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Iterate an error and every node reachable along its `cause` chain and any
|
|
84
|
+
* `AggregateError.errors` siblings (depth-first), cycle-safe via a visited set.
|
|
85
|
+
*
|
|
86
|
+
* Native-binding failures thrown from openBetterSqlite3 /
|
|
87
|
+
* probeBetterSqlite3Driver are caught and re-thrown as a sanitized
|
|
88
|
+
* `unavailableError` WRAPPER: the wrapper's message drops the ABI markers
|
|
89
|
+
* (NODE_MODULE_VERSION, better_sqlite3.node, …) that live on the ORIGINAL
|
|
90
|
+
* error. So classification must walk `.cause` (and aggregate siblings) instead
|
|
91
|
+
* of inspecting only the top wrapper's message — otherwise startup logs, browse
|
|
92
|
+
* warnings, and the memory_projection doctor check all MISS the native-binding
|
|
93
|
+
* hint (issue #1848).
|
|
94
|
+
*/
|
|
95
|
+
function* errorChain(error: unknown): Generator<unknown> {
|
|
96
|
+
const seen = new Set<unknown>();
|
|
97
|
+
const stack: unknown[] = [error];
|
|
98
|
+
while (stack.length > 0) {
|
|
99
|
+
const node = stack.pop();
|
|
100
|
+
if (node === null || node === undefined) continue;
|
|
101
|
+
if (typeof node !== "object") continue;
|
|
102
|
+
if (seen.has(node)) continue;
|
|
103
|
+
seen.add(node);
|
|
104
|
+
yield node;
|
|
105
|
+
// Narrow with `in` (not a cast) so the property access is compiler-checked.
|
|
106
|
+
if ("cause" in node) {
|
|
107
|
+
const cause = node.cause;
|
|
108
|
+
if (cause !== null && cause !== undefined) stack.push(cause);
|
|
109
|
+
}
|
|
110
|
+
if ("errors" in node) {
|
|
111
|
+
const errors = node.errors;
|
|
112
|
+
if (Array.isArray(errors)) {
|
|
113
|
+
for (const member of errors) {
|
|
114
|
+
if (member !== null && member !== undefined) stack.push(member);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// True when a single error's RAW message carries a native-binding ABI marker.
|
|
122
|
+
// Raw (not displayErrorDetail) so redaction can't strip detection markers
|
|
123
|
+
// (e.g. the loader path containing "better_sqlite3.node").
|
|
124
|
+
function messageHasNativeBindingMarker(error: unknown): boolean {
|
|
56
125
|
const detail = rawErrorMessage(error);
|
|
57
126
|
return (
|
|
58
127
|
detail.includes("Could not locate the bindings file") ||
|
|
@@ -63,6 +132,17 @@ export function isLikelyBetterSqlite3NativeBindingError(error: unknown): boolean
|
|
|
63
132
|
);
|
|
64
133
|
}
|
|
65
134
|
|
|
135
|
+
export function isLikelyBetterSqlite3NativeBindingError(error: unknown): boolean {
|
|
136
|
+
// Walk the full cause / aggregate chain so a SANITIZED wrapper
|
|
137
|
+
// (unavailableError) — whose message drops the ABI markers that live on the
|
|
138
|
+
// original error — is still classified. Inspecting only the top-level message
|
|
139
|
+
// misses the real mismatch when the failure was wrapped (issue #1848).
|
|
140
|
+
for (const node of errorChain(error)) {
|
|
141
|
+
if (messageHasNativeBindingMarker(node)) return true;
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
66
146
|
function unavailableError(error: unknown): Error {
|
|
67
147
|
const detail = displayErrorDetail(error);
|
|
68
148
|
const nativeBindingHint = isLikelyBetterSqlite3NativeBindingError(error)
|
|
@@ -132,3 +132,59 @@ test("input conversation is not mutated", () => {
|
|
|
132
132
|
cleanConversation(input, ALL_ON);
|
|
133
133
|
assert.equal(JSON.stringify(input), before);
|
|
134
134
|
});
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
test("merges consecutive same-speaker runs across diarized speakers", () => {
|
|
138
|
+
const result = cleanConversation(
|
|
139
|
+
conversation([
|
|
140
|
+
{ speakerKey: "0", text: "Hello there.", startIso: "2026-06-10T10:00:00Z", endIso: "2026-06-10T10:00:03Z" },
|
|
141
|
+
{ speakerKey: "0", text: "How are you?", startIso: "2026-06-10T10:00:04Z", endIso: "2026-06-10T10:00:07Z" },
|
|
142
|
+
{ speakerKey: "1", text: "Good, thanks.", startIso: "2026-06-10T10:00:08Z", endIso: "2026-06-10T10:00:11Z" },
|
|
143
|
+
{ speakerKey: "1", text: "And you?", startIso: "2026-06-10T10:00:12Z", endIso: "2026-06-10T10:00:14Z" },
|
|
144
|
+
{ speakerKey: "0", text: "Busy day.", startIso: "2026-06-10T10:00:15Z", endIso: "2026-06-10T10:00:18Z" },
|
|
145
|
+
]),
|
|
146
|
+
ALL_ON,
|
|
147
|
+
);
|
|
148
|
+
// Three runs: 0+0, 1+1, 0. Generic-label protection is off here, so
|
|
149
|
+
// diarized same-speaker adjacency merges within the gap.
|
|
150
|
+
assert.equal(result.conversation.segments.length, 3);
|
|
151
|
+
assert.equal(result.conversation.segments[0].text, "Hello there. How are you?");
|
|
152
|
+
assert.equal(result.conversation.segments[1].text, "Good, thanks. And you?");
|
|
153
|
+
assert.equal(result.conversation.segments[2].text, "Busy day.");
|
|
154
|
+
assert.equal(result.mergedSegments, 2);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("preserveUtteranceBoundaries keeps generic-labeled utterances distinct (#1811)", () => {
|
|
158
|
+
const settings: WearableCleanupSettings = { ...ALL_ON, preserveUtteranceBoundaries: true };
|
|
159
|
+
const result = cleanConversation(
|
|
160
|
+
conversation([
|
|
161
|
+
{ speakerKey: "unknown", text: "First.", startIso: "2026-06-10T10:00:00Z", endIso: "2026-06-10T10:00:02Z" },
|
|
162
|
+
{ speakerKey: "unknown", text: "Second.", startIso: "2026-06-10T10:00:03Z", endIso: "2026-06-10T10:00:05Z" },
|
|
163
|
+
{ speakerKey: "Unknown", text: "Third.", startIso: "2026-06-10T10:00:06Z", endIso: "2026-06-10T10:00:08Z" },
|
|
164
|
+
{ speakerKey: "0", text: "Diarized A.", startIso: "2026-06-10T10:00:09Z", endIso: "2026-06-10T10:00:11Z" },
|
|
165
|
+
{ speakerKey: "0", text: "Diarized B.", startIso: "2026-06-10T10:00:12Z", endIso: "2026-06-10T10:00:14Z" },
|
|
166
|
+
]),
|
|
167
|
+
settings,
|
|
168
|
+
);
|
|
169
|
+
// Generic "unknown"/"Unknown" utterances are NOT merged into one block.
|
|
170
|
+
assert.equal(result.conversation.segments.length, 4);
|
|
171
|
+
assert.deepEqual(
|
|
172
|
+
result.conversation.segments.map((segment) => segment.text),
|
|
173
|
+
["First.", "Second.", "Third.", "Diarized A. Diarized B."],
|
|
174
|
+
);
|
|
175
|
+
assert.equal(result.mergedSegments, 1);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("preserveUtteranceBoundaries default (off) still collapses generic labels", () => {
|
|
179
|
+
// The flag is opt-in: without it the legacy merge-everything behavior
|
|
180
|
+
// is unchanged for sources that never set it.
|
|
181
|
+
const result = cleanConversation(
|
|
182
|
+
conversation([
|
|
183
|
+
{ speakerKey: "unknown", text: "First.", startIso: "2026-06-10T10:00:00Z", endIso: "2026-06-10T10:00:02Z" },
|
|
184
|
+
{ speakerKey: "unknown", text: "Second.", startIso: "2026-06-10T10:00:03Z", endIso: "2026-06-10T10:00:05Z" },
|
|
185
|
+
]),
|
|
186
|
+
ALL_ON,
|
|
187
|
+
);
|
|
188
|
+
assert.equal(result.conversation.segments.length, 1);
|
|
189
|
+
assert.equal(result.conversation.segments[0].text, "First. Second.");
|
|
190
|
+
});
|
package/src/wearables/cleanup.ts
CHANGED
|
@@ -24,6 +24,14 @@ export interface CleanupResult {
|
|
|
24
24
|
/** Merge consecutive same-speaker segments when gaps are below this. */
|
|
25
25
|
const MERGE_GAP_MS = 30_000;
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Speaker labels that carry no real diarization signal. Bee (and other
|
|
29
|
+
* providers that fall back to a placeholder) emit "Unknown"/"unknown"
|
|
30
|
+
* or an empty string when diarization is unavailable; merging on such a
|
|
31
|
+
* label would collapse an entire conversation into one segment (issue #1811).
|
|
32
|
+
*/
|
|
33
|
+
const GENERIC_SPEAKER_PATTERN = /^unknown$/i;
|
|
34
|
+
|
|
27
35
|
/**
|
|
28
36
|
* Standalone filler tokens stripped when `stripFillers` is on. Matched
|
|
29
37
|
* case-insensitively on word boundaries, only as whole tokens — "um"
|
|
@@ -47,6 +55,9 @@ export function cleanConversation(
|
|
|
47
55
|
let segments = conversation.segments.map((segment) => ({ ...segment }));
|
|
48
56
|
let droppedSegments = 0;
|
|
49
57
|
let mergedSegments = 0;
|
|
58
|
+
// Optional on the type so other connectors keep the legacy no-op
|
|
59
|
+
// default; absent means "off" (unchanged merge behavior).
|
|
60
|
+
const preserveBoundaries = settings.preserveUtteranceBoundaries === true;
|
|
50
61
|
|
|
51
62
|
if (settings.stripFillers) {
|
|
52
63
|
for (const segment of segments) {
|
|
@@ -86,7 +97,7 @@ export function cleanConversation(
|
|
|
86
97
|
const merged: WearableTranscriptSegment[] = [];
|
|
87
98
|
for (const segment of segments) {
|
|
88
99
|
const previous = merged[merged.length - 1];
|
|
89
|
-
if (previous && canMerge(previous, segment)) {
|
|
100
|
+
if (previous && canMerge(previous, segment, preserveBoundaries)) {
|
|
90
101
|
previous.text = `${previous.text} ${segment.text}`.trim();
|
|
91
102
|
if (segment.endIso) previous.endIso = segment.endIso;
|
|
92
103
|
mergedSegments += 1;
|
|
@@ -107,8 +118,18 @@ export function cleanConversation(
|
|
|
107
118
|
function canMerge(
|
|
108
119
|
previous: WearableTranscriptSegment,
|
|
109
120
|
next: WearableTranscriptSegment,
|
|
121
|
+
preserveUtteranceBoundaries: boolean,
|
|
110
122
|
): boolean {
|
|
111
123
|
if (previous.speakerKey !== next.speakerKey) return false;
|
|
124
|
+
// A generic/low-confidence speaker label ("Unknown", empty) carries no
|
|
125
|
+
// real diarization: merging on it collapses unrelated utterances. When
|
|
126
|
+
// the source opts into boundary preservation, refuse to merge across
|
|
127
|
+
// such a label (issue #1811). The keys are equal here, so checking one
|
|
128
|
+
// suffices; diarized labels still merge normally.
|
|
129
|
+
if (preserveUtteranceBoundaries) {
|
|
130
|
+
const label = previous.speakerKey.trim();
|
|
131
|
+
if (label.length === 0 || GENERIC_SPEAKER_PATTERN.test(label)) return false;
|
|
132
|
+
}
|
|
112
133
|
const previousEnd = previous.endIso ? Date.parse(previous.endIso) : NaN;
|
|
113
134
|
const nextStart = next.startIso ? Date.parse(next.startIso) : NaN;
|
|
114
135
|
// Without timestamps, adjacency is the only signal — still merge.
|
|
@@ -44,9 +44,34 @@ test("source settings default to the fully-automated smart pipeline", () => {
|
|
|
44
44
|
stripFillers: true,
|
|
45
45
|
collapseRepeats: true,
|
|
46
46
|
dropLowQuality: true,
|
|
47
|
+
// Opt-in for Bee only; limitless keeps the legacy default (issue #1811).
|
|
48
|
+
preserveUtteranceBoundaries: false,
|
|
47
49
|
});
|
|
48
50
|
});
|
|
49
51
|
|
|
52
|
+
test("bee source defaults to preserving utterance boundaries (#1811)", () => {
|
|
53
|
+
const parsed = parseWearablesConfig({
|
|
54
|
+
enabled: true,
|
|
55
|
+
sources: { bee: { enabled: true } },
|
|
56
|
+
});
|
|
57
|
+
assert.equal(parsed.sources.bee.cleanup.preserveUtteranceBoundaries, true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("cleanup.preserveUtteranceBoundaries is parsed and overrides the source default", () => {
|
|
61
|
+
const parsed = parseWearablesConfig({
|
|
62
|
+
enabled: true,
|
|
63
|
+
sources: { bee: { enabled: true, cleanup: { preserveUtteranceBoundaries: false } } },
|
|
64
|
+
});
|
|
65
|
+
assert.equal(parsed.sources.bee.cleanup.preserveUtteranceBoundaries, false);
|
|
66
|
+
assert.throws(
|
|
67
|
+
() =>
|
|
68
|
+
parseWearablesConfig({
|
|
69
|
+
sources: { bee: { cleanup: { preserveUtteranceBoundaries: "maybe" } } },
|
|
70
|
+
}),
|
|
71
|
+
/cleanup.preserveUtteranceBoundaries/,
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
50
75
|
test("top-level defaults are full-featured: digest and off-the-record on", () => {
|
|
51
76
|
const parsed = parseWearablesConfig({});
|
|
52
77
|
assert.equal(parsed.digestEnabled, true);
|
package/src/wearables/config.ts
CHANGED
|
@@ -48,16 +48,35 @@ const DEFAULT_SOURCE_TRUST = 0.8;
|
|
|
48
48
|
const DEFAULT_AUTO_APPROVE_TRUST = 0.7;
|
|
49
49
|
const DEFAULT_REVIEW_TRUST = 0.45;
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
// Sources whose provider emits per-utterance text but unreliable
|
|
52
|
+
// speaker labels (Bee falls back to a generic "unknown" label when
|
|
53
|
+
// diarization is unavailable). For those, the cleanup default keeps
|
|
54
|
+
// utterance-level boundaries so a whole conversation does not collapse
|
|
55
|
+
// into one mega-segment (issue #1811). Other sources keep the legacy
|
|
56
|
+
// merge-everything default unless explicitly configured.
|
|
57
|
+
const BOUNDARY_PRESERVING_SOURCE_IDS = new Set<string>(["bee"]);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Default cleanup settings. `sourceId` (the connector id this block
|
|
61
|
+
* belongs to) only adjusts the `preserveUtteranceBoundaries` default —
|
|
62
|
+
* every other toggle is identical across sources.
|
|
63
|
+
*/
|
|
64
|
+
export function defaultWearableCleanupSettings(
|
|
65
|
+
sourceId?: string,
|
|
66
|
+
): WearableCleanupSettings {
|
|
52
67
|
return {
|
|
53
68
|
mergeSameSpeaker: true,
|
|
54
69
|
stripFillers: true,
|
|
55
70
|
collapseRepeats: true,
|
|
56
71
|
dropLowQuality: true,
|
|
72
|
+
preserveUtteranceBoundaries:
|
|
73
|
+
sourceId !== undefined && BOUNDARY_PRESERVING_SOURCE_IDS.has(sourceId),
|
|
57
74
|
};
|
|
58
75
|
}
|
|
59
76
|
|
|
60
|
-
export function defaultWearableSourceSettings(
|
|
77
|
+
export function defaultWearableSourceSettings(
|
|
78
|
+
sourceId?: string,
|
|
79
|
+
): WearableSourceSettings {
|
|
61
80
|
return {
|
|
62
81
|
enabled: false,
|
|
63
82
|
memoryMode: "smart",
|
|
@@ -68,7 +87,7 @@ export function defaultWearableSourceSettings(): WearableSourceSettings {
|
|
|
68
87
|
minImportance: DEFAULT_MIN_IMPORTANCE,
|
|
69
88
|
maxMemoriesPerDay: DEFAULT_MAX_MEMORIES_PER_DAY,
|
|
70
89
|
importNativeMemories: "smart",
|
|
71
|
-
cleanup: defaultWearableCleanupSettings(),
|
|
90
|
+
cleanup: defaultWearableCleanupSettings(sourceId),
|
|
72
91
|
};
|
|
73
92
|
}
|
|
74
93
|
|
|
@@ -184,9 +203,10 @@ function parseCorrectionRules(
|
|
|
184
203
|
function parseSourceSettings(
|
|
185
204
|
value: unknown,
|
|
186
205
|
keyPath: string,
|
|
206
|
+
sourceId: string,
|
|
187
207
|
): WearableSourceSettings {
|
|
188
208
|
const raw = requireObject(value, keyPath);
|
|
189
|
-
const defaults = defaultWearableSourceSettings();
|
|
209
|
+
const defaults = defaultWearableSourceSettings(sourceId);
|
|
190
210
|
|
|
191
211
|
const minConfidenceRaw = coerceNumber(raw.minConfidence);
|
|
192
212
|
// Out-of-range values reject loudly instead of clamping — silently
|
|
@@ -266,6 +286,12 @@ function parseSourceSettings(
|
|
|
266
286
|
`${keyPath}.cleanup.dropLowQuality`,
|
|
267
287
|
defaults.cleanup.dropLowQuality,
|
|
268
288
|
),
|
|
289
|
+
preserveUtteranceBoundaries: parseBool(
|
|
290
|
+
rawCleanup.preserveUtteranceBoundaries,
|
|
291
|
+
`${keyPath}.cleanup.preserveUtteranceBoundaries`,
|
|
292
|
+
// Optional on the type; the per-source default is always concrete.
|
|
293
|
+
defaults.cleanup.preserveUtteranceBoundaries ?? false,
|
|
294
|
+
),
|
|
269
295
|
};
|
|
270
296
|
|
|
271
297
|
return {
|
|
@@ -397,6 +423,7 @@ export function parseWearablesConfig(value: unknown): WearablesConfig {
|
|
|
397
423
|
sources[sourceId] = parseSourceSettings(
|
|
398
424
|
sourceValue,
|
|
399
425
|
`wearables.sources.${sourceId}`,
|
|
426
|
+
sourceId,
|
|
400
427
|
);
|
|
401
428
|
}
|
|
402
429
|
}
|
package/src/wearables/types.ts
CHANGED
|
@@ -210,6 +210,18 @@ export interface WearableCleanupSettings {
|
|
|
210
210
|
* sync summary and excluded from memory extraction.
|
|
211
211
|
*/
|
|
212
212
|
dropLowQuality: boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Keep utterance-level boundaries for segments whose speaker label
|
|
215
|
+
* carries no real diarization signal (generic labels like "Unknown"
|
|
216
|
+
* or empty). When `mergeSameSpeaker` is also on, such segments are
|
|
217
|
+
* left distinct instead of collapsing into one block — a whole
|
|
218
|
+
* conversation of per-utterance text under a single generic label
|
|
219
|
+
* otherwise merges into one mega-segment (issue #1811). Sources whose
|
|
220
|
+
* provider emits reliable per-utterance text but unreliable speaker
|
|
221
|
+
* labels (Bee) default this on; others default off so existing merge
|
|
222
|
+
* behavior is unchanged unless explicitly configured.
|
|
223
|
+
*/
|
|
224
|
+
preserveUtteranceBoundaries?: boolean;
|
|
213
225
|
}
|
|
214
226
|
|
|
215
227
|
/** A single user-specific transcript correction rule. */
|
|
@@ -337,4 +349,3 @@ export interface WearableSourceStatus {
|
|
|
337
349
|
lastDateSynced: string | null;
|
|
338
350
|
transcriptDays: number;
|
|
339
351
|
}
|
|
340
|
-
|