@juspay/shooter 1.5.0 → 1.6.1
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/README.md +24 -20
- package/bin/shooter.cjs +68 -17
- package/build/client/_app/immutable/assets/2.Dk9NfqnS.css +1 -0
- package/build/client/_app/immutable/assets/2.Dk9NfqnS.css.br +0 -0
- package/build/client/_app/immutable/assets/2.Dk9NfqnS.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.DHxQoulp.css +1 -0
- package/build/client/_app/immutable/assets/3.DHxQoulp.css.br +0 -0
- package/build/client/_app/immutable/assets/3.DHxQoulp.css.gz +0 -0
- package/build/client/_app/immutable/assets/{3.DGDHCVnW.css → 4.D5l1JxgO.css} +1 -1
- package/build/client/_app/immutable/assets/4.D5l1JxgO.css.br +0 -0
- package/build/client/_app/immutable/assets/4.D5l1JxgO.css.gz +0 -0
- package/build/client/_app/immutable/assets/5.C5qz-NeI.css +1 -0
- package/build/client/_app/immutable/assets/5.C5qz-NeI.css.br +0 -0
- package/build/client/_app/immutable/assets/5.C5qz-NeI.css.gz +0 -0
- package/build/client/_app/immutable/chunks/1mEchsPO.js +1 -0
- package/build/client/_app/immutable/chunks/1mEchsPO.js.br +0 -0
- package/build/client/_app/immutable/chunks/1mEchsPO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B7X-vhXI.js +1 -0
- package/build/client/_app/immutable/chunks/B7X-vhXI.js.br +0 -0
- package/build/client/_app/immutable/chunks/B7X-vhXI.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BRkqKgVG.js +1 -0
- package/build/client/_app/immutable/chunks/BRkqKgVG.js.br +0 -0
- package/build/client/_app/immutable/chunks/BRkqKgVG.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BfJ-f-Tu.js +1 -0
- package/build/client/_app/immutable/chunks/BfJ-f-Tu.js.br +2 -0
- package/build/client/_app/immutable/chunks/BfJ-f-Tu.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CGMJxf7r.js +1 -0
- package/build/client/_app/immutable/chunks/CGMJxf7r.js.br +0 -0
- package/build/client/_app/immutable/chunks/CGMJxf7r.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CZHsSL_X.js → CJFjKwJ7.js} +1 -1
- package/build/client/_app/immutable/chunks/CJFjKwJ7.js.br +0 -0
- package/build/client/_app/immutable/chunks/CJFjKwJ7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CNH2HlKj.js +20 -0
- package/build/client/_app/immutable/chunks/CNH2HlKj.js.br +0 -0
- package/build/client/_app/immutable/chunks/CNH2HlKj.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CR6bkGJW.js +6 -0
- package/build/client/_app/immutable/chunks/CR6bkGJW.js.br +0 -0
- package/build/client/_app/immutable/chunks/CR6bkGJW.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CVtJ6yRM.js +1 -0
- package/build/client/_app/immutable/chunks/CVtJ6yRM.js.br +0 -0
- package/build/client/_app/immutable/chunks/CVtJ6yRM.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CSoRdFvv.js → CaiJSUi3.js} +1 -1
- package/build/client/_app/immutable/chunks/CaiJSUi3.js.br +0 -0
- package/build/client/_app/immutable/chunks/CaiJSUi3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DjsDGxCa.js → CmczWE_d.js} +4 -4
- package/build/client/_app/immutable/chunks/CmczWE_d.js.br +0 -0
- package/build/client/_app/immutable/chunks/CmczWE_d.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CsgHjHGZ.js +1 -0
- package/build/client/_app/immutable/chunks/CsgHjHGZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/CsgHjHGZ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{UJOiqIYE.js → CtrCjGZT.js} +1 -1
- package/build/client/_app/immutable/chunks/CtrCjGZT.js.br +0 -0
- package/build/client/_app/immutable/chunks/CtrCjGZT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DDiOVAd8.js +61 -0
- package/build/client/_app/immutable/chunks/DDiOVAd8.js.br +0 -0
- package/build/client/_app/immutable/chunks/DDiOVAd8.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DVl0sebP.js +2 -0
- package/build/client/_app/immutable/chunks/DVl0sebP.js.br +0 -0
- package/build/client/_app/immutable/chunks/DVl0sebP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CiF38mQq.js → Dc_Gg2H6.js} +1 -1
- package/build/client/_app/immutable/chunks/Dc_Gg2H6.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dc_Gg2H6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{CRbaG9cv.js → DlnAjkg1.js} +1 -1
- package/build/client/_app/immutable/chunks/DlnAjkg1.js.br +0 -0
- package/build/client/_app/immutable/chunks/{CRbaG9cv.js.gz → DlnAjkg1.js.gz} +0 -0
- package/build/client/_app/immutable/chunks/YKoRJzXZ.js +3 -0
- package/build/client/_app/immutable/chunks/YKoRJzXZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/YKoRJzXZ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/gQJcRhou.js +1 -0
- package/build/client/_app/immutable/chunks/gQJcRhou.js.br +0 -0
- package/build/client/_app/immutable/chunks/gQJcRhou.js.gz +0 -0
- package/build/client/_app/immutable/chunks/pRcLbE0d.js +1 -0
- package/build/client/_app/immutable/chunks/pRcLbE0d.js.br +0 -0
- package/build/client/_app/immutable/chunks/pRcLbE0d.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CFPgQOa8.js +2 -0
- package/build/client/_app/immutable/entry/app.CFPgQOa8.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CFPgQOa8.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BnJOVqhI.js +1 -0
- package/build/client/_app/immutable/entry/start.BnJOVqhI.js.br +2 -0
- package/build/client/_app/immutable/entry/start.BnJOVqhI.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.DR-BBF5r.js +1 -0
- package/build/client/_app/immutable/nodes/0.DR-BBF5r.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.DR-BBF5r.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.CNm6rAwf.js +1 -0
- package/build/client/_app/immutable/nodes/1.CNm6rAwf.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.CNm6rAwf.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.B08usYzr.js +13 -0
- package/build/client/_app/immutable/nodes/2.B08usYzr.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.B08usYzr.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.CsY6J5HS.js +9 -0
- package/build/client/_app/immutable/nodes/3.CsY6J5HS.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.CsY6J5HS.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.B_pbOZoD.js +4 -0
- package/build/client/_app/immutable/nodes/4.B_pbOZoD.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.B_pbOZoD.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.CdLPNo5-.js +1 -0
- package/build/client/_app/immutable/nodes/5.CdLPNo5-.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.CdLPNo5-.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.CbQQ3FtZ.js +1 -0
- package/build/client/_app/immutable/nodes/6.CbQQ3FtZ.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.CbQQ3FtZ.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{5.DIkXVP4q.js → 7.CCKgiNNk.js} +3 -3
- package/build/client/_app/immutable/nodes/7.CCKgiNNk.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.CCKgiNNk.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.C7AaheUD.js +2 -0
- package/build/client/_app/immutable/nodes/8.C7AaheUD.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.C7AaheUD.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.DfL9kMC4.js +2 -0
- package/build/client/_app/immutable/nodes/9.DfL9kMC4.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.DfL9kMC4.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/server/chunks/0-DC2VLooL.js +23 -0
- package/build/server/chunks/0-DC2VLooL.js.map +1 -0
- package/build/server/chunks/1-XJaf8Jvf.js +9 -0
- package/build/server/chunks/{1-D0N7vVhH.js.map → 1-XJaf8Jvf.js.map} +1 -1
- package/build/server/chunks/2-D4Cx-1QL.js +21 -0
- package/build/server/chunks/2-D4Cx-1QL.js.map +1 -0
- package/build/server/chunks/3-CVhIEP-u.js +21 -0
- package/build/server/chunks/3-CVhIEP-u.js.map +1 -0
- package/build/server/chunks/4-0UE_6Ep-.js +23 -0
- package/build/server/chunks/4-0UE_6Ep-.js.map +1 -0
- package/build/server/chunks/5-BBIP1PzX.js +24 -0
- package/build/server/chunks/5-BBIP1PzX.js.map +1 -0
- package/build/server/chunks/6-QFSbzRMP.js +9 -0
- package/build/server/chunks/6-QFSbzRMP.js.map +1 -0
- package/build/server/chunks/7-CZ_YGjMV.js +9 -0
- package/build/server/chunks/7-CZ_YGjMV.js.map +1 -0
- package/build/server/chunks/8-Xe2Rugb4.js +9 -0
- package/build/server/chunks/8-Xe2Rugb4.js.map +1 -0
- package/build/server/chunks/9-IwHpC4SO.js +9 -0
- package/build/server/chunks/9-IwHpC4SO.js.map +1 -0
- package/build/server/chunks/{Button-Cs1aE6ka.js → Button-WKgiLWZI.js} +4 -9
- package/build/server/chunks/Button-WKgiLWZI.js.map +1 -0
- package/build/server/chunks/{EmptyState-DDFH1K8g.js → EmptyState-BUBqASsp.js} +3 -3
- package/build/server/chunks/{EmptyState-DDFH1K8g.js.map → EmptyState-BUBqASsp.js.map} +1 -1
- package/build/server/chunks/{Icon-CEUrotA6.js → Icon-BNBAg85a.js} +3 -3
- package/build/server/chunks/Icon-BNBAg85a.js.map +1 -0
- package/build/server/chunks/{Shimmer-DB8W1zt6.js → Shimmer-C4uBVwxz.js} +2 -2
- package/build/server/chunks/{Shimmer-DB8W1zt6.js.map → Shimmer-C4uBVwxz.js.map} +1 -1
- package/build/server/chunks/{_error.svelte-uCOJNxvr.js → _error.svelte-DkIwmECt.js} +5 -5
- package/build/server/chunks/{_error.svelte-uCOJNxvr.js.map → _error.svelte-DkIwmECt.js.map} +1 -1
- package/build/server/chunks/{_layout.svelte-CtWmEJwe.js → _layout.svelte-DllETxmJ.js} +13 -7
- package/build/server/chunks/_layout.svelte-DllETxmJ.js.map +1 -0
- package/build/server/chunks/_page.svelte-BZSdLKE_.js +118 -0
- package/build/server/chunks/_page.svelte-BZSdLKE_.js.map +1 -0
- package/build/server/chunks/{_page.svelte-CxWcQ0Am.js → _page.svelte-Cmuco1mC.js} +84 -199
- package/build/server/chunks/_page.svelte-Cmuco1mC.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BgevQjq1.js → _page.svelte-Co5sF7W-.js} +12 -11
- package/build/server/chunks/{_page.svelte-BgevQjq1.js.map → _page.svelte-Co5sF7W-.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DO4oa_LY.js → _page.svelte-CpL3R-VI.js} +8 -8
- package/build/server/chunks/{_page.svelte-DO4oa_LY.js.map → _page.svelte-CpL3R-VI.js.map} +1 -1
- package/build/server/chunks/_page.svelte-DDSzYLUs.js +137 -0
- package/build/server/chunks/_page.svelte-DDSzYLUs.js.map +1 -0
- package/build/server/chunks/_page.svelte-JIkgFUFf.js +26 -0
- package/build/server/chunks/_page.svelte-JIkgFUFf.js.map +1 -0
- package/build/server/chunks/{_page.svelte-CVq6tRb3.js → _page.svelte-Y9-O5a5w.js} +10 -9
- package/build/server/chunks/_page.svelte-Y9-O5a5w.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BcZaKdX9.js → _page.svelte-fcX09N4d.js} +9 -9
- package/build/server/chunks/{_page.svelte-BcZaKdX9.js.map → _page.svelte-fcX09N4d.js.map} +1 -1
- package/build/server/chunks/{_server.ts-DYpJImqd.js → _server.ts-0Xr2fWaq.js} +9 -5
- package/build/server/chunks/_server.ts-0Xr2fWaq.js.map +1 -0
- package/build/server/chunks/{_server.ts-CTpcLUH8.js → _server.ts-2ixC-X3K.js} +20 -5
- package/build/server/chunks/_server.ts-2ixC-X3K.js.map +1 -0
- package/build/server/chunks/{_server.ts-CAxsWKvS.js → _server.ts-40c_epk8.js} +20 -4
- package/build/server/chunks/_server.ts-40c_epk8.js.map +1 -0
- package/build/server/chunks/{_server.ts-WhTJBEJy.js → _server.ts-A9_tRR-K.js} +5 -4
- package/build/server/chunks/{_server.ts-WhTJBEJy.js.map → _server.ts-A9_tRR-K.js.map} +1 -1
- package/build/server/chunks/_server.ts-BRAzC6W1.js +98 -0
- package/build/server/chunks/_server.ts-BRAzC6W1.js.map +1 -0
- package/build/server/chunks/{_server.ts-DB_Kg97c.js → _server.ts-BScvgttw.js} +24 -4
- package/build/server/chunks/_server.ts-BScvgttw.js.map +1 -0
- package/build/server/chunks/{_server.ts-tSpgyl1D.js → _server.ts-Bjbr7glm.js} +4 -3
- package/build/server/chunks/_server.ts-Bjbr7glm.js.map +1 -0
- package/build/server/chunks/{_server.ts-COu0vNpd.js → _server.ts-BrqaMMAa.js} +7 -6
- package/build/server/chunks/_server.ts-BrqaMMAa.js.map +1 -0
- package/build/server/chunks/{_server.ts-vekTmWAx.js → _server.ts-BuYyCrnF.js} +6 -4
- package/build/server/chunks/_server.ts-BuYyCrnF.js.map +1 -0
- package/build/server/chunks/{_server.ts-DYvb9ijZ.js → _server.ts-ByPExYfO.js} +4 -3
- package/build/server/chunks/{_server.ts-DYvb9ijZ.js.map → _server.ts-ByPExYfO.js.map} +1 -1
- package/build/server/chunks/_server.ts-CjpQ10xh.js +123 -0
- package/build/server/chunks/_server.ts-CjpQ10xh.js.map +1 -0
- package/build/server/chunks/_server.ts-CyjDrcZN.js +21 -0
- package/build/server/chunks/_server.ts-CyjDrcZN.js.map +1 -0
- package/build/server/chunks/{_server.ts-DV8zTCF9.js → _server.ts-DOGUMzPx.js} +4 -3
- package/build/server/chunks/{_server.ts-DV8zTCF9.js.map → _server.ts-DOGUMzPx.js.map} +1 -1
- package/build/server/chunks/_server.ts-DZvfyuNj.js +15 -0
- package/build/server/chunks/_server.ts-DZvfyuNj.js.map +1 -0
- package/build/server/chunks/{_server.ts-XzT2UHM1.js → _server.ts-DkPPTUPo.js} +4 -3
- package/build/server/chunks/{_server.ts-XzT2UHM1.js.map → _server.ts-DkPPTUPo.js.map} +1 -1
- package/build/server/chunks/{_server.ts-Deok2y88.js → _server.ts-Ds_SUGC3.js} +184 -90
- package/build/server/chunks/_server.ts-Ds_SUGC3.js.map +1 -0
- package/build/server/chunks/{_server.ts-Ch-6iOHp.js → _server.ts-G8OeADGj.js} +141 -89
- package/build/server/chunks/_server.ts-G8OeADGj.js.map +1 -0
- package/build/server/chunks/{auth-DeCdZ83n.js → auth-DuunT7Cg.js} +2 -2
- package/build/server/chunks/{auth-DeCdZ83n.js.map → auth-DuunT7Cg.js.map} +1 -1
- package/build/server/chunks/{client-BdGHe_hY.js → client-DRtPDkMh.js} +4 -4
- package/build/server/chunks/{client-BdGHe_hY.js.map → client-DRtPDkMh.js.map} +1 -1
- package/build/server/chunks/client2-bqqmu0b7.js +7 -0
- package/build/server/chunks/{client2-CCBGA-2V.js.map → client2-bqqmu0b7.js.map} +1 -1
- package/build/server/chunks/close-BGlLztTb.js +192 -0
- package/build/server/chunks/close-BGlLztTb.js.map +1 -0
- package/build/server/chunks/events-handler-Dm1mNPQP.js +20 -0
- package/build/server/chunks/events-handler-Dm1mNPQP.js.map +1 -0
- package/build/server/chunks/html-FW6Ia4bL.js +8 -0
- package/build/server/chunks/html-FW6Ia4bL.js.map +1 -0
- package/build/server/chunks/{shared-server-sSGG17Df.js → index-CoD1IJuy.js} +2 -11
- package/build/server/chunks/index-CoD1IJuy.js.map +1 -0
- package/build/server/chunks/{index-DwaY1cAm.js → index-DP9bWJrR.js} +2 -2
- package/build/server/chunks/{index-DwaY1cAm.js.map → index-DP9bWJrR.js.map} +1 -1
- package/build/server/chunks/{index-server-CrDaL06Y.js → index-server-BUmV4MIG.js} +2 -2
- package/build/server/chunks/index-server-BUmV4MIG.js.map +1 -0
- package/build/server/chunks/index-server2-BJrT0wnA.js +5 -0
- package/build/server/chunks/index-server2-BJrT0wnA.js.map +1 -0
- package/build/server/chunks/{index2-CgclKpUj.js → index2-D5Y19GKR.js} +2 -2
- package/build/server/chunks/index2-D5Y19GKR.js.map +1 -0
- package/build/server/chunks/{library-apns-BqJbvSKh.js → library-apns-Cf-E-DhM.js} +5 -2
- package/build/server/chunks/library-apns-Cf-E-DhM.js.map +1 -0
- package/build/server/chunks/providers-DtstoHQ0.js +17 -0
- package/build/server/chunks/providers-DtstoHQ0.js.map +1 -0
- package/build/server/chunks/{pty-manager-BQVB7IVj.js → pty-manager-TyMUpDA9.js} +41 -9
- package/build/server/chunks/pty-manager-TyMUpDA9.js.map +1 -0
- package/build/server/chunks/{root-DDSnEAZv.js → root-CATOR_0t.js} +2 -2
- package/build/server/chunks/root-CATOR_0t.js.map +1 -0
- package/build/server/chunks/shared-server-DaWdgxVh.js +11 -0
- package/build/server/chunks/shared-server-DaWdgxVh.js.map +1 -0
- package/build/server/chunks/{state.svelte-hBbXlUak.js → state.svelte-CftllyvC.js} +3 -3
- package/build/server/chunks/state.svelte-CftllyvC.js.map +1 -0
- package/build/server/chunks/{stores-DHNzYNpX.js → stores-BjL57aOK.js} +4 -4
- package/build/server/chunks/{stores-DHNzYNpX.js.map → stores-BjL57aOK.js.map} +1 -1
- package/build/server/index.js +173 -6
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +53 -30
- package/build/server/manifest.js.map +1 -1
- package/package.json +24 -6
- package/scripts/dev.mjs +361 -0
- package/scripts/install.sh +11 -3
- package/scripts/{fix-generated-types.sh → postgen-types.sh} +2 -2
- package/scripts/setup.cjs +219 -24
- package/scripts/vercel-env-commands.sh +3 -3
- package/server.ts +3 -3
- package/src/app.html +163 -0
- package/src/lib/modules/client/activity/ActivityFeed.svelte +279 -0
- package/src/lib/modules/client/activity/index.ts +8 -0
- package/src/lib/modules/client/activity/store.svelte.ts +478 -0
- package/src/lib/modules/client/activity/summarizer.ts +224 -0
- package/src/lib/modules/client/common/Card.svelte +2 -9
- package/src/lib/modules/client/common/EmptyState.svelte +2 -20
- package/src/lib/modules/client/common/Icon.svelte +3 -7
- package/src/lib/modules/client/common/StatusBadge.svelte +2 -4
- package/src/lib/modules/client/common/config-guard.ts +22 -2
- package/src/lib/modules/client/common/index.ts +1 -1
- package/src/lib/modules/client/common/time.ts +27 -9
- package/src/lib/modules/client/dashboard/DashboardCard.svelte +374 -0
- package/src/lib/modules/client/dashboard/DashboardView.svelte +66 -0
- package/src/lib/modules/client/dashboard/index.ts +12 -0
- package/src/lib/modules/client/dashboard/store.svelte.ts +663 -0
- package/src/lib/modules/client/dashboard/summarizer.ts +205 -0
- package/src/lib/modules/client/neurolink/fetch-proxy.ts +70 -0
- package/src/lib/modules/client/neurolink/provider-config.ts +111 -0
- package/src/lib/modules/client/terminal/ChatView.svelte +46 -43
- package/src/lib/modules/client/terminal/CommandPalette.svelte +3 -12
- package/src/lib/modules/client/terminal/ConnectionStatus.svelte +3 -6
- package/src/lib/modules/client/terminal/LaunchSheet.svelte +10 -21
- package/src/lib/modules/client/terminal/QuickKeys.svelte +4 -11
- package/src/lib/modules/client/terminal/ShortcutsHelp.svelte +3 -6
- package/src/lib/modules/client/terminal/keyboard-shortcuts.ts +5 -7
- package/src/lib/modules/client/terminal/xterm-wrapper.ts +27 -47
- package/src/lib/modules/server/apn/library-apns.ts +6 -3
- package/src/lib/modules/server/apn/notification-history.ts +2 -2
- package/src/lib/modules/server/apn/notification-sessions.ts +1 -3
- package/src/lib/modules/server/apn/pending-requests.ts +1 -1
- package/src/lib/modules/server/apn/types.ts +2 -52
- package/src/lib/modules/server/cli/index.ts +1 -30
- package/src/lib/modules/server/cli/runner.ts +7 -15
- package/src/lib/modules/server/fcm/fcm-service.ts +2 -2
- package/src/lib/modules/server/sessions/jsonl-parser.ts +97 -42
- package/src/lib/modules/server/sessions/jsonl-reader.ts +144 -76
- package/src/lib/modules/server/sessions/opencode-reader.ts +1 -1
- package/src/lib/modules/server/sessions/process-detector.ts +72 -31
- package/src/lib/modules/server/sessions/types.ts +2 -42
- package/src/lib/modules/server/terminal/holder-client.ts +11 -35
- package/src/lib/modules/server/terminal/opencode-watcher.ts +16 -24
- package/src/lib/modules/server/terminal/pty-manager.ts +40 -45
- package/src/lib/modules/server/terminal/session-watcher.ts +15 -17
- package/src/lib/modules/server/terminal/terminal-store.ts +1 -1
- package/src/lib/modules/server/ws/events-handler.ts +1 -16
- package/src/lib/modules/server/ws/keepalive.ts +1 -5
- package/src/lib/modules/server/ws/server.ts +1 -1
- package/src/lib/modules/server/ws/session-handler.ts +20 -86
- package/src/lib/modules/server/ws/terminal-handler.ts +28 -51
- package/src/lib/modules/server/ws/ticket-store.ts +1 -1
- package/src/lib/modules/shared/providers.ts +21 -0
- package/src/lib/types/activity.ts +18 -0
- package/src/lib/types/apn.ts +43 -0
- package/src/lib/types/cli.ts +39 -0
- package/src/lib/types/common.ts +39 -0
- package/src/lib/types/dashboard.ts +4 -0
- package/src/lib/types/generated/Client.ts +1656 -0
- package/src/{generated/types → lib/types/generated}/WsProtocol.ts +344 -2
- package/src/lib/types/index.ts +28 -0
- package/src/lib/types/neurolink.ts +4 -0
- package/src/lib/types/server.ts +93 -0
- package/src/lib/types/sessions.ts +59 -0
- package/src/lib/types/terminal-client.ts +132 -0
- package/src/lib/types/ws.ts +161 -0
- package/src/routes/+error.svelte +7 -2
- package/src/routes/+layout.server.ts +9 -0
- package/src/routes/+layout.svelte +36 -7
- package/src/routes/+page.server.ts +7 -0
- package/src/routes/+page.svelte +85 -35
- package/src/routes/activity/+page.server.ts +7 -0
- package/src/routes/activity/+page.svelte +58 -0
- package/src/routes/api/health/+server.ts +32 -19
- package/src/routes/api/neurolink-proxy/+server.ts +136 -0
- package/src/routes/api/notify/+server.ts +190 -87
- package/src/routes/api/sessions/+server.ts +1 -1
- package/src/routes/api/sessions/connect/+server.ts +10 -6
- package/src/routes/api/terminals/+server.ts +20 -1
- package/src/routes/api/terminals/[id]/+server.ts +16 -2
- package/src/routes/api/webhook/+server.ts +5 -33
- package/src/routes/api/ws-ticket/+server.ts +4 -4
- package/src/routes/config/+page.server.ts +9 -0
- package/src/routes/config/+page.svelte +118 -25
- package/src/routes/neurolink/+page.server.ts +10 -0
- package/src/routes/neurolink/+page.svelte +331 -0
- package/src/routes/project/+page.svelte +17 -12
- package/src/routes/session/[id]/+page.svelte +146 -62
- package/src/routes/terminals/+page.svelte +2 -2
- package/src/routes/terminals/[id]/+page.svelte +99 -88
- package/svelte.config.js +1 -3
- package/tsconfig.json +1 -0
- package/build/client/_app/immutable/assets/2.CAShZ7lQ.css +0 -1
- package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.br +0 -1
- package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.DGDHCVnW.css.br +0 -0
- package/build/client/_app/immutable/assets/3.DGDHCVnW.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B5NAKyil.js +0 -20
- package/build/client/_app/immutable/chunks/B5NAKyil.js.br +0 -0
- package/build/client/_app/immutable/chunks/B5NAKyil.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B8XegpSE.js +0 -1
- package/build/client/_app/immutable/chunks/B8XegpSE.js.br +0 -0
- package/build/client/_app/immutable/chunks/B8XegpSE.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B8zoBsv3.js +0 -6
- package/build/client/_app/immutable/chunks/B8zoBsv3.js.br +0 -0
- package/build/client/_app/immutable/chunks/B8zoBsv3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BIaXC2t9.js +0 -1
- package/build/client/_app/immutable/chunks/BIaXC2t9.js.br +0 -0
- package/build/client/_app/immutable/chunks/BIaXC2t9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BOYo8yTr.js +0 -1
- package/build/client/_app/immutable/chunks/BOYo8yTr.js.br +0 -0
- package/build/client/_app/immutable/chunks/BOYo8yTr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bu1aqm5j.js +0 -1
- package/build/client/_app/immutable/chunks/Bu1aqm5j.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bu1aqm5j.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CQjSATpv.js +0 -61
- package/build/client/_app/immutable/chunks/CQjSATpv.js.br +0 -0
- package/build/client/_app/immutable/chunks/CQjSATpv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CRbaG9cv.js.br +0 -0
- package/build/client/_app/immutable/chunks/CSoRdFvv.js.br +0 -0
- package/build/client/_app/immutable/chunks/CSoRdFvv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CZHsSL_X.js.br +0 -0
- package/build/client/_app/immutable/chunks/CZHsSL_X.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CiF38mQq.js.br +0 -0
- package/build/client/_app/immutable/chunks/CiF38mQq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DSU1n5N_.js +0 -1
- package/build/client/_app/immutable/chunks/DSU1n5N_.js.br +0 -0
- package/build/client/_app/immutable/chunks/DSU1n5N_.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DVkn4r72.js +0 -1
- package/build/client/_app/immutable/chunks/DVkn4r72.js.br +0 -0
- package/build/client/_app/immutable/chunks/DVkn4r72.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DjsDGxCa.js.br +0 -0
- package/build/client/_app/immutable/chunks/DjsDGxCa.js.gz +0 -0
- package/build/client/_app/immutable/chunks/UJOiqIYE.js.br +0 -0
- package/build/client/_app/immutable/chunks/UJOiqIYE.js.gz +0 -0
- package/build/client/_app/immutable/chunks/r0JawsZc.js +0 -2
- package/build/client/_app/immutable/chunks/r0JawsZc.js.br +0 -0
- package/build/client/_app/immutable/chunks/r0JawsZc.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CU7KVZja.js +0 -2
- package/build/client/_app/immutable/entry/app.CU7KVZja.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CU7KVZja.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.RAMZY19t.js +0 -1
- package/build/client/_app/immutable/entry/start.RAMZY19t.js.br +0 -2
- package/build/client/_app/immutable/entry/start.RAMZY19t.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.Bi3XYMSu.js +0 -1
- package/build/client/_app/immutable/nodes/0.Bi3XYMSu.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.Bi3XYMSu.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.DTmfBFmm.js +0 -1
- package/build/client/_app/immutable/nodes/1.DTmfBFmm.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.DTmfBFmm.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.Cm269yzt.js +0 -1
- package/build/client/_app/immutable/nodes/2.Cm269yzt.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.Cm269yzt.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.3yohCM25.js +0 -3
- package/build/client/_app/immutable/nodes/3.3yohCM25.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.3yohCM25.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.C25c5hMg.js +0 -1
- package/build/client/_app/immutable/nodes/4.C25c5hMg.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.C25c5hMg.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.DIkXVP4q.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.DIkXVP4q.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.BPL-HzUX.js +0 -2
- package/build/client/_app/immutable/nodes/6.BPL-HzUX.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BPL-HzUX.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.IgEqce53.js +0 -2
- package/build/client/_app/immutable/nodes/7.IgEqce53.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.IgEqce53.js.gz +0 -0
- package/build/server/chunks/0-DiORznXb.js +0 -9
- package/build/server/chunks/0-DiORznXb.js.map +0 -1
- package/build/server/chunks/1-D0N7vVhH.js +0 -9
- package/build/server/chunks/2-DfSav7a7.js +0 -9
- package/build/server/chunks/2-DfSav7a7.js.map +0 -1
- package/build/server/chunks/3-Ck7ewhOX.js +0 -9
- package/build/server/chunks/3-Ck7ewhOX.js.map +0 -1
- package/build/server/chunks/4-DV5MZUz_.js +0 -9
- package/build/server/chunks/4-DV5MZUz_.js.map +0 -1
- package/build/server/chunks/5-DJhoAjb0.js +0 -9
- package/build/server/chunks/5-DJhoAjb0.js.map +0 -1
- package/build/server/chunks/6-Cp8CzYbr.js +0 -9
- package/build/server/chunks/6-Cp8CzYbr.js.map +0 -1
- package/build/server/chunks/7-BA4xzUj3.js +0 -9
- package/build/server/chunks/7-BA4xzUj3.js.map +0 -1
- package/build/server/chunks/Button-Cs1aE6ka.js.map +0 -1
- package/build/server/chunks/Icon-CEUrotA6.js.map +0 -1
- package/build/server/chunks/_layout.svelte-CtWmEJwe.js.map +0 -1
- package/build/server/chunks/_page.svelte-BdYynOck.js +0 -85
- package/build/server/chunks/_page.svelte-BdYynOck.js.map +0 -1
- package/build/server/chunks/_page.svelte-CVq6tRb3.js.map +0 -1
- package/build/server/chunks/_page.svelte-CxWcQ0Am.js.map +0 -1
- package/build/server/chunks/_server.ts-BStnNIcq.js +0 -34
- package/build/server/chunks/_server.ts-BStnNIcq.js.map +0 -1
- package/build/server/chunks/_server.ts-CAxsWKvS.js.map +0 -1
- package/build/server/chunks/_server.ts-COu0vNpd.js.map +0 -1
- package/build/server/chunks/_server.ts-CTpcLUH8.js.map +0 -1
- package/build/server/chunks/_server.ts-Cf84YIaW.js +0 -25
- package/build/server/chunks/_server.ts-Cf84YIaW.js.map +0 -1
- package/build/server/chunks/_server.ts-Ch-6iOHp.js.map +0 -1
- package/build/server/chunks/_server.ts-CtH0dhUp.js +0 -71
- package/build/server/chunks/_server.ts-CtH0dhUp.js.map +0 -1
- package/build/server/chunks/_server.ts-DB_Kg97c.js.map +0 -1
- package/build/server/chunks/_server.ts-DYpJImqd.js.map +0 -1
- package/build/server/chunks/_server.ts-Deok2y88.js.map +0 -1
- package/build/server/chunks/_server.ts-tSpgyl1D.js.map +0 -1
- package/build/server/chunks/_server.ts-vekTmWAx.js.map +0 -1
- package/build/server/chunks/client2-CCBGA-2V.js +0 -7
- package/build/server/chunks/index-server-CrDaL06Y.js.map +0 -1
- package/build/server/chunks/index2-CgclKpUj.js.map +0 -1
- package/build/server/chunks/library-apns-BqJbvSKh.js.map +0 -1
- package/build/server/chunks/pty-manager-BQVB7IVj.js.map +0 -1
- package/build/server/chunks/root-DDSnEAZv.js.map +0 -1
- package/build/server/chunks/shared-server-sSGG17Df.js.map +0 -1
- package/build/server/chunks/state.svelte-hBbXlUak.js.map +0 -1
- package/src/generated/types/Client.ts +0 -589
- package/src/lib/types/config.ts +0 -1
- /package/build/client/_app/immutable/assets/{4.BFUut--w.css → 6.BFUut--w.css} +0 -0
- /package/build/client/_app/immutable/assets/{4.BFUut--w.css.br → 6.BFUut--w.css.br} +0 -0
- /package/build/client/_app/immutable/assets/{4.BFUut--w.css.gz → 6.BFUut--w.css.gz} +0 -0
- /package/build/client/_app/immutable/assets/{5.BTOx7yt7.css → 7.BTOx7yt7.css} +0 -0
- /package/build/client/_app/immutable/assets/{5.BTOx7yt7.css.br → 7.BTOx7yt7.css.br} +0 -0
- /package/build/client/_app/immutable/assets/{5.BTOx7yt7.css.gz → 7.BTOx7yt7.css.gz} +0 -0
- /package/build/client/_app/immutable/assets/{6.eZGZN-BF.css → 8.eZGZN-BF.css} +0 -0
- /package/build/client/_app/immutable/assets/{6.eZGZN-BF.css.br → 8.eZGZN-BF.css.br} +0 -0
- /package/build/client/_app/immutable/assets/{6.eZGZN-BF.css.gz → 8.eZGZN-BF.css.gz} +0 -0
- /package/build/client/_app/immutable/assets/{7.DwS5ZHBh.css → 9.DwS5ZHBh.css} +0 -0
- /package/build/client/_app/immutable/assets/{7.DwS5ZHBh.css.br → 9.DwS5ZHBh.css.br} +0 -0
- /package/build/client/_app/immutable/assets/{7.DwS5ZHBh.css.gz → 9.DwS5ZHBh.css.gz} +0 -0
- /package/src/{generated/types → lib/types/generated}/API.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/APN.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/CLI.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/Config.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/Holder.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/JWT.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/Notification.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/OpenCode.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/Sessions.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/Terminal.ts +0 -0
- /package/src/{generated/types → lib/types/generated}/index.ts +0 -0
|
@@ -0,0 +1,1656 @@
|
|
|
1
|
+
import { type SessionSource, decodeSessionSource } from './index';
|
|
2
|
+
import {
|
|
3
|
+
isJSON,
|
|
4
|
+
decodeString,
|
|
5
|
+
_decodeString,
|
|
6
|
+
decodeArray,
|
|
7
|
+
_decodeArray,
|
|
8
|
+
decodeNumber,
|
|
9
|
+
_decodeNumber,
|
|
10
|
+
decodeBoolean,
|
|
11
|
+
_decodeBoolean,
|
|
12
|
+
} from 'type-decoder';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @type { ClientTerminalStatus }
|
|
16
|
+
* @description Whether a client-side terminal view is running or has exited
|
|
17
|
+
*/
|
|
18
|
+
export type ClientTerminalStatus = 'running' | 'exited';
|
|
19
|
+
|
|
20
|
+
export function decodeClientTerminalStatus(rawInput: unknown): ClientTerminalStatus | null {
|
|
21
|
+
switch (rawInput) {
|
|
22
|
+
case 'running':
|
|
23
|
+
case 'exited':
|
|
24
|
+
return rawInput;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function _decodeClientTerminalStatus(rawInput: unknown): ClientTerminalStatus | undefined {
|
|
30
|
+
switch (rawInput) {
|
|
31
|
+
case 'running':
|
|
32
|
+
case 'exited':
|
|
33
|
+
return rawInput;
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @type { SessionMessage }
|
|
40
|
+
* @description A conversation message entry
|
|
41
|
+
*/
|
|
42
|
+
export type SessionMessage = {
|
|
43
|
+
/**
|
|
44
|
+
* @description Unique message identifier
|
|
45
|
+
* @type { string }
|
|
46
|
+
* @memberof SessionMessage
|
|
47
|
+
*/
|
|
48
|
+
id: string;
|
|
49
|
+
/**
|
|
50
|
+
* @description Message type discriminator (e.g. "user", "assistant", "tool-use", "tool-result")
|
|
51
|
+
* @type { string }
|
|
52
|
+
* @memberof SessionMessage
|
|
53
|
+
*/
|
|
54
|
+
type: string;
|
|
55
|
+
/**
|
|
56
|
+
* @description Primary text content of the message
|
|
57
|
+
* @type { string }
|
|
58
|
+
* @memberof SessionMessage
|
|
59
|
+
*/
|
|
60
|
+
content: string;
|
|
61
|
+
/**
|
|
62
|
+
* @description ISO 8601 timestamp of the message
|
|
63
|
+
* @type { string }
|
|
64
|
+
* @memberof SessionMessage
|
|
65
|
+
*/
|
|
66
|
+
timestamp: string;
|
|
67
|
+
[keys: string]: unknown;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export function decodeSessionMessage(rawInput: unknown): SessionMessage | null {
|
|
71
|
+
if (isJSON(rawInput)) {
|
|
72
|
+
const decodedId = decodeString(rawInput['id']);
|
|
73
|
+
const decodedType = decodeString(rawInput['type']);
|
|
74
|
+
const decodedContent = decodeString(rawInput['content']);
|
|
75
|
+
const decodedTimestamp = decodeString(rawInput['timestamp']);
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
decodedId === null ||
|
|
79
|
+
decodedType === null ||
|
|
80
|
+
decodedContent === null ||
|
|
81
|
+
decodedTimestamp === null
|
|
82
|
+
) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
...rawInput,
|
|
88
|
+
id: decodedId,
|
|
89
|
+
type: decodedType,
|
|
90
|
+
content: decodedContent,
|
|
91
|
+
timestamp: decodedTimestamp,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @type { TerminalListItem }
|
|
99
|
+
* @description Terminal entry displayed in the /terminals list page
|
|
100
|
+
*/
|
|
101
|
+
export type TerminalListItem = {
|
|
102
|
+
/**
|
|
103
|
+
* @description Unique terminal identifier
|
|
104
|
+
* @type { string }
|
|
105
|
+
* @memberof TerminalListItem
|
|
106
|
+
*/
|
|
107
|
+
id: string;
|
|
108
|
+
/**
|
|
109
|
+
* @description The command that was launched (e.g. "zsh", "claude")
|
|
110
|
+
* @type { string }
|
|
111
|
+
* @memberof TerminalListItem
|
|
112
|
+
*/
|
|
113
|
+
command: string;
|
|
114
|
+
/**
|
|
115
|
+
* @description Command arguments passed at launch
|
|
116
|
+
* @type { string[] }
|
|
117
|
+
* @memberof TerminalListItem
|
|
118
|
+
*/
|
|
119
|
+
args: string[];
|
|
120
|
+
/**
|
|
121
|
+
* @description Working directory the terminal was launched in
|
|
122
|
+
* @type { string }
|
|
123
|
+
* @memberof TerminalListItem
|
|
124
|
+
*/
|
|
125
|
+
cwd: string;
|
|
126
|
+
/**
|
|
127
|
+
* @description Current working directory detected via OSC 7, or null if not yet detected
|
|
128
|
+
* @type { string }
|
|
129
|
+
* @memberof TerminalListItem
|
|
130
|
+
*/
|
|
131
|
+
currentCwd: string | null;
|
|
132
|
+
/**
|
|
133
|
+
* @description OS process ID of the terminal process
|
|
134
|
+
* @type { number }
|
|
135
|
+
* @memberof TerminalListItem
|
|
136
|
+
*/
|
|
137
|
+
pid: number;
|
|
138
|
+
/**
|
|
139
|
+
* @description ISO 8601 timestamp when the terminal was created
|
|
140
|
+
* @type { string }
|
|
141
|
+
* @memberof TerminalListItem
|
|
142
|
+
*/
|
|
143
|
+
createdAt: string;
|
|
144
|
+
/**
|
|
145
|
+
* @description ISO 8601 timestamp when the process exited, or null if still running
|
|
146
|
+
* @type { string }
|
|
147
|
+
* @memberof TerminalListItem
|
|
148
|
+
*/
|
|
149
|
+
exitedAt: string | null;
|
|
150
|
+
/**
|
|
151
|
+
* @description Whether the terminal is running or has exited
|
|
152
|
+
* @type { ClientTerminalStatus }
|
|
153
|
+
* @memberof TerminalListItem
|
|
154
|
+
*/
|
|
155
|
+
status: ClientTerminalStatus;
|
|
156
|
+
/**
|
|
157
|
+
* @description Process exit code, or null if still running
|
|
158
|
+
* @type { number }
|
|
159
|
+
* @memberof TerminalListItem
|
|
160
|
+
*/
|
|
161
|
+
exitCode: number | null;
|
|
162
|
+
/**
|
|
163
|
+
* @description Whether the terminal is currently producing output
|
|
164
|
+
* @type { boolean }
|
|
165
|
+
* @memberof TerminalListItem
|
|
166
|
+
*/
|
|
167
|
+
isActive: boolean | null;
|
|
168
|
+
/**
|
|
169
|
+
* @description Most recent output line for preview display, or null if none
|
|
170
|
+
* @type { string }
|
|
171
|
+
* @memberof TerminalListItem
|
|
172
|
+
*/
|
|
173
|
+
lastOutput: string | null;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export function decodeTerminalListItem(rawInput: unknown): TerminalListItem | null {
|
|
177
|
+
if (isJSON(rawInput)) {
|
|
178
|
+
const decodedId = decodeString(rawInput['id']);
|
|
179
|
+
const decodedCommand = decodeString(rawInput['command']);
|
|
180
|
+
const decodedArgs = decodeArray(rawInput['args'], decodeString);
|
|
181
|
+
const decodedCwd = decodeString(rawInput['cwd']);
|
|
182
|
+
const decodedCurrentCwd = decodeString(rawInput['currentCwd']);
|
|
183
|
+
const decodedPid = decodeNumber(rawInput['pid']);
|
|
184
|
+
const decodedCreatedAt = decodeString(rawInput['createdAt']);
|
|
185
|
+
const decodedExitedAt = decodeString(rawInput['exitedAt']);
|
|
186
|
+
const decodedStatus = decodeClientTerminalStatus(rawInput['status']);
|
|
187
|
+
const decodedExitCode = decodeNumber(rawInput['exitCode']);
|
|
188
|
+
const decodedIsActive = decodeBoolean(rawInput['isActive']);
|
|
189
|
+
const decodedLastOutput = decodeString(rawInput['lastOutput']);
|
|
190
|
+
|
|
191
|
+
if (
|
|
192
|
+
decodedId === null ||
|
|
193
|
+
decodedCommand === null ||
|
|
194
|
+
decodedArgs === null ||
|
|
195
|
+
decodedCwd === null ||
|
|
196
|
+
decodedPid === null ||
|
|
197
|
+
decodedCreatedAt === null ||
|
|
198
|
+
decodedStatus === null
|
|
199
|
+
) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
id: decodedId,
|
|
205
|
+
command: decodedCommand,
|
|
206
|
+
args: decodedArgs,
|
|
207
|
+
cwd: decodedCwd,
|
|
208
|
+
currentCwd: decodedCurrentCwd,
|
|
209
|
+
pid: decodedPid,
|
|
210
|
+
createdAt: decodedCreatedAt,
|
|
211
|
+
exitedAt: decodedExitedAt,
|
|
212
|
+
status: decodedStatus,
|
|
213
|
+
exitCode: decodedExitCode,
|
|
214
|
+
isActive: decodedIsActive,
|
|
215
|
+
lastOutput: decodedLastOutput,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @type { TerminalDetailView }
|
|
223
|
+
* @description Terminal data used by the /terminals/[id] detail page
|
|
224
|
+
*/
|
|
225
|
+
export type TerminalDetailView = {
|
|
226
|
+
/**
|
|
227
|
+
* @description Unique terminal identifier
|
|
228
|
+
* @type { string }
|
|
229
|
+
* @memberof TerminalDetailView
|
|
230
|
+
*/
|
|
231
|
+
id: string;
|
|
232
|
+
/**
|
|
233
|
+
* @description The command that was launched
|
|
234
|
+
* @type { string }
|
|
235
|
+
* @memberof TerminalDetailView
|
|
236
|
+
*/
|
|
237
|
+
command: string;
|
|
238
|
+
/**
|
|
239
|
+
* @description Command arguments passed at launch
|
|
240
|
+
* @type { string[] }
|
|
241
|
+
* @memberof TerminalDetailView
|
|
242
|
+
*/
|
|
243
|
+
args: string[];
|
|
244
|
+
/**
|
|
245
|
+
* @description Working directory the terminal was launched in
|
|
246
|
+
* @type { string }
|
|
247
|
+
* @memberof TerminalDetailView
|
|
248
|
+
*/
|
|
249
|
+
cwd: string;
|
|
250
|
+
/**
|
|
251
|
+
* @description OS process ID of the terminal process
|
|
252
|
+
* @type { number }
|
|
253
|
+
* @memberof TerminalDetailView
|
|
254
|
+
*/
|
|
255
|
+
pid: number;
|
|
256
|
+
/**
|
|
257
|
+
* @description ISO 8601 timestamp when the terminal was created
|
|
258
|
+
* @type { string }
|
|
259
|
+
* @memberof TerminalDetailView
|
|
260
|
+
*/
|
|
261
|
+
createdAt: string;
|
|
262
|
+
/**
|
|
263
|
+
* @description ISO 8601 timestamp when the process exited, or null if still running
|
|
264
|
+
* @type { string }
|
|
265
|
+
* @memberof TerminalDetailView
|
|
266
|
+
*/
|
|
267
|
+
exitedAt: string | null;
|
|
268
|
+
/**
|
|
269
|
+
* @description Whether the terminal is running or has exited
|
|
270
|
+
* @type { ClientTerminalStatus }
|
|
271
|
+
* @memberof TerminalDetailView
|
|
272
|
+
*/
|
|
273
|
+
status: ClientTerminalStatus;
|
|
274
|
+
/**
|
|
275
|
+
* @description Process exit code, or null if still running
|
|
276
|
+
* @type { number }
|
|
277
|
+
* @memberof TerminalDetailView
|
|
278
|
+
*/
|
|
279
|
+
exitCode: number | null;
|
|
280
|
+
/**
|
|
281
|
+
* @description Number of WebSocket clients currently attached to this terminal
|
|
282
|
+
* @type { number }
|
|
283
|
+
* @memberof TerminalDetailView
|
|
284
|
+
*/
|
|
285
|
+
clientCount: number | null;
|
|
286
|
+
/**
|
|
287
|
+
* @description Most recent scrollback line for preview display, or null if empty
|
|
288
|
+
* @type { string }
|
|
289
|
+
* @memberof TerminalDetailView
|
|
290
|
+
*/
|
|
291
|
+
lastOutput: string | null;
|
|
292
|
+
/**
|
|
293
|
+
* @description ISO 8601 timestamp when this response was generated
|
|
294
|
+
* @type { string }
|
|
295
|
+
* @memberof TerminalDetailView
|
|
296
|
+
*/
|
|
297
|
+
timestamp: string | null;
|
|
298
|
+
/**
|
|
299
|
+
* @description WebSocket path for raw terminal I/O
|
|
300
|
+
* @type { string }
|
|
301
|
+
* @memberof TerminalDetailView
|
|
302
|
+
*/
|
|
303
|
+
ws: string;
|
|
304
|
+
/**
|
|
305
|
+
* @description WebSocket path for structured session stream
|
|
306
|
+
* @type { string }
|
|
307
|
+
* @memberof TerminalDetailView
|
|
308
|
+
*/
|
|
309
|
+
sessionWs: string;
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
export function decodeTerminalDetailView(rawInput: unknown): TerminalDetailView | null {
|
|
313
|
+
if (isJSON(rawInput)) {
|
|
314
|
+
const decodedId = decodeString(rawInput['id']);
|
|
315
|
+
const decodedCommand = decodeString(rawInput['command']);
|
|
316
|
+
const decodedArgs = decodeArray(rawInput['args'], decodeString);
|
|
317
|
+
const decodedCwd = decodeString(rawInput['cwd']);
|
|
318
|
+
const decodedPid = decodeNumber(rawInput['pid']);
|
|
319
|
+
const decodedCreatedAt = decodeString(rawInput['createdAt']);
|
|
320
|
+
const decodedExitedAt = decodeString(rawInput['exitedAt']);
|
|
321
|
+
const decodedStatus = decodeClientTerminalStatus(rawInput['status']);
|
|
322
|
+
const decodedExitCode = decodeNumber(rawInput['exitCode']);
|
|
323
|
+
const decodedClientCount = decodeNumber(rawInput['clientCount']);
|
|
324
|
+
const decodedLastOutput = decodeString(rawInput['lastOutput']);
|
|
325
|
+
const decodedTimestamp = decodeString(rawInput['timestamp']);
|
|
326
|
+
const decodedWs = decodeString(rawInput['ws']);
|
|
327
|
+
const decodedSessionWs = decodeString(rawInput['sessionWs']);
|
|
328
|
+
|
|
329
|
+
if (
|
|
330
|
+
decodedId === null ||
|
|
331
|
+
decodedCommand === null ||
|
|
332
|
+
decodedArgs === null ||
|
|
333
|
+
decodedCwd === null ||
|
|
334
|
+
decodedPid === null ||
|
|
335
|
+
decodedCreatedAt === null ||
|
|
336
|
+
decodedStatus === null ||
|
|
337
|
+
decodedWs === null ||
|
|
338
|
+
decodedSessionWs === null
|
|
339
|
+
) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
id: decodedId,
|
|
345
|
+
command: decodedCommand,
|
|
346
|
+
args: decodedArgs,
|
|
347
|
+
cwd: decodedCwd,
|
|
348
|
+
pid: decodedPid,
|
|
349
|
+
createdAt: decodedCreatedAt,
|
|
350
|
+
exitedAt: decodedExitedAt,
|
|
351
|
+
status: decodedStatus,
|
|
352
|
+
exitCode: decodedExitCode,
|
|
353
|
+
clientCount: decodedClientCount,
|
|
354
|
+
lastOutput: decodedLastOutput,
|
|
355
|
+
timestamp: decodedTimestamp,
|
|
356
|
+
ws: decodedWs,
|
|
357
|
+
sessionWs: decodedSessionWs,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* @type { SessionViewResponse }
|
|
365
|
+
* @description API response shape for fetching a single session with its conversation messages
|
|
366
|
+
*/
|
|
367
|
+
export type SessionViewResponse = {
|
|
368
|
+
/**
|
|
369
|
+
* @description Session metadata
|
|
370
|
+
* @type { SessionViewResponseSession }
|
|
371
|
+
* @memberof SessionViewResponse
|
|
372
|
+
*/
|
|
373
|
+
session: SessionViewResponseSession;
|
|
374
|
+
/**
|
|
375
|
+
* @description Conversation messages in the session
|
|
376
|
+
* @type { SessionMessage[] }
|
|
377
|
+
* @memberof SessionViewResponse
|
|
378
|
+
*/
|
|
379
|
+
messages: SessionMessage[];
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
export function decodeSessionViewResponse(rawInput: unknown): SessionViewResponse | null {
|
|
383
|
+
if (isJSON(rawInput)) {
|
|
384
|
+
const decodedSession = decodeSessionViewResponseSession(rawInput['session']);
|
|
385
|
+
const decodedMessages = decodeArray(rawInput['messages'], decodeSessionMessage);
|
|
386
|
+
|
|
387
|
+
if (decodedSession === null || decodedMessages === null) {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return {
|
|
392
|
+
session: decodedSession,
|
|
393
|
+
messages: decodedMessages,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* @type { SessionViewResponseSession }
|
|
401
|
+
* @description Session metadata
|
|
402
|
+
*/
|
|
403
|
+
export type SessionViewResponseSession = {
|
|
404
|
+
/**
|
|
405
|
+
* @description Unique session identifier
|
|
406
|
+
* @type { string }
|
|
407
|
+
* @memberof SessionViewResponseSession
|
|
408
|
+
*/
|
|
409
|
+
id: string;
|
|
410
|
+
/**
|
|
411
|
+
* @description Human-readable session title
|
|
412
|
+
* @type { string }
|
|
413
|
+
* @memberof SessionViewResponseSession
|
|
414
|
+
*/
|
|
415
|
+
title: string;
|
|
416
|
+
/**
|
|
417
|
+
* @description Absolute path to the project directory
|
|
418
|
+
* @type { string }
|
|
419
|
+
* @memberof SessionViewResponseSession
|
|
420
|
+
*/
|
|
421
|
+
projectPath: string;
|
|
422
|
+
/**
|
|
423
|
+
* @description Git branch active during the session
|
|
424
|
+
* @type { string }
|
|
425
|
+
* @memberof SessionViewResponseSession
|
|
426
|
+
*/
|
|
427
|
+
gitBranch: string;
|
|
428
|
+
/**
|
|
429
|
+
* @description Total number of messages in the session
|
|
430
|
+
* @type { number }
|
|
431
|
+
* @memberof SessionViewResponseSession
|
|
432
|
+
*/
|
|
433
|
+
messageCount: number;
|
|
434
|
+
/**
|
|
435
|
+
* @description ISO 8601 timestamp when the session started
|
|
436
|
+
* @type { string }
|
|
437
|
+
* @memberof SessionViewResponseSession
|
|
438
|
+
*/
|
|
439
|
+
created: string;
|
|
440
|
+
/**
|
|
441
|
+
* @description ISO 8601 timestamp of the last session update
|
|
442
|
+
* @type { string }
|
|
443
|
+
* @memberof SessionViewResponseSession
|
|
444
|
+
*/
|
|
445
|
+
modified: string;
|
|
446
|
+
/**
|
|
447
|
+
* @description Brief summary of the session content
|
|
448
|
+
* @type { string }
|
|
449
|
+
* @memberof SessionViewResponseSession
|
|
450
|
+
*/
|
|
451
|
+
summary: string;
|
|
452
|
+
/**
|
|
453
|
+
* @description Source tool that created the session
|
|
454
|
+
* @type { SessionSource }
|
|
455
|
+
* @memberof SessionViewResponseSession
|
|
456
|
+
*/
|
|
457
|
+
source: SessionSource;
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
export function decodeSessionViewResponseSession(
|
|
461
|
+
rawInput: unknown
|
|
462
|
+
): SessionViewResponseSession | null {
|
|
463
|
+
if (isJSON(rawInput)) {
|
|
464
|
+
const decodedId = decodeString(rawInput['id']);
|
|
465
|
+
const decodedTitle = decodeString(rawInput['title']);
|
|
466
|
+
const decodedProjectPath = decodeString(rawInput['projectPath']);
|
|
467
|
+
const decodedGitBranch = decodeString(rawInput['gitBranch']);
|
|
468
|
+
const decodedMessageCount = decodeNumber(rawInput['messageCount']);
|
|
469
|
+
const decodedCreated = decodeString(rawInput['created']);
|
|
470
|
+
const decodedModified = decodeString(rawInput['modified']);
|
|
471
|
+
const decodedSummary = decodeString(rawInput['summary']);
|
|
472
|
+
const decodedSource = decodeSessionSource(rawInput['source']);
|
|
473
|
+
|
|
474
|
+
if (
|
|
475
|
+
decodedId === null ||
|
|
476
|
+
decodedTitle === null ||
|
|
477
|
+
decodedProjectPath === null ||
|
|
478
|
+
decodedGitBranch === null ||
|
|
479
|
+
decodedMessageCount === null ||
|
|
480
|
+
decodedCreated === null ||
|
|
481
|
+
decodedModified === null ||
|
|
482
|
+
decodedSummary === null ||
|
|
483
|
+
decodedSource === null
|
|
484
|
+
) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return {
|
|
489
|
+
id: decodedId,
|
|
490
|
+
title: decodedTitle,
|
|
491
|
+
projectPath: decodedProjectPath,
|
|
492
|
+
gitBranch: decodedGitBranch,
|
|
493
|
+
messageCount: decodedMessageCount,
|
|
494
|
+
created: decodedCreated,
|
|
495
|
+
modified: decodedModified,
|
|
496
|
+
summary: decodedSummary,
|
|
497
|
+
source: decodedSource,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* @type { ShortcutAction }
|
|
505
|
+
* @description A keyboard shortcut definition for the terminal help overlay
|
|
506
|
+
*/
|
|
507
|
+
export type ShortcutAction = {
|
|
508
|
+
/**
|
|
509
|
+
* @description Key character that triggers the shortcut (e.g. "/", "k")
|
|
510
|
+
* @type { string }
|
|
511
|
+
* @memberof ShortcutAction
|
|
512
|
+
*/
|
|
513
|
+
key: string;
|
|
514
|
+
/**
|
|
515
|
+
* @description Human-readable key combo label shown in the UI (e.g. "Cmd+/")
|
|
516
|
+
* @type { string }
|
|
517
|
+
* @memberof ShortcutAction
|
|
518
|
+
*/
|
|
519
|
+
label: string;
|
|
520
|
+
/**
|
|
521
|
+
* @description What the shortcut does
|
|
522
|
+
* @type { string }
|
|
523
|
+
* @memberof ShortcutAction
|
|
524
|
+
*/
|
|
525
|
+
description: string;
|
|
526
|
+
/**
|
|
527
|
+
* @description Whether the shift modifier is also required
|
|
528
|
+
* @type { boolean }
|
|
529
|
+
* @memberof ShortcutAction
|
|
530
|
+
*/
|
|
531
|
+
shift: boolean | null;
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
export function decodeShortcutAction(rawInput: unknown): ShortcutAction | null {
|
|
535
|
+
if (isJSON(rawInput)) {
|
|
536
|
+
const decodedKey = decodeString(rawInput['key']);
|
|
537
|
+
const decodedLabel = decodeString(rawInput['label']);
|
|
538
|
+
const decodedDescription = decodeString(rawInput['description']);
|
|
539
|
+
const decodedShift = decodeBoolean(rawInput['shift']);
|
|
540
|
+
|
|
541
|
+
if (decodedKey === null || decodedLabel === null || decodedDescription === null) {
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return {
|
|
546
|
+
key: decodedKey,
|
|
547
|
+
label: decodedLabel,
|
|
548
|
+
description: decodedDescription,
|
|
549
|
+
shift: decodedShift,
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* @type { SessionStatus }
|
|
557
|
+
* @description Lifecycle status of a dashboard session card
|
|
558
|
+
*/
|
|
559
|
+
export type SessionStatus = 'running' | 'idle' | 'exited' | 'error';
|
|
560
|
+
|
|
561
|
+
export function decodeSessionStatus(rawInput: unknown): SessionStatus | null {
|
|
562
|
+
switch (rawInput) {
|
|
563
|
+
case 'running':
|
|
564
|
+
case 'idle':
|
|
565
|
+
case 'exited':
|
|
566
|
+
case 'error':
|
|
567
|
+
return rawInput;
|
|
568
|
+
}
|
|
569
|
+
return null;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export function _decodeSessionStatus(rawInput: unknown): SessionStatus | undefined {
|
|
573
|
+
switch (rawInput) {
|
|
574
|
+
case 'running':
|
|
575
|
+
case 'idle':
|
|
576
|
+
case 'exited':
|
|
577
|
+
case 'error':
|
|
578
|
+
return rawInput;
|
|
579
|
+
}
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* @type { SessionEvent }
|
|
585
|
+
* @description A single event recorded from the /ws/events WebSocket channel for a session
|
|
586
|
+
*/
|
|
587
|
+
export type SessionEvent = {
|
|
588
|
+
/**
|
|
589
|
+
* @description Raw event payload received from the server
|
|
590
|
+
* @type { SessionEventData }
|
|
591
|
+
* @memberof SessionEvent
|
|
592
|
+
*/
|
|
593
|
+
data: SessionEventData;
|
|
594
|
+
/**
|
|
595
|
+
* @description Unique event identifier (e.g. "evt-1", "evt-42")
|
|
596
|
+
* @type { string }
|
|
597
|
+
* @memberof SessionEvent
|
|
598
|
+
*/
|
|
599
|
+
id: string;
|
|
600
|
+
/**
|
|
601
|
+
* @description Whether this event has been included in an AI summary
|
|
602
|
+
* @type { boolean }
|
|
603
|
+
* @memberof SessionEvent
|
|
604
|
+
*/
|
|
605
|
+
summarized: boolean;
|
|
606
|
+
/**
|
|
607
|
+
* @description Terminal identifier this event belongs to
|
|
608
|
+
* @type { string }
|
|
609
|
+
* @memberof SessionEvent
|
|
610
|
+
*/
|
|
611
|
+
terminalId: string;
|
|
612
|
+
/**
|
|
613
|
+
* @description ISO 8601 timestamp of the event
|
|
614
|
+
* @type { string }
|
|
615
|
+
* @memberof SessionEvent
|
|
616
|
+
*/
|
|
617
|
+
timestamp: string;
|
|
618
|
+
/**
|
|
619
|
+
* @description Event type discriminator (e.g. "tool-started", "tool-failed", "agent-idle")
|
|
620
|
+
* @type { string }
|
|
621
|
+
* @memberof SessionEvent
|
|
622
|
+
*/
|
|
623
|
+
type: string;
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
export function decodeSessionEvent(rawInput: unknown): SessionEvent | null {
|
|
627
|
+
if (isJSON(rawInput)) {
|
|
628
|
+
const decodedData = decodeSessionEventData(rawInput['data']);
|
|
629
|
+
const decodedId = decodeString(rawInput['id']);
|
|
630
|
+
const decodedSummarized = decodeBoolean(rawInput['summarized']);
|
|
631
|
+
const decodedTerminalId = decodeString(rawInput['terminalId']);
|
|
632
|
+
const decodedTimestamp = decodeString(rawInput['timestamp']);
|
|
633
|
+
const decodedType = decodeString(rawInput['type']);
|
|
634
|
+
|
|
635
|
+
if (
|
|
636
|
+
decodedData === null ||
|
|
637
|
+
decodedId === null ||
|
|
638
|
+
decodedSummarized === null ||
|
|
639
|
+
decodedTerminalId === null ||
|
|
640
|
+
decodedTimestamp === null ||
|
|
641
|
+
decodedType === null
|
|
642
|
+
) {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return {
|
|
647
|
+
data: decodedData,
|
|
648
|
+
id: decodedId,
|
|
649
|
+
summarized: decodedSummarized,
|
|
650
|
+
terminalId: decodedTerminalId,
|
|
651
|
+
timestamp: decodedTimestamp,
|
|
652
|
+
type: decodedType,
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* @type { SessionEventData }
|
|
660
|
+
* @description Raw event payload received from the server
|
|
661
|
+
*/
|
|
662
|
+
export type SessionEventData = Record<string, unknown>;
|
|
663
|
+
|
|
664
|
+
export function decodeSessionEventData(rawInput: unknown): SessionEventData | null {
|
|
665
|
+
if (isJSON(rawInput)) {
|
|
666
|
+
return {
|
|
667
|
+
...rawInput,
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
return null;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* @type { SessionState }
|
|
675
|
+
* @description Live state of one session card tracked by the dashboard store
|
|
676
|
+
*/
|
|
677
|
+
export type SessionState = {
|
|
678
|
+
/**
|
|
679
|
+
* @description The command running in the terminal (e.g. "claude", "opencode")
|
|
680
|
+
* @type { string }
|
|
681
|
+
* @memberof SessionState
|
|
682
|
+
*/
|
|
683
|
+
command: string;
|
|
684
|
+
/**
|
|
685
|
+
* @description ISO 8601 timestamp when the terminal was created
|
|
686
|
+
* @type { string }
|
|
687
|
+
* @memberof SessionState
|
|
688
|
+
*/
|
|
689
|
+
createdAt: string;
|
|
690
|
+
/**
|
|
691
|
+
* @description Working directory path of the terminal
|
|
692
|
+
* @type { string }
|
|
693
|
+
* @memberof SessionState
|
|
694
|
+
*/
|
|
695
|
+
cwd: string;
|
|
696
|
+
/**
|
|
697
|
+
* @description Total number of error events accumulated in this session
|
|
698
|
+
* @type { number }
|
|
699
|
+
* @memberof SessionState
|
|
700
|
+
*/
|
|
701
|
+
errorCount: number;
|
|
702
|
+
/**
|
|
703
|
+
* @description Total events received (including truncated ones beyond the ring buffer)
|
|
704
|
+
* @type { number }
|
|
705
|
+
* @memberof SessionState
|
|
706
|
+
*/
|
|
707
|
+
eventCount: number;
|
|
708
|
+
/**
|
|
709
|
+
* @description Recent events ring buffer (capped at 100 entries)
|
|
710
|
+
* @type { SessionEvent[] }
|
|
711
|
+
* @memberof SessionState
|
|
712
|
+
*/
|
|
713
|
+
events: SessionEvent[];
|
|
714
|
+
/**
|
|
715
|
+
* @description ISO 8601 timestamp when the terminal exited, or null if still running
|
|
716
|
+
* @type { string }
|
|
717
|
+
* @memberof SessionState
|
|
718
|
+
*/
|
|
719
|
+
exitedAt: string | null;
|
|
720
|
+
/**
|
|
721
|
+
* @description What Claude is working on (extracted from first user message), or null if not yet known
|
|
722
|
+
* @type { string }
|
|
723
|
+
* @memberof SessionState
|
|
724
|
+
*/
|
|
725
|
+
goal: string | null;
|
|
726
|
+
/**
|
|
727
|
+
* @description Whether an AI summary is currently being generated for this session
|
|
728
|
+
* @type { boolean }
|
|
729
|
+
* @memberof SessionState
|
|
730
|
+
*/
|
|
731
|
+
isSummarizing: boolean;
|
|
732
|
+
/**
|
|
733
|
+
* @description Display name of the project (basename of cwd)
|
|
734
|
+
* @type { string }
|
|
735
|
+
* @memberof SessionState
|
|
736
|
+
*/
|
|
737
|
+
projectName: string;
|
|
738
|
+
/**
|
|
739
|
+
* @description Full cwd path used as the project path
|
|
740
|
+
* @type { string }
|
|
741
|
+
* @memberof SessionState
|
|
742
|
+
*/
|
|
743
|
+
projectPath: string;
|
|
744
|
+
/**
|
|
745
|
+
* @description Current lifecycle status of the session
|
|
746
|
+
* @type { SessionStatus }
|
|
747
|
+
* @memberof SessionState
|
|
748
|
+
*/
|
|
749
|
+
status: SessionStatus;
|
|
750
|
+
/**
|
|
751
|
+
* @description Current AI-generated progress summary, or null if not yet summarized
|
|
752
|
+
* @type { string }
|
|
753
|
+
* @memberof SessionState
|
|
754
|
+
*/
|
|
755
|
+
summary: string | null;
|
|
756
|
+
/**
|
|
757
|
+
* @description ISO 8601 timestamp when the summary was last updated, or null if never
|
|
758
|
+
* @type { string }
|
|
759
|
+
* @memberof SessionState
|
|
760
|
+
*/
|
|
761
|
+
summaryUpdatedAt: string | null;
|
|
762
|
+
/**
|
|
763
|
+
* @description Unique terminal identifier (e.g. "term_a1b2c3")
|
|
764
|
+
* @type { string }
|
|
765
|
+
* @memberof SessionState
|
|
766
|
+
*/
|
|
767
|
+
terminalId: string;
|
|
768
|
+
/**
|
|
769
|
+
* @description Total number of tool calls made in this session
|
|
770
|
+
* @type { number }
|
|
771
|
+
* @memberof SessionState
|
|
772
|
+
*/
|
|
773
|
+
toolCallCount: number;
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
export function decodeSessionState(rawInput: unknown): SessionState | null {
|
|
777
|
+
if (isJSON(rawInput)) {
|
|
778
|
+
const decodedCommand = decodeString(rawInput['command']);
|
|
779
|
+
const decodedCreatedAt = decodeString(rawInput['createdAt']);
|
|
780
|
+
const decodedCwd = decodeString(rawInput['cwd']);
|
|
781
|
+
const decodedErrorCount = decodeNumber(rawInput['errorCount']);
|
|
782
|
+
const decodedEventCount = decodeNumber(rawInput['eventCount']);
|
|
783
|
+
const decodedEvents = decodeArray(rawInput['events'], decodeSessionEvent);
|
|
784
|
+
const decodedExitedAt = decodeString(rawInput['exitedAt']);
|
|
785
|
+
const decodedGoal = decodeString(rawInput['goal']);
|
|
786
|
+
const decodedIsSummarizing = decodeBoolean(rawInput['isSummarizing']);
|
|
787
|
+
const decodedProjectName = decodeString(rawInput['projectName']);
|
|
788
|
+
const decodedProjectPath = decodeString(rawInput['projectPath']);
|
|
789
|
+
const decodedStatus = decodeSessionStatus(rawInput['status']);
|
|
790
|
+
const decodedSummary = decodeString(rawInput['summary']);
|
|
791
|
+
const decodedSummaryUpdatedAt = decodeString(rawInput['summaryUpdatedAt']);
|
|
792
|
+
const decodedTerminalId = decodeString(rawInput['terminalId']);
|
|
793
|
+
const decodedToolCallCount = decodeNumber(rawInput['toolCallCount']);
|
|
794
|
+
|
|
795
|
+
if (
|
|
796
|
+
decodedCommand === null ||
|
|
797
|
+
decodedCreatedAt === null ||
|
|
798
|
+
decodedCwd === null ||
|
|
799
|
+
decodedErrorCount === null ||
|
|
800
|
+
decodedEventCount === null ||
|
|
801
|
+
decodedEvents === null ||
|
|
802
|
+
decodedIsSummarizing === null ||
|
|
803
|
+
decodedProjectName === null ||
|
|
804
|
+
decodedProjectPath === null ||
|
|
805
|
+
decodedStatus === null ||
|
|
806
|
+
decodedTerminalId === null ||
|
|
807
|
+
decodedToolCallCount === null
|
|
808
|
+
) {
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
return {
|
|
813
|
+
command: decodedCommand,
|
|
814
|
+
createdAt: decodedCreatedAt,
|
|
815
|
+
cwd: decodedCwd,
|
|
816
|
+
errorCount: decodedErrorCount,
|
|
817
|
+
eventCount: decodedEventCount,
|
|
818
|
+
events: decodedEvents,
|
|
819
|
+
exitedAt: decodedExitedAt,
|
|
820
|
+
goal: decodedGoal,
|
|
821
|
+
isSummarizing: decodedIsSummarizing,
|
|
822
|
+
projectName: decodedProjectName,
|
|
823
|
+
projectPath: decodedProjectPath,
|
|
824
|
+
status: decodedStatus,
|
|
825
|
+
summary: decodedSummary,
|
|
826
|
+
summaryUpdatedAt: decodedSummaryUpdatedAt,
|
|
827
|
+
terminalId: decodedTerminalId,
|
|
828
|
+
toolCallCount: decodedToolCallCount,
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
return null;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* @type { DashboardCard }
|
|
836
|
+
* @description A session card displayed on the home dashboard — extends SessionState with derived display fields
|
|
837
|
+
*/
|
|
838
|
+
export type DashboardCard = {
|
|
839
|
+
/**
|
|
840
|
+
* @description The command running in the terminal
|
|
841
|
+
* @type { string }
|
|
842
|
+
* @memberof DashboardCard
|
|
843
|
+
*/
|
|
844
|
+
command: string;
|
|
845
|
+
/**
|
|
846
|
+
* @description ISO 8601 timestamp when the terminal was created
|
|
847
|
+
* @type { string }
|
|
848
|
+
* @memberof DashboardCard
|
|
849
|
+
*/
|
|
850
|
+
createdAt: string;
|
|
851
|
+
/**
|
|
852
|
+
* @description Working directory path of the terminal
|
|
853
|
+
* @type { string }
|
|
854
|
+
* @memberof DashboardCard
|
|
855
|
+
*/
|
|
856
|
+
cwd: string;
|
|
857
|
+
/**
|
|
858
|
+
* @description Milliseconds elapsed since createdAt (derived at render time)
|
|
859
|
+
* @type { number }
|
|
860
|
+
* @memberof DashboardCard
|
|
861
|
+
*/
|
|
862
|
+
duration: number;
|
|
863
|
+
/**
|
|
864
|
+
* @description Total number of error events accumulated in this session
|
|
865
|
+
* @type { number }
|
|
866
|
+
* @memberof DashboardCard
|
|
867
|
+
*/
|
|
868
|
+
errorCount: number;
|
|
869
|
+
/**
|
|
870
|
+
* @description Total events received (including truncated ones beyond the ring buffer)
|
|
871
|
+
* @type { number }
|
|
872
|
+
* @memberof DashboardCard
|
|
873
|
+
*/
|
|
874
|
+
eventCount: number;
|
|
875
|
+
/**
|
|
876
|
+
* @description Recent events ring buffer (capped at 100 entries)
|
|
877
|
+
* @type { SessionEvent[] }
|
|
878
|
+
* @memberof DashboardCard
|
|
879
|
+
*/
|
|
880
|
+
events: SessionEvent[];
|
|
881
|
+
/**
|
|
882
|
+
* @description ISO 8601 timestamp when the terminal exited, or null if still running
|
|
883
|
+
* @type { string }
|
|
884
|
+
* @memberof DashboardCard
|
|
885
|
+
*/
|
|
886
|
+
exitedAt: string | null;
|
|
887
|
+
/**
|
|
888
|
+
* @description What Claude is working on, or null if not yet known
|
|
889
|
+
* @type { string }
|
|
890
|
+
* @memberof DashboardCard
|
|
891
|
+
*/
|
|
892
|
+
goal: string | null;
|
|
893
|
+
/**
|
|
894
|
+
* @description Whether the session has received events within the last 30 seconds
|
|
895
|
+
* @type { boolean }
|
|
896
|
+
* @memberof DashboardCard
|
|
897
|
+
*/
|
|
898
|
+
isActive: boolean;
|
|
899
|
+
/**
|
|
900
|
+
* @description Whether an AI summary is currently being generated
|
|
901
|
+
* @type { boolean }
|
|
902
|
+
* @memberof DashboardCard
|
|
903
|
+
*/
|
|
904
|
+
isSummarizing: boolean;
|
|
905
|
+
/**
|
|
906
|
+
* @description Display name of the project (basename of cwd)
|
|
907
|
+
* @type { string }
|
|
908
|
+
* @memberof DashboardCard
|
|
909
|
+
*/
|
|
910
|
+
projectName: string;
|
|
911
|
+
/**
|
|
912
|
+
* @description Full cwd path used as the project path
|
|
913
|
+
* @type { string }
|
|
914
|
+
* @memberof DashboardCard
|
|
915
|
+
*/
|
|
916
|
+
projectPath: string;
|
|
917
|
+
/**
|
|
918
|
+
* @description Current lifecycle status of the session
|
|
919
|
+
* @type { SessionStatus }
|
|
920
|
+
* @memberof DashboardCard
|
|
921
|
+
*/
|
|
922
|
+
status: SessionStatus;
|
|
923
|
+
/**
|
|
924
|
+
* @description Current AI-generated progress summary, or null if not yet summarized
|
|
925
|
+
* @type { string }
|
|
926
|
+
* @memberof DashboardCard
|
|
927
|
+
*/
|
|
928
|
+
summary: string | null;
|
|
929
|
+
/**
|
|
930
|
+
* @description ISO 8601 timestamp when the summary was last updated, or null if never
|
|
931
|
+
* @type { string }
|
|
932
|
+
* @memberof DashboardCard
|
|
933
|
+
*/
|
|
934
|
+
summaryUpdatedAt: string | null;
|
|
935
|
+
/**
|
|
936
|
+
* @description Unique terminal identifier
|
|
937
|
+
* @type { string }
|
|
938
|
+
* @memberof DashboardCard
|
|
939
|
+
*/
|
|
940
|
+
terminalId: string;
|
|
941
|
+
/**
|
|
942
|
+
* @description Total number of tool calls made in this session
|
|
943
|
+
* @type { number }
|
|
944
|
+
* @memberof DashboardCard
|
|
945
|
+
*/
|
|
946
|
+
toolCallCount: number;
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
export function decodeDashboardCard(rawInput: unknown): DashboardCard | null {
|
|
950
|
+
if (isJSON(rawInput)) {
|
|
951
|
+
const decodedCommand = decodeString(rawInput['command']);
|
|
952
|
+
const decodedCreatedAt = decodeString(rawInput['createdAt']);
|
|
953
|
+
const decodedCwd = decodeString(rawInput['cwd']);
|
|
954
|
+
const decodedDuration = decodeNumber(rawInput['duration']);
|
|
955
|
+
const decodedErrorCount = decodeNumber(rawInput['errorCount']);
|
|
956
|
+
const decodedEventCount = decodeNumber(rawInput['eventCount']);
|
|
957
|
+
const decodedEvents = decodeArray(rawInput['events'], decodeSessionEvent);
|
|
958
|
+
const decodedExitedAt = decodeString(rawInput['exitedAt']);
|
|
959
|
+
const decodedGoal = decodeString(rawInput['goal']);
|
|
960
|
+
const decodedIsActive = decodeBoolean(rawInput['isActive']);
|
|
961
|
+
const decodedIsSummarizing = decodeBoolean(rawInput['isSummarizing']);
|
|
962
|
+
const decodedProjectName = decodeString(rawInput['projectName']);
|
|
963
|
+
const decodedProjectPath = decodeString(rawInput['projectPath']);
|
|
964
|
+
const decodedStatus = decodeSessionStatus(rawInput['status']);
|
|
965
|
+
const decodedSummary = decodeString(rawInput['summary']);
|
|
966
|
+
const decodedSummaryUpdatedAt = decodeString(rawInput['summaryUpdatedAt']);
|
|
967
|
+
const decodedTerminalId = decodeString(rawInput['terminalId']);
|
|
968
|
+
const decodedToolCallCount = decodeNumber(rawInput['toolCallCount']);
|
|
969
|
+
|
|
970
|
+
if (
|
|
971
|
+
decodedCommand === null ||
|
|
972
|
+
decodedCreatedAt === null ||
|
|
973
|
+
decodedCwd === null ||
|
|
974
|
+
decodedDuration === null ||
|
|
975
|
+
decodedErrorCount === null ||
|
|
976
|
+
decodedEventCount === null ||
|
|
977
|
+
decodedEvents === null ||
|
|
978
|
+
decodedIsActive === null ||
|
|
979
|
+
decodedIsSummarizing === null ||
|
|
980
|
+
decodedProjectName === null ||
|
|
981
|
+
decodedProjectPath === null ||
|
|
982
|
+
decodedStatus === null ||
|
|
983
|
+
decodedTerminalId === null ||
|
|
984
|
+
decodedToolCallCount === null
|
|
985
|
+
) {
|
|
986
|
+
return null;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
return {
|
|
990
|
+
command: decodedCommand,
|
|
991
|
+
createdAt: decodedCreatedAt,
|
|
992
|
+
cwd: decodedCwd,
|
|
993
|
+
duration: decodedDuration,
|
|
994
|
+
errorCount: decodedErrorCount,
|
|
995
|
+
eventCount: decodedEventCount,
|
|
996
|
+
events: decodedEvents,
|
|
997
|
+
exitedAt: decodedExitedAt,
|
|
998
|
+
goal: decodedGoal,
|
|
999
|
+
isActive: decodedIsActive,
|
|
1000
|
+
isSummarizing: decodedIsSummarizing,
|
|
1001
|
+
projectName: decodedProjectName,
|
|
1002
|
+
projectPath: decodedProjectPath,
|
|
1003
|
+
status: decodedStatus,
|
|
1004
|
+
summary: decodedSummary,
|
|
1005
|
+
summaryUpdatedAt: decodedSummaryUpdatedAt,
|
|
1006
|
+
terminalId: decodedTerminalId,
|
|
1007
|
+
toolCallCount: decodedToolCallCount,
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* @type { SummaryRecentEvent }
|
|
1015
|
+
* @description A summarized view of a recent session event used as input to the AI summarizer
|
|
1016
|
+
*/
|
|
1017
|
+
export type SummaryRecentEvent = {
|
|
1018
|
+
/**
|
|
1019
|
+
* @description Command string if the event carries one (e.g. bash command), or undefined if not applicable
|
|
1020
|
+
* @type { string }
|
|
1021
|
+
* @memberof SummaryRecentEvent
|
|
1022
|
+
*/
|
|
1023
|
+
command: string | null;
|
|
1024
|
+
/**
|
|
1025
|
+
* @description Error message if the event is an error event, or undefined if not applicable
|
|
1026
|
+
* @type { string }
|
|
1027
|
+
* @memberof SummaryRecentEvent
|
|
1028
|
+
*/
|
|
1029
|
+
error: string | null;
|
|
1030
|
+
/**
|
|
1031
|
+
* @description Tool name if the event involves a tool call (e.g. "Edit", "Bash"), or undefined if not applicable
|
|
1032
|
+
* @type { string }
|
|
1033
|
+
* @memberof SummaryRecentEvent
|
|
1034
|
+
*/
|
|
1035
|
+
tool: string | null;
|
|
1036
|
+
/**
|
|
1037
|
+
* @description Event type discriminator
|
|
1038
|
+
* @type { string }
|
|
1039
|
+
* @memberof SummaryRecentEvent
|
|
1040
|
+
*/
|
|
1041
|
+
type: string;
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
export function decodeSummaryRecentEvent(rawInput: unknown): SummaryRecentEvent | null {
|
|
1045
|
+
if (isJSON(rawInput)) {
|
|
1046
|
+
const decodedCommand = decodeString(rawInput['command']);
|
|
1047
|
+
const decodedError = decodeString(rawInput['error']);
|
|
1048
|
+
const decodedTool = decodeString(rawInput['tool']);
|
|
1049
|
+
const decodedType = decodeString(rawInput['type']);
|
|
1050
|
+
|
|
1051
|
+
if (decodedType === null) {
|
|
1052
|
+
return null;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
return {
|
|
1056
|
+
command: decodedCommand,
|
|
1057
|
+
error: decodedError,
|
|
1058
|
+
tool: decodedTool,
|
|
1059
|
+
type: decodedType,
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* @type { SummaryContext }
|
|
1067
|
+
* @description Session context passed to the SessionSummarizer to generate an AI summary
|
|
1068
|
+
*/
|
|
1069
|
+
export type SummaryContext = {
|
|
1070
|
+
/**
|
|
1071
|
+
* @description Last 3 user+assistant messages concatenated for context
|
|
1072
|
+
* @type { string }
|
|
1073
|
+
* @memberof SummaryContext
|
|
1074
|
+
*/
|
|
1075
|
+
conversationExcerpt: string;
|
|
1076
|
+
/**
|
|
1077
|
+
* @description Total errors in the session
|
|
1078
|
+
* @type { number }
|
|
1079
|
+
* @memberof SummaryContext
|
|
1080
|
+
*/
|
|
1081
|
+
errorCount: number;
|
|
1082
|
+
/**
|
|
1083
|
+
* @description Null until first user message is seen; the user's stated task
|
|
1084
|
+
* @type { string }
|
|
1085
|
+
* @memberof SummaryContext
|
|
1086
|
+
*/
|
|
1087
|
+
goal: string | null;
|
|
1088
|
+
/**
|
|
1089
|
+
* @description Subset of recent events from the session store (last 10)
|
|
1090
|
+
* @type { SummaryRecentEvent[] }
|
|
1091
|
+
* @memberof SummaryContext
|
|
1092
|
+
*/
|
|
1093
|
+
recentEvents: SummaryRecentEvent[];
|
|
1094
|
+
/**
|
|
1095
|
+
* @description Current session status
|
|
1096
|
+
* @type { SessionStatus }
|
|
1097
|
+
* @memberof SummaryContext
|
|
1098
|
+
*/
|
|
1099
|
+
status: SessionStatus;
|
|
1100
|
+
/**
|
|
1101
|
+
* @description Total tool calls in the session
|
|
1102
|
+
* @type { number }
|
|
1103
|
+
* @memberof SummaryContext
|
|
1104
|
+
*/
|
|
1105
|
+
toolCallCount: number;
|
|
1106
|
+
};
|
|
1107
|
+
|
|
1108
|
+
export function decodeSummaryContext(rawInput: unknown): SummaryContext | null {
|
|
1109
|
+
if (isJSON(rawInput)) {
|
|
1110
|
+
const decodedConversationExcerpt = decodeString(rawInput['conversationExcerpt']);
|
|
1111
|
+
const decodedErrorCount = decodeNumber(rawInput['errorCount']);
|
|
1112
|
+
const decodedGoal = decodeString(rawInput['goal']);
|
|
1113
|
+
const decodedRecentEvents = decodeArray(rawInput['recentEvents'], decodeSummaryRecentEvent);
|
|
1114
|
+
const decodedStatus = decodeSessionStatus(rawInput['status']);
|
|
1115
|
+
const decodedToolCallCount = decodeNumber(rawInput['toolCallCount']);
|
|
1116
|
+
|
|
1117
|
+
if (
|
|
1118
|
+
decodedConversationExcerpt === null ||
|
|
1119
|
+
decodedErrorCount === null ||
|
|
1120
|
+
decodedRecentEvents === null ||
|
|
1121
|
+
decodedStatus === null ||
|
|
1122
|
+
decodedToolCallCount === null
|
|
1123
|
+
) {
|
|
1124
|
+
return null;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
return {
|
|
1128
|
+
conversationExcerpt: decodedConversationExcerpt,
|
|
1129
|
+
errorCount: decodedErrorCount,
|
|
1130
|
+
goal: decodedGoal,
|
|
1131
|
+
recentEvents: decodedRecentEvents,
|
|
1132
|
+
status: decodedStatus,
|
|
1133
|
+
toolCallCount: decodedToolCallCount,
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
return null;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* @type { SummaryTone }
|
|
1141
|
+
* @description Which prompt style was used to generate the summary
|
|
1142
|
+
*/
|
|
1143
|
+
export type SummaryTone = 'conversational' | 'status-report';
|
|
1144
|
+
|
|
1145
|
+
export function decodeSummaryTone(rawInput: unknown): SummaryTone | null {
|
|
1146
|
+
switch (rawInput) {
|
|
1147
|
+
case 'conversational':
|
|
1148
|
+
case 'status-report':
|
|
1149
|
+
return rawInput;
|
|
1150
|
+
}
|
|
1151
|
+
return null;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
export function _decodeSummaryTone(rawInput: unknown): SummaryTone | undefined {
|
|
1155
|
+
switch (rawInput) {
|
|
1156
|
+
case 'conversational':
|
|
1157
|
+
case 'status-report':
|
|
1158
|
+
return rawInput;
|
|
1159
|
+
}
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* @type { SummaryResult }
|
|
1165
|
+
* @description Result returned by SessionSummarizer.summarize
|
|
1166
|
+
*/
|
|
1167
|
+
export type SummaryResult = {
|
|
1168
|
+
/**
|
|
1169
|
+
* @description ISO 8601 timestamp of when this summary was generated
|
|
1170
|
+
* @type { string }
|
|
1171
|
+
* @memberof SummaryResult
|
|
1172
|
+
*/
|
|
1173
|
+
generatedAt: string;
|
|
1174
|
+
/**
|
|
1175
|
+
* @description Plain-English summary text
|
|
1176
|
+
* @type { string }
|
|
1177
|
+
* @memberof SummaryResult
|
|
1178
|
+
*/
|
|
1179
|
+
text: string;
|
|
1180
|
+
/**
|
|
1181
|
+
* @description Which prompt style produced this result
|
|
1182
|
+
* @type { SummaryTone }
|
|
1183
|
+
* @memberof SummaryResult
|
|
1184
|
+
*/
|
|
1185
|
+
tone: SummaryTone;
|
|
1186
|
+
};
|
|
1187
|
+
|
|
1188
|
+
export function decodeSummaryResult(rawInput: unknown): SummaryResult | null {
|
|
1189
|
+
if (isJSON(rawInput)) {
|
|
1190
|
+
const decodedGeneratedAt = decodeString(rawInput['generatedAt']);
|
|
1191
|
+
const decodedText = decodeString(rawInput['text']);
|
|
1192
|
+
const decodedTone = decodeSummaryTone(rawInput['tone']);
|
|
1193
|
+
|
|
1194
|
+
if (decodedGeneratedAt === null || decodedText === null || decodedTone === null) {
|
|
1195
|
+
return null;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
return {
|
|
1199
|
+
generatedAt: decodedGeneratedAt,
|
|
1200
|
+
text: decodedText,
|
|
1201
|
+
tone: decodedTone,
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
return null;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* @type { DashboardTerminalRecord }
|
|
1209
|
+
* @description Slim terminal record returned by GET /api/terminals used to populate dashboard session cards
|
|
1210
|
+
*/
|
|
1211
|
+
export type DashboardTerminalRecord = {
|
|
1212
|
+
/**
|
|
1213
|
+
* @description The command running in the terminal
|
|
1214
|
+
* @type { string }
|
|
1215
|
+
* @memberof DashboardTerminalRecord
|
|
1216
|
+
*/
|
|
1217
|
+
command: string;
|
|
1218
|
+
/**
|
|
1219
|
+
* @description ISO 8601 timestamp when the terminal was created
|
|
1220
|
+
* @type { string }
|
|
1221
|
+
* @memberof DashboardTerminalRecord
|
|
1222
|
+
*/
|
|
1223
|
+
createdAt: string;
|
|
1224
|
+
/**
|
|
1225
|
+
* @description Working directory of the terminal
|
|
1226
|
+
* @type { string }
|
|
1227
|
+
* @memberof DashboardTerminalRecord
|
|
1228
|
+
*/
|
|
1229
|
+
cwd: string;
|
|
1230
|
+
/**
|
|
1231
|
+
* @description ISO 8601 timestamp when the terminal exited, or null if still running
|
|
1232
|
+
* @type { string }
|
|
1233
|
+
* @memberof DashboardTerminalRecord
|
|
1234
|
+
*/
|
|
1235
|
+
exitedAt: string | null;
|
|
1236
|
+
/**
|
|
1237
|
+
* @description Unique terminal identifier
|
|
1238
|
+
* @type { string }
|
|
1239
|
+
* @memberof DashboardTerminalRecord
|
|
1240
|
+
*/
|
|
1241
|
+
id: string;
|
|
1242
|
+
/**
|
|
1243
|
+
* @description Raw terminal status string from the server
|
|
1244
|
+
* @type { string }
|
|
1245
|
+
* @memberof DashboardTerminalRecord
|
|
1246
|
+
*/
|
|
1247
|
+
status: string;
|
|
1248
|
+
};
|
|
1249
|
+
|
|
1250
|
+
export function decodeDashboardTerminalRecord(rawInput: unknown): DashboardTerminalRecord | null {
|
|
1251
|
+
if (isJSON(rawInput)) {
|
|
1252
|
+
const decodedCommand = decodeString(rawInput['command']);
|
|
1253
|
+
const decodedCreatedAt = decodeString(rawInput['createdAt']);
|
|
1254
|
+
const decodedCwd = decodeString(rawInput['cwd']);
|
|
1255
|
+
const decodedExitedAt = decodeString(rawInput['exitedAt']);
|
|
1256
|
+
const decodedId = decodeString(rawInput['id']);
|
|
1257
|
+
const decodedStatus = decodeString(rawInput['status']);
|
|
1258
|
+
|
|
1259
|
+
if (
|
|
1260
|
+
decodedCommand === null ||
|
|
1261
|
+
decodedCreatedAt === null ||
|
|
1262
|
+
decodedCwd === null ||
|
|
1263
|
+
decodedId === null ||
|
|
1264
|
+
decodedStatus === null
|
|
1265
|
+
) {
|
|
1266
|
+
return null;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
return {
|
|
1270
|
+
command: decodedCommand,
|
|
1271
|
+
createdAt: decodedCreatedAt,
|
|
1272
|
+
cwd: decodedCwd,
|
|
1273
|
+
exitedAt: decodedExitedAt,
|
|
1274
|
+
id: decodedId,
|
|
1275
|
+
status: decodedStatus,
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
return null;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* @type { DashboardTerminalListResponse }
|
|
1283
|
+
* @description API response shape for GET /api/terminals as consumed by the dashboard store
|
|
1284
|
+
*/
|
|
1285
|
+
export type DashboardTerminalListResponse = {
|
|
1286
|
+
/**
|
|
1287
|
+
* @description Array of slim terminal records
|
|
1288
|
+
* @type { DashboardTerminalRecord[] }
|
|
1289
|
+
* @memberof DashboardTerminalListResponse
|
|
1290
|
+
*/
|
|
1291
|
+
terminals: DashboardTerminalRecord[];
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
export function decodeDashboardTerminalListResponse(
|
|
1295
|
+
rawInput: unknown
|
|
1296
|
+
): DashboardTerminalListResponse | null {
|
|
1297
|
+
if (isJSON(rawInput)) {
|
|
1298
|
+
const decodedTerminals = decodeArray(rawInput['terminals'], decodeDashboardTerminalRecord);
|
|
1299
|
+
|
|
1300
|
+
if (decodedTerminals === null) {
|
|
1301
|
+
return null;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
return {
|
|
1305
|
+
terminals: decodedTerminals,
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
return null;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
/**
|
|
1312
|
+
* @type { ActivityEvent }
|
|
1313
|
+
* @description A single event captured from a Claude Code session WebSocket for the activity feed
|
|
1314
|
+
*/
|
|
1315
|
+
export type ActivityEvent = {
|
|
1316
|
+
/**
|
|
1317
|
+
* @description Raw event payload with tool name, file path, command, etc.
|
|
1318
|
+
* @type { ActivityEventData }
|
|
1319
|
+
* @memberof ActivityEvent
|
|
1320
|
+
*/
|
|
1321
|
+
data: ActivityEventData;
|
|
1322
|
+
/**
|
|
1323
|
+
* @description Unique event identifier (e.g. "evt-1")
|
|
1324
|
+
* @type { string }
|
|
1325
|
+
* @memberof ActivityEvent
|
|
1326
|
+
*/
|
|
1327
|
+
id: string;
|
|
1328
|
+
/**
|
|
1329
|
+
* @description Display name of the project this event belongs to
|
|
1330
|
+
* @type { string }
|
|
1331
|
+
* @memberof ActivityEvent
|
|
1332
|
+
*/
|
|
1333
|
+
projectName: string;
|
|
1334
|
+
/**
|
|
1335
|
+
* @description Claude Code session ID this event was received from
|
|
1336
|
+
* @type { string }
|
|
1337
|
+
* @memberof ActivityEvent
|
|
1338
|
+
*/
|
|
1339
|
+
sessionId: string;
|
|
1340
|
+
/**
|
|
1341
|
+
* @description Whether this event has been included in an AI-generated summary
|
|
1342
|
+
* @type { boolean }
|
|
1343
|
+
* @memberof ActivityEvent
|
|
1344
|
+
*/
|
|
1345
|
+
summarized: boolean;
|
|
1346
|
+
/**
|
|
1347
|
+
* @description ISO 8601 timestamp of the event
|
|
1348
|
+
* @type { string }
|
|
1349
|
+
* @memberof ActivityEvent
|
|
1350
|
+
*/
|
|
1351
|
+
timestamp: string;
|
|
1352
|
+
/**
|
|
1353
|
+
* @description Event type discriminator (e.g. "tool_use", "tool_result", "user_message", "error")
|
|
1354
|
+
* @type { string }
|
|
1355
|
+
* @memberof ActivityEvent
|
|
1356
|
+
*/
|
|
1357
|
+
type: string;
|
|
1358
|
+
};
|
|
1359
|
+
|
|
1360
|
+
export function decodeActivityEvent(rawInput: unknown): ActivityEvent | null {
|
|
1361
|
+
if (isJSON(rawInput)) {
|
|
1362
|
+
const decodedData = decodeActivityEventData(rawInput['data']);
|
|
1363
|
+
const decodedId = decodeString(rawInput['id']);
|
|
1364
|
+
const decodedProjectName = decodeString(rawInput['projectName']);
|
|
1365
|
+
const decodedSessionId = decodeString(rawInput['sessionId']);
|
|
1366
|
+
const decodedSummarized = decodeBoolean(rawInput['summarized']);
|
|
1367
|
+
const decodedTimestamp = decodeString(rawInput['timestamp']);
|
|
1368
|
+
const decodedType = decodeString(rawInput['type']);
|
|
1369
|
+
|
|
1370
|
+
if (
|
|
1371
|
+
decodedData === null ||
|
|
1372
|
+
decodedId === null ||
|
|
1373
|
+
decodedProjectName === null ||
|
|
1374
|
+
decodedSessionId === null ||
|
|
1375
|
+
decodedSummarized === null ||
|
|
1376
|
+
decodedTimestamp === null ||
|
|
1377
|
+
decodedType === null
|
|
1378
|
+
) {
|
|
1379
|
+
return null;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
return {
|
|
1383
|
+
data: decodedData,
|
|
1384
|
+
id: decodedId,
|
|
1385
|
+
projectName: decodedProjectName,
|
|
1386
|
+
sessionId: decodedSessionId,
|
|
1387
|
+
summarized: decodedSummarized,
|
|
1388
|
+
timestamp: decodedTimestamp,
|
|
1389
|
+
type: decodedType,
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
return null;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
/**
|
|
1396
|
+
* @type { ActivityEventData }
|
|
1397
|
+
* @description Raw event payload with tool name, file path, command, etc.
|
|
1398
|
+
*/
|
|
1399
|
+
export type ActivityEventData = Record<string, unknown>;
|
|
1400
|
+
|
|
1401
|
+
export function decodeActivityEventData(rawInput: unknown): ActivityEventData | null {
|
|
1402
|
+
if (isJSON(rawInput)) {
|
|
1403
|
+
return {
|
|
1404
|
+
...rawInput,
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
/**
|
|
1411
|
+
* @type { ActivitySummary }
|
|
1412
|
+
* @description An AI-generated rolling summary covering a batch of activity events
|
|
1413
|
+
*/
|
|
1414
|
+
export type ActivitySummary = {
|
|
1415
|
+
/**
|
|
1416
|
+
* @description IDs of the events included in this summary
|
|
1417
|
+
* @type { string[] }
|
|
1418
|
+
* @memberof ActivitySummary
|
|
1419
|
+
*/
|
|
1420
|
+
eventIds: string[];
|
|
1421
|
+
/**
|
|
1422
|
+
* @description Unique summary identifier (e.g. "sum-1")
|
|
1423
|
+
* @type { string }
|
|
1424
|
+
* @memberof ActivitySummary
|
|
1425
|
+
*/
|
|
1426
|
+
id: string;
|
|
1427
|
+
/**
|
|
1428
|
+
* @description Project this summary covers
|
|
1429
|
+
* @type { string }
|
|
1430
|
+
* @memberof ActivitySummary
|
|
1431
|
+
*/
|
|
1432
|
+
projectName: string;
|
|
1433
|
+
/**
|
|
1434
|
+
* @description AI-generated summary text
|
|
1435
|
+
* @type { string }
|
|
1436
|
+
* @memberof ActivitySummary
|
|
1437
|
+
*/
|
|
1438
|
+
text: string;
|
|
1439
|
+
/**
|
|
1440
|
+
* @description ISO 8601 timestamp when the summary was generated
|
|
1441
|
+
* @type { string }
|
|
1442
|
+
* @memberof ActivitySummary
|
|
1443
|
+
*/
|
|
1444
|
+
timestamp: string;
|
|
1445
|
+
};
|
|
1446
|
+
|
|
1447
|
+
export function decodeActivitySummary(rawInput: unknown): ActivitySummary | null {
|
|
1448
|
+
if (isJSON(rawInput)) {
|
|
1449
|
+
const decodedEventIds = decodeArray(rawInput['eventIds'], decodeString);
|
|
1450
|
+
const decodedId = decodeString(rawInput['id']);
|
|
1451
|
+
const decodedProjectName = decodeString(rawInput['projectName']);
|
|
1452
|
+
const decodedText = decodeString(rawInput['text']);
|
|
1453
|
+
const decodedTimestamp = decodeString(rawInput['timestamp']);
|
|
1454
|
+
|
|
1455
|
+
if (
|
|
1456
|
+
decodedEventIds === null ||
|
|
1457
|
+
decodedId === null ||
|
|
1458
|
+
decodedProjectName === null ||
|
|
1459
|
+
decodedText === null ||
|
|
1460
|
+
decodedTimestamp === null
|
|
1461
|
+
) {
|
|
1462
|
+
return null;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
return {
|
|
1466
|
+
eventIds: decodedEventIds,
|
|
1467
|
+
id: decodedId,
|
|
1468
|
+
projectName: decodedProjectName,
|
|
1469
|
+
text: decodedText,
|
|
1470
|
+
timestamp: decodedTimestamp,
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
return null;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
* @type { ActivitySummaryResult }
|
|
1478
|
+
* @description Result from the activity feed summarizer (NeuroLink generate call)
|
|
1479
|
+
*/
|
|
1480
|
+
export type ActivitySummaryResult = {
|
|
1481
|
+
/**
|
|
1482
|
+
* @description Error message if summarization failed, or null on success
|
|
1483
|
+
* @type { string }
|
|
1484
|
+
* @memberof ActivitySummaryResult
|
|
1485
|
+
*/
|
|
1486
|
+
error: string | null;
|
|
1487
|
+
/**
|
|
1488
|
+
* @description Summary text or fallback description
|
|
1489
|
+
* @type { string }
|
|
1490
|
+
* @memberof ActivitySummaryResult
|
|
1491
|
+
*/
|
|
1492
|
+
text: string;
|
|
1493
|
+
};
|
|
1494
|
+
|
|
1495
|
+
export function decodeActivitySummaryResult(rawInput: unknown): ActivitySummaryResult | null {
|
|
1496
|
+
if (isJSON(rawInput)) {
|
|
1497
|
+
const decodedError = decodeString(rawInput['error']);
|
|
1498
|
+
const decodedText = decodeString(rawInput['text']);
|
|
1499
|
+
|
|
1500
|
+
if (decodedText === null) {
|
|
1501
|
+
return null;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
return {
|
|
1505
|
+
error: decodedError,
|
|
1506
|
+
text: decodedText,
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
return null;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
/**
|
|
1513
|
+
* @type { ProviderStatus }
|
|
1514
|
+
* @description Configuration status of a single AI provider
|
|
1515
|
+
*/
|
|
1516
|
+
export type ProviderStatus = {
|
|
1517
|
+
/**
|
|
1518
|
+
* @description Whether the provider has valid API credentials
|
|
1519
|
+
* @type { boolean }
|
|
1520
|
+
* @memberof ProviderStatus
|
|
1521
|
+
*/
|
|
1522
|
+
configured: boolean;
|
|
1523
|
+
/**
|
|
1524
|
+
* @description Provider identifier (e.g. "google-ai", "anthropic")
|
|
1525
|
+
* @type { string }
|
|
1526
|
+
* @memberof ProviderStatus
|
|
1527
|
+
*/
|
|
1528
|
+
id: string;
|
|
1529
|
+
/**
|
|
1530
|
+
* @description Human-readable provider name
|
|
1531
|
+
* @type { string }
|
|
1532
|
+
* @memberof ProviderStatus
|
|
1533
|
+
*/
|
|
1534
|
+
label: string;
|
|
1535
|
+
};
|
|
1536
|
+
|
|
1537
|
+
export function decodeProviderStatus(rawInput: unknown): ProviderStatus | null {
|
|
1538
|
+
if (isJSON(rawInput)) {
|
|
1539
|
+
const decodedConfigured = decodeBoolean(rawInput['configured']);
|
|
1540
|
+
const decodedId = decodeString(rawInput['id']);
|
|
1541
|
+
const decodedLabel = decodeString(rawInput['label']);
|
|
1542
|
+
|
|
1543
|
+
if (decodedConfigured === null || decodedId === null || decodedLabel === null) {
|
|
1544
|
+
return null;
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
return {
|
|
1548
|
+
configured: decodedConfigured,
|
|
1549
|
+
id: decodedId,
|
|
1550
|
+
label: decodedLabel,
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
return null;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
/**
|
|
1557
|
+
* @type { ActivitySessionRecord }
|
|
1558
|
+
* @description A discovered active session that the activity store connects to via WebSocket
|
|
1559
|
+
*/
|
|
1560
|
+
export type ActivitySessionRecord = {
|
|
1561
|
+
/**
|
|
1562
|
+
* @description ISO 8601 timestamp when the session was created
|
|
1563
|
+
* @type { string }
|
|
1564
|
+
* @memberof ActivitySessionRecord
|
|
1565
|
+
*/
|
|
1566
|
+
createdAt: string;
|
|
1567
|
+
/**
|
|
1568
|
+
* @description Session identifier
|
|
1569
|
+
* @type { string }
|
|
1570
|
+
* @memberof ActivitySessionRecord
|
|
1571
|
+
*/
|
|
1572
|
+
id: string;
|
|
1573
|
+
/**
|
|
1574
|
+
* @description ISO 8601 timestamp of last session modification
|
|
1575
|
+
* @type { string }
|
|
1576
|
+
* @memberof ActivitySessionRecord
|
|
1577
|
+
*/
|
|
1578
|
+
modifiedAt: string;
|
|
1579
|
+
/**
|
|
1580
|
+
* @description Display name of the project
|
|
1581
|
+
* @type { string }
|
|
1582
|
+
* @memberof ActivitySessionRecord
|
|
1583
|
+
*/
|
|
1584
|
+
projectName: string;
|
|
1585
|
+
/**
|
|
1586
|
+
* @description Full filesystem path of the project
|
|
1587
|
+
* @type { string }
|
|
1588
|
+
* @memberof ActivitySessionRecord
|
|
1589
|
+
*/
|
|
1590
|
+
projectPath: string;
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1593
|
+
export function decodeActivitySessionRecord(rawInput: unknown): ActivitySessionRecord | null {
|
|
1594
|
+
if (isJSON(rawInput)) {
|
|
1595
|
+
const decodedCreatedAt = decodeString(rawInput['createdAt']);
|
|
1596
|
+
const decodedId = decodeString(rawInput['id']);
|
|
1597
|
+
const decodedModifiedAt = decodeString(rawInput['modifiedAt']);
|
|
1598
|
+
const decodedProjectName = decodeString(rawInput['projectName']);
|
|
1599
|
+
const decodedProjectPath = decodeString(rawInput['projectPath']);
|
|
1600
|
+
|
|
1601
|
+
if (
|
|
1602
|
+
decodedCreatedAt === null ||
|
|
1603
|
+
decodedId === null ||
|
|
1604
|
+
decodedModifiedAt === null ||
|
|
1605
|
+
decodedProjectName === null ||
|
|
1606
|
+
decodedProjectPath === null
|
|
1607
|
+
) {
|
|
1608
|
+
return null;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
return {
|
|
1612
|
+
createdAt: decodedCreatedAt,
|
|
1613
|
+
id: decodedId,
|
|
1614
|
+
modifiedAt: decodedModifiedAt,
|
|
1615
|
+
projectName: decodedProjectName,
|
|
1616
|
+
projectPath: decodedProjectPath,
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
return null;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/**
|
|
1623
|
+
* @type { NativeBridgeConfig }
|
|
1624
|
+
* @description Configuration returned by ShooterBridge.getConfig() in the native app WebView
|
|
1625
|
+
*/
|
|
1626
|
+
export type NativeBridgeConfig = {
|
|
1627
|
+
/**
|
|
1628
|
+
* @description Base URL of the Shooter server
|
|
1629
|
+
* @type { string }
|
|
1630
|
+
* @memberof NativeBridgeConfig
|
|
1631
|
+
*/
|
|
1632
|
+
serverUrl: string;
|
|
1633
|
+
/**
|
|
1634
|
+
* @description API key for authenticating with the server
|
|
1635
|
+
* @type { string }
|
|
1636
|
+
* @memberof NativeBridgeConfig
|
|
1637
|
+
*/
|
|
1638
|
+
apiKey: string;
|
|
1639
|
+
};
|
|
1640
|
+
|
|
1641
|
+
export function decodeNativeBridgeConfig(rawInput: unknown): NativeBridgeConfig | null {
|
|
1642
|
+
if (isJSON(rawInput)) {
|
|
1643
|
+
const decodedServerUrl = decodeString(rawInput['serverUrl']);
|
|
1644
|
+
const decodedApiKey = decodeString(rawInput['apiKey']);
|
|
1645
|
+
|
|
1646
|
+
if (decodedServerUrl === null || decodedApiKey === null) {
|
|
1647
|
+
return null;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
return {
|
|
1651
|
+
serverUrl: decodedServerUrl,
|
|
1652
|
+
apiKey: decodedApiKey,
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
return null;
|
|
1656
|
+
}
|