@remnic/core 10.0.92 → 10.0.94
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.js +332 -59
- package/dist/access-authorization-probe.js +2 -283
- package/dist/access-boundary.d.ts +1 -1
- package/dist/access-boundary.d.ts.map +1 -1
- package/dist/access-boundary.js +1 -282
- package/dist/access-cli.js +287 -303
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.js +3 -3
- package/dist/access-extraction-force-flush.js +332 -59
- package/dist/access-http-briefing.js +332 -60
- package/dist/access-http-query.js +332 -61
- package/dist/access-http.js +330 -112
- package/dist/access-identity-continuity-surface.js +332 -59
- package/dist/access-lcm-surface.js +332 -59
- package/dist/access-mcp-frames.d.ts +20 -6
- package/dist/access-mcp-frames.d.ts.map +1 -1
- package/dist/access-mcp-frames.js +1 -1
- package/dist/access-mcp.d.ts +5 -0
- package/dist/access-mcp.d.ts.map +1 -1
- package/dist/access-mcp.js +330 -87
- package/dist/access-namespace-preflight.js +2 -282
- package/dist/access-observe-transcript.js +3 -3
- package/dist/access-observe-write-category.js +6 -6
- package/dist/access-observe-write-surface.js +332 -59
- package/dist/access-offline-manifest.js +12 -11
- package/dist/access-operations-batch.js +330 -64
- package/dist/access-operations.js +330 -73
- package/dist/access-recall-concurrency.js +332 -59
- package/dist/access-recall-diagnostics.js +5 -4
- package/dist/access-recall-response.js +332 -59
- package/dist/access-recall-surface.js +332 -59
- package/dist/access-schema.js +2 -2
- package/dist/access-service.js +335 -62
- package/dist/access-surface-catalog.js +6 -283
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/active-context-transform.js +1 -1
- package/dist/active-memory-bridge.js +3 -2
- package/dist/active-recall.js +36 -37
- package/dist/active-recall.js.map +1 -1
- package/dist/activity/journal-extract.d.ts +13 -1
- package/dist/activity/journal-extract.d.ts.map +1 -1
- package/dist/{auto-sync-3AZW7MXI.js → auto-sync-BO5YZKM6.js} +13 -15
- package/dist/{auto-sync-3AZW7MXI.js.map → auto-sync-BO5YZKM6.js.map} +1 -1
- package/dist/briefing.js +20 -20
- package/dist/buffer.js +16 -16
- package/dist/calibration.js +10 -10
- package/dist/{capsule-merge-2IIXFXN5.js → capsule-merge-6IDAYTKG.js} +6 -6
- package/dist/causal-consolidation.js +23 -23
- package/dist/{chunk-RGUUBAT5.js → chunk-2WCLTWV2.js} +3 -3
- package/dist/{chunk-BQZEGOZ4.js → chunk-2YODOG2O.js} +2 -2
- package/dist/{chunk-WYG5UNDY.js → chunk-3AUDELZL.js} +2 -2
- package/dist/{chunk-MB6ZJDN6.js → chunk-3FBAEPCU.js} +2 -2
- package/dist/{chunk-PIITB2YZ.js → chunk-3ZS3NUEI.js} +4 -4
- package/dist/{chunk-ATPWZ4F7.js → chunk-4EZWSDFL.js} +5 -5
- package/dist/{chunk-ANZZLRUX.js → chunk-4IVRQMZW.js} +2 -2
- package/dist/{chunk-63E37JCN.js → chunk-4RAJT5L2.js} +4 -4
- package/dist/{chunk-45VUHDV2.js → chunk-5CO5G4MN.js} +2 -2
- package/dist/{chunk-LUJCQQ3L.js → chunk-65HWAQ4F.js} +2 -2
- package/dist/{chunk-T67LUYCR.js → chunk-77NTFICT.js} +5 -5
- package/dist/chunk-A2WFUMUN.js +86 -0
- package/dist/chunk-A2WFUMUN.js.map +1 -0
- package/dist/{chunk-UE6RRXMF.js → chunk-A4F7OIC5.js} +2 -2
- package/dist/chunk-AHA5VQGP.js +117 -0
- package/dist/chunk-AHA5VQGP.js.map +1 -0
- package/dist/{chunk-RRJBDXAQ.js → chunk-B377OKUP.js} +2 -2
- package/dist/{chunk-IUKYFTGW.js → chunk-B3DR2JBZ.js} +140 -125
- package/dist/chunk-B3DR2JBZ.js.map +1 -0
- package/dist/{chunk-Z7JIZ42P.js → chunk-BN2EBCLB.js} +3 -3
- package/dist/{chunk-YYOMGOHB.js → chunk-BOK6BN5M.js} +2 -2
- package/dist/{chunk-U6UNF5ZS.js → chunk-BPK32FRM.js} +3 -3
- package/dist/{chunk-OH7QLI6W.js → chunk-BPPUH5JM.js} +5 -5
- package/dist/{chunk-O6ZSWHVR.js → chunk-C2KE5DMD.js} +4 -4
- package/dist/{chunk-47F6WWLQ.js → chunk-C73N66PR.js} +2 -2
- package/dist/{chunk-WRT7GJ2D.js → chunk-CIWMTNHW.js} +4 -4
- package/dist/{chunk-HF3BKUVV.js → chunk-CL4JU3DF.js} +7 -7
- package/dist/{chunk-O55EKIEC.js → chunk-D3ZKHLN2.js} +2 -2
- package/dist/chunk-D5S6RL32.js +67137 -0
- package/dist/chunk-D5S6RL32.js.map +1 -0
- package/dist/{chunk-ETZLQOUR.js → chunk-D5XG2KPS.js} +2 -2
- package/dist/{chunk-CD4BCCNP.js → chunk-DJ7WVEWX.js} +2 -2
- package/dist/{chunk-PWXPRVLK.js → chunk-DNY63QWJ.js} +2 -2
- package/dist/{chunk-4CJTQHEG.js → chunk-ESLOLCD4.js} +3 -3
- package/dist/{chunk-VILPVT4S.js → chunk-EZ47HOJ6.js} +4 -4
- package/dist/{chunk-EFYN5I7Z.js → chunk-F4QFU5IZ.js} +2 -2
- package/dist/{chunk-T6OZW2WR.js → chunk-FA7SLQ5X.js} +7 -1
- package/dist/chunk-FA7SLQ5X.js.map +1 -0
- package/dist/{chunk-BRLXOZLM.js → chunk-FQAQ63QA.js} +729 -17
- package/dist/chunk-FQAQ63QA.js.map +1 -0
- package/dist/{chunk-FSO3G4JJ.js → chunk-FWRXW7CZ.js} +5000 -2748
- package/dist/chunk-FWRXW7CZ.js.map +1 -0
- package/dist/{chunk-XYKBWTWI.js → chunk-FZZMLGWQ.js} +2 -2
- package/dist/{chunk-FNXQZGUS.js → chunk-GBJUTX44.js} +2 -2
- package/dist/{chunk-YLXETSAH.js → chunk-GCZJ7XRI.js} +2 -2
- package/dist/{chunk-UDKWFDV2.js → chunk-HLUHEMN4.js} +27 -3
- package/dist/chunk-HLUHEMN4.js.map +1 -0
- package/dist/{chunk-SUSW74WU.js → chunk-IL3RHBWM.js} +56 -5
- package/dist/chunk-IL3RHBWM.js.map +1 -0
- package/dist/{chunk-JV4S6VDH.js → chunk-ILY5SSOM.js} +2 -2
- package/dist/{chunk-EXHXJETE.js → chunk-IQ55QGY5.js} +2 -2
- package/dist/{chunk-4J363OAA.js → chunk-J7BIFOYP.js} +2 -2
- package/dist/{chunk-QFEDITXM.js → chunk-JNDMIAJ4.js} +2 -2
- package/dist/chunk-JTSSSR4L.js +359 -0
- package/dist/chunk-JTSSSR4L.js.map +1 -0
- package/dist/{chunk-5KBIOI4G.js → chunk-JVBAPAWZ.js} +217 -13
- package/dist/chunk-JVBAPAWZ.js.map +1 -0
- package/dist/{chunk-E5PPE4VA.js → chunk-K2VRKCPA.js} +2 -2
- package/dist/{chunk-MKRYQROF.js → chunk-LGEHAQHK.js} +4 -4
- package/dist/{chunk-7HTUYFR3.js → chunk-LLPMMMWG.js} +27 -10
- package/dist/chunk-LLPMMMWG.js.map +1 -0
- package/dist/{chunk-XYTQJD7F.js → chunk-LMJVP5CM.js} +2 -2
- package/dist/{chunk-E7YZXWIS.js → chunk-LNGELD2M.js} +2 -2
- package/dist/{chunk-FQKBJJYB.js → chunk-LPV72KRQ.js} +2 -2
- package/dist/{chunk-2LCRG2YV.js → chunk-M2XR6B6V.js} +2 -2
- package/dist/{chunk-EQ4U73UH.js → chunk-MLAMXQAW.js} +14 -2
- package/dist/chunk-MLAMXQAW.js.map +1 -0
- package/dist/{chunk-ZU5JDLOH.js → chunk-MMRTPH3J.js} +2 -2
- package/dist/{chunk-TVIVY7KU.js → chunk-NED7IR7B.js} +4 -4
- package/dist/{chunk-6F5MJFXY.js → chunk-NHVAX7MH.js} +2 -2
- package/dist/{chunk-TG3R2SID.js → chunk-NMGHGTVR.js} +5 -5
- package/dist/{chunk-YCNIGRRF.js → chunk-NS7U4ZYU.js} +13 -117
- package/dist/chunk-NS7U4ZYU.js.map +1 -0
- package/dist/{chunk-NGHDW6UU.js → chunk-NUQEREIP.js} +2 -2
- package/dist/{chunk-5IIQU4JZ.js → chunk-OB72KNMF.js} +4 -4
- package/dist/{chunk-RIMK327Y.js → chunk-OUVYYKYU.js} +7 -7
- package/dist/{chunk-QJPJXCS4.js → chunk-P3WRNWWM.js} +157 -4
- package/dist/chunk-P3WRNWWM.js.map +1 -0
- package/dist/{chunk-E6M225BJ.js → chunk-PC5DRBGD.js} +18 -8
- package/dist/chunk-PC5DRBGD.js.map +1 -0
- package/dist/{chunk-RWGRSKN5.js → chunk-PT4DZDJA.js} +2 -2
- package/dist/{chunk-7EPY3IQL.js → chunk-PZJQ46DH.js} +2 -2
- package/dist/{chunk-MXHMNKWG.js → chunk-QDESY76F.js} +3 -3
- package/dist/{chunk-E3A7ELSG.js → chunk-QHARXWTC.js} +2 -2
- package/dist/{chunk-BLJT6JP2.js → chunk-QMFAMOT2.js} +2 -2
- package/dist/{chunk-I6QGI65T.js → chunk-QRMG4HK4.js} +3 -3
- package/dist/{chunk-ZU3NJNO7.js → chunk-QSF5SJAM.js} +4 -4
- package/dist/{chunk-5IYOKDM4.js → chunk-R23JWJD3.js} +5 -5
- package/dist/{chunk-RHQLIHMB.js → chunk-R4BBGPI2.js} +218 -218
- package/dist/chunk-R4BBGPI2.js.map +1 -0
- package/dist/{chunk-NT7F7WJQ.js → chunk-RFUL2ZIQ.js} +291 -93
- package/dist/chunk-RFUL2ZIQ.js.map +1 -0
- package/dist/{chunk-E4IRW2FG.js → chunk-RKABLU5M.js} +233 -40
- package/dist/chunk-RKABLU5M.js.map +1 -0
- package/dist/{chunk-P4WNBSTW.js → chunk-RNG7S3FY.js} +2 -2
- package/dist/{chunk-IPT2OY4B.js → chunk-RQFXZYTF.js} +35 -33
- package/dist/chunk-RQFXZYTF.js.map +1 -0
- package/dist/{chunk-5HFXGXE5.js → chunk-RUTN5MMC.js} +7 -9
- package/dist/{chunk-5HFXGXE5.js.map → chunk-RUTN5MMC.js.map} +1 -1
- package/dist/{chunk-AP6NCP3V.js → chunk-S3S72HRM.js} +8 -6
- package/dist/chunk-S3S72HRM.js.map +1 -0
- package/dist/{chunk-ZGFLIK5H.js → chunk-SPAKBUJY.js} +2 -2
- package/dist/{chunk-ER7XANP3.js → chunk-SQ3GEIEL.js} +4 -4
- package/dist/{chunk-PMJFRDJI.js → chunk-SUTEBYGI.js} +2 -2
- package/dist/{chunk-HVX4LPNY.js → chunk-T4KY6UYF.js} +5 -3
- package/dist/{chunk-HVX4LPNY.js.map → chunk-T4KY6UYF.js.map} +1 -1
- package/dist/{chunk-R6HMAIKM.js → chunk-TOSPNM4T.js} +2 -2
- package/dist/{chunk-RMXS4I66.js → chunk-TVDJEUV5.js} +2 -2
- package/dist/{chunk-PLCYKAWH.js → chunk-TYRWSE4B.js} +2 -2
- package/dist/{chunk-B4QYQFGY.js → chunk-UBEKET2V.js} +383 -36
- package/dist/chunk-UBEKET2V.js.map +1 -0
- package/dist/{chunk-IQWUACVG.js → chunk-UHMHJX5G.js} +3 -3
- package/dist/{chunk-YODUDA6R.js → chunk-UN4RVUG2.js} +22 -22
- package/dist/{chunk-E6Z4FBX6.js → chunk-V2QSNFCT.js} +2 -2
- package/dist/{chunk-NBH6K6G5.js → chunk-V65H7MI6.js} +345 -16
- package/dist/chunk-V65H7MI6.js.map +1 -0
- package/dist/chunk-W54Z2MOP.js +4500 -0
- package/dist/chunk-W54Z2MOP.js.map +1 -0
- package/dist/{chunk-7W3RXOIG.js → chunk-WGGRZYSQ.js} +14 -14
- package/dist/{chunk-RIZ5NUNN.js → chunk-WQ4XKIOX.js} +4 -4
- package/dist/{chunk-QEYTRFR3.js → chunk-X26YOFGS.js} +2 -2
- package/dist/{chunk-ITHZFHST.js → chunk-X2BVB74H.js} +2 -2
- package/dist/{chunk-6F42QONS.js → chunk-X5HGU2EM.js} +4 -4
- package/dist/{chunk-GVGAO3WV.js → chunk-XJ2S5UBF.js} +3 -3
- package/dist/{chunk-IBJ6U753.js → chunk-XKZBZOKV.js} +4 -4
- package/dist/{chunk-65AUYLU3.js → chunk-XPXHQI6N.js} +2 -2
- package/dist/chunk-XRWWCW4H.js +102 -0
- package/dist/chunk-XRWWCW4H.js.map +1 -0
- package/dist/{chunk-HH5LY6RR.js → chunk-YIXJSW5M.js} +5 -5
- package/dist/{chunk-2JSDPUKD.js → chunk-YMFPFXEX.js} +2 -2
- package/dist/{chunk-N4KAE2NB.js → chunk-Z3FTSHT5.js} +3 -3
- package/dist/{chunk-7GLJMDEQ.js → chunk-ZDV5YWID.js} +6 -6
- package/dist/{chunk-645WOU5I.js → chunk-ZDZJNXL6.js} +4 -4
- package/dist/{chunk-6TCXIRP5.js → chunk-ZKE4CO6B.js} +4 -4
- package/dist/cli.js +303 -185
- package/dist/coding/export-okf-codegraph.js +29 -29
- package/dist/compounding/engine.js +23 -24
- package/dist/config.js +36 -37
- package/dist/connectors/codex-materialize-runner.js +20 -20
- package/dist/connectors/index.js +21 -21
- package/dist/connectors/live/google-drive.d.ts +2 -0
- package/dist/connectors/live/google-drive.d.ts.map +1 -1
- package/dist/consolidation-provenance-check.js +4 -4
- package/dist/consolidation-undo.js +5 -5
- package/dist/contradiction/index.js +7 -6
- package/dist/{contradiction-scan-P2MHYFVG.js → contradiction-scan-IBPYGQZF.js} +4 -3
- package/dist/convergence-refresh.js +22 -22
- package/dist/corpus-watermark.js +23 -23
- package/dist/deep-recall-http-glue.js +2 -2
- package/dist/deep-recall-policy-llm.js +4 -4
- package/dist/direct-answer-wiring.js +2 -2
- package/dist/embedding-fallback.js +1 -1
- package/dist/entity-retrieval.js +21 -21
- package/dist/eval-trajectory-store.js +2 -2
- package/dist/eval-trajectory.js +2 -2
- package/dist/event-order-recall.js +2 -2
- package/dist/explicit-capture.d.ts +3 -2
- package/dist/explicit-capture.d.ts.map +1 -1
- package/dist/explicit-capture.js +530 -6
- package/dist/explicit-cue-recall.js +2 -2
- package/dist/external-wiki-access.js +2 -283
- package/dist/extraction-faithfulness.js +4 -4
- package/dist/extraction-judge.js +5 -5
- package/dist/extraction-normalization.js +1 -1
- package/dist/extraction-quote-grounding.d.ts.map +1 -1
- package/dist/extraction-quote-grounding.js +1 -1
- package/dist/extraction-source-grounding-rules.js +2 -2
- package/dist/extraction-source-grounding.js +3 -3
- package/dist/extraction.js +43 -44
- package/dist/fallback-llm-codex-subscription.js +2 -2
- package/dist/fallback-llm.js +3 -3
- package/dist/{first-start-migration-QFI7B5SH.js → first-start-migration-FILJH3RO.js} +6 -5
- package/dist/{first-start-migration-QFI7B5SH.js.map → first-start-migration-FILJH3RO.js.map} +1 -1
- package/dist/focused-list-recall.js +2 -2
- package/dist/harmonic-retrieval.js +20 -20
- package/dist/index.js +773 -794
- package/dist/lcm/index.js +2 -2
- package/dist/live-connectors-runner.js +2 -3
- package/dist/local-llm-config.js +2 -2
- package/dist/local-llm-helpers.d.ts +4 -0
- package/dist/local-llm-helpers.d.ts.map +1 -1
- package/dist/local-llm-helpers.js +3 -1
- package/dist/local-llm.d.ts +4 -1
- package/dist/local-llm.d.ts.map +1 -1
- package/dist/local-llm.js +4 -4
- package/dist/location/index.js +27 -29
- package/dist/maintenance/memory-governance.js +20 -20
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +20 -20
- package/dist/maintenance/rebuild-memory-projection-runner.js +22 -22
- package/dist/maintenance/rebuild-memory-projection.js +21 -21
- package/dist/memory-browse-operations.js +2 -283
- package/dist/memory-browse.js +8 -7
- package/dist/memory-controller.js +2 -2
- package/dist/memory-subject.js +2 -2
- package/dist/namespaces/migrate.js +21 -21
- package/dist/namespaces/search.js +5 -5
- package/dist/namespaces/storage.js +20 -20
- package/dist/offline-sync-changeset-generations.js +1 -1
- package/dist/offline-sync-embedding-generation.js +1 -1
- package/dist/offline-sync-impression-drain.js +6 -6
- package/dist/offline-sync-snapshot-stream.js +1 -1
- package/dist/offline-sync.js +1 -1
- package/dist/operator-doctor-corpus.js +24 -24
- package/dist/operator-toolkit.js +58 -61
- package/dist/orchestration/backlog-scheduler.js +278 -294
- package/dist/orchestration/backlog-scheduler.js.map +1 -1
- package/dist/orchestration/buffer-drain-runner.js +278 -294
- package/dist/orchestration/extraction-run.d.ts +4 -0
- package/dist/orchestration/extraction-run.d.ts.map +1 -1
- package/dist/orchestration/fact-dedup-window.d.ts +1 -1
- package/dist/orchestration/fact-dedup-window.d.ts.map +1 -1
- package/dist/orchestration/maintenance.js +39 -42
- package/dist/orchestrator.d.ts +9 -11
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +290 -307
- package/dist/page-versioning.js +3 -3
- package/dist/qmd-daemon-session.js +2 -2
- package/dist/qmd.js +3 -3
- package/dist/recall-explain-renderer.js +1 -1
- package/dist/recall-navigation-operations.js +2 -283
- package/dist/recall-navigation.js +332 -59
- package/dist/recall-planner-llm.js +3 -3
- package/dist/recall-state-view-admission.js +6 -6
- package/dist/recall-why-service.js +10 -9
- package/dist/recall-why.js +4 -3
- package/dist/recall-xray-cli.js +2 -2
- package/dist/recall-xray-renderer.js +1 -1
- package/dist/reconcile/manifest.js +3 -3
- package/dist/{resolution-N7H3F2E4.js → resolution-OVVIF7ZY.js} +8 -7
- package/dist/response-guidance-recall.js +2 -2
- package/dist/resume-bundles.js +40 -41
- package/dist/salvage-envelope.js +4 -4
- package/dist/search/factory.js +4 -4
- package/dist/search/index.js +4 -4
- package/dist/semantic-consolidation.js +23 -23
- package/dist/semantic-rule-promotion.js +20 -20
- package/dist/semantic-rule-verifier.js +20 -20
- package/dist/shared-context/manager.js +2 -3
- package/dist/source-agent-qualifier.js +32 -33
- package/dist/standup/build.js +20 -20
- package/dist/storage/buffer-drain-claims.d.ts +97 -12
- package/dist/storage/buffer-drain-claims.d.ts.map +1 -1
- package/dist/storage/buffer-drain-claims.js +1 -1
- package/dist/storage/buffer-session-files.d.ts +4 -0
- package/dist/storage/buffer-session-files.d.ts.map +1 -1
- package/dist/storage/buffer-session-files.js +1 -1
- package/dist/storage/content-hash-index.d.ts +10 -0
- package/dist/storage/content-hash-index.d.ts.map +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +19 -19
- package/dist/subject-config.js +3 -3
- package/dist/summarizer.d.ts +4 -1
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +6 -6
- package/dist/support-passport/index.js +53 -297
- package/dist/targeted-fact-recall.js +2 -2
- package/dist/tier-routing.js +3 -2
- package/dist/{tier-stats-FQGQSFET.js → tier-stats-FXEUJN73.js} +6 -5
- package/dist/{tier-stats-FQGQSFET.js.map → tier-stats-FXEUJN73.js.map} +1 -1
- package/dist/transcript.js +2 -2
- package/dist/transfer/capsule-import.js +4 -4
- package/dist/transfer/export-okf.js +20 -20
- package/dist/verified-recall.js +20 -20
- package/dist/wearables/memory-gen.d.ts +5 -1
- package/dist/wearables/memory-gen.d.ts.map +1 -1
- package/dist/wearables/service.d.ts.map +1 -1
- package/dist/who-knows-cli.js +21 -21
- package/dist/who-knows.js +20 -20
- package/dist/write-envelope.js +3 -3
- package/package.json +2 -2
- package/src/access-boundary.ts +5 -1
- package/src/access-category-alias.test.ts +5 -0
- package/src/access-mcp-frames.test.ts +60 -5
- package/src/access-mcp-frames.ts +72 -18
- package/src/access-mcp.test.ts +66 -2
- package/src/access-mcp.ts +19 -13
- package/src/access-service-coding-write.test.ts +7 -0
- package/src/activity/journal-extract-storage.test.ts +31 -0
- package/src/activity/journal-extract.test.ts +1 -0
- package/src/activity/journal-extract.ts +24 -3
- package/src/buffer-drain-handover.test.ts +5 -1
- package/src/connectors/live/google-drive.test.ts +39 -0
- package/src/connectors/live/google-drive.ts +41 -12
- package/src/explicit-capture.test.ts +109 -17
- package/src/explicit-capture.ts +90 -37
- package/src/extraction-quote-grounding.test.ts +20 -0
- package/src/extraction-quote-grounding.ts +21 -11
- package/src/fact-dedup-window.test.ts +37 -0
- package/src/local-llm-helpers.ts +12 -0
- package/src/local-llm-shutdown.test.ts +194 -0
- package/src/local-llm.ts +32 -30
- package/src/orchestration/extraction-run.ts +12 -3
- package/src/orchestration/fact-dedup-window.ts +5 -1
- package/src/orchestrator-connector-dedup.test.ts +9 -5
- package/src/orchestrator.ts +47 -50
- package/src/storage/buffer-drain-claims.test.ts +385 -1
- package/src/storage/buffer-drain-claims.ts +380 -97
- package/src/storage/buffer-session-files.ts +4 -0
- package/src/storage/content-hash-index.ts +27 -2
- package/src/storage-fact-hash-publish-failure.test.ts +87 -0
- package/src/storage.ts +5 -1
- package/src/summarizer-shutdown.test.ts +195 -0
- package/src/summarizer.ts +15 -2
- package/src/wearables/memory-gen.test.ts +20 -0
- package/src/wearables/memory-gen.ts +14 -7
- package/src/wearables/service.ts +14 -1
- package/src/wearables/storage-io.test.ts +25 -0
- package/dist/chunk-2FGLEF7C.js +0 -61
- package/dist/chunk-2FGLEF7C.js.map +0 -1
- package/dist/chunk-3RLK65ZK.js +0 -203
- package/dist/chunk-3RLK65ZK.js.map +0 -1
- package/dist/chunk-4WR2OD7K.js +0 -43
- package/dist/chunk-4WR2OD7K.js.map +0 -1
- package/dist/chunk-5KBIOI4G.js.map +0 -1
- package/dist/chunk-5M5M22GW.js +0 -346
- package/dist/chunk-5M5M22GW.js.map +0 -1
- package/dist/chunk-7HTUYFR3.js.map +0 -1
- package/dist/chunk-AP6NCP3V.js.map +0 -1
- package/dist/chunk-B4QYQFGY.js.map +0 -1
- package/dist/chunk-BJRTMNCB.js +0 -1919
- package/dist/chunk-BJRTMNCB.js.map +0 -1
- package/dist/chunk-BRLXOZLM.js.map +0 -1
- package/dist/chunk-BSACVS6R.js +0 -621
- package/dist/chunk-BSACVS6R.js.map +0 -1
- package/dist/chunk-DKAA2IHQ.js +0 -3644
- package/dist/chunk-DKAA2IHQ.js.map +0 -1
- package/dist/chunk-E4IRW2FG.js.map +0 -1
- package/dist/chunk-E6M225BJ.js.map +0 -1
- package/dist/chunk-EQ4U73UH.js.map +0 -1
- package/dist/chunk-ETSJD5IV.js +0 -361
- package/dist/chunk-ETSJD5IV.js.map +0 -1
- package/dist/chunk-F55YQP7N.js +0 -336
- package/dist/chunk-F55YQP7N.js.map +0 -1
- package/dist/chunk-FHGWKODN.js +0 -2300
- package/dist/chunk-FHGWKODN.js.map +0 -1
- package/dist/chunk-FLRP63GU.js +0 -32219
- package/dist/chunk-FLRP63GU.js.map +0 -1
- package/dist/chunk-FSO3G4JJ.js.map +0 -1
- package/dist/chunk-ID6JGIMD.js +0 -25
- package/dist/chunk-ID6JGIMD.js.map +0 -1
- package/dist/chunk-IGLJNHOX.js +0 -62
- package/dist/chunk-IGLJNHOX.js.map +0 -1
- package/dist/chunk-IPT2OY4B.js.map +0 -1
- package/dist/chunk-IUKYFTGW.js.map +0 -1
- package/dist/chunk-NBH6K6G5.js.map +0 -1
- package/dist/chunk-NT7F7WJQ.js.map +0 -1
- package/dist/chunk-NTRUKAAE.js +0 -223
- package/dist/chunk-NTRUKAAE.js.map +0 -1
- package/dist/chunk-OGXXGHW6.js +0 -223
- package/dist/chunk-OGXXGHW6.js.map +0 -1
- package/dist/chunk-PPCLZ4JU.js +0 -28
- package/dist/chunk-PPCLZ4JU.js.map +0 -1
- package/dist/chunk-QJPJXCS4.js.map +0 -1
- package/dist/chunk-R2LBF4HH.js +0 -729
- package/dist/chunk-R2LBF4HH.js.map +0 -1
- package/dist/chunk-RHQLIHMB.js.map +0 -1
- package/dist/chunk-RRTVGD3J.js +0 -792
- package/dist/chunk-RRTVGD3J.js.map +0 -1
- package/dist/chunk-SUSW74WU.js.map +0 -1
- package/dist/chunk-T6OZW2WR.js.map +0 -1
- package/dist/chunk-UDKWFDV2.js.map +0 -1
- package/dist/chunk-V7IZKJI3.js +0 -22
- package/dist/chunk-V7IZKJI3.js.map +0 -1
- package/dist/chunk-X562NQFA.js +0 -10144
- package/dist/chunk-X562NQFA.js.map +0 -1
- package/dist/chunk-XDSCJOH7.js +0 -3991
- package/dist/chunk-XDSCJOH7.js.map +0 -1
- package/dist/chunk-YCNIGRRF.js.map +0 -1
- package/dist/chunk-ZTTCDQ4I.js +0 -18796
- package/dist/chunk-ZTTCDQ4I.js.map +0 -1
- /package/dist/{capsule-merge-2IIXFXN5.js.map → capsule-merge-6IDAYTKG.js.map} +0 -0
- /package/dist/{chunk-RGUUBAT5.js.map → chunk-2WCLTWV2.js.map} +0 -0
- /package/dist/{chunk-BQZEGOZ4.js.map → chunk-2YODOG2O.js.map} +0 -0
- /package/dist/{chunk-WYG5UNDY.js.map → chunk-3AUDELZL.js.map} +0 -0
- /package/dist/{chunk-MB6ZJDN6.js.map → chunk-3FBAEPCU.js.map} +0 -0
- /package/dist/{chunk-PIITB2YZ.js.map → chunk-3ZS3NUEI.js.map} +0 -0
- /package/dist/{chunk-ATPWZ4F7.js.map → chunk-4EZWSDFL.js.map} +0 -0
- /package/dist/{chunk-ANZZLRUX.js.map → chunk-4IVRQMZW.js.map} +0 -0
- /package/dist/{chunk-63E37JCN.js.map → chunk-4RAJT5L2.js.map} +0 -0
- /package/dist/{chunk-45VUHDV2.js.map → chunk-5CO5G4MN.js.map} +0 -0
- /package/dist/{chunk-LUJCQQ3L.js.map → chunk-65HWAQ4F.js.map} +0 -0
- /package/dist/{chunk-T67LUYCR.js.map → chunk-77NTFICT.js.map} +0 -0
- /package/dist/{chunk-UE6RRXMF.js.map → chunk-A4F7OIC5.js.map} +0 -0
- /package/dist/{chunk-RRJBDXAQ.js.map → chunk-B377OKUP.js.map} +0 -0
- /package/dist/{chunk-Z7JIZ42P.js.map → chunk-BN2EBCLB.js.map} +0 -0
- /package/dist/{chunk-YYOMGOHB.js.map → chunk-BOK6BN5M.js.map} +0 -0
- /package/dist/{chunk-U6UNF5ZS.js.map → chunk-BPK32FRM.js.map} +0 -0
- /package/dist/{chunk-OH7QLI6W.js.map → chunk-BPPUH5JM.js.map} +0 -0
- /package/dist/{chunk-O6ZSWHVR.js.map → chunk-C2KE5DMD.js.map} +0 -0
- /package/dist/{chunk-47F6WWLQ.js.map → chunk-C73N66PR.js.map} +0 -0
- /package/dist/{chunk-WRT7GJ2D.js.map → chunk-CIWMTNHW.js.map} +0 -0
- /package/dist/{chunk-HF3BKUVV.js.map → chunk-CL4JU3DF.js.map} +0 -0
- /package/dist/{chunk-O55EKIEC.js.map → chunk-D3ZKHLN2.js.map} +0 -0
- /package/dist/{chunk-ETZLQOUR.js.map → chunk-D5XG2KPS.js.map} +0 -0
- /package/dist/{chunk-CD4BCCNP.js.map → chunk-DJ7WVEWX.js.map} +0 -0
- /package/dist/{chunk-PWXPRVLK.js.map → chunk-DNY63QWJ.js.map} +0 -0
- /package/dist/{chunk-4CJTQHEG.js.map → chunk-ESLOLCD4.js.map} +0 -0
- /package/dist/{chunk-VILPVT4S.js.map → chunk-EZ47HOJ6.js.map} +0 -0
- /package/dist/{chunk-EFYN5I7Z.js.map → chunk-F4QFU5IZ.js.map} +0 -0
- /package/dist/{chunk-XYKBWTWI.js.map → chunk-FZZMLGWQ.js.map} +0 -0
- /package/dist/{chunk-FNXQZGUS.js.map → chunk-GBJUTX44.js.map} +0 -0
- /package/dist/{chunk-YLXETSAH.js.map → chunk-GCZJ7XRI.js.map} +0 -0
- /package/dist/{chunk-JV4S6VDH.js.map → chunk-ILY5SSOM.js.map} +0 -0
- /package/dist/{chunk-EXHXJETE.js.map → chunk-IQ55QGY5.js.map} +0 -0
- /package/dist/{chunk-4J363OAA.js.map → chunk-J7BIFOYP.js.map} +0 -0
- /package/dist/{chunk-QFEDITXM.js.map → chunk-JNDMIAJ4.js.map} +0 -0
- /package/dist/{chunk-E5PPE4VA.js.map → chunk-K2VRKCPA.js.map} +0 -0
- /package/dist/{chunk-MKRYQROF.js.map → chunk-LGEHAQHK.js.map} +0 -0
- /package/dist/{chunk-XYTQJD7F.js.map → chunk-LMJVP5CM.js.map} +0 -0
- /package/dist/{chunk-E7YZXWIS.js.map → chunk-LNGELD2M.js.map} +0 -0
- /package/dist/{chunk-FQKBJJYB.js.map → chunk-LPV72KRQ.js.map} +0 -0
- /package/dist/{chunk-2LCRG2YV.js.map → chunk-M2XR6B6V.js.map} +0 -0
- /package/dist/{chunk-ZU5JDLOH.js.map → chunk-MMRTPH3J.js.map} +0 -0
- /package/dist/{chunk-TVIVY7KU.js.map → chunk-NED7IR7B.js.map} +0 -0
- /package/dist/{chunk-6F5MJFXY.js.map → chunk-NHVAX7MH.js.map} +0 -0
- /package/dist/{chunk-TG3R2SID.js.map → chunk-NMGHGTVR.js.map} +0 -0
- /package/dist/{chunk-NGHDW6UU.js.map → chunk-NUQEREIP.js.map} +0 -0
- /package/dist/{chunk-5IIQU4JZ.js.map → chunk-OB72KNMF.js.map} +0 -0
- /package/dist/{chunk-RIMK327Y.js.map → chunk-OUVYYKYU.js.map} +0 -0
- /package/dist/{chunk-RWGRSKN5.js.map → chunk-PT4DZDJA.js.map} +0 -0
- /package/dist/{chunk-7EPY3IQL.js.map → chunk-PZJQ46DH.js.map} +0 -0
- /package/dist/{chunk-MXHMNKWG.js.map → chunk-QDESY76F.js.map} +0 -0
- /package/dist/{chunk-E3A7ELSG.js.map → chunk-QHARXWTC.js.map} +0 -0
- /package/dist/{chunk-BLJT6JP2.js.map → chunk-QMFAMOT2.js.map} +0 -0
- /package/dist/{chunk-I6QGI65T.js.map → chunk-QRMG4HK4.js.map} +0 -0
- /package/dist/{chunk-ZU3NJNO7.js.map → chunk-QSF5SJAM.js.map} +0 -0
- /package/dist/{chunk-5IYOKDM4.js.map → chunk-R23JWJD3.js.map} +0 -0
- /package/dist/{chunk-P4WNBSTW.js.map → chunk-RNG7S3FY.js.map} +0 -0
- /package/dist/{chunk-ZGFLIK5H.js.map → chunk-SPAKBUJY.js.map} +0 -0
- /package/dist/{chunk-ER7XANP3.js.map → chunk-SQ3GEIEL.js.map} +0 -0
- /package/dist/{chunk-PMJFRDJI.js.map → chunk-SUTEBYGI.js.map} +0 -0
- /package/dist/{chunk-R6HMAIKM.js.map → chunk-TOSPNM4T.js.map} +0 -0
- /package/dist/{chunk-RMXS4I66.js.map → chunk-TVDJEUV5.js.map} +0 -0
- /package/dist/{chunk-PLCYKAWH.js.map → chunk-TYRWSE4B.js.map} +0 -0
- /package/dist/{chunk-IQWUACVG.js.map → chunk-UHMHJX5G.js.map} +0 -0
- /package/dist/{chunk-YODUDA6R.js.map → chunk-UN4RVUG2.js.map} +0 -0
- /package/dist/{chunk-E6Z4FBX6.js.map → chunk-V2QSNFCT.js.map} +0 -0
- /package/dist/{chunk-7W3RXOIG.js.map → chunk-WGGRZYSQ.js.map} +0 -0
- /package/dist/{chunk-RIZ5NUNN.js.map → chunk-WQ4XKIOX.js.map} +0 -0
- /package/dist/{chunk-QEYTRFR3.js.map → chunk-X26YOFGS.js.map} +0 -0
- /package/dist/{chunk-ITHZFHST.js.map → chunk-X2BVB74H.js.map} +0 -0
- /package/dist/{chunk-6F42QONS.js.map → chunk-X5HGU2EM.js.map} +0 -0
- /package/dist/{chunk-GVGAO3WV.js.map → chunk-XJ2S5UBF.js.map} +0 -0
- /package/dist/{chunk-IBJ6U753.js.map → chunk-XKZBZOKV.js.map} +0 -0
- /package/dist/{chunk-65AUYLU3.js.map → chunk-XPXHQI6N.js.map} +0 -0
- /package/dist/{chunk-HH5LY6RR.js.map → chunk-YIXJSW5M.js.map} +0 -0
- /package/dist/{chunk-2JSDPUKD.js.map → chunk-YMFPFXEX.js.map} +0 -0
- /package/dist/{chunk-N4KAE2NB.js.map → chunk-Z3FTSHT5.js.map} +0 -0
- /package/dist/{chunk-7GLJMDEQ.js.map → chunk-ZDV5YWID.js.map} +0 -0
- /package/dist/{chunk-645WOU5I.js.map → chunk-ZDZJNXL6.js.map} +0 -0
- /package/dist/{chunk-6TCXIRP5.js.map → chunk-ZKE4CO6B.js.map} +0 -0
- /package/dist/{contradiction-scan-P2MHYFVG.js.map → contradiction-scan-IBPYGQZF.js.map} +0 -0
- /package/dist/{resolution-N7H3F2E4.js.map → resolution-OVVIF7ZY.js.map} +0 -0
|
@@ -1,11 +1,152 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
SupportPassportCardCategorySchema,
|
|
3
|
+
SupportPassportMemoryIdSchema,
|
|
4
|
+
SupportPassportNamespaceSchema
|
|
5
|
+
} from "./chunk-AHA5VQGP.js";
|
|
6
|
+
import {
|
|
7
|
+
parseIsoOffsetTimestamp
|
|
8
|
+
} from "./chunk-P7FMDTKL.js";
|
|
5
9
|
import {
|
|
6
10
|
abortError,
|
|
7
11
|
isAbortError
|
|
8
12
|
} from "./chunk-R2MBW2S4.js";
|
|
13
|
+
import {
|
|
14
|
+
getOperation
|
|
15
|
+
} from "./chunk-JTSSSR4L.js";
|
|
16
|
+
|
|
17
|
+
// src/support-passport/grant-contracts.ts
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
var IsoTimestampSchema = z.string().datetime({ offset: true }).refine((value) => parseIsoOffsetTimestamp(value) !== null, "timestamp must be a real date");
|
|
20
|
+
var RevisionSchema = z.string().regex(/^[a-f0-9]{64}$/);
|
|
21
|
+
var GrantIdSchema = z.string().uuid().transform((value) => value.toLowerCase());
|
|
22
|
+
var SupportPassportGrantCardRefSchema = z.object({
|
|
23
|
+
cardId: SupportPassportMemoryIdSchema,
|
|
24
|
+
revision: RevisionSchema
|
|
25
|
+
}).strict();
|
|
26
|
+
var SupportPassportGrantStateSchema = z.object({
|
|
27
|
+
schemaVersion: z.literal(1),
|
|
28
|
+
stateVersion: z.number().int().positive(),
|
|
29
|
+
grantId: GrantIdSchema,
|
|
30
|
+
namespace: SupportPassportNamespaceSchema,
|
|
31
|
+
principalHash: RevisionSchema,
|
|
32
|
+
ownerLockKey: RevisionSchema,
|
|
33
|
+
secretHash: RevisionSchema,
|
|
34
|
+
cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
|
|
35
|
+
createdAt: IsoTimestampSchema,
|
|
36
|
+
expiresAt: IsoTimestampSchema,
|
|
37
|
+
revokedAt: IsoTimestampSchema.optional()
|
|
38
|
+
}).strict().superRefine((grant, ctx) => {
|
|
39
|
+
const ids = /* @__PURE__ */ new Set();
|
|
40
|
+
for (const [index, card] of grant.cards.entries()) {
|
|
41
|
+
if (ids.has(card.cardId)) {
|
|
42
|
+
ctx.addIssue({
|
|
43
|
+
code: z.ZodIssueCode.custom,
|
|
44
|
+
message: "card IDs must be unique",
|
|
45
|
+
path: ["cards", index, "cardId"]
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
ids.add(card.cardId);
|
|
49
|
+
}
|
|
50
|
+
if (Date.parse(grant.expiresAt) <= Date.parse(grant.createdAt)) {
|
|
51
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "expiresAt must follow createdAt", path: ["expiresAt"] });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
var SupportPassportCreateGrantInputSchema = z.object({
|
|
55
|
+
principal: z.string().trim().min(1).max(512),
|
|
56
|
+
cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
|
|
57
|
+
expiresAt: IsoTimestampSchema.optional(),
|
|
58
|
+
durationMs: z.number().int().min(3e5).max(6048e5).optional()
|
|
59
|
+
}).strict().superRefine((input, ctx) => {
|
|
60
|
+
const ids = /* @__PURE__ */ new Set();
|
|
61
|
+
for (const [index, card] of input.cards.entries()) {
|
|
62
|
+
if (ids.has(card.cardId)) {
|
|
63
|
+
ctx.addIssue({
|
|
64
|
+
code: z.ZodIssueCode.custom,
|
|
65
|
+
message: "card IDs must be unique",
|
|
66
|
+
path: ["cards", index, "cardId"]
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
ids.add(card.cardId);
|
|
70
|
+
}
|
|
71
|
+
if (input.expiresAt === void 0 === (input.durationMs === void 0)) {
|
|
72
|
+
ctx.addIssue({
|
|
73
|
+
code: z.ZodIssueCode.custom,
|
|
74
|
+
message: "one expiry value is required",
|
|
75
|
+
path: ["expiresAt"]
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
var SupportPassportCreateGrantRequestSchema = z.object({
|
|
80
|
+
cardIds: z.array(SupportPassportMemoryIdSchema).min(1).max(8),
|
|
81
|
+
cardRevisions: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
|
|
82
|
+
expiresAt: IsoTimestampSchema.optional(),
|
|
83
|
+
durationMs: z.number().int().min(3e5).max(6048e5).optional()
|
|
84
|
+
}).strict().superRefine((input, ctx) => {
|
|
85
|
+
const cardIds = new Set(input.cardIds);
|
|
86
|
+
const revisionIds = new Set(input.cardRevisions.map((card) => card.cardId));
|
|
87
|
+
if (cardIds.size !== input.cardIds.length || revisionIds.size !== input.cardRevisions.length || cardIds.size !== revisionIds.size || input.cardIds.some((cardId) => !revisionIds.has(cardId))) {
|
|
88
|
+
ctx.addIssue({
|
|
89
|
+
code: z.ZodIssueCode.custom,
|
|
90
|
+
message: "card revisions must match the selected card IDs",
|
|
91
|
+
path: ["cardRevisions"]
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (input.expiresAt === void 0 === (input.durationMs === void 0)) {
|
|
95
|
+
ctx.addIssue({
|
|
96
|
+
code: z.ZodIssueCode.custom,
|
|
97
|
+
message: "one expiry value is required",
|
|
98
|
+
path: ["expiresAt"]
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
var SupportPassportOwnerCreateGrantRequestSchema = SupportPassportCreateGrantRequestSchema;
|
|
103
|
+
var SupportPassportOwnerGrantSchema = z.object({
|
|
104
|
+
grantId: GrantIdSchema,
|
|
105
|
+
stateVersion: z.number().int().positive(),
|
|
106
|
+
cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),
|
|
107
|
+
createdAt: IsoTimestampSchema,
|
|
108
|
+
expiresAt: IsoTimestampSchema,
|
|
109
|
+
revokedAt: IsoTimestampSchema.optional(),
|
|
110
|
+
status: z.enum(["active", "expired", "revoked"])
|
|
111
|
+
}).strict();
|
|
112
|
+
var SupportPassportCreatedGrantSchema = z.object({
|
|
113
|
+
grant: SupportPassportOwnerGrantSchema,
|
|
114
|
+
secret: z.string().regex(/^[A-Za-z0-9_-]{43}$/)
|
|
115
|
+
}).strict();
|
|
116
|
+
var SupportPassportPublicCardSchema = z.object({
|
|
117
|
+
cardId: SupportPassportMemoryIdSchema,
|
|
118
|
+
title: z.string().trim().min(1).max(80),
|
|
119
|
+
statement: z.string().trim().min(1).max(500),
|
|
120
|
+
category: SupportPassportCardCategorySchema,
|
|
121
|
+
updatedAt: IsoTimestampSchema
|
|
122
|
+
}).strict();
|
|
123
|
+
var SupportPassportPublicGuideSchema = z.object({
|
|
124
|
+
schemaVersion: z.literal(1),
|
|
125
|
+
grantId: GrantIdSchema,
|
|
126
|
+
expiresAt: IsoTimestampSchema,
|
|
127
|
+
updatedAt: IsoTimestampSchema,
|
|
128
|
+
cards: z.array(SupportPassportPublicCardSchema).min(1).max(8)
|
|
129
|
+
}).strict();
|
|
130
|
+
var SupportPassportRevokeGrantInputSchema = z.object({
|
|
131
|
+
principal: z.string().trim().min(1).max(512),
|
|
132
|
+
grantId: GrantIdSchema,
|
|
133
|
+
expectedStateVersion: z.number().int().positive().optional()
|
|
134
|
+
}).strict();
|
|
135
|
+
var SupportPassportListGrantsInputSchema = z.object({
|
|
136
|
+
principal: z.string().trim().min(1).max(512)
|
|
137
|
+
}).strict();
|
|
138
|
+
|
|
139
|
+
// src/support-passport/errors.ts
|
|
140
|
+
var SupportPassportError = class extends Error {
|
|
141
|
+
code;
|
|
142
|
+
status;
|
|
143
|
+
constructor(code, message, status) {
|
|
144
|
+
super(message);
|
|
145
|
+
this.name = "SupportPassportError";
|
|
146
|
+
this.code = code;
|
|
147
|
+
this.status = status;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
9
150
|
|
|
10
151
|
// src/support-passport/public-http.ts
|
|
11
152
|
import { createHash } from "crypto";
|
|
@@ -494,9 +635,21 @@ function composeSupportPassportExternalRequestHandlers(...handlers) {
|
|
|
494
635
|
}
|
|
495
636
|
|
|
496
637
|
export {
|
|
638
|
+
SupportPassportGrantCardRefSchema,
|
|
639
|
+
SupportPassportGrantStateSchema,
|
|
640
|
+
SupportPassportCreateGrantInputSchema,
|
|
641
|
+
SupportPassportCreateGrantRequestSchema,
|
|
642
|
+
SupportPassportOwnerCreateGrantRequestSchema,
|
|
643
|
+
SupportPassportOwnerGrantSchema,
|
|
644
|
+
SupportPassportCreatedGrantSchema,
|
|
645
|
+
SupportPassportPublicCardSchema,
|
|
646
|
+
SupportPassportPublicGuideSchema,
|
|
647
|
+
SupportPassportRevokeGrantInputSchema,
|
|
648
|
+
SupportPassportListGrantsInputSchema,
|
|
649
|
+
SupportPassportError,
|
|
497
650
|
SUPPORT_PASSPORT_PUBLIC_HTTP_ROUTES,
|
|
498
651
|
normalizeSupportPassportNetworkAddress,
|
|
499
652
|
buildSupportPassportPublicRequestHandler,
|
|
500
653
|
composeSupportPassportExternalRequestHandlers
|
|
501
654
|
};
|
|
502
|
-
//# sourceMappingURL=chunk-
|
|
655
|
+
//# sourceMappingURL=chunk-P3WRNWWM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/support-passport/grant-contracts.ts","../src/support-passport/errors.ts","../src/support-passport/public-http.ts"],"sourcesContent":["import { z } from \"zod\";\n\nimport { parseIsoOffsetTimestamp } from \"../utils/iso-timestamp.js\";\nimport {\n SupportPassportCardCategorySchema,\n SupportPassportMemoryIdSchema,\n SupportPassportNamespaceSchema,\n} from \"./contracts.js\";\n\nconst IsoTimestampSchema = z\n .string()\n .datetime({ offset: true })\n .refine((value) => parseIsoOffsetTimestamp(value) !== null, \"timestamp must be a real date\");\nconst RevisionSchema = z.string().regex(/^[a-f0-9]{64}$/);\nconst GrantIdSchema = z\n .string()\n .uuid()\n .transform((value) => value.toLowerCase());\n\nexport const SupportPassportGrantCardRefSchema = z\n .object({\n cardId: SupportPassportMemoryIdSchema,\n revision: RevisionSchema,\n })\n .strict();\n\nexport const SupportPassportGrantStateSchema = z\n .object({\n schemaVersion: z.literal(1),\n stateVersion: z.number().int().positive(),\n grantId: GrantIdSchema,\n namespace: SupportPassportNamespaceSchema,\n principalHash: RevisionSchema,\n ownerLockKey: RevisionSchema,\n secretHash: RevisionSchema,\n cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),\n createdAt: IsoTimestampSchema,\n expiresAt: IsoTimestampSchema,\n revokedAt: IsoTimestampSchema.optional(),\n })\n .strict()\n .superRefine((grant, ctx) => {\n const ids = new Set<string>();\n for (const [index, card] of grant.cards.entries()) {\n if (ids.has(card.cardId)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"card IDs must be unique\",\n path: [\"cards\", index, \"cardId\"],\n });\n }\n ids.add(card.cardId);\n }\n if (Date.parse(grant.expiresAt) <= Date.parse(grant.createdAt)) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: \"expiresAt must follow createdAt\", path: [\"expiresAt\"] });\n }\n });\n\nexport const SupportPassportCreateGrantInputSchema = z\n .object({\n principal: z.string().trim().min(1).max(512),\n cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),\n expiresAt: IsoTimestampSchema.optional(),\n durationMs: z.number().int().min(300_000).max(604_800_000).optional(),\n })\n .strict()\n .superRefine((input, ctx) => {\n const ids = new Set<string>();\n for (const [index, card] of input.cards.entries()) {\n if (ids.has(card.cardId)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"card IDs must be unique\",\n path: [\"cards\", index, \"cardId\"],\n });\n }\n ids.add(card.cardId);\n }\n if ((input.expiresAt === undefined) === (input.durationMs === undefined)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"one expiry value is required\",\n path: [\"expiresAt\"],\n });\n }\n });\n\nexport const SupportPassportCreateGrantRequestSchema = z\n .object({\n cardIds: z.array(SupportPassportMemoryIdSchema).min(1).max(8),\n cardRevisions: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),\n expiresAt: IsoTimestampSchema.optional(),\n durationMs: z.number().int().min(300_000).max(604_800_000).optional(),\n })\n .strict()\n .superRefine((input, ctx) => {\n const cardIds = new Set(input.cardIds);\n const revisionIds = new Set(input.cardRevisions.map((card) => card.cardId));\n if (\n cardIds.size !== input.cardIds.length ||\n revisionIds.size !== input.cardRevisions.length ||\n cardIds.size !== revisionIds.size ||\n input.cardIds.some((cardId) => !revisionIds.has(cardId))\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"card revisions must match the selected card IDs\",\n path: [\"cardRevisions\"],\n });\n }\n if ((input.expiresAt === undefined) === (input.durationMs === undefined)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"one expiry value is required\",\n path: [\"expiresAt\"],\n });\n }\n });\n\nexport const SupportPassportOwnerCreateGrantRequestSchema = SupportPassportCreateGrantRequestSchema;\n\nexport const SupportPassportOwnerGrantSchema = z\n .object({\n grantId: GrantIdSchema,\n stateVersion: z.number().int().positive(),\n cards: z.array(SupportPassportGrantCardRefSchema).min(1).max(8),\n createdAt: IsoTimestampSchema,\n expiresAt: IsoTimestampSchema,\n revokedAt: IsoTimestampSchema.optional(),\n status: z.enum([\"active\", \"expired\", \"revoked\"]),\n })\n .strict();\n\nexport const SupportPassportCreatedGrantSchema = z\n .object({\n grant: SupportPassportOwnerGrantSchema,\n secret: z.string().regex(/^[A-Za-z0-9_-]{43}$/),\n })\n .strict();\n\nexport const SupportPassportPublicCardSchema = z\n .object({\n cardId: SupportPassportMemoryIdSchema,\n title: z.string().trim().min(1).max(80),\n statement: z.string().trim().min(1).max(500),\n category: SupportPassportCardCategorySchema,\n updatedAt: IsoTimestampSchema,\n })\n .strict();\n\nexport const SupportPassportPublicGuideSchema = z\n .object({\n schemaVersion: z.literal(1),\n grantId: GrantIdSchema,\n expiresAt: IsoTimestampSchema,\n updatedAt: IsoTimestampSchema,\n cards: z.array(SupportPassportPublicCardSchema).min(1).max(8),\n })\n .strict();\n\nexport const SupportPassportRevokeGrantInputSchema = z\n .object({\n principal: z.string().trim().min(1).max(512),\n grantId: GrantIdSchema,\n expectedStateVersion: z.number().int().positive().optional(),\n })\n .strict();\n\nexport const SupportPassportListGrantsInputSchema = z\n .object({\n principal: z.string().trim().min(1).max(512),\n })\n .strict();\n\nexport type SupportPassportGrantCardRef = z.infer<typeof SupportPassportGrantCardRefSchema>;\nexport type SupportPassportGrantState = z.infer<typeof SupportPassportGrantStateSchema>;\nexport type SupportPassportCreateGrantInput = z.input<typeof SupportPassportCreateGrantInputSchema>;\nexport type SupportPassportCreateGrantRequest = z.input<typeof SupportPassportCreateGrantRequestSchema>;\nexport type SupportPassportOwnerCreateGrantRequest = z.input<typeof SupportPassportOwnerCreateGrantRequestSchema>;\nexport type SupportPassportOwnerGrant = z.infer<typeof SupportPassportOwnerGrantSchema>;\nexport type SupportPassportCreatedGrant = z.infer<typeof SupportPassportCreatedGrantSchema>;\nexport type SupportPassportPublicGuide = z.infer<typeof SupportPassportPublicGuideSchema>;\nexport type SupportPassportRevokeGrantInput = z.input<typeof SupportPassportRevokeGrantInputSchema>;\n","export type SupportPassportErrorCode =\n | \"card_data_invalid\"\n | \"card_not_found\"\n | \"consent_required\"\n | \"feature_disabled\"\n | \"forbidden\"\n | \"grant_expired\"\n | \"grant_gone\"\n | \"grant_not_found\"\n | \"grant_stale\"\n | \"invalid_card_status\"\n | \"invalid_input\"\n | \"model_output_invalid\"\n | \"provider_unavailable\"\n | \"rate_limited\"\n | \"revision_conflict\"\n | \"state_conflict\"\n | \"storage_conflict\";\n\nexport class SupportPassportError extends Error {\n readonly code: SupportPassportErrorCode;\n readonly status: number;\n\n constructor(code: SupportPassportErrorCode, message: string, status: number) {\n super(message);\n this.name = \"SupportPassportError\";\n this.code = code;\n this.status = status;\n }\n}\n","import { createHash } from \"node:crypto\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { isIP } from \"node:net\";\n\nimport { abortError, isAbortError } from \"../abort-error.js\";\nimport { type OperationName, getOperation } from \"../access-boundary.js\";\nimport type { EngramAccessService } from \"../access-service.js\";\nimport { SupportPassportError } from \"./errors.js\";\n\nconst PUBLIC_RATE_LIMIT_MAX_KEYS = 20_000;\nconst PUBLIC_AUTH_MAX_IN_FLIGHT_PER_NETWORK = 8;\nconst PUBLIC_AUTH_MAX_IN_FLIGHT_TOTAL = 256;\nconst PUBLIC_MODEL_MAX_IN_FLIGHT_PER_NETWORK = 8;\nconst PUBLIC_MODEL_MAX_IN_FLIGHT_TOTAL = 256;\n\nexport const SUPPORT_PASSPORT_PUBLIC_HTTP_ROUTES = [\n {\n method: \"GET\",\n pathname: \"/engram/v1/support-passport/public/grants/:id\",\n operation: \"support_passport_grant_read\",\n },\n {\n method: \"POST\",\n pathname: \"/engram/v1/support-passport/public/grants/:id/ask\",\n operation: \"support_passport_grant_ask\",\n },\n] as const satisfies ReadonlyArray<{ method: string; pathname: string; operation: OperationName }>;\n\nexport type SupportPassportExternalRequestHandler = (\n req: IncomingMessage,\n res: ServerResponse,\n ctx: {\n authorized: boolean;\n tokenAuthorized: boolean;\n }\n) => Promise<boolean>;\n\ninterface WindowEntry {\n count: number;\n resetAt: number;\n}\n\ninterface WindowReservation {\n commit(): void;\n release(): void;\n}\n\nclass UnreadSupportPassportRequestError extends Error {\n constructor(readonly response: SupportPassportError) {\n super(response.message);\n this.name = \"UnreadSupportPassportRequestError\";\n }\n}\n\nclass FixedWindowLimiter {\n private readonly entries = new Map<string, WindowEntry>();\n\n constructor(\n private readonly limit: number,\n private readonly windowMs: number,\n private readonly now: () => number\n ) {}\n\n consume(key: string): boolean {\n const reservation = this.reserve(key);\n if (!reservation) return false;\n reservation.commit();\n return true;\n }\n\n reserve(key: string): WindowReservation | undefined {\n const now = this.now();\n let entry = this.entries.get(key);\n if (!entry || entry.resetAt <= now) {\n if (!entry && this.entries.size >= PUBLIC_RATE_LIMIT_MAX_KEYS) {\n this.prune(now);\n if (this.entries.size >= PUBLIC_RATE_LIMIT_MAX_KEYS) return undefined;\n }\n entry = { count: 0, resetAt: now + this.windowMs };\n this.entries.set(key, entry);\n }\n if (entry.count >= this.limit) return undefined;\n entry.count += 1;\n let active = true;\n return {\n commit: () => {\n active = false;\n },\n release: () => {\n if (!active) return;\n active = false;\n if (this.entries.get(key) !== entry) return;\n entry.count -= 1;\n if (entry.count === 0) this.entries.delete(key);\n },\n };\n }\n\n allows(key: string): boolean {\n const now = this.now();\n const current = this.entries.get(key);\n if (current && current.resetAt > now) return current.count < this.limit;\n if (!current && this.entries.size >= PUBLIC_RATE_LIMIT_MAX_KEYS) {\n this.prune(now);\n if (this.entries.size >= PUBLIC_RATE_LIMIT_MAX_KEYS) return false;\n }\n return true;\n }\n\n private prune(now: number): void {\n for (const [key, entry] of this.entries) {\n if (entry.resetAt <= now) this.entries.delete(key);\n }\n }\n}\n\nclass InFlightLimiter {\n private readonly counts = new Map<string, number>();\n private total = 0;\n\n constructor(\n private readonly perKeyLimit: number,\n private readonly totalLimit: number\n ) {}\n\n reserve(key: string): (() => void) | undefined {\n const current = this.counts.get(key) ?? 0;\n if (current >= this.perKeyLimit || this.total >= this.totalLimit) return undefined;\n this.counts.set(key, current + 1);\n this.total += 1;\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n const count = this.counts.get(key) ?? 0;\n if (count <= 1) this.counts.delete(key);\n else this.counts.set(key, count - 1);\n this.total -= 1;\n };\n }\n}\n\ninterface PublicRateLimits {\n authentications: InFlightLimiter;\n modelCalls: InFlightLimiter;\n grantReads: FixedWindowLimiter;\n networkReads: FixedWindowLimiter;\n networkReadFailures: FixedWindowLimiter;\n grantQuestions: FixedWindowLimiter;\n networkQuestions: FixedWindowLimiter;\n networkQuestionFailures: FixedWindowLimiter;\n}\n\nexport interface SupportPassportPublicHandlerOptions {\n now?: () => number;\n trustedProxyAddresses?: readonly string[];\n}\n\nfunction createRateLimits(now: () => number): PublicRateLimits {\n return {\n authentications: new InFlightLimiter(PUBLIC_AUTH_MAX_IN_FLIGHT_PER_NETWORK, PUBLIC_AUTH_MAX_IN_FLIGHT_TOTAL),\n modelCalls: new InFlightLimiter(PUBLIC_MODEL_MAX_IN_FLIGHT_PER_NETWORK, PUBLIC_MODEL_MAX_IN_FLIGHT_TOTAL),\n grantReads: new FixedWindowLimiter(60, 60_000, now),\n networkReads: new FixedWindowLimiter(60, 60_000, now),\n networkReadFailures: new FixedWindowLimiter(60, 60_000, now),\n grantQuestions: new FixedWindowLimiter(20, 10 * 60_000, now),\n networkQuestions: new FixedWindowLimiter(20, 10 * 60_000, now),\n networkQuestionFailures: new FixedWindowLimiter(20, 10 * 60_000, now),\n };\n}\n\nfunction rateLimited(): SupportPassportError {\n return new SupportPassportError(\"rate_limited\", \"Too many helper requests.\", 429);\n}\n\nasync function runPublicOperation(\n service: EngramAccessService,\n name: \"support_passport_grant_read\" | \"support_passport_grant_ask\",\n input: Record<string, unknown>,\n signal?: AbortSignal\n): Promise<unknown> {\n const operation = getOperation(name);\n if (!operation) throw new Error(`access-boundary: operation not registered: ${name}`);\n const output = (await operation.run(input, {\n service,\n ...(signal ? { abortSignal: signal } : {}),\n })) as { result: unknown };\n return output.result;\n}\n\nfunction reserveAuthenticatedLimits(\n networkLimiter: FixedWindowLimiter,\n grantLimiter: FixedWindowLimiter,\n networkKey: string,\n grantId: string\n): WindowReservation {\n const network = networkLimiter.reserve(networkKey);\n if (!network) throw rateLimited();\n const grant = grantLimiter.reserve(grantId);\n if (!grant) {\n network.release();\n throw rateLimited();\n }\n let active = true;\n return {\n commit: () => {\n if (!active) return;\n active = false;\n network.commit();\n grant.commit();\n },\n release: () => {\n if (!active) return;\n active = false;\n grant.release();\n network.release();\n },\n };\n}\n\nasync function readGrantUnderAuthenticationReservation(\n service: EngramAccessService,\n grantId: string,\n secret: string,\n networkKey: string,\n networkLimiter: FixedWindowLimiter,\n grantLimiter: FixedWindowLimiter,\n failureLimiter: FixedWindowLimiter\n) {\n if (!failureLimiter.allows(networkKey)) throw rateLimited();\n const limits = reserveAuthenticatedLimits(networkLimiter, grantLimiter, networkKey, grantId);\n let guide: Awaited<ReturnType<EngramAccessService[\"supportPassportReadGrant\"]>>;\n try {\n guide = (await runPublicOperation(service, \"support_passport_grant_read\", { grantId, secret })) as Awaited<\n ReturnType<EngramAccessService[\"supportPassportReadGrant\"]>\n >;\n } catch (error) {\n if (error instanceof SupportPassportError) {\n if (error.code === \"grant_not_found\") {\n limits.release();\n if (!failureLimiter.consume(networkKey)) throw rateLimited();\n } else {\n limits.commit();\n }\n } else {\n limits.release();\n }\n throw error;\n }\n limits.commit();\n return guide;\n}\n\nasync function readGrantWithRateLimits(\n service: EngramAccessService,\n grantId: string,\n secret: string,\n networkKey: string,\n networkLimiter: FixedWindowLimiter,\n grantLimiter: FixedWindowLimiter,\n failureLimiter: FixedWindowLimiter,\n authenticationLimiter: InFlightLimiter\n) {\n const releaseAuthentication = authenticationLimiter.reserve(networkKey);\n if (!releaseAuthentication) throw rateLimited();\n try {\n return await readGrantUnderAuthenticationReservation(\n service,\n grantId,\n secret,\n networkKey,\n networkLimiter,\n grantLimiter,\n failureLimiter\n );\n } finally {\n releaseAuthentication();\n }\n}\n\nexport function normalizeSupportPassportNetworkAddress(value: string | undefined): string | undefined {\n if (!value) return undefined;\n const address = value.trim().toLowerCase();\n const family = isIP(address);\n if (family === 0) return undefined;\n if (family === 4) return address;\n const canonical = new URL(`http://[${address}]/`).hostname.slice(1, -1);\n const mapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(canonical);\n if (!mapped) return canonical;\n const high = Number.parseInt(mapped[1] ?? \"\", 16);\n const low = Number.parseInt(mapped[2] ?? \"\", 16);\n return `${high >>> 8}.${high & 0xff}.${low >>> 8}.${low & 0xff}`;\n}\n\nfunction requestNetworkAddress(req: IncomingMessage, trustedProxyAddresses: ReadonlySet<string>): string {\n const directAddress = normalizeSupportPassportNetworkAddress(req.socket.remoteAddress) ?? \"unknown\";\n if (!trustedProxyAddresses.has(directAddress)) return directAddress;\n const forwarded = req.headers[\"x-forwarded-for\"];\n if (typeof forwarded !== \"string\") return directAddress;\n const rawAddresses = forwarded.split(\",\");\n if (rawAddresses.length < 1 || rawAddresses.length > 32) return directAddress;\n const addresses = rawAddresses.map((address) => normalizeSupportPassportNetworkAddress(address));\n if (addresses.some((address) => address === undefined)) return directAddress;\n for (let index = addresses.length - 1; index >= 0; index -= 1) {\n const address = addresses[index];\n if (address && !trustedProxyAddresses.has(address)) return address;\n }\n return addresses[0] ?? directAddress;\n}\n\nfunction networkDigest(req: IncomingMessage, trustedProxyAddresses: ReadonlySet<string>): string {\n return createHash(\"sha256\")\n .update(requestNetworkAddress(req, trustedProxyAddresses))\n .digest(\"hex\");\n}\n\nfunction parseSecret(req: IncomingMessage): string | undefined {\n const raw = req.headers.authorization;\n if (typeof raw !== \"string\") return undefined;\n const match = /^(\\S+)[ \\t]+(\\S+)$/.exec(raw);\n if (!match || match[1]?.toLowerCase() !== \"supportpassport\") return undefined;\n const secret = match[2] ?? \"\";\n if (!/^[A-Za-z0-9_-]{32,256}$/.test(secret)) return undefined;\n return secret;\n}\n\nfunction requestDeclaresBody(req: IncomingMessage): boolean {\n const contentLength = req.headers[\"content-length\"];\n const transferEncoding = req.headers[\"transfer-encoding\"];\n return transferEncoding !== undefined || (contentLength !== undefined && contentLength !== \"0\");\n}\n\nfunction respondJson(res: ServerResponse, status: number, payload: unknown): void {\n const body = JSON.stringify(payload);\n res.statusCode = status;\n res.setHeader(\"cache-control\", \"private, no-store\");\n res.setHeader(\"vary\", \"Authorization\");\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.setHeader(\"content-length\", String(Buffer.byteLength(body)));\n res.end(body);\n}\n\nfunction respondJsonAndCloseUnreadRequest(\n req: IncomingMessage,\n res: ServerResponse,\n status: number,\n payload: unknown\n): void {\n res.shouldKeepAlive = false;\n res.setHeader(\"connection\", \"close\");\n res.once(\"finish\", () => req.destroy());\n respondJson(res, status, payload);\n}\n\nfunction respondBeforeReadingBody(\n req: IncomingMessage,\n res: ServerResponse,\n status: number,\n payload: unknown\n): void {\n if (requestDeclaresBody(req)) {\n respondJsonAndCloseUnreadRequest(req, res, status, payload);\n return;\n }\n respondJson(res, status, payload);\n}\n\nasync function readQuestionBody(req: IncomingMessage, signal: AbortSignal): Promise<string> {\n const content = await new Promise<Buffer>((resolve, reject) => {\n const chunks: Buffer[] = [];\n let bytes = 0;\n let settled = false;\n const cleanup = () => {\n req.off(\"data\", onData);\n req.off(\"end\", onEnd);\n req.off(\"error\", onError);\n req.off(\"aborted\", onAborted);\n signal.removeEventListener(\"abort\", onSignalAbort);\n };\n const fail = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(error);\n };\n const helperLeft = () =>\n isAbortError(signal.reason) ? signal.reason : abortError(\"The helper left.\");\n const onData = (chunk: Buffer | string) => {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n bytes += buffer.length;\n if (bytes > 4_096) {\n req.pause();\n fail(\n new UnreadSupportPassportRequestError(\n new SupportPassportError(\"invalid_input\", \"The helper question is invalid.\", 400)\n )\n );\n return;\n }\n chunks.push(buffer);\n };\n const onEnd = () => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(Buffer.concat(chunks, bytes));\n };\n const onError = (error: Error) => fail(signal.aborted || req.aborted ? helperLeft() : error);\n const onAborted = () => fail(helperLeft());\n const onSignalAbort = () => fail(helperLeft());\n req.on(\"data\", onData);\n req.once(\"end\", onEnd);\n req.once(\"error\", onError);\n req.once(\"aborted\", onAborted);\n signal.addEventListener(\"abort\", onSignalAbort, { once: true });\n if (signal.aborted) onSignalAbort();\n });\n let parsed: unknown;\n try {\n parsed = JSON.parse(content.toString(\"utf8\"));\n } catch {\n throw new SupportPassportError(\"invalid_input\", \"The helper question is invalid.\", 400);\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new SupportPassportError(\"invalid_input\", \"The helper question is invalid.\", 400);\n }\n const body = parsed as Record<string, unknown>;\n if (Object.keys(body).length !== 1 || typeof body.question !== \"string\") {\n throw new SupportPassportError(\"invalid_input\", \"The helper question is invalid.\", 400);\n }\n const question = body.question.trim();\n if (question.length < 1 || question.length > 500) {\n throw new SupportPassportError(\"invalid_input\", \"The helper question is invalid.\", 400);\n }\n return question;\n}\n\nfunction requestSignal(req: IncomingMessage, res: ServerResponse): { signal: AbortSignal; cleanup(): void } {\n const controller = new AbortController();\n const abort = () => {\n if (!res.writableFinished && !controller.signal.aborted) controller.abort(abortError(\"The helper left.\"));\n };\n req.once(\"aborted\", abort);\n res.once(\"close\", abort);\n return {\n signal: controller.signal,\n cleanup: () => {\n req.off(\"aborted\", abort);\n res.off(\"close\", abort);\n },\n };\n}\n\nfunction decodeGrantId(raw: string): string | undefined {\n try {\n const value = decodeURIComponent(raw);\n return /^[A-Za-z0-9_-]{1,128}$/.test(value) ? value.toLowerCase() : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function buildSupportPassportPublicRequestHandler(\n service: EngramAccessService,\n options: SupportPassportPublicHandlerOptions = {}\n): SupportPassportExternalRequestHandler {\n const rateLimits = createRateLimits(options.now ?? Date.now);\n const trustedProxyAddresses = new Set(\n (options.trustedProxyAddresses ?? [])\n .map((address) => normalizeSupportPassportNetworkAddress(address))\n .filter((address): address is string => address !== undefined)\n );\n return async (req, res) => {\n let parsed: URL;\n try {\n parsed = new URL(req.url ?? \"/\", \"http://placeholder\");\n } catch {\n return false;\n }\n const readMatch = /^\\/engram\\/v1\\/support-passport\\/public\\/grants\\/([^/]+)$/.exec(parsed.pathname);\n const askMatch = /^\\/engram\\/v1\\/support-passport\\/public\\/grants\\/([^/]+)\\/ask$/.exec(parsed.pathname);\n const ownedRead = req.method === \"GET\" && readMatch;\n const ownedQuestion = req.method === \"POST\" && askMatch;\n if (!ownedRead && !ownedQuestion) return false;\n\n res.setHeader(\"cache-control\", \"private, no-store\");\n res.setHeader(\"vary\", \"Authorization\");\n const grantId = decodeGrantId((ownedRead ? readMatch?.[1] : askMatch?.[1]) ?? \"\");\n const secret = parseSecret(req);\n if (parsed.search.length > 0) {\n respondBeforeReadingBody(req, res, 400, {\n error: \"The share link request is invalid.\",\n code: \"invalid_input\",\n });\n return true;\n }\n if (ownedRead && requestDeclaresBody(req)) {\n respondJsonAndCloseUnreadRequest(req, res, 400, {\n error: \"The share link request is invalid.\",\n code: \"invalid_input\",\n });\n return true;\n }\n if (!grantId || !secret) {\n respondBeforeReadingBody(req, res, 404, {\n error: \"The share link was not found.\",\n code: \"grant_not_found\",\n });\n return true;\n }\n\n const lifecycle = requestSignal(req, res);\n try {\n const digest = networkDigest(req, trustedProxyAddresses);\n if (ownedRead) {\n const guide = await readGrantWithRateLimits(\n service,\n grantId,\n secret,\n digest,\n rateLimits.networkReads,\n rateLimits.grantReads,\n rateLimits.networkReadFailures,\n rateLimits.authentications\n );\n respondJson(res, 200, guide);\n } else {\n let releaseAuthentication = rateLimits.authentications.reserve(digest);\n if (!releaseAuthentication) throw new UnreadSupportPassportRequestError(rateLimited());\n try {\n let question: string;\n const bodyFailure = rateLimits.networkQuestionFailures.reserve(digest);\n if (!bodyFailure) throw new UnreadSupportPassportRequestError(rateLimited());\n try {\n question = await readQuestionBody(req, lifecycle.signal);\n bodyFailure.release();\n } catch (error) {\n const supportError =\n error instanceof UnreadSupportPassportRequestError ? error.response : error;\n if (supportError instanceof SupportPassportError && supportError.code === \"invalid_input\") {\n bodyFailure.commit();\n } else {\n bodyFailure.release();\n }\n throw error;\n }\n const releaseModelCall = rateLimits.modelCalls.reserve(digest);\n if (!releaseModelCall) throw rateLimited();\n try {\n await readGrantUnderAuthenticationReservation(\n service,\n grantId,\n secret,\n digest,\n rateLimits.networkQuestions,\n rateLimits.grantQuestions,\n rateLimits.networkQuestionFailures\n );\n releaseAuthentication();\n releaseAuthentication = undefined;\n const answer = await runPublicOperation(\n service,\n \"support_passport_grant_ask\",\n { grantId, secret, question },\n lifecycle.signal\n );\n respondJson(res, 200, answer);\n } finally {\n releaseModelCall();\n }\n } finally {\n releaseAuthentication?.();\n }\n }\n } catch (error) {\n if (error instanceof UnreadSupportPassportRequestError) {\n respondJsonAndCloseUnreadRequest(req, res, error.response.status, {\n error: error.response.message,\n code: error.response.code,\n });\n return true;\n }\n if (!(error instanceof SupportPassportError)) throw error;\n respondJson(res, error.status, { error: error.message, code: error.code });\n } finally {\n lifecycle.cleanup();\n }\n return true;\n };\n}\n\nexport function composeSupportPassportExternalRequestHandlers(\n ...handlers: Array<SupportPassportExternalRequestHandler | undefined>\n): SupportPassportExternalRequestHandler {\n return async (req, res, ctx) => {\n for (const handler of handlers) {\n if (handler && (await handler(req, res, ctx))) return true;\n }\n return false;\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS;AASlB,IAAM,qBAAqB,EACxB,OAAO,EACP,SAAS,EAAE,QAAQ,KAAK,CAAC,EACzB,OAAO,CAAC,UAAU,wBAAwB,KAAK,MAAM,MAAM,+BAA+B;AAC7F,IAAM,iBAAiB,EAAE,OAAO,EAAE,MAAM,gBAAgB;AACxD,IAAM,gBAAgB,EACnB,OAAO,EACP,KAAK,EACL,UAAU,CAAC,UAAU,MAAM,YAAY,CAAC;AAEpC,IAAM,oCAAoC,EAC9C,OAAO;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AACZ,CAAC,EACA,OAAO;AAEH,IAAM,kCAAkC,EAC5C,OAAO;AAAA,EACN,eAAe,EAAE,QAAQ,CAAC;AAAA,EAC1B,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACxC,SAAS;AAAA,EACT,WAAW;AAAA,EACX,eAAe;AAAA,EACf,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,OAAO,EAAE,MAAM,iCAAiC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC9D,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW,mBAAmB,SAAS;AACzC,CAAC,EACA,OAAO,EACP,YAAY,CAAC,OAAO,QAAQ;AAC3B,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,CAAC,OAAO,IAAI,KAAK,MAAM,MAAM,QAAQ,GAAG;AACjD,QAAI,IAAI,IAAI,KAAK,MAAM,GAAG;AACxB,UAAI,SAAS;AAAA,QACX,MAAM,EAAE,aAAa;AAAA,QACrB,SAAS;AAAA,QACT,MAAM,CAAC,SAAS,OAAO,QAAQ;AAAA,MACjC,CAAC;AAAA,IACH;AACA,QAAI,IAAI,KAAK,MAAM;AAAA,EACrB;AACA,MAAI,KAAK,MAAM,MAAM,SAAS,KAAK,KAAK,MAAM,MAAM,SAAS,GAAG;AAC9D,QAAI,SAAS,EAAE,MAAM,EAAE,aAAa,QAAQ,SAAS,mCAAmC,MAAM,CAAC,WAAW,EAAE,CAAC;AAAA,EAC/G;AACF,CAAC;AAEI,IAAM,wCAAwC,EAClD,OAAO;AAAA,EACN,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAC3C,OAAO,EAAE,MAAM,iCAAiC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC9D,WAAW,mBAAmB,SAAS;AAAA,EACvC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAO,EAAE,IAAI,MAAW,EAAE,SAAS;AACtE,CAAC,EACA,OAAO,EACP,YAAY,CAAC,OAAO,QAAQ;AAC3B,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,CAAC,OAAO,IAAI,KAAK,MAAM,MAAM,QAAQ,GAAG;AACjD,QAAI,IAAI,IAAI,KAAK,MAAM,GAAG;AACxB,UAAI,SAAS;AAAA,QACX,MAAM,EAAE,aAAa;AAAA,QACrB,SAAS;AAAA,QACT,MAAM,CAAC,SAAS,OAAO,QAAQ;AAAA,MACjC,CAAC;AAAA,IACH;AACA,QAAI,IAAI,KAAK,MAAM;AAAA,EACrB;AACA,MAAK,MAAM,cAAc,YAAgB,MAAM,eAAe,SAAY;AACxE,QAAI,SAAS;AAAA,MACX,MAAM,EAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,WAAW;AAAA,IACpB,CAAC;AAAA,EACH;AACF,CAAC;AAEI,IAAM,0CAA0C,EACpD,OAAO;AAAA,EACN,SAAS,EAAE,MAAM,6BAA6B,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC5D,eAAe,EAAE,MAAM,iCAAiC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACtE,WAAW,mBAAmB,SAAS;AAAA,EACvC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAO,EAAE,IAAI,MAAW,EAAE,SAAS;AACtE,CAAC,EACA,OAAO,EACP,YAAY,CAAC,OAAO,QAAQ;AAC3B,QAAM,UAAU,IAAI,IAAI,MAAM,OAAO;AACrC,QAAM,cAAc,IAAI,IAAI,MAAM,cAAc,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC;AAC1E,MACE,QAAQ,SAAS,MAAM,QAAQ,UAC/B,YAAY,SAAS,MAAM,cAAc,UACzC,QAAQ,SAAS,YAAY,QAC7B,MAAM,QAAQ,KAAK,CAAC,WAAW,CAAC,YAAY,IAAI,MAAM,CAAC,GACvD;AACA,QAAI,SAAS;AAAA,MACX,MAAM,EAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,eAAe;AAAA,IACxB,CAAC;AAAA,EACH;AACA,MAAK,MAAM,cAAc,YAAgB,MAAM,eAAe,SAAY;AACxE,QAAI,SAAS;AAAA,MACX,MAAM,EAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,WAAW;AAAA,IACpB,CAAC;AAAA,EACH;AACF,CAAC;AAEI,IAAM,+CAA+C;AAErD,IAAM,kCAAkC,EAC5C,OAAO;AAAA,EACN,SAAS;AAAA,EACT,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACxC,OAAO,EAAE,MAAM,iCAAiC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC9D,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW,mBAAmB,SAAS;AAAA,EACvC,QAAQ,EAAE,KAAK,CAAC,UAAU,WAAW,SAAS,CAAC;AACjD,CAAC,EACA,OAAO;AAEH,IAAM,oCAAoC,EAC9C,OAAO;AAAA,EACN,OAAO;AAAA,EACP,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB;AAChD,CAAC,EACA,OAAO;AAEH,IAAM,kCAAkC,EAC5C,OAAO;AAAA,EACN,QAAQ;AAAA,EACR,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EACtC,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAC3C,UAAU;AAAA,EACV,WAAW;AACb,CAAC,EACA,OAAO;AAEH,IAAM,mCAAmC,EAC7C,OAAO;AAAA,EACN,eAAe,EAAE,QAAQ,CAAC;AAAA,EAC1B,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,OAAO,EAAE,MAAM,+BAA+B,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAC9D,CAAC,EACA,OAAO;AAEH,IAAM,wCAAwC,EAClD,OAAO;AAAA,EACN,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAC3C,SAAS;AAAA,EACT,sBAAsB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAC7D,CAAC,EACA,OAAO;AAEH,IAAM,uCAAuC,EACjD,OAAO;AAAA,EACN,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAC7C,CAAC,EACA,OAAO;;;ACzJH,IAAM,uBAAN,cAAmC,MAAM;AAAA,EACrC;AAAA,EACA;AAAA,EAET,YAAY,MAAgC,SAAiB,QAAgB;AAC3E,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;;;AC7BA,SAAS,kBAAkB;AAE3B,SAAS,YAAY;AAOrB,IAAM,6BAA6B;AACnC,IAAM,wCAAwC;AAC9C,IAAM,kCAAkC;AACxC,IAAM,yCAAyC;AAC/C,IAAM,mCAAmC;AAElC,IAAM,sCAAsC;AAAA,EACjD;AAAA,IACE,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAAA,EACA;AAAA,IACE,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AACF;AAqBA,IAAM,oCAAN,cAAgD,MAAM;AAAA,EACpD,YAAqB,UAAgC;AACnD,UAAM,SAAS,OAAO;AADH;AAEnB,SAAK,OAAO;AAAA,EACd;AAAA,EAHqB;AAIvB;AAEA,IAAM,qBAAN,MAAyB;AAAA,EAGvB,YACmB,OACA,UACA,KACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EALF,UAAU,oBAAI,IAAyB;AAAA,EAQxD,QAAQ,KAAsB;AAC5B,UAAM,cAAc,KAAK,QAAQ,GAAG;AACpC,QAAI,CAAC,YAAa,QAAO;AACzB,gBAAY,OAAO;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,KAA4C;AAClD,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,QAAQ,KAAK,QAAQ,IAAI,GAAG;AAChC,QAAI,CAAC,SAAS,MAAM,WAAW,KAAK;AAClC,UAAI,CAAC,SAAS,KAAK,QAAQ,QAAQ,4BAA4B;AAC7D,aAAK,MAAM,GAAG;AACd,YAAI,KAAK,QAAQ,QAAQ,2BAA4B,QAAO;AAAA,MAC9D;AACA,cAAQ,EAAE,OAAO,GAAG,SAAS,MAAM,KAAK,SAAS;AACjD,WAAK,QAAQ,IAAI,KAAK,KAAK;AAAA,IAC7B;AACA,QAAI,MAAM,SAAS,KAAK,MAAO,QAAO;AACtC,UAAM,SAAS;AACf,QAAI,SAAS;AACb,WAAO;AAAA,MACL,QAAQ,MAAM;AACZ,iBAAS;AAAA,MACX;AAAA,MACA,SAAS,MAAM;AACb,YAAI,CAAC,OAAQ;AACb,iBAAS;AACT,YAAI,KAAK,QAAQ,IAAI,GAAG,MAAM,MAAO;AACrC,cAAM,SAAS;AACf,YAAI,MAAM,UAAU,EAAG,MAAK,QAAQ,OAAO,GAAG;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,KAAsB;AAC3B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;AACpC,QAAI,WAAW,QAAQ,UAAU,IAAK,QAAO,QAAQ,QAAQ,KAAK;AAClE,QAAI,CAAC,WAAW,KAAK,QAAQ,QAAQ,4BAA4B;AAC/D,WAAK,MAAM,GAAG;AACd,UAAI,KAAK,QAAQ,QAAQ,2BAA4B,QAAO;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,MAAM,KAAmB;AAC/B,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,SAAS;AACvC,UAAI,MAAM,WAAW,IAAK,MAAK,QAAQ,OAAO,GAAG;AAAA,IACnD;AAAA,EACF;AACF;AAEA,IAAM,kBAAN,MAAsB;AAAA,EAIpB,YACmB,aACA,YACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EALF,SAAS,oBAAI,IAAoB;AAAA,EAC1C,QAAQ;AAAA,EAOhB,QAAQ,KAAuC;AAC7C,UAAM,UAAU,KAAK,OAAO,IAAI,GAAG,KAAK;AACxC,QAAI,WAAW,KAAK,eAAe,KAAK,SAAS,KAAK,WAAY,QAAO;AACzE,SAAK,OAAO,IAAI,KAAK,UAAU,CAAC;AAChC,SAAK,SAAS;AACd,QAAI,SAAS;AACb,WAAO,MAAM;AACX,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,YAAM,QAAQ,KAAK,OAAO,IAAI,GAAG,KAAK;AACtC,UAAI,SAAS,EAAG,MAAK,OAAO,OAAO,GAAG;AAAA,UACjC,MAAK,OAAO,IAAI,KAAK,QAAQ,CAAC;AACnC,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AACF;AAkBA,SAAS,iBAAiB,KAAqC;AAC7D,SAAO;AAAA,IACL,iBAAiB,IAAI,gBAAgB,uCAAuC,+BAA+B;AAAA,IAC3G,YAAY,IAAI,gBAAgB,wCAAwC,gCAAgC;AAAA,IACxG,YAAY,IAAI,mBAAmB,IAAI,KAAQ,GAAG;AAAA,IAClD,cAAc,IAAI,mBAAmB,IAAI,KAAQ,GAAG;AAAA,IACpD,qBAAqB,IAAI,mBAAmB,IAAI,KAAQ,GAAG;AAAA,IAC3D,gBAAgB,IAAI,mBAAmB,IAAI,KAAK,KAAQ,GAAG;AAAA,IAC3D,kBAAkB,IAAI,mBAAmB,IAAI,KAAK,KAAQ,GAAG;AAAA,IAC7D,yBAAyB,IAAI,mBAAmB,IAAI,KAAK,KAAQ,GAAG;AAAA,EACtE;AACF;AAEA,SAAS,cAAoC;AAC3C,SAAO,IAAI,qBAAqB,gBAAgB,6BAA6B,GAAG;AAClF;AAEA,eAAe,mBACb,SACA,MACA,OACA,QACkB;AAClB,QAAM,YAAY,aAAa,IAAI;AACnC,MAAI,CAAC,UAAW,OAAM,IAAI,MAAM,8CAA8C,IAAI,EAAE;AACpF,QAAM,SAAU,MAAM,UAAU,IAAI,OAAO;AAAA,IACzC;AAAA,IACA,GAAI,SAAS,EAAE,aAAa,OAAO,IAAI,CAAC;AAAA,EAC1C,CAAC;AACD,SAAO,OAAO;AAChB;AAEA,SAAS,2BACP,gBACA,cACA,YACA,SACmB;AACnB,QAAM,UAAU,eAAe,QAAQ,UAAU;AACjD,MAAI,CAAC,QAAS,OAAM,YAAY;AAChC,QAAM,QAAQ,aAAa,QAAQ,OAAO;AAC1C,MAAI,CAAC,OAAO;AACV,YAAQ,QAAQ;AAChB,UAAM,YAAY;AAAA,EACpB;AACA,MAAI,SAAS;AACb,SAAO;AAAA,IACL,QAAQ,MAAM;AACZ,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,cAAQ,OAAO;AACf,YAAM,OAAO;AAAA,IACf;AAAA,IACA,SAAS,MAAM;AACb,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,YAAM,QAAQ;AACd,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AACF;AAEA,eAAe,wCACb,SACA,SACA,QACA,YACA,gBACA,cACA,gBACA;AACA,MAAI,CAAC,eAAe,OAAO,UAAU,EAAG,OAAM,YAAY;AAC1D,QAAM,SAAS,2BAA2B,gBAAgB,cAAc,YAAY,OAAO;AAC3F,MAAI;AACJ,MAAI;AACF,YAAS,MAAM,mBAAmB,SAAS,+BAA+B,EAAE,SAAS,OAAO,CAAC;AAAA,EAG/F,SAAS,OAAO;AACd,QAAI,iBAAiB,sBAAsB;AACzC,UAAI,MAAM,SAAS,mBAAmB;AACpC,eAAO,QAAQ;AACf,YAAI,CAAC,eAAe,QAAQ,UAAU,EAAG,OAAM,YAAY;AAAA,MAC7D,OAAO;AACL,eAAO,OAAO;AAAA,MAChB;AAAA,IACF,OAAO;AACL,aAAO,QAAQ;AAAA,IACjB;AACA,UAAM;AAAA,EACR;AACA,SAAO,OAAO;AACd,SAAO;AACT;AAEA,eAAe,wBACb,SACA,SACA,QACA,YACA,gBACA,cACA,gBACA,uBACA;AACA,QAAM,wBAAwB,sBAAsB,QAAQ,UAAU;AACtE,MAAI,CAAC,sBAAuB,OAAM,YAAY;AAC9C,MAAI;AACF,WAAO,MAAM;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,UAAE;AACA,0BAAsB;AAAA,EACxB;AACF;AAEO,SAAS,uCAAuC,OAA+C;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,MAAM,KAAK,EAAE,YAAY;AACzC,QAAM,SAAS,KAAK,OAAO;AAC3B,MAAI,WAAW,EAAG,QAAO;AACzB,MAAI,WAAW,EAAG,QAAO;AACzB,QAAM,YAAY,IAAI,IAAI,WAAW,OAAO,IAAI,EAAE,SAAS,MAAM,GAAG,EAAE;AACtE,QAAM,SAAS,2CAA2C,KAAK,SAAS;AACxE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,OAAO,OAAO,SAAS,OAAO,CAAC,KAAK,IAAI,EAAE;AAChD,QAAM,MAAM,OAAO,SAAS,OAAO,CAAC,KAAK,IAAI,EAAE;AAC/C,SAAO,GAAG,SAAS,CAAC,IAAI,OAAO,GAAI,IAAI,QAAQ,CAAC,IAAI,MAAM,GAAI;AAChE;AAEA,SAAS,sBAAsB,KAAsB,uBAAoD;AACvG,QAAM,gBAAgB,uCAAuC,IAAI,OAAO,aAAa,KAAK;AAC1F,MAAI,CAAC,sBAAsB,IAAI,aAAa,EAAG,QAAO;AACtD,QAAM,YAAY,IAAI,QAAQ,iBAAiB;AAC/C,MAAI,OAAO,cAAc,SAAU,QAAO;AAC1C,QAAM,eAAe,UAAU,MAAM,GAAG;AACxC,MAAI,aAAa,SAAS,KAAK,aAAa,SAAS,GAAI,QAAO;AAChE,QAAM,YAAY,aAAa,IAAI,CAAC,YAAY,uCAAuC,OAAO,CAAC;AAC/F,MAAI,UAAU,KAAK,CAAC,YAAY,YAAY,MAAS,EAAG,QAAO;AAC/D,WAAS,QAAQ,UAAU,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC7D,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,WAAW,CAAC,sBAAsB,IAAI,OAAO,EAAG,QAAO;AAAA,EAC7D;AACA,SAAO,UAAU,CAAC,KAAK;AACzB;AAEA,SAAS,cAAc,KAAsB,uBAAoD;AAC/F,SAAO,WAAW,QAAQ,EACvB,OAAO,sBAAsB,KAAK,qBAAqB,CAAC,EACxD,OAAO,KAAK;AACjB;AAEA,SAAS,YAAY,KAA0C;AAC7D,QAAM,MAAM,IAAI,QAAQ;AACxB,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAM,QAAQ,qBAAqB,KAAK,GAAG;AAC3C,MAAI,CAAC,SAAS,MAAM,CAAC,GAAG,YAAY,MAAM,kBAAmB,QAAO;AACpE,QAAM,SAAS,MAAM,CAAC,KAAK;AAC3B,MAAI,CAAC,0BAA0B,KAAK,MAAM,EAAG,QAAO;AACpD,SAAO;AACT;AAEA,SAAS,oBAAoB,KAA+B;AAC1D,QAAM,gBAAgB,IAAI,QAAQ,gBAAgB;AAClD,QAAM,mBAAmB,IAAI,QAAQ,mBAAmB;AACxD,SAAO,qBAAqB,UAAc,kBAAkB,UAAa,kBAAkB;AAC7F;AAEA,SAAS,YAAY,KAAqB,QAAgB,SAAwB;AAChF,QAAM,OAAO,KAAK,UAAU,OAAO;AACnC,MAAI,aAAa;AACjB,MAAI,UAAU,iBAAiB,mBAAmB;AAClD,MAAI,UAAU,QAAQ,eAAe;AACrC,MAAI,UAAU,gBAAgB,iCAAiC;AAC/D,MAAI,UAAU,kBAAkB,OAAO,OAAO,WAAW,IAAI,CAAC,CAAC;AAC/D,MAAI,IAAI,IAAI;AACd;AAEA,SAAS,iCACP,KACA,KACA,QACA,SACM;AACN,MAAI,kBAAkB;AACtB,MAAI,UAAU,cAAc,OAAO;AACnC,MAAI,KAAK,UAAU,MAAM,IAAI,QAAQ,CAAC;AACtC,cAAY,KAAK,QAAQ,OAAO;AAClC;AAEA,SAAS,yBACP,KACA,KACA,QACA,SACM;AACN,MAAI,oBAAoB,GAAG,GAAG;AAC5B,qCAAiC,KAAK,KAAK,QAAQ,OAAO;AAC1D;AAAA,EACF;AACA,cAAY,KAAK,QAAQ,OAAO;AAClC;AAEA,eAAe,iBAAiB,KAAsB,QAAsC;AAC1F,QAAM,UAAU,MAAM,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC7D,UAAM,SAAmB,CAAC;AAC1B,QAAI,QAAQ;AACZ,QAAI,UAAU;AACd,UAAM,UAAU,MAAM;AACpB,UAAI,IAAI,QAAQ,MAAM;AACtB,UAAI,IAAI,OAAO,KAAK;AACpB,UAAI,IAAI,SAAS,OAAO;AACxB,UAAI,IAAI,WAAW,SAAS;AAC5B,aAAO,oBAAoB,SAAS,aAAa;AAAA,IACnD;AACA,UAAM,OAAO,CAAC,UAAmB;AAC/B,UAAI,QAAS;AACb,gBAAU;AACV,cAAQ;AACR,aAAO,KAAK;AAAA,IACd;AACA,UAAM,aAAa,MACjB,aAAa,OAAO,MAAM,IAAI,OAAO,SAAS,WAAW,kBAAkB;AAC7E,UAAM,SAAS,CAAC,UAA2B;AACzC,YAAM,SAAS,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AACjE,eAAS,OAAO;AAChB,UAAI,QAAQ,MAAO;AACjB,YAAI,MAAM;AACV;AAAA,UACE,IAAI;AAAA,YACF,IAAI,qBAAqB,iBAAiB,mCAAmC,GAAG;AAAA,UAClF;AAAA,QACF;AACA;AAAA,MACF;AACA,aAAO,KAAK,MAAM;AAAA,IACpB;AACA,UAAM,QAAQ,MAAM;AAClB,UAAI,QAAS;AACb,gBAAU;AACV,cAAQ;AACR,cAAQ,OAAO,OAAO,QAAQ,KAAK,CAAC;AAAA,IACtC;AACA,UAAM,UAAU,CAAC,UAAiB,KAAK,OAAO,WAAW,IAAI,UAAU,WAAW,IAAI,KAAK;AAC3F,UAAM,YAAY,MAAM,KAAK,WAAW,CAAC;AACzC,UAAM,gBAAgB,MAAM,KAAK,WAAW,CAAC;AAC7C,QAAI,GAAG,QAAQ,MAAM;AACrB,QAAI,KAAK,OAAO,KAAK;AACrB,QAAI,KAAK,SAAS,OAAO;AACzB,QAAI,KAAK,WAAW,SAAS;AAC7B,WAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,KAAK,CAAC;AAC9D,QAAI,OAAO,QAAS,eAAc;AAAA,EACpC,CAAC;AACD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,QAAQ,SAAS,MAAM,CAAC;AAAA,EAC9C,QAAQ;AACN,UAAM,IAAI,qBAAqB,iBAAiB,mCAAmC,GAAG;AAAA,EACxF;AACA,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,UAAM,IAAI,qBAAqB,iBAAiB,mCAAmC,GAAG;AAAA,EACxF;AACA,QAAM,OAAO;AACb,MAAI,OAAO,KAAK,IAAI,EAAE,WAAW,KAAK,OAAO,KAAK,aAAa,UAAU;AACvE,UAAM,IAAI,qBAAqB,iBAAiB,mCAAmC,GAAG;AAAA,EACxF;AACA,QAAM,WAAW,KAAK,SAAS,KAAK;AACpC,MAAI,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK;AAChD,UAAM,IAAI,qBAAqB,iBAAiB,mCAAmC,GAAG;AAAA,EACxF;AACA,SAAO;AACT;AAEA,SAAS,cAAc,KAAsB,KAA+D;AAC1G,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,MAAM;AAClB,QAAI,CAAC,IAAI,oBAAoB,CAAC,WAAW,OAAO,QAAS,YAAW,MAAM,WAAW,kBAAkB,CAAC;AAAA,EAC1G;AACA,MAAI,KAAK,WAAW,KAAK;AACzB,MAAI,KAAK,SAAS,KAAK;AACvB,SAAO;AAAA,IACL,QAAQ,WAAW;AAAA,IACnB,SAAS,MAAM;AACb,UAAI,IAAI,WAAW,KAAK;AACxB,UAAI,IAAI,SAAS,KAAK;AAAA,IACxB;AAAA,EACF;AACF;AAEA,SAAS,cAAc,KAAiC;AACtD,MAAI;AACF,UAAM,QAAQ,mBAAmB,GAAG;AACpC,WAAO,yBAAyB,KAAK,KAAK,IAAI,MAAM,YAAY,IAAI;AAAA,EACtE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,yCACd,SACA,UAA+C,CAAC,GACT;AACvC,QAAM,aAAa,iBAAiB,QAAQ,OAAO,KAAK,GAAG;AAC3D,QAAM,wBAAwB,IAAI;AAAA,KAC/B,QAAQ,yBAAyB,CAAC,GAChC,IAAI,CAAC,YAAY,uCAAuC,OAAO,CAAC,EAChE,OAAO,CAAC,YAA+B,YAAY,MAAS;AAAA,EACjE;AACA,SAAO,OAAO,KAAK,QAAQ;AACzB,QAAI;AACJ,QAAI;AACF,eAAS,IAAI,IAAI,IAAI,OAAO,KAAK,oBAAoB;AAAA,IACvD,QAAQ;AACN,aAAO;AAAA,IACT;AACA,UAAM,YAAY,4DAA4D,KAAK,OAAO,QAAQ;AAClG,UAAM,WAAW,iEAAiE,KAAK,OAAO,QAAQ;AACtG,UAAM,YAAY,IAAI,WAAW,SAAS;AAC1C,UAAM,gBAAgB,IAAI,WAAW,UAAU;AAC/C,QAAI,CAAC,aAAa,CAAC,cAAe,QAAO;AAEzC,QAAI,UAAU,iBAAiB,mBAAmB;AAClD,QAAI,UAAU,QAAQ,eAAe;AACrC,UAAM,UAAU,eAAe,YAAY,YAAY,CAAC,IAAI,WAAW,CAAC,MAAM,EAAE;AAChF,UAAM,SAAS,YAAY,GAAG;AAC9B,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,+BAAyB,KAAK,KAAK,KAAK;AAAA,QACtC,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAC;AACD,aAAO;AAAA,IACT;AACA,QAAI,aAAa,oBAAoB,GAAG,GAAG;AACzC,uCAAiC,KAAK,KAAK,KAAK;AAAA,QAC9C,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAC;AACD,aAAO;AAAA,IACT;AACA,QAAI,CAAC,WAAW,CAAC,QAAQ;AACvB,+BAAyB,KAAK,KAAK,KAAK;AAAA,QACtC,OAAO;AAAA,QACP,MAAM;AAAA,MACR,CAAC;AACD,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,cAAc,KAAK,GAAG;AACxC,QAAI;AACF,YAAM,SAAS,cAAc,KAAK,qBAAqB;AACvD,UAAI,WAAW;AACb,cAAM,QAAQ,MAAM;AAAA,UAClB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,WAAW;AAAA,UACX,WAAW;AAAA,UACX,WAAW;AAAA,QACb;AACA,oBAAY,KAAK,KAAK,KAAK;AAAA,MAC7B,OAAO;AACL,YAAI,wBAAwB,WAAW,gBAAgB,QAAQ,MAAM;AACrE,YAAI,CAAC,sBAAuB,OAAM,IAAI,kCAAkC,YAAY,CAAC;AACrF,YAAI;AACF,cAAI;AACJ,gBAAM,cAAc,WAAW,wBAAwB,QAAQ,MAAM;AACrE,cAAI,CAAC,YAAa,OAAM,IAAI,kCAAkC,YAAY,CAAC;AAC3E,cAAI;AACF,uBAAW,MAAM,iBAAiB,KAAK,UAAU,MAAM;AACvD,wBAAY,QAAQ;AAAA,UACtB,SAAS,OAAO;AACd,kBAAM,eACJ,iBAAiB,oCAAoC,MAAM,WAAW;AACxE,gBAAI,wBAAwB,wBAAwB,aAAa,SAAS,iBAAiB;AACzF,0BAAY,OAAO;AAAA,YACrB,OAAO;AACL,0BAAY,QAAQ;AAAA,YACtB;AACA,kBAAM;AAAA,UACR;AACA,gBAAM,mBAAmB,WAAW,WAAW,QAAQ,MAAM;AAC7D,cAAI,CAAC,iBAAkB,OAAM,YAAY;AACzC,cAAI;AACF,kBAAM;AAAA,cACJ;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,WAAW;AAAA,cACX,WAAW;AAAA,cACX,WAAW;AAAA,YACb;AACA,kCAAsB;AACtB,oCAAwB;AACxB,kBAAM,SAAS,MAAM;AAAA,cACnB;AAAA,cACA;AAAA,cACA,EAAE,SAAS,QAAQ,SAAS;AAAA,cAC5B,UAAU;AAAA,YACZ;AACA,wBAAY,KAAK,KAAK,MAAM;AAAA,UAC9B,UAAE;AACA,6BAAiB;AAAA,UACnB;AAAA,QACF,UAAE;AACA,kCAAwB;AAAA,QAC1B;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,mCAAmC;AACtD,yCAAiC,KAAK,KAAK,MAAM,SAAS,QAAQ;AAAA,UAChE,OAAO,MAAM,SAAS;AAAA,UACtB,MAAM,MAAM,SAAS;AAAA,QACvB,CAAC;AACD,eAAO;AAAA,MACT;AACA,UAAI,EAAE,iBAAiB,sBAAuB,OAAM;AACpD,kBAAY,KAAK,MAAM,QAAQ,EAAE,OAAO,MAAM,SAAS,MAAM,MAAM,KAAK,CAAC;AAAA,IAC3E,UAAE;AACA,gBAAU,QAAQ;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,iDACX,UACoC;AACvC,SAAO,OAAO,KAAK,KAAK,QAAQ;AAC9B,eAAW,WAAW,UAAU;AAC9B,UAAI,WAAY,MAAM,QAAQ,KAAK,KAAK,GAAG,EAAI,QAAO;AAAA,IACxD;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-QNUNAXBE.js";
|
|
12
12
|
import {
|
|
13
13
|
LocalLlmClient
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-RQFXZYTF.js";
|
|
15
15
|
import {
|
|
16
16
|
completeBackgroundGeneration,
|
|
17
17
|
parseBackgroundGenerationJson
|
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
import {
|
|
20
20
|
FallbackLlmClient,
|
|
21
21
|
gatewayTaskChainOptions
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-MMRTPH3J.js";
|
|
23
23
|
import {
|
|
24
24
|
fallbackLlmRuntimeContextFromConfig
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-QSF5SJAM.js";
|
|
26
26
|
import {
|
|
27
27
|
extractJsonCandidates
|
|
28
28
|
} from "./chunk-YBA52OKG.js";
|
|
@@ -91,12 +91,16 @@ var HourlySummarizer = class {
|
|
|
91
91
|
fallbackLlm;
|
|
92
92
|
modelRegistry;
|
|
93
93
|
transcript;
|
|
94
|
-
|
|
94
|
+
/** Orchestrator-owned stop signal: refuses new summaries and aborts the
|
|
95
|
+
* in-flight local LLM call once teardown begins. */
|
|
96
|
+
shutdownSignal;
|
|
97
|
+
constructor(config, gatewayConfig, modelRegistry, transcript, shutdownSignal) {
|
|
95
98
|
this.config = config;
|
|
96
99
|
this.summariesDir = path.join(config.memoryDir, "summaries", "hourly");
|
|
97
100
|
this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);
|
|
98
101
|
this.transcript = transcript;
|
|
99
|
-
this.
|
|
102
|
+
this.shutdownSignal = shutdownSignal;
|
|
103
|
+
this.localLlm = new LocalLlmClient(config, this.modelRegistry, shutdownSignal);
|
|
100
104
|
this.fallbackLlm = new FallbackLlmClient(gatewayConfig, fallbackLlmRuntimeContextFromConfig(config));
|
|
101
105
|
if (!gatewayConfig?.agents?.defaults?.model?.primary && !resolveLocalLlmCapabilities(config).localLlm && config.modelSource !== "gateway") {
|
|
102
106
|
log.warn("no gateway default AI and local LLM disabled \u2014 hourly summarization disabled");
|
|
@@ -137,6 +141,7 @@ var HourlySummarizer = class {
|
|
|
137
141
|
// Generate summary for a specific hour and session
|
|
138
142
|
async generateSummary(sessionKey, hourStart, entries) {
|
|
139
143
|
if (entries.length === 0) return null;
|
|
144
|
+
this.shutdownSignal?.throwIfAborted();
|
|
140
145
|
const conversation = entries.map((e) => `[${e.role}] ${e.content}`).join("\n\n");
|
|
141
146
|
if (resolvePipelineProcessingCapabilities(this.config).hourlySummariesExtended) {
|
|
142
147
|
const extended = await this.generateExtended(sessionKey, hourStart, conversation, entries);
|
|
@@ -213,6 +218,7 @@ ${conversation}` }
|
|
|
213
218
|
log.info("summary generation: local LLM error, falling back to gateway default AI:", err);
|
|
214
219
|
}
|
|
215
220
|
}
|
|
221
|
+
if (this.shutdownSignal?.aborted) return null;
|
|
216
222
|
log.info("summary generation: falling back to gateway default AI");
|
|
217
223
|
try {
|
|
218
224
|
const messages = [
|
|
@@ -335,7 +341,8 @@ ${conversation}
|
|
|
335
341
|
temperature: 0.2,
|
|
336
342
|
maxTokens: contextSizes.maxOutputTokens,
|
|
337
343
|
operation: "hourly_summary_extended",
|
|
338
|
-
priority: "background"
|
|
344
|
+
priority: "background",
|
|
345
|
+
signal: this.shutdownSignal
|
|
339
346
|
}
|
|
340
347
|
);
|
|
341
348
|
if (response?.content) {
|
|
@@ -357,6 +364,7 @@ ${conversation}
|
|
|
357
364
|
log.info("extended summary: local failed, falling back:", err);
|
|
358
365
|
}
|
|
359
366
|
}
|
|
367
|
+
if (this.shutdownSignal?.aborted) return null;
|
|
360
368
|
try {
|
|
361
369
|
const result = await this.fallbackLlm.parseWithSchema(
|
|
362
370
|
[
|
|
@@ -417,7 +425,8 @@ ${truncatedConversation}`;
|
|
|
417
425
|
temperature: 0.3,
|
|
418
426
|
maxTokens: contextSizes.maxOutputTokens,
|
|
419
427
|
operation: "hourly_summary",
|
|
420
|
-
priority: "background"
|
|
428
|
+
priority: "background",
|
|
429
|
+
signal: this.shutdownSignal
|
|
421
430
|
}
|
|
422
431
|
);
|
|
423
432
|
if (!response?.content) {
|
|
@@ -641,6 +650,7 @@ ${truncatedConversation}`;
|
|
|
641
650
|
}
|
|
642
651
|
// Main entry point for cron job
|
|
643
652
|
async runHourly() {
|
|
653
|
+
this.shutdownSignal?.throwIfAborted();
|
|
644
654
|
log.debug("running hourly summary generation");
|
|
645
655
|
const scan = await this.getActiveSessions();
|
|
646
656
|
const sessions = scan.sessionKeys;
|
|
@@ -798,4 +808,4 @@ export {
|
|
|
798
808
|
summarizeHourlyStatus,
|
|
799
809
|
HourlySummarizer
|
|
800
810
|
};
|
|
801
|
-
//# sourceMappingURL=chunk-
|
|
811
|
+
//# sourceMappingURL=chunk-PC5DRBGD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/summarizer.ts"],"sourcesContent":["import { mkdir, readFile, writeFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { log } from \"./logger.js\";\nimport { LocalLlmClient } from \"./local-llm.js\";\nimport { FallbackLlmClient, fallbackLlmRuntimeContextFromConfig, gatewayTaskChainOptions } from \"./fallback-llm.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { extractJsonCandidates } from \"./json-extract.js\";\nimport {\n completeBackgroundGeneration,\n parseBackgroundGenerationJson,\n} from \"./background-generation.js\";\nimport type { HourlySummary, TranscriptEntry, PluginConfig, GatewayConfig } from \"./types.js\";\nimport type { TranscriptManager } from \"./transcript.js\";\nimport { readSummarySnapshot, upsertSummarySnapshot, writeSummarySnapshot } from \"./summary-snapshot.js\";\nimport { encodeStoragePathSegment, resolveSafeStoragePath } from \"./storage-paths.js\";\nimport { sessionStoragePaths } from \"./session-identity.js\";\nimport { resolveLocalLlmCapabilities } from \"./capabilities.js\";\nimport { resolvePipelineProcessingCapabilities } from \"./capabilities.js\";\n\n// Schema for LLM summary output\nconst HourlySummarySchema = z.object({\n bullets: z.array(z.string().trim().min(1)).min(1).describe(\"3-5 bullet points summarizing the hour's activity\"),\n});\n\ntype HourlySummaryResult = z.infer<typeof HourlySummarySchema>;\n\nconst HourlySummaryExtendedSchema = z.object({\n topics: z.array(z.string()).default([]),\n decisions: z.array(z.string()).default([]),\n actionItems: z.array(z.string()).default([]),\n rejected: z.array(z.string()).default([]),\n});\n\ntype HourlySummaryExtendedResult = z.infer<typeof HourlySummaryExtendedSchema>;\n\ntype HourlySummaryExtendedMeta = {\n userTurns: number;\n assistantTurns: number;\n toolCalls: number;\n toolCounts: Record<string, number>;\n};\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Outcome stats of one `runHourly` pass (issue #2783). The summarizer must\n * not report success on empty work: an empty or stale transcript store is\n * the delegate-mode starvation signature, and callers surface these counts\n * and the staleness flag as a distinct warning instead of a bare ok.\n */\nexport interface HourlySummarizerRunStats {\n sessionsConsidered: number;\n sessionsWithEntries: number;\n summariesWritten: number;\n /** True when the newest transcript entry across the store is older than STALE_STORE_MS. */\n staleStore: boolean;\n /** ISO timestamp of the newest transcript entry seen by the scan, when any exist. */\n newestEntryTimestamp: string | null;\n /** True when the transcript scan itself FAILED (unreadable store) — distinct from an empty store. */\n scanFailed: boolean;\n}\n\n/** A store whose newest entry is older than this is considered stale (starvation signal, issue #2783). */\nconst STALE_STORE_MS = 2 * 60 * 60 * 1000;\n\n/**\n * Interpret one {@link HourlySummarizerRunStats} into the operator-facing\n * message/warning (issue #2783). Every degraded shape — failed scan, empty\n * store, backend-down, stale store — is DISTINCT from success; monitoring\n * alerts on `warning`, never on `ok` (ok only means \"the run completed\").\n */\nexport function summarizeHourlyStatus(stats: HourlySummarizerRunStats): {\n message: string;\n warning?: string;\n} {\n if (stats.scanFailed) {\n return {\n message:\n \"Hourly summarization completed, but the transcript store scan FAILED (unreadable directory or I/O error). Investigate the daemon's memoryDir.\",\n warning: \"transcript store scan failed\",\n };\n }\n if (stats.sessionsConsidered === 0) {\n return {\n message:\n \"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.\",\n warning: \"transcript store is empty\",\n };\n }\n if (stats.sessionsWithEntries > 0 && stats.summariesWritten === 0) {\n return {\n message: `Hourly summarization found ${stats.sessionsWithEntries} session(s) with transcript entries but wrote no summaries — the summarizer backend may be down.`,\n warning: \"sessions with entries produced no summaries\",\n };\n }\n if (stats.sessionsWithEntries === 0 && stats.staleStore) {\n return {\n message: `Hourly summarization completed with no transcript entries for the target hour, and the store looks stale (newest entry ${stats.newestEntryTimestamp ?? \"unknown\"}).`,\n warning: \"no transcript entries for the target hour and no new entries recently\",\n };\n }\n return {\n message: `Hourly summarization completed: ${stats.summariesWritten} summar${stats.summariesWritten === 1 ? \"y\" : \"ies\"} written across ${stats.sessionsWithEntries} session${stats.sessionsWithEntries === 1 ? \"\" : \"s\"} with transcript entries.`,\n };\n}\n\nexport class HourlySummarizer {\n private summariesDir: string;\n private config: PluginConfig;\n private localLlm: LocalLlmClient;\n private fallbackLlm: FallbackLlmClient;\n private modelRegistry: ModelRegistry;\n private transcript?: TranscriptManager;\n /** Orchestrator-owned stop signal: refuses new summaries and aborts the\n * in-flight local LLM call once teardown begins. */\n private readonly shutdownSignal: AbortSignal | undefined;\n\n constructor(\n config: PluginConfig,\n gatewayConfig?: GatewayConfig,\n modelRegistry?: ModelRegistry,\n transcript?: TranscriptManager,\n shutdownSignal?: AbortSignal\n ) {\n this.config = config;\n this.summariesDir = path.join(config.memoryDir, \"summaries\", \"hourly\");\n this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);\n this.transcript = transcript;\n this.shutdownSignal = shutdownSignal;\n\n // Initialize local LLM client with shared model registry\n this.localLlm = new LocalLlmClient(config, this.modelRegistry, shutdownSignal);\n\n // Initialize fallback client with gateway config\n this.fallbackLlm = new FallbackLlmClient(gatewayConfig, fallbackLlmRuntimeContextFromConfig(config));\n\n if (\n !gatewayConfig?.agents?.defaults?.model?.primary &&\n !resolveLocalLlmCapabilities(config).localLlm &&\n config.modelSource !== \"gateway\"\n ) {\n log.warn(\"no gateway default AI and local LLM disabled — hourly summarization disabled\");\n }\n }\n\n private get useGatewayModelSource(): boolean {\n return this.config.modelSource === \"gateway\";\n }\n\n private get shouldUseLocalLlm(): boolean {\n return resolveLocalLlmCapabilities(this.config).localLlm && !this.useGatewayModelSource;\n }\n\n private withGatewayAgent(\n options: import(\"./fallback-llm.js\").FallbackLlmOptions\n ): import(\"./fallback-llm.js\").FallbackLlmOptions {\n if (!this.useGatewayModelSource) return options;\n // Shared resolution (taskModelChain > gatewayAgentId) — gotcha #22. Issue #1365.\n return { ...options, ...gatewayTaskChainOptions(this.config) };\n }\n\n async initialize(): Promise<void> {\n await mkdir(this.summariesDir, { recursive: true });\n log.info(\"hourly summarizer initialized\");\n }\n\n private async summarySessionDir(sessionKey: string): Promise<string> {\n return resolveSafeStoragePath(this.summariesDir, encodeStoragePathSegment(sessionKey, \"session\"));\n }\n\n private async legacySummarySessionDir(sessionKey: string): Promise<string | null> {\n if (sessionKey.includes(\"\\0\")) return null;\n try {\n return await resolveSafeStoragePath(this.summariesDir, sessionKey);\n } catch {\n return null;\n }\n }\n\n private summaryDateString(hour: string): string {\n const dateStr = hour.slice(0, 10);\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(dateStr)) {\n throw new Error(`invalid hourly summary timestamp: ${hour}`);\n }\n return dateStr;\n }\n\n // Generate summary for a specific hour and session\n async generateSummary(\n sessionKey: string,\n hourStart: Date,\n entries: TranscriptEntry[]\n ): Promise<HourlySummary | null> {\n if (entries.length === 0) return null;\n this.shutdownSignal?.throwIfAborted();\n\n // Format entries for the LLM\n const conversation = entries.map((e) => `[${e.role}] ${e.content}`).join(\"\\n\\n\");\n\n if (resolvePipelineProcessingCapabilities(this.config).hourlySummariesExtended) {\n const extended = await this.generateExtended(sessionKey, hourStart, conversation, entries);\n if (!extended) return null;\n const meta: HourlySummaryExtendedMeta = {\n userTurns: entries.filter((e) => e.role === \"user\").length,\n assistantTurns: entries.filter((e) => e.role === \"assistant\").length,\n toolCalls: extended._meta.toolCalls,\n toolCounts: extended._meta.toolCounts,\n };\n // Keep HourlySummary surface stable; encode \"topics\" as bullets for recall injection.\n const base: HourlySummary = {\n hour: hourStart.toISOString(),\n sessionKey,\n bullets: extended.topics.length > 0 ? extended.topics.slice(0, 5) : [\"(summary generated)\"],\n turnCount: entries.length,\n generatedAt: new Date().toISOString(),\n };\n const withExtras = base as any;\n withExtras._extended = extended;\n withExtras._extendedMeta = meta;\n return base;\n }\n\n const hourIso = hourStart.toISOString();\n const startTime = Date.now();\n\n if (this.config.backgroundGeneration) {\n try {\n const text = await completeBackgroundGeneration(this.config, [\n {\n role: \"system\",\n content:\n \"You are a conversation summarization system. Summarize the following conversation transcript into 3-5 concise bullet points.\\n\\nGuidelines:\\n- Focus on what was accomplished, decided, or discussed\\n- Include specific topics, projects, or entities mentioned\\n- Note any significant user requests or agent actions\\n- Keep bullets brief but informative (1-2 sentences each)\\n- Skip trivial greetings or meta-conversation\\n- Use present tense for ongoing work, past for completed items\\n\\nRespond with valid JSON only, matching this schema:\\n{\\\"bullets\\\": [\\\"bullet 1\\\", \\\"bullet 2\\\", \\\"bullet 3\\\"]}\",\n },\n { role: \"user\", content: `Summarize this conversation:\\n\\n${conversation}` },\n ]);\n const parsed = parseBackgroundGenerationJson(text, (value) => HourlySummarySchema.parse(value));\n if (parsed) {\n return {\n hour: hourIso,\n sessionKey,\n bullets: parsed.bullets,\n turnCount: entries.length,\n generatedAt: new Date().toISOString(),\n };\n }\n } catch {\n log.info(\"summary generation: background generation unavailable, continuing\");\n }\n }\n\n // Try local LLM first if enabled\n if (this.shouldUseLocalLlm) {\n try {\n const localResult = await this.generateWithLocalLlm(conversation);\n if (localResult) {\n const durationMs = Date.now() - startTime;\n log.debug(`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms using local LLM`);\n return {\n hour: hourIso,\n sessionKey,\n bullets: localResult.bullets,\n turnCount: entries.length,\n generatedAt: new Date().toISOString(),\n };\n }\n // Local failed, fall back if allowed\n if (!this.config.localLlmFallback) {\n log.warn(\"summary generation: local LLM failed and fallback disabled\");\n return null;\n }\n log.info(\"summary generation: local LLM unavailable, falling back to gateway default AI\");\n } catch (err) {\n if (!this.config.localLlmFallback) {\n log.warn(\"summary generation: local LLM error and fallback disabled:\", err);\n return null;\n }\n log.info(\"summary generation: local LLM error, falling back to gateway default AI:\", err);\n }\n }\n\n if (this.shutdownSignal?.aborted) return null;\n\n // Fall back to gateway's default AI\n log.info(\"summary generation: falling back to gateway default AI\");\n\n try {\n const messages = [\n {\n role: \"system\" as const,\n content: `You are a conversation summarization system. Summarize the following conversation transcript into 3-5 concise bullet points.\n\nGuidelines:\n- Focus on what was accomplished, decided, or discussed\n- Include specific topics, projects, or entities mentioned\n- Note any significant user requests or agent actions\n- Keep bullets brief but informative (1-2 sentences each)\n- Skip trivial greetings or meta-conversation\n- Use present tense for ongoing work, past for completed items\n\nRespond with valid JSON matching this schema:\n{\n \"bullets\": [\"bullet 1\", \"bullet 2\", \"bullet 3\"]\n}`,\n },\n { role: \"user\" as const, content: `Summarize this conversation:\\n\\n${conversation}` },\n ];\n\n const result = await this.fallbackLlm.parseWithSchema(\n messages,\n HourlySummarySchema,\n this.withGatewayAgent({ temperature: 0.3, maxTokens: 8192 })\n );\n\n const durationMs = Date.now() - startTime;\n\n if (result) {\n log.debug(`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms via fallback`);\n return {\n hour: hourIso,\n sessionKey,\n bullets: result.bullets,\n turnCount: entries.length,\n generatedAt: new Date().toISOString(),\n };\n }\n\n log.warn(\"summary generation fallback returned no parsed output\");\n return null;\n } catch (err) {\n log.error(\"summary generation fallback failed\", err);\n return null;\n }\n }\n\n private async generateExtended(\n sessionKey: string,\n hourStart: Date,\n conversation: string,\n entries: TranscriptEntry[]\n ): Promise<(HourlySummaryExtendedResult & { _meta: HourlySummaryExtendedMeta }) | null> {\n const hourIso = hourStart.toISOString();\n const startTime = Date.now();\n\n const hourEnd = new Date(hourStart.getTime() + 60 * 60 * 1000);\n let toolCounts: Record<string, number> = {};\n if (this.config.hourlySummariesIncludeToolStats && this.transcript) {\n const uses = await this.transcript.readToolUse(sessionKey, hourStart, hourEnd);\n for (const u of uses) toolCounts[u.tool] = (toolCounts[u.tool] ?? 0) + 1;\n }\n\n 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`;\n\n const toolStatsLine =\n Object.keys(toolCounts).length > 0\n ? `Tools used (counts): ${Object.entries(toolCounts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([k, v]) => `${k}=${v}`)\n .join(\", \")}\\n\\n`\n : \"\";\n const userTurns = entries.filter((e) => e.role === \"user\").length;\n const assistantTurns = entries.filter((e) => e.role === \"assistant\").length;\n const toolCalls = Object.values(toolCounts).reduce((a, b) => a + b, 0);\n const statsLine = `Stats: userTurns=${userTurns}, assistantTurns=${assistantTurns}, toolCalls=${toolCalls}\\n\\n`;\n\n const user = `Hour: ${hourIso}\\nSession: ${sessionKey}\\n\\n${statsLine}${toolStatsLine}Conversation:\\n${conversation}\\n`;\n\n if (this.config.backgroundGeneration) {\n try {\n const text = await completeBackgroundGeneration(this.config, [\n { role: \"system\", content: sys },\n { role: \"user\", content: user },\n ]);\n const parsed = parseBackgroundGenerationJson(text, (value) => HourlySummaryExtendedSchema.parse(value));\n if (parsed) {\n log.debug(\n `generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (background)`\n );\n return { ...parsed, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };\n }\n } catch {\n log.info(\"extended summary: background generation unavailable, continuing\");\n }\n }\n\n // Try local LLM first if enabled\n if (this.shouldUseLocalLlm) {\n try {\n const contextSizes = this.modelRegistry.calculateContextSizes(\n this.config.localLlmModel,\n this.config.localLlmMaxContext\n );\n const truncated =\n user.length > contextSizes.maxInputChars\n ? user.slice(0, contextSizes.maxInputChars) + \"\\n\\n[truncated]\"\n : user;\n const response = await this.localLlm.chatCompletion(\n [\n { role: \"system\", content: \"Output valid JSON only.\" },\n { role: \"user\", content: sys + \"\\n\\n\" + truncated },\n ],\n {\n temperature: 0.2,\n maxTokens: contextSizes.maxOutputTokens,\n operation: \"hourly_summary_extended\",\n priority: \"background\",\n signal: this.shutdownSignal,\n }\n );\n if (response?.content) {\n const content = response.content.trim();\n for (const candidate of extractJsonCandidates(content)) {\n try {\n const parsed = JSON.parse(candidate);\n const result = HourlySummaryExtendedSchema.parse(parsed);\n log.debug(\n `generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (local)`\n );\n return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };\n } catch {\n // keep trying candidates\n }\n }\n }\n } catch (err) {\n if (!this.config.localLlmFallback) return null;\n log.info(\"extended summary: local failed, falling back:\", err);\n }\n }\n\n if (this.shutdownSignal?.aborted) return null;\n\n try {\n const result = await this.fallbackLlm.parseWithSchema(\n [\n { role: \"system\" as const, content: sys },\n { role: \"user\" as const, content: user },\n ],\n HourlySummaryExtendedSchema,\n this.withGatewayAgent({ temperature: 0.2, maxTokens: 2048 })\n );\n if (result) {\n log.debug(\n `generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (fallback)`\n );\n return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };\n }\n return null;\n } catch (err) {\n log.error(\"extended summary generation failed\", err);\n return null;\n }\n }\n\n /**\n * Generate summary using local LLM with JSON mode.\n * Uses dynamic context sizing based on model capabilities.\n */\n private async generateWithLocalLlm(conversation: string): Promise<HourlySummaryResult | null> {\n // Get dynamic context sizes based on model capabilities\n const contextSizes = this.modelRegistry.calculateContextSizes(\n this.config.localLlmModel,\n this.config.localLlmMaxContext\n );\n log.debug(`Summarizer model context: ${contextSizes.description}`);\n\n const maxConversationChars = contextSizes.maxInputChars;\n const truncatedConversation =\n conversation.length > maxConversationChars\n ? conversation.slice(0, maxConversationChars) + \"\\n\\n[truncated]\"\n : conversation;\n\n const instructions = `You are a conversation summarization system. Summarize the following conversation transcript into 3-5 concise bullet points.\n\nGuidelines:\n- Focus on what was accomplished, decided, or discussed\n- Include specific topics, projects, or entities mentioned\n- Note any significant user requests or agent actions\n- Keep bullets brief but informative (1-2 sentences each)\n- Skip trivial greetings or meta-conversation\n- Use present tense for ongoing work, past for completed items\n\nRespond with valid JSON matching this schema:\n{\n \"bullets\": [\"bullet 1\", \"bullet 2\", \"bullet 3\"]\n}`;\n\n const fullPrompt = `${instructions}\\n\\nConversation to summarize:\\n${truncatedConversation}`;\n\n const response = await this.localLlm.chatCompletion(\n [\n { role: \"system\", content: \"You are a conversation summarization system. Output valid JSON only.\" },\n { role: \"user\", content: fullPrompt },\n ],\n {\n temperature: 0.3,\n maxTokens: contextSizes.maxOutputTokens,\n operation: \"hourly_summary\",\n priority: \"background\",\n signal: this.shutdownSignal,\n }\n );\n\n if (!response?.content) {\n return null;\n }\n\n try {\n // Parse JSON response\n const content = response.content.trim();\n for (const candidate of extractJsonCandidates(content)) {\n try {\n const parsed = JSON.parse(candidate);\n return HourlySummarySchema.parse(parsed);\n } catch {\n // keep trying candidates\n }\n }\n return null;\n } catch (err) {\n log.warn(\"local LLM summary: failed to parse JSON response:\", err);\n return null;\n }\n }\n\n // Save summary to file\n async saveSummary(summary: HourlySummary): Promise<void> {\n const sessionDir = await this.summarySessionDir(summary.sessionKey);\n await mkdir(sessionDir, { recursive: true });\n\n // Format date as YYYY-MM-DD for the filename\n const dateStr = this.summaryDateString(summary.hour);\n const filePath = await resolveSafeStoragePath(sessionDir, `${dateStr}.md`);\n\n // Format hour as HH:00 for display\n const hourStr = summary.hour.slice(11, 13);\n\n // Build markdown content\n const lines: string[] = [];\n\n // Check if file exists to append or create\n let existingContent = \"\";\n try {\n existingContent = await readFile(filePath, \"utf-8\");\n } catch {\n // File doesn't exist yet, will create new\n }\n\n // Check if this hour already exists (idempotent)\n const hourHeader = `## ${hourStr}:00`;\n if (existingContent.includes(hourHeader)) {\n // Replace existing hour section\n const headerMatch = new RegExp(`(^|\\\\n)${escapeRegExp(hourHeader)}\\\\n`).exec(existingContent);\n const sectionStart = headerMatch\n ? headerMatch.index + headerMatch[1].length\n : existingContent.indexOf(hourHeader);\n const nextHeaderPattern = /\\n## \\d{2}:00\\n/g;\n nextHeaderPattern.lastIndex = sectionStart + hourHeader.length;\n const nextHeader = nextHeaderPattern.exec(existingContent);\n const beforeHour = existingContent.slice(0, sectionStart);\n const afterHour = nextHeader ? existingContent.slice(nextHeader.index + 1) : \"\";\n const newSection = this.formatHourSection(summary, hourHeader);\n existingContent = beforeHour + newSection.trimEnd() + (afterHour ? \"\\n\\n\" + afterHour : \"\\n\");\n\n await writeFile(filePath, existingContent, \"utf-8\");\n log.debug(`updated hourly summary for ${summary.sessionKey} at ${hourStr}:00`);\n } else {\n // Append new hour section\n const newSection = this.formatHourSection(summary, hourHeader);\n\n if (existingContent) {\n // Add to existing file\n await writeFile(filePath, existingContent.trimEnd() + \"\\n\\n\" + newSection, \"utf-8\");\n } else {\n // Create new file with header\n const header = `# Hourly Summaries — ${dateStr}\\n\\n*Session: ${summary.sessionKey}*\\n`;\n await writeFile(filePath, header + \"\\n\" + newSection, \"utf-8\");\n }\n log.debug(`saved hourly summary for ${summary.sessionKey} at ${hourStr}:00`);\n }\n try {\n await upsertSummarySnapshot(this.config.memoryDir, summary);\n } catch (error) {\n log.warn(\n `hourly summarizer: failed to update summary snapshot for ${summary.sessionKey} (fail-open): ${String(error)}`\n );\n }\n }\n\n private formatHourSection(summary: HourlySummary, hourHeader: string): string {\n const ext = (summary as any)._extended as\n | (HourlySummaryExtendedResult & { _meta?: HourlySummaryExtendedMeta })\n | undefined;\n const meta = (summary as any)._extendedMeta as HourlySummaryExtendedMeta | undefined;\n const lines: string[] = [hourHeader, \"\"];\n\n if (resolvePipelineProcessingCapabilities(this.config).hourlySummariesExtended && ext) {\n lines.push(\"### Topics Discussed\");\n for (const t of ext.topics) lines.push(`- ${t}`);\n lines.push(\"\");\n lines.push(\"### Decisions Made\");\n for (const d of ext.decisions) lines.push(`- ${d}`);\n lines.push(\"\");\n lines.push(\"### Action Items\");\n for (const a of ext.actionItems) lines.push(`- ${a}`);\n lines.push(\"\");\n lines.push(\"### Rejected Ideas / Reversals\");\n for (const r of ext.rejected) lines.push(`- ${r}`);\n lines.push(\"\");\n if (meta && Object.keys(meta.toolCounts).length > 0) {\n lines.push(\"### Tools Used\");\n const top = Object.entries(meta.toolCounts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 12);\n for (const [name, count] of top) lines.push(`- ${name}: ${count}`);\n lines.push(\"\");\n }\n lines.push(\"### Stats\");\n lines.push(`- Turns: ${summary.turnCount}`);\n if (meta) {\n lines.push(`- User turns: ${meta.userTurns}`);\n lines.push(`- Assistant turns: ${meta.assistantTurns}`);\n lines.push(`- Tool calls: ${meta.toolCalls}`);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n }\n\n for (const bullet of summary.bullets) lines.push(`- ${bullet}`);\n lines.push(` *(${summary.turnCount} turns)*`);\n lines.push(\"\");\n return lines.join(\"\\n\");\n }\n\n // Read recent summaries for recall injection\n async readRecent(sessionKey: string, hours: number): Promise<HourlySummary[]> {\n try {\n const cutoffTime = Date.now() - hours * 60 * 60 * 1000;\n\n const snapshot = await readSummarySnapshot(this.config.memoryDir, sessionKey);\n if (snapshot) {\n return snapshot\n .filter((s) => new Date(s.hour).getTime() >= cutoffTime)\n .sort((a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime());\n }\n\n const summaries: HourlySummary[] = [];\n const encodedDir = await this.summarySessionDir(sessionKey);\n const legacyDir = await this.legacySummarySessionDir(sessionKey);\n const seenDirs = new Set<string>();\n\n for (const sessionDir of [encodedDir, legacyDir]) {\n if (!sessionDir || seenDirs.has(sessionDir)) continue;\n seenDirs.add(sessionDir);\n const parsed = await this.readSummaryDir(sessionDir, sessionKey);\n summaries.push(...parsed);\n }\n\n const byHour = new Map<string, HourlySummary>();\n for (const summary of summaries) {\n if (!byHour.has(summary.hour)) byHour.set(summary.hour, summary);\n }\n\n const sortedSummaries = Array.from(byHour.values()).sort(\n (a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime()\n );\n\n // Filter to recent hours while materializing the full parsed history.\n const recent = sortedSummaries.filter((s) => new Date(s.hour).getTime() >= cutoffTime);\n\n if (sortedSummaries.length > 0) {\n try {\n await writeSummarySnapshot(this.config.memoryDir, sessionKey, sortedSummaries);\n } catch (error) {\n log.warn(\n `hourly summarizer: failed to materialize summary snapshot for ${sessionKey} (fail-open): ${String(error)}`\n );\n }\n }\n\n return recent;\n } catch {\n // Directory doesn't exist or error reading\n return [];\n }\n }\n\n private async readSummaryDir(sessionDir: string, sessionKey: string): Promise<HourlySummary[]> {\n let files: string[];\n try {\n files = await readdir(sessionDir);\n } catch {\n return [];\n }\n\n const summaries: HourlySummary[] = [];\n const mdFiles = files.filter((f) => f.endsWith(\".md\"));\n for (const file of mdFiles) {\n const filePath = await resolveSafeStoragePath(sessionDir, file).catch(() => null);\n if (filePath === null) continue;\n\n try {\n const content = await readFile(filePath, \"utf-8\");\n summaries.push(...this.parseSummaryFile(content, sessionKey, file));\n } catch {\n // Skip unreadable summary files.\n }\n }\n\n return summaries;\n }\n\n private parseSummaryFile(content: string, sessionKey: string, filename: string): HourlySummary[] {\n const summaries: HourlySummary[] = [];\n\n // Extract date from filename (YYYY-MM-DD.md)\n const dateMatch = filename.match(/^(\\d{4}-\\d{2}-\\d{2})\\.md$/);\n if (!dateMatch) return summaries;\n const dateStr = dateMatch[1];\n\n // Split by hour sections\n const hourSections = content.split(/\\n## (\\d{2}):00\\n/);\n\n // First element is the header, skip it\n for (let i = 1; i < hourSections.length; i += 2) {\n const hourStr = hourSections[i];\n const sectionContent = hourSections[i + 1] || \"\";\n\n // Parse bullets\n const bullets: string[] = [];\n const lines = sectionContent.split(\"\\n\");\n let turnCount = 0;\n\n let inTopics = false;\n let sawExtendedTopicsHeader = false;\n for (const line of lines) {\n if (line.startsWith(\"### Topics\")) {\n inTopics = true;\n sawExtendedTopicsHeader = true;\n continue;\n }\n if (line.startsWith(\"### \") && !line.startsWith(\"### Topics\")) {\n inTopics = false;\n }\n const bulletMatch = line.match(/^- (.+)$/);\n if (bulletMatch) {\n // For extended format, only treat topic bullets as recall bullets.\n if (!sawExtendedTopicsHeader || inTopics) bullets.push(bulletMatch[1]);\n }\n const turnMatch = line.match(/\\((\\d+) turns?\\)/);\n if (turnMatch) turnCount = parseInt(turnMatch[1], 10);\n }\n\n if (bullets.length > 0) {\n summaries.push({\n hour: `${dateStr}T${hourStr}:00:00.000Z`,\n sessionKey,\n bullets,\n turnCount,\n generatedAt: \"\", // Not stored in file, not needed for recall\n });\n }\n }\n\n return summaries;\n }\n\n // Format summaries for recall injection\n formatForRecall(summaries: HourlySummary[], maxCount: number): string {\n if (summaries.length === 0) return \"\";\n\n const limited = summaries.slice(0, maxCount);\n const lines: string[] = [`## Recent Activity (last ${limited.length} hours)`];\n\n for (const summary of limited) {\n const hourStr = summary.hour.slice(11, 16); // HH:MM\n for (const bullet of summary.bullets) {\n lines.push(`- ${hourStr}: ${bullet}`);\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n // Main entry point for cron job\n async runHourly(): Promise<HourlySummarizerRunStats> {\n this.shutdownSignal?.throwIfAborted();\n log.debug(\"running hourly summary generation\");\n\n // Get active sessions from transcript. The scan outcome is kept LOCAL to\n // this invocation (review round 2): shared instance state would let two\n // concurrent runHourly calls cross-report each other's timestamps.\n const scan = await this.getActiveSessions();\n const sessions = scan.sessionKeys;\n let sessionsWithEntries = 0;\n let summariesWritten = 0;\n\n for (const sessionKey of sessions) {\n // Calculate the hour we want to summarize (previous hour)\n const now = new Date();\n const hourStart = new Date(now.getTime() - 60 * 60 * 1000);\n hourStart.setMinutes(0, 0, 0);\n const hourEnd = new Date(hourStart.getTime() + 60 * 60 * 1000);\n\n // Get entries for this session in the target hour\n const entries = await this.getTranscriptEntries(sessionKey, hourStart, hourEnd);\n\n if (entries.length === 0) {\n log.debug(`no transcript entries for ${sessionKey} at ${hourStart.toISOString()}`);\n continue;\n }\n sessionsWithEntries += 1;\n\n // Generate and save summary\n const summary = await this.generateSummary(sessionKey, hourStart, entries);\n if (summary) {\n await this.saveSummary(summary);\n summariesWritten += 1;\n log.info(`generated hourly summary for ${sessionKey} (${entries.length} turns)`);\n }\n }\n\n return {\n sessionsConsidered: sessions.length,\n sessionsWithEntries,\n summariesWritten,\n // Staleness signal (issue #2783): newest entry across the whole\n // store, from the same scan getActiveSessions already performs.\n staleStore:\n scan.newestEntryTimestamp !== null &&\n Date.now() - new Date(scan.newestEntryTimestamp).getTime() > STALE_STORE_MS,\n newestEntryTimestamp: scan.newestEntryTimestamp,\n scanFailed: scan.scanFailed,\n };\n }\n\n // Get list of active sessions from the transcript directory, plus the\n // scan bookkeeping runHourly reports: newest entry timestamp (staleness\n // signal) and whether the scan itself FAILED. A failed scan must not be\n // reported as an empty store — those are different incidents (review\n // round 2).\n private async getActiveSessions(): Promise<{\n sessionKeys: string[];\n newestEntryTimestamp: string | null;\n scanFailed: boolean;\n }> {\n const transcriptDir = await resolveSafeStoragePath(this.config.memoryDir, \"transcripts\").catch(() => null);\n if (transcriptDir === null) {\n return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: false };\n }\n\n const sessionKeys = new Set<string>();\n let newestEntryTimestamp: string | null = null;\n let newestEntryTimeMs = Number.NaN;\n let fileReadFailed = false;\n const collect = async (transcriptPath: string): Promise<void> => {\n try {\n const raw = await readFile(transcriptPath, \"utf-8\");\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n if (typeof entry.sessionKey === \"string\" && entry.sessionKey.length > 0) {\n sessionKeys.add(entry.sessionKey);\n }\n // Compare parsed epoch values, never strings: a malformed\n // timestamp in a hand-edited file must not poison the staleness\n // signal with a lexically-maximal garbage value (review).\n if (typeof entry.timestamp === \"string\") {\n const timeMs = new Date(entry.timestamp).getTime();\n if (Number.isFinite(timeMs) && (Number.isNaN(newestEntryTimeMs) || timeMs > newestEntryTimeMs)) {\n newestEntryTimeMs = timeMs;\n newestEntryTimestamp = entry.timestamp;\n }\n }\n } catch {\n // ignore malformed transcript lines\n }\n }\n } catch (err) {\n // ENOENT is a concurrently-deleted file — ignore. Any other read\n // failure (permissions, I/O) means the store is partially UNREADABLE:\n // mark the scan failed so the caller warns instead of reporting an\n // empty store (review round 3).\n if ((err as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n fileReadFailed = true;\n }\n }\n };\n\n try {\n const typeEntries = await readdir(transcriptDir, { withFileTypes: true });\n for (const typeEnt of typeEntries) {\n if (!typeEnt.isDirectory()) continue;\n const typeDir = await resolveSafeStoragePath(transcriptDir, typeEnt.name).catch(() => null);\n if (typeDir === null) continue;\n const idEntries = await readdir(typeDir, { withFileTypes: true });\n for (const idEnt of idEntries) {\n if (!idEnt.isDirectory()) continue;\n const chanDir = await resolveSafeStoragePath(typeDir, idEnt.name).catch(() => null);\n if (chanDir === null) continue;\n const files = (await readdir(chanDir)).filter((f) => f.endsWith(\".jsonl\")).sort();\n for (const file of files) {\n const transcriptPath = await resolveSafeStoragePath(chanDir, file).catch(() => null);\n if (transcriptPath === null) continue;\n await collect(transcriptPath);\n }\n }\n }\n return {\n sessionKeys: Array.from(sessionKeys),\n newestEntryTimestamp,\n scanFailed: fileReadFailed,\n };\n } catch (err) {\n // ENOENT on the root is a never-written store — an EMPTY store, not a\n // scan failure (those are different incidents).\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code === \"ENOENT\") {\n return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: false };\n }\n log.warn(`transcript scan failed: ${err}`);\n return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: true };\n }\n }\n\n // Get transcript entries for a session within a time range\n private async getTranscriptEntries(sessionKey: string, startTime: Date, endTime: Date): Promise<TranscriptEntry[]> {\n // Shared session-identity layer (issue #1496, rule #22). Arbitrary keys\n // route to `session/<hash>`; legacy `agent:<id>:...` keep their paths. The\n // shared helper also supplies the read-back-only candidate dirs (mirrors\n // TranscriptManager) so legacy `other/default` AND old `parts.length >= 3`\n // data stays discoverable here too.\n const paths = sessionStoragePaths(sessionKey);\n\n try {\n const transcriptRoot = path.join(this.config.memoryDir, \"transcripts\");\n const candidateDirs = new Set(\n [paths.dir, paths.alternateDir, paths.legacyDir, ...paths.readbackDirs].filter(\n (dir): dir is string => typeof dir === \"string\" && dir.length > 0\n )\n );\n const entries: TranscriptEntry[] = [];\n // Dedup identical raw rows that a partially-applied migration may have\n // left in both the primary dir and a read-back dir (issue #1496, cursor\n // review). Exact raw JSONL line is the stable identity.\n const seenRawLines = new Set<string>();\n\n // Read all daily transcript files in the directory\n for (const candidateDir of candidateDirs) {\n const transcriptDir = await resolveSafeStoragePath(transcriptRoot, candidateDir).catch(() => null);\n if (transcriptDir === null) continue;\n\n const files = await readdir(transcriptDir).catch(() => []);\n for (const file of files) {\n if (!file.endsWith(\".jsonl\")) continue;\n\n const transcriptPath = await resolveSafeStoragePath(transcriptDir, file).catch(() => null);\n if (transcriptPath === null) continue;\n\n try {\n const content = await readFile(transcriptPath, \"utf-8\");\n const lines = content.trim().split(\"\\n\");\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n const entryTime = new Date(entry.timestamp).getTime();\n\n if (\n entry.sessionKey === sessionKey &&\n entryTime >= startTime.getTime() &&\n entryTime < endTime.getTime() &&\n !seenRawLines.has(line)\n ) {\n seenRawLines.add(line);\n entries.push(entry);\n }\n } catch {\n // Skip malformed lines\n }\n }\n } catch {\n // Skip unreadable files\n }\n }\n }\n\n return entries;\n } catch {\n return [];\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
quoteAnchoredEntitySupport,
|
|
6
6
|
quoteAnchors,
|
|
7
7
|
tokenPool
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MLAMXQAW.js";
|
|
9
9
|
import {
|
|
10
10
|
GROUNDING_AUXILIARY_TOKENS,
|
|
11
11
|
GROUNDING_COPULAR_FORMS,
|
|
@@ -835,4 +835,4 @@ export {
|
|
|
835
835
|
applyExtractionSourceGrounding,
|
|
836
836
|
filterExtractionResultBySource
|
|
837
837
|
};
|
|
838
|
-
//# sourceMappingURL=chunk-
|
|
838
|
+
//# sourceMappingURL=chunk-PT4DZDJA.js.map
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
combineNamespaces,
|
|
17
17
|
stableHash
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-4RAJT5L2.js";
|
|
19
19
|
|
|
20
20
|
// src/namespaces/scope-profiles.ts
|
|
21
21
|
import { createHash } from "crypto";
|
|
@@ -339,4 +339,4 @@ export {
|
|
|
339
339
|
resolveScopeProfilePlan,
|
|
340
340
|
expandScopeProfileReadNamespaces
|
|
341
341
|
};
|
|
342
|
-
//# sourceMappingURL=chunk-
|
|
342
|
+
//# sourceMappingURL=chunk-PZJQ46DH.js.map
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-B2NXOVZN.js";
|
|
5
5
|
import {
|
|
6
6
|
TranscriptManager
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WQ4XKIOX.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveCommitmentLedgerDir,
|
|
10
10
|
validateCommitmentLedgerEntry
|
|
11
11
|
} from "./chunk-ZAJLJ35W.js";
|
|
12
12
|
import {
|
|
13
13
|
parseConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UBEKET2V.js";
|
|
15
15
|
import {
|
|
16
16
|
resolveObjectiveStateStoreDir,
|
|
17
17
|
validateObjectiveStateSnapshot
|
|
@@ -268,4 +268,4 @@ export {
|
|
|
268
268
|
recordResumeBundle,
|
|
269
269
|
getResumeBundleStatus
|
|
270
270
|
};
|
|
271
|
-
//# sourceMappingURL=chunk-
|
|
271
|
+
//# sourceMappingURL=chunk-QDESY76F.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
StorageManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FWRXW7CZ.js";
|
|
4
4
|
import {
|
|
5
5
|
isSafeRouteNamespace
|
|
6
6
|
} from "./chunk-PCXDUHQH.js";
|
|
@@ -416,4 +416,4 @@ export {
|
|
|
416
416
|
resolveNamespaceStorageRoot,
|
|
417
417
|
NamespaceStorageRouter
|
|
418
418
|
};
|
|
419
|
-
//# sourceMappingURL=chunk-
|
|
419
|
+
//# sourceMappingURL=chunk-QHARXWTC.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rebuildMemoryProjection
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-CL4JU3DF.js";
|
|
4
4
|
|
|
5
5
|
// src/convergence-refresh.ts
|
|
6
6
|
async function refreshConvergedNamespaces(namespaces, namespaceSearchRouter, getStorage, searchEnabled) {
|
|
@@ -32,4 +32,4 @@ async function refreshConvergedNamespaces(namespaces, namespaceSearchRouter, get
|
|
|
32
32
|
export {
|
|
33
33
|
refreshConvergedNamespaces
|
|
34
34
|
};
|
|
35
|
-
//# sourceMappingURL=chunk-
|
|
35
|
+
//# sourceMappingURL=chunk-QMFAMOT2.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
expandScopeProfileReadNamespaces,
|
|
3
3
|
resolveScopeProfilePlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PZJQ46DH.js";
|
|
5
5
|
import {
|
|
6
6
|
canReadNamespace,
|
|
7
7
|
canWriteNamespace,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
combineNamespaces,
|
|
23
23
|
lcmReadSessionIdsForNamespaces,
|
|
24
24
|
resolveCodingNamespaceOverlay
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-4RAJT5L2.js";
|
|
26
26
|
|
|
27
27
|
// src/scopes/scope-plan.ts
|
|
28
28
|
import path from "path";
|
|
@@ -204,4 +204,4 @@ export {
|
|
|
204
204
|
resolveWritableNamespaceValue,
|
|
205
205
|
resolveScopedWritableNamespaceValue
|
|
206
206
|
};
|
|
207
|
-
//# sourceMappingURL=chunk-
|
|
207
|
+
//# sourceMappingURL=chunk-QRMG4HK4.js.map
|