@remnic/core 9.69.16 → 9.69.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.d.ts +1 -1
- package/dist/access-admin-ops-surface.js +43 -39
- package/dist/access-authorization-probe.d.ts +1 -1
- package/dist/access-authorization-probe.js +44 -40
- package/dist/access-boundary.d.ts +1 -1
- package/dist/access-boundary.js +43 -39
- package/dist/access-cli.js +103 -102
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +1 -1
- package/dist/access-extraction-force-flush.js +43 -39
- package/dist/access-http-lcm-compaction.d.ts +1 -1
- package/dist/access-http-lifecycle-flush.d.ts +1 -1
- package/dist/access-http-offline-stream.d.ts +1 -1
- package/dist/access-http-query.js +45 -41
- package/dist/access-http.d.ts +2 -2
- package/dist/access-http.js +63 -59
- package/dist/access-identity-continuity-surface.js +43 -39
- package/dist/access-lcm-surface.d.ts +1 -1
- package/dist/access-lcm-surface.js +43 -39
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +1 -1
- package/dist/access-mcp.js +54 -50
- package/dist/access-namespace-preflight.js +43 -39
- 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 +2 -1
- package/dist/access-observe-write-surface.js +43 -39
- package/dist/access-offline-manifest.js +3 -3
- package/dist/access-operations-batch.js +46 -42
- package/dist/access-operations.d.ts +2 -2
- package/dist/access-operations.js +51 -47
- package/dist/access-recall-concurrency.d.ts +1 -1
- package/dist/access-recall-concurrency.js +43 -39
- package/dist/access-recall-response.d.ts +1 -1
- package/dist/access-recall-response.js +43 -39
- package/dist/access-recall-surface.d.ts +1 -1
- package/dist/access-recall-surface.js +43 -39
- 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-DmDS8Y5P.d.ts} +9 -0
- package/dist/access-service-helpers.d.ts +1 -1
- package/dist/access-service.d.ts +1 -1
- package/dist/access-service.js +43 -39
- package/dist/access-surface-catalog.d.ts +1 -1
- package/dist/access-surface-catalog.js +45 -41
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/active-recall.js +6 -6
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/{auto-sync-Q6Q2FVSC.js → auto-sync-GRUJFD2F.js} +3 -3
- package/dist/briefing.js +13 -13
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +15 -15
- package/dist/causal-retrieval.js +2 -2
- 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-AU7Q3LSC.js → chunk-2QSZNTDO.js} +4 -4
- package/dist/{chunk-P6GKRT2H.js → chunk-2Z3DG5CQ.js} +1 -1
- package/dist/{chunk-MSDIETFC.js → chunk-376CEAYL.js} +53 -44
- package/dist/chunk-376CEAYL.js.map +1 -0
- package/dist/{chunk-XMIAU4CO.js → chunk-3ZAZ77WB.js} +2 -2
- package/dist/{chunk-3TSU662L.js → chunk-46QMN7I7.js} +5 -5
- package/dist/{chunk-LF6SHWVV.js → chunk-5CX3NSR7.js} +2 -2
- package/dist/{chunk-QRDSXR3V.js → chunk-5DRBG5U6.js} +2 -2
- package/dist/{chunk-I4QAH4SY.js → chunk-5J36BYRI.js} +3 -3
- package/dist/{chunk-7JV4JST3.js → chunk-5Z6JYMK4.js} +44 -44
- package/dist/{chunk-JGXMA6HL.js → chunk-6FUMA6AA.js} +2 -2
- package/dist/{chunk-K2IJH4D3.js → chunk-7RRUHJPG.js} +7 -7
- package/dist/{chunk-NNBZS3DY.js → chunk-AG46P24C.js} +4 -4
- package/dist/{chunk-QUVWFZOU.js → chunk-AYHPGLG6.js} +2 -2
- package/dist/{chunk-S35IIP5P.js → chunk-B67W7CBL.js} +2 -2
- package/dist/{chunk-OLBZ2WGG.js → chunk-C2JCVZWX.js} +2 -2
- package/dist/{chunk-S5G2LAL7.js → chunk-CHWUICVY.js} +4 -4
- package/dist/{chunk-XQGFIAG7.js → chunk-CM3JBYD4.js} +2 -2
- package/dist/{chunk-F2ERDKY2.js → chunk-CWPVXVIT.js} +16 -16
- package/dist/{chunk-BE4Y6GK6.js → chunk-D35XLYQ7.js} +11 -11
- package/dist/{chunk-P7LVYPIX.js → chunk-DBLVQROL.js} +3 -3
- package/dist/{chunk-5H2G5X4R.js → chunk-DGKQVGLC.js} +3 -3
- package/dist/{chunk-M7DGN6JZ.js → chunk-EQEP23JK.js} +2 -2
- package/dist/{chunk-I6DUKBUI.js → chunk-EYKDBZB3.js} +2 -2
- package/dist/{chunk-LUDXSSTW.js → chunk-FCL6ENLF.js} +2 -2
- package/dist/{chunk-LJAP4KSW.js → chunk-FK2SJX27.js} +2 -2
- package/dist/{chunk-4WIKMOE3.js → chunk-GF7QLY6E.js} +1 -1
- package/dist/{chunk-B64IVEOH.js → chunk-GI726D4G.js} +2 -2
- package/dist/{chunk-NHLEFBE2.js → chunk-I4Y6TBD7.js} +3 -3
- package/dist/{chunk-BO4PWIJY.js → chunk-I672YBXY.js} +3 -3
- package/dist/{chunk-HODFGQGT.js → chunk-IDZU6I4H.js} +2 -2
- package/dist/{chunk-OAKATRAN.js → chunk-IO4OJ73B.js} +10 -10
- package/dist/{chunk-CTCGHNWN.js → chunk-J2R275FN.js} +4 -4
- package/dist/{chunk-C25N5HWX.js → chunk-J6HRJ37H.js} +2 -2
- package/dist/{chunk-XJJYSX6F.js → chunk-JCUG7AXZ.js} +4 -4
- package/dist/{chunk-BX6GW4KC.js → chunk-JMAG7WZ7.js} +2 -2
- package/dist/{chunk-7LCGFUMB.js → chunk-KQAFEZQX.js} +4 -4
- package/dist/{chunk-BEXFNGQ3.js → chunk-LE7B5ETE.js} +3 -3
- package/dist/chunk-LVE64P5Y.js +80 -0
- package/dist/chunk-LVE64P5Y.js.map +1 -0
- package/dist/{chunk-VAMZYOOV.js → chunk-MAIBNEB6.js} +2 -2
- package/dist/{chunk-VYD63IFH.js → chunk-N3DSSCOR.js} +2 -2
- package/dist/{chunk-IEZ6CGTW.js → chunk-N3SS45OW.js} +115 -55
- package/dist/chunk-N3SS45OW.js.map +1 -0
- package/dist/{chunk-SXHBZXHK.js → chunk-NAOAZASM.js} +5 -5
- package/dist/{chunk-3BS2OGDT.js → chunk-NCUODVUI.js} +5 -5
- package/dist/{chunk-63I7LMLG.js → chunk-NISCAOSR.js} +2 -2
- package/dist/{chunk-YWN3GYI2.js → chunk-NYFWBYY4.js} +2 -2
- package/dist/{chunk-BIJAWZYW.js → chunk-OLT3YTDH.js} +4 -4
- package/dist/{chunk-BFDOBESV.js → chunk-QFMFZILG.js} +2 -2
- package/dist/{chunk-G7VEQEMG.js → chunk-QVSRE355.js} +65 -39
- package/dist/chunk-QVSRE355.js.map +1 -0
- package/dist/{chunk-N37X5RU7.js → chunk-RACZB5HT.js} +4 -4
- package/dist/{chunk-5JQV4T5Q.js → chunk-ROHBPMWD.js} +2 -2
- package/dist/{chunk-ZKZCJRRO.js → chunk-S6ZZOFVJ.js} +2 -2
- package/dist/{chunk-KLSPKMIO.js → chunk-SJ5JGIBT.js} +2 -2
- package/dist/{chunk-JHTF22NQ.js → chunk-TA7UZZMW.js} +2 -2
- package/dist/{chunk-2XJDAEAM.js → chunk-V5RWV5DK.js} +5 -5
- package/dist/{chunk-2EHDPHMD.js → chunk-W7M7NKR7.js} +2 -2
- package/dist/{chunk-4UVDLNHQ.js → chunk-WHO6ITU7.js} +2 -2
- package/dist/{chunk-7ZMU4XQT.js → chunk-WMZ6F7GY.js} +2 -2
- package/dist/{chunk-W6GEMUZM.js → chunk-WOEKJPJG.js} +13 -13
- package/dist/{chunk-5YQ7RFSO.js → chunk-WP37SBRE.js} +2 -2
- package/dist/{chunk-RJ57OOCD.js → chunk-X66BHMAU.js} +2 -2
- package/dist/{chunk-W272SWN7.js → chunk-X73YCO3E.js} +6 -6
- package/dist/{chunk-PAWIY5OQ.js → chunk-XAJWPB2V.js} +6 -6
- package/dist/{chunk-QVI63XSO.js → chunk-XR6LLNLU.js} +48 -48
- package/dist/{chunk-GIC6BASP.js → chunk-XZBXINXZ.js} +4 -4
- package/dist/{chunk-APZXA4WI.js → chunk-Y7E5SUZ6.js} +2 -2
- package/dist/{chunk-LDOQE34V.js → chunk-YCJASQMN.js} +2 -2
- package/dist/{chunk-H5IIBGDM.js → chunk-YYE5MKRX.js} +2 -2
- package/dist/{chunk-TRLCMLX7.js → chunk-YYP5GM6J.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/{cli-BI9YYpKx.d.ts → cli-CYQIKncA.d.ts} +1 -1
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +85 -81
- package/dist/coding/export-okf-codegraph.js +12 -12
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.js +12 -12
- package/dist/config.js +6 -6
- package/dist/connectors/codex-materialize-runner.js +12 -12
- package/dist/connectors/index.js +12 -12
- package/dist/convergence-refresh.js +14 -14
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +14 -14
- package/dist/deep-recall-http-glue.d.ts +1 -1
- package/dist/deep-recall-http-glue.js +6 -6
- package/dist/deep-recall-mcp-tools.d.ts +1 -1
- package/dist/deep-recall.js +2 -2
- package/dist/entity-retrieval.js +12 -12
- package/dist/external-wiki-access.d.ts +1 -1
- package/dist/external-wiki-access.js +44 -40
- package/dist/external-wiki-mcp-tools.d.ts +1 -1
- package/dist/extraction.js +15 -15
- 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-snapshot.js +3 -3
- package/dist/graph.js +2 -2
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +119 -118
- package/dist/location/index.js +14 -14
- package/dist/maintenance/memory-governance.js +12 -12
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +12 -12
- package/dist/maintenance/rebuild-memory-projection.js +13 -13
- package/dist/mcp-memory-inspector-app.d.ts +1 -1
- package/dist/memory-subject-cli.d.ts +1 -1
- package/dist/memory-subject.d.ts +1 -1
- package/dist/namespaces/migrate.js +13 -13
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.js +12 -12
- package/dist/offline-sync.js +2 -2
- package/dist/operator-doctor-corpus.js +15 -15
- package/dist/operator-toolkit.js +28 -28
- package/dist/orchestration/maintenance.js +20 -20
- package/dist/orchestrator.js +103 -102
- package/dist/{public-http-Bocro5ZU.d.ts → public-http-C_hWt6I8.d.ts} +1 -1
- package/dist/resume-bundles.js +7 -7
- package/dist/search/factory.js +8 -8
- package/dist/search/index.js +13 -13
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/orama-backend.js +2 -2
- package/dist/semantic-consolidation.js +13 -13
- package/dist/semantic-rule-promotion.js +12 -12
- package/dist/semantic-rule-verifier.js +12 -12
- package/dist/source-agent-qualifier.js +12 -12
- package/dist/standup/build.js +12 -12
- package/dist/storage.js +11 -11
- package/dist/summarizer.d.ts +29 -3
- package/dist/summarizer.js +6 -4
- package/dist/support-passport/index.d.ts +4 -4
- package/dist/support-passport/index.js +46 -42
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/export-okf.js +13 -13
- package/dist/verified-recall.js +12 -12
- package/dist/who-knows-cli.d.ts +1 -1
- package/dist/who-knows-cli.js +13 -13
- package/dist/who-knows.d.ts +1 -1
- package/dist/who-knows.js +12 -12
- 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/summarizer.ts +217 -111
- package/src/summary-snapshot.test.ts +8 -6
- package/dist/chunk-G7VEQEMG.js.map +0 -1
- package/dist/chunk-IEZ6CGTW.js.map +0 -1
- package/dist/chunk-MSDIETFC.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-AU7Q3LSC.js.map → chunk-2QSZNTDO.js.map} +0 -0
- /package/dist/{chunk-P6GKRT2H.js.map → chunk-2Z3DG5CQ.js.map} +0 -0
- /package/dist/{chunk-XMIAU4CO.js.map → chunk-3ZAZ77WB.js.map} +0 -0
- /package/dist/{chunk-3TSU662L.js.map → chunk-46QMN7I7.js.map} +0 -0
- /package/dist/{chunk-LF6SHWVV.js.map → chunk-5CX3NSR7.js.map} +0 -0
- /package/dist/{chunk-QRDSXR3V.js.map → chunk-5DRBG5U6.js.map} +0 -0
- /package/dist/{chunk-I4QAH4SY.js.map → chunk-5J36BYRI.js.map} +0 -0
- /package/dist/{chunk-7JV4JST3.js.map → chunk-5Z6JYMK4.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-NNBZS3DY.js.map → chunk-AG46P24C.js.map} +0 -0
- /package/dist/{chunk-QUVWFZOU.js.map → chunk-AYHPGLG6.js.map} +0 -0
- /package/dist/{chunk-S35IIP5P.js.map → chunk-B67W7CBL.js.map} +0 -0
- /package/dist/{chunk-OLBZ2WGG.js.map → chunk-C2JCVZWX.js.map} +0 -0
- /package/dist/{chunk-S5G2LAL7.js.map → chunk-CHWUICVY.js.map} +0 -0
- /package/dist/{chunk-XQGFIAG7.js.map → chunk-CM3JBYD4.js.map} +0 -0
- /package/dist/{chunk-F2ERDKY2.js.map → chunk-CWPVXVIT.js.map} +0 -0
- /package/dist/{chunk-BE4Y6GK6.js.map → chunk-D35XLYQ7.js.map} +0 -0
- /package/dist/{chunk-P7LVYPIX.js.map → chunk-DBLVQROL.js.map} +0 -0
- /package/dist/{chunk-5H2G5X4R.js.map → chunk-DGKQVGLC.js.map} +0 -0
- /package/dist/{chunk-M7DGN6JZ.js.map → chunk-EQEP23JK.js.map} +0 -0
- /package/dist/{chunk-I6DUKBUI.js.map → chunk-EYKDBZB3.js.map} +0 -0
- /package/dist/{chunk-LUDXSSTW.js.map → chunk-FCL6ENLF.js.map} +0 -0
- /package/dist/{chunk-LJAP4KSW.js.map → chunk-FK2SJX27.js.map} +0 -0
- /package/dist/{chunk-4WIKMOE3.js.map → chunk-GF7QLY6E.js.map} +0 -0
- /package/dist/{chunk-B64IVEOH.js.map → chunk-GI726D4G.js.map} +0 -0
- /package/dist/{chunk-NHLEFBE2.js.map → chunk-I4Y6TBD7.js.map} +0 -0
- /package/dist/{chunk-BO4PWIJY.js.map → chunk-I672YBXY.js.map} +0 -0
- /package/dist/{chunk-HODFGQGT.js.map → chunk-IDZU6I4H.js.map} +0 -0
- /package/dist/{chunk-OAKATRAN.js.map → chunk-IO4OJ73B.js.map} +0 -0
- /package/dist/{chunk-CTCGHNWN.js.map → chunk-J2R275FN.js.map} +0 -0
- /package/dist/{chunk-C25N5HWX.js.map → chunk-J6HRJ37H.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-7LCGFUMB.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-BEXFNGQ3.js.map → chunk-LE7B5ETE.js.map} +0 -0
- /package/dist/{chunk-VAMZYOOV.js.map → chunk-MAIBNEB6.js.map} +0 -0
- /package/dist/{chunk-VYD63IFH.js.map → chunk-N3DSSCOR.js.map} +0 -0
- /package/dist/{chunk-SXHBZXHK.js.map → chunk-NAOAZASM.js.map} +0 -0
- /package/dist/{chunk-3BS2OGDT.js.map → chunk-NCUODVUI.js.map} +0 -0
- /package/dist/{chunk-63I7LMLG.js.map → chunk-NISCAOSR.js.map} +0 -0
- /package/dist/{chunk-YWN3GYI2.js.map → chunk-NYFWBYY4.js.map} +0 -0
- /package/dist/{chunk-BIJAWZYW.js.map → chunk-OLT3YTDH.js.map} +0 -0
- /package/dist/{chunk-BFDOBESV.js.map → chunk-QFMFZILG.js.map} +0 -0
- /package/dist/{chunk-N37X5RU7.js.map → chunk-RACZB5HT.js.map} +0 -0
- /package/dist/{chunk-5JQV4T5Q.js.map → chunk-ROHBPMWD.js.map} +0 -0
- /package/dist/{chunk-ZKZCJRRO.js.map → chunk-S6ZZOFVJ.js.map} +0 -0
- /package/dist/{chunk-KLSPKMIO.js.map → chunk-SJ5JGIBT.js.map} +0 -0
- /package/dist/{chunk-JHTF22NQ.js.map → chunk-TA7UZZMW.js.map} +0 -0
- /package/dist/{chunk-2XJDAEAM.js.map → chunk-V5RWV5DK.js.map} +0 -0
- /package/dist/{chunk-2EHDPHMD.js.map → chunk-W7M7NKR7.js.map} +0 -0
- /package/dist/{chunk-4UVDLNHQ.js.map → chunk-WHO6ITU7.js.map} +0 -0
- /package/dist/{chunk-7ZMU4XQT.js.map → chunk-WMZ6F7GY.js.map} +0 -0
- /package/dist/{chunk-W6GEMUZM.js.map → chunk-WOEKJPJG.js.map} +0 -0
- /package/dist/{chunk-5YQ7RFSO.js.map → chunk-WP37SBRE.js.map} +0 -0
- /package/dist/{chunk-RJ57OOCD.js.map → chunk-X66BHMAU.js.map} +0 -0
- /package/dist/{chunk-W272SWN7.js.map → chunk-X73YCO3E.js.map} +0 -0
- /package/dist/{chunk-PAWIY5OQ.js.map → chunk-XAJWPB2V.js.map} +0 -0
- /package/dist/{chunk-QVI63XSO.js.map → chunk-XR6LLNLU.js.map} +0 -0
- /package/dist/{chunk-GIC6BASP.js.map → chunk-XZBXINXZ.js.map} +0 -0
- /package/dist/{chunk-APZXA4WI.js.map → chunk-Y7E5SUZ6.js.map} +0 -0
- /package/dist/{chunk-LDOQE34V.js.map → chunk-YCJASQMN.js.map} +0 -0
- /package/dist/{chunk-H5IIBGDM.js.map → chunk-YYE5MKRX.js.map} +0 -0
- /package/dist/{chunk-TRLCMLX7.js.map → chunk-YYP5GM6J.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
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observe-derived transcript persistence (issue #2783).
|
|
3
|
+
*
|
|
4
|
+
* Delegate-mode gateways POST every turn to `/observe`; without a transcript
|
|
5
|
+
* append in the daemon's observe path the transcript store never grows and
|
|
6
|
+
* the hourly summarizer starves silently while every run reports ok. This
|
|
7
|
+
* module is that append: it mirrors the embedded runtime's `agent_end`
|
|
8
|
+
* handler (src/index.ts) — same `TranscriptManager`, same entry shape, same
|
|
9
|
+
* `transcriptEnabled` presentation gate, same 10-char noise floor.
|
|
10
|
+
*
|
|
11
|
+
* Turns are deduped against a bounded process-lifetime (session, role,
|
|
12
|
+
* content) fingerprint — the daemon-side equivalent of the embedded
|
|
13
|
+
* runtime's `observedInboundContentFingerprints`, extended to both roles
|
|
14
|
+
* because an un-keyed client re-POST always carries the whole turn — so a
|
|
15
|
+
* retry cannot double-write it.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
19
|
+
import { lcmSessionKeyForNamespace } from "./coding/coding-namespace.js";
|
|
20
|
+
import type { PluginConfig } from "./types.js";
|
|
21
|
+
import { log } from "./logger.js";
|
|
22
|
+
import type { Orchestrator } from "./orchestrator.js";
|
|
23
|
+
import type { TranscriptEntry } from "./types.js";
|
|
24
|
+
|
|
25
|
+
const OBSERVE_TRANSCRIPT_DEDUPE_MAX_ENTRIES = 8192;
|
|
26
|
+
const OBSERVE_TRANSCRIPT_MIN_CONTENT_CHARS = 10;
|
|
27
|
+
/**
|
|
28
|
+
* A fingerprint only suppresses re-POSTs inside this window. A client retry
|
|
29
|
+
* lands seconds later; a session LEGITIMATELY repeating the same >10-char
|
|
30
|
+
* turn usually does so minutes or hours later, and that repeat is a real
|
|
31
|
+
* conversation event the transcripts must keep (review: preserve legitimate
|
|
32
|
+
* repeated turns).
|
|
33
|
+
*/
|
|
34
|
+
const OBSERVE_TRANSCRIPT_DEDUPE_TTL_MS = 10 * 60 * 1000;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The transcript-side session identity for an observe payload (issue #2783
|
|
38
|
+
* review: namespace scoping). Two authenticated principals can submit the
|
|
39
|
+
* same client-controlled sessionKey while resolving to different effective
|
|
40
|
+
* write namespaces; persisting through the raw key would let one
|
|
41
|
+
* principal's transcript-derived summaries surface under the other's
|
|
42
|
+
* session. Mirror the LCM archive's answer (rule 42 parity): prefix the
|
|
43
|
+
* key with the effective write namespace whenever it diverges from the
|
|
44
|
+
* default store. The summarizer lists sessions from the store itself, so
|
|
45
|
+
* reads self-consistently follow the same prefixed keys.
|
|
46
|
+
*/
|
|
47
|
+
export function observeTranscriptSessionKey(
|
|
48
|
+
sessionKey: string,
|
|
49
|
+
writeNamespace: string,
|
|
50
|
+
config: Pick<PluginConfig, "defaultNamespace">
|
|
51
|
+
): string {
|
|
52
|
+
return lcmSessionKeyForNamespace(writeNamespace, sessionKey, config.defaultNamespace) ?? sessionKey;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Bounded FIFO of seen fingerprints; insertion order is the eviction order. */
|
|
56
|
+
export class ObserveTranscriptPersister {
|
|
57
|
+
private readonly seenFingerprintsAt = new Map<string, number>();
|
|
58
|
+
/** In-flight appends by fingerprint: an overlapping identical observe waits for the first append instead of double-writing. */
|
|
59
|
+
private readonly inflightAppends = new Map<string, Promise<void>>();
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Append every eligible message of an observe payload to the per-session
|
|
63
|
+
* transcript store. Best-effort: a failing append logs and does not fail
|
|
64
|
+
* the observe. Returns true when at least one turn was appended.
|
|
65
|
+
*/
|
|
66
|
+
async persist(
|
|
67
|
+
orchestrator: Orchestrator,
|
|
68
|
+
sessionKey: string,
|
|
69
|
+
messages: ReadonlyArray<{ role: string; content: string }>,
|
|
70
|
+
rawSessionKey?: string
|
|
71
|
+
): Promise<boolean> {
|
|
72
|
+
let persisted = false;
|
|
73
|
+
// TranscriptManager.append silently no-ops for skip-listed channel types
|
|
74
|
+
// (cron by default) — check BEFORE appending so the response's
|
|
75
|
+
// transcriptPersisted stays truthful (review: report skipped appends).
|
|
76
|
+
// The channel identity must derive from the RAW session key: the legacy
|
|
77
|
+
// parser requires the key to start with "agent:", so a namespace-prefixed
|
|
78
|
+
// transcript identity would always classify as "session" and the skip
|
|
79
|
+
// list would silently not apply to namespaced cron sessions (review r4).
|
|
80
|
+
const { channelType } = orchestrator.transcript.getTranscriptPath(rawSessionKey ?? sessionKey);
|
|
81
|
+
if (orchestrator.config.transcriptSkipChannelTypes.includes(channelType)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
for (const message of messages) {
|
|
85
|
+
if (message.content.length < OBSERVE_TRANSCRIPT_MIN_CONTENT_CHARS) continue;
|
|
86
|
+
// Fixed-size digest, never the raw content: 8192 retained entries of
|
|
87
|
+
// full turn text is an avoidable heap-exhaustion surface on a daemon
|
|
88
|
+
// that accepts arbitrary observe payloads (review round 2).
|
|
89
|
+
const fingerprint = createHash("sha256")
|
|
90
|
+
.update(`${sessionKey}\0${message.role}\0${message.content}`)
|
|
91
|
+
.digest("hex");
|
|
92
|
+
// Two identical observes can overlap before either records its
|
|
93
|
+
// fingerprint; both would then append and the transcript would carry
|
|
94
|
+
// the turn twice. The attempt loop serializes per fingerprint: a caller
|
|
95
|
+
// that finds an in-flight append awaits it and RE-RUNS BOTH checks — on
|
|
96
|
+
// success the completed-set check skips the message; on failure (no
|
|
97
|
+
// fingerprint recorded) exactly ONE waiter proceeds to retry, because
|
|
98
|
+
// the check-then-register sequence has no await between its steps and
|
|
99
|
+
// is therefore atomic on the event loop (review r4).
|
|
100
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
101
|
+
const seenAt = this.seenFingerprintsAt.get(fingerprint);
|
|
102
|
+
if (seenAt !== undefined && Date.now() - seenAt < OBSERVE_TRANSCRIPT_DEDUPE_TTL_MS) {
|
|
103
|
+
break; // duplicate within the retry window — skip the message
|
|
104
|
+
}
|
|
105
|
+
const inflight = this.inflightAppends.get(fingerprint);
|
|
106
|
+
if (inflight) {
|
|
107
|
+
await inflight;
|
|
108
|
+
continue; // re-run both checks with the append's outcome visible
|
|
109
|
+
}
|
|
110
|
+
const entry: TranscriptEntry = {
|
|
111
|
+
timestamp: new Date().toISOString(),
|
|
112
|
+
role: message.role as TranscriptEntry["role"],
|
|
113
|
+
content: message.content,
|
|
114
|
+
sessionKey,
|
|
115
|
+
turnId: randomUUID(),
|
|
116
|
+
};
|
|
117
|
+
const appendPromise = orchestrator.transcript
|
|
118
|
+
.append(entry)
|
|
119
|
+
.then(() => {
|
|
120
|
+
// Remember only after a successful append: a transient failure
|
|
121
|
+
// must not permanently swallow the turn — the client's retry has
|
|
122
|
+
// to be able to re-append it (review round 2).
|
|
123
|
+
this.remember(fingerprint);
|
|
124
|
+
persisted = true;
|
|
125
|
+
})
|
|
126
|
+
.catch((err) => {
|
|
127
|
+
// Same policy as the LCM enqueue in the observe path: transcript
|
|
128
|
+
// persistence must never fail the observe itself.
|
|
129
|
+
log.error(`access-observe transcript append failed: ${err}`);
|
|
130
|
+
})
|
|
131
|
+
.finally(() => {
|
|
132
|
+
this.inflightAppends.delete(fingerprint);
|
|
133
|
+
});
|
|
134
|
+
this.inflightAppends.set(fingerprint, appendPromise);
|
|
135
|
+
await appendPromise;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return persisted;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private remember(fingerprint: string): void {
|
|
143
|
+
// Map.set keeps an existing key at its ORIGINAL insertion position, so a
|
|
144
|
+
// TTL-refreshed fingerprint could still be the FIFO-oldest and get
|
|
145
|
+
// evicted immediately — delete first to move it to the end (review r4).
|
|
146
|
+
this.seenFingerprintsAt.delete(fingerprint);
|
|
147
|
+
this.seenFingerprintsAt.set(fingerprint, Date.now());
|
|
148
|
+
if (this.seenFingerprintsAt.size > OBSERVE_TRANSCRIPT_DEDUPE_MAX_ENTRIES) {
|
|
149
|
+
const oldest = this.seenFingerprintsAt.keys().next().value;
|
|
150
|
+
if (typeof oldest === "string") this.seenFingerprintsAt.delete(oldest);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|