@juspay/shooter 1.5.0 → 1.6.0
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/{CiF38mQq.js → CqfYvnci.js} +1 -1
- package/build/client/_app/immutable/chunks/CqfYvnci.js.br +0 -0
- package/build/client/_app/immutable/chunks/CqfYvnci.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/EhLZwqfu.js +3 -0
- package/build/client/_app/immutable/chunks/EhLZwqfu.js.br +0 -0
- package/build/client/_app/immutable/chunks/EhLZwqfu.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/chunks/{CRbaG9cv.js → y_g-KC7l.js} +1 -1
- package/build/client/_app/immutable/chunks/y_g-KC7l.js.br +0 -0
- package/build/client/_app/immutable/chunks/{CRbaG9cv.js.gz → y_g-KC7l.js.gz} +0 -0
- package/build/client/_app/immutable/entry/app.zJvbFXsj.js +2 -0
- package/build/client/_app/immutable/entry/app.zJvbFXsj.js.br +0 -0
- package/build/client/_app/immutable/entry/app.zJvbFXsj.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.B2Jf5iFd.js +1 -0
- package/build/client/_app/immutable/entry/start.B2Jf5iFd.js.br +2 -0
- package/build/client/_app/immutable/entry/start.B2Jf5iFd.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.B_E4j3MX.js +1 -0
- package/build/client/_app/immutable/nodes/0.B_E4j3MX.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.B_E4j3MX.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.B0oFqb8X.js +1 -0
- package/build/client/_app/immutable/nodes/1.B0oFqb8X.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.B0oFqb8X.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.Bqul0XyM.js +13 -0
- package/build/client/_app/immutable/nodes/2.Bqul0XyM.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.Bqul0XyM.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.CTqUQKSN.js +9 -0
- package/build/client/_app/immutable/nodes/3.CTqUQKSN.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.CTqUQKSN.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.BvjUfHnH.js +1 -0
- package/build/client/_app/immutable/nodes/6.BvjUfHnH.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BvjUfHnH.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{5.DIkXVP4q.js → 7.5K7Od8ba.js} +3 -3
- package/build/client/_app/immutable/nodes/7.5K7Od8ba.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.5K7Od8ba.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.Bs1DrW0_.js +2 -0
- package/build/client/_app/immutable/nodes/8.Bs1DrW0_.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.Bs1DrW0_.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.1fMlGdqv.js +2 -0
- package/build/client/_app/immutable/nodes/9.1fMlGdqv.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.1fMlGdqv.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-e1fgD9Mi.js +23 -0
- package/build/server/chunks/0-e1fgD9Mi.js.map +1 -0
- package/build/server/chunks/1-D2_XVthm.js +9 -0
- package/build/server/chunks/{1-D0N7vVhH.js.map → 1-D2_XVthm.js.map} +1 -1
- package/build/server/chunks/2-DADX86JZ.js +21 -0
- package/build/server/chunks/2-DADX86JZ.js.map +1 -0
- package/build/server/chunks/3-CHacdiCg.js +21 -0
- package/build/server/chunks/3-CHacdiCg.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-CWLNQu6F.js +9 -0
- package/build/server/chunks/6-CWLNQu6F.js.map +1 -0
- package/build/server/chunks/7-DmQ3B8uy.js +9 -0
- package/build/server/chunks/7-DmQ3B8uy.js.map +1 -0
- package/build/server/chunks/8-CnFVjQtZ.js +9 -0
- package/build/server/chunks/8-CnFVjQtZ.js.map +1 -0
- package/build/server/chunks/9-Dw7-P6aF.js +9 -0
- package/build/server/chunks/9-Dw7-P6aF.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-Ch-6iOHp.js → _server.ts-B__YN2kX.js} +121 -87
- package/build/server/chunks/_server.ts-B__YN2kX.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-Deok2y88.js → _server.ts-ByIrRtCx.js} +132 -76
- package/build/server/chunks/_server.ts-ByIrRtCx.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/{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 +69 -60
- 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 +159 -84
- 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,136 @@
|
|
|
1
|
+
// Server-side proxy for AI providers that block direct browser requests (CORS).
|
|
2
|
+
// The browser NeuroLink bundle POSTs here; this endpoint forwards to the real API.
|
|
3
|
+
// Currently supports: anthropic (api.anthropic.com blocks browser fetch).
|
|
4
|
+
|
|
5
|
+
import { env } from '$env/dynamic/private';
|
|
6
|
+
import { validateAuth } from '$lib/modules/server/auth';
|
|
7
|
+
import { json } from '@sveltejs/kit';
|
|
8
|
+
|
|
9
|
+
import type { RequestHandler } from './$types';
|
|
10
|
+
|
|
11
|
+
// Per-provider allowlist of client-supplied headers that may be forwarded
|
|
12
|
+
// upstream. Everything else (including host, x-forwarded-*, content-type) is
|
|
13
|
+
// dropped so the browser can't influence provider behavior beyond what we
|
|
14
|
+
// explicitly permit.
|
|
15
|
+
const ALLOWED_CLIENT_HEADERS: Record<string, Set<string>> = {
|
|
16
|
+
anthropic: new Set(['anthropic-beta', 'anthropic-version']),
|
|
17
|
+
'google-ai': new Set<string>([]),
|
|
18
|
+
mistral: new Set([]),
|
|
19
|
+
openai: new Set(['openai-organization', 'openai-project']),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const POST: RequestHandler = async ({ request }) => {
|
|
23
|
+
const authError = validateAuth(request);
|
|
24
|
+
if (authError) {
|
|
25
|
+
return authError;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let payload: unknown;
|
|
29
|
+
try {
|
|
30
|
+
payload = await request.json();
|
|
31
|
+
} catch {
|
|
32
|
+
return json({ error: 'Invalid JSON body' }, { status: 400 });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (
|
|
36
|
+
!payload ||
|
|
37
|
+
typeof payload !== 'object' ||
|
|
38
|
+
typeof (payload as { provider?: unknown }).provider !== 'string' ||
|
|
39
|
+
typeof (payload as { url?: unknown }).url !== 'string' ||
|
|
40
|
+
!(payload as { headers?: unknown }).headers ||
|
|
41
|
+
typeof (payload as { headers?: unknown }).headers !== 'object'
|
|
42
|
+
) {
|
|
43
|
+
return json({ error: 'Invalid proxy payload' }, { status: 400 });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const {
|
|
47
|
+
body,
|
|
48
|
+
headers: reqHeaders,
|
|
49
|
+
provider,
|
|
50
|
+
url,
|
|
51
|
+
} = payload as {
|
|
52
|
+
body: unknown;
|
|
53
|
+
headers: Record<string, string>;
|
|
54
|
+
provider: string;
|
|
55
|
+
url: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Only proxy known safe providers — never forward arbitrary URLs
|
|
59
|
+
const ALLOWED_PREFIXES: Record<string, string> = {
|
|
60
|
+
anthropic: 'https://api.anthropic.com/',
|
|
61
|
+
'google-ai': 'https://generativelanguage.googleapis.com/',
|
|
62
|
+
mistral: 'https://api.mistral.ai/',
|
|
63
|
+
openai: 'https://api.openai.com/',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const allowedPrefix = ALLOWED_PREFIXES[provider];
|
|
67
|
+
if (!allowedPrefix || !url.startsWith(allowedPrefix)) {
|
|
68
|
+
return json({ error: `Provider "${provider}" or URL not allowed` }, { status: 403 });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Inject the server-side API key so the browser never sees it
|
|
72
|
+
const apiKeyEnv: Record<string, string> = {
|
|
73
|
+
anthropic: env.ANTHROPIC_API_KEY ?? '',
|
|
74
|
+
'google-ai': env.GOOGLE_AI_API_KEY ?? '',
|
|
75
|
+
mistral: env.MISTRAL_API_KEY ?? '',
|
|
76
|
+
openai: env.OPENAI_API_KEY ?? '',
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Copy only explicitly-allowed headers per provider. Everything else is
|
|
80
|
+
// dropped so the browser can't influence upstream behavior via host,
|
|
81
|
+
// x-forwarded-*, organization selectors, provider feature toggles, etc.
|
|
82
|
+
const allowedForProvider = ALLOWED_CLIENT_HEADERS[provider] ?? new Set<string>();
|
|
83
|
+
const normalizedReqHeaders: Record<string, string> = {};
|
|
84
|
+
for (const [k, v] of Object.entries(reqHeaders)) {
|
|
85
|
+
const key = k.toLowerCase();
|
|
86
|
+
if (allowedForProvider.has(key)) {
|
|
87
|
+
normalizedReqHeaders[key] = v;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const forwardHeaders: Record<string, string> = {
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
...normalizedReqHeaders,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Override / set auth header with server-side key
|
|
97
|
+
if (provider === 'anthropic') {
|
|
98
|
+
forwardHeaders['x-api-key'] = apiKeyEnv.anthropic;
|
|
99
|
+
forwardHeaders['anthropic-version'] = forwardHeaders['anthropic-version'] ?? '2023-06-01';
|
|
100
|
+
} else if (provider === 'google-ai') {
|
|
101
|
+
forwardHeaders['x-goog-api-key'] = apiKeyEnv['google-ai'];
|
|
102
|
+
} else if (provider === 'openai') {
|
|
103
|
+
forwardHeaders.Authorization = `Bearer ${apiKeyEnv.openai}`;
|
|
104
|
+
} else if (provider === 'mistral') {
|
|
105
|
+
forwardHeaders.Authorization = `Bearer ${apiKeyEnv.mistral}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const controller = new AbortController();
|
|
109
|
+
const timeout = setTimeout(() => {
|
|
110
|
+
controller.abort();
|
|
111
|
+
}, 30_000);
|
|
112
|
+
|
|
113
|
+
let resp: Response;
|
|
114
|
+
try {
|
|
115
|
+
resp = await fetch(url, {
|
|
116
|
+
body: JSON.stringify(body),
|
|
117
|
+
headers: forwardHeaders,
|
|
118
|
+
method: 'POST',
|
|
119
|
+
signal: controller.signal,
|
|
120
|
+
});
|
|
121
|
+
} catch (err) {
|
|
122
|
+
clearTimeout(timeout);
|
|
123
|
+
const message = err instanceof Error ? err.message : 'Upstream request failed';
|
|
124
|
+
return json({ error: message }, { status: 502 });
|
|
125
|
+
}
|
|
126
|
+
clearTimeout(timeout);
|
|
127
|
+
|
|
128
|
+
let data: unknown;
|
|
129
|
+
try {
|
|
130
|
+
data = await resp.json();
|
|
131
|
+
} catch {
|
|
132
|
+
return json({ error: 'Upstream returned non-JSON response' }, { status: 502 });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return json(data, { status: resp.status });
|
|
136
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NotificationData } from '$
|
|
1
|
+
import type { NotificationData } from '$lib/types';
|
|
2
2
|
|
|
3
3
|
import { env } from '$env/dynamic/private';
|
|
4
4
|
import { LibraryAPNsService } from '$lib/modules/server/apn/library-apns';
|
|
@@ -7,6 +7,7 @@ import { createPendingRequest } from '$lib/modules/server/apn/pending-requests';
|
|
|
7
7
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
8
8
|
import { isFCMConfigured, sendFCMNotification } from '$lib/modules/server/fcm/fcm-service.js';
|
|
9
9
|
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
10
|
+
import { broadcastEvent } from '$lib/modules/server/ws/server';
|
|
10
11
|
import { json } from '@sveltejs/kit';
|
|
11
12
|
|
|
12
13
|
import type { RequestHandler } from './$types';
|
|
@@ -24,15 +25,118 @@ function getAPNsClient(): LibraryAPNsService {
|
|
|
24
25
|
const notificationCache = new Map<string, number>();
|
|
25
26
|
const DEDUP_WINDOW = 10000; // 10 seconds deduplication window
|
|
26
27
|
|
|
28
|
+
function broadcastHookEvent(body: Record<string, unknown>): void {
|
|
29
|
+
const data = (body.data ?? {}) as Record<string, unknown>;
|
|
30
|
+
const eventType =
|
|
31
|
+
typeof data.eventType === 'string'
|
|
32
|
+
? data.eventType
|
|
33
|
+
: typeof body.eventType === 'string'
|
|
34
|
+
? body.eventType
|
|
35
|
+
: '';
|
|
36
|
+
const tool = typeof data.tool === 'string' ? data.tool : '';
|
|
37
|
+
const terminalId = typeof data.terminalId === 'string' ? data.terminalId : undefined;
|
|
38
|
+
const sessionId = typeof data.sessionId === 'string' ? data.sessionId : undefined;
|
|
39
|
+
|
|
40
|
+
switch (eventType) {
|
|
41
|
+
case 'error':
|
|
42
|
+
broadcastEvent({
|
|
43
|
+
error:
|
|
44
|
+
typeof data.error === 'string'
|
|
45
|
+
? data.error
|
|
46
|
+
: typeof data.message === 'string'
|
|
47
|
+
? data.message
|
|
48
|
+
: 'Unknown error',
|
|
49
|
+
terminalId,
|
|
50
|
+
tool,
|
|
51
|
+
type: 'tool-failed',
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
54
|
+
case 'idle_input':
|
|
55
|
+
case 'session.idle':
|
|
56
|
+
broadcastEvent({
|
|
57
|
+
message: typeof data.message === 'string' ? data.message : '',
|
|
58
|
+
sessionId,
|
|
59
|
+
terminalId,
|
|
60
|
+
type: 'agent-idle',
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
63
|
+
case 'permission':
|
|
64
|
+
case 'permission_notification':
|
|
65
|
+
if (data.requestId && data.toolName) {
|
|
66
|
+
broadcastEvent({
|
|
67
|
+
input:
|
|
68
|
+
typeof data.toolInput === 'object' && data.toolInput !== null
|
|
69
|
+
? (data.toolInput as Record<string, unknown>)
|
|
70
|
+
: {},
|
|
71
|
+
requestId: data.requestId as string,
|
|
72
|
+
tool: data.toolName as string,
|
|
73
|
+
type: 'permission-requested',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
case 'question':
|
|
78
|
+
broadcastEvent({
|
|
79
|
+
message: typeof data.message === 'string' ? data.message : '',
|
|
80
|
+
sessionId,
|
|
81
|
+
terminalId,
|
|
82
|
+
type: 'agent-question',
|
|
83
|
+
});
|
|
84
|
+
break;
|
|
85
|
+
case 'tool.after':
|
|
86
|
+
broadcastEvent({ success: true, terminalId, tool, type: 'tool-completed' });
|
|
87
|
+
break;
|
|
88
|
+
case 'tool.before':
|
|
89
|
+
broadcastEvent({
|
|
90
|
+
command: typeof data.command === 'string' ? data.command : '',
|
|
91
|
+
filePath:
|
|
92
|
+
typeof data.filePath === 'string'
|
|
93
|
+
? data.filePath
|
|
94
|
+
: typeof data.files === 'string'
|
|
95
|
+
? data.files
|
|
96
|
+
: '',
|
|
97
|
+
terminalId,
|
|
98
|
+
tool,
|
|
99
|
+
type: 'tool-started',
|
|
100
|
+
});
|
|
101
|
+
break;
|
|
102
|
+
// session.status, intervention — skip or use existing types
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Build a notification history record from common fields. */
|
|
107
|
+
function buildNotificationRecord(
|
|
108
|
+
id: string,
|
|
109
|
+
title: string,
|
|
110
|
+
message: string,
|
|
111
|
+
status: 'failed' | 'filtered' | 'sent' | 'skipped',
|
|
112
|
+
data?: NotificationData,
|
|
113
|
+
error?: null | string
|
|
114
|
+
): Parameters<typeof addNotification>[0] {
|
|
115
|
+
return {
|
|
116
|
+
category: data?.category ?? null,
|
|
117
|
+
data: (data as Record<string, unknown>) ?? null,
|
|
118
|
+
error: error ?? null,
|
|
119
|
+
id,
|
|
120
|
+
message,
|
|
121
|
+
project: data?.project ?? null,
|
|
122
|
+
source: data?.source ?? null,
|
|
123
|
+
status,
|
|
124
|
+
timestamp: new Date().toISOString(),
|
|
125
|
+
title,
|
|
126
|
+
tool: data?.tool ?? null,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
27
130
|
function intelligentNotificationFilter(
|
|
28
131
|
title: string,
|
|
29
132
|
message: string,
|
|
30
|
-
data?: NotificationData
|
|
133
|
+
data?: NotificationData,
|
|
134
|
+
waitForResponse = false
|
|
31
135
|
): { reason: string; send: boolean } {
|
|
32
136
|
const source = data?.source || 'unknown';
|
|
33
137
|
|
|
34
138
|
// Check for duplicate notifications first
|
|
35
|
-
if (isDuplicateNotification(title, message, data)) {
|
|
139
|
+
if (isDuplicateNotification(title, message, data, waitForResponse)) {
|
|
36
140
|
return {
|
|
37
141
|
reason: 'Duplicate notification within 10-second window',
|
|
38
142
|
send: false,
|
|
@@ -100,12 +204,23 @@ function intelligentNotificationFilter(
|
|
|
100
204
|
};
|
|
101
205
|
}
|
|
102
206
|
|
|
103
|
-
function isDuplicateNotification(
|
|
207
|
+
function isDuplicateNotification(
|
|
208
|
+
title: string,
|
|
209
|
+
message: string,
|
|
210
|
+
data?: NotificationData,
|
|
211
|
+
waitForResponse = false
|
|
212
|
+
): boolean {
|
|
213
|
+
// Never deduplicate bidirectional permission requests — each one creates a
|
|
214
|
+
// unique pending request that the hook polls by requestId.
|
|
215
|
+
if (waitForResponse) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
104
219
|
const key = `${title}|${message}|${data?.category || 'unknown'}`;
|
|
105
220
|
const now = Date.now();
|
|
106
221
|
|
|
107
222
|
if (notificationCache.has(key)) {
|
|
108
|
-
const lastSent = notificationCache.get(key)
|
|
223
|
+
const lastSent = notificationCache.get(key) ?? 0;
|
|
109
224
|
if (now - lastSent < DEDUP_WINDOW) {
|
|
110
225
|
return true; // Duplicate within time window
|
|
111
226
|
}
|
|
@@ -159,6 +274,13 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
159
274
|
const waitForResponse =
|
|
160
275
|
typeof body.waitForResponse === 'boolean' ? body.waitForResponse : false;
|
|
161
276
|
|
|
277
|
+
// Broadcast to /ws/events for real-time activity feed
|
|
278
|
+
try {
|
|
279
|
+
broadcastHookEvent(body);
|
|
280
|
+
} catch {
|
|
281
|
+
// Best-effort broadcast — don't fail the notify request
|
|
282
|
+
}
|
|
283
|
+
|
|
162
284
|
if (!title || typeof title !== 'string' || !message || typeof message !== 'string') {
|
|
163
285
|
return json({ error: 'Title and message are required and must be strings' }, { status: 400 });
|
|
164
286
|
}
|
|
@@ -171,22 +293,24 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
171
293
|
const requestId = Math.random().toString(36).substring(2, 15);
|
|
172
294
|
const dataRequestId = typeof data?.requestId === 'string' ? data.requestId : undefined;
|
|
173
295
|
const canonicalRequestId = dataRequestId || requestId;
|
|
174
|
-
const shouldSendNotification = intelligentNotificationFilter(
|
|
296
|
+
const shouldSendNotification = intelligentNotificationFilter(
|
|
297
|
+
title,
|
|
298
|
+
message,
|
|
299
|
+
data,
|
|
300
|
+
waitForResponse
|
|
301
|
+
);
|
|
175
302
|
|
|
176
303
|
if (!shouldSendNotification.send) {
|
|
177
|
-
addNotification(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
title,
|
|
188
|
-
tool: data?.tool ?? null,
|
|
189
|
-
});
|
|
304
|
+
addNotification(
|
|
305
|
+
buildNotificationRecord(
|
|
306
|
+
canonicalRequestId,
|
|
307
|
+
title,
|
|
308
|
+
message,
|
|
309
|
+
'filtered',
|
|
310
|
+
data,
|
|
311
|
+
shouldSendNotification.reason
|
|
312
|
+
)
|
|
313
|
+
);
|
|
190
314
|
|
|
191
315
|
return json({
|
|
192
316
|
message: 'Notification filtered (not sent)',
|
|
@@ -209,19 +333,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
209
333
|
});
|
|
210
334
|
}
|
|
211
335
|
|
|
212
|
-
addNotification(
|
|
213
|
-
category: data?.category ?? null,
|
|
214
|
-
data: (data as Record<string, unknown>) ?? null,
|
|
215
|
-
error: null,
|
|
216
|
-
id: canonicalRequestId,
|
|
217
|
-
message,
|
|
218
|
-
project: data?.project ?? null,
|
|
219
|
-
source: data?.source ?? null,
|
|
220
|
-
status: 'skipped',
|
|
221
|
-
timestamp: new Date().toISOString(),
|
|
222
|
-
title,
|
|
223
|
-
tool: data?.tool ?? null,
|
|
224
|
-
});
|
|
336
|
+
addNotification(buildNotificationRecord(canonicalRequestId, title, message, 'skipped', data));
|
|
225
337
|
|
|
226
338
|
return json({
|
|
227
339
|
message: 'Push skipped (WebSocket clients connected)',
|
|
@@ -293,19 +405,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
293
405
|
});
|
|
294
406
|
}
|
|
295
407
|
|
|
296
|
-
addNotification(
|
|
297
|
-
category: data?.category ?? null,
|
|
298
|
-
data: (data as Record<string, unknown>) ?? null,
|
|
299
|
-
error: null,
|
|
300
|
-
id: canonicalRequestId,
|
|
301
|
-
message,
|
|
302
|
-
project: data?.project ?? null,
|
|
303
|
-
source: data?.source ?? null,
|
|
304
|
-
status: 'sent',
|
|
305
|
-
timestamp: new Date().toISOString(),
|
|
306
|
-
title,
|
|
307
|
-
tool: data?.tool ?? null,
|
|
308
|
-
});
|
|
408
|
+
addNotification(buildNotificationRecord(canonicalRequestId, title, message, 'sent', data));
|
|
309
409
|
|
|
310
410
|
return json({
|
|
311
411
|
message: 'Notification sent successfully',
|
|
@@ -317,19 +417,16 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
317
417
|
} else {
|
|
318
418
|
console.error(`[notify] FCM delivery failed: ${fcmResult.error}`);
|
|
319
419
|
|
|
320
|
-
addNotification(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
title,
|
|
331
|
-
tool: data?.tool ?? null,
|
|
332
|
-
});
|
|
420
|
+
addNotification(
|
|
421
|
+
buildNotificationRecord(
|
|
422
|
+
canonicalRequestId,
|
|
423
|
+
title,
|
|
424
|
+
message,
|
|
425
|
+
'failed',
|
|
426
|
+
data,
|
|
427
|
+
fcmResult.error
|
|
428
|
+
)
|
|
429
|
+
);
|
|
333
430
|
|
|
334
431
|
return json(
|
|
335
432
|
{
|
|
@@ -384,19 +481,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
384
481
|
});
|
|
385
482
|
}
|
|
386
483
|
|
|
387
|
-
addNotification(
|
|
388
|
-
category: data?.category ?? null,
|
|
389
|
-
data: (data as Record<string, unknown>) ?? null,
|
|
390
|
-
error: null,
|
|
391
|
-
id: canonicalRequestId,
|
|
392
|
-
message,
|
|
393
|
-
project: data?.project ?? null,
|
|
394
|
-
source: data?.source ?? null,
|
|
395
|
-
status: 'sent',
|
|
396
|
-
timestamp: new Date().toISOString(),
|
|
397
|
-
title,
|
|
398
|
-
tool: data?.tool ?? null,
|
|
399
|
-
});
|
|
484
|
+
addNotification(buildNotificationRecord(canonicalRequestId, title, message, 'sent', data));
|
|
400
485
|
|
|
401
486
|
return json({
|
|
402
487
|
message: 'Notification sent successfully',
|
|
@@ -409,19 +494,9 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
409
494
|
const notifErrMsg = toErrorMessage(notificationError);
|
|
410
495
|
console.error(`[notify] APNs delivery failed: ${notifErrMsg}`);
|
|
411
496
|
|
|
412
|
-
addNotification(
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
error: notifErrMsg,
|
|
416
|
-
id: canonicalRequestId,
|
|
417
|
-
message,
|
|
418
|
-
project: data?.project ?? null,
|
|
419
|
-
source: data?.source ?? null,
|
|
420
|
-
status: 'failed',
|
|
421
|
-
timestamp: new Date().toISOString(),
|
|
422
|
-
title,
|
|
423
|
-
tool: data?.tool ?? null,
|
|
424
|
-
});
|
|
497
|
+
addNotification(
|
|
498
|
+
buildNotificationRecord(canonicalRequestId, title, message, 'failed', data, notifErrMsg)
|
|
499
|
+
);
|
|
425
500
|
|
|
426
501
|
return json(
|
|
427
502
|
{
|
|
@@ -65,9 +65,11 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
65
65
|
|
|
66
66
|
const existing = ptyManager
|
|
67
67
|
.list()
|
|
68
|
-
.find(
|
|
69
|
-
t
|
|
70
|
-
|
|
68
|
+
.find(
|
|
69
|
+
(t) =>
|
|
70
|
+
t.status === 'running' &&
|
|
71
|
+
(t.sessionFile?.endsWith(`/${sessionId}.jsonl`) || t.openCodeSessionId === sessionId)
|
|
72
|
+
);
|
|
71
73
|
|
|
72
74
|
if (existing) {
|
|
73
75
|
console.log(
|
|
@@ -94,8 +96,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
94
96
|
|
|
95
97
|
// --- Build args based on command ---
|
|
96
98
|
|
|
97
|
-
const args: string[] =
|
|
98
|
-
command === 'claude' ? ['--resume', sessionId] : ['--session', sessionId];
|
|
99
|
+
const args: string[] = command === 'claude' ? ['--resume', sessionId] : ['--session', sessionId];
|
|
99
100
|
|
|
100
101
|
try {
|
|
101
102
|
const terminal = await ptyManager.create(command, args, realCwd, 120, 40);
|
|
@@ -107,7 +108,10 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
107
108
|
return json(
|
|
108
109
|
{
|
|
109
110
|
command: terminal.command,
|
|
110
|
-
createdAt:
|
|
111
|
+
createdAt:
|
|
112
|
+
terminal.createdAt instanceof Date
|
|
113
|
+
? terminal.createdAt.toISOString()
|
|
114
|
+
: terminal.createdAt,
|
|
111
115
|
cwd: terminal.cwd,
|
|
112
116
|
id: terminal.id,
|
|
113
117
|
pid: terminal.pid,
|
|
@@ -9,6 +9,21 @@ import type { RequestHandler } from './$types';
|
|
|
9
9
|
|
|
10
10
|
const ALLOWED_COMMANDS = ['zsh', 'bash', 'sh', 'fish', 'claude', 'opencode'];
|
|
11
11
|
|
|
12
|
+
/** Extract the last non-empty line from a scrollback string. */
|
|
13
|
+
function lastScrollbackLine(scrollback: string): null | string {
|
|
14
|
+
if (!scrollback) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const lines = scrollback.trimEnd().split('\n');
|
|
18
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
19
|
+
const line = lines[i].trim();
|
|
20
|
+
if (line) {
|
|
21
|
+
return line.slice(0, 200);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
12
27
|
// GET /api/terminals — List all terminals (active + recently exited)
|
|
13
28
|
export const GET: RequestHandler = ({ request }) => {
|
|
14
29
|
const authError = validateAuth(request);
|
|
@@ -28,6 +43,7 @@ export const GET: RequestHandler = ({ request }) => {
|
|
|
28
43
|
exitedAt: t.exitedAt?.toISOString() ?? null,
|
|
29
44
|
id: t.id,
|
|
30
45
|
isActive: t.isActive,
|
|
46
|
+
lastOutput: lastScrollbackLine(t.scrollback),
|
|
31
47
|
pid: t.pid,
|
|
32
48
|
status: t.status,
|
|
33
49
|
}));
|
|
@@ -127,7 +143,10 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
127
143
|
return json(
|
|
128
144
|
{
|
|
129
145
|
command: terminal.command,
|
|
130
|
-
createdAt:
|
|
146
|
+
createdAt:
|
|
147
|
+
terminal.createdAt instanceof Date
|
|
148
|
+
? terminal.createdAt.toISOString()
|
|
149
|
+
: terminal.createdAt,
|
|
131
150
|
cwd: terminal.cwd,
|
|
132
151
|
id: terminal.id,
|
|
133
152
|
pid: terminal.pid,
|
|
@@ -5,6 +5,21 @@ import { json } from '@sveltejs/kit';
|
|
|
5
5
|
|
|
6
6
|
import type { RequestHandler } from './$types';
|
|
7
7
|
|
|
8
|
+
/** Extract the last non-empty line from a scrollback string. */
|
|
9
|
+
function lastScrollbackLine(scrollback: string): null | string {
|
|
10
|
+
if (!scrollback) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const lines = scrollback.trimEnd().split('\n');
|
|
14
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
15
|
+
const line = lines[i].trim();
|
|
16
|
+
if (line) {
|
|
17
|
+
return line.slice(0, 200);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
8
23
|
// GET /api/terminals/:id — Get terminal details by ID
|
|
9
24
|
export const GET: RequestHandler = ({ params, request }) => {
|
|
10
25
|
const authError = validateAuth(request);
|
|
@@ -28,8 +43,7 @@ export const GET: RequestHandler = ({ params, request }) => {
|
|
|
28
43
|
exitCode: terminal.exitCode,
|
|
29
44
|
exitedAt: terminal.exitedAt?.toISOString() ?? null,
|
|
30
45
|
id: terminal.id,
|
|
31
|
-
lastOutput:
|
|
32
|
-
terminal.scrollback.length > 0 ? terminal.scrollback[terminal.scrollback.length - 1] : null,
|
|
46
|
+
lastOutput: lastScrollbackLine(terminal.scrollback),
|
|
33
47
|
pid: terminal.pid,
|
|
34
48
|
sessionWs: `/ws/session/${terminal.id}`,
|
|
35
49
|
status: terminal.status,
|
|
@@ -1,40 +1,12 @@
|
|
|
1
1
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
|
-
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
3
2
|
import { json } from '@sveltejs/kit';
|
|
4
3
|
|
|
5
4
|
import type { RequestHandler } from './$types';
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const authError = validateAuth(request);
|
|
12
|
-
if (authError) {
|
|
13
|
-
return authError;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const body = (await request.json()) as Record<string, unknown>;
|
|
17
|
-
|
|
18
|
-
console.log('Webhook received:', {
|
|
19
|
-
body,
|
|
20
|
-
timestamp: new Date().toISOString(),
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// In a full implementation, this would forward to Claude Code
|
|
24
|
-
// For now, just log and acknowledge
|
|
25
|
-
|
|
26
|
-
return json({
|
|
27
|
-
message: 'Webhook received successfully',
|
|
28
|
-
success: true,
|
|
29
|
-
timestamp: new Date().toISOString(),
|
|
30
|
-
});
|
|
31
|
-
} catch (error) {
|
|
32
|
-
console.error('[webhook] Failed to process webhook:', toErrorMessage(error));
|
|
33
|
-
return json(
|
|
34
|
-
{
|
|
35
|
-
error: 'Failed to process webhook',
|
|
36
|
-
},
|
|
37
|
-
{ status: 500 }
|
|
38
|
-
);
|
|
6
|
+
export const POST: RequestHandler = ({ request }) => {
|
|
7
|
+
const authError = validateAuth(request);
|
|
8
|
+
if (authError) {
|
|
9
|
+
return authError;
|
|
39
10
|
}
|
|
11
|
+
return json({ error: 'Webhook endpoint not implemented' }, { status: 501 });
|
|
40
12
|
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// query parameter on the WebSocket upgrade URL, keeping the long-lived API_KEY
|
|
6
6
|
// out of URL strings (which appear in proxy logs and browser history).
|
|
7
7
|
//
|
|
8
|
-
// Rate limited to
|
|
8
|
+
// Rate limited to 30 requests per minute per API key.
|
|
9
9
|
|
|
10
10
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
11
11
|
import { generateTicket } from '$lib/modules/server/ws/ticket-store';
|
|
@@ -16,7 +16,7 @@ import type { RequestHandler } from './$types';
|
|
|
16
16
|
// ── Rate limiting ───────────────────────────────────────────────────
|
|
17
17
|
|
|
18
18
|
const RATE_LIMIT_WINDOW_MS = 60_000; // 60 seconds
|
|
19
|
-
const RATE_LIMIT_MAX =
|
|
19
|
+
const RATE_LIMIT_MAX = 30; // max 30 requests per window (activity feed + dashboard + per-terminal sockets)
|
|
20
20
|
|
|
21
21
|
/** Maps API key -> array of request timestamps (epoch ms). */
|
|
22
22
|
const rateLimitMap = new Map<string, number[]>();
|
|
@@ -69,11 +69,11 @@ export const POST: RequestHandler = ({ request }) => {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// Extract the API key for rate limiting
|
|
72
|
-
const apiKey = request.headers.get('authorization')
|
|
72
|
+
const apiKey = (request.headers.get('authorization') ?? '').substring(7).trim();
|
|
73
73
|
|
|
74
74
|
if (!checkRateLimit(apiKey)) {
|
|
75
75
|
return json(
|
|
76
|
-
{ error: 'Rate limit exceeded. Maximum
|
|
76
|
+
{ error: 'Rate limit exceeded. Maximum 30 ticket requests per minute.' },
|
|
77
77
|
{ status: 429 }
|
|
78
78
|
);
|
|
79
79
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { env } from '$env/dynamic/private';
|
|
2
|
+
import { getProviderAvailability } from '$lib/modules/shared/providers';
|
|
3
|
+
|
|
4
|
+
import type { PageServerLoad } from './$types';
|
|
5
|
+
|
|
6
|
+
export const load: PageServerLoad = () => ({
|
|
7
|
+
activeProvider: env.NEUROLINK_PROVIDER ?? '',
|
|
8
|
+
aiProviders: getProviderAvailability(env),
|
|
9
|
+
});
|