@remnic/core 9.69.16 → 9.69.18
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 +49 -45
- package/dist/access-authorization-probe.d.ts +11 -11
- package/dist/access-authorization-probe.js +50 -46
- package/dist/access-boundary.d.ts +11 -11
- package/dist/access-boundary.js +49 -45
- package/dist/access-cli.js +111 -110
- 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 +49 -45
- 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 +51 -47
- package/dist/access-http.d.ts +12 -12
- package/dist/access-http.js +69 -65
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +49 -45
- package/dist/access-lcm-surface.d.ts +11 -11
- package/dist/access-lcm-surface.js +49 -45
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +11 -11
- package/dist/access-mcp.js +60 -56
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-Rzuo1nGR.d.ts → access-namespace-preflight-BMHhxoL9.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +49 -45
- package/dist/access-observe-transcript.d.ts +147 -0
- package/dist/access-observe-transcript.js +16 -0
- package/dist/access-observe-write-surface.d.ts +12 -11
- package/dist/access-observe-write-surface.js +49 -45
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-offline-manifest.js +6 -6
- package/dist/access-operations-batch.js +52 -48
- package/dist/access-operations.d.ts +13 -13
- package/dist/access-operations.js +57 -53
- package/dist/access-recall-concurrency.d.ts +11 -11
- package/dist/access-recall-concurrency.js +49 -45
- package/dist/access-recall-response.d.ts +11 -11
- package/dist/access-recall-response.js +49 -45
- package/dist/access-recall-surface.d.ts +11 -11
- package/dist/access-recall-surface.js +49 -45
- package/dist/access-schema.d.ts +4 -4
- package/dist/access-schema.js +5 -5
- package/dist/{access-service-tcC_jK6C.d.ts → access-service-CYdqPfpS.d.ts} +22 -13
- package/dist/access-service-helpers.d.ts +11 -11
- package/dist/access-service.d.ts +11 -11
- package/dist/access-service.js +49 -45
- package/dist/access-surface-catalog.d.ts +11 -11
- package/dist/access-surface-catalog.js +51 -47
- package/dist/access-surface-catalog.js.map +1 -1
- 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/active-recall.js +7 -7
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/{auto-sync-Q6Q2FVSC.js → auto-sync-GRUJFD2F.js} +3 -3
- 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 +2 -2
- package/dist/briefing.js +14 -14
- 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/{catalog-DjTLVOYp.d.ts → catalog-C1qHsGew.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +16 -16
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
- package/dist/{chunk-RJ57OOCD.js → chunk-2J4TIFBK.js} +3 -3
- package/dist/{chunk-AU7Q3LSC.js → chunk-2QSZNTDO.js} +4 -4
- package/dist/{chunk-P6GKRT2H.js → chunk-2Z3DG5CQ.js} +1 -1
- package/dist/{chunk-BO4PWIJY.js → chunk-3LADWWMA.js} +3 -3
- package/dist/{chunk-P7LVYPIX.js → chunk-3LJPSRAN.js} +3 -3
- package/dist/{chunk-ZKZCJRRO.js → chunk-43HMVVOL.js} +2 -2
- package/dist/{chunk-3TSU662L.js → chunk-46QMN7I7.js} +5 -5
- package/dist/{chunk-HODFGQGT.js → chunk-4HYNMLT6.js} +2 -2
- package/dist/{chunk-HTOWFFAI.js → chunk-5CF2R4NS.js} +2 -2
- package/dist/{chunk-QVI63XSO.js → chunk-5MF4EGL5.js} +50 -50
- package/dist/{chunk-KLSPKMIO.js → chunk-5SGOARQJ.js} +2 -2
- package/dist/{chunk-JGXMA6HL.js → chunk-6FUMA6AA.js} +2 -2
- package/dist/chunk-6MINUTGJ.js +64 -0
- package/dist/chunk-6MINUTGJ.js.map +1 -0
- package/dist/{chunk-K2IJH4D3.js → chunk-7RRUHJPG.js} +7 -7
- package/dist/{chunk-I4QAH4SY.js → chunk-7TUB6JWA.js} +3 -3
- package/dist/{chunk-NNBZS3DY.js → chunk-AG46P24C.js} +4 -4
- package/dist/{chunk-B64IVEOH.js → chunk-AWF4CNYJ.js} +2 -2
- package/dist/{chunk-C25N5HWX.js → chunk-B2AGUKSS.js} +2 -2
- package/dist/{chunk-7ZMU4XQT.js → chunk-BR3OOQZQ.js} +2 -2
- package/dist/{chunk-TRLCMLX7.js → chunk-BZTJEILZ.js} +2 -2
- package/dist/{chunk-OLBZ2WGG.js → chunk-C2JCVZWX.js} +2 -2
- package/dist/{chunk-YWN3GYI2.js → chunk-CASWJ2HM.js} +2 -2
- package/dist/{chunk-S35IIP5P.js → chunk-CFKCFY4B.js} +2 -2
- package/dist/{chunk-S5G2LAL7.js → chunk-CHWUICVY.js} +4 -4
- package/dist/{chunk-7JV4JST3.js → chunk-CVJMGVEW.js} +47 -47
- package/dist/{chunk-BE4Y6GK6.js → chunk-D35XLYQ7.js} +11 -11
- package/dist/{chunk-DA4ZMCBU.js → chunk-D5ZNOKR7.js} +3 -3
- package/dist/{chunk-BEXFNGQ3.js → chunk-DK6GMO6D.js} +3 -3
- package/dist/{chunk-I6DUKBUI.js → chunk-DP4EBV7C.js} +2 -2
- package/dist/{chunk-W6GEMUZM.js → chunk-EFCBJDYE.js} +13 -13
- package/dist/{chunk-XMIAU4CO.js → chunk-EJ5RKUXW.js} +2 -2
- package/dist/{chunk-LF6SHWVV.js → chunk-F5UWQ4LX.js} +2 -2
- package/dist/{chunk-XQGFIAG7.js → chunk-FB7LAJQM.js} +2 -2
- package/dist/{chunk-OAKATRAN.js → chunk-G6N654ND.js} +10 -10
- package/dist/{chunk-2EHDPHMD.js → chunk-GGYDJJBO.js} +2 -2
- package/dist/{chunk-VAMZYOOV.js → chunk-HOUST5UX.js} +2 -2
- package/dist/{chunk-NHLEFBE2.js → chunk-I4Y6TBD7.js} +3 -3
- package/dist/{chunk-W272SWN7.js → chunk-I7FY43VC.js} +7 -7
- package/dist/{chunk-MSDIETFC.js → chunk-IZZ7Q2RJ.js} +56 -47
- package/dist/chunk-IZZ7Q2RJ.js.map +1 -0
- package/dist/{chunk-CTCGHNWN.js → chunk-J2R275FN.js} +4 -4
- package/dist/{chunk-XJJYSX6F.js → chunk-JCUG7AXZ.js} +4 -4
- package/dist/{chunk-ZRUEP4IK.js → chunk-JIM4BIOC.js} +30 -49
- package/dist/chunk-JIM4BIOC.js.map +1 -0
- package/dist/{chunk-BX6GW4KC.js → chunk-JMAG7WZ7.js} +2 -2
- package/dist/{chunk-NF3NMAG7.js → chunk-JOYC4RYC.js} +2 -2
- package/dist/{chunk-5JQV4T5Q.js → chunk-JZ6EYAVP.js} +2 -2
- package/dist/{chunk-QRDSXR3V.js → chunk-KA2HZCMG.js} +2 -2
- package/dist/{chunk-7LCGFUMB.js → chunk-KQAFEZQX.js} +4 -4
- package/dist/{chunk-ETZ7KKOS.js → chunk-KTVSPFCQ.js} +2 -2
- package/dist/{chunk-PAWIY5OQ.js → chunk-L74A6NTI.js} +6 -6
- package/dist/{chunk-2XJDAEAM.js → chunk-LFK623SF.js} +5 -5
- package/dist/chunk-LVE64P5Y.js +80 -0
- package/dist/chunk-LVE64P5Y.js.map +1 -0
- package/dist/{chunk-IEZ6CGTW.js → chunk-N3SS45OW.js} +115 -55
- package/dist/chunk-N3SS45OW.js.map +1 -0
- package/dist/{chunk-QUVWFZOU.js → chunk-N7JK2RKG.js} +2 -2
- package/dist/{chunk-BFDOBESV.js → chunk-NYRB7BKY.js} +2 -2
- package/dist/{chunk-LDOQE34V.js → chunk-NZGO2GKL.js} +2 -2
- package/dist/{chunk-VYD63IFH.js → chunk-OGTKQ5MJ.js} +3 -3
- package/dist/{chunk-BIJAWZYW.js → chunk-OLT3YTDH.js} +4 -4
- package/dist/{chunk-F2ERDKY2.js → chunk-PC7WNIRL.js} +17 -17
- package/dist/{chunk-3BS2OGDT.js → chunk-PPOT6SPR.js} +5 -5
- package/dist/{chunk-G7VEQEMG.js → chunk-QVSRE355.js} +65 -39
- package/dist/chunk-QVSRE355.js.map +1 -0
- package/dist/{chunk-LUDXSSTW.js → chunk-R7LY4YKF.js} +2 -2
- package/dist/{chunk-N37X5RU7.js → chunk-RACZB5HT.js} +4 -4
- package/dist/{chunk-LJAP4KSW.js → chunk-RO2X2EYM.js} +2 -2
- package/dist/{chunk-5YQ7RFSO.js → chunk-S37NN23M.js} +2 -2
- package/dist/{chunk-DDX6KIXF.js → chunk-SB4OBB7P.js} +2 -2
- package/dist/{chunk-JHTF22NQ.js → chunk-TA7UZZMW.js} +2 -2
- package/dist/{chunk-4UVDLNHQ.js → chunk-UMEOXLIZ.js} +2 -2
- package/dist/{chunk-63I7LMLG.js → chunk-WL5PR5YC.js} +2 -2
- package/dist/{chunk-H5IIBGDM.js → chunk-X33MJFD2.js} +2 -2
- package/dist/{chunk-SXHBZXHK.js → chunk-XJJLWTLW.js} +5 -5
- package/dist/{chunk-OYV6RKPM.js → chunk-XOQGUGJL.js} +2 -6
- package/dist/chunk-XOQGUGJL.js.map +1 -0
- package/dist/{chunk-GIC6BASP.js → chunk-XZBXINXZ.js} +4 -4
- package/dist/{chunk-APZXA4WI.js → chunk-YVLENSNS.js} +2 -2
- package/dist/{chunk-OUKBMQ2O.js → chunk-Z3SQEEB6.js} +2 -2
- package/dist/{chunk-NN5CQTAJ.js → chunk-ZEBRENA6.js} +2 -2
- package/dist/{chunk-5H2G5X4R.js → chunk-ZJWDWPX6.js} +3 -3
- package/dist/{chunk-M7DGN6JZ.js → chunk-ZL3XX5LW.js} +2 -2
- package/dist/{chunk-4WIKMOE3.js → chunk-ZZM476NV.js} +1 -1
- package/dist/{cli-BI9YYpKx.d.ts → cli-DN9LpWf0.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +92 -88
- package/dist/coding/export-okf-codegraph.d.ts +1 -1
- package/dist/coding/export-okf-codegraph.js +13 -13
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +13 -13
- 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 +7 -7
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +13 -13
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +13 -13
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +3 -3
- package/dist/converge-config.d.ts +16 -2
- package/dist/converge-config.js +9 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +15 -15
- 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/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +15 -15
- package/dist/cross-lingual-recall.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/deep-recall-http-glue.d.ts +11 -11
- package/dist/deep-recall-http-glue.js +6 -6
- package/dist/deep-recall-mcp-tools.d.ts +11 -11
- package/dist/deep-recall-policy-llm.d.ts +1 -1
- package/dist/deep-recall-seeds.d.ts +1 -1
- package/dist/deep-recall.js +2 -2
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-37JdQv_3.d.ts → dependency-propagation-delivery-DjpUlhLi.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-origin-fields.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +13 -13
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/eval-trajectory-contracts.d.ts +1 -1
- package/dist/eval-trajectory-store.d.ts +1 -1
- package/dist/eval-trajectory.d.ts +1 -1
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/external-wiki-access.d.ts +11 -11
- package/dist/external-wiki-access.js +50 -46
- 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-rules.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +16 -16
- 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-decay-FXGELBFA.js → graph-edge-decay-DGTBFALQ.js} +4 -4
- package/dist/graph-edge-decay-DGTBFALQ.js.map +1 -0
- 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-snapshot.js +3 -3
- package/dist/graph.d.ts +1 -1
- package/dist/graph.js +2 -2
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/{index-DquhYqsc.d.ts → index-CsUrdMyL.d.ts} +2 -2
- package/dist/index.d.ts +26 -26
- package/dist/index.js +138 -127
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- 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/location/index.d.ts +3 -3
- package/dist/location/index.js +15 -15
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +13 -13
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -13
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +14 -14
- package/dist/{maintenance-CizZOycr.d.ts → maintenance-D1GRGLTE.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-controller.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-subject-cli.d.ts +11 -11
- package/dist/memory-subject.d.ts +11 -11
- 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 +14 -14
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +13 -13
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/offline-sync.js +2 -2
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +16 -16
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +30 -30
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +21 -21
- package/dist/{orchestrator-DqLcuNMP.d.ts → orchestrator-DeqaPGT5.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +111 -110
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-DbJpmcRu.d.ts → pipeline-umUzU0D1.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-Bocro5ZU.d.ts → public-http-C1ht4oDJ.d.ts} +1 -1
- package/dist/{qmd-DA_7fbSz.d.ts → qmd-BasT78PP.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- 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-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-navigate-access.d.ts +1 -1
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.d.ts +1 -1
- package/dist/recall-navigate-disclosure.js +1 -1
- package/dist/recall-navigate.d.ts +1 -1
- package/dist/recall-navigate.js +2 -2
- 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-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/cursor.js +2 -2
- package/dist/reconcile/manifest.d.ts +1 -1
- package/dist/reconcile/manifest.js +3 -3
- package/dist/reconcile/plan.d.ts +16 -1
- package/dist/reconcile/plan.js +2 -2
- 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/resume-bundles.js +8 -8
- 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/schemas.d.ts +42 -42
- package/dist/{scope-profiles-BpiWKZzx.d.ts → scope-profiles-DXYzyOXW.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 +8 -8
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +13 -13
- 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-NJpaZpkY.d.ts → semantic-consolidation-CqDeaY0U.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +14 -14
- package/dist/semantic-rule-promotion.js +13 -13
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +13 -13
- package/dist/{service-DdlZjX1D.d.ts → service-BKD-DVYZ.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/standup/build.js +13 -13
- package/dist/{storage-C7BWrpU9.d.ts → storage-BcFd1lN_.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +12 -12
- package/dist/subject-config.d.ts +1 -1
- package/dist/summarizer.d.ts +30 -4
- package/dist/summarizer.js +6 -4
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +14 -14
- package/dist/support-passport/index.js +52 -48
- 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/transcript.d.ts +1 -1
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/export-okf.d.ts +1 -1
- package/dist/transfer/export-okf.js +14 -14
- package/dist/transfer/types.d.ts +12 -12
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-Cy1l6fzp.d.ts → types-BRg3tMyp.d.ts} +2 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +13 -13
- package/dist/who-knows-cli.d.ts +11 -11
- package/dist/who-knows-cli.js +14 -14
- package/dist/who-knows.d.ts +11 -11
- package/dist/who-knows.js +13 -13
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-mcp-output-schemas.ts +60 -34
- package/src/access-observe-transcript-persistence.test.ts +252 -0
- package/src/access-observe-transcript.ts +153 -0
- package/src/access-observe-write-surface.ts +234 -224
- package/src/access-service.ts +33 -28
- package/src/converge-config.ts +40 -3
- package/src/index.ts +1 -1
- package/src/reconcile/plan.test.ts +118 -88
- package/src/reconcile/plan.ts +98 -84
- package/src/summarizer.ts +217 -111
- package/src/summary-snapshot.test.ts +8 -6
- package/src/types.ts +47 -44
- package/dist/chunk-G7VEQEMG.js.map +0 -1
- package/dist/chunk-HBVPYRDW.js +0 -39
- package/dist/chunk-HBVPYRDW.js.map +0 -1
- package/dist/chunk-IEZ6CGTW.js.map +0 -1
- package/dist/chunk-MSDIETFC.js.map +0 -1
- package/dist/chunk-OYV6RKPM.js.map +0 -1
- package/dist/chunk-ZRUEP4IK.js.map +0 -1
- /package/dist/{graph-edge-decay-FXGELBFA.js.map → access-observe-transcript.js.map} +0 -0
- /package/dist/{auto-sync-Q6Q2FVSC.js.map → auto-sync-GRUJFD2F.js.map} +0 -0
- /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
- /package/dist/{chunk-RJ57OOCD.js.map → chunk-2J4TIFBK.js.map} +0 -0
- /package/dist/{chunk-AU7Q3LSC.js.map → chunk-2QSZNTDO.js.map} +0 -0
- /package/dist/{chunk-P6GKRT2H.js.map → chunk-2Z3DG5CQ.js.map} +0 -0
- /package/dist/{chunk-BO4PWIJY.js.map → chunk-3LADWWMA.js.map} +0 -0
- /package/dist/{chunk-P7LVYPIX.js.map → chunk-3LJPSRAN.js.map} +0 -0
- /package/dist/{chunk-ZKZCJRRO.js.map → chunk-43HMVVOL.js.map} +0 -0
- /package/dist/{chunk-3TSU662L.js.map → chunk-46QMN7I7.js.map} +0 -0
- /package/dist/{chunk-HODFGQGT.js.map → chunk-4HYNMLT6.js.map} +0 -0
- /package/dist/{chunk-HTOWFFAI.js.map → chunk-5CF2R4NS.js.map} +0 -0
- /package/dist/{chunk-QVI63XSO.js.map → chunk-5MF4EGL5.js.map} +0 -0
- /package/dist/{chunk-KLSPKMIO.js.map → chunk-5SGOARQJ.js.map} +0 -0
- /package/dist/{chunk-JGXMA6HL.js.map → chunk-6FUMA6AA.js.map} +0 -0
- /package/dist/{chunk-K2IJH4D3.js.map → chunk-7RRUHJPG.js.map} +0 -0
- /package/dist/{chunk-I4QAH4SY.js.map → chunk-7TUB6JWA.js.map} +0 -0
- /package/dist/{chunk-NNBZS3DY.js.map → chunk-AG46P24C.js.map} +0 -0
- /package/dist/{chunk-B64IVEOH.js.map → chunk-AWF4CNYJ.js.map} +0 -0
- /package/dist/{chunk-C25N5HWX.js.map → chunk-B2AGUKSS.js.map} +0 -0
- /package/dist/{chunk-7ZMU4XQT.js.map → chunk-BR3OOQZQ.js.map} +0 -0
- /package/dist/{chunk-TRLCMLX7.js.map → chunk-BZTJEILZ.js.map} +0 -0
- /package/dist/{chunk-OLBZ2WGG.js.map → chunk-C2JCVZWX.js.map} +0 -0
- /package/dist/{chunk-YWN3GYI2.js.map → chunk-CASWJ2HM.js.map} +0 -0
- /package/dist/{chunk-S35IIP5P.js.map → chunk-CFKCFY4B.js.map} +0 -0
- /package/dist/{chunk-S5G2LAL7.js.map → chunk-CHWUICVY.js.map} +0 -0
- /package/dist/{chunk-7JV4JST3.js.map → chunk-CVJMGVEW.js.map} +0 -0
- /package/dist/{chunk-BE4Y6GK6.js.map → chunk-D35XLYQ7.js.map} +0 -0
- /package/dist/{chunk-DA4ZMCBU.js.map → chunk-D5ZNOKR7.js.map} +0 -0
- /package/dist/{chunk-BEXFNGQ3.js.map → chunk-DK6GMO6D.js.map} +0 -0
- /package/dist/{chunk-I6DUKBUI.js.map → chunk-DP4EBV7C.js.map} +0 -0
- /package/dist/{chunk-W6GEMUZM.js.map → chunk-EFCBJDYE.js.map} +0 -0
- /package/dist/{chunk-XMIAU4CO.js.map → chunk-EJ5RKUXW.js.map} +0 -0
- /package/dist/{chunk-LF6SHWVV.js.map → chunk-F5UWQ4LX.js.map} +0 -0
- /package/dist/{chunk-XQGFIAG7.js.map → chunk-FB7LAJQM.js.map} +0 -0
- /package/dist/{chunk-OAKATRAN.js.map → chunk-G6N654ND.js.map} +0 -0
- /package/dist/{chunk-2EHDPHMD.js.map → chunk-GGYDJJBO.js.map} +0 -0
- /package/dist/{chunk-VAMZYOOV.js.map → chunk-HOUST5UX.js.map} +0 -0
- /package/dist/{chunk-NHLEFBE2.js.map → chunk-I4Y6TBD7.js.map} +0 -0
- /package/dist/{chunk-W272SWN7.js.map → chunk-I7FY43VC.js.map} +0 -0
- /package/dist/{chunk-CTCGHNWN.js.map → chunk-J2R275FN.js.map} +0 -0
- /package/dist/{chunk-XJJYSX6F.js.map → chunk-JCUG7AXZ.js.map} +0 -0
- /package/dist/{chunk-BX6GW4KC.js.map → chunk-JMAG7WZ7.js.map} +0 -0
- /package/dist/{chunk-NF3NMAG7.js.map → chunk-JOYC4RYC.js.map} +0 -0
- /package/dist/{chunk-5JQV4T5Q.js.map → chunk-JZ6EYAVP.js.map} +0 -0
- /package/dist/{chunk-QRDSXR3V.js.map → chunk-KA2HZCMG.js.map} +0 -0
- /package/dist/{chunk-7LCGFUMB.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-ETZ7KKOS.js.map → chunk-KTVSPFCQ.js.map} +0 -0
- /package/dist/{chunk-PAWIY5OQ.js.map → chunk-L74A6NTI.js.map} +0 -0
- /package/dist/{chunk-2XJDAEAM.js.map → chunk-LFK623SF.js.map} +0 -0
- /package/dist/{chunk-QUVWFZOU.js.map → chunk-N7JK2RKG.js.map} +0 -0
- /package/dist/{chunk-BFDOBESV.js.map → chunk-NYRB7BKY.js.map} +0 -0
- /package/dist/{chunk-LDOQE34V.js.map → chunk-NZGO2GKL.js.map} +0 -0
- /package/dist/{chunk-VYD63IFH.js.map → chunk-OGTKQ5MJ.js.map} +0 -0
- /package/dist/{chunk-BIJAWZYW.js.map → chunk-OLT3YTDH.js.map} +0 -0
- /package/dist/{chunk-F2ERDKY2.js.map → chunk-PC7WNIRL.js.map} +0 -0
- /package/dist/{chunk-3BS2OGDT.js.map → chunk-PPOT6SPR.js.map} +0 -0
- /package/dist/{chunk-LUDXSSTW.js.map → chunk-R7LY4YKF.js.map} +0 -0
- /package/dist/{chunk-N37X5RU7.js.map → chunk-RACZB5HT.js.map} +0 -0
- /package/dist/{chunk-LJAP4KSW.js.map → chunk-RO2X2EYM.js.map} +0 -0
- /package/dist/{chunk-5YQ7RFSO.js.map → chunk-S37NN23M.js.map} +0 -0
- /package/dist/{chunk-DDX6KIXF.js.map → chunk-SB4OBB7P.js.map} +0 -0
- /package/dist/{chunk-JHTF22NQ.js.map → chunk-TA7UZZMW.js.map} +0 -0
- /package/dist/{chunk-4UVDLNHQ.js.map → chunk-UMEOXLIZ.js.map} +0 -0
- /package/dist/{chunk-63I7LMLG.js.map → chunk-WL5PR5YC.js.map} +0 -0
- /package/dist/{chunk-H5IIBGDM.js.map → chunk-X33MJFD2.js.map} +0 -0
- /package/dist/{chunk-SXHBZXHK.js.map → chunk-XJJLWTLW.js.map} +0 -0
- /package/dist/{chunk-GIC6BASP.js.map → chunk-XZBXINXZ.js.map} +0 -0
- /package/dist/{chunk-APZXA4WI.js.map → chunk-YVLENSNS.js.map} +0 -0
- /package/dist/{chunk-OUKBMQ2O.js.map → chunk-Z3SQEEB6.js.map} +0 -0
- /package/dist/{chunk-NN5CQTAJ.js.map → chunk-ZEBRENA6.js.map} +0 -0
- /package/dist/{chunk-5H2G5X4R.js.map → chunk-ZJWDWPX6.js.map} +0 -0
- /package/dist/{chunk-M7DGN6JZ.js.map → chunk-ZL3XX5LW.js.map} +0 -0
- /package/dist/{chunk-4WIKMOE3.js.map → chunk-ZZM476NV.js.map} +0 -0
package/src/summarizer.ts
CHANGED
|
@@ -9,20 +9,14 @@ import { extractJsonCandidates } from "./json-extract.js";
|
|
|
9
9
|
import type { HourlySummary, TranscriptEntry, PluginConfig, GatewayConfig } from "./types.js";
|
|
10
10
|
import type { TranscriptManager } from "./transcript.js";
|
|
11
11
|
import { readSummarySnapshot, upsertSummarySnapshot, writeSummarySnapshot } from "./summary-snapshot.js";
|
|
12
|
-
import {
|
|
13
|
-
encodeStoragePathSegment,
|
|
14
|
-
resolveSafeStoragePath,
|
|
15
|
-
} from "./storage-paths.js";
|
|
12
|
+
import { encodeStoragePathSegment, resolveSafeStoragePath } from "./storage-paths.js";
|
|
16
13
|
import { sessionStoragePaths } from "./session-identity.js";
|
|
17
14
|
import { resolveLocalLlmCapabilities } from "./capabilities.js";
|
|
18
15
|
import { resolvePipelineProcessingCapabilities } from "./capabilities.js";
|
|
19
16
|
|
|
20
17
|
// Schema for LLM summary output
|
|
21
18
|
const HourlySummarySchema = z.object({
|
|
22
|
-
bullets: z
|
|
23
|
-
.array(z.string().trim().min(1))
|
|
24
|
-
.min(1)
|
|
25
|
-
.describe("3-5 bullet points summarizing the hour's activity"),
|
|
19
|
+
bullets: z.array(z.string().trim().min(1)).min(1).describe("3-5 bullet points summarizing the hour's activity"),
|
|
26
20
|
});
|
|
27
21
|
|
|
28
22
|
type HourlySummaryResult = z.infer<typeof HourlySummarySchema>;
|
|
@@ -47,6 +41,68 @@ function escapeRegExp(value: string): string {
|
|
|
47
41
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
48
42
|
}
|
|
49
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Outcome stats of one `runHourly` pass (issue #2783). The summarizer must
|
|
46
|
+
* not report success on empty work: an empty or stale transcript store is
|
|
47
|
+
* the delegate-mode starvation signature, and callers surface these counts
|
|
48
|
+
* and the staleness flag as a distinct warning instead of a bare ok.
|
|
49
|
+
*/
|
|
50
|
+
export interface HourlySummarizerRunStats {
|
|
51
|
+
sessionsConsidered: number;
|
|
52
|
+
sessionsWithEntries: number;
|
|
53
|
+
summariesWritten: number;
|
|
54
|
+
/** True when the newest transcript entry across the store is older than STALE_STORE_MS. */
|
|
55
|
+
staleStore: boolean;
|
|
56
|
+
/** ISO timestamp of the newest transcript entry seen by the scan, when any exist. */
|
|
57
|
+
newestEntryTimestamp: string | null;
|
|
58
|
+
/** True when the transcript scan itself FAILED (unreadable store) — distinct from an empty store. */
|
|
59
|
+
scanFailed: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** A store whose newest entry is older than this is considered stale (starvation signal, issue #2783). */
|
|
63
|
+
const STALE_STORE_MS = 2 * 60 * 60 * 1000;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Interpret one {@link HourlySummarizerRunStats} into the operator-facing
|
|
67
|
+
* message/warning (issue #2783). Every degraded shape — failed scan, empty
|
|
68
|
+
* store, backend-down, stale store — is DISTINCT from success; monitoring
|
|
69
|
+
* alerts on `warning`, never on `ok` (ok only means "the run completed").
|
|
70
|
+
*/
|
|
71
|
+
export function summarizeHourlyStatus(stats: HourlySummarizerRunStats): {
|
|
72
|
+
message: string;
|
|
73
|
+
warning?: string;
|
|
74
|
+
} {
|
|
75
|
+
if (stats.scanFailed) {
|
|
76
|
+
return {
|
|
77
|
+
message:
|
|
78
|
+
"Hourly summarization completed, but the transcript store scan FAILED (unreadable directory or I/O error). Investigate the daemon's memoryDir.",
|
|
79
|
+
warning: "transcript store scan failed",
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (stats.sessionsConsidered === 0) {
|
|
83
|
+
return {
|
|
84
|
+
message:
|
|
85
|
+
"Hourly summarization completed, but the transcript store is empty — no sessions found. If turns are ingested via observe, transcript persistence may be disabled or failing.",
|
|
86
|
+
warning: "transcript store is empty",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (stats.sessionsWithEntries > 0 && stats.summariesWritten === 0) {
|
|
90
|
+
return {
|
|
91
|
+
message: `Hourly summarization found ${stats.sessionsWithEntries} session(s) with transcript entries but wrote no summaries — the summarizer backend may be down.`,
|
|
92
|
+
warning: "sessions with entries produced no summaries",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (stats.sessionsWithEntries === 0 && stats.staleStore) {
|
|
96
|
+
return {
|
|
97
|
+
message: `Hourly summarization completed with no transcript entries for the target hour, and the store looks stale (newest entry ${stats.newestEntryTimestamp ?? "unknown"}).`,
|
|
98
|
+
warning: "no transcript entries for the target hour and no new entries recently",
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
message: `Hourly summarization completed: ${stats.summariesWritten} summar${stats.summariesWritten === 1 ? "y" : "ies"} written across ${stats.sessionsWithEntries} session${stats.sessionsWithEntries === 1 ? "" : "s"} with transcript entries.`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
50
106
|
export class HourlySummarizer {
|
|
51
107
|
private summariesDir: string;
|
|
52
108
|
private config: PluginConfig;
|
|
@@ -55,7 +111,12 @@ export class HourlySummarizer {
|
|
|
55
111
|
private modelRegistry: ModelRegistry;
|
|
56
112
|
private transcript?: TranscriptManager;
|
|
57
113
|
|
|
58
|
-
constructor(
|
|
114
|
+
constructor(
|
|
115
|
+
config: PluginConfig,
|
|
116
|
+
gatewayConfig?: GatewayConfig,
|
|
117
|
+
modelRegistry?: ModelRegistry,
|
|
118
|
+
transcript?: TranscriptManager
|
|
119
|
+
) {
|
|
59
120
|
this.config = config;
|
|
60
121
|
this.summariesDir = path.join(config.memoryDir, "summaries", "hourly");
|
|
61
122
|
this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);
|
|
@@ -65,12 +126,13 @@ export class HourlySummarizer {
|
|
|
65
126
|
this.localLlm = new LocalLlmClient(config, this.modelRegistry);
|
|
66
127
|
|
|
67
128
|
// Initialize fallback client with gateway config
|
|
68
|
-
this.fallbackLlm = new FallbackLlmClient(
|
|
69
|
-
gatewayConfig,
|
|
70
|
-
fallbackLlmRuntimeContextFromConfig(config),
|
|
71
|
-
);
|
|
129
|
+
this.fallbackLlm = new FallbackLlmClient(gatewayConfig, fallbackLlmRuntimeContextFromConfig(config));
|
|
72
130
|
|
|
73
|
-
if (
|
|
131
|
+
if (
|
|
132
|
+
!gatewayConfig?.agents?.defaults?.model?.primary &&
|
|
133
|
+
!resolveLocalLlmCapabilities(config).localLlm &&
|
|
134
|
+
config.modelSource !== "gateway"
|
|
135
|
+
) {
|
|
74
136
|
log.warn("no gateway default AI and local LLM disabled — hourly summarization disabled");
|
|
75
137
|
}
|
|
76
138
|
}
|
|
@@ -83,7 +145,9 @@ export class HourlySummarizer {
|
|
|
83
145
|
return resolveLocalLlmCapabilities(this.config).localLlm && !this.useGatewayModelSource;
|
|
84
146
|
}
|
|
85
147
|
|
|
86
|
-
private withGatewayAgent(
|
|
148
|
+
private withGatewayAgent(
|
|
149
|
+
options: import("./fallback-llm.js").FallbackLlmOptions
|
|
150
|
+
): import("./fallback-llm.js").FallbackLlmOptions {
|
|
87
151
|
if (!this.useGatewayModelSource) return options;
|
|
88
152
|
// Shared resolution (taskModelChain > gatewayAgentId) — gotcha #22. Issue #1365.
|
|
89
153
|
return { ...options, ...gatewayTaskChainOptions(this.config) };
|
|
@@ -95,10 +159,7 @@ export class HourlySummarizer {
|
|
|
95
159
|
}
|
|
96
160
|
|
|
97
161
|
private async summarySessionDir(sessionKey: string): Promise<string> {
|
|
98
|
-
return resolveSafeStoragePath(
|
|
99
|
-
this.summariesDir,
|
|
100
|
-
encodeStoragePathSegment(sessionKey, "session"),
|
|
101
|
-
);
|
|
162
|
+
return resolveSafeStoragePath(this.summariesDir, encodeStoragePathSegment(sessionKey, "session"));
|
|
102
163
|
}
|
|
103
164
|
|
|
104
165
|
private async legacySummarySessionDir(sessionKey: string): Promise<string | null> {
|
|
@@ -127,9 +188,7 @@ export class HourlySummarizer {
|
|
|
127
188
|
if (entries.length === 0) return null;
|
|
128
189
|
|
|
129
190
|
// Format entries for the LLM
|
|
130
|
-
const conversation = entries
|
|
131
|
-
.map((e) => `[${e.role}] ${e.content}`)
|
|
132
|
-
.join("\n\n");
|
|
191
|
+
const conversation = entries.map((e) => `[${e.role}] ${e.content}`).join("\n\n");
|
|
133
192
|
|
|
134
193
|
if (resolvePipelineProcessingCapabilities(this.config).hourlySummariesExtended) {
|
|
135
194
|
const extended = await this.generateExtended(sessionKey, hourStart, conversation, entries);
|
|
@@ -163,9 +222,7 @@ export class HourlySummarizer {
|
|
|
163
222
|
const localResult = await this.generateWithLocalLlm(conversation);
|
|
164
223
|
if (localResult) {
|
|
165
224
|
const durationMs = Date.now() - startTime;
|
|
166
|
-
log.debug(
|
|
167
|
-
`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms using local LLM`
|
|
168
|
-
);
|
|
225
|
+
log.debug(`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms using local LLM`);
|
|
169
226
|
return {
|
|
170
227
|
hour: hourIso,
|
|
171
228
|
sessionKey,
|
|
@@ -217,15 +274,13 @@ Respond with valid JSON matching this schema:
|
|
|
217
274
|
const result = await this.fallbackLlm.parseWithSchema(
|
|
218
275
|
messages,
|
|
219
276
|
HourlySummarySchema,
|
|
220
|
-
this.withGatewayAgent({ temperature: 0.3, maxTokens: 8192 })
|
|
277
|
+
this.withGatewayAgent({ temperature: 0.3, maxTokens: 8192 })
|
|
221
278
|
);
|
|
222
279
|
|
|
223
280
|
const durationMs = Date.now() - startTime;
|
|
224
281
|
|
|
225
282
|
if (result) {
|
|
226
|
-
log.debug(
|
|
227
|
-
`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms via fallback`,
|
|
228
|
-
);
|
|
283
|
+
log.debug(`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms via fallback`);
|
|
229
284
|
return {
|
|
230
285
|
hour: hourIso,
|
|
231
286
|
sessionKey,
|
|
@@ -247,7 +302,7 @@ Respond with valid JSON matching this schema:
|
|
|
247
302
|
sessionKey: string,
|
|
248
303
|
hourStart: Date,
|
|
249
304
|
conversation: string,
|
|
250
|
-
entries: TranscriptEntry[]
|
|
305
|
+
entries: TranscriptEntry[]
|
|
251
306
|
): Promise<(HourlySummaryExtendedResult & { _meta: HourlySummaryExtendedMeta }) | null> {
|
|
252
307
|
const hourIso = hourStart.toISOString();
|
|
253
308
|
const startTime = Date.now();
|
|
@@ -261,12 +316,17 @@ Respond with valid JSON matching this schema:
|
|
|
261
316
|
|
|
262
317
|
const sys = `You are a conversation summarization system.\n\nSummarize the hour into structured sections.\n\nReturn valid JSON matching:\n{\n \"topics\": [\"...\"],\n \"decisions\": [\"...\"],\n \"actionItems\": [\"...\"],\n \"rejected\": [\"...\"]\n}\n\nGuidelines:\n- Prefer concrete topics and decisions.\n- Action items should be imperative.\n- Rejected ideas are things that were explicitly discarded or reversed.\n- If there are none for a section, return an empty array.\n`;
|
|
263
318
|
|
|
264
|
-
const toolStatsLine =
|
|
265
|
-
|
|
266
|
-
|
|
319
|
+
const toolStatsLine =
|
|
320
|
+
Object.keys(toolCounts).length > 0
|
|
321
|
+
? `Tools used (counts): ${Object.entries(toolCounts)
|
|
322
|
+
.sort((a, b) => b[1] - a[1])
|
|
323
|
+
.slice(0, 10)
|
|
324
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
325
|
+
.join(", ")}\n\n`
|
|
326
|
+
: "";
|
|
267
327
|
const userTurns = entries.filter((e) => e.role === "user").length;
|
|
268
328
|
const assistantTurns = entries.filter((e) => e.role === "assistant").length;
|
|
269
|
-
const toolCalls = Object.values(toolCounts).reduce((a,b)=>a+b,0);
|
|
329
|
+
const toolCalls = Object.values(toolCounts).reduce((a, b) => a + b, 0);
|
|
270
330
|
const statsLine = `Stats: userTurns=${userTurns}, assistantTurns=${assistantTurns}, toolCalls=${toolCalls}\n\n`;
|
|
271
331
|
|
|
272
332
|
const user = `Hour: ${hourIso}\nSession: ${sessionKey}\n\n${statsLine}${toolStatsLine}Conversation:\n${conversation}\n`;
|
|
@@ -274,8 +334,14 @@ Respond with valid JSON matching this schema:
|
|
|
274
334
|
// Try local LLM first if enabled
|
|
275
335
|
if (this.shouldUseLocalLlm) {
|
|
276
336
|
try {
|
|
277
|
-
const contextSizes = this.modelRegistry.calculateContextSizes(
|
|
278
|
-
|
|
337
|
+
const contextSizes = this.modelRegistry.calculateContextSizes(
|
|
338
|
+
this.config.localLlmModel,
|
|
339
|
+
this.config.localLlmMaxContext
|
|
340
|
+
);
|
|
341
|
+
const truncated =
|
|
342
|
+
user.length > contextSizes.maxInputChars
|
|
343
|
+
? user.slice(0, contextSizes.maxInputChars) + "\n\n[truncated]"
|
|
344
|
+
: user;
|
|
279
345
|
const response = await this.localLlm.chatCompletion(
|
|
280
346
|
[
|
|
281
347
|
{ role: "system", content: "Output valid JSON only." },
|
|
@@ -286,7 +352,7 @@ Respond with valid JSON matching this schema:
|
|
|
286
352
|
maxTokens: contextSizes.maxOutputTokens,
|
|
287
353
|
operation: "hourly_summary_extended",
|
|
288
354
|
priority: "background",
|
|
289
|
-
}
|
|
355
|
+
}
|
|
290
356
|
);
|
|
291
357
|
if (response?.content) {
|
|
292
358
|
const content = response.content.trim();
|
|
@@ -295,7 +361,7 @@ Respond with valid JSON matching this schema:
|
|
|
295
361
|
const parsed = JSON.parse(candidate);
|
|
296
362
|
const result = HourlySummaryExtendedSchema.parse(parsed);
|
|
297
363
|
log.debug(
|
|
298
|
-
`generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (local)
|
|
364
|
+
`generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (local)`
|
|
299
365
|
);
|
|
300
366
|
return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };
|
|
301
367
|
} catch {
|
|
@@ -316,10 +382,12 @@ Respond with valid JSON matching this schema:
|
|
|
316
382
|
{ role: "user" as const, content: user },
|
|
317
383
|
],
|
|
318
384
|
HourlySummaryExtendedSchema,
|
|
319
|
-
this.withGatewayAgent({ temperature: 0.2, maxTokens: 2048 })
|
|
385
|
+
this.withGatewayAgent({ temperature: 0.2, maxTokens: 2048 })
|
|
320
386
|
);
|
|
321
387
|
if (result) {
|
|
322
|
-
log.debug(
|
|
388
|
+
log.debug(
|
|
389
|
+
`generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (fallback)`
|
|
390
|
+
);
|
|
323
391
|
return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };
|
|
324
392
|
}
|
|
325
393
|
return null;
|
|
@@ -342,9 +410,10 @@ Respond with valid JSON matching this schema:
|
|
|
342
410
|
log.debug(`Summarizer model context: ${contextSizes.description}`);
|
|
343
411
|
|
|
344
412
|
const maxConversationChars = contextSizes.maxInputChars;
|
|
345
|
-
const truncatedConversation =
|
|
346
|
-
|
|
347
|
-
|
|
413
|
+
const truncatedConversation =
|
|
414
|
+
conversation.length > maxConversationChars
|
|
415
|
+
? conversation.slice(0, maxConversationChars) + "\n\n[truncated]"
|
|
416
|
+
: conversation;
|
|
348
417
|
|
|
349
418
|
const instructions = `You are a conversation summarization system. Summarize the following conversation transcript into 3-5 concise bullet points.
|
|
350
419
|
|
|
@@ -373,7 +442,7 @@ Respond with valid JSON matching this schema:
|
|
|
373
442
|
maxTokens: contextSizes.maxOutputTokens,
|
|
374
443
|
operation: "hourly_summary",
|
|
375
444
|
priority: "background",
|
|
376
|
-
}
|
|
445
|
+
}
|
|
377
446
|
);
|
|
378
447
|
|
|
379
448
|
if (!response?.content) {
|
|
@@ -433,9 +502,7 @@ Respond with valid JSON matching this schema:
|
|
|
433
502
|
nextHeaderPattern.lastIndex = sectionStart + hourHeader.length;
|
|
434
503
|
const nextHeader = nextHeaderPattern.exec(existingContent);
|
|
435
504
|
const beforeHour = existingContent.slice(0, sectionStart);
|
|
436
|
-
const afterHour = nextHeader
|
|
437
|
-
? existingContent.slice(nextHeader.index + 1)
|
|
438
|
-
: "";
|
|
505
|
+
const afterHour = nextHeader ? existingContent.slice(nextHeader.index + 1) : "";
|
|
439
506
|
const newSection = this.formatHourSection(summary, hourHeader);
|
|
440
507
|
existingContent = beforeHour + newSection.trimEnd() + (afterHour ? "\n\n" + afterHour : "\n");
|
|
441
508
|
|
|
@@ -459,13 +526,15 @@ Respond with valid JSON matching this schema:
|
|
|
459
526
|
await upsertSummarySnapshot(this.config.memoryDir, summary);
|
|
460
527
|
} catch (error) {
|
|
461
528
|
log.warn(
|
|
462
|
-
`hourly summarizer: failed to update summary snapshot for ${summary.sessionKey} (fail-open): ${String(error)}
|
|
529
|
+
`hourly summarizer: failed to update summary snapshot for ${summary.sessionKey} (fail-open): ${String(error)}`
|
|
463
530
|
);
|
|
464
531
|
}
|
|
465
532
|
}
|
|
466
533
|
|
|
467
534
|
private formatHourSection(summary: HourlySummary, hourHeader: string): string {
|
|
468
|
-
const ext = (summary as any)._extended as
|
|
535
|
+
const ext = (summary as any)._extended as
|
|
536
|
+
| (HourlySummaryExtendedResult & { _meta?: HourlySummaryExtendedMeta })
|
|
537
|
+
| undefined;
|
|
469
538
|
const meta = (summary as any)._extendedMeta as HourlySummaryExtendedMeta | undefined;
|
|
470
539
|
const lines: string[] = [hourHeader, ""];
|
|
471
540
|
|
|
@@ -537,24 +606,18 @@ Respond with valid JSON matching this schema:
|
|
|
537
606
|
}
|
|
538
607
|
|
|
539
608
|
const sortedSummaries = Array.from(byHour.values()).sort(
|
|
540
|
-
(a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime()
|
|
609
|
+
(a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime()
|
|
541
610
|
);
|
|
542
611
|
|
|
543
612
|
// Filter to recent hours while materializing the full parsed history.
|
|
544
|
-
const recent = sortedSummaries.filter(
|
|
545
|
-
(s) => new Date(s.hour).getTime() >= cutoffTime,
|
|
546
|
-
);
|
|
613
|
+
const recent = sortedSummaries.filter((s) => new Date(s.hour).getTime() >= cutoffTime);
|
|
547
614
|
|
|
548
615
|
if (sortedSummaries.length > 0) {
|
|
549
616
|
try {
|
|
550
|
-
await writeSummarySnapshot(
|
|
551
|
-
this.config.memoryDir,
|
|
552
|
-
sessionKey,
|
|
553
|
-
sortedSummaries,
|
|
554
|
-
);
|
|
617
|
+
await writeSummarySnapshot(this.config.memoryDir, sessionKey, sortedSummaries);
|
|
555
618
|
} catch (error) {
|
|
556
619
|
log.warn(
|
|
557
|
-
`hourly summarizer: failed to materialize summary snapshot for ${sessionKey} (fail-open): ${String(error)}
|
|
620
|
+
`hourly summarizer: failed to materialize summary snapshot for ${sessionKey} (fail-open): ${String(error)}`
|
|
558
621
|
);
|
|
559
622
|
}
|
|
560
623
|
}
|
|
@@ -566,10 +629,7 @@ Respond with valid JSON matching this schema:
|
|
|
566
629
|
}
|
|
567
630
|
}
|
|
568
631
|
|
|
569
|
-
private async readSummaryDir(
|
|
570
|
-
sessionDir: string,
|
|
571
|
-
sessionKey: string,
|
|
572
|
-
): Promise<HourlySummary[]> {
|
|
632
|
+
private async readSummaryDir(sessionDir: string, sessionKey: string): Promise<HourlySummary[]> {
|
|
573
633
|
let files: string[];
|
|
574
634
|
try {
|
|
575
635
|
files = await readdir(sessionDir);
|
|
@@ -594,11 +654,7 @@ Respond with valid JSON matching this schema:
|
|
|
594
654
|
return summaries;
|
|
595
655
|
}
|
|
596
656
|
|
|
597
|
-
private parseSummaryFile(
|
|
598
|
-
content: string,
|
|
599
|
-
sessionKey: string,
|
|
600
|
-
filename: string
|
|
601
|
-
): HourlySummary[] {
|
|
657
|
+
private parseSummaryFile(content: string, sessionKey: string, filename: string): HourlySummary[] {
|
|
602
658
|
const summaries: HourlySummary[] = [];
|
|
603
659
|
|
|
604
660
|
// Extract date from filename (YYYY-MM-DD.md)
|
|
@@ -671,11 +727,16 @@ Respond with valid JSON matching this schema:
|
|
|
671
727
|
}
|
|
672
728
|
|
|
673
729
|
// Main entry point for cron job
|
|
674
|
-
async runHourly(): Promise<
|
|
730
|
+
async runHourly(): Promise<HourlySummarizerRunStats> {
|
|
675
731
|
log.debug("running hourly summary generation");
|
|
676
732
|
|
|
677
|
-
// Get active sessions from transcript
|
|
678
|
-
|
|
733
|
+
// Get active sessions from transcript. The scan outcome is kept LOCAL to
|
|
734
|
+
// this invocation (review round 2): shared instance state would let two
|
|
735
|
+
// concurrent runHourly calls cross-report each other's timestamps.
|
|
736
|
+
const scan = await this.getActiveSessions();
|
|
737
|
+
const sessions = scan.sessionKeys;
|
|
738
|
+
let sessionsWithEntries = 0;
|
|
739
|
+
let summariesWritten = 0;
|
|
679
740
|
|
|
680
741
|
for (const sessionKey of sessions) {
|
|
681
742
|
// Calculate the hour we want to summarize (previous hour)
|
|
@@ -691,26 +752,86 @@ Respond with valid JSON matching this schema:
|
|
|
691
752
|
log.debug(`no transcript entries for ${sessionKey} at ${hourStart.toISOString()}`);
|
|
692
753
|
continue;
|
|
693
754
|
}
|
|
755
|
+
sessionsWithEntries += 1;
|
|
694
756
|
|
|
695
757
|
// Generate and save summary
|
|
696
758
|
const summary = await this.generateSummary(sessionKey, hourStart, entries);
|
|
697
759
|
if (summary) {
|
|
698
760
|
await this.saveSummary(summary);
|
|
761
|
+
summariesWritten += 1;
|
|
699
762
|
log.info(`generated hourly summary for ${sessionKey} (${entries.length} turns)`);
|
|
700
763
|
}
|
|
701
764
|
}
|
|
765
|
+
|
|
766
|
+
return {
|
|
767
|
+
sessionsConsidered: sessions.length,
|
|
768
|
+
sessionsWithEntries,
|
|
769
|
+
summariesWritten,
|
|
770
|
+
// Staleness signal (issue #2783): newest entry across the whole
|
|
771
|
+
// store, from the same scan getActiveSessions already performs.
|
|
772
|
+
staleStore:
|
|
773
|
+
scan.newestEntryTimestamp !== null &&
|
|
774
|
+
Date.now() - new Date(scan.newestEntryTimestamp).getTime() > STALE_STORE_MS,
|
|
775
|
+
newestEntryTimestamp: scan.newestEntryTimestamp,
|
|
776
|
+
scanFailed: scan.scanFailed,
|
|
777
|
+
};
|
|
702
778
|
}
|
|
703
779
|
|
|
704
|
-
// Get list of active sessions from transcript directory
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
780
|
+
// Get list of active sessions from the transcript directory, plus the
|
|
781
|
+
// scan bookkeeping runHourly reports: newest entry timestamp (staleness
|
|
782
|
+
// signal) and whether the scan itself FAILED. A failed scan must not be
|
|
783
|
+
// reported as an empty store — those are different incidents (review
|
|
784
|
+
// round 2).
|
|
785
|
+
private async getActiveSessions(): Promise<{
|
|
786
|
+
sessionKeys: string[];
|
|
787
|
+
newestEntryTimestamp: string | null;
|
|
788
|
+
scanFailed: boolean;
|
|
789
|
+
}> {
|
|
790
|
+
const transcriptDir = await resolveSafeStoragePath(this.config.memoryDir, "transcripts").catch(() => null);
|
|
791
|
+
if (transcriptDir === null) {
|
|
792
|
+
return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: false };
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const sessionKeys = new Set<string>();
|
|
796
|
+
let newestEntryTimestamp: string | null = null;
|
|
797
|
+
let newestEntryTimeMs = Number.NaN;
|
|
798
|
+
let fileReadFailed = false;
|
|
799
|
+
const collect = async (transcriptPath: string): Promise<void> => {
|
|
800
|
+
try {
|
|
801
|
+
const raw = await readFile(transcriptPath, "utf-8");
|
|
802
|
+
for (const line of raw.split("\n")) {
|
|
803
|
+
if (!line.trim()) continue;
|
|
804
|
+
try {
|
|
805
|
+
const entry = JSON.parse(line) as TranscriptEntry;
|
|
806
|
+
if (typeof entry.sessionKey === "string" && entry.sessionKey.length > 0) {
|
|
807
|
+
sessionKeys.add(entry.sessionKey);
|
|
808
|
+
}
|
|
809
|
+
// Compare parsed epoch values, never strings: a malformed
|
|
810
|
+
// timestamp in a hand-edited file must not poison the staleness
|
|
811
|
+
// signal with a lexically-maximal garbage value (review).
|
|
812
|
+
if (typeof entry.timestamp === "string") {
|
|
813
|
+
const timeMs = new Date(entry.timestamp).getTime();
|
|
814
|
+
if (Number.isFinite(timeMs) && (Number.isNaN(newestEntryTimeMs) || timeMs > newestEntryTimeMs)) {
|
|
815
|
+
newestEntryTimeMs = timeMs;
|
|
816
|
+
newestEntryTimestamp = entry.timestamp;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
} catch {
|
|
820
|
+
// ignore malformed transcript lines
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
} catch (err) {
|
|
824
|
+
// ENOENT is a concurrently-deleted file — ignore. Any other read
|
|
825
|
+
// failure (permissions, I/O) means the store is partially UNREADABLE:
|
|
826
|
+
// mark the scan failed so the caller warns instead of reporting an
|
|
827
|
+
// empty store (review round 3).
|
|
828
|
+
if ((err as NodeJS.ErrnoException)?.code !== "ENOENT") {
|
|
829
|
+
fileReadFailed = true;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
};
|
|
711
833
|
|
|
712
834
|
try {
|
|
713
|
-
const sessionKeys = new Set<string>();
|
|
714
835
|
const typeEntries = await readdir(transcriptDir, { withFileTypes: true });
|
|
715
836
|
for (const typeEnt of typeEntries) {
|
|
716
837
|
if (!typeEnt.isDirectory()) continue;
|
|
@@ -725,44 +846,29 @@ Respond with valid JSON matching this schema:
|
|
|
725
846
|
for (const file of files) {
|
|
726
847
|
const transcriptPath = await resolveSafeStoragePath(chanDir, file).catch(() => null);
|
|
727
848
|
if (transcriptPath === null) continue;
|
|
728
|
-
await
|
|
849
|
+
await collect(transcriptPath);
|
|
729
850
|
}
|
|
730
851
|
}
|
|
731
852
|
}
|
|
732
|
-
return
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
const raw = await readFile(transcriptPath, "utf-8");
|
|
744
|
-
for (const line of raw.split("\n")) {
|
|
745
|
-
if (!line.trim()) continue;
|
|
746
|
-
try {
|
|
747
|
-
const entry = JSON.parse(line) as TranscriptEntry;
|
|
748
|
-
if (typeof entry.sessionKey === "string" && entry.sessionKey.length > 0) {
|
|
749
|
-
sessionKeys.add(entry.sessionKey);
|
|
750
|
-
}
|
|
751
|
-
} catch {
|
|
752
|
-
// ignore malformed transcript lines
|
|
753
|
-
}
|
|
853
|
+
return {
|
|
854
|
+
sessionKeys: Array.from(sessionKeys),
|
|
855
|
+
newestEntryTimestamp,
|
|
856
|
+
scanFailed: fileReadFailed,
|
|
857
|
+
};
|
|
858
|
+
} catch (err) {
|
|
859
|
+
// ENOENT on the root is a never-written store — an EMPTY store, not a
|
|
860
|
+
// scan failure (those are different incidents).
|
|
861
|
+
const code = (err as NodeJS.ErrnoException)?.code;
|
|
862
|
+
if (code === "ENOENT") {
|
|
863
|
+
return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: false };
|
|
754
864
|
}
|
|
755
|
-
|
|
756
|
-
|
|
865
|
+
log.warn(`transcript scan failed: ${err}`);
|
|
866
|
+
return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: true };
|
|
757
867
|
}
|
|
758
868
|
}
|
|
759
869
|
|
|
760
870
|
// Get transcript entries for a session within a time range
|
|
761
|
-
private async getTranscriptEntries(
|
|
762
|
-
sessionKey: string,
|
|
763
|
-
startTime: Date,
|
|
764
|
-
endTime: Date
|
|
765
|
-
): Promise<TranscriptEntry[]> {
|
|
871
|
+
private async getTranscriptEntries(sessionKey: string, startTime: Date, endTime: Date): Promise<TranscriptEntry[]> {
|
|
766
872
|
// Shared session-identity layer (issue #1496, rule #22). Arbitrary keys
|
|
767
873
|
// route to `session/<hash>`; legacy `agent:<id>:...` keep their paths. The
|
|
768
874
|
// shared helper also supplies the read-back-only candidate dirs (mirrors
|
|
@@ -774,8 +880,8 @@ Respond with valid JSON matching this schema:
|
|
|
774
880
|
const transcriptRoot = path.join(this.config.memoryDir, "transcripts");
|
|
775
881
|
const candidateDirs = new Set(
|
|
776
882
|
[paths.dir, paths.alternateDir, paths.legacyDir, ...paths.readbackDirs].filter(
|
|
777
|
-
(dir): dir is string => typeof dir === "string" && dir.length > 0
|
|
778
|
-
)
|
|
883
|
+
(dir): dir is string => typeof dir === "string" && dir.length > 0
|
|
884
|
+
)
|
|
779
885
|
);
|
|
780
886
|
const entries: TranscriptEntry[] = [];
|
|
781
887
|
// Dedup identical raw rows that a partially-applied migration may have
|
|
@@ -605,10 +605,11 @@ test("runHourly keeps processing later sessions when snapshot upsert fails after
|
|
|
605
605
|
},
|
|
606
606
|
] as any[];
|
|
607
607
|
|
|
608
|
-
(summarizer as any).getActiveSessions = async () =>
|
|
609
|
-
failingSession,
|
|
610
|
-
|
|
611
|
-
|
|
608
|
+
(summarizer as any).getActiveSessions = async () => ({
|
|
609
|
+
sessionKeys: [failingSession, succeedingSession],
|
|
610
|
+
newestEntryTimestamp: null,
|
|
611
|
+
scanFailed: false,
|
|
612
|
+
});
|
|
612
613
|
(summarizer as any).getTranscriptEntries = async () => fakeEntries;
|
|
613
614
|
(summarizer as any).generateSummary = async (
|
|
614
615
|
sessionKey: string,
|
|
@@ -680,11 +681,12 @@ test("hourly active session discovery reads every session key in a transcript fi
|
|
|
680
681
|
"utf-8",
|
|
681
682
|
);
|
|
682
683
|
|
|
683
|
-
const
|
|
684
|
+
const scan = await (summarizer as any).getActiveSessions();
|
|
684
685
|
assert.deepEqual(
|
|
685
|
-
[...
|
|
686
|
+
[...scan.sessionKeys].sort(),
|
|
686
687
|
["agent:first:main", "agent:second:main"],
|
|
687
688
|
);
|
|
689
|
+
assert.equal(scan.scanFailed, false);
|
|
688
690
|
});
|
|
689
691
|
|
|
690
692
|
test("hourly transcript lookup ignores traversal channel paths", async () => {
|