@cleocode/cleo 2026.9.7 → 2026.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +3873 -2234
- package/package.json +14 -13
- package/scripts/check-cleo-tarball-size.mjs +105 -0
- package/scripts/copy-studio-dist.mjs +33 -9
- package/studio-dist/client/_app/immutable/chunks/{wI_OOyoh.js → BB7zPpV2.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{D8NsLz6i.js → BOnrCZaR.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{eK8hf4s7.js → BSRBuVG3.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/C6jhAnil.js +1 -0
- package/studio-dist/client/_app/immutable/chunks/C87Q3uxm.js +1 -0
- package/studio-dist/client/_app/immutable/chunks/{DVHIxkgs.js → CLZBEpLY.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{CqF5Lomf.js → CTLGzgdN.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{o1PZ6Kzq.js → CY3heNub.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{RptFUp2P.js → Cge6qiwc.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{BRgWBQlV.js → CnwXLaZJ.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{Bxz2A0ZC.js → DEH43YwF.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/DGftG5oL.js +3 -0
- package/studio-dist/client/_app/immutable/chunks/DX_JOBSO.js +1 -0
- package/studio-dist/client/_app/immutable/chunks/{CEqOYim7.js → DZrdToAH.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/EZwHPWle.js +2 -0
- package/studio-dist/client/_app/immutable/chunks/cWVw9W0E.js +3 -0
- package/studio-dist/client/_app/immutable/chunks/{B9psmq5-.js → rB_71s8h.js} +1 -1
- package/studio-dist/client/_app/immutable/chunks/{JPJd4fEI.js → rUtW7Hx6.js} +1 -1
- package/studio-dist/client/_app/immutable/entry/app.tvu3-wbp.js +2 -0
- package/studio-dist/client/_app/immutable/entry/start.BS-rpdjH.js +1 -0
- package/studio-dist/client/_app/immutable/nodes/{0.CZzEEyVh.js → 0.DMP7swbx.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{1.Bj3Opbua.js → 1.CYZMFpIp.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{10.xe_Mc2Ko.js → 10.3rxHNnSx.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{11.DuKPA7JD.js → 11.B6jWv3Kz.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{12.BoZ_QrUS.js → 12.BrDHeTEq.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{13.DFJiUiv8.js → 13.CE5bd4JV.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{14.eaAlFU4w.js → 14.DgXD2LRx.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{15.BfXgiwMC.js → 15.Cz1KI9Fv.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{16.mEwy9cqh.js → 16.K9wYQPhb.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{17.DP2QtQGn.js → 17.CtUmdfMg.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{18.Bu0054sX.js → 18.mtosd0sL.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{19.UWt6QbCm.js → 19.su55K8y_.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{2.y5jKpHiR.js → 2.mqgFVWFQ.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{20.B1AIHdkP.js → 20.NJuHLxuS.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{21.CpAN71H8.js → 21.BhwhdQCq.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{22.CrYKrN4c.js → 22.BmJEWwER.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{23.pGRaHQjq.js → 23.CAVIJEH-.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{24.BUoUu37z.js → 24.CMuXs5Sy.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/25.DhMBJYAo.js +39 -0
- package/studio-dist/client/_app/immutable/nodes/26.CJ4FA5FS.js +1 -0
- package/studio-dist/client/_app/immutable/nodes/{28.DcmYM7lb.js → 28.D64RBcfs.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{29.lbHbMqNO.js → 29.yfuBeH1x.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{3.Dyir4xXj.js → 3.y115j1d5.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{30.DXj0Wm2A.js → 30.1WUv5bh9.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/4.D6vXYBoQ.js +1 -0
- package/studio-dist/client/_app/immutable/nodes/{5.VWSdP7oc.js → 5.hjw2O-4e.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{6.Dl-XLwOj.js → 6.CAoDfDt6.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{7.CFuC5L-y.js → 7.CLgPSQ8Z.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{8.BCJ0DhOb.js → 8.zuaO1Hik.js} +1 -1
- package/studio-dist/client/_app/immutable/nodes/{9.Bq4SUzL9.js → 9.Cdsd85m2.js} +1 -1
- package/studio-dist/client/_app/version.json +1 -1
- package/studio-dist/server/chunks/0-BQvtFOrC.js +41 -0
- package/studio-dist/server/chunks/1-Bx2_yoiK.js +9 -0
- package/studio-dist/server/chunks/{10-DvOD4ksa.js → 10-CYLc3d5x.js} +3 -3
- package/studio-dist/server/chunks/{11-DMnBZ02H.js → 11-DcIYR5vm.js} +3 -3
- package/studio-dist/server/chunks/{12-CCyRyRWX.js → 12-WE1u104t.js} +3 -3
- package/studio-dist/server/chunks/{13-Dx1c3a_X.js → 13-joBDoxhK.js} +3 -3
- package/studio-dist/server/chunks/{14-Bo-dTCaZ.js → 14-Doj5F4uJ.js} +3 -3
- package/studio-dist/server/chunks/{15-BvUNl3KL.js → 15-nQTeHGD1.js} +3 -3
- package/studio-dist/server/chunks/{16-De6EzPSa.js → 16-CcTN0e8k.js} +5 -4
- package/studio-dist/server/chunks/{17-CZNsiZhi.js → 17-DWiFnzES.js} +10 -93
- package/studio-dist/server/chunks/{18-CbxxjZox.js → 18-Dcc9GnPo.js} +5 -4
- package/studio-dist/server/chunks/{19-DqHyladS.js → 19-BAQHPrMB.js} +3 -3
- package/studio-dist/server/chunks/{2-COvmA-ZA.js → 2-DXSVVaej.js} +10 -93
- package/studio-dist/server/chunks/20-DfQlGHPW.js +57 -0
- package/studio-dist/server/chunks/{21-DXK9ptAC.js → 21-qhGjkW41.js} +4 -31
- package/studio-dist/server/chunks/{22-DD5CLWJC.js → 22-Byy16hFA.js} +3 -3
- package/studio-dist/server/chunks/23-CZpFrGp4.js +97 -0
- package/studio-dist/server/chunks/24-EEysaT9T.js +67 -0
- package/studio-dist/server/chunks/{25-CAg6Xcmn.js → 25-CgiYn70L.js} +15 -96
- package/studio-dist/server/chunks/{26-_nfVTvNi.js → 26-Cfd6BaUb.js} +12 -93
- package/studio-dist/server/chunks/{27-C9edghG4.js → 27-Cqzlh9gZ.js} +3 -2
- package/studio-dist/server/chunks/{28-VemTJGyc.js → 28-DeYe2rpm.js} +8 -62
- package/studio-dist/server/chunks/{29-CXP-m29t.js → 29-6pjLM0Z1.js} +10 -93
- package/studio-dist/server/chunks/{3-B8KhfvHp.js → 3-E_fWDAkq.js} +9 -25
- package/studio-dist/server/chunks/{30-QiM1S4cJ.js → 30-Dw317sSW.js} +10 -93
- package/studio-dist/server/chunks/{31-BwdY9NnB.js → 31-Q4kHbp8j.js} +3 -2
- package/studio-dist/server/chunks/{4-CSaG4HjO.js → 4-C9BMSh4K.js} +4 -3
- package/studio-dist/server/chunks/{5-i5ry4y3C.js → 5-C0CF4WKG.js} +3 -3
- package/studio-dist/server/chunks/{6-DR1GWBMT.js → 6-BWyOJust.js} +3 -3
- package/studio-dist/server/chunks/{7-DSNwn3aQ.js → 7-CK4MK5gy.js} +3 -3
- package/studio-dist/server/chunks/{8-Bj0bx07K.js → 8-CiX7Xk9k.js} +3 -3
- package/studio-dist/server/chunks/{9-B3Tz0mZq.js → 9-Be5118w4.js} +3 -3
- package/studio-dist/server/chunks/{HeroHeader-v4Q9vaGr.js → HeroHeader-BrGN5WPw.js} +2 -2
- package/studio-dist/server/chunks/{Sparkline-BJ-GuhRd.js → Sparkline-DU_NVxz9.js} +2 -2
- package/studio-dist/server/chunks/{StatBlock-DHJMmOCx.js → StatBlock-jNsxycS1.js} +2 -2
- package/studio-dist/server/chunks/{Tabs-DzG6Bn9a.js → Tabs-DQKDflnT.js} +2 -2
- package/studio-dist/server/chunks/_dispatch-DTWViLGL.js +145 -0
- package/studio-dist/server/chunks/{_layout.svelte-BEIGQcIv.js → _layout.svelte-CL6GfET2.js} +7 -9
- package/studio-dist/server/chunks/{_page.svelte-al08ovKm.js → _page.svelte-6iMiGR11.js} +5 -5
- package/studio-dist/server/chunks/{_page.svelte-Byz2djto.js → _page.svelte-B-YXGvAW.js} +5 -5
- package/studio-dist/server/chunks/{_page.svelte-tYN7_LXI.js → _page.svelte-B5E6RqVb.js} +9 -11
- package/studio-dist/server/chunks/{_page.svelte-UYiF7YBK.js → _page.svelte-BCRyjlk2.js} +5 -5
- package/studio-dist/server/chunks/{_page.svelte-CCoTp89s.js → _page.svelte-BoYafqft.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-nzffIbBP.js → _page.svelte-C7Wm6_HB.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-C_VSL8NW.js → _page.svelte-Cgqt7ucn.js} +13 -71
- package/studio-dist/server/chunks/{_page.svelte-CophUar3.js → _page.svelte-CqI6hqMm.js} +5 -5
- package/studio-dist/server/chunks/{_page.svelte-BgwL2Gyu.js → _page.svelte-CvQ2rZZ1.js} +11 -13
- package/studio-dist/server/chunks/{_page.svelte-l4Z_xjl9.js → _page.svelte-CvTyJEyS.js} +9 -11
- package/studio-dist/server/chunks/{_page.svelte-DOWw416I.js → _page.svelte-CvzAttO9.js} +11 -13
- package/studio-dist/server/chunks/{_page.svelte-DYNorA0S.js → _page.svelte-Cx9Ptecp.js} +10 -67
- package/studio-dist/server/chunks/{_page.svelte-Wfx7ww_h.js → _page.svelte-Cx9dPjsT.js} +11 -13
- package/studio-dist/server/chunks/{_page.svelte-2cgtvHwW.js → _page.svelte-DGN5j-At.js} +13 -71
- package/studio-dist/server/chunks/{_page.svelte-BVVTrzTL.js → _page.svelte-DaheDIRs.js} +5 -5
- package/studio-dist/server/chunks/{_page.svelte-M5D2QnMS.js → _page.svelte-Dm8y5a8S.js} +10 -67
- package/studio-dist/server/chunks/{_page.svelte-B_pq-Z98.js → _page.svelte-DqXxyNsF.js} +7 -7
- package/studio-dist/server/chunks/{_page.svelte-C3aIui4o.js → _page.svelte-DqsbnAhk.js} +4 -4
- package/studio-dist/server/chunks/{_page.svelte-ksTJUXce.js → _page.svelte-Dt0_c1T-.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-bGhsrIjS.js → _page.svelte-Dv6iwhu7.js} +3 -3
- package/studio-dist/server/chunks/{_page.svelte-BXyoMME1.js → _page.svelte-GPiHej3P.js} +5 -5
- package/studio-dist/server/chunks/{_page.svelte-CYDjW1R0.js → _page.svelte-LuRm8XxE.js} +5 -5
- package/studio-dist/server/chunks/{_page.svelte-Clbkk1gm.js → _page.svelte-Z7nL9SC-.js} +8 -9
- package/studio-dist/server/chunks/{_page.svelte-DUWbZjC7.js → _page.svelte-_kntHS6v.js} +4 -4
- package/studio-dist/server/chunks/{_page.svelte-BIlhmugm.js → _page.svelte-eiomv6Pa.js} +11 -13
- package/studio-dist/server/chunks/{_page.svelte-9OQphlnm.js → _page.svelte-jXJbd8Mx.js} +14 -69
- package/studio-dist/server/chunks/{_page.svelte-CHzXuw2Q.js → _page.svelte-me5SUosG.js} +3 -3
- package/studio-dist/server/chunks/{_server.ts-DSzRdt1U.js → _server.ts--2m_U4SL.js} +11 -94
- package/studio-dist/server/chunks/{_server.ts-ujoDR2_g.js → _server.ts--sGLmBsz.js} +10 -92
- package/studio-dist/server/chunks/{_server.ts-k2fApwOp.js → _server.ts-0ukyuE0I.js} +5 -60
- package/studio-dist/server/chunks/_server.ts-1eW2mTeh.js +40 -0
- package/studio-dist/server/chunks/{_server.ts-Bfr4u3EP.js → _server.ts-3LzqLzt0.js} +10 -92
- package/studio-dist/server/chunks/_server.ts-40h9Y46Y.js +122 -0
- package/studio-dist/server/chunks/_server.ts-5euivmMj.js +38 -0
- package/studio-dist/server/chunks/{_server.ts-CShsBkeE.js → _server.ts-B0uoay97.js} +7 -23
- package/studio-dist/server/chunks/{_server.ts-hL92cV7Z.js → _server.ts-B5vYKkI6.js} +9 -63
- package/studio-dist/server/chunks/{_server.ts-_RJXtmfi.js → _server.ts-B8dTbPHd.js} +8 -23
- package/studio-dist/server/chunks/{_server.ts-C3Jo-ju8.js → _server.ts-BA8Xdegq.js} +10 -92
- package/studio-dist/server/chunks/_server.ts-BBClE0n9.js +54 -0
- package/studio-dist/server/chunks/{_server.ts-ZS1_yMwR.js → _server.ts-BDwMoyZ_.js} +6 -32
- package/studio-dist/server/chunks/{_server.ts-sv4pA808.js → _server.ts-BE-Uhx4N.js} +5 -46
- package/studio-dist/server/chunks/{_server.ts-DV6pzF-M.js → _server.ts-BSHADOUJ.js} +4 -3
- package/studio-dist/server/chunks/_server.ts-BcsqAqXt.js +67 -0
- package/studio-dist/server/chunks/_server.ts-Bl9tMqwZ.js +159 -0
- package/studio-dist/server/chunks/_server.ts-BlzDnRI0.js +51 -0
- package/studio-dist/server/chunks/{_server.ts-DnE0f-iC.js → _server.ts-BtuemCsf.js} +4 -3
- package/studio-dist/server/chunks/{_server.ts-BPcErnS0.js → _server.ts-C2nYqbd9.js} +10 -92
- package/studio-dist/server/chunks/{_server.ts-4p6cp9ke.js → _server.ts-C6IDM_3I.js} +10 -92
- package/studio-dist/server/chunks/_server.ts-C8Z32vuL.js +45 -0
- package/studio-dist/server/chunks/_server.ts-CBXyadsy.js +26 -0
- package/studio-dist/server/chunks/{_server.ts-Do9RIPRo.js → _server.ts-CE6h2ATE.js} +5 -32
- package/studio-dist/server/chunks/_server.ts-CH06JVqZ.js +65 -0
- package/studio-dist/server/chunks/_server.ts-CNqcws-M.js +29 -0
- package/studio-dist/server/chunks/{_server.ts-CJA1djzJ.js → _server.ts-CPf8necd.js} +8 -92
- package/studio-dist/server/chunks/{_server.ts-uUx7uT2Y.js → _server.ts-CYv5YuHd.js} +6 -43
- package/studio-dist/server/chunks/{_server.ts-B2E7fxo9.js → _server.ts-CZ5GZRWX.js} +6 -91
- package/studio-dist/server/chunks/{_server.ts-DSAv66wD.js → _server.ts-CbThsyhY.js} +4 -3
- package/studio-dist/server/chunks/{_server.ts-DgbY5EB3.js → _server.ts-CeQolQOK.js} +10 -92
- package/studio-dist/server/chunks/_server.ts-ChoGyX5C.js +61 -0
- package/studio-dist/server/chunks/_server.ts-CjJYkLJH.js +61 -0
- package/studio-dist/server/chunks/{_server.ts-lPlBUIJX.js → _server.ts-CtjArzxf.js} +5 -60
- package/studio-dist/server/chunks/{_server.ts-Cq60m8Pw.js → _server.ts-D3QWZwt_.js} +4 -3
- package/studio-dist/server/chunks/{_server.ts-CkoJ2HCW.js → _server.ts-D6wP5bCh.js} +10 -92
- package/studio-dist/server/chunks/{_server.ts-DwTRjS4y.js → _server.ts-D7JwQTun.js} +10 -93
- package/studio-dist/server/chunks/_server.ts-DKFJdXPK.js +97 -0
- package/studio-dist/server/chunks/_server.ts-DNAPGKEF.js +55 -0
- package/studio-dist/server/chunks/_server.ts-DQiTiY3E.js +78 -0
- package/studio-dist/server/chunks/{_server.ts-BT0Uq2yq.js → _server.ts-DUyeSXbV.js} +10 -92
- package/studio-dist/server/chunks/{_server.ts-DRVz9D-J.js → _server.ts-DY7BwZCv.js} +9 -24
- package/studio-dist/server/chunks/{_server.ts-Cz0zgaUV.js → _server.ts-D_E276ms.js} +3 -2
- package/studio-dist/server/chunks/{_server.ts-B5g3eScF.js → _server.ts-DgtmTAp5.js} +5 -60
- package/studio-dist/server/chunks/{_server.ts-CboRJY0Q.js → _server.ts-DhTKaw7h.js} +10 -63
- package/studio-dist/server/chunks/_server.ts-DqKBSCPT.js +31 -0
- package/studio-dist/server/chunks/{_server.ts-CpmMp5D8.js → _server.ts-DyXBNnRD.js} +4 -3
- package/studio-dist/server/chunks/_server.ts-DzjUpduu.js +25 -0
- package/studio-dist/server/chunks/{_server.ts-CGiAXy5i.js → _server.ts-Dznqw6Dg.js} +8 -23
- package/studio-dist/server/chunks/{_server.ts-tKMjUFUP.js → _server.ts-EVwS7UXb.js} +4 -3
- package/studio-dist/server/chunks/_server.ts-J17j25VG.js +62 -0
- package/studio-dist/server/chunks/{_server.ts-BdN4AJ6o.js → _server.ts-VQchZxXq.js} +10 -91
- package/studio-dist/server/chunks/{_server.ts-C4BcDGqS.js → _server.ts-XLV5SvjH.js} +7 -63
- package/studio-dist/server/chunks/_server.ts-jZgqFIJz.js +45 -0
- package/studio-dist/server/chunks/{_server.ts-Bw7A4zgb.js → _server.ts-lyiGGv7w.js} +5 -3
- package/studio-dist/server/chunks/{brain-CXR7ZT7S.js → brain-xt_NeshR.js} +2 -2
- package/studio-dist/server/chunks/cleo-home-_XIqkZaL.js +109 -0
- package/studio-dist/server/chunks/{cli-action-DQcaqcfn.js → cli-action-VJPEn1pY.js} +2 -2
- package/studio-dist/server/chunks/{client-CgX38JBu.js → client-D71MZ7Vi.js} +5 -6
- package/studio-dist/server/chunks/cluster-label-layer-CysRMvhi.js +6721 -0
- package/studio-dist/server/chunks/connections-CWLPjwBP.js +15 -0
- package/studio-dist/server/chunks/{connections2-mi7mZqJM.js → connections2-DHVs5ytW.js} +32 -19
- package/studio-dist/server/chunks/{dev-BNpEUZI3.js → dev-Br5zieNA.js} +2 -2
- package/studio-dist/server/chunks/dist-BzgWhfUR.js +18748 -0
- package/studio-dist/server/chunks/{error.svelte-CplNulnS.js → error.svelte-BIToUowC.js} +6 -8
- package/studio-dist/server/chunks/{explorer-loader-BN_mkt3_.js → explorer-loader-B_uCSs9_.js} +2 -2
- package/studio-dist/server/chunks/exports-Dg-gdPPq.js +124 -0
- package/studio-dist/server/chunks/{hooks.server-DBsyphiX.js → hooks.server-CWBRp8NI.js} +10 -93
- package/studio-dist/server/chunks/{http-CRTZe306.js → http-DPU3HHl2.js} +3 -4
- package/studio-dist/server/chunks/{index-server-DocJvixA.js → index-server-BgfA6C0S.js} +17 -4
- package/studio-dist/server/chunks/{internal-D6eWgsHJ.js → internal-DPnIJYMs.js} +56 -92
- package/studio-dist/server/chunks/{memory2-Cgc_4D5q.js → memory-BZHnDZzu.js} +4 -4
- package/studio-dist/server/chunks/{nexus-adapter-9EL_VlGI.js → nexus-adapter-D1ryYG1Z.js} +5 -5
- package/studio-dist/server/chunks/{no-face-up-DcejJLy-.js → no-face-up-B_3h6Hgs.js} +2 -2
- package/studio-dist/server/chunks/project-context-BAXQmgch.js +188 -0
- package/studio-dist/server/chunks/{src-BUqGet2c.js → src-D2rW9bIF.js} +422 -5
- package/studio-dist/server/chunks/{stores-5DmdjPCH.js → stores-BZdYTyl7.js} +3 -3
- package/studio-dist/server/chunks/{tasks2-Bf9VHrv-.js → tasks-sWuEmiGW.js} +2349 -9
- package/studio-dist/server/chunks/{ui-DR8zOSpC.js → ui-CkQ-pCs3.js} +2 -2
- package/studio-dist/server/chunks/utils-g564cUMV.js +151 -0
- package/studio-dist/server/index.js +5 -16
- package/studio-dist/server/manifest.js +88 -88
- package/dist/cli/index.js.map +0 -6
- package/studio-dist/client/_app/immutable/assets/parse-worker.CSEr67Qi.js +0 -1127
- package/studio-dist/client/_app/immutable/chunks/2mEksghu2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/3KebaI-z.js +0 -53
- package/studio-dist/client/_app/immutable/chunks/3y2yNYEk2.js +0 -3
- package/studio-dist/client/_app/immutable/chunks/7UXYlaI1.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/83VLmCvk.js +0 -4
- package/studio-dist/client/_app/immutable/chunks/84Rhmi6r.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/9CV9TXTg2.js +0 -92
- package/studio-dist/client/_app/immutable/chunks/9LFtcz24.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/9bLMgKwu2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/9kKqohVR2.js +0 -37
- package/studio-dist/client/_app/immutable/chunks/B-Ye28EY.js +0 -7
- package/studio-dist/client/_app/immutable/chunks/B-jnUl7o.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B0ORuy8x2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B0xCM1wN2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B0zCN4sX.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B1wt-iGW.js +0 -7
- package/studio-dist/client/_app/immutable/chunks/B2F3KUIU.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B2_6RrlL2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B2qKEYxA2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B2u2rNyI2.js +0 -8
- package/studio-dist/client/_app/immutable/chunks/B3_X3Lhd2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B3sNtbqf.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/B4NQP1Ax2.js +0 -6
- package/studio-dist/client/_app/immutable/chunks/BAtZg5v5.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BB6WKLm82.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BBX8UDtn.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BBs1U1iU.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BEli_4Jp2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BEt2wIUt.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BEyM8qSW2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BFZA3Dsk2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BGdPweG1.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BGiusSqE.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BGmpyfzD.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BH5rhSIR.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BHciFt922.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BHnFwTQY.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BIvye3XP2.js +0 -59
- package/studio-dist/client/_app/immutable/chunks/BJ8mcpQA2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BK17qSHw.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BLkgUtyb.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BMUko3r62.js +0 -5
- package/studio-dist/client/_app/immutable/chunks/BMwzdEaa.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BQZx6brg.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BUPJTTTd.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BVNGAeZe2.js +0 -146
- package/studio-dist/client/_app/immutable/chunks/BWfLryGm.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BXIfeogw.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BXTfFyUU.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BYJC6_MM.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BZV1ZJzH.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BZu9rehd.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Bbzm48C52.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BfGnlwjH.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Bfjb9LPp.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BieFfu-R.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Bmv63uXe2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BtBW1A0u.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/BxISGQCl2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/ByNR_KvT.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BzjhD6Hr2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/BzpWnq0c2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/C-yJVcyI2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/C0cQ-8kS2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/C1vWmhYe.js +0 -48
- package/studio-dist/client/_app/immutable/chunks/C1w6bBje.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/C243sn7r.js +0 -4
- package/studio-dist/client/_app/immutable/chunks/C2oZaDvt.js +0 -67
- package/studio-dist/client/_app/immutable/chunks/C3OziSQx.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/C3hFPbMK.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/C4P9oFvU2.js +0 -6
- package/studio-dist/client/_app/immutable/chunks/C5Nlanei.js +0 -8
- package/studio-dist/client/_app/immutable/chunks/C6KBAXPl.js +0 -15
- package/studio-dist/client/_app/immutable/chunks/C8MZnWta.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CAoan3K12.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CBpcINYH.js +0 -29
- package/studio-dist/client/_app/immutable/chunks/CE7phgWq.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CFb4Co_K.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/CGWoRK3t2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CH3t4xo1.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CHJgk6g-.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CHgPjuDQ.js +0 -17
- package/studio-dist/client/_app/immutable/chunks/CHkCZrnr.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CI_91WUN.js +0 -4
- package/studio-dist/client/_app/immutable/chunks/CJ7-hP0H.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CKIrNnkY2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CKoQ7Ko5.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CM8O4zqs.js +0 -56
- package/studio-dist/client/_app/immutable/chunks/CMz3AVRO.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CNToUR3P.js +0 -13
- package/studio-dist/client/_app/immutable/chunks/CNuQG1yl2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CQLIZtxj.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/CQYVNgM0.js +0 -20
- package/studio-dist/client/_app/immutable/chunks/CQeVOmFO2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CSPHHq09.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CTJEdbIn.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CTTT3wYw.js +0 -35
- package/studio-dist/client/_app/immutable/chunks/CV4ck7fz.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/CXQrVnHf.js +0 -11
- package/studio-dist/client/_app/immutable/chunks/CXTCtOUQ.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/C_CsU7Qq.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/C_IZx3682.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/CbTnu2Po2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Cba8RZ1a2.js +0 -8
- package/studio-dist/client/_app/immutable/chunks/Cc8xxDr5.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CdPxoldu.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CdqDTozW.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CdsmcCfC.js +0 -25
- package/studio-dist/client/_app/immutable/chunks/CeYPAoY9.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Cf4kGS9y.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CfWEqXtJ2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Cg7Wj2b9.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/CgTpKZfi2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Chpy9ca7.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/CiLKuLrQ.js +0 -4
- package/studio-dist/client/_app/immutable/chunks/CjNDJjwu.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Cjde0ZKr2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Cjgnade02.js +0 -3
- package/studio-dist/client/_app/immutable/chunks/Ckp90om52.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/ClAPVhCD.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/ClT89UdO.js +0 -11
- package/studio-dist/client/_app/immutable/chunks/CnJf5tML.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CpF4Rrcc2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CqCka5yX2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CqtqZrOl.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CrJdywQt.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Cs0zC2l2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CsMn5fBs.js +0 -141
- package/studio-dist/client/_app/immutable/chunks/CsvKLHQQ2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/Ctaresvj.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Ctetf8vc2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/Cv7yW6MG.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CxRIz-Zd.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/CxbvtjIH.js +0 -3
- package/studio-dist/client/_app/immutable/chunks/CxfeoXkZ.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/CySLscL2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/D0PKQAbM.js +0 -87
- package/studio-dist/client/_app/immutable/chunks/D0WQsLTu.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D1LBVx6r2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D1NlFXu9.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D1QfC4hu2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D1yrHAn72.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D2pa4reh.js +0 -7
- package/studio-dist/client/_app/immutable/chunks/D3QsWcIw2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/D4OkQuPl2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D6UDnATk2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D7w7HllH.js +0 -38
- package/studio-dist/client/_app/immutable/chunks/D93KpglN.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D99fQj2G2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DB5ifLM-.js +0 -3
- package/studio-dist/client/_app/immutable/chunks/DBhP8ifO2.js +0 -15
- package/studio-dist/client/_app/immutable/chunks/DF_4OWhj.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/DFpNK1vs2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DGRYMk-W.js +0 -142
- package/studio-dist/client/_app/immutable/chunks/DH3CcQwq.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DHQfJeLU.js +0 -4
- package/studio-dist/client/_app/immutable/chunks/DL89yEDy2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DLRku_0p2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/DMZkjPYT2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DNP72foU.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DO2GztVm.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DOVNXmCK2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DOqzs8kl2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DQnR63hh2.js +0 -7
- package/studio-dist/client/_app/immutable/chunks/DTxtWPkw.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DVDgCC9A2.js +0 -20
- package/studio-dist/client/_app/immutable/chunks/DVVCJYjz.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DWRhYUMj2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DWavBJBI.js +0 -4
- package/studio-dist/client/_app/immutable/chunks/DXDSWRw-.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DXoHaH4a.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/DXpCX2Hi.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DYP3EJMY.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DYQphR_V.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DYUlIivP.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DYo2ye8X2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DYxFu8yV.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DZ66sRb6.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/D_XTiylm2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DaRv9jn22.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DaXb9i_E.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Dccf4VP2.js +0 -24
- package/studio-dist/client/_app/immutable/chunks/DdODs-Sb.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DdekYWer.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/DeHaovsF.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DeRRkRO52.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DeWI5qCn.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DfivR-Md.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DgmxpSo7.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DhPLWrun2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DhhrVdfi.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/Djr2dbcc2.js +0 -37
- package/studio-dist/client/_app/immutable/chunks/DjuRo5vv.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Djz4EDzO.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DkRfaw-K2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DksB5g4W2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Dmqenb5z2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DnbToVyf.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/DpGZwlmj.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Dq0lE5C32.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Dq54XqHT2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DqK84mbb.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DqjFtSJD.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/DrKWWDpL.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DsQIgu-4.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DsqdgJHS2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DtNkZUkq.js +0 -17
- package/studio-dist/client/_app/immutable/chunks/DutIls4V2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DvxYFW4C.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Dwp-76GQ.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/DxSZd548.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DxiUMhk0.js +0 -5
- package/studio-dist/client/_app/immutable/chunks/DxslLswf.js +0 -23
- package/studio-dist/client/_app/immutable/chunks/Dy7EjGgb2.js +0 -9
- package/studio-dist/client/_app/immutable/chunks/DyGQ_VXC.js +0 -3
- package/studio-dist/client/_app/immutable/chunks/DySe3kTV2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DyzE2Uxw.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/DzhuJaxE2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/FmMHyrh6.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Gxs0J274.js +0 -5
- package/studio-dist/client/_app/immutable/chunks/HwtzDYxN.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/ITRz_Q7H2.js +0 -15
- package/studio-dist/client/_app/immutable/chunks/KDNP98XY2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/LmVjFhpk2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/MiAejGV_.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Ml4JR6Jz2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/NU5S3nNs2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/Oh5zPjv3.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/QZkvJ9vi.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Rbn8UpBm.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/SPX3gYwn2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/TX-23QW3.js +0 -3
- package/studio-dist/client/_app/immutable/chunks/UyeQuL132.js +0 -12
- package/studio-dist/client/_app/immutable/chunks/VQszoXcV.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/VtZsEMxD.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/W2IeK61p2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Wadww7ZG.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/WgfA1zWk2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/WxIgAS1f.js +0 -21
- package/studio-dist/client/_app/immutable/chunks/XrsBoOj9.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/Y3PX4poR.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/YxfwqiF32.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/Z7uO1YaO.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/_4ykQk_8.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/_kRcZFVn.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/aQNM7eVA2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/bHKz_Fb2.js +0 -45
- package/studio-dist/client/_app/immutable/chunks/bJRyRGSZ.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/dlzF6lnR.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/fjRbpfEr2.js +0 -26
- package/studio-dist/client/_app/immutable/chunks/imLk4if5.js +0 -3
- package/studio-dist/client/_app/immutable/chunks/lgRG0R-32.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/mFhCjxQJ2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/mgnH6qYg.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/n6M_5LoW.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/nLIOiDZp2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/nab7WB3u2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/orUmAKoW2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/p-fLQDfY2.js +0 -63
- package/studio-dist/client/_app/immutable/chunks/s0-WkOGk2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/sPuXfbUF.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/t4h0vrqR2.js +0 -2
- package/studio-dist/client/_app/immutable/chunks/uE83FKL-.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/uzhXlm0g2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/vTrEsGlD2.js +0 -1
- package/studio-dist/client/_app/immutable/chunks/xJgCk3dx2.js +0 -28
- package/studio-dist/client/_app/immutable/chunks/z0Mt579s2.js +0 -13
- package/studio-dist/client/_app/immutable/entry/app.BoQ7cgT2.js +0 -2
- package/studio-dist/client/_app/immutable/entry/start.Cg1v8DU4.js +0 -1
- package/studio-dist/client/_app/immutable/nodes/25.ddZ1_EFk.js +0 -1
- package/studio-dist/client/_app/immutable/nodes/26.6OcmQbLV.js +0 -1
- package/studio-dist/client/_app/immutable/nodes/4.CCjOEwVU.js +0 -1
- package/studio-dist/server/chunks/0-CvsKDxQ6.js +0 -126
- package/studio-dist/server/chunks/1-ck_x2Hf0.js +0 -9
- package/studio-dist/server/chunks/20-DVU22np7.js +0 -142
- package/studio-dist/server/chunks/23-D_tUnnoc.js +0 -181
- package/studio-dist/server/chunks/24-CVlymvLF.js +0 -151
- package/studio-dist/server/chunks/AwsRestJsonProtocol-BZuoNBmL.js +0 -416
- package/studio-dist/server/chunks/UnionSerde-BflIkhKj.js +0 -2653
- package/studio-dist/server/chunks/_dispatch-ncuRztUQ.js +0 -5597
- package/studio-dist/server/chunks/_server.ts-4NyKAneX.js +0 -116
- package/studio-dist/server/chunks/_server.ts-7hGdxdEI.js +0 -136
- package/studio-dist/server/chunks/_server.ts-B6b3b-yA.js +0 -131
- package/studio-dist/server/chunks/_server.ts-BOgGqaZp.js +0 -144
- package/studio-dist/server/chunks/_server.ts-BV1HiKZ0.js +0 -120
- package/studio-dist/server/chunks/_server.ts-BWp3g6Cr.js +0 -110
- package/studio-dist/server/chunks/_server.ts-C5NF-UgC.js +0 -122
- package/studio-dist/server/chunks/_server.ts-CDMurH5m.js +0 -2301
- package/studio-dist/server/chunks/_server.ts-COJHCgbq.js +0 -127
- package/studio-dist/server/chunks/_server.ts-CUl-Utkt.js +0 -148
- package/studio-dist/server/chunks/_server.ts-D0GAFJRb.js +0 -156
- package/studio-dist/server/chunks/_server.ts-DA6p3pmi.js +0 -117
- package/studio-dist/server/chunks/_server.ts-DThYFaZj.js +0 -160
- package/studio-dist/server/chunks/_server.ts-D_3Pm0gr.js +0 -179
- package/studio-dist/server/chunks/_server.ts-DcHxdMsm.js +0 -144
- package/studio-dist/server/chunks/_server.ts-Dlfadh2I.js +0 -144
- package/studio-dist/server/chunks/_server.ts-JallJnps.js +0 -240
- package/studio-dist/server/chunks/_server.ts-NEFTbJpM.js +0 -142
- package/studio-dist/server/chunks/_server.ts-d-2NvRwX.js +0 -122
- package/studio-dist/server/chunks/_server.ts-rUWMLkIw.js +0 -146
- package/studio-dist/server/chunks/abort-events-CDRAJSqb.js +0 -30
- package/studio-dist/server/chunks/adapters-BkMgPNUM.js +0 -359
- package/studio-dist/server/chunks/adapters2-CQ3PzoaK.js +0 -28
- package/studio-dist/server/chunks/api-mode2-3W-I1-XO.js +0 -36
- package/studio-dist/server/chunks/api2-CmNQzb0b.js +0 -96
- package/studio-dist/server/chunks/attention-consolidate-CidG1jfH.js +0 -485
- package/studio-dist/server/chunks/audit3-DMO_fUGp.js +0 -52
- package/studio-dist/server/chunks/auto-extract-B84La1Vs.js +0 -34
- package/studio-dist/server/chunks/brain-consolidator-JGm6mzFf.js +0 -373
- package/studio-dist/server/chunks/brain-doctor-Dc2WqVbs.js +0 -311
- package/studio-dist/server/chunks/brain-embedding-Djw9ekXu.js +0 -42
- package/studio-dist/server/chunks/brain-lifecycle-BOOa876K.js +0 -969
- package/studio-dist/server/chunks/brain-maintenance-U6VvsvmK.js +0 -133
- package/studio-dist/server/chunks/brain-maintenance2-CwVSmfDT.js +0 -43
- package/studio-dist/server/chunks/brain-retrieval2-exR8mdgh.js +0 -751
- package/studio-dist/server/chunks/brain-search-CpSh-SNi.js +0 -48
- package/studio-dist/server/chunks/brain-search2-CwI2cXgg.js +0 -716
- package/studio-dist/server/chunks/brain-similarity-DI4yzm9e.js +0 -113
- package/studio-dist/server/chunks/brain-stdp2-BxSBIlSr.js +0 -960
- package/studio-dist/server/chunks/brain-writer-handlers-Dwu0QCAA.js +0 -188
- package/studio-dist/server/chunks/brain-writer-thread-6n7wI7Gy.js +0 -360
- package/studio-dist/server/chunks/branch-lock-Cq7zzmFK.js +0 -1118
- package/studio-dist/server/chunks/branch-lock2-CmDc4CZW.js +0 -45
- package/studio-dist/server/chunks/cancelled-child-waiver-audit-DkesrN83.js +0 -54
- package/studio-dist/server/chunks/catalog-model-resolver-Bas9qnoP.js +0 -9
- package/studio-dist/server/chunks/catalog-model-resolver2-Cexk2TN0.js +0 -237
- package/studio-dist/server/chunks/catalog-resolver-CLot3XJO.js +0 -260
- package/studio-dist/server/chunks/catalog-resolver2-JmKb91kY.js +0 -33
- package/studio-dist/server/chunks/chunk-DDP5xfzh.js +0 -39
- package/studio-dist/server/chunks/cleo-home-CCfe6kAQ.js +0 -64
- package/studio-dist/server/chunks/concrete-session2-bb_vxJ2N.js +0 -43
- package/studio-dist/server/chunks/config-DHj9CcFs.js +0 -386
- package/studio-dist/server/chunks/config2-F6PPIn7D.js +0 -35
- package/studio-dist/server/chunks/connections-BMGJVYcS.js +0 -98
- package/studio-dist/server/chunks/credential-pool-vF6NdtT9.js +0 -4600
- package/studio-dist/server/chunks/credentials-C7EJFf5O.js +0 -35
- package/studio-dist/server/chunks/credentials-store-CFygIuB2.js +0 -35
- package/studio-dist/server/chunks/cross-db-cleanup-1LWTUKPi.js +0 -147
- package/studio-dist/server/chunks/data-accessor-CWgVndbR.js +0 -72
- package/studio-dist/server/chunks/data-safety-central-DaFxK27G.js +0 -683
- package/studio-dist/server/chunks/decisions-CmVXV2-H.js +0 -574
- package/studio-dist/server/chunks/decisions2-XQsSYdxa.js +0 -48
- package/studio-dist/server/chunks/depends-waiver-audit-CUmlBYHx.js +0 -56
- package/studio-dist/server/chunks/dialectic-evaluator2-BOyyXhdI.js +0 -96
- package/studio-dist/server/chunks/dist-es2-DQy2Mjn_.js +0 -43
- package/studio-dist/server/chunks/dist-es3-CBygU4n5.js +0 -365
- package/studio-dist/server/chunks/dist-es4-CavbNu4B.js +0 -162
- package/studio-dist/server/chunks/dist-es5-Crpm8Wsl.js +0 -465
- package/studio-dist/server/chunks/dist-es6-CgePHzh4.js +0 -99
- package/studio-dist/server/chunks/dist-es7-k6c5GEd7.js +0 -311
- package/studio-dist/server/chunks/dist-es8-Bd9v0_pE.js +0 -91
- package/studio-dist/server/chunks/dist3-23bsJhRw.js +0 -27
- package/studio-dist/server/chunks/dist4-DmC1zSXi.js +0 -35618
- package/studio-dist/server/chunks/dual-scope-db-DKnWu1KM.js +0 -5672
- package/studio-dist/server/chunks/dual-scope-db2-Dht3luRw.js +0 -31
- package/studio-dist/server/chunks/duplicate-bypass-audit-BN5w1H2y.js +0 -36
- package/studio-dist/server/chunks/duplicate-detector-CaVFMKdE.js +0 -692
- package/studio-dist/server/chunks/edge-types-CgBvb0w1.js +0 -28
- package/studio-dist/server/chunks/embedding-local-xEnym8Ho.js +0 -92
- package/studio-dist/server/chunks/event-streams-Bi2p_fVo.js +0 -232
- package/studio-dist/server/chunks/execution-learning-BVCw7Plq.js +0 -278
- package/studio-dist/server/chunks/exodus-BBuuN6aA.js +0 -2594
- package/studio-dist/server/chunks/externalDataInterceptor-C3C4cObe.js +0 -21
- package/studio-dist/server/chunks/extraction-gate-DDNBq7gu.js +0 -48
- package/studio-dist/server/chunks/extraction-gate2-D77EZBQ6.js +0 -375
- package/studio-dist/server/chunks/getSSOTokenFromFile-yZAJxDci.js +0 -21
- package/studio-dist/server/chunks/governor2-CtfV3wfX.js +0 -923
- package/studio-dist/server/chunks/graph-auto-populate-Dmsr9ZJM.js +0 -42
- package/studio-dist/server/chunks/graph-auto-populate2-Cz0qeebM.js +0 -156
- package/studio-dist/server/chunks/graph-memory-bridge-CY8ft_d7.js +0 -43
- package/studio-dist/server/chunks/graph-memory-bridge2-Cd0XZwqc.js +0 -429
- package/studio-dist/server/chunks/handler-helpers-AANBGA_p.js +0 -49
- package/studio-dist/server/chunks/hash-Cm6yMET4.js +0 -14
- package/studio-dist/server/chunks/health-monitor-FepUZN1m.js +0 -106
- package/studio-dist/server/chunks/identity-DRpurt56.js +0 -30
- package/studio-dist/server/chunks/identity2-DeAB5RXE.js +0 -114
- package/studio-dist/server/chunks/index-61916rmV.js +0 -632
- package/studio-dist/server/chunks/index-DAgVDouG.js +0 -268
- package/studio-dist/server/chunks/index-Dtt_h58T.js +0 -2116
- package/studio-dist/server/chunks/indexes-DZ52grq6.js +0 -615
- package/studio-dist/server/chunks/json-Bfixam3g.js +0 -126
- package/studio-dist/server/chunks/learnings-D6Y3YGMU.js +0 -47
- package/studio-dist/server/chunks/learnings2-MwBdR9vb.js +0 -171
- package/studio-dist/server/chunks/lifecycle-ops2-V2CR5-7X.js +0 -121
- package/studio-dist/server/chunks/list-BhObczvn.js +0 -229
- package/studio-dist/server/chunks/living-brain2-j0B_Ir8j.js +0 -285
- package/studio-dist/server/chunks/llm-backend-resolver-D4ANvUPL.js +0 -295
- package/studio-dist/server/chunks/llm-extraction-DVCu4heR.js +0 -408
- package/studio-dist/server/chunks/loadSharedConfigFiles-umvW7kuz.js +0 -73
- package/studio-dist/server/chunks/loadSso-iidd5iKx.js +0 -599
- package/studio-dist/server/chunks/local-model-fit-B0TxifnX.js +0 -53
- package/studio-dist/server/chunks/local-model-fit2-BMqo6GJm.js +0 -2664
- package/studio-dist/server/chunks/lock-CA7d6lj7.js +0 -57
- package/studio-dist/server/chunks/logger-DQIoyZbq.js +0 -34
- package/studio-dist/server/chunks/memory-BUbicBbE.js +0 -618
- package/studio-dist/server/chunks/memory-accessor-i3P-RHSg.js +0 -42
- package/studio-dist/server/chunks/memory-accessor2-B981tHDR.js +0 -467
- package/studio-dist/server/chunks/memory-bridge-BOlEWg9w.js +0 -424
- package/studio-dist/server/chunks/memory-sqlite2-B7dq8doO.js +0 -42
- package/studio-dist/server/chunks/model-runner2-B71xjp4y.js +0 -43
- package/studio-dist/server/chunks/mvi-helpers-BNsJ8ZpQ.js +0 -59
- package/studio-dist/server/chunks/nexus-plasticity-BTfU8cW_.js +0 -269
- package/studio-dist/server/chunks/nexus-risk-audit-p379-TU5.js +0 -54
- package/studio-dist/server/chunks/nexus-schema-zeygY8OD.js +0 -11
- package/studio-dist/server/chunks/nexus-schema2-DP0Qd7CA.js +0 -444
- package/studio-dist/server/chunks/nexus-sqlite-BVNIpwc7.js +0 -36
- package/studio-dist/server/chunks/nexus-sqlite2-BBfY2xnY.js +0 -1103
- package/studio-dist/server/chunks/node-http-handler-CJI8kn7X.js +0 -386
- package/studio-dist/server/chunks/observe-Bo9veHGe.js +0 -47
- package/studio-dist/server/chunks/observe2-wzO0MaMY.js +0 -245
- package/studio-dist/server/chunks/observer-reflector-BwNOuq1d.js +0 -62
- package/studio-dist/server/chunks/observer-reflector2-ggtC1hmk.js +0 -478
- package/studio-dist/server/chunks/on-open-Wpcw7DV4.js +0 -740
- package/studio-dist/server/chunks/open-cleo-db--8sYNaYY.js +0 -70
- package/studio-dist/server/chunks/parseKnownFiles-Dg0pMFcT.js +0 -18
- package/studio-dist/server/chunks/parseUrl-qgGfl-Vh.js +0 -120
- package/studio-dist/server/chunks/paths-CV7S5-Zm.js +0 -30012
- package/studio-dist/server/chunks/patterns-lh5kn13I.js +0 -48
- package/studio-dist/server/chunks/patterns2-CzIcT-ai.js +0 -177
- package/studio-dist/server/chunks/pipeline-stage-IB_pOft-.js +0 -63
- package/studio-dist/server/chunks/prediction-D1lSGJ4c.js +0 -217
- package/studio-dist/server/chunks/premature-close-audit-VG09uAco.js +0 -53
- package/studio-dist/server/chunks/project-context-BjiqfEBi.js +0 -166
- package/studio-dist/server/chunks/provider-registry2-Cu7rAF0R.js +0 -35
- package/studio-dist/server/chunks/quality-feedback-CuCGEI6S.js +0 -371
- package/studio-dist/server/chunks/quality-scoring-CCPuRQmJ.js +0 -160
- package/studio-dist/server/chunks/query-ops-DCrjbZb9.js +0 -78
- package/studio-dist/server/chunks/query-promise-BkPmGPJy.js +0 -1257
- package/studio-dist/server/chunks/readFile-CxwXhymG.js +0 -31
- package/studio-dist/server/chunks/registry-CL2gN1zd.js +0 -27
- package/studio-dist/server/chunks/registry2-DoPYJnUW.js +0 -233
- package/studio-dist/server/chunks/registry3-BajEb-ll.js +0 -42
- package/studio-dist/server/chunks/registry4-DCqffZkT.js +0 -142
- package/studio-dist/server/chunks/retry-B3oEKYpp.js +0 -105
- package/studio-dist/server/chunks/role-executor-CC8BU54L.js +0 -25379
- package/studio-dist/server/chunks/role-resolver-D9QaDT0e.js +0 -6544
- package/studio-dist/server/chunks/role-resolver2-nkhzS1oy.js +0 -37
- package/studio-dist/server/chunks/rollup-CiefjN_Y.js +0 -194
- package/studio-dist/server/chunks/safety-data-accessor-CniDmGJO.js +0 -276
- package/studio-dist/server/chunks/service-connections-accessor-yBCdcgU-.js +0 -282
- package/studio-dist/server/chunks/session-factory-vbengc42.js +0 -96
- package/studio-dist/server/chunks/session-grade-BF4ZZtN_.js +0 -244
- package/studio-dist/server/chunks/session-journal-Bvey70Ur.js +0 -235
- package/studio-dist/server/chunks/session-narrative-BirZINSU.js +0 -304
- package/studio-dist/server/chunks/session-store--N_xHxUH.js +0 -557
- package/studio-dist/server/chunks/session-store2-DAM-eVTH.js +0 -43
- package/studio-dist/server/chunks/sessions-33DD4hkt.js +0 -2273
- package/studio-dist/server/chunks/sessions2-BHswKRDP.js +0 -50
- package/studio-dist/server/chunks/sigil-B-RznFXz.js +0 -33
- package/studio-dist/server/chunks/sigil2-jRMG5DuR.js +0 -47
- package/studio-dist/server/chunks/signin-BAsW3mM8.js +0 -644
- package/studio-dist/server/chunks/sleep-consolidation-BnSwXrvq.js +0 -823
- package/studio-dist/server/chunks/specialists-B_ZbpQlK.js +0 -441
- package/studio-dist/server/chunks/sqlite-Bm5LzbPs.js +0 -5977
- package/studio-dist/server/chunks/sqlite-backup-CFG1-b2e.js +0 -42
- package/studio-dist/server/chunks/sqlite-data-accessor-DD_RFX6r.js +0 -987
- package/studio-dist/server/chunks/sqlite-data-accessor2-CRmgNBnq.js +0 -44
- package/studio-dist/server/chunks/sqlite-native-BwlIqtbs.js +0 -42
- package/studio-dist/server/chunks/sqlite2-CUPut2fh.js +0 -42
- package/studio-dist/server/chunks/src2-DK8DKufK.js +0 -290
- package/studio-dist/server/chunks/src3-BJjf7XRG.js +0 -798
- package/studio-dist/server/chunks/src4-DNleK_t_.js +0 -28
- package/studio-dist/server/chunks/sso-oidc-eUvwseuL.js +0 -861
- package/studio-dist/server/chunks/storage-B9UA3BHR.js +0 -198
- package/studio-dist/server/chunks/sts-g7LDMLEd.js +0 -4655
- package/studio-dist/server/chunks/surprisal-CwTfWQi8.js +0 -224
- package/studio-dist/server/chunks/surprisal-tree-7dfHsuw1.js +0 -230
- package/studio-dist/server/chunks/system-resolver2-Bzhue_zQ.js +0 -53
- package/studio-dist/server/chunks/tasks-SHX7UPGY.js +0 -19694
- package/studio-dist/server/chunks/tasks-schema2-CTMoQKQy.js +0 -42
- package/studio-dist/server/chunks/temporal-supersession-DP4GPG_B.js +0 -298
- package/studio-dist/server/chunks/token-cAhAD9f9.js +0 -139
- package/studio-dist/server/chunks/token-util-D6drEz8_.js +0 -353
- package/studio-dist/server/chunks/token-util2-8UPSGvbb.js +0 -97
- package/studio-dist/server/chunks/transcript-scanner-kJWhWmlg.js +0 -53
- package/studio-dist/server/chunks/transformers.node-_xbxmK5p.js +0 -38475
- package/studio-dist/server/chunks/typed-query-l1D_QElt.js +0 -18
- package/studio-dist/server/chunks/unique-constraint-BZrrwgwc.js +0 -88
- package/studio-dist/server/chunks/update-B2YVBZG0.js +0 -1594
- package/studio-dist/server/chunks/user-profile-B61ZhVmC.js +0 -89
- package/studio-dist/server/chunks/utils-BPSZyajG.js +0 -1176
- package/studio-dist/server/chunks/validation-rules-CE27rtoF.js +0 -44
- package/studio-dist/server/chunks/zod-DsAeKNLm.js +0 -141
- /package/studio-dist/client/_app/immutable/chunks/{CQCxd1p9.js → B8WnZMYa.js} +0 -0
- /package/studio-dist/client/_app/immutable/chunks/{D13Quv9e2.js → B_0_YCYG.js} +0 -0
- /package/studio-dist/client/_app/immutable/chunks/{djL6V-tr.js → CqgtdAx_.js} +0 -0
- /package/studio-dist/client/_app/immutable/chunks/{_FU7h_8p2.js → KrUPZzXZ.js} +0 -0
|
@@ -1,2273 +0,0 @@
|
|
|
1
|
-
import 'node:module';
|
|
2
|
-
import { existsSync } from 'node:fs';
|
|
3
|
-
import { resolve, dirname, isAbsolute, relative } from 'node:path';
|
|
4
|
-
import { execFile } from 'node:child_process';
|
|
5
|
-
import { randomUUID } from 'node:crypto';
|
|
6
|
-
import 'node:os';
|
|
7
|
-
import { o as resolveOrCwd, b as getLogger } from './paths-CV7S5-Zm.js';
|
|
8
|
-
import { k as withWriterLease } from './dual-scope-db-DKnWu1KM.js';
|
|
9
|
-
import { h as hooks } from './registry2-DoPYJnUW.js';
|
|
10
|
-
import { g as getTaskAccessor } from './data-accessor-CWgVndbR.js';
|
|
11
|
-
import { O as getConduitDbPath, P as openFreshConduitDb } from './sqlite-Bm5LzbPs.js';
|
|
12
|
-
import './index-Dtt_h58T.js';
|
|
13
|
-
import { mkdir, appendFile } from 'node:fs/promises';
|
|
14
|
-
import './index-61916rmV.js';
|
|
15
|
-
import { s as sessionListItemNext } from './mvi-helpers-BNsJ8ZpQ.js';
|
|
16
|
-
import './session-store--N_xHxUH.js';
|
|
17
|
-
import { promisify } from 'node:util';
|
|
18
|
-
import { s as sqliteTable, t as text, a as index } from './indexes-DZ52grq6.js';
|
|
19
|
-
import { s as sql } from './utils-BPSZyajG.js';
|
|
20
|
-
|
|
21
|
-
//#region ../core/dist/hooks/handlers/handler-helpers.js
|
|
22
|
-
/**
|
|
23
|
-
* Shared helpers for hook handler modules.
|
|
24
|
-
*
|
|
25
|
-
* Centralises the two patterns repeated across all brain-capture handlers:
|
|
26
|
-
*
|
|
27
|
-
* 1. `isMissingBrainSchemaError` — detects the "no such table: brain_*" error
|
|
28
|
-
* thrown when brain.db has not been migrated yet, so handlers can swallow
|
|
29
|
-
* it silently instead of crashing agent workflows.
|
|
30
|
-
*
|
|
31
|
-
* 2. `isAutoCaptureEnabled` — reads `brain.autoCapture` from the cascaded
|
|
32
|
-
* project config and returns false when the config is unreadable.
|
|
33
|
-
*
|
|
34
|
-
* Import these instead of redefining them in each handler file.
|
|
35
|
-
*
|
|
36
|
-
* @task T166
|
|
37
|
-
* @epic T134
|
|
38
|
-
*/
|
|
39
|
-
/**
|
|
40
|
-
* Return true when the error is the "no such table: brain_*" SQLite error
|
|
41
|
-
* thrown before brain.db has been migrated.
|
|
42
|
-
*
|
|
43
|
-
* Hook handlers use this to swallow migration-lag errors without hiding
|
|
44
|
-
* genuine failures: if the error is NOT a missing-schema error it is
|
|
45
|
-
* re-thrown so it propagates normally.
|
|
46
|
-
*
|
|
47
|
-
* @param err - The caught error value (may be any type).
|
|
48
|
-
*/
|
|
49
|
-
function isMissingBrainSchemaError(err) {
|
|
50
|
-
if (!(err instanceof Error)) return false;
|
|
51
|
-
const message = String(err.message || "").toLowerCase();
|
|
52
|
-
return message.includes("no such table") && message.includes("brain_");
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Return true when the error is the "No CLEO project found" resolution error
|
|
56
|
-
* thrown by `resolveCleoDir` (CleoError `NEXUS_PROJECT_NOT_FOUND`) when no CLEO
|
|
57
|
-
* project is resolvable from the current context.
|
|
58
|
-
*
|
|
59
|
-
* Brain-capture hooks are best-effort: an observation with no project to write
|
|
60
|
-
* into is a no-op, not a crash. Handlers swallow this exactly like the
|
|
61
|
-
* missing-schema case, so a context with no resolvable project never fails the
|
|
62
|
-
* agent flow.
|
|
63
|
-
*
|
|
64
|
-
* This also closes a cross-file test-isolation leak (T11281): the
|
|
65
|
-
* `brain-tool-complete` PostToolUse capture could resolve with no anchor inside a
|
|
66
|
-
* shared vitest fork — most acutely in CI, where the gitignored
|
|
67
|
-
* `.cleo/project-info.json` is absent — and the uncaught throw collateral-failed
|
|
68
|
-
* sibling test files (saga-audit / invariant-audit). Swallowing it at the source
|
|
69
|
-
* fixes the leak without a global env / resolution-precedence change.
|
|
70
|
-
*
|
|
71
|
-
* @param err - The caught error value (may be any type).
|
|
72
|
-
*/
|
|
73
|
-
function isNoProjectError(err) {
|
|
74
|
-
if (!(err instanceof Error)) return false;
|
|
75
|
-
return String(err.message || "").includes("No CLEO project found");
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Return true when `brain.autoCapture` is enabled for the given project.
|
|
79
|
-
*
|
|
80
|
-
* Resolution order (first truthy wins):
|
|
81
|
-
* 1. `brain.autoCapture` project config value (via `loadConfig` cascade)
|
|
82
|
-
*
|
|
83
|
-
* Defaults to `false` when the config is unreadable or the key is absent,
|
|
84
|
-
* so handlers are safely disabled in environments where brain.db is not set up.
|
|
85
|
-
*
|
|
86
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
87
|
-
*/
|
|
88
|
-
async function isAutoCaptureEnabled(projectRoot) {
|
|
89
|
-
try {
|
|
90
|
-
const { loadConfig } = await import('./config2-F6PPIn7D.js');
|
|
91
|
-
return (await loadConfig(projectRoot)).brain?.autoCapture ?? false;
|
|
92
|
-
} catch {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
promisify(execFile);
|
|
98
|
-
/**
|
|
99
|
-
* Get handoff data for the most recent ended session.
|
|
100
|
-
* Filters by scope if provided.
|
|
101
|
-
*/
|
|
102
|
-
async function getLastHandoff(projectRoot, scope) {
|
|
103
|
-
let endedSessions = (await (await getTaskAccessor(projectRoot)).loadSessions()).filter((s) => s.status === "ended" && s.endedAt);
|
|
104
|
-
endedSessions.sort((a, b) => new Date(b.endedAt).getTime() - new Date(a.endedAt).getTime());
|
|
105
|
-
for (const session of endedSessions) {
|
|
106
|
-
if (typeof session.handoffJson === "string") try {
|
|
107
|
-
const handoff = JSON.parse(session.handoffJson);
|
|
108
|
-
return {
|
|
109
|
-
sessionId: session.id,
|
|
110
|
-
handoff
|
|
111
|
-
};
|
|
112
|
-
} catch {}
|
|
113
|
-
if (typeof session.debriefJson === "string") try {
|
|
114
|
-
const debrief = JSON.parse(session.debriefJson);
|
|
115
|
-
if (debrief?.handoff) return {
|
|
116
|
-
sessionId: session.id,
|
|
117
|
-
handoff: debrief.handoff
|
|
118
|
-
};
|
|
119
|
-
} catch {}
|
|
120
|
-
}
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
//#region ../core/dist/store/schema/cleo-global/session-manifest.js
|
|
125
|
-
/**
|
|
126
|
-
* Global-scope `cleo.db` — cross-project **session manifest** mirror (1 table).
|
|
127
|
-
*
|
|
128
|
-
* EP-SESSION-MANIFEST (epic T11638, task T11639). The `session_manifest` table is
|
|
129
|
-
* a CROSS-PROJECT MIRROR of the per-project `tasks_sessions` rows: each project's
|
|
130
|
-
* authoritative session lives in that project's `tasks_sessions` table (PROJECT
|
|
131
|
-
* scope `cleo.db`), and a best-effort writer copies a compact projection into this
|
|
132
|
-
* GLOBAL-scope row so the fleet has a single, machine-wide view of every session
|
|
133
|
-
* across every project — without ATTACHing N per-project DBs.
|
|
134
|
-
*
|
|
135
|
-
* ## NOT named `sessions` (AC1)
|
|
136
|
-
*
|
|
137
|
-
* The table is deliberately `session_manifest`, NOT `sessions`. The authoritative
|
|
138
|
-
* project-tier table is `tasks_sessions`; naming the global mirror `sessions` would
|
|
139
|
-
* invite a future reader to mistake the mirror for the source of truth. The name
|
|
140
|
-
* encodes its role: a manifest (an index/catalog), never the authority.
|
|
141
|
-
*
|
|
142
|
-
* ## MIRROR, never authoritative (AC4)
|
|
143
|
-
*
|
|
144
|
-
* Every column here is derived from the project row. The mirror writer is
|
|
145
|
-
* best-effort (a failure NEVER fails the underlying session op) and reconcile-on-
|
|
146
|
-
* start re-reads the authoritative project row and OVERWRITES the manifest row, so
|
|
147
|
-
* a stale or partially-written manifest entry can never drift into being treated as
|
|
148
|
-
* truth. Consumers needing exact session state MUST read the project's
|
|
149
|
-
* `tasks_sessions`; this table answers "which sessions exist, where, and how are
|
|
150
|
-
* they forked" cheaply across projects.
|
|
151
|
-
*
|
|
152
|
-
* ## Identity (`project_id`)
|
|
153
|
-
*
|
|
154
|
-
* `project_id` is the canonical `nexus_project_registry.project_id` (12-hex) for
|
|
155
|
-
* the project that owns the session — a soft FK into the global registry table in
|
|
156
|
-
* THIS same `cleo.db`. It is reused (never minted here) so the manifest joins
|
|
157
|
-
* cleanly to the registry. Nullable: a session started outside any resolvable
|
|
158
|
-
* registered project still mirrors, with `project_id` NULL.
|
|
159
|
-
*
|
|
160
|
-
* ## Fork tree (`parent_session_id`)
|
|
161
|
-
*
|
|
162
|
-
* `parent_session_id` mirrors the project row's own `parent_session_id`
|
|
163
|
-
* (populated from `CLEO_PARENT_SESSION_ID`, stamped by the supervisor — PR #996 /
|
|
164
|
-
* T11629). It reconstructs the orchestrator→worker fork tree machine-wide without
|
|
165
|
-
* a per-project DB scan. Soft self-reference to `session_manifest.session_id`;
|
|
166
|
-
* NULL for a root session.
|
|
167
|
-
*
|
|
168
|
-
* @task T11639
|
|
169
|
-
* @epic T11638
|
|
170
|
-
* @saga T11242
|
|
171
|
-
* @see ../cleo-project/tasks-core.ts — `tasksSessions` (the authoritative source)
|
|
172
|
-
* @see ./nexus.ts — `nexusProjectRegistry` (the `project_id` SSoT)
|
|
173
|
-
* @see ../../sessions/session-manifest-mirror.ts — the best-effort mirror writers
|
|
174
|
-
*/
|
|
175
|
-
/**
|
|
176
|
-
* `session_manifest` — cross-project mirror of per-project `tasks_sessions` rows.
|
|
177
|
-
*
|
|
178
|
-
* A best-effort projection: one row per session, keyed on the session id, carrying
|
|
179
|
-
* just enough to answer fleet-wide "what sessions exist, in which project, and how
|
|
180
|
-
* are they forked" without opening every project's `cleo.db`. NOT authoritative —
|
|
181
|
-
* the project's `tasks_sessions` row is the source of truth; this row is overwritten
|
|
182
|
-
* on reconcile-on-start so it can never drift into authority (AC4).
|
|
183
|
-
*
|
|
184
|
-
* @task T11639
|
|
185
|
-
*/
|
|
186
|
-
sqliteTable("session_manifest", {
|
|
187
|
-
sessionId: text("session_id").primaryKey(),
|
|
188
|
-
projectId: text("project_id"),
|
|
189
|
-
parentSessionId: text("parent_session_id"),
|
|
190
|
-
name: text("name"),
|
|
191
|
-
status: text("status"),
|
|
192
|
-
projectPath: text("project_path"),
|
|
193
|
-
startedAt: text("started_at"),
|
|
194
|
-
endedAt: text("ended_at"),
|
|
195
|
-
mirroredAt: text("mirrored_at").notNull().default(sql`(datetime('now'))`)
|
|
196
|
-
}, (table) => [
|
|
197
|
-
index("idx_session_manifest_project_id").on(table.projectId),
|
|
198
|
-
index("idx_session_manifest_parent").on(table.parentSessionId),
|
|
199
|
-
index("idx_session_manifest_status").on(table.status)
|
|
200
|
-
]);
|
|
201
|
-
|
|
202
|
-
//#region ../core/dist/conduit/local-transport.js
|
|
203
|
-
/**
|
|
204
|
-
* LocalTransport — In-process SQLite transport for fully offline agent messaging.
|
|
205
|
-
*
|
|
206
|
-
* Reads and writes messages directly to conduit.db via node:sqlite.
|
|
207
|
-
* No network calls. Works fully offline. Messages are stored in the
|
|
208
|
-
* project-local conduit.db (ADR-037), keeping agent messaging isolated
|
|
209
|
-
* from the global-identity signaldock.db.
|
|
210
|
-
*
|
|
211
|
-
* Priority: LocalTransport is preferred over HttpTransport when
|
|
212
|
-
* conduit.db is available (see factory.ts).
|
|
213
|
-
*
|
|
214
|
-
* @see docs/specs/SIGNALDOCK-UNIFIED-AGENT-REGISTRY.md Section 4.4
|
|
215
|
-
* @task T213
|
|
216
|
-
* @task T356
|
|
217
|
-
* @epic T310
|
|
218
|
-
*/
|
|
219
|
-
/**
|
|
220
|
-
* Parse an A2A topic name into its epic_id and optional wave_id components.
|
|
221
|
-
*
|
|
222
|
-
* Supported formats:
|
|
223
|
-
* - `"epic-T1149.wave-2"` → `{ epicId: "T1149", waveId: 2 }`
|
|
224
|
-
* - `"epic-T1149.coordination"` → `{ epicId: "T1149", waveId: undefined }`
|
|
225
|
-
* - `"T1149.wave-2"` → `{ epicId: "T1149", waveId: 2 }` (short form)
|
|
226
|
-
* - `"some-topic"` → `{ epicId: "some-topic", waveId: undefined }` (fallback)
|
|
227
|
-
*
|
|
228
|
-
* @param topicName - Raw topic name string.
|
|
229
|
-
* @returns Parsed epic ID and optional integer wave ID.
|
|
230
|
-
* @task T1252
|
|
231
|
-
*/
|
|
232
|
-
function parseTopicName(topicName) {
|
|
233
|
-
const epicWaveMatch = topicName.match(/(?:epic-)?([A-Z]\d+)\.wave-(\d+)/);
|
|
234
|
-
if (epicWaveMatch) return {
|
|
235
|
-
epicId: epicWaveMatch[1] ?? topicName,
|
|
236
|
-
waveId: parseInt(epicWaveMatch[2] ?? "0", 10)
|
|
237
|
-
};
|
|
238
|
-
const epicMatch = topicName.match(/(?:epic-)?([A-Z]\d+)\./);
|
|
239
|
-
if (epicMatch) return {
|
|
240
|
-
epicId: epicMatch[1] ?? topicName,
|
|
241
|
-
waveId: void 0
|
|
242
|
-
};
|
|
243
|
-
return {
|
|
244
|
-
epicId: topicName,
|
|
245
|
-
waveId: void 0
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
/** In-process SQLite transport for fully offline agent messaging. */
|
|
249
|
-
var LocalTransport = class {
|
|
250
|
-
name = "local";
|
|
251
|
-
state = null;
|
|
252
|
-
/**
|
|
253
|
-
* Connect to conduit.db for in-process messaging.
|
|
254
|
-
*
|
|
255
|
-
* Opens the database, sets WAL mode pragmas, and verifies
|
|
256
|
-
* the messages table exists. Throws if conduit.db is missing
|
|
257
|
-
* or uninitialized (run `cleo init` first).
|
|
258
|
-
*
|
|
259
|
-
* @task T356
|
|
260
|
-
* @epic T310
|
|
261
|
-
*/
|
|
262
|
-
async connect(config) {
|
|
263
|
-
const dbPath = getConduitDbPath(process.cwd());
|
|
264
|
-
if (!existsSync(dbPath)) throw new Error(`LocalTransport: conduit.db not found at ${dbPath}. Run: cleo init`);
|
|
265
|
-
const db = openFreshConduitDb(process.cwd());
|
|
266
|
-
if (!db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='conduit_messages'").get()) {
|
|
267
|
-
db.close();
|
|
268
|
-
throw new Error("LocalTransport: conduit.db exists but conduit_messages table missing — run cleo init or allow auto-migration (T358)");
|
|
269
|
-
}
|
|
270
|
-
this.state = {
|
|
271
|
-
agentId: config.agentId,
|
|
272
|
-
db,
|
|
273
|
-
dbPath,
|
|
274
|
-
subscribers: /* @__PURE__ */ new Set(),
|
|
275
|
-
topicHandlers: /* @__PURE__ */ new Map(),
|
|
276
|
-
pollTimer: null,
|
|
277
|
-
topicPollTimer: null,
|
|
278
|
-
topicLastSeen: /* @__PURE__ */ new Map()
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
/** Close the database connection and stop any subscriber polling. */
|
|
282
|
-
async disconnect() {
|
|
283
|
-
if (!this.state) return;
|
|
284
|
-
if (this.state.pollTimer) clearInterval(this.state.pollTimer);
|
|
285
|
-
if (this.state.topicPollTimer) clearInterval(this.state.topicPollTimer);
|
|
286
|
-
this.state.subscribers.clear();
|
|
287
|
-
this.state.topicHandlers.clear();
|
|
288
|
-
this.state.topicLastSeen.clear();
|
|
289
|
-
this.state.db.close();
|
|
290
|
-
this.state = null;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Store a message in conduit.db.
|
|
294
|
-
*
|
|
295
|
-
* Inserts into the messages table with status 'pending'.
|
|
296
|
-
* For conversation messages, also links via conversation_participants
|
|
297
|
-
* if not already present.
|
|
298
|
-
*/
|
|
299
|
-
async push(to, content, options) {
|
|
300
|
-
this.ensureConnected();
|
|
301
|
-
const { db, agentId } = this.state;
|
|
302
|
-
const messageId = randomUUID();
|
|
303
|
-
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
304
|
-
await this.runWrite(() => {
|
|
305
|
-
if (options?.conversationId) db.prepare(`INSERT INTO conduit_messages (id, conversation_id, from_agent_id, to_agent_id, content, content_type, status, created_at)
|
|
306
|
-
VALUES (?, ?, ?, ?, ?, 'text', 'pending', ?)`).run(messageId, options.conversationId, agentId, to, content, nowIso);
|
|
307
|
-
else {
|
|
308
|
-
const convId = this.ensureDmConversation(agentId, to);
|
|
309
|
-
db.prepare(`INSERT INTO conduit_messages (id, conversation_id, from_agent_id, to_agent_id, content, content_type, status, created_at)
|
|
310
|
-
VALUES (?, ?, ?, ?, ?, 'text', 'pending', ?)`).run(messageId, convId, agentId, to, content, nowIso);
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
this.notifySubscribers({
|
|
314
|
-
id: messageId,
|
|
315
|
-
from: agentId,
|
|
316
|
-
content,
|
|
317
|
-
threadId: options?.conversationId,
|
|
318
|
-
timestamp: nowIso
|
|
319
|
-
});
|
|
320
|
-
return { messageId };
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Poll for messages addressed to this agent.
|
|
324
|
-
*
|
|
325
|
-
* Returns messages with status 'pending' where to_agent_id matches
|
|
326
|
-
* the connected agent. Messages are returned oldest-first.
|
|
327
|
-
*/
|
|
328
|
-
async poll(options) {
|
|
329
|
-
this.ensureConnected();
|
|
330
|
-
const { db, agentId } = this.state;
|
|
331
|
-
const limit = options?.limit ?? 50;
|
|
332
|
-
let query;
|
|
333
|
-
let params;
|
|
334
|
-
if (options?.since) {
|
|
335
|
-
query = `SELECT id, from_agent_id, content, conversation_id, created_at
|
|
336
|
-
FROM conduit_messages
|
|
337
|
-
WHERE to_agent_id = ? AND status = 'pending' AND created_at > ?
|
|
338
|
-
ORDER BY created_at ASC
|
|
339
|
-
LIMIT ?`;
|
|
340
|
-
params = [
|
|
341
|
-
agentId,
|
|
342
|
-
options.since,
|
|
343
|
-
limit
|
|
344
|
-
];
|
|
345
|
-
} else {
|
|
346
|
-
query = `SELECT id, from_agent_id, content, conversation_id, created_at
|
|
347
|
-
FROM conduit_messages
|
|
348
|
-
WHERE to_agent_id = ? AND status = 'pending'
|
|
349
|
-
ORDER BY created_at ASC
|
|
350
|
-
LIMIT ?`;
|
|
351
|
-
params = [agentId, limit];
|
|
352
|
-
}
|
|
353
|
-
return db.prepare(query).all(...params).map((r) => ({
|
|
354
|
-
id: r.id,
|
|
355
|
-
from: r.from_agent_id,
|
|
356
|
-
content: r.content,
|
|
357
|
-
threadId: r.conversation_id ?? void 0,
|
|
358
|
-
timestamp: r.created_at
|
|
359
|
-
}));
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Acknowledge messages by marking them as 'delivered'.
|
|
363
|
-
*
|
|
364
|
-
* Updates the status and delivered_at timestamp for each message ID.
|
|
365
|
-
*/
|
|
366
|
-
async ack(messageIds) {
|
|
367
|
-
this.ensureConnected();
|
|
368
|
-
if (messageIds.length === 0) return;
|
|
369
|
-
const { db } = this.state;
|
|
370
|
-
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
371
|
-
const placeholders = messageIds.map(() => "?").join(", ");
|
|
372
|
-
await this.runWrite(() => {
|
|
373
|
-
db.prepare(`UPDATE conduit_messages SET status = 'delivered', delivered_at = ? WHERE id IN (${placeholders})`).run(nowIso, ...messageIds);
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Subscribe to real-time local messages.
|
|
378
|
-
*
|
|
379
|
-
* Since this is in-process, subscribers are notified synchronously
|
|
380
|
-
* when push() is called. Additionally, a polling interval checks
|
|
381
|
-
* for messages inserted by other processes (e.g., Rust CLI).
|
|
382
|
-
*
|
|
383
|
-
* @returns Unsubscribe function.
|
|
384
|
-
*/
|
|
385
|
-
subscribe(handler) {
|
|
386
|
-
this.ensureConnected();
|
|
387
|
-
this.state.subscribers.add(handler);
|
|
388
|
-
if (!this.state.pollTimer && this.state.subscribers.size === 1) this.state.pollTimer = setInterval(() => {
|
|
389
|
-
this.pollAndNotify();
|
|
390
|
-
}, 1e3);
|
|
391
|
-
return () => {
|
|
392
|
-
this.state?.subscribers.delete(handler);
|
|
393
|
-
if (this.state?.subscribers.size === 0 && this.state.pollTimer) {
|
|
394
|
-
clearInterval(this.state.pollTimer);
|
|
395
|
-
this.state.pollTimer = null;
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* Subscribe this agent to a named topic in conduit.db.
|
|
401
|
-
*
|
|
402
|
-
* Creates the topic row if it does not exist (idempotent via ON CONFLICT DO NOTHING).
|
|
403
|
-
* Inserts a `topic_subscriptions` row linking this agent to the topic.
|
|
404
|
-
*
|
|
405
|
-
* Topic name convention: `<epicId>.<waveId>` or `<epicId>.coordination`.
|
|
406
|
-
*
|
|
407
|
-
* @param topicName - Topic name, e.g. `"epic-T1149.wave-2"`.
|
|
408
|
-
* @param _options - Reserved for future filter support (not stored in DB yet).
|
|
409
|
-
* @task T1252
|
|
410
|
-
*/
|
|
411
|
-
async subscribeTopic(topicName, _options) {
|
|
412
|
-
this.ensureConnected();
|
|
413
|
-
const { db, agentId } = this.state;
|
|
414
|
-
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
415
|
-
const { epicId, waveId } = parseTopicName(topicName);
|
|
416
|
-
const topicId = randomUUID();
|
|
417
|
-
await this.runWrite(() => {
|
|
418
|
-
db.prepare(`INSERT INTO conduit_topics (id, name, epic_id, wave_id, created_by, created_at)
|
|
419
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
420
|
-
ON CONFLICT(name) DO NOTHING`).run(topicId, topicName, epicId, waveId ?? null, agentId, nowIso);
|
|
421
|
-
const topic = db.prepare("SELECT id FROM conduit_topics WHERE name = ?").get(topicName);
|
|
422
|
-
if (!topic) return;
|
|
423
|
-
db.prepare(`INSERT INTO conduit_topic_subscriptions (topic_id, agent_id, subscribed_at)
|
|
424
|
-
VALUES (?, ?, ?)
|
|
425
|
-
ON CONFLICT(topic_id, agent_id) DO NOTHING`).run(topic.id, agentId, nowIso);
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Publish a message to a named topic in conduit.db.
|
|
430
|
-
*
|
|
431
|
-
* The message is broadcast to all current subscribers via the in-process
|
|
432
|
-
* handler map (`topicHandlers`). Cross-process subscribers receive it via
|
|
433
|
-
* the periodic poll timer started by `onTopic()`.
|
|
434
|
-
*
|
|
435
|
-
* The topic must already exist (via a prior `subscribeTopic()` call), or
|
|
436
|
-
* this method creates it automatically with a synthetic creator.
|
|
437
|
-
*
|
|
438
|
-
* @param topicName - Target topic name.
|
|
439
|
-
* @param content - Human-readable message content.
|
|
440
|
-
* @param options - Message kind and optional structured payload.
|
|
441
|
-
* @returns Object containing the assigned `messageId`.
|
|
442
|
-
* @task T1252
|
|
443
|
-
*/
|
|
444
|
-
async publishToTopic(topicName, content, options) {
|
|
445
|
-
this.ensureConnected();
|
|
446
|
-
const { db, agentId } = this.state;
|
|
447
|
-
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
448
|
-
const messageId = randomUUID();
|
|
449
|
-
const kind = options?.kind ?? "message";
|
|
450
|
-
const { epicId, waveId } = parseTopicName(topicName);
|
|
451
|
-
const topicInsertId = randomUUID();
|
|
452
|
-
await this.runWrite(() => {
|
|
453
|
-
db.prepare(`INSERT INTO conduit_topics (id, name, epic_id, wave_id, created_by, created_at)
|
|
454
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
455
|
-
ON CONFLICT(name) DO NOTHING`).run(topicInsertId, topicName, epicId, waveId ?? null, agentId, nowIso);
|
|
456
|
-
const topic = db.prepare("SELECT id FROM conduit_topics WHERE name = ?").get(topicName);
|
|
457
|
-
if (!topic) throw new Error(`LocalTransport.publishToTopic: could not resolve topic "${topicName}"`);
|
|
458
|
-
db.prepare(`INSERT INTO conduit_topic_messages (id, topic_id, from_agent_id, kind, content, payload, created_at)
|
|
459
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`).run(messageId, topic.id, agentId, kind, content, options?.payload != null ? JSON.stringify(options.payload) : null, nowIso);
|
|
460
|
-
});
|
|
461
|
-
this.notifyTopicHandlers(topicName, {
|
|
462
|
-
id: messageId,
|
|
463
|
-
from: agentId,
|
|
464
|
-
fromPeerId: agentId,
|
|
465
|
-
toPeerId: null,
|
|
466
|
-
content,
|
|
467
|
-
kind,
|
|
468
|
-
threadId: topicName,
|
|
469
|
-
payload: options?.payload,
|
|
470
|
-
timestamp: nowIso
|
|
471
|
-
});
|
|
472
|
-
return { messageId };
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Register a real-time handler for messages on a named topic.
|
|
476
|
-
*
|
|
477
|
-
* In-process publishers notify the handler synchronously via `publishToTopic()`.
|
|
478
|
-
* Cross-process publishers are picked up via a 1-second polling interval
|
|
479
|
-
* that is started on the first `onTopic()` call and stopped when all
|
|
480
|
-
* topic handlers are removed.
|
|
481
|
-
*
|
|
482
|
-
* @param topicName - Topic name to watch.
|
|
483
|
-
* @param handler - Callback invoked for each incoming message.
|
|
484
|
-
* @returns Unsubscribe function that removes this handler.
|
|
485
|
-
* @task T1252
|
|
486
|
-
*/
|
|
487
|
-
onTopic(topicName, handler) {
|
|
488
|
-
this.ensureConnected();
|
|
489
|
-
const state = this.state;
|
|
490
|
-
if (!state.topicHandlers.has(topicName)) state.topicHandlers.set(topicName, /* @__PURE__ */ new Set());
|
|
491
|
-
state.topicHandlers.get(topicName).add(handler);
|
|
492
|
-
if (!state.topicPollTimer) state.topicPollTimer = setInterval(() => {
|
|
493
|
-
this.pollAndNotifyTopics();
|
|
494
|
-
}, 1e3);
|
|
495
|
-
return () => {
|
|
496
|
-
const handlers = state.topicHandlers.get(topicName);
|
|
497
|
-
if (handlers) {
|
|
498
|
-
handlers.delete(handler);
|
|
499
|
-
if (handlers.size === 0) {
|
|
500
|
-
state.topicHandlers.delete(topicName);
|
|
501
|
-
state.topicLastSeen.delete(topicName);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
if (state.topicHandlers.size === 0 && state.topicPollTimer) {
|
|
505
|
-
clearInterval(state.topicPollTimer);
|
|
506
|
-
state.topicPollTimer = null;
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Unsubscribe this agent from a named topic.
|
|
512
|
-
*
|
|
513
|
-
* Removes the `topic_subscriptions` row; does not delete the topic or messages.
|
|
514
|
-
* In-process `onTopic` handlers are NOT automatically removed — callers should
|
|
515
|
-
* call the unsubscribe function returned by `onTopic()` before `unsubscribeTopic()`.
|
|
516
|
-
*
|
|
517
|
-
* @param topicName - Topic name to leave.
|
|
518
|
-
* @task T1252
|
|
519
|
-
*/
|
|
520
|
-
async unsubscribeTopic(topicName) {
|
|
521
|
-
this.ensureConnected();
|
|
522
|
-
const { db, agentId } = this.state;
|
|
523
|
-
const topic = db.prepare("SELECT id FROM conduit_topics WHERE name = ?").get(topicName);
|
|
524
|
-
if (!topic) return;
|
|
525
|
-
await this.runWrite(() => {
|
|
526
|
-
db.prepare("DELETE FROM conduit_topic_subscriptions WHERE topic_id = ? AND agent_id = ?").run(topic.id, agentId);
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Poll for new topic messages and deliver to registered handlers.
|
|
531
|
-
*
|
|
532
|
-
* Queries each topic with registered handlers for messages newer than
|
|
533
|
-
* `topicLastSeen`. Updates `topicLastSeen` after each poll. Called
|
|
534
|
-
* periodically by the `topicPollTimer`.
|
|
535
|
-
*
|
|
536
|
-
* @task T1252
|
|
537
|
-
*/
|
|
538
|
-
async pollTopic(topicName, options) {
|
|
539
|
-
this.ensureConnected();
|
|
540
|
-
const { db } = this.state;
|
|
541
|
-
const limit = options?.limit ?? 50;
|
|
542
|
-
const since = options?.since ?? "";
|
|
543
|
-
const topic = db.prepare("SELECT id FROM conduit_topics WHERE name = ?").get(topicName);
|
|
544
|
-
if (!topic) return [];
|
|
545
|
-
return db.prepare(`SELECT id, from_agent_id, kind, content, payload, created_at
|
|
546
|
-
FROM conduit_topic_messages
|
|
547
|
-
WHERE topic_id = ? AND created_at > ?
|
|
548
|
-
ORDER BY created_at ASC
|
|
549
|
-
LIMIT ?`).all(topic.id, since, limit).map((r) => ({
|
|
550
|
-
id: r.id,
|
|
551
|
-
from: r.from_agent_id,
|
|
552
|
-
fromPeerId: r.from_agent_id,
|
|
553
|
-
toPeerId: null,
|
|
554
|
-
content: r.content,
|
|
555
|
-
kind: r.kind,
|
|
556
|
-
threadId: topicName,
|
|
557
|
-
payload: r.payload != null ? JSON.parse(r.payload) : void 0,
|
|
558
|
-
timestamp: r.created_at
|
|
559
|
-
}));
|
|
560
|
-
}
|
|
561
|
-
/**
|
|
562
|
-
* Check whether conduit.db is available for local transport.
|
|
563
|
-
*
|
|
564
|
-
* Used by factory.ts to decide whether to use LocalTransport.
|
|
565
|
-
*
|
|
566
|
-
* @task T356
|
|
567
|
-
* @epic T310
|
|
568
|
-
* @param cwd - Optional working directory override (defaults to process.cwd()).
|
|
569
|
-
* @returns `true` if conduit.db exists at the expected path.
|
|
570
|
-
*/
|
|
571
|
-
static isAvailable(cwd) {
|
|
572
|
-
let dbPath;
|
|
573
|
-
try {
|
|
574
|
-
dbPath = getConduitDbPath(resolveOrCwd(cwd));
|
|
575
|
-
} catch {
|
|
576
|
-
return false;
|
|
577
|
-
}
|
|
578
|
-
return existsSync(dbPath);
|
|
579
|
-
}
|
|
580
|
-
/** Poll for new messages and notify subscribers (cross-process sync). */
|
|
581
|
-
async pollAndNotify() {
|
|
582
|
-
if (!this.state || this.state.subscribers.size === 0) return;
|
|
583
|
-
const messages = await this.poll({ limit: 20 });
|
|
584
|
-
for (const msg of messages) this.notifySubscribers(msg);
|
|
585
|
-
if (messages.length > 0) await this.ack(messages.map((m) => m.id));
|
|
586
|
-
}
|
|
587
|
-
/** Poll all watched topics for new messages and notify in-process handlers. */
|
|
588
|
-
async pollAndNotifyTopics() {
|
|
589
|
-
if (!this.state || this.state.topicHandlers.size === 0) return;
|
|
590
|
-
for (const [topicName] of this.state.topicHandlers) {
|
|
591
|
-
const since = this.state.topicLastSeen.get(topicName) ?? "";
|
|
592
|
-
const messages = await this.pollTopic(topicName, {
|
|
593
|
-
limit: 50,
|
|
594
|
-
since
|
|
595
|
-
});
|
|
596
|
-
if (messages.length > 0) {
|
|
597
|
-
const lastTs = messages[messages.length - 1];
|
|
598
|
-
if (lastTs?.timestamp) this.state.topicLastSeen.set(topicName, lastTs.timestamp);
|
|
599
|
-
for (const msg of messages) this.notifyTopicHandlers(topicName, msg);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
/** Notify all handlers registered for a specific topic. */
|
|
604
|
-
notifyTopicHandlers(topicName, message) {
|
|
605
|
-
if (!this.state) return;
|
|
606
|
-
const handlers = this.state.topicHandlers.get(topicName);
|
|
607
|
-
if (!handlers) return;
|
|
608
|
-
for (const handler of handlers) try {
|
|
609
|
-
handler(message);
|
|
610
|
-
} catch {}
|
|
611
|
-
}
|
|
612
|
-
/** Notify all active subscribers of a new message. */
|
|
613
|
-
notifySubscribers(message) {
|
|
614
|
-
if (!this.state) return;
|
|
615
|
-
for (const handler of this.state.subscribers) try {
|
|
616
|
-
handler(message);
|
|
617
|
-
} catch {}
|
|
618
|
-
}
|
|
619
|
-
/**
|
|
620
|
-
* Ensure a DM conversation exists between two agents.
|
|
621
|
-
*
|
|
622
|
-
* Conversations store participants as a comma-separated TEXT field.
|
|
623
|
-
* We search for existing private conversations containing both agents.
|
|
624
|
-
*
|
|
625
|
-
* @returns The conversation ID.
|
|
626
|
-
*/
|
|
627
|
-
ensureDmConversation(fromAgentId, toAgentId) {
|
|
628
|
-
const { db } = this.state;
|
|
629
|
-
const sortedParticipants = [fromAgentId, toAgentId].sort().join(",");
|
|
630
|
-
const existing = db.prepare(`SELECT id FROM conduit_conversations
|
|
631
|
-
WHERE visibility = 'private' AND participants = ?
|
|
632
|
-
LIMIT 1`).get(sortedParticipants);
|
|
633
|
-
if (existing) return existing.id;
|
|
634
|
-
const convId = randomUUID();
|
|
635
|
-
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
636
|
-
db.prepare(`INSERT INTO conduit_conversations (id, participants, visibility, message_count, created_at, updated_at)
|
|
637
|
-
VALUES (?, ?, 'private', 0, ?, ?)`).run(convId, sortedParticipants, nowIso, nowIso);
|
|
638
|
-
return convId;
|
|
639
|
-
}
|
|
640
|
-
/** Throw if not connected. */
|
|
641
|
-
ensureConnected() {
|
|
642
|
-
if (!this.state) throw new Error("LocalTransport not connected. Call connect() first.");
|
|
643
|
-
}
|
|
644
|
-
/**
|
|
645
|
-
* Run a synchronous conduit write under the project `bulk` lease. Conduit uses
|
|
646
|
-
* the consolidated project cleo.db, so the connection state's exact path pins
|
|
647
|
-
* the lease to this project rather than the process cwd.
|
|
648
|
-
*
|
|
649
|
-
* @param fn - The synchronous write block to run under the lease.
|
|
650
|
-
* @returns The value returned by `fn`.
|
|
651
|
-
*/
|
|
652
|
-
runWrite(fn) {
|
|
653
|
-
return withWriterLease("project", "bulk", async () => fn(), { dbPath: this.state.dbPath });
|
|
654
|
-
}
|
|
655
|
-
};
|
|
656
|
-
//#endregion
|
|
657
|
-
//#region ../core/dist/hooks/handlers/memory-bridge-refresh.js
|
|
658
|
-
/**
|
|
659
|
-
* Shared memory bridge refresh helper for hook handlers.
|
|
660
|
-
*
|
|
661
|
-
* Provides a config-gated, debounced wrapper around refreshMemoryBridge().
|
|
662
|
-
* Prevents rapid regeneration of .cleo/memory-bridge.md when multiple
|
|
663
|
-
* lifecycle events fire in quick succession (e.g. session end + task complete).
|
|
664
|
-
*
|
|
665
|
-
* Debounce: max one refresh per 30 seconds across all callers in the process.
|
|
666
|
-
*
|
|
667
|
-
* @task T138
|
|
668
|
-
* @epic T134
|
|
669
|
-
*/
|
|
670
|
-
/** Debounce window in milliseconds. */
|
|
671
|
-
var DEBOUNCE_MS = 3e4;
|
|
672
|
-
/** Timestamp of the last successful refresh call (module-level singleton). */
|
|
673
|
-
var lastRefreshTime = 0;
|
|
674
|
-
/**
|
|
675
|
-
* Refresh the memory bridge if autoRefresh is enabled and the debounce window
|
|
676
|
-
* has elapsed. Reads config via loadConfig() (cascaded). Never throws.
|
|
677
|
-
*
|
|
678
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
679
|
-
*/
|
|
680
|
-
async function maybeRefreshMemoryBridge(projectRoot) {
|
|
681
|
-
try {
|
|
682
|
-
const { loadConfig } = await import('./config2-F6PPIn7D.js');
|
|
683
|
-
if (!(await loadConfig(projectRoot)).brain?.memoryBridge?.autoRefresh) return;
|
|
684
|
-
const now = Date.now();
|
|
685
|
-
if (now - lastRefreshTime < DEBOUNCE_MS) return;
|
|
686
|
-
lastRefreshTime = now;
|
|
687
|
-
const { refreshMemoryBridge } = await import('./memory-bridge-BOlEWg9w.js');
|
|
688
|
-
await refreshMemoryBridge(projectRoot);
|
|
689
|
-
} catch {}
|
|
690
|
-
}
|
|
691
|
-
//#endregion
|
|
692
|
-
//#region ../core/dist/hooks/handlers/session-hooks.js
|
|
693
|
-
/**
|
|
694
|
-
* Session Hook Handlers - Phase 2D of T5237
|
|
695
|
-
*
|
|
696
|
-
* Handlers that capture session lifecycle events.
|
|
697
|
-
* Auto-registers on module load.
|
|
698
|
-
*
|
|
699
|
-
* T138: Triggers memory bridge refresh on session start and end.
|
|
700
|
-
* T139: Regenerates bridge with session scope on start.
|
|
701
|
-
* T144: Extracts transcript observations on session end.
|
|
702
|
-
* T5158: Auto-snapshots SQLite databases (tasks.db + brain.db) via
|
|
703
|
-
* VACUUM INTO on SessionEnd to preserve a recovery point now that
|
|
704
|
-
* the databases are no longer tracked in project git (ADR-013).
|
|
705
|
-
* T527: Removed duplicate session observeBrain writes — session data already
|
|
706
|
-
* lives in the sessions table; writing it again to brain_observations
|
|
707
|
-
* was pure noise.
|
|
708
|
-
* T549 Wave 3-E: Fire-and-forget sleep-time consolidation on session end.
|
|
709
|
-
* Runs after backup (priority 5) so brain.db snapshot is captured first.
|
|
710
|
-
* T554: Fire-and-forget LLM reflector on session end. Runs at priority 4
|
|
711
|
-
* (after consolidation at priority 5) to synthesize final session knowledge.
|
|
712
|
-
* T732: Write `transcript_pending_extraction` tombstone on session end (priority 3).
|
|
713
|
-
* Runs after reflector so it is the last scheduled operation. Records the
|
|
714
|
-
* session JSONL path so `cleo transcript scan --pending` can list queued work.
|
|
715
|
-
* T1263: Append session journal entry at priority 2 (last in pipeline).
|
|
716
|
-
* Absorbs T1262 session-end hook: calls scanBrainNoise and embeds
|
|
717
|
-
* doctorSummary in each session_end journal entry.
|
|
718
|
-
* MUST use `await` (not setImmediate) — process exits after this hook.
|
|
719
|
-
*/
|
|
720
|
-
/**
|
|
721
|
-
* Handle SessionStart - refresh memory bridge on session start.
|
|
722
|
-
*
|
|
723
|
-
* T138: Refresh memory bridge on session start.
|
|
724
|
-
* T139: Regenerate bridge with session scope context.
|
|
725
|
-
* T527: Removed duplicate observeBrain write — session data is already
|
|
726
|
-
* persisted in the sessions table.
|
|
727
|
-
*/
|
|
728
|
-
async function handleSessionStart(projectRoot, _payload) {
|
|
729
|
-
await maybeRefreshMemoryBridge(projectRoot);
|
|
730
|
-
}
|
|
731
|
-
/**
|
|
732
|
-
* Handle SessionEnd - run post-session tasks and refresh memory bridge.
|
|
733
|
-
*
|
|
734
|
-
* T138: Refresh memory bridge after session ends.
|
|
735
|
-
* T144: Extract transcript observations via cross-provider adapter.
|
|
736
|
-
* T527: Removed duplicate observeBrain write — session data is already
|
|
737
|
-
* persisted in the sessions table.
|
|
738
|
-
*/
|
|
739
|
-
async function handleSessionEnd(projectRoot, payload) {
|
|
740
|
-
if (!process.env["VITEST"]) try {
|
|
741
|
-
const { gradeSession } = await import('./session-grade-BF4ZZtN_.js');
|
|
742
|
-
await gradeSession(payload.sessionId, projectRoot);
|
|
743
|
-
} catch {}
|
|
744
|
-
try {
|
|
745
|
-
const { loadConfig } = await import('./config2-F6PPIn7D.js');
|
|
746
|
-
if ((await loadConfig(projectRoot)).brain?.autoCapture) {
|
|
747
|
-
const { AdapterManager } = await import('./adapters2-CQ3PzoaK.js');
|
|
748
|
-
const hookProvider = AdapterManager.getInstance(projectRoot).getActive()?.hooks;
|
|
749
|
-
if (hookProvider && typeof hookProvider.getTranscript === "function") {
|
|
750
|
-
const transcript = await hookProvider.getTranscript(payload.sessionId, projectRoot);
|
|
751
|
-
if (transcript) {
|
|
752
|
-
const { extractFromTranscript } = await import('./auto-extract-B84La1Vs.js');
|
|
753
|
-
await extractFromTranscript(projectRoot, payload.sessionId, transcript);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
} catch {}
|
|
758
|
-
await maybeRefreshMemoryBridge(projectRoot);
|
|
759
|
-
}
|
|
760
|
-
/**
|
|
761
|
-
* Handle SessionEnd - snapshot SQLite databases to `.cleo/backups/sqlite/`.
|
|
762
|
-
*
|
|
763
|
-
* ADR-013 / T5158: `.cleo/tasks.db` and `.cleo/brain.db` are NOT tracked in
|
|
764
|
-
* project git, so we need an out-of-band recovery mechanism. This handler
|
|
765
|
-
* calls `vacuumIntoBackupAll` with `force: true` at every session end to
|
|
766
|
-
* guarantee a fresh point-in-time snapshot of both databases.
|
|
767
|
-
*
|
|
768
|
-
* Rotation (MAX_SNAPSHOTS = 10 per database) is handled inside
|
|
769
|
-
* `sqlite-backup.ts`. Failures here are non-fatal: a backup error must
|
|
770
|
-
* never block session end.
|
|
771
|
-
*
|
|
772
|
-
* The `vacuumIntoBackupAll` import is deferred to call time so tests that
|
|
773
|
-
* auto-load session-hooks (e.g. via `handlers/index.ts`) do not have to
|
|
774
|
-
* mock every transitive dependency of `sqlite-backup.ts` at hoisted
|
|
775
|
-
* `vi.mock` time.
|
|
776
|
-
*/
|
|
777
|
-
async function handleSessionEndBackup(projectRoot, _payload) {
|
|
778
|
-
try {
|
|
779
|
-
const { vacuumIntoBackupAll } = await import('./sqlite-backup-CFG1-b2e.js');
|
|
780
|
-
await vacuumIntoBackupAll({
|
|
781
|
-
cwd: projectRoot,
|
|
782
|
-
force: true
|
|
783
|
-
});
|
|
784
|
-
} catch {}
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Handle SessionEnd — fire-and-forget sleep-time memory consolidation.
|
|
788
|
-
*
|
|
789
|
-
* T549 Wave 3-E: Runs the full consolidation pipeline (dedup, quality recompute,
|
|
790
|
-
* tier promotion, contradiction detection, soft eviction, graph strengthening,
|
|
791
|
-
* summary generation) in the background after the session backup has completed.
|
|
792
|
-
*
|
|
793
|
-
* Uses setImmediate to yield control so the session end flow completes before
|
|
794
|
-
* consolidation begins. Consolidation errors are caught and logged to console.warn
|
|
795
|
-
* — they MUST NOT block session end or throw to callers.
|
|
796
|
-
*
|
|
797
|
-
* Priority 5 ensures this runs last (after backup at priority 10).
|
|
798
|
-
*/
|
|
799
|
-
async function handleSessionEndConsolidation(projectRoot, _payload) {
|
|
800
|
-
setImmediate(async () => {
|
|
801
|
-
try {
|
|
802
|
-
const { runConsolidation } = await import('./brain-lifecycle-BOOa876K.js');
|
|
803
|
-
await runConsolidation(projectRoot);
|
|
804
|
-
} catch (err) {
|
|
805
|
-
console.warn("[consolidation] Session-end consolidation failed:", err);
|
|
806
|
-
}
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
/**
|
|
810
|
-
* Handle SessionEnd — fire-and-forget LLM Observer compression.
|
|
811
|
-
*
|
|
812
|
-
* T740: GAP-6 fix — Observer was only triggered on task completion when
|
|
813
|
-
* observation count >= threshold (default 10). Sessions with < 10 observations
|
|
814
|
-
* never got compression. This hook runs Observer unconditionally at session end
|
|
815
|
-
* with a threshold override of 1, ensuring even short sessions get compressed.
|
|
816
|
-
*
|
|
817
|
-
* Priority 4.5 (between consolidation at 5 and reflector at 4) so Observer
|
|
818
|
-
* compresses the raw observations before Reflector synthesizes patterns/learnings
|
|
819
|
-
* from them. This matches the intended pipeline order.
|
|
820
|
-
*
|
|
821
|
-
* Uses setImmediate to yield control before the LLM call. Errors are caught
|
|
822
|
-
* and logged — they MUST NOT block session end or throw to callers.
|
|
823
|
-
*/
|
|
824
|
-
async function handleSessionEndObserver(projectRoot, payload) {
|
|
825
|
-
setImmediate(async () => {
|
|
826
|
-
try {
|
|
827
|
-
const { runObserver } = await import('./observer-reflector-BwNOuq1d.js');
|
|
828
|
-
await runObserver(projectRoot, payload.sessionId, { thresholdOverride: 1 });
|
|
829
|
-
} catch (err) {
|
|
830
|
-
console.warn("[observer] Session-end observer failed:", err);
|
|
831
|
-
}
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* Handle SessionEnd — fire-and-forget LLM reflector synthesis.
|
|
836
|
-
*
|
|
837
|
-
* T554: Runs the Reflector after the consolidation pass (priority 5) to
|
|
838
|
-
* synthesize session observations into durable patterns and learnings.
|
|
839
|
-
*
|
|
840
|
-
* Uses setImmediate to yield control before the LLM call. Errors are caught
|
|
841
|
-
* and logged — they MUST NOT block session end or throw to callers.
|
|
842
|
-
*
|
|
843
|
-
* Priority 4 ensures this runs after consolidation (priority 5).
|
|
844
|
-
*/
|
|
845
|
-
async function handleSessionEndReflector(projectRoot, payload) {
|
|
846
|
-
setImmediate(async () => {
|
|
847
|
-
try {
|
|
848
|
-
const { runReflector } = await import('./observer-reflector-BwNOuq1d.js');
|
|
849
|
-
await runReflector(projectRoot, payload.sessionId);
|
|
850
|
-
} catch (err) {
|
|
851
|
-
console.warn("[reflector] Session-end reflector failed:", err);
|
|
852
|
-
}
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* Handle SessionEnd — write a `transcript_pending_extraction` record to brain_observations.
|
|
857
|
-
*
|
|
858
|
-
* T732: Records the session JSONL path so the warm-tier extractor and
|
|
859
|
-
* `cleo transcript scan --pending` can locate queued sessions.
|
|
860
|
-
*
|
|
861
|
-
* The record is idempotent: re-running session end for the same session_id
|
|
862
|
-
* updates the timestamp but does not create a duplicate (content-hash dedup
|
|
863
|
-
* in observeBrain handles this automatically).
|
|
864
|
-
*
|
|
865
|
-
* Priority 3 — runs after reflector (priority 4) so it is the last step in
|
|
866
|
-
* the session-end pipeline.
|
|
867
|
-
*
|
|
868
|
-
* Uses setImmediate to yield so the session-end response reaches the CLI
|
|
869
|
-
* before the brain write occurs.
|
|
870
|
-
*/
|
|
871
|
-
async function handleSessionEndTranscriptSchedule(projectRoot, payload) {
|
|
872
|
-
setImmediate(async () => {
|
|
873
|
-
try {
|
|
874
|
-
const { findSessionTranscriptPath } = await import('./transcript-scanner-kJWhWmlg.js');
|
|
875
|
-
const filePath = await findSessionTranscriptPath(payload.sessionId);
|
|
876
|
-
if (!filePath) return;
|
|
877
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
878
|
-
await observeBrain(projectRoot, {
|
|
879
|
-
title: `transcript_pending_extraction:${payload.sessionId}`,
|
|
880
|
-
text: `Session ${payload.sessionId} transcript queued for warm-tier extraction. File: ${filePath}`,
|
|
881
|
-
type: "discovery",
|
|
882
|
-
sourceType: "agent",
|
|
883
|
-
sourceSessionId: payload.sessionId
|
|
884
|
-
});
|
|
885
|
-
} catch (err) {
|
|
886
|
-
console.warn("[transcript-schedule] Failed to queue transcript:", err);
|
|
887
|
-
}
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
/**
|
|
891
|
-
* Handle SessionEnd — append a session journal entry to `.cleo/session-journals/`.
|
|
892
|
-
*
|
|
893
|
-
* T1263 PSYCHE E6: Writes a `session_end` JSONL entry capturing session metadata
|
|
894
|
-
* and the compact result of `scanBrainNoise` (T1262 absorption).
|
|
895
|
-
*
|
|
896
|
-
* **MUST use synchronous `await`** — this hook runs at priority 2, immediately
|
|
897
|
-
* before process.exit. Using `setImmediate` here would silently drop the write.
|
|
898
|
-
*
|
|
899
|
-
* Runs at priority 2 — the last synchronous hook in the session-end pipeline,
|
|
900
|
-
* ensuring all prior work (backup, consolidation, observer, reflector, transcript)
|
|
901
|
-
* has been scheduled before the journal entry is written.
|
|
902
|
-
*/
|
|
903
|
-
async function handleSessionEndJournal(projectRoot, payload) {
|
|
904
|
-
try {
|
|
905
|
-
const { SESSION_JOURNAL_SCHEMA_VERSION } = await import('./dist3-23bsJhRw.js');
|
|
906
|
-
const { appendSessionJournalEntry } = await import('./session-journal-Bvey70Ur.js');
|
|
907
|
-
let doctorSummary;
|
|
908
|
-
try {
|
|
909
|
-
const { scanBrainNoise } = await import('./brain-doctor-Dc2WqVbs.js');
|
|
910
|
-
const scanResult = await scanBrainNoise(projectRoot);
|
|
911
|
-
doctorSummary = {
|
|
912
|
-
isClean: scanResult.isClean,
|
|
913
|
-
findingsCount: scanResult.findings.length,
|
|
914
|
-
patterns: scanResult.findings.map((f) => f.pattern),
|
|
915
|
-
totalScanned: scanResult.totalScanned
|
|
916
|
-
};
|
|
917
|
-
} catch {}
|
|
918
|
-
const agentIdentifier = process.env.CLEO_AGENT_ID ?? process.env.CLAUDE_CODE_AGENT_ID ?? void 0;
|
|
919
|
-
await appendSessionJournalEntry(projectRoot, {
|
|
920
|
-
schemaVersion: SESSION_JOURNAL_SCHEMA_VERSION,
|
|
921
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
922
|
-
sessionId: payload.sessionId,
|
|
923
|
-
eventType: "session_end",
|
|
924
|
-
agentIdentifier,
|
|
925
|
-
providerId: payload.providerId,
|
|
926
|
-
duration: payload.duration,
|
|
927
|
-
tasksCompleted: payload.tasksCompleted,
|
|
928
|
-
...doctorSummary !== void 0 ? { doctorSummary } : {}
|
|
929
|
-
});
|
|
930
|
-
} catch {}
|
|
931
|
-
}
|
|
932
|
-
hooks.register({
|
|
933
|
-
id: "brain-session-start",
|
|
934
|
-
event: "SessionStart",
|
|
935
|
-
handler: handleSessionStart,
|
|
936
|
-
priority: 100
|
|
937
|
-
});
|
|
938
|
-
hooks.register({
|
|
939
|
-
id: "brain-session-end",
|
|
940
|
-
event: "SessionEnd",
|
|
941
|
-
handler: handleSessionEnd,
|
|
942
|
-
priority: 100
|
|
943
|
-
});
|
|
944
|
-
hooks.register({
|
|
945
|
-
id: "backup-session-end",
|
|
946
|
-
event: "SessionEnd",
|
|
947
|
-
handler: handleSessionEndBackup,
|
|
948
|
-
priority: 10
|
|
949
|
-
});
|
|
950
|
-
hooks.register({
|
|
951
|
-
id: "consolidation-session-end",
|
|
952
|
-
event: "SessionEnd",
|
|
953
|
-
handler: handleSessionEndConsolidation,
|
|
954
|
-
priority: 5
|
|
955
|
-
});
|
|
956
|
-
hooks.register({
|
|
957
|
-
id: "observer-session-end",
|
|
958
|
-
event: "SessionEnd",
|
|
959
|
-
handler: handleSessionEndObserver,
|
|
960
|
-
priority: 4.5
|
|
961
|
-
});
|
|
962
|
-
hooks.register({
|
|
963
|
-
id: "reflector-session-end",
|
|
964
|
-
event: "SessionEnd",
|
|
965
|
-
handler: handleSessionEndReflector,
|
|
966
|
-
priority: 4
|
|
967
|
-
});
|
|
968
|
-
hooks.register({
|
|
969
|
-
id: "transcript-schedule-session-end",
|
|
970
|
-
event: "SessionEnd",
|
|
971
|
-
handler: handleSessionEndTranscriptSchedule,
|
|
972
|
-
priority: 3
|
|
973
|
-
});
|
|
974
|
-
hooks.register({
|
|
975
|
-
id: "journal-session-end",
|
|
976
|
-
event: "SessionEnd",
|
|
977
|
-
handler: handleSessionEndJournal,
|
|
978
|
-
priority: 2
|
|
979
|
-
});
|
|
980
|
-
//#endregion
|
|
981
|
-
//#region ../core/dist/hooks/handlers/task-hooks.js
|
|
982
|
-
/**
|
|
983
|
-
* Task Hook Handlers - Phase 2D of T5237
|
|
984
|
-
*
|
|
985
|
-
* Handlers that capture task lifecycle events to BRAIN via memory.observe.
|
|
986
|
-
* Auto-registers on module load.
|
|
987
|
-
*
|
|
988
|
-
* T138: Triggers memory bridge refresh after task completion.
|
|
989
|
-
* T554: Triggers LLM observer after task completion when observation count ≥ threshold.
|
|
990
|
-
*/
|
|
991
|
-
/**
|
|
992
|
-
* Handle PreToolUse (maps to task.start in CLEO, canonical: was onToolStart)
|
|
993
|
-
*/
|
|
994
|
-
async function handleToolStart(projectRoot, payload) {
|
|
995
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
996
|
-
try {
|
|
997
|
-
await observeBrain(projectRoot, {
|
|
998
|
-
text: `Started work on ${payload.taskId}: ${payload.taskTitle}`,
|
|
999
|
-
title: `Task start: ${payload.taskId}`,
|
|
1000
|
-
type: "change",
|
|
1001
|
-
sourceType: "agent"
|
|
1002
|
-
});
|
|
1003
|
-
} catch (err) {
|
|
1004
|
-
if (!isMissingBrainSchemaError(err) && !isNoProjectError(err)) throw err;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
/**
|
|
1008
|
-
* Handle PostToolUse (maps to task.complete in CLEO, canonical: was onToolComplete)
|
|
1009
|
-
*
|
|
1010
|
-
* T138: Refresh memory bridge after task completion.
|
|
1011
|
-
* T554: Fire-and-forget LLM observer when observation count ≥ threshold.
|
|
1012
|
-
*/
|
|
1013
|
-
async function handleToolComplete(projectRoot, payload) {
|
|
1014
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1015
|
-
try {
|
|
1016
|
-
await observeBrain(projectRoot, {
|
|
1017
|
-
text: `Task ${payload.taskId} completed with status: ${payload.status}`,
|
|
1018
|
-
title: `Task complete: ${payload.taskId}`,
|
|
1019
|
-
type: "change",
|
|
1020
|
-
sourceType: "agent"
|
|
1021
|
-
});
|
|
1022
|
-
} catch (err) {
|
|
1023
|
-
if (!isMissingBrainSchemaError(err) && !isNoProjectError(err)) throw err;
|
|
1024
|
-
}
|
|
1025
|
-
setImmediate(async () => {
|
|
1026
|
-
try {
|
|
1027
|
-
const { runObserver } = await import('./observer-reflector-BwNOuq1d.js');
|
|
1028
|
-
await runObserver(projectRoot);
|
|
1029
|
-
} catch {}
|
|
1030
|
-
});
|
|
1031
|
-
setImmediate(async () => {
|
|
1032
|
-
try {
|
|
1033
|
-
const { correlateOutcomes } = await import('./quality-feedback-CuCGEI6S.js');
|
|
1034
|
-
await correlateOutcomes(projectRoot);
|
|
1035
|
-
} catch {}
|
|
1036
|
-
});
|
|
1037
|
-
await maybeRefreshMemoryBridge(projectRoot);
|
|
1038
|
-
}
|
|
1039
|
-
hooks.register({
|
|
1040
|
-
id: "brain-tool-start",
|
|
1041
|
-
event: "PreToolUse",
|
|
1042
|
-
handler: handleToolStart,
|
|
1043
|
-
priority: 100
|
|
1044
|
-
});
|
|
1045
|
-
hooks.register({
|
|
1046
|
-
id: "brain-tool-complete",
|
|
1047
|
-
event: "PostToolUse",
|
|
1048
|
-
handler: handleToolComplete,
|
|
1049
|
-
priority: 100
|
|
1050
|
-
});
|
|
1051
|
-
//#endregion
|
|
1052
|
-
//#region ../core/dist/hooks/handlers/error-hooks.js
|
|
1053
|
-
/**
|
|
1054
|
-
* Error Hook Handlers - Wave 2 of T5237
|
|
1055
|
-
*
|
|
1056
|
-
* Captures operation errors to BRAIN via memory.observe.
|
|
1057
|
-
* Includes infinite-loop guard to prevent onError triggering onError.
|
|
1058
|
-
* Auto-registers on module load.
|
|
1059
|
-
*/
|
|
1060
|
-
/**
|
|
1061
|
-
* Handle PostToolUseFailure — capture operation errors to BRAIN.
|
|
1062
|
-
*
|
|
1063
|
-
* Includes an infinite-loop guard: if the payload carries a `_fromHook`
|
|
1064
|
-
* metadata marker the handler skips immediately to prevent the cycle
|
|
1065
|
-
* `PostToolUseFailure → observeBrain → PostToolUseFailure`. All
|
|
1066
|
-
* `observeBrain` errors are also silently suppressed for the same reason.
|
|
1067
|
-
*
|
|
1068
|
-
* Never throws. All brain-write errors are swallowed so error hooks
|
|
1069
|
-
* never block the original error path.
|
|
1070
|
-
*
|
|
1071
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1072
|
-
* @param payload - PostToolUseFailure event payload.
|
|
1073
|
-
*
|
|
1074
|
-
* @task T166
|
|
1075
|
-
* @epic T134
|
|
1076
|
-
*/
|
|
1077
|
-
async function handleError(projectRoot, payload) {
|
|
1078
|
-
if (payload.metadata?.["_fromHook"]) return;
|
|
1079
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1080
|
-
const domainOp = payload.domain && payload.operation ? `${payload.domain}.${payload.operation}` : "unknown";
|
|
1081
|
-
try {
|
|
1082
|
-
await observeBrain(projectRoot, {
|
|
1083
|
-
text: `Error in ${domainOp}: ${payload.message}\nCode: ${payload.errorCode}${payload.gateway ? `\nGateway: ${payload.gateway}` : ""}`,
|
|
1084
|
-
title: `Error: ${domainOp}`,
|
|
1085
|
-
type: "discovery",
|
|
1086
|
-
sourceType: "agent"
|
|
1087
|
-
});
|
|
1088
|
-
} catch (_err) {}
|
|
1089
|
-
}
|
|
1090
|
-
hooks.register({
|
|
1091
|
-
id: "brain-error",
|
|
1092
|
-
event: "PostToolUseFailure",
|
|
1093
|
-
handler: handleError,
|
|
1094
|
-
priority: 100
|
|
1095
|
-
});
|
|
1096
|
-
//#endregion
|
|
1097
|
-
//#region ../core/dist/hooks/handlers/file-hooks.js
|
|
1098
|
-
/**
|
|
1099
|
-
* File Change Hook Handlers - Wave 2 of T5237
|
|
1100
|
-
*
|
|
1101
|
-
* Captures file change events to BRAIN via memory.observe.
|
|
1102
|
-
* Includes 5-second dedup and path-based filtering to avoid noisy writes.
|
|
1103
|
-
* Auto-registers on module load.
|
|
1104
|
-
*
|
|
1105
|
-
* Disabled by default. Enable via:
|
|
1106
|
-
* - Config: brain.captureFiles = true (checked first)
|
|
1107
|
-
* - Env: CLEO_BRAIN_CAPTURE_FILES=true (overrides config)
|
|
1108
|
-
*/
|
|
1109
|
-
/** 5-second dedup map: filePath -> last dispatch timestamp */
|
|
1110
|
-
var recentWrites = /* @__PURE__ */ new Map();
|
|
1111
|
-
var DEDUP_INTERVAL_MS = 5e3;
|
|
1112
|
-
/** Path patterns to exclude from brain observations (internal/noisy files). */
|
|
1113
|
-
var SKIP_PATTERNS = [
|
|
1114
|
-
/\.cleo\//,
|
|
1115
|
-
/\.cleo\\/,
|
|
1116
|
-
/\/\.temp\//,
|
|
1117
|
-
/cleo-test-/,
|
|
1118
|
-
/cleo-edge-/,
|
|
1119
|
-
/node_modules\//,
|
|
1120
|
-
/\.git\//,
|
|
1121
|
-
/dist\//
|
|
1122
|
-
];
|
|
1123
|
-
/** Check whether a relative path should be skipped. */
|
|
1124
|
-
function shouldSkipPath(relativePath) {
|
|
1125
|
-
return SKIP_PATTERNS.some((pattern) => pattern.test(relativePath));
|
|
1126
|
-
}
|
|
1127
|
-
/**
|
|
1128
|
-
* Check whether file-change capture is enabled.
|
|
1129
|
-
*
|
|
1130
|
-
* Resolution order (first truthy wins):
|
|
1131
|
-
* 1. CLEO_BRAIN_CAPTURE_FILES env var (explicit override)
|
|
1132
|
-
* 2. brain.captureFiles project config value
|
|
1133
|
-
*
|
|
1134
|
-
* Defaults to false when neither is set.
|
|
1135
|
-
*/
|
|
1136
|
-
async function isFileCaptureEnabled(projectRoot) {
|
|
1137
|
-
const envOverride = process.env["CLEO_BRAIN_CAPTURE_FILES"];
|
|
1138
|
-
if (envOverride !== void 0) return envOverride === "true";
|
|
1139
|
-
try {
|
|
1140
|
-
const { loadConfig } = await import('./config2-F6PPIn7D.js');
|
|
1141
|
-
return (await loadConfig(projectRoot)).brain?.captureFiles ?? false;
|
|
1142
|
-
} catch {
|
|
1143
|
-
return false;
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
/**
|
|
1147
|
-
* Handle Notification (file-change variant) - capture file changes to BRAIN
|
|
1148
|
-
*
|
|
1149
|
-
* Gated behind brain.captureFiles config or CLEO_BRAIN_CAPTURE_FILES env var.
|
|
1150
|
-
* Env var takes precedence over config for backward compatibility.
|
|
1151
|
-
* Deduplicates rapid writes to the same file within a 5-second window.
|
|
1152
|
-
* Filters out .cleo/ internal files and test temp directories.
|
|
1153
|
-
* Converts absolute paths to project-relative paths.
|
|
1154
|
-
*/
|
|
1155
|
-
async function handleFileChange(projectRoot, payload) {
|
|
1156
|
-
if (!payload.filePath || !payload.changeType) return;
|
|
1157
|
-
if (!await isFileCaptureEnabled(projectRoot)) return;
|
|
1158
|
-
const now = Date.now();
|
|
1159
|
-
const lastWrite = recentWrites.get(payload.filePath);
|
|
1160
|
-
if (lastWrite && now - lastWrite < DEDUP_INTERVAL_MS) return;
|
|
1161
|
-
recentWrites.set(payload.filePath, now);
|
|
1162
|
-
const relativePath = (isAbsolute(payload.filePath) ? relative(projectRoot, payload.filePath) : payload.filePath).replaceAll("\\", "/");
|
|
1163
|
-
if (shouldSkipPath(relativePath)) return;
|
|
1164
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1165
|
-
try {
|
|
1166
|
-
await observeBrain(projectRoot, {
|
|
1167
|
-
text: `File ${payload.changeType}: ${relativePath}${payload.sizeBytes != null ? ` (${payload.sizeBytes} bytes)` : ""}`,
|
|
1168
|
-
title: `File changed: ${relativePath}`,
|
|
1169
|
-
type: "change",
|
|
1170
|
-
sourceType: "agent"
|
|
1171
|
-
});
|
|
1172
|
-
} catch (err) {
|
|
1173
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
hooks.register({
|
|
1177
|
-
id: "brain-file-change",
|
|
1178
|
-
event: "Notification",
|
|
1179
|
-
handler: handleFileChange,
|
|
1180
|
-
priority: 100
|
|
1181
|
-
});
|
|
1182
|
-
//#endregion
|
|
1183
|
-
//#region ../core/dist/hooks/handlers/notification-hooks.js
|
|
1184
|
-
/**
|
|
1185
|
-
* System Notification Hook Handler
|
|
1186
|
-
*
|
|
1187
|
-
* Captures message-bearing system notifications as BRAIN observations.
|
|
1188
|
-
* File-change notifications (filePath + changeType) are handled by
|
|
1189
|
-
* file-hooks.ts; this module only handles Notification payloads with
|
|
1190
|
-
* a `message` field.
|
|
1191
|
-
*
|
|
1192
|
-
* Gated behind brain.autoCapture config. Never throws.
|
|
1193
|
-
* Auto-registers on module load.
|
|
1194
|
-
*
|
|
1195
|
-
* @task T166
|
|
1196
|
-
*/
|
|
1197
|
-
/**
|
|
1198
|
-
* Handle Notification — capture system notifications as BRAIN observations.
|
|
1199
|
-
*
|
|
1200
|
-
* Only fires for Notification payloads that carry a message field (i.e. system
|
|
1201
|
-
* notifications). File-change notifications (filePath + changeType) are
|
|
1202
|
-
* handled exclusively by file-hooks.ts and are skipped here to avoid
|
|
1203
|
-
* double-capture.
|
|
1204
|
-
*
|
|
1205
|
-
* Gated behind brain.autoCapture config. Never throws.
|
|
1206
|
-
*
|
|
1207
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1208
|
-
* @param payload - Notification event payload.
|
|
1209
|
-
*
|
|
1210
|
-
* @task T166
|
|
1211
|
-
*/
|
|
1212
|
-
async function handleSystemNotification(projectRoot, payload) {
|
|
1213
|
-
if (payload.filePath || payload.changeType) return;
|
|
1214
|
-
if (!payload.message) return;
|
|
1215
|
-
if (!await isAutoCaptureEnabled(projectRoot)) return;
|
|
1216
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1217
|
-
try {
|
|
1218
|
-
await observeBrain(projectRoot, {
|
|
1219
|
-
text: `System notification: ${payload.message}`,
|
|
1220
|
-
title: `Notification: ${payload.message.slice(0, 60)}`,
|
|
1221
|
-
type: "discovery",
|
|
1222
|
-
sourceSessionId: payload.sessionId,
|
|
1223
|
-
sourceType: "agent"
|
|
1224
|
-
});
|
|
1225
|
-
} catch (err) {
|
|
1226
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
hooks.register({
|
|
1230
|
-
id: "brain-system-notification",
|
|
1231
|
-
event: "Notification",
|
|
1232
|
-
handler: handleSystemNotification,
|
|
1233
|
-
priority: 90
|
|
1234
|
-
});
|
|
1235
|
-
//#endregion
|
|
1236
|
-
//#region ../core/dist/hooks/handlers/work-capture-hooks.js
|
|
1237
|
-
/**
|
|
1238
|
-
* Active-Work Capture Hook Handlers
|
|
1239
|
-
*
|
|
1240
|
-
* Captures dispatch mutation events to BRAIN during active work, closing
|
|
1241
|
-
* the gap between lifecycle-only capture (session end, task complete) and
|
|
1242
|
-
* continuous capture. Only WRITE operations that represent meaningful work
|
|
1243
|
-
* are captured — reads and operations already handled by lifecycle hooks
|
|
1244
|
-
* are skipped to avoid flooding brain.db.
|
|
1245
|
-
*
|
|
1246
|
-
* Disabled by default. Enable via:
|
|
1247
|
-
* - Config: brain.captureWork = true (checked first)
|
|
1248
|
-
* - Env: CLEO_BRAIN_CAPTURE_WORK=true (overrides config)
|
|
1249
|
-
*
|
|
1250
|
-
* Auto-registers on module load.
|
|
1251
|
-
*
|
|
1252
|
-
* @task T142
|
|
1253
|
-
*/
|
|
1254
|
-
/**
|
|
1255
|
-
* Check whether active-work capture is enabled.
|
|
1256
|
-
*
|
|
1257
|
-
* Resolution order (first truthy wins):
|
|
1258
|
-
* 1. CLEO_BRAIN_CAPTURE_WORK env var (explicit override)
|
|
1259
|
-
* 2. brain.captureWork project config value
|
|
1260
|
-
*
|
|
1261
|
-
* Defaults to false when neither is set.
|
|
1262
|
-
*/
|
|
1263
|
-
async function isWorkCaptureEnabled(projectRoot) {
|
|
1264
|
-
const envOverride = process.env["CLEO_BRAIN_CAPTURE_WORK"];
|
|
1265
|
-
if (envOverride !== void 0) return envOverride === "true";
|
|
1266
|
-
try {
|
|
1267
|
-
const { loadConfig } = await import('./config2-F6PPIn7D.js');
|
|
1268
|
-
return (await loadConfig(projectRoot)).brain?.captureWork ?? false;
|
|
1269
|
-
} catch {
|
|
1270
|
-
return false;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
/**
|
|
1274
|
-
* Mutations that represent novel work not already captured by lifecycle hooks.
|
|
1275
|
-
*
|
|
1276
|
-
* Excluded (already captured elsewhere):
|
|
1277
|
-
* - tasks.complete → task-hooks.ts (PostToolUse)
|
|
1278
|
-
* - session.start → session-hooks.ts (SessionStart)
|
|
1279
|
-
* - session.end → session-hooks.ts (SessionEnd)
|
|
1280
|
-
* - memory.brain.observe → observeBrain itself writes to brain; self-loop
|
|
1281
|
-
*
|
|
1282
|
-
* All query gateway operations are excluded by the gateway check before
|
|
1283
|
-
* this set is consulted.
|
|
1284
|
-
*/
|
|
1285
|
-
var CAPTURE_OPERATIONS = new Set([
|
|
1286
|
-
"tasks.add",
|
|
1287
|
-
"tasks.update",
|
|
1288
|
-
"tasks.move",
|
|
1289
|
-
"tasks.link",
|
|
1290
|
-
"tasks.unlink",
|
|
1291
|
-
"tasks.label",
|
|
1292
|
-
"tasks.unlabel",
|
|
1293
|
-
"tasks.note"
|
|
1294
|
-
]);
|
|
1295
|
-
/**
|
|
1296
|
-
* Determine whether a mutate operation should be captured.
|
|
1297
|
-
*
|
|
1298
|
-
* Only `mutate` gateway operations in CAPTURE_OPERATIONS are captured.
|
|
1299
|
-
* All `query` gateway calls are skipped (reads produce no novel work).
|
|
1300
|
-
*
|
|
1301
|
-
* @param gateway - 'query' or 'mutate'
|
|
1302
|
-
* @param domain - e.g. 'tasks'
|
|
1303
|
-
* @param operation - e.g. 'add'
|
|
1304
|
-
*/
|
|
1305
|
-
function shouldCapture(gateway, domain, operation) {
|
|
1306
|
-
if (gateway !== "mutate") return false;
|
|
1307
|
-
const key = `${domain}.${operation}`;
|
|
1308
|
-
return CAPTURE_OPERATIONS.has(key);
|
|
1309
|
-
}
|
|
1310
|
-
/**
|
|
1311
|
-
* Handle PromptSubmit — log incoming mutation intents to BRAIN.
|
|
1312
|
-
*
|
|
1313
|
-
* Only fires for mutate operations in CAPTURE_OPERATIONS.
|
|
1314
|
-
* Gated behind brain.captureWork config (or CLEO_BRAIN_CAPTURE_WORK env).
|
|
1315
|
-
*
|
|
1316
|
-
* @param projectRoot - Absolute path to the project root
|
|
1317
|
-
* @param payload - PromptSubmit event payload
|
|
1318
|
-
*/
|
|
1319
|
-
async function handleWorkPromptSubmit(projectRoot, payload) {
|
|
1320
|
-
if (!shouldCapture(payload.gateway, payload.domain, payload.operation)) return;
|
|
1321
|
-
if (!await isWorkCaptureEnabled(projectRoot)) return;
|
|
1322
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1323
|
-
try {
|
|
1324
|
-
await observeBrain(projectRoot, {
|
|
1325
|
-
text: `Dispatch intent: ${payload.gateway}:${payload.domain}.${payload.operation}${payload.source ? ` (from ${payload.source})` : ""}`,
|
|
1326
|
-
title: `Work intent: ${payload.domain}.${payload.operation}`,
|
|
1327
|
-
type: "discovery",
|
|
1328
|
-
sourceType: "agent"
|
|
1329
|
-
});
|
|
1330
|
-
} catch (err) {
|
|
1331
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
/**
|
|
1335
|
-
* Handle ResponseComplete — capture completed mutations to BRAIN.
|
|
1336
|
-
*
|
|
1337
|
-
* Only fires for successful mutate operations in CAPTURE_OPERATIONS.
|
|
1338
|
-
* Failures are skipped — the intent was already captured by handleWorkPromptSubmit.
|
|
1339
|
-
* Gated behind brain.captureWork config (or CLEO_BRAIN_CAPTURE_WORK env).
|
|
1340
|
-
*
|
|
1341
|
-
* @param projectRoot - Absolute path to the project root
|
|
1342
|
-
* @param payload - ResponseComplete event payload
|
|
1343
|
-
*/
|
|
1344
|
-
async function handleWorkResponseComplete(projectRoot, payload) {
|
|
1345
|
-
if (!shouldCapture(payload.gateway, payload.domain, payload.operation)) return;
|
|
1346
|
-
if (!payload.success) return;
|
|
1347
|
-
if (!await isWorkCaptureEnabled(projectRoot)) return;
|
|
1348
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1349
|
-
try {
|
|
1350
|
-
const durationNote = payload.durationMs != null ? ` (${payload.durationMs}ms)` : "";
|
|
1351
|
-
await observeBrain(projectRoot, {
|
|
1352
|
-
text: `Dispatch complete: ${payload.gateway}:${payload.domain}.${payload.operation}${durationNote}`,
|
|
1353
|
-
title: `Work done: ${payload.domain}.${payload.operation}`,
|
|
1354
|
-
type: "change",
|
|
1355
|
-
sourceType: "agent"
|
|
1356
|
-
});
|
|
1357
|
-
} catch (err) {
|
|
1358
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
hooks.register({
|
|
1362
|
-
id: "work-capture-prompt-submit",
|
|
1363
|
-
event: "PromptSubmit",
|
|
1364
|
-
handler: handleWorkPromptSubmit,
|
|
1365
|
-
priority: 90
|
|
1366
|
-
});
|
|
1367
|
-
hooks.register({
|
|
1368
|
-
id: "work-capture-response-complete",
|
|
1369
|
-
event: "ResponseComplete",
|
|
1370
|
-
handler: handleWorkResponseComplete,
|
|
1371
|
-
priority: 90
|
|
1372
|
-
});
|
|
1373
|
-
//#endregion
|
|
1374
|
-
//#region ../core/dist/hooks/handlers/agent-hooks.js
|
|
1375
|
-
/**
|
|
1376
|
-
* Agent (Subagent) Lifecycle Hook Handlers
|
|
1377
|
-
*
|
|
1378
|
-
* Captures SubagentStart and SubagentStop events to BRAIN so that
|
|
1379
|
-
* multi-agent orchestration runs leave an auditable trail of which
|
|
1380
|
-
* subagents were spawned, what tasks they were assigned, and how
|
|
1381
|
-
* they completed.
|
|
1382
|
-
*
|
|
1383
|
-
* Gated behind brain.autoCapture config. Never throws — all errors are
|
|
1384
|
-
* swallowed so that brain capture never blocks agent orchestration.
|
|
1385
|
-
*
|
|
1386
|
-
* Auto-registers on module load.
|
|
1387
|
-
*
|
|
1388
|
-
* @task T166
|
|
1389
|
-
* @epic T134
|
|
1390
|
-
*/
|
|
1391
|
-
/**
|
|
1392
|
-
* Handle SubagentStart — log subagent spawn as a BRAIN observation.
|
|
1393
|
-
*
|
|
1394
|
-
* Records the agent ID, role, and task assignment so orchestrators can
|
|
1395
|
-
* trace which agents were active in a given session.
|
|
1396
|
-
*
|
|
1397
|
-
* Gated behind brain.autoCapture config. Never throws.
|
|
1398
|
-
*
|
|
1399
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1400
|
-
* @param payload - SubagentStart event payload.
|
|
1401
|
-
*
|
|
1402
|
-
* @task T166
|
|
1403
|
-
* @epic T134
|
|
1404
|
-
*/
|
|
1405
|
-
async function handleSubagentStart(projectRoot, payload) {
|
|
1406
|
-
if (!await isAutoCaptureEnabled(projectRoot)) return;
|
|
1407
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1408
|
-
const rolePart = payload.role ? ` role=${payload.role}` : "";
|
|
1409
|
-
const taskPart = payload.taskId ? ` task=${payload.taskId}` : "";
|
|
1410
|
-
try {
|
|
1411
|
-
await observeBrain(projectRoot, {
|
|
1412
|
-
text: `Subagent spawned: ${payload.agentId}${rolePart}${taskPart}`,
|
|
1413
|
-
title: `Subagent start: ${payload.agentId}`,
|
|
1414
|
-
type: "discovery",
|
|
1415
|
-
sourceSessionId: payload.sessionId,
|
|
1416
|
-
sourceType: "agent"
|
|
1417
|
-
});
|
|
1418
|
-
} catch (err) {
|
|
1419
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
/**
|
|
1423
|
-
* Handle SubagentStop — log subagent completion result as a BRAIN observation.
|
|
1424
|
-
*
|
|
1425
|
-
* Records the agent ID, completion status, assigned task, and optional
|
|
1426
|
-
* summary reference so orchestrators can audit subagent outcomes.
|
|
1427
|
-
*
|
|
1428
|
-
* Gated behind brain.autoCapture config. Never throws.
|
|
1429
|
-
*
|
|
1430
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1431
|
-
* @param payload - SubagentStop event payload.
|
|
1432
|
-
*
|
|
1433
|
-
* @task T166
|
|
1434
|
-
* @epic T134
|
|
1435
|
-
*/
|
|
1436
|
-
async function handleSubagentStop(projectRoot, payload) {
|
|
1437
|
-
if (!await isAutoCaptureEnabled(projectRoot)) return;
|
|
1438
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1439
|
-
const statusPart = payload.status ? ` status=${payload.status}` : "";
|
|
1440
|
-
const taskPart = payload.taskId ? ` task=${payload.taskId}` : "";
|
|
1441
|
-
const summaryPart = payload.summary ? `\nSummary: ${payload.summary}` : "";
|
|
1442
|
-
try {
|
|
1443
|
-
await observeBrain(projectRoot, {
|
|
1444
|
-
text: `Subagent completed: ${payload.agentId}${statusPart}${taskPart}${summaryPart}`,
|
|
1445
|
-
title: `Subagent stop: ${payload.agentId}`,
|
|
1446
|
-
type: "change",
|
|
1447
|
-
sourceSessionId: payload.sessionId,
|
|
1448
|
-
sourceType: "agent"
|
|
1449
|
-
});
|
|
1450
|
-
} catch (err) {
|
|
1451
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
hooks.register({
|
|
1455
|
-
id: "brain-subagent-start",
|
|
1456
|
-
event: "SubagentStart",
|
|
1457
|
-
handler: handleSubagentStart,
|
|
1458
|
-
priority: 100
|
|
1459
|
-
});
|
|
1460
|
-
hooks.register({
|
|
1461
|
-
id: "brain-subagent-stop",
|
|
1462
|
-
event: "SubagentStop",
|
|
1463
|
-
handler: handleSubagentStop,
|
|
1464
|
-
priority: 100
|
|
1465
|
-
});
|
|
1466
|
-
//#endregion
|
|
1467
|
-
//#region ../core/dist/hooks/handlers/context-hooks.js
|
|
1468
|
-
/**
|
|
1469
|
-
* Context Compaction Hook Handlers
|
|
1470
|
-
*
|
|
1471
|
-
* Captures PreCompact and PostCompact events to BRAIN so that agents
|
|
1472
|
-
* can later observe when context compactions occurred and what state
|
|
1473
|
-
* preceded them. This is especially useful for long sessions where
|
|
1474
|
-
* context is compacted multiple times.
|
|
1475
|
-
*
|
|
1476
|
-
* PreCompact saves a session context snapshot before compaction begins.
|
|
1477
|
-
* PostCompact records that compaction occurred and the resulting token counts.
|
|
1478
|
-
*
|
|
1479
|
-
* Gated behind brain.autoCapture config. Never throws — all errors are
|
|
1480
|
-
* swallowed so brain capture never blocks context compaction.
|
|
1481
|
-
*
|
|
1482
|
-
* Auto-registers on module load.
|
|
1483
|
-
*
|
|
1484
|
-
* @task T166
|
|
1485
|
-
* @epic T134
|
|
1486
|
-
*/
|
|
1487
|
-
/**
|
|
1488
|
-
* Handle PreCompact — snapshot current session memory context to BRAIN.
|
|
1489
|
-
*
|
|
1490
|
-
* Fires immediately before context compaction begins. Records the token
|
|
1491
|
-
* count and compaction reason so the brain retains context about what
|
|
1492
|
-
* was in scope before compaction.
|
|
1493
|
-
*
|
|
1494
|
-
* Gated behind brain.autoCapture config. Never throws.
|
|
1495
|
-
*
|
|
1496
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1497
|
-
* @param payload - PreCompact event payload.
|
|
1498
|
-
*
|
|
1499
|
-
* @task T166
|
|
1500
|
-
* @epic T134
|
|
1501
|
-
*/
|
|
1502
|
-
async function handlePreCompact(projectRoot, payload) {
|
|
1503
|
-
if (!await isAutoCaptureEnabled(projectRoot)) return;
|
|
1504
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1505
|
-
const tokensPart = payload.tokensBefore != null ? ` (~${payload.tokensBefore.toLocaleString()} tokens)` : "";
|
|
1506
|
-
const reasonPart = payload.reason ? ` Reason: ${payload.reason}` : "";
|
|
1507
|
-
try {
|
|
1508
|
-
await observeBrain(projectRoot, {
|
|
1509
|
-
text: `Context compaction about to begin${tokensPart}.${reasonPart}`,
|
|
1510
|
-
title: "Pre-compaction context snapshot",
|
|
1511
|
-
type: "discovery",
|
|
1512
|
-
sourceSessionId: payload.sessionId,
|
|
1513
|
-
sourceType: "agent"
|
|
1514
|
-
});
|
|
1515
|
-
} catch (err) {
|
|
1516
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
/**
|
|
1520
|
-
* Handle PostCompact — record compaction completion to BRAIN.
|
|
1521
|
-
*
|
|
1522
|
-
* Fires immediately after context compaction completes. Records the
|
|
1523
|
-
* before/after token counts so agents can correlate observations made
|
|
1524
|
-
* before compaction with those made after.
|
|
1525
|
-
*
|
|
1526
|
-
* Gated behind brain.autoCapture config. Never throws.
|
|
1527
|
-
*
|
|
1528
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1529
|
-
* @param payload - PostCompact event payload.
|
|
1530
|
-
*
|
|
1531
|
-
* @task T166
|
|
1532
|
-
* @epic T134
|
|
1533
|
-
*/
|
|
1534
|
-
async function handlePostCompact(projectRoot, payload) {
|
|
1535
|
-
if (!await isAutoCaptureEnabled(projectRoot)) return;
|
|
1536
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1537
|
-
const statusPart = payload.success ? "succeeded" : "failed";
|
|
1538
|
-
const beforePart = payload.tokensBefore != null ? ` before=${payload.tokensBefore.toLocaleString()}` : "";
|
|
1539
|
-
const afterPart = payload.tokensAfter != null ? ` after=${payload.tokensAfter.toLocaleString()}` : "";
|
|
1540
|
-
try {
|
|
1541
|
-
await observeBrain(projectRoot, {
|
|
1542
|
-
text: `Context compaction ${statusPart}${beforePart}${afterPart}`,
|
|
1543
|
-
title: "Post-compaction record",
|
|
1544
|
-
type: "change",
|
|
1545
|
-
sourceSessionId: payload.sessionId,
|
|
1546
|
-
sourceType: "agent"
|
|
1547
|
-
});
|
|
1548
|
-
} catch (err) {
|
|
1549
|
-
if (!isMissingBrainSchemaError(err)) throw err;
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
hooks.register({
|
|
1553
|
-
id: "brain-pre-compact",
|
|
1554
|
-
event: "PreCompact",
|
|
1555
|
-
handler: handlePreCompact,
|
|
1556
|
-
priority: 100
|
|
1557
|
-
});
|
|
1558
|
-
hooks.register({
|
|
1559
|
-
id: "brain-post-compact",
|
|
1560
|
-
event: "PostCompact",
|
|
1561
|
-
handler: handlePostCompact,
|
|
1562
|
-
priority: 100
|
|
1563
|
-
});
|
|
1564
|
-
//#endregion
|
|
1565
|
-
//#region ../core/dist/hooks/handlers/watchdog-hooks.js
|
|
1566
|
-
/**
|
|
1567
|
-
* Watchdog Scheduler Hook Handlers
|
|
1568
|
-
*
|
|
1569
|
-
* Starts a periodic health-check timer when a session begins and stops it when
|
|
1570
|
-
* the session ends. One watchdog per project root, enforced by a module-level
|
|
1571
|
-
* Map keyed on the resolved project root.
|
|
1572
|
-
*
|
|
1573
|
-
* Each 60-second tick:
|
|
1574
|
-
* 1. Detects agents with a stale heartbeat (> STALE_THRESHOLD_MS)
|
|
1575
|
-
* 2. Records each crash as a learning event in brain.db
|
|
1576
|
-
* 3. Attempts recovery (status reset to 'starting') for all crashed agents
|
|
1577
|
-
* 4. Fires the `onPatrol` hook for observability
|
|
1578
|
-
*
|
|
1579
|
-
* Best-effort contract: the watchdog NEVER crashes or throws. Any tick failure
|
|
1580
|
-
* is swallowed so the timer continues. Any error in the start/stop handlers is
|
|
1581
|
-
* also swallowed so it never blocks session operations.
|
|
1582
|
-
*
|
|
1583
|
-
* Gated behind `brain.autoCapture` config — the watchdog does NOT start unless
|
|
1584
|
-
* auto-capture is enabled.
|
|
1585
|
-
*
|
|
1586
|
-
* Auto-registers on module load.
|
|
1587
|
-
*
|
|
1588
|
-
* @task T549
|
|
1589
|
-
* @epic T5149
|
|
1590
|
-
*/
|
|
1591
|
-
/** One active timer per project root (resolved path). */
|
|
1592
|
-
var activeWatchdogs = /* @__PURE__ */ new Map();
|
|
1593
|
-
/** Interval between watchdog ticks in milliseconds. */
|
|
1594
|
-
var WATCHDOG_INTERVAL_MS = 6e4;
|
|
1595
|
-
/**
|
|
1596
|
-
* Execute one watchdog patrol tick.
|
|
1597
|
-
*
|
|
1598
|
-
* Steps:
|
|
1599
|
-
* 1. detectCrashedAgents — find and mark stale agents as 'crashed'
|
|
1600
|
-
* 2. processAgentLifecycleEvent — write failure events to brain.db for each
|
|
1601
|
-
* 3. recoverCrashedAgents — reset crashed agents to 'starting'
|
|
1602
|
-
* 4. hooks.dispatch('onPatrol') — emit observability event
|
|
1603
|
-
*
|
|
1604
|
-
* Any thrown error is caught and logged as a warning; the timer continues.
|
|
1605
|
-
*
|
|
1606
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1607
|
-
*/
|
|
1608
|
-
async function runWatchdogTick(projectRoot) {
|
|
1609
|
-
try {
|
|
1610
|
-
const { detectCrashedAgents, STALE_THRESHOLD_MS } = await import('./health-monitor-FepUZN1m.js');
|
|
1611
|
-
const { recoverCrashedAgents } = await import('./retry-B3oEKYpp.js');
|
|
1612
|
-
const { processAgentLifecycleEvent } = await import('./execution-learning-BVCw7Plq.js');
|
|
1613
|
-
const crashed = await detectCrashedAgents(STALE_THRESHOLD_MS, projectRoot);
|
|
1614
|
-
for (const agent of crashed) try {
|
|
1615
|
-
await processAgentLifecycleEvent({
|
|
1616
|
-
agentId: agent.id,
|
|
1617
|
-
agentType: agent.agentType ?? "custom",
|
|
1618
|
-
taskId: agent.taskId ?? "unknown",
|
|
1619
|
-
taskType: "unknown",
|
|
1620
|
-
outcome: "failure",
|
|
1621
|
-
errorMessage: "Heartbeat timeout — agent presumed crashed",
|
|
1622
|
-
errorType: "retriable",
|
|
1623
|
-
sessionId: agent.sessionId ?? void 0
|
|
1624
|
-
}, projectRoot);
|
|
1625
|
-
} catch (err) {
|
|
1626
|
-
if (!isMissingBrainSchemaError(err)) console.warn("[watchdog] Failed to record agent crash event:", err);
|
|
1627
|
-
}
|
|
1628
|
-
if (crashed.length > 0) await recoverCrashedAgents(STALE_THRESHOLD_MS, projectRoot);
|
|
1629
|
-
const patrolPayload = {
|
|
1630
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1631
|
-
watcherId: "health-watchdog",
|
|
1632
|
-
patrolType: "health",
|
|
1633
|
-
scope: `crashed=${crashed.length}`
|
|
1634
|
-
};
|
|
1635
|
-
await hooks.dispatch("onPatrol", projectRoot, patrolPayload);
|
|
1636
|
-
} catch (err) {
|
|
1637
|
-
console.warn("[watchdog] Tick failed:", err);
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
|
-
/**
|
|
1641
|
-
* Handle SessionStart — start the watchdog timer for this project root.
|
|
1642
|
-
*
|
|
1643
|
-
* Idempotent: if a watchdog is already running for this root (e.g. a second
|
|
1644
|
-
* session in the same process), the existing timer is reused.
|
|
1645
|
-
*
|
|
1646
|
-
* Gated behind `brain.autoCapture` — watchdog does not start unless auto-capture
|
|
1647
|
-
* is enabled. This aligns with all other brain-capture hooks.
|
|
1648
|
-
*
|
|
1649
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1650
|
-
* @param _payload - SessionStart payload (unused).
|
|
1651
|
-
*/
|
|
1652
|
-
async function handleWatchdogStart(projectRoot, _payload) {
|
|
1653
|
-
try {
|
|
1654
|
-
if (!await isAutoCaptureEnabled(projectRoot)) return;
|
|
1655
|
-
if (activeWatchdogs.has(projectRoot)) return;
|
|
1656
|
-
const timer = setInterval(() => {
|
|
1657
|
-
runWatchdogTick(projectRoot);
|
|
1658
|
-
}, WATCHDOG_INTERVAL_MS);
|
|
1659
|
-
activeWatchdogs.set(projectRoot, timer);
|
|
1660
|
-
} catch {}
|
|
1661
|
-
}
|
|
1662
|
-
/**
|
|
1663
|
-
* Handle SessionEnd — stop the watchdog timer for this project root.
|
|
1664
|
-
*
|
|
1665
|
-
* Safe to call when no watchdog is running (no-op).
|
|
1666
|
-
*
|
|
1667
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1668
|
-
* @param _payload - SessionEnd payload (unused).
|
|
1669
|
-
*/
|
|
1670
|
-
async function handleWatchdogStop(projectRoot, _payload) {
|
|
1671
|
-
try {
|
|
1672
|
-
const timer = activeWatchdogs.get(projectRoot);
|
|
1673
|
-
if (timer) {
|
|
1674
|
-
clearInterval(timer);
|
|
1675
|
-
activeWatchdogs.delete(projectRoot);
|
|
1676
|
-
}
|
|
1677
|
-
} catch {}
|
|
1678
|
-
}
|
|
1679
|
-
hooks.register({
|
|
1680
|
-
id: "watchdog-session-start",
|
|
1681
|
-
event: "SessionStart",
|
|
1682
|
-
handler: handleWatchdogStart,
|
|
1683
|
-
priority: 50
|
|
1684
|
-
});
|
|
1685
|
-
hooks.register({
|
|
1686
|
-
id: "watchdog-session-end",
|
|
1687
|
-
event: "SessionEnd",
|
|
1688
|
-
handler: handleWatchdogStop,
|
|
1689
|
-
priority: 50
|
|
1690
|
-
});
|
|
1691
|
-
//#endregion
|
|
1692
|
-
//#region ../core/dist/hooks/handlers/intelligence-hooks.js
|
|
1693
|
-
/**
|
|
1694
|
-
* Intelligence Hook Handlers — Wave 5-D/E of T549
|
|
1695
|
-
*
|
|
1696
|
-
* Best-effort intelligence side-effects wired into task lifecycle events.
|
|
1697
|
-
*
|
|
1698
|
-
* On task start → calculate risk; if riskScore exceeds the HIGH threshold
|
|
1699
|
-
* (≥ 0.8), store a warning observation so future agents see it.
|
|
1700
|
-
*
|
|
1701
|
-
* All handlers are fire-and-forget: failures MUST NOT propagate or block the
|
|
1702
|
-
* operation that triggered them.
|
|
1703
|
-
*
|
|
1704
|
-
* @task T549
|
|
1705
|
-
* @epic T549
|
|
1706
|
-
*/
|
|
1707
|
-
var RISK_HIGH = .8;
|
|
1708
|
-
/**
|
|
1709
|
-
* Handle task start: calculate risk and store a warning observation if the
|
|
1710
|
-
* riskScore is at or above the HIGH threshold (≥ 0.8).
|
|
1711
|
-
*
|
|
1712
|
-
* Uses deferred imports so this module can be imported in environments where
|
|
1713
|
-
* not all transitive dependencies (brain.db, tasks.db) are present.
|
|
1714
|
-
*
|
|
1715
|
-
* Best-effort: any error is silently swallowed.
|
|
1716
|
-
*/
|
|
1717
|
-
async function handleTaskStartIntelligence(projectRoot, payload) {
|
|
1718
|
-
try {
|
|
1719
|
-
const { getTaskAccessor } = await import('./data-accessor-CWgVndbR.js').then(function (n) { return n.d; });
|
|
1720
|
-
const { getBrainAccessor } = await import('./memory-accessor-i3P-RHSg.js');
|
|
1721
|
-
const { calculateTaskRisk } = await import('./prediction-D1lSGJ4c.js');
|
|
1722
|
-
const { observeBrain } = await import('./brain-retrieval2-exR8mdgh.js');
|
|
1723
|
-
const [accessor, brain] = await Promise.all([getTaskAccessor(projectRoot), getBrainAccessor(projectRoot)]);
|
|
1724
|
-
const risk = await calculateTaskRisk(payload.taskId, accessor, brain);
|
|
1725
|
-
if (risk.riskScore >= RISK_HIGH) {
|
|
1726
|
-
const level = risk.riskScore >= .95 ? "critical" : "high";
|
|
1727
|
-
const factorNames = risk.factors.map((f) => f.name).join(", ");
|
|
1728
|
-
await observeBrain(projectRoot, {
|
|
1729
|
-
text: `Risk alert for ${payload.taskId} (score ${risk.riskScore.toFixed(2)}): ${factorNames}. ${risk.recommendation}`,
|
|
1730
|
-
title: `Task risk: ${level} — ${payload.taskId}`,
|
|
1731
|
-
type: "discovery",
|
|
1732
|
-
sourceType: "agent"
|
|
1733
|
-
});
|
|
1734
|
-
}
|
|
1735
|
-
} catch {}
|
|
1736
|
-
}
|
|
1737
|
-
hooks.register({
|
|
1738
|
-
id: "intelligence-task-start",
|
|
1739
|
-
event: "PreToolUse",
|
|
1740
|
-
handler: handleTaskStartIntelligence,
|
|
1741
|
-
priority: 50
|
|
1742
|
-
});
|
|
1743
|
-
//#endregion
|
|
1744
|
-
//#region ../core/dist/hooks/handlers/conduit-hooks.js
|
|
1745
|
-
/**
|
|
1746
|
-
* Conduit Messaging Hook Handlers
|
|
1747
|
-
*
|
|
1748
|
-
* Captures orchestration lifecycle events (SubagentStart, SubagentStop,
|
|
1749
|
-
* SessionEnd) and writes structured messages to conduit.db via LocalTransport.
|
|
1750
|
-
* This is the DECOUPLED approach: hooks observe orchestration events without
|
|
1751
|
-
* any changes to the orchestrate engine itself.
|
|
1752
|
-
*
|
|
1753
|
-
* Message format (JSON string stored as conduit message content):
|
|
1754
|
-
* { type, from, to, content, taskId, timestamp }
|
|
1755
|
-
*
|
|
1756
|
-
* All handlers are best-effort — failures are silently swallowed so that
|
|
1757
|
-
* conduit writes NEVER crash or block agent orchestration.
|
|
1758
|
-
*
|
|
1759
|
-
* Auto-registers on module load.
|
|
1760
|
-
*
|
|
1761
|
-
* @task T268
|
|
1762
|
-
*/
|
|
1763
|
-
/** Well-known system agent ID used as the "from" sender for lifecycle messages. */
|
|
1764
|
-
var SYSTEM_AGENT_ID = "cleo-orchestrator";
|
|
1765
|
-
/** Well-known broadcast recipient for lifecycle events. */
|
|
1766
|
-
var BROADCAST_RECIPIENT = "cleo-system";
|
|
1767
|
-
/**
|
|
1768
|
-
* Build the content string for a SubagentStart conduit message.
|
|
1769
|
-
*
|
|
1770
|
-
* @param payload - SubagentStart event payload.
|
|
1771
|
-
* @returns JSON-serialised message content string.
|
|
1772
|
-
*/
|
|
1773
|
-
function buildSpawnMessageContent(payload) {
|
|
1774
|
-
return JSON.stringify({
|
|
1775
|
-
type: "subagent.spawn",
|
|
1776
|
-
from: SYSTEM_AGENT_ID,
|
|
1777
|
-
to: payload.agentId,
|
|
1778
|
-
content: `Subagent spawned: ${payload.agentId}${payload.role ? ` (${payload.role})` : ""}`,
|
|
1779
|
-
taskId: payload.taskId ?? null,
|
|
1780
|
-
timestamp: payload.timestamp
|
|
1781
|
-
});
|
|
1782
|
-
}
|
|
1783
|
-
/**
|
|
1784
|
-
* Build the content string for a SubagentStop conduit message.
|
|
1785
|
-
*
|
|
1786
|
-
* @param payload - SubagentStop event payload.
|
|
1787
|
-
* @returns JSON-serialised message content string.
|
|
1788
|
-
*/
|
|
1789
|
-
function buildCompletionMessageContent(payload) {
|
|
1790
|
-
return JSON.stringify({
|
|
1791
|
-
type: "subagent.complete",
|
|
1792
|
-
from: payload.agentId,
|
|
1793
|
-
to: BROADCAST_RECIPIENT,
|
|
1794
|
-
content: `Subagent completed: ${payload.agentId} status=${payload.status ?? "unknown"}${payload.taskId ? ` task=${payload.taskId}` : ""}`,
|
|
1795
|
-
taskId: payload.taskId ?? null,
|
|
1796
|
-
timestamp: payload.timestamp
|
|
1797
|
-
});
|
|
1798
|
-
}
|
|
1799
|
-
/**
|
|
1800
|
-
* Build the content string for a SessionEnd handoff conduit message.
|
|
1801
|
-
*
|
|
1802
|
-
* @param payload - SessionEnd event payload.
|
|
1803
|
-
* @param nextTask - Optional next suggested task ID from the session.
|
|
1804
|
-
* @returns JSON-serialised message content string.
|
|
1805
|
-
*/
|
|
1806
|
-
function buildHandoffMessageContent(payload, nextTask) {
|
|
1807
|
-
return JSON.stringify({
|
|
1808
|
-
type: "session.handoff",
|
|
1809
|
-
from: SYSTEM_AGENT_ID,
|
|
1810
|
-
to: BROADCAST_RECIPIENT,
|
|
1811
|
-
content: `Session ended: ${payload.sessionId}${nextTask ? ` \u2014 next task: ${nextTask}` : ""}`,
|
|
1812
|
-
taskId: nextTask ?? null,
|
|
1813
|
-
timestamp: payload.timestamp
|
|
1814
|
-
});
|
|
1815
|
-
}
|
|
1816
|
-
/**
|
|
1817
|
-
* Attempt to create and connect a LocalTransport for conduit.db.
|
|
1818
|
-
*
|
|
1819
|
-
* Returns null when conduit.db is unavailable (not yet initialised), or when
|
|
1820
|
-
* the connect call fails, so callers can bail out gracefully without throwing.
|
|
1821
|
-
*
|
|
1822
|
-
* The `transportFactory` parameter exists for testing: callers can inject a
|
|
1823
|
-
* mock constructor so no real conduit.db is required in unit tests.
|
|
1824
|
-
*
|
|
1825
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1826
|
-
* @param transportFactory - Optional factory used to construct the transport.
|
|
1827
|
-
* Defaults to the `LocalTransport` class.
|
|
1828
|
-
*/
|
|
1829
|
-
async function tryGetLocalTransport(projectRoot, transportFactory = LocalTransport) {
|
|
1830
|
-
try {
|
|
1831
|
-
if (!transportFactory.isAvailable(projectRoot)) return null;
|
|
1832
|
-
const transport = new transportFactory();
|
|
1833
|
-
await transport.connect({
|
|
1834
|
-
agentId: SYSTEM_AGENT_ID,
|
|
1835
|
-
apiKey: "",
|
|
1836
|
-
apiBaseUrl: "local"
|
|
1837
|
-
});
|
|
1838
|
-
return transport;
|
|
1839
|
-
} catch {
|
|
1840
|
-
return null;
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
/**
|
|
1844
|
-
* Handle SubagentStart — send a spawn message to conduit.db.
|
|
1845
|
-
*
|
|
1846
|
-
* Writes a `subagent.spawn` message from `cleo-orchestrator` to the
|
|
1847
|
-
* spawned agent ID so orchestrators and watchers can observe the event.
|
|
1848
|
-
*
|
|
1849
|
-
* Best-effort: failures are swallowed and logged at debug level.
|
|
1850
|
-
*
|
|
1851
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1852
|
-
* @param payload - SubagentStart event payload.
|
|
1853
|
-
*/
|
|
1854
|
-
async function handleConduitSubagentStart(projectRoot, payload) {
|
|
1855
|
-
const transport = await tryGetLocalTransport(projectRoot);
|
|
1856
|
-
if (!transport) return;
|
|
1857
|
-
try {
|
|
1858
|
-
const content = buildSpawnMessageContent(payload);
|
|
1859
|
-
await transport.push(payload.agentId, content);
|
|
1860
|
-
} catch (err) {
|
|
1861
|
-
getLogger("conduit-hooks").debug({
|
|
1862
|
-
err,
|
|
1863
|
-
agentId: payload.agentId
|
|
1864
|
-
}, "conduit spawn write failed");
|
|
1865
|
-
} finally {
|
|
1866
|
-
try {
|
|
1867
|
-
await transport.disconnect();
|
|
1868
|
-
} catch {}
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
/**
|
|
1872
|
-
* Handle SubagentStop — send a completion message to conduit.db.
|
|
1873
|
-
*
|
|
1874
|
-
* Writes a `subagent.complete` message from the stopped agent to
|
|
1875
|
-
* `cleo-system` so orchestrators can audit completion outcomes.
|
|
1876
|
-
*
|
|
1877
|
-
* Best-effort: failures are swallowed and logged at debug level.
|
|
1878
|
-
*
|
|
1879
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1880
|
-
* @param payload - SubagentStop event payload.
|
|
1881
|
-
*/
|
|
1882
|
-
async function handleConduitSubagentStop(projectRoot, payload) {
|
|
1883
|
-
const transport = await tryGetLocalTransport(projectRoot);
|
|
1884
|
-
if (!transport) return;
|
|
1885
|
-
try {
|
|
1886
|
-
const content = buildCompletionMessageContent(payload);
|
|
1887
|
-
await transport.push(BROADCAST_RECIPIENT, content);
|
|
1888
|
-
} catch (err) {
|
|
1889
|
-
getLogger("conduit-hooks").debug({
|
|
1890
|
-
err,
|
|
1891
|
-
agentId: payload.agentId
|
|
1892
|
-
}, "conduit complete write failed");
|
|
1893
|
-
} finally {
|
|
1894
|
-
try {
|
|
1895
|
-
await transport.disconnect();
|
|
1896
|
-
} catch {}
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
/**
|
|
1900
|
-
* Handle SessionEnd — send a handoff message if a next task is suggested.
|
|
1901
|
-
*
|
|
1902
|
-
* Writes a `session.handoff` message to `cleo-system` when the session
|
|
1903
|
-
* metadata includes a `nextTask` suggestion (stored in `metadata.nextTask`).
|
|
1904
|
-
* The message lets waiting agents pick up where the session left off.
|
|
1905
|
-
*
|
|
1906
|
-
* Best-effort: failures are swallowed and logged at debug level.
|
|
1907
|
-
*
|
|
1908
|
-
* @param projectRoot - Absolute path to the project root directory.
|
|
1909
|
-
* @param payload - SessionEnd event payload.
|
|
1910
|
-
*/
|
|
1911
|
-
async function handleConduitSessionEnd(projectRoot, payload) {
|
|
1912
|
-
const transport = await tryGetLocalTransport(projectRoot);
|
|
1913
|
-
if (!transport) return;
|
|
1914
|
-
try {
|
|
1915
|
-
const content = buildHandoffMessageContent(payload, typeof payload.metadata?.nextTask === "string" ? payload.metadata.nextTask : void 0);
|
|
1916
|
-
await transport.push(BROADCAST_RECIPIENT, content);
|
|
1917
|
-
} catch (err) {
|
|
1918
|
-
getLogger("conduit-hooks").debug({
|
|
1919
|
-
err,
|
|
1920
|
-
sessionId: payload.sessionId
|
|
1921
|
-
}, "conduit handoff write failed");
|
|
1922
|
-
} finally {
|
|
1923
|
-
try {
|
|
1924
|
-
await transport.disconnect();
|
|
1925
|
-
} catch {}
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
hooks.register({
|
|
1929
|
-
id: "conduit-subagent-start",
|
|
1930
|
-
event: "SubagentStart",
|
|
1931
|
-
handler: handleConduitSubagentStart,
|
|
1932
|
-
priority: 50
|
|
1933
|
-
});
|
|
1934
|
-
hooks.register({
|
|
1935
|
-
id: "conduit-subagent-stop",
|
|
1936
|
-
event: "SubagentStop",
|
|
1937
|
-
handler: handleConduitSubagentStop,
|
|
1938
|
-
priority: 50
|
|
1939
|
-
});
|
|
1940
|
-
hooks.register({
|
|
1941
|
-
id: "conduit-session-end",
|
|
1942
|
-
event: "SessionEnd",
|
|
1943
|
-
handler: handleConduitSessionEnd,
|
|
1944
|
-
priority: 8
|
|
1945
|
-
});
|
|
1946
|
-
//#endregion
|
|
1947
|
-
//#region ../core/dist/sessions/agent-session-adapter.js
|
|
1948
|
-
/**
|
|
1949
|
-
* CLEO wrapper around `llmtxt/sdk.AgentSession` — T947 Step 2.
|
|
1950
|
-
*
|
|
1951
|
-
* Satisfies owner Constraint #4 (zero primitive duplication) per GitHub
|
|
1952
|
-
* issue #96: CLEO no longer rolls its own session-level audit receipts,
|
|
1953
|
-
* crypto-random session IDs, or manual state-transition writes. Those
|
|
1954
|
-
* primitives come from llmtxt's {@link AgentSession}, and this module
|
|
1955
|
-
* only adapts them to CLEO's project layout.
|
|
1956
|
-
*
|
|
1957
|
-
* Responsibilities:
|
|
1958
|
-
* - Open an {@link AgentSession} backed by a lightweight `standalone`
|
|
1959
|
-
* llmtxt backend scoped to `<projectRoot>/.cleo/llmtxt/`, ONLY when
|
|
1960
|
-
* llmtxt's optional peer dependencies (`better-sqlite3`,
|
|
1961
|
-
* `drizzle-orm/better-sqlite3`) are installed.
|
|
1962
|
-
* - Wrap a caller-provided async unit of work in `session.contribute()`
|
|
1963
|
-
* so the receipt's `eventCount` and (optionally) `documentIds` are
|
|
1964
|
-
* populated with programmatic proof.
|
|
1965
|
-
* - Close the session and emit a {@link ContributionReceipt}. The
|
|
1966
|
-
* receipt is appended to `.cleo/audit/receipts.jsonl` alongside the
|
|
1967
|
-
* existing ADR-051 evidence trail (`.cleo/audit/gates.jsonl`,
|
|
1968
|
-
* `.cleo/audit/force-bypass.jsonl`) so all tamper-evident records
|
|
1969
|
-
* live in one place on disk.
|
|
1970
|
-
* - Degrade gracefully when llmtxt peer deps are absent: every entry
|
|
1971
|
-
* point resolves to `{ result, receipt: null }` and NEVER throws,
|
|
1972
|
-
* so `cleo complete` / `cleo session` behaviour is unchanged in
|
|
1973
|
-
* minimal environments.
|
|
1974
|
-
*
|
|
1975
|
-
* Non-goals:
|
|
1976
|
-
* - Remote sync. We intentionally choose `topology: 'standalone'` so
|
|
1977
|
-
* the backend is a per-project SQLite file with zero network
|
|
1978
|
-
* surface. Cross-machine receipt replication is a Wave B concern.
|
|
1979
|
-
* - Replacing the existing CLEO `Session` record in `tasks.db`. This
|
|
1980
|
-
* adapter runs ALONGSIDE `startSession` / `endSession`; CLEO owns
|
|
1981
|
-
* session metadata, llmtxt owns the signed receipt.
|
|
1982
|
-
*
|
|
1983
|
-
* @task T947
|
|
1984
|
-
* @adr ADR-051 (Gate Integrity & Evidence) — receipts are the session-
|
|
1985
|
-
* level companion to per-gate audit records.
|
|
1986
|
-
* @see packages/core/src/tasks/gate-audit.ts
|
|
1987
|
-
* @see packages/core/src/store/llmtxt-blob-adapter.ts (mirror peer-dep
|
|
1988
|
-
* lazy-load pattern)
|
|
1989
|
-
*/
|
|
1990
|
-
/**
|
|
1991
|
-
* Resolve the absolute path of the receipts audit log.
|
|
1992
|
-
*
|
|
1993
|
-
* Mirrors the shape of {@link getGateAuditPath} so operators can glob
|
|
1994
|
-
* `.cleo/audit/*.jsonl` to find every ADR-051 artifact.
|
|
1995
|
-
*
|
|
1996
|
-
* @param projectRoot - Absolute path to the project root.
|
|
1997
|
-
* @returns Absolute path to `.cleo/audit/receipts.jsonl`.
|
|
1998
|
-
*
|
|
1999
|
-
* @task T947
|
|
2000
|
-
* @adr ADR-051 §6
|
|
2001
|
-
*/
|
|
2002
|
-
function getReceiptsAuditPath(projectRoot) {
|
|
2003
|
-
return resolve(projectRoot, ".cleo", "audit", "receipts.jsonl");
|
|
2004
|
-
}
|
|
2005
|
-
/**
|
|
2006
|
-
* Open an llmtxt AgentSession, or return `null` if llmtxt peer deps are
|
|
2007
|
-
* absent. NEVER throws — peer-dep failure, filesystem failure, and
|
|
2008
|
-
* backend-open failure all degrade to `null` and are logged at debug.
|
|
2009
|
-
*
|
|
2010
|
-
* The returned handle MUST be closed via {@link closeAgentSession} to
|
|
2011
|
-
* flush the receipt and release SQLite handles.
|
|
2012
|
-
*
|
|
2013
|
-
* @param options - Session options (see {@link AgentSessionAdapterOptions}).
|
|
2014
|
-
* @returns A handle, or `null` when the adapter cannot be initialised.
|
|
2015
|
-
*
|
|
2016
|
-
* @task T947
|
|
2017
|
-
*/
|
|
2018
|
-
async function openAgentSession(options = {}) {
|
|
2019
|
-
const projectRoot = resolveOrCwd(options.projectRoot);
|
|
2020
|
-
const agentId = options.agentId ?? process.env.CLEO_AGENT_ID ?? "cleo";
|
|
2021
|
-
let createBackendFn;
|
|
2022
|
-
let AgentSessionCtor;
|
|
2023
|
-
try {
|
|
2024
|
-
const [llmtxtMod, sdkMod] = await Promise.all([import('llmtxt'), import('llmtxt/sdk')]);
|
|
2025
|
-
createBackendFn = llmtxtMod.createBackend;
|
|
2026
|
-
AgentSessionCtor = sdkMod.AgentSession;
|
|
2027
|
-
} catch {
|
|
2028
|
-
return null;
|
|
2029
|
-
}
|
|
2030
|
-
let backend;
|
|
2031
|
-
try {
|
|
2032
|
-
backend = await createBackendFn({
|
|
2033
|
-
topology: "standalone",
|
|
2034
|
-
storagePath: resolve(projectRoot, ".cleo", "llmtxt")
|
|
2035
|
-
});
|
|
2036
|
-
await backend.open();
|
|
2037
|
-
} catch {
|
|
2038
|
-
return null;
|
|
2039
|
-
}
|
|
2040
|
-
try {
|
|
2041
|
-
const session = new AgentSessionCtor({
|
|
2042
|
-
backend,
|
|
2043
|
-
agentId,
|
|
2044
|
-
...options.sessionId ? { sessionId: options.sessionId } : {},
|
|
2045
|
-
...options.label ? { label: options.label } : {}
|
|
2046
|
-
});
|
|
2047
|
-
await session.open();
|
|
2048
|
-
return {
|
|
2049
|
-
session,
|
|
2050
|
-
projectRoot,
|
|
2051
|
-
closeBackend: async () => {
|
|
2052
|
-
try {
|
|
2053
|
-
await backend.close();
|
|
2054
|
-
} catch {}
|
|
2055
|
-
}
|
|
2056
|
-
};
|
|
2057
|
-
} catch {
|
|
2058
|
-
await backend.close().catch(() => {});
|
|
2059
|
-
return null;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
/**
|
|
2063
|
-
* Close a previously-opened AgentSession and persist the receipt.
|
|
2064
|
-
*
|
|
2065
|
-
* Behaviour:
|
|
2066
|
-
* - Calls `session.close()` which emits a {@link ContributionReceipt}
|
|
2067
|
-
* (llmtxt handles all state transitions and Ed25519 signing once
|
|
2068
|
-
* llmtxt T461 ships).
|
|
2069
|
-
* - Appends the receipt to `.cleo/audit/receipts.jsonl` as a single
|
|
2070
|
-
* JSON line (matches `.cleo/audit/gates.jsonl`).
|
|
2071
|
-
* - Returns the receipt so callers (e.g. `cleo complete`) can surface
|
|
2072
|
-
* `receiptId` on the CLI envelope.
|
|
2073
|
-
* - Swallows `SESSION_CLOSE_PARTIAL` errors: the partial receipt is
|
|
2074
|
-
* still returned and persisted, matching llmtxt's best-effort
|
|
2075
|
-
* close contract.
|
|
2076
|
-
* - Returns `null` on any unexpected throw so teardown NEVER breaks
|
|
2077
|
-
* the caller.
|
|
2078
|
-
*
|
|
2079
|
-
* @param handle - Handle previously returned by {@link openAgentSession}.
|
|
2080
|
-
* @returns The emitted receipt, or `null` on failure.
|
|
2081
|
-
*
|
|
2082
|
-
* @task T947
|
|
2083
|
-
* @adr ADR-051 §6
|
|
2084
|
-
*/
|
|
2085
|
-
async function closeAgentSession(handle) {
|
|
2086
|
-
let receipt = null;
|
|
2087
|
-
try {
|
|
2088
|
-
receipt = await handle.session.close();
|
|
2089
|
-
} catch (err) {
|
|
2090
|
-
const maybePartial = err;
|
|
2091
|
-
if (maybePartial?.receipt !== void 0) receipt = maybePartial.receipt;
|
|
2092
|
-
else receipt = null;
|
|
2093
|
-
}
|
|
2094
|
-
if (receipt !== null) try {
|
|
2095
|
-
await persistReceipt(handle.projectRoot, receipt);
|
|
2096
|
-
} catch {}
|
|
2097
|
-
await handle.closeBackend();
|
|
2098
|
-
return receipt;
|
|
2099
|
-
}
|
|
2100
|
-
/**
|
|
2101
|
-
* Wrap an async function inside an AgentSession, returning both the
|
|
2102
|
-
* function's result and a persisted receipt (when peer deps allow).
|
|
2103
|
-
*
|
|
2104
|
-
* Contract:
|
|
2105
|
-
* - The wrapped `fn` ALWAYS runs. Its result is returned verbatim on
|
|
2106
|
-
* success, and its thrown error is re-thrown verbatim on failure.
|
|
2107
|
-
* - When peer deps are present, `fn` is invoked inside
|
|
2108
|
-
* {@link AgentSession.contribute}, so its returned object is
|
|
2109
|
-
* scanned for `documentId` / `documentIds` fields (see llmtxt spec
|
|
2110
|
-
* §3.3) and eventCount is incremented.
|
|
2111
|
-
* - When peer deps are absent, `fn` runs unwrapped and the returned
|
|
2112
|
-
* `receipt` is `null`.
|
|
2113
|
-
* - On error, no receipt is emitted (the session is closed with
|
|
2114
|
-
* zero eventCount — llmtxt spec §3.3 MUST NOT increment on error).
|
|
2115
|
-
* The error propagates.
|
|
2116
|
-
*
|
|
2117
|
-
* @typeParam T - Return type of the wrapped function.
|
|
2118
|
-
* @param options - Adapter options (see {@link AgentSessionAdapterOptions}).
|
|
2119
|
-
* @param fn - The async work unit to wrap.
|
|
2120
|
-
* @returns An envelope with `result` (always present on success) and
|
|
2121
|
-
* `receipt` (null when peer deps unavailable).
|
|
2122
|
-
*
|
|
2123
|
-
* @example
|
|
2124
|
-
* ```ts
|
|
2125
|
-
* const { result, receipt } = await wrapWithAgentSession(
|
|
2126
|
-
* { sessionId, agentId: 'cleo', projectRoot: '/repo' },
|
|
2127
|
-
* async () => {
|
|
2128
|
-
* return applyTaskCompletion(task);
|
|
2129
|
-
* },
|
|
2130
|
-
* );
|
|
2131
|
-
* if (receipt) console.log(receipt.sessionId, receipt.eventCount);
|
|
2132
|
-
* ```
|
|
2133
|
-
*
|
|
2134
|
-
* @task T947
|
|
2135
|
-
* @adr ADR-051 §6
|
|
2136
|
-
*/
|
|
2137
|
-
async function wrapWithAgentSession(options, fn) {
|
|
2138
|
-
const handle = await openAgentSession(options);
|
|
2139
|
-
if (handle === null) return {
|
|
2140
|
-
result: await fn(),
|
|
2141
|
-
receipt: null
|
|
2142
|
-
};
|
|
2143
|
-
let result;
|
|
2144
|
-
try {
|
|
2145
|
-
result = await handle.session.contribute(async () => fn());
|
|
2146
|
-
} catch (err) {
|
|
2147
|
-
await handle.session.close().catch(() => {});
|
|
2148
|
-
await handle.closeBackend();
|
|
2149
|
-
throw err;
|
|
2150
|
-
}
|
|
2151
|
-
const receipt = await closeAgentSession(handle);
|
|
2152
|
-
return {
|
|
2153
|
-
result,
|
|
2154
|
-
receipt
|
|
2155
|
-
};
|
|
2156
|
-
}
|
|
2157
|
-
/**
|
|
2158
|
-
* Append a {@link ContributionReceipt} to `.cleo/audit/receipts.jsonl`.
|
|
2159
|
-
*
|
|
2160
|
-
* Creates the audit directory on first use. Serialises the receipt as
|
|
2161
|
-
* a single JSON line so the file remains valid JSON-lines.
|
|
2162
|
-
*
|
|
2163
|
-
* @param projectRoot - Absolute path to the project root.
|
|
2164
|
-
* @param receipt - Receipt emitted by {@link AgentSession.close}.
|
|
2165
|
-
*
|
|
2166
|
-
* @internal
|
|
2167
|
-
* @task T947
|
|
2168
|
-
*/
|
|
2169
|
-
async function persistReceipt(projectRoot, receipt) {
|
|
2170
|
-
const path = getReceiptsAuditPath(projectRoot);
|
|
2171
|
-
await mkdir(dirname(path), { recursive: true });
|
|
2172
|
-
await appendFile(path, `${JSON.stringify(receipt)}\n`, { encoding: "utf-8" });
|
|
2173
|
-
}
|
|
2174
|
-
//#endregion
|
|
2175
|
-
//#region ../core/dist/render/ansi.js
|
|
2176
|
-
/**
|
|
2177
|
-
* Minimal ANSI escape primitives used by the shared render helpers.
|
|
2178
|
-
*
|
|
2179
|
-
* Kept tiny and self-contained so `@cleocode/core/render` has zero coupling
|
|
2180
|
-
* to the cleo CLI's larger colors module. Respects `NO_COLOR` and
|
|
2181
|
-
* `FORCE_COLOR` envs the same way (https://no-color.org).
|
|
2182
|
-
*
|
|
2183
|
-
* @task T10129
|
|
2184
|
-
*/
|
|
2185
|
-
/** Whether ANSI color escape codes should be emitted. */
|
|
2186
|
-
var colorsEnabled = (() => {
|
|
2187
|
-
if (process.env["NO_COLOR"] !== void 0) return false;
|
|
2188
|
-
if (process.env["FORCE_COLOR"] !== void 0) return true;
|
|
2189
|
-
return process.stdout.isTTY === true;
|
|
2190
|
-
})();
|
|
2191
|
-
function ansi(code) {
|
|
2192
|
-
return colorsEnabled ? code : "";
|
|
2193
|
-
}
|
|
2194
|
-
/** Bold text. */
|
|
2195
|
-
var BOLD = ansi("\x1B[1m");
|
|
2196
|
-
/** Dim text. */
|
|
2197
|
-
var DIM = ansi("\x1B[2m");
|
|
2198
|
-
/** Reset (no-color). */
|
|
2199
|
-
var NC = ansi("\x1B[0m");
|
|
2200
|
-
//#endregion
|
|
2201
|
-
//#region ../core/dist/render/helpers.js
|
|
2202
|
-
/** Default single-glyph ellipsis appended by {@link truncateString}. */
|
|
2203
|
-
var DEFAULT_ELLIPSIS = "…";
|
|
2204
|
-
/**
|
|
2205
|
-
* Truncate a plain (non-ANSI) string to at most `max` characters, appending an
|
|
2206
|
-
* ellipsis when truncation occurs.
|
|
2207
|
-
*
|
|
2208
|
-
* This is the single SSoT for scalar-string truncation — it replaces the 6+
|
|
2209
|
-
* ad-hoc `truncate(str, max)` helpers that were copy-pasted across
|
|
2210
|
-
* `output-mode.ts`, `briefing.ts`, `memory/public-api.ts`, `gate-runner.ts`,
|
|
2211
|
-
* and friends. The result length never exceeds `max`: the ellipsis is counted
|
|
2212
|
-
* against the budget, so `truncateString('abcdef', 4)` returns `'abc…'`.
|
|
2213
|
-
*
|
|
2214
|
-
* For ANSI-colored content use {@link truncateVisible} (which counts visible
|
|
2215
|
-
* columns and never splits an escape sequence); for windowing an *array* use
|
|
2216
|
-
* {@link truncated}.
|
|
2217
|
-
*
|
|
2218
|
-
* @param value - The string to truncate. `null` / `undefined` collapse to `''`.
|
|
2219
|
-
* @param max - Maximum length of the returned string (including the ellipsis).
|
|
2220
|
-
* @param ellipsis - The suffix appended when truncated. Defaults to `'…'`.
|
|
2221
|
-
* Pass `'...'` for ASCII contexts.
|
|
2222
|
-
* @returns The original string when it fits, otherwise a truncated string of
|
|
2223
|
-
* length ≤ `max`.
|
|
2224
|
-
*
|
|
2225
|
-
* @example
|
|
2226
|
-
* ```ts
|
|
2227
|
-
* truncateString('a very long title', 8); // 'a very…'
|
|
2228
|
-
* truncateString('a very long title', 8, '...'); // 'a ve...'
|
|
2229
|
-
* truncateString(null, 10); // ''
|
|
2230
|
-
* ```
|
|
2231
|
-
*
|
|
2232
|
-
* @task T11353
|
|
2233
|
-
* @epic T11285
|
|
2234
|
-
*/
|
|
2235
|
-
function truncateString(value, max, ellipsis = DEFAULT_ELLIPSIS) {
|
|
2236
|
-
if (!value) return "";
|
|
2237
|
-
if (max <= 0) return "";
|
|
2238
|
-
if (value.length <= max) return value;
|
|
2239
|
-
if (ellipsis.length >= max) return value.slice(0, max);
|
|
2240
|
-
return value.slice(0, max - ellipsis.length) + ellipsis;
|
|
2241
|
-
}
|
|
2242
|
-
/**
|
|
2243
|
-
* Read sessions from accessor or JSON file.
|
|
2244
|
-
* Internal helper — not exposed via dispatch contracts.
|
|
2245
|
-
* @task T4463
|
|
2246
|
-
*/
|
|
2247
|
-
async function readSessions(cwd, accessor) {
|
|
2248
|
-
return (accessor ?? await getTaskAccessor(cwd)).loadSessions();
|
|
2249
|
-
}
|
|
2250
|
-
/**
|
|
2251
|
-
* Get current session status.
|
|
2252
|
-
* Normalized Core signature: (projectRoot, params) → Result.
|
|
2253
|
-
* @task T1450
|
|
2254
|
-
*/
|
|
2255
|
-
async function sessionStatus(projectRoot, _params) {
|
|
2256
|
-
return (await readSessions(projectRoot, await getTaskAccessor(projectRoot))).filter((s) => s.status === "active").sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime())[0] ?? null;
|
|
2257
|
-
}
|
|
2258
|
-
/**
|
|
2259
|
-
* List sessions with optional filtering.
|
|
2260
|
-
* Normalized Core signature: (projectRoot, params) → Result.
|
|
2261
|
-
* @task T1450
|
|
2262
|
-
*/
|
|
2263
|
-
async function listSessions(projectRoot, params) {
|
|
2264
|
-
let sessions = await readSessions(projectRoot, await getTaskAccessor(projectRoot));
|
|
2265
|
-
if (params.status) sessions = sessions.filter((s) => s.status === params.status);
|
|
2266
|
-
sessions.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
|
|
2267
|
-
if (params.limit) sessions = sessions.slice(0, params.limit);
|
|
2268
|
-
for (const s of sessions) Object.assign(s, { _next: sessionListItemNext(s.id) });
|
|
2269
|
-
return sessions;
|
|
2270
|
-
}
|
|
2271
|
-
|
|
2272
|
-
export { BOLD as B, DIM as D, NC as N, getLastHandoff as g, isAutoCaptureEnabled as i, listSessions as l, readSessions as r, sessionStatus as s, truncateString as t, wrapWithAgentSession as w };
|
|
2273
|
-
//# sourceMappingURL=sessions-33DD4hkt.js.map
|