@juspay/shooter 1.0.0 → 1.2.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/.claude/hooks/notifier.cjs +117 -33
- package/.claude/settings.json +14 -14
- package/README.md +116 -84
- package/bin/shooter.cjs +471 -102
- package/build/client/_app/immutable/assets/{0.CM9Hl6d-.css → 0.BhZOCxO4.css} +1 -1
- package/build/client/_app/immutable/assets/0.BhZOCxO4.css.br +0 -0
- package/build/client/_app/immutable/assets/0.BhZOCxO4.css.gz +0 -0
- package/build/client/_app/immutable/assets/1.BYutk3aU.css +1 -0
- package/build/client/_app/immutable/assets/1.BYutk3aU.css.br +0 -0
- package/build/client/_app/immutable/assets/1.BYutk3aU.css.gz +0 -0
- package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.DGDHCVnW.css +1 -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/assets/4.BFUut--w.css +1 -0
- package/build/client/_app/immutable/assets/4.BFUut--w.css.br +0 -0
- package/build/client/_app/immutable/assets/4.BFUut--w.css.gz +0 -0
- package/build/client/_app/immutable/assets/5.BTOx7yt7.css +1 -0
- package/build/client/_app/immutable/assets/5.BTOx7yt7.css.br +0 -0
- package/build/client/_app/immutable/assets/5.BTOx7yt7.css.gz +0 -0
- package/build/client/_app/immutable/assets/6.eZGZN-BF.css +1 -0
- package/build/client/_app/immutable/assets/6.eZGZN-BF.css.br +0 -0
- package/build/client/_app/immutable/assets/6.eZGZN-BF.css.gz +0 -0
- package/build/client/_app/immutable/assets/7.DwS5ZHBh.css +1 -0
- package/build/client/_app/immutable/assets/7.DwS5ZHBh.css.br +0 -0
- package/build/client/_app/immutable/assets/7.DwS5ZHBh.css.gz +0 -0
- package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css +1 -0
- package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css.br +0 -0
- package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css.gz +0 -0
- package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css +1 -0
- package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css.br +0 -0
- package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css.gz +0 -0
- package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css +1 -0
- package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css.br +0 -0
- package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css.gz +0 -0
- package/build/client/_app/immutable/assets/xterm.DFuMZ0ql.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B-K5Sh65.js +1 -0
- package/build/client/_app/immutable/chunks/B-K5Sh65.js.br +0 -0
- package/build/client/_app/immutable/chunks/B-K5Sh65.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B5NAKyil.js +20 -0
- 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 +1 -0
- 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 +6 -0
- 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/BLszSzTT.js +1 -0
- package/build/client/_app/immutable/chunks/BLszSzTT.js.br +0 -0
- package/build/client/_app/immutable/chunks/BLszSzTT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BOYo8yTr.js +1 -0
- 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/BTGVxaYV.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BYqGCrTe.js +1 -0
- package/build/client/_app/immutable/chunks/BYqGCrTe.js.br +0 -0
- package/build/client/_app/immutable/chunks/BYqGCrTe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BlxrFPDK.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bu1aqm5j.js +1 -0
- 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/C4mLaWWx.js +1 -0
- package/build/client/_app/immutable/chunks/C4mLaWWx.js.br +0 -0
- package/build/client/_app/immutable/chunks/C4mLaWWx.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CQjSATpv.js +61 -0
- 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/CSoRdFvv.js +1 -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 +1 -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/DLu6yJIZ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DSU1n5N_.js +1 -0
- 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 +1 -0
- 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 +41 -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/PPVm8Dsz.js.gz +0 -0
- package/build/client/_app/immutable/chunks/UJOiqIYE.js +1 -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 +2 -0
- 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.Z3zMnuSx.js +2 -0
- package/build/client/_app/immutable/entry/app.Z3zMnuSx.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Z3zMnuSx.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.Dd-gIP4y.js +1 -0
- package/build/client/_app/immutable/entry/start.Dd-gIP4y.js.br +2 -0
- package/build/client/_app/immutable/entry/start.Dd-gIP4y.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.D2YR8tTD.js +1 -0
- package/build/client/_app/immutable/nodes/0.D2YR8tTD.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.D2YR8tTD.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.B3m6rO4C.js +1 -0
- package/build/client/_app/immutable/nodes/1.B3m6rO4C.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.B3m6rO4C.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.CyRB2euU.js +1 -0
- package/build/client/_app/immutable/nodes/2.CyRB2euU.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CyRB2euU.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.3yohCM25.js +3 -0
- 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.DEAcwl7l.js +1 -0
- package/build/client/_app/immutable/nodes/4.DEAcwl7l.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.DEAcwl7l.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.C6bLGWQR.js +4 -0
- package/build/client/_app/immutable/nodes/5.C6bLGWQR.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.C6bLGWQR.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.ByTzlA2D.js +2 -0
- package/build/client/_app/immutable/nodes/6.ByTzlA2D.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.ByTzlA2D.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.BPMfwzd2.js +2 -0
- package/build/client/_app/immutable/nodes/7.BPMfwzd2.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.BPMfwzd2.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/client/favicon.svg.gz +0 -0
- package/build/client/manifest.json +13 -0
- package/build/client/manifest.json.br +0 -0
- package/build/client/manifest.json.gz +0 -0
- package/build/pty-holder.cjs +37 -8
- package/build/server/chunks/0-Vk38tI2J.js +9 -0
- package/build/server/chunks/0-Vk38tI2J.js.map +1 -0
- package/build/server/chunks/1-BvYQX5MR.js +9 -0
- package/build/server/chunks/1-BvYQX5MR.js.map +1 -0
- package/build/server/chunks/2-Cl7R4Qk2.js +9 -0
- package/build/server/chunks/2-Cl7R4Qk2.js.map +1 -0
- package/build/server/chunks/3-Ck7ewhOX.js +9 -0
- package/build/server/chunks/3-Ck7ewhOX.js.map +1 -0
- package/build/server/chunks/4-CnDeRm2Z.js +9 -0
- package/build/server/chunks/4-CnDeRm2Z.js.map +1 -0
- package/build/server/chunks/5-IxitzEvN.js +9 -0
- package/build/server/chunks/5-IxitzEvN.js.map +1 -0
- package/build/server/chunks/6-CyZ3r1iS.js +9 -0
- package/build/server/chunks/6-CyZ3r1iS.js.map +1 -0
- package/build/server/chunks/7-BmI7du46.js +9 -0
- package/build/server/chunks/7-BmI7du46.js.map +1 -0
- package/build/server/chunks/Button-Cs1aE6ka.js +80 -0
- package/build/server/chunks/Button-Cs1aE6ka.js.map +1 -0
- package/build/server/chunks/EmptyState-DDFH1K8g.js +26 -0
- package/build/server/chunks/EmptyState-DDFH1K8g.js.map +1 -0
- package/build/server/chunks/Icon-CEUrotA6.js +36 -0
- package/build/server/chunks/Icon-CEUrotA6.js.map +1 -0
- package/build/server/chunks/Shimmer-DB8W1zt6.js +10 -0
- package/build/server/chunks/Shimmer-DB8W1zt6.js.map +1 -0
- package/build/server/chunks/_error.svelte-uCOJNxvr.js +39 -0
- package/build/server/chunks/_error.svelte-uCOJNxvr.js.map +1 -0
- package/build/server/chunks/_layout.svelte-CtWmEJwe.js +56 -0
- package/build/server/chunks/_layout.svelte-CtWmEJwe.js.map +1 -0
- package/build/server/chunks/_page.svelte-BcZaKdX9.js +45 -0
- package/build/server/chunks/_page.svelte-BcZaKdX9.js.map +1 -0
- package/build/server/chunks/_page.svelte-BdYynOck.js +85 -0
- package/build/server/chunks/_page.svelte-BdYynOck.js.map +1 -0
- package/build/server/chunks/_page.svelte-BgevQjq1.js +101 -0
- package/build/server/chunks/_page.svelte-BgevQjq1.js.map +1 -0
- package/build/server/chunks/_page.svelte-CVq6tRb3.js +550 -0
- package/build/server/chunks/_page.svelte-CVq6tRb3.js.map +1 -0
- package/build/server/chunks/_page.svelte-CxWcQ0Am.js +651 -0
- package/build/server/chunks/_page.svelte-CxWcQ0Am.js.map +1 -0
- package/build/server/chunks/_page.svelte-DO4oa_LY.js +44 -0
- package/build/server/chunks/_page.svelte-DO4oa_LY.js.map +1 -0
- package/build/server/chunks/{_server.ts-CbDRDIoP.js → _server.ts-BStnNIcq.js} +9 -11
- package/build/server/chunks/_server.ts-BStnNIcq.js.map +1 -0
- package/build/server/chunks/{_server.ts-DRVbgm6k.js → _server.ts-CAxsWKvS.js} +22 -25
- package/build/server/chunks/_server.ts-CAxsWKvS.js.map +1 -0
- package/build/server/chunks/{_server.ts-CPa6DgIt.js → _server.ts-COu0vNpd.js} +6 -6
- package/build/server/chunks/_server.ts-COu0vNpd.js.map +1 -0
- package/build/server/chunks/{_server.ts-C29xzfaw.js → _server.ts-CTpcLUH8.js} +10 -10
- package/build/server/chunks/_server.ts-CTpcLUH8.js.map +1 -0
- package/build/server/chunks/{_server.ts-D4MNi4cD.js → _server.ts-Cf84YIaW.js} +3 -3
- package/build/server/chunks/{_server.ts-D4MNi4cD.js.map → _server.ts-Cf84YIaW.js.map} +1 -1
- package/build/server/chunks/{_server.ts-BL2FGb5Z.js → _server.ts-Ch-6iOHp.js} +99 -53
- package/build/server/chunks/_server.ts-Ch-6iOHp.js.map +1 -0
- package/build/server/chunks/_server.ts-CtH0dhUp.js +71 -0
- package/build/server/chunks/_server.ts-CtH0dhUp.js.map +1 -0
- package/build/server/chunks/_server.ts-DB_Kg97c.js +73 -0
- package/build/server/chunks/_server.ts-DB_Kg97c.js.map +1 -0
- package/build/server/chunks/{_server.ts-DfajWaqh.js → _server.ts-DV8zTCF9.js} +7 -9
- package/build/server/chunks/_server.ts-DV8zTCF9.js.map +1 -0
- package/build/server/chunks/_server.ts-DYpJImqd.js +99 -0
- package/build/server/chunks/_server.ts-DYpJImqd.js.map +1 -0
- package/build/server/chunks/{_server.ts-ColfDHW8.js → _server.ts-DYvb9ijZ.js} +21 -10
- package/build/server/chunks/_server.ts-DYvb9ijZ.js.map +1 -0
- package/build/server/chunks/{_server.ts-Cv_OrRuL.js → _server.ts-Deok2y88.js} +209 -34
- package/build/server/chunks/_server.ts-Deok2y88.js.map +1 -0
- package/build/server/chunks/{_server.ts-y9-WYDMa.js → _server.ts-WhTJBEJy.js} +5 -4
- package/build/server/chunks/{_server.ts-y9-WYDMa.js.map → _server.ts-WhTJBEJy.js.map} +1 -1
- package/build/server/chunks/{_server.ts-BjOJsoy4.js → _server.ts-XzT2UHM1.js} +6 -5
- package/build/server/chunks/_server.ts-XzT2UHM1.js.map +1 -0
- package/build/server/chunks/{_server.ts-BgdjBZco.js → _server.ts-tSpgyl1D.js} +7 -5
- package/build/server/chunks/_server.ts-tSpgyl1D.js.map +1 -0
- package/build/server/chunks/{_server.ts-BihKSdj_.js → _server.ts-vekTmWAx.js} +8 -8
- package/build/server/chunks/_server.ts-vekTmWAx.js.map +1 -0
- package/build/server/chunks/{auth-CEgFis71.js → auth-DeCdZ83n.js} +2 -2
- package/build/server/chunks/{auth-CEgFis71.js.map → auth-DeCdZ83n.js.map} +1 -1
- package/build/server/chunks/client-BdGHe_hY.js +25 -0
- package/build/server/chunks/client-BdGHe_hY.js.map +1 -0
- package/build/server/chunks/client2-CCBGA-2V.js +7 -0
- package/build/server/chunks/client2-CCBGA-2V.js.map +1 -0
- package/build/server/chunks/error-DDXB3duW.js +12 -0
- package/build/server/chunks/error-DDXB3duW.js.map +1 -0
- package/build/server/chunks/{exports-CJ0Q5XmL.js → index-DwaY1cAm.js} +1111 -1634
- package/build/server/chunks/index-DwaY1cAm.js.map +1 -0
- package/build/server/chunks/index-server-CrDaL06Y.js +9 -0
- package/build/server/chunks/index-server-CrDaL06Y.js.map +1 -0
- package/build/server/chunks/index2-CgclKpUj.js +58 -0
- package/build/server/chunks/index2-CgclKpUj.js.map +1 -0
- package/build/server/chunks/{library-apns-BHxLmuIx.js → library-apns-BqJbvSKh.js} +4 -4
- package/build/server/chunks/library-apns-BqJbvSKh.js.map +1 -0
- package/build/server/chunks/markdown-W_mTBct0.js +8 -0
- package/build/server/chunks/markdown-W_mTBct0.js.map +1 -0
- package/build/server/chunks/opencode-db-path-DcfhJtJy.js +15 -0
- package/build/server/chunks/opencode-db-path-DcfhJtJy.js.map +1 -0
- package/build/server/chunks/{pty-manager-C0FhBiVq.js → pty-manager-BQVB7IVj.js} +155 -326
- package/build/server/chunks/pty-manager-BQVB7IVj.js.map +1 -0
- package/build/server/chunks/root-DDSnEAZv.js +1171 -0
- package/build/server/chunks/root-DDSnEAZv.js.map +1 -0
- package/build/server/chunks/{shared-server-BDY8jh20.js → shared-server-sSGG17Df.js} +2 -3
- package/build/server/chunks/{shared-server-BDY8jh20.js.map → shared-server-sSGG17Df.js.map} +1 -1
- package/build/server/chunks/state.svelte-hBbXlUak.js +11 -0
- package/build/server/chunks/state.svelte-hBbXlUak.js.map +1 -0
- package/build/server/chunks/stores-DHNzYNpX.js +28 -0
- package/build/server/chunks/stores-DHNzYNpX.js.map +1 -0
- package/build/server/index.js +1085 -2242
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +39 -25
- package/build/server/manifest.js.map +1 -1
- package/package.json +32 -9
- package/scripts/fix-generated-types.sh +37 -0
- package/scripts/homebrew/shooter.rb +51 -0
- package/scripts/install.sh +348 -186
- package/scripts/setup.cjs +215 -45
- package/server.ts +114 -71
- package/src/app.css +12 -3
- package/src/app.d.ts +13 -20
- package/src/app.html +3 -2
- package/src/generated/types/API.ts +280 -0
- package/src/generated/types/APN.ts +186 -203
- package/src/generated/types/CLI.ts +18 -25
- package/src/generated/types/Client.ts +589 -0
- package/src/generated/types/Config.ts +53 -0
- package/src/generated/types/Holder.ts +638 -0
- package/src/generated/types/JWT.ts +39 -50
- package/src/generated/types/Notification.ts +426 -0
- package/src/generated/types/OpenCode.ts +356 -0
- package/src/generated/types/Sessions.ts +570 -0
- package/src/generated/types/Terminal.ts +2184 -2071
- package/src/generated/types/WsProtocol.ts +2004 -0
- package/src/generated/types/index.ts +9 -3
- package/src/lib/env.ts +29 -0
- package/src/lib/modules/client/common/cache.ts +10 -2
- package/src/lib/modules/client/common/config-guard.ts +37 -5
- package/src/lib/modules/client/common/error.ts +10 -0
- package/src/lib/modules/client/common/index.ts +6 -5
- package/src/lib/modules/client/common/markdown.ts +22 -1
- package/src/lib/modules/client/common/native-bridge.ts +28 -20
- package/src/lib/modules/client/common/time.ts +13 -11
- package/src/lib/modules/client/terminal/ChatView.svelte +354 -74
- package/src/lib/modules/client/terminal/CommandPalette.svelte +3 -2
- package/src/lib/modules/client/terminal/ConnectionStatus.svelte +7 -1
- package/src/lib/modules/client/terminal/LaunchSheet.svelte +147 -84
- package/src/lib/modules/client/terminal/QuickKeys.svelte +3 -1
- package/src/lib/modules/client/terminal/ShortcutsHelp.svelte +2 -5
- package/src/lib/modules/client/terminal/keyboard-shortcuts.ts +27 -24
- package/src/lib/modules/client/terminal/xterm-wrapper.ts +74 -45
- package/src/lib/modules/server/apn/library-apns.ts +3 -2
- package/src/lib/modules/server/apn/notification-history.ts +2 -13
- package/src/lib/modules/server/apn/notification-sessions.ts +3 -13
- package/src/lib/modules/server/apn/pending-requests.ts +3 -8
- package/src/lib/modules/server/apn/types.ts +5 -4
- package/src/lib/modules/server/cli/index.ts +3 -2
- package/src/lib/modules/server/fcm/fcm-service.ts +8 -6
- package/src/lib/modules/server/sessions/jsonl-parser.ts +3 -3
- package/src/lib/modules/server/sessions/jsonl-reader.ts +86 -26
- package/src/lib/modules/server/sessions/opencode-db-path.ts +26 -0
- package/src/lib/modules/server/sessions/opencode-reader.ts +13 -15
- package/src/lib/modules/server/sessions/process-detector.ts +103 -0
- package/src/lib/modules/server/sessions/types.ts +11 -22
- package/src/lib/modules/server/terminal/holder-client.ts +272 -248
- package/src/lib/modules/server/terminal/opencode-watcher.ts +547 -556
- package/src/lib/modules/server/terminal/pty-holder.cjs +37 -8
- package/src/lib/modules/server/terminal/pty-manager.ts +157 -115
- package/src/lib/modules/server/terminal/session-watcher.ts +6 -4
- package/src/lib/modules/server/terminal/terminal-store.ts +131 -128
- package/src/lib/modules/server/utils/error.ts +9 -0
- package/src/lib/modules/server/ws/events-handler.ts +12 -6
- package/src/lib/modules/server/ws/keepalive.ts +86 -69
- package/src/lib/modules/server/ws/server.ts +43 -37
- package/src/lib/modules/server/ws/session-handler.ts +332 -147
- package/src/lib/modules/server/ws/terminal-handler.ts +29 -17
- package/src/lib/modules/server/ws/ticket-store.ts +29 -26
- package/src/lib/theme.css +30 -0
- package/src/lib/types/config.ts +1 -6
- package/src/routes/+error.svelte +94 -0
- package/src/routes/+layout.svelte +66 -31
- package/src/routes/+page.svelte +25 -22
- package/src/routes/api/debug/+server.ts +3 -1
- package/src/routes/api/device-token/+server.ts +60 -60
- package/src/routes/api/health/+server.ts +81 -73
- package/src/routes/api/notify/+server.ts +115 -68
- package/src/routes/api/qr-config/+server.ts +30 -32
- package/src/routes/api/response/+server.ts +9 -4
- package/src/routes/api/sessions/+server.ts +15 -5
- package/src/routes/api/sessions/connect/+server.ts +125 -0
- package/src/routes/api/sessions/detect/+server.ts +27 -0
- package/src/routes/api/terminals/+server.ts +26 -24
- package/src/routes/api/terminals/[id]/+server.ts +13 -7
- package/src/routes/api/terminals/[id]/paste-image/+server.ts +54 -52
- package/src/routes/api/terminals/[id]/resize/+server.ts +6 -3
- package/src/routes/api/webhook/+server.ts +8 -10
- package/src/routes/api/ws-status/+server.ts +7 -5
- package/src/routes/api/ws-ticket/+server.ts +42 -41
- package/src/routes/config/+page.svelte +149 -75
- package/src/routes/project/+page.svelte +165 -35
- package/src/routes/session/[id]/+page.svelte +479 -283
- package/src/routes/terminals/+page.svelte +58 -45
- package/src/routes/terminals/[id]/+page.svelte +223 -91
- package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.br +0 -0
- package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.gz +0 -0
- package/build/client/_app/immutable/assets/3.C0uFg0IS.css +0 -1
- package/build/client/_app/immutable/assets/3.C0uFg0IS.css.br +0 -0
- package/build/client/_app/immutable/assets/3.C0uFg0IS.css.gz +0 -0
- package/build/client/_app/immutable/assets/4.cJuCkJKZ.css +0 -1
- package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.br +0 -0
- package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.gz +0 -0
- package/build/client/_app/immutable/assets/5.DRjApZQW.css +0 -1
- package/build/client/_app/immutable/assets/5.DRjApZQW.css.br +0 -0
- package/build/client/_app/immutable/assets/5.DRjApZQW.css.gz +0 -0
- package/build/client/_app/immutable/assets/6.AraZrY8I.css +0 -1
- package/build/client/_app/immutable/assets/6.AraZrY8I.css.br +0 -0
- package/build/client/_app/immutable/assets/6.AraZrY8I.css.gz +0 -0
- package/build/client/_app/immutable/assets/7.BCJ1IuMx.css +0 -1
- package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.br +0 -0
- package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.gz +0 -0
- package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css +0 -1
- package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.br +0 -0
- package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.gz +0 -0
- package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css +0 -1
- package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.br +0 -0
- package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.gz +0 -0
- package/build/client/_app/immutable/chunks/BNJphC1q.js +0 -56
- package/build/client/_app/immutable/chunks/BNJphC1q.js.br +0 -0
- package/build/client/_app/immutable/chunks/BNJphC1q.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Bvk7mfPM.js +0 -1
- package/build/client/_app/immutable/chunks/Bvk7mfPM.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bvk7mfPM.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CAokzuPQ.js +0 -1
- package/build/client/_app/immutable/chunks/CAokzuPQ.js.br +0 -0
- package/build/client/_app/immutable/chunks/CAokzuPQ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CGLrx-H5.js +0 -1
- package/build/client/_app/immutable/chunks/CGLrx-H5.js.br +0 -0
- package/build/client/_app/immutable/chunks/CGLrx-H5.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CgCpWzEA.js +0 -1
- package/build/client/_app/immutable/chunks/CgCpWzEA.js.br +0 -0
- package/build/client/_app/immutable/chunks/CgCpWzEA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cjwk_cGO.js +0 -6
- package/build/client/_app/immutable/chunks/Cjwk_cGO.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cjwk_cGO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CtQ8EED1.js +0 -11
- package/build/client/_app/immutable/chunks/CtQ8EED1.js.br +0 -0
- package/build/client/_app/immutable/chunks/CtQ8EED1.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DERQCisl.js +0 -1
- package/build/client/_app/immutable/chunks/DERQCisl.js.br +0 -0
- package/build/client/_app/immutable/chunks/DERQCisl.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DKrg8TQs.js +0 -1
- package/build/client/_app/immutable/chunks/DKrg8TQs.js.br +0 -0
- package/build/client/_app/immutable/chunks/DKrg8TQs.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dkkpz_4D.js +0 -126
- package/build/client/_app/immutable/chunks/Dkkpz_4D.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dkkpz_4D.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DoczjQhA.js +0 -1
- package/build/client/_app/immutable/chunks/DoczjQhA.js.br +0 -0
- package/build/client/_app/immutable/chunks/DoczjQhA.js.gz +0 -0
- package/build/client/_app/immutable/chunks/RpcNruLP.js +0 -2
- package/build/client/_app/immutable/chunks/RpcNruLP.js.br +0 -0
- package/build/client/_app/immutable/chunks/RpcNruLP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/a-St0Zwo.js +0 -1
- package/build/client/_app/immutable/chunks/a-St0Zwo.js.br +0 -0
- package/build/client/_app/immutable/chunks/a-St0Zwo.js.gz +0 -0
- package/build/client/_app/immutable/chunks/bo70OQUZ.js +0 -1
- package/build/client/_app/immutable/chunks/bo70OQUZ.js.br +0 -0
- package/build/client/_app/immutable/chunks/bo70OQUZ.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.QvGgdvTI.js +0 -2
- package/build/client/_app/immutable/entry/app.QvGgdvTI.js.br +0 -0
- package/build/client/_app/immutable/entry/app.QvGgdvTI.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BntDNRMC.js +0 -1
- package/build/client/_app/immutable/entry/start.BntDNRMC.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BntDNRMC.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js +0 -1
- package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.MG1QhfrI.js +0 -1
- package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.B4MlOSh6.js +0 -1
- package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.DIwYkjDn.js +0 -3
- package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.D-cIe70D.js +0 -1
- package/build/client/_app/immutable/nodes/4.D-cIe70D.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.D-cIe70D.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.D7zPRe3L.js +0 -1
- package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.BB7QE48r.js +0 -2
- package/build/client/_app/immutable/nodes/6.BB7QE48r.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BB7QE48r.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.D8mqsrZG.js +0 -2
- package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.gz +0 -0
- package/build/client/manifest.webmanifest +0 -1
- package/build/client/registerSW.js +0 -1
- package/build/client/registerSW.js.br +0 -0
- package/build/client/registerSW.js.gz +0 -0
- package/build/client/sw.js +0 -222
- package/build/client/sw.js.br +0 -0
- package/build/client/sw.js.gz +0 -0
- package/build/client/workbox-5119daf5.js +0 -3395
- package/build/client/workbox-5119daf5.js.br +0 -0
- package/build/client/workbox-5119daf5.js.gz +0 -0
- package/build/server/chunks/0-q2IUp76Y.js +0 -9
- package/build/server/chunks/0-q2IUp76Y.js.map +0 -1
- package/build/server/chunks/1-CU50G5wZ.js +0 -9
- package/build/server/chunks/1-CU50G5wZ.js.map +0 -1
- package/build/server/chunks/2-D01t9s8T.js +0 -9
- package/build/server/chunks/2-D01t9s8T.js.map +0 -1
- package/build/server/chunks/3-5PUQ04wC.js +0 -9
- package/build/server/chunks/3-5PUQ04wC.js.map +0 -1
- package/build/server/chunks/4-e7gywnSG.js +0 -9
- package/build/server/chunks/4-e7gywnSG.js.map +0 -1
- package/build/server/chunks/5-CA1SA6KZ.js +0 -9
- package/build/server/chunks/5-CA1SA6KZ.js.map +0 -1
- package/build/server/chunks/6-71H221sV.js +0 -9
- package/build/server/chunks/6-71H221sV.js.map +0 -1
- package/build/server/chunks/7-Bo-vmdyz.js +0 -9
- package/build/server/chunks/7-Bo-vmdyz.js.map +0 -1
- package/build/server/chunks/_layout.svelte-SFHOxs74.js +0 -132
- package/build/server/chunks/_layout.svelte-SFHOxs74.js.map +0 -1
- package/build/server/chunks/_page.svelte-B4w-2wD-.js +0 -120
- package/build/server/chunks/_page.svelte-B4w-2wD-.js.map +0 -1
- package/build/server/chunks/_page.svelte-B_qAXjkh.js +0 -213
- package/build/server/chunks/_page.svelte-B_qAXjkh.js.map +0 -1
- package/build/server/chunks/_page.svelte-CsF1_TRG.js +0 -50
- package/build/server/chunks/_page.svelte-CsF1_TRG.js.map +0 -1
- package/build/server/chunks/_page.svelte-DJC6U-P0.js +0 -68
- package/build/server/chunks/_page.svelte-DJC6U-P0.js.map +0 -1
- package/build/server/chunks/_page.svelte-DQ6HBtsz.js +0 -407
- package/build/server/chunks/_page.svelte-DQ6HBtsz.js.map +0 -1
- package/build/server/chunks/_page.svelte-LbhhjP21.js +0 -148
- package/build/server/chunks/_page.svelte-LbhhjP21.js.map +0 -1
- package/build/server/chunks/_server.ts-BL2FGb5Z.js.map +0 -1
- package/build/server/chunks/_server.ts-BgdjBZco.js.map +0 -1
- package/build/server/chunks/_server.ts-BihKSdj_.js.map +0 -1
- package/build/server/chunks/_server.ts-BjOJsoy4.js.map +0 -1
- package/build/server/chunks/_server.ts-C29xzfaw.js.map +0 -1
- package/build/server/chunks/_server.ts-CPa6DgIt.js.map +0 -1
- package/build/server/chunks/_server.ts-CbDRDIoP.js.map +0 -1
- package/build/server/chunks/_server.ts-Cl1OEWL4.js +0 -54
- package/build/server/chunks/_server.ts-Cl1OEWL4.js.map +0 -1
- package/build/server/chunks/_server.ts-ColfDHW8.js.map +0 -1
- package/build/server/chunks/_server.ts-Cv_OrRuL.js.map +0 -1
- package/build/server/chunks/_server.ts-DRVbgm6k.js.map +0 -1
- package/build/server/chunks/_server.ts-DfajWaqh.js.map +0 -1
- package/build/server/chunks/client-CxCatAKr.js +0 -255
- package/build/server/chunks/client-CxCatAKr.js.map +0 -1
- package/build/server/chunks/error.svelte-BqdwMWdK.js +0 -26
- package/build/server/chunks/error.svelte-BqdwMWdK.js.map +0 -1
- package/build/server/chunks/exports-CJ0Q5XmL.js.map +0 -1
- package/build/server/chunks/index2-DAxIoAO-.js +0 -36
- package/build/server/chunks/index2-DAxIoAO-.js.map +0 -1
- package/build/server/chunks/jsonl-parser-dmZU_Hyu.js +0 -137
- package/build/server/chunks/jsonl-parser-dmZU_Hyu.js.map +0 -1
- package/build/server/chunks/library-apns-BHxLmuIx.js.map +0 -1
- package/build/server/chunks/markdown-Bxrl3cCF.js +0 -1241
- package/build/server/chunks/markdown-Bxrl3cCF.js.map +0 -1
- package/build/server/chunks/pty-manager-C0FhBiVq.js.map +0 -1
- package/build/server/chunks/stores-D0HorpgL.js +0 -36
- package/build/server/chunks/stores-D0HorpgL.js.map +0 -1
|
@@ -1,45 +1,43 @@
|
|
|
1
1
|
import { env } from '$env/dynamic/private';
|
|
2
2
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
3
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
3
4
|
import { json } from '@sveltejs/kit';
|
|
4
5
|
import QRCode from 'qrcode';
|
|
5
6
|
|
|
6
7
|
import type { RequestHandler } from './$types';
|
|
7
8
|
|
|
8
|
-
export const GET: RequestHandler = async ({ request }) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
export const GET: RequestHandler = async ({ request, url }) => {
|
|
10
|
+
const authError = validateAuth(request);
|
|
11
|
+
if (authError) {
|
|
12
|
+
return authError;
|
|
13
|
+
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const apiKey = env.API_KEY?.trim();
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
return json({ error: 'API_KEY not configured on server' }, { status: 500 });
|
|
18
|
+
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const host = request.headers.get('x-forwarded-host') || request.headers.get('host') || 'localhost:3000';
|
|
23
|
-
const serverUrl = `${proto}://${host}`;
|
|
20
|
+
// Use a configured server URL from env when available (trusted), otherwise
|
|
21
|
+
// fall back to url.origin (derived from the incoming request URL by SvelteKit).
|
|
22
|
+
const serverUrl = env.ORIGIN?.trim() || url.origin;
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
const configPayload = JSON.stringify({ apiKey, serverUrl });
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
try {
|
|
27
|
+
const dataUrl = await QRCode.toDataURL(configPayload, {
|
|
28
|
+
color: {
|
|
29
|
+
dark: '#ededed',
|
|
30
|
+
light: '#0a0a0a',
|
|
31
|
+
},
|
|
32
|
+
errorCorrectionLevel: 'M',
|
|
33
|
+
margin: 2,
|
|
34
|
+
type: 'image/png',
|
|
35
|
+
width: 280,
|
|
36
|
+
});
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
38
|
+
return json({ dataUrl, serverUrl });
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('[qr-config] QR generation failed:', toErrorMessage(error));
|
|
41
|
+
return json({ error: 'Failed to generate QR code' }, { status: 500 });
|
|
42
|
+
}
|
|
45
43
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cleanup, getDecision, setDecision } from '$lib/modules/server/apn/pending-requests';
|
|
2
2
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
3
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
3
4
|
import { json } from '@sveltejs/kit';
|
|
4
5
|
|
|
5
6
|
import type { RequestHandler } from './$types';
|
|
@@ -9,7 +10,9 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
9
10
|
cleanup();
|
|
10
11
|
|
|
11
12
|
const authError = validateAuth(request);
|
|
12
|
-
if (authError) {
|
|
13
|
+
if (authError) {
|
|
14
|
+
return authError;
|
|
15
|
+
}
|
|
13
16
|
|
|
14
17
|
let body: { decision?: string; requestId?: string };
|
|
15
18
|
try {
|
|
@@ -42,8 +45,8 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
42
45
|
timestamp: new Date().toISOString(),
|
|
43
46
|
});
|
|
44
47
|
} catch (error) {
|
|
45
|
-
|
|
46
|
-
return json({
|
|
48
|
+
console.error('[response] Failed to process response:', toErrorMessage(error));
|
|
49
|
+
return json({ error: 'Failed to process response' }, { status: 500 });
|
|
47
50
|
}
|
|
48
51
|
};
|
|
49
52
|
|
|
@@ -52,7 +55,9 @@ export const GET: RequestHandler = ({ request, url }) => {
|
|
|
52
55
|
cleanup();
|
|
53
56
|
|
|
54
57
|
const authErr = validateAuth(request);
|
|
55
|
-
if (authErr) {
|
|
58
|
+
if (authErr) {
|
|
59
|
+
return authErr;
|
|
60
|
+
}
|
|
56
61
|
|
|
57
62
|
const requestId = url.searchParams.get('requestId');
|
|
58
63
|
if (!requestId) {
|
|
@@ -13,10 +13,10 @@ import { json } from '@sveltejs/kit';
|
|
|
13
13
|
|
|
14
14
|
import type { RequestHandler } from './$types';
|
|
15
15
|
|
|
16
|
-
// Server-side cache for merged projects (
|
|
16
|
+
// Server-side cache for merged projects (5s TTL)
|
|
17
17
|
let cachedProjects: null | ProjectGroup[] = null;
|
|
18
18
|
let cacheTimestamp = 0;
|
|
19
|
-
const CACHE_TTL_MS =
|
|
19
|
+
const CACHE_TTL_MS = 5_000;
|
|
20
20
|
|
|
21
21
|
function getMergedProjects(): ProjectGroup[] {
|
|
22
22
|
const now = Date.now();
|
|
@@ -57,14 +57,24 @@ function getMergedProjects(): ProjectGroup[] {
|
|
|
57
57
|
|
|
58
58
|
export const GET: RequestHandler = ({ request, url }) => {
|
|
59
59
|
const authError = validateAuth(request);
|
|
60
|
-
if (authError) {
|
|
60
|
+
if (authError) {
|
|
61
|
+
return authError;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Force cache invalidation when ?refresh=true is passed
|
|
65
|
+
if (url.searchParams.get('refresh') === 'true') {
|
|
66
|
+
cachedProjects = null;
|
|
67
|
+
cacheTimestamp = 0;
|
|
68
|
+
}
|
|
61
69
|
|
|
62
70
|
const sessionId = url.searchParams.get('id');
|
|
63
71
|
|
|
64
72
|
if (sessionId) {
|
|
65
73
|
const projectId = url.searchParams.get('project') || '';
|
|
66
|
-
const
|
|
67
|
-
const
|
|
74
|
+
const rawOffset = parseInt(url.searchParams.get('offset') || '0');
|
|
75
|
+
const rawLimit = parseInt(url.searchParams.get('limit') || '200');
|
|
76
|
+
const offset = Number.isFinite(rawOffset) && rawOffset >= 0 ? rawOffset : 0;
|
|
77
|
+
const limit = Number.isFinite(rawLimit) && rawLimit >= 1 ? Math.min(rawLimit, 500) : 200;
|
|
68
78
|
|
|
69
79
|
// Resolve short project ID to full path for the readers
|
|
70
80
|
const allProjects = getMergedProjects();
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
|
+
import { ptyManager } from '$lib/modules/server/terminal/pty-manager';
|
|
3
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
4
|
+
import { json } from '@sveltejs/kit';
|
|
5
|
+
import { realpathSync, statSync } from 'fs';
|
|
6
|
+
import { isAbsolute, relative } from 'path';
|
|
7
|
+
|
|
8
|
+
import type { RequestHandler } from './$types';
|
|
9
|
+
|
|
10
|
+
// POST /api/sessions/connect — Resume a Claude Code / OpenCode session in a new terminal
|
|
11
|
+
export const POST: RequestHandler = async ({ request }) => {
|
|
12
|
+
const authError = validateAuth(request);
|
|
13
|
+
if (authError) {
|
|
14
|
+
return authError;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let body: { command?: string; cwd?: string; noCreate?: boolean; sessionId?: string };
|
|
18
|
+
try {
|
|
19
|
+
body = (await request.json()) as {
|
|
20
|
+
command?: string;
|
|
21
|
+
cwd?: string;
|
|
22
|
+
noCreate?: boolean;
|
|
23
|
+
sessionId?: string;
|
|
24
|
+
};
|
|
25
|
+
} catch {
|
|
26
|
+
return json({ error: 'Invalid JSON in request body' }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const { command, cwd, noCreate, sessionId } = body;
|
|
30
|
+
|
|
31
|
+
// --- Validate required fields ---
|
|
32
|
+
|
|
33
|
+
if (!sessionId || typeof sessionId !== 'string') {
|
|
34
|
+
return json({ error: 'sessionId is required (string)' }, { status: 400 });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!cwd || typeof cwd !== 'string') {
|
|
38
|
+
return json({ error: 'cwd is required (string)' }, { status: 400 });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!command || (command !== 'claude' && command !== 'opencode')) {
|
|
42
|
+
return json({ error: 'command must be "claude" or "opencode"' }, { status: 400 });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// --- Validate cwd (same checks as POST /api/terminals) ---
|
|
46
|
+
|
|
47
|
+
let realCwd: string;
|
|
48
|
+
try {
|
|
49
|
+
realCwd = realpathSync(cwd);
|
|
50
|
+
if (!statSync(realCwd).isDirectory()) {
|
|
51
|
+
return json({ error: 'Invalid working directory' }, { status: 400 });
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
return json({ error: 'Invalid working directory' }, { status: 400 });
|
|
55
|
+
}
|
|
56
|
+
const home = process.env.HOME || '';
|
|
57
|
+
if (home) {
|
|
58
|
+
const rel = relative(home, realCwd);
|
|
59
|
+
if (rel.startsWith('..') || isAbsolute(rel)) {
|
|
60
|
+
return json({ error: 'Working directory must be under home directory' }, { status: 400 });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// --- Reuse existing terminal if one is already running for this session ---
|
|
65
|
+
|
|
66
|
+
const existing = ptyManager
|
|
67
|
+
.list()
|
|
68
|
+
.find((t) => t.status === 'running' && (
|
|
69
|
+
t.sessionFile?.endsWith(`/${sessionId}.jsonl`) || t.openCodeSessionId === sessionId
|
|
70
|
+
));
|
|
71
|
+
|
|
72
|
+
if (existing) {
|
|
73
|
+
console.log(
|
|
74
|
+
`[sessions/connect] Reusing terminal ${existing.id} for ${command} session ${sessionId}`
|
|
75
|
+
);
|
|
76
|
+
return json({
|
|
77
|
+
command: existing.command,
|
|
78
|
+
createdAt: existing.createdAt.toISOString(),
|
|
79
|
+
cwd: existing.cwd,
|
|
80
|
+
id: existing.id,
|
|
81
|
+
pid: existing.pid,
|
|
82
|
+
reused: true,
|
|
83
|
+
sessionId,
|
|
84
|
+
sessionWs: `/ws/session/${existing.id}`,
|
|
85
|
+
terminalId: existing.id,
|
|
86
|
+
ws: `/ws/terminal/${existing.id}`,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// No existing terminal — return 404 if caller requested no-create
|
|
91
|
+
if (noCreate) {
|
|
92
|
+
return json({ error: 'No existing terminal for this session' }, { status: 404 });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// --- Build args based on command ---
|
|
96
|
+
|
|
97
|
+
const args: string[] =
|
|
98
|
+
command === 'claude' ? ['--resume', sessionId] : ['--session', sessionId];
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const terminal = await ptyManager.create(command, args, realCwd, 120, 40);
|
|
102
|
+
|
|
103
|
+
console.log(
|
|
104
|
+
`[sessions/connect] Created terminal ${terminal.id} for ${command} session ${sessionId} (pid=${terminal.pid})`
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return json(
|
|
108
|
+
{
|
|
109
|
+
command: terminal.command,
|
|
110
|
+
createdAt: terminal.createdAt instanceof Date ? terminal.createdAt.toISOString() : terminal.createdAt,
|
|
111
|
+
cwd: terminal.cwd,
|
|
112
|
+
id: terminal.id,
|
|
113
|
+
pid: terminal.pid,
|
|
114
|
+
sessionId,
|
|
115
|
+
sessionWs: `/ws/session/${terminal.id}`,
|
|
116
|
+
terminalId: terminal.id,
|
|
117
|
+
ws: `/ws/terminal/${terminal.id}`,
|
|
118
|
+
},
|
|
119
|
+
{ status: 201 }
|
|
120
|
+
);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error('[sessions/connect] Failed to create terminal:', toErrorMessage(error));
|
|
123
|
+
return json({ error: 'Failed to create terminal for session' }, { status: 500 });
|
|
124
|
+
}
|
|
125
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
|
+
import { detectRunningAISessions } from '$lib/modules/server/sessions/process-detector';
|
|
3
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
4
|
+
import { json } from '@sveltejs/kit';
|
|
5
|
+
|
|
6
|
+
import type { RequestHandler } from './$types';
|
|
7
|
+
|
|
8
|
+
// GET /api/sessions/detect — Detect running Claude Code / OpenCode processes
|
|
9
|
+
export const GET: RequestHandler = ({ request }) => {
|
|
10
|
+
const authError = validateAuth(request);
|
|
11
|
+
if (authError) {
|
|
12
|
+
return authError;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const processes = detectRunningAISessions();
|
|
17
|
+
|
|
18
|
+
return json({
|
|
19
|
+
count: processes.length,
|
|
20
|
+
processes,
|
|
21
|
+
timestamp: new Date().toISOString(),
|
|
22
|
+
});
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error('[sessions/detect] Failed to detect running sessions:', toErrorMessage(error));
|
|
25
|
+
return json({ error: 'Failed to detect running sessions' }, { status: 500 });
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
|
-
import { ptyManager } from '$lib/modules/server/terminal/pty-manager
|
|
2
|
+
import { ptyManager } from '$lib/modules/server/terminal/pty-manager';
|
|
3
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
3
4
|
import { json } from '@sveltejs/kit';
|
|
4
5
|
import { realpathSync, statSync } from 'fs';
|
|
5
|
-
import { basename } from 'path';
|
|
6
|
+
import { basename, isAbsolute, relative } from 'path';
|
|
6
7
|
|
|
7
8
|
import type { RequestHandler } from './$types';
|
|
8
9
|
|
|
@@ -11,10 +12,12 @@ const ALLOWED_COMMANDS = ['zsh', 'bash', 'sh', 'fish', 'claude', 'opencode'];
|
|
|
11
12
|
// GET /api/terminals — List all terminals (active + recently exited)
|
|
12
13
|
export const GET: RequestHandler = ({ request }) => {
|
|
13
14
|
const authError = validateAuth(request);
|
|
14
|
-
if (authError) {
|
|
15
|
+
if (authError) {
|
|
16
|
+
return authError;
|
|
17
|
+
}
|
|
15
18
|
|
|
16
19
|
try {
|
|
17
|
-
const terminals = ptyManager.list().map(t => ({
|
|
20
|
+
const terminals = ptyManager.list().map((t) => ({
|
|
18
21
|
args: t.args,
|
|
19
22
|
clientCount: t.clients.size,
|
|
20
23
|
command: t.command,
|
|
@@ -35,15 +38,17 @@ export const GET: RequestHandler = ({ request }) => {
|
|
|
35
38
|
timestamp: new Date().toISOString(),
|
|
36
39
|
});
|
|
37
40
|
} catch (error) {
|
|
38
|
-
|
|
39
|
-
return json({
|
|
41
|
+
console.error('[terminals] Failed to list terminals:', toErrorMessage(error));
|
|
42
|
+
return json({ error: 'Failed to list terminals' }, { status: 500 });
|
|
40
43
|
}
|
|
41
44
|
};
|
|
42
45
|
|
|
43
46
|
// POST /api/terminals — Create a new terminal session
|
|
44
47
|
export const POST: RequestHandler = async ({ request }) => {
|
|
45
48
|
const authError = validateAuth(request);
|
|
46
|
-
if (authError) {
|
|
49
|
+
if (authError) {
|
|
50
|
+
return authError;
|
|
51
|
+
}
|
|
47
52
|
|
|
48
53
|
let body: { args?: string[]; cols?: number; command?: string; cwd?: string; rows?: number };
|
|
49
54
|
try {
|
|
@@ -70,7 +75,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
70
75
|
if (!ALLOWED_COMMANDS.includes(commandBasename)) {
|
|
71
76
|
return json(
|
|
72
77
|
{ error: `Command not allowed. Allowed: ${ALLOWED_COMMANDS.join(', ')}` },
|
|
73
|
-
{ status: 400 }
|
|
78
|
+
{ status: 400 }
|
|
74
79
|
);
|
|
75
80
|
}
|
|
76
81
|
|
|
@@ -82,15 +87,18 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
82
87
|
let realCwd: string;
|
|
83
88
|
try {
|
|
84
89
|
realCwd = realpathSync(cwd);
|
|
90
|
+
if (!statSync(realCwd).isDirectory()) {
|
|
91
|
+
return json({ error: 'cwd must be a directory' }, { status: 400 });
|
|
92
|
+
}
|
|
85
93
|
} catch {
|
|
86
|
-
return json({ error: '
|
|
87
|
-
}
|
|
88
|
-
if (!statSync(realCwd).isDirectory()) {
|
|
89
|
-
return json({ error: 'Invalid working directory' }, { status: 400 });
|
|
94
|
+
return json({ error: 'cwd must be a directory' }, { status: 400 });
|
|
90
95
|
}
|
|
91
96
|
const home = process.env.HOME || '';
|
|
92
|
-
if (home
|
|
93
|
-
|
|
97
|
+
if (home) {
|
|
98
|
+
const rel = relative(home, realCwd);
|
|
99
|
+
if (rel.startsWith('..') || isAbsolute(rel)) {
|
|
100
|
+
return json({ error: 'Working directory must be under home directory' }, { status: 400 });
|
|
101
|
+
}
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
if (args !== undefined && !Array.isArray(args)) {
|
|
@@ -110,13 +118,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
110
118
|
return json({ error: 'rows must be a positive number' }, { status: 400 });
|
|
111
119
|
}
|
|
112
120
|
|
|
113
|
-
const terminal = await ptyManager.create(
|
|
114
|
-
command,
|
|
115
|
-
args ?? [],
|
|
116
|
-
realCwd,
|
|
117
|
-
cols ?? 80,
|
|
118
|
-
rows ?? 24,
|
|
119
|
-
);
|
|
121
|
+
const terminal = await ptyManager.create(command, args ?? [], realCwd, cols ?? 80, rows ?? 24);
|
|
120
122
|
|
|
121
123
|
console.log(
|
|
122
124
|
`[terminals] Created terminal ${terminal.id} (pid=${terminal.pid}, command=${command})`
|
|
@@ -125,7 +127,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
125
127
|
return json(
|
|
126
128
|
{
|
|
127
129
|
command: terminal.command,
|
|
128
|
-
createdAt: terminal.createdAt,
|
|
130
|
+
createdAt: terminal.createdAt instanceof Date ? terminal.createdAt.toISOString() : terminal.createdAt,
|
|
129
131
|
cwd: terminal.cwd,
|
|
130
132
|
id: terminal.id,
|
|
131
133
|
pid: terminal.pid,
|
|
@@ -135,7 +137,7 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
135
137
|
{ status: 201 }
|
|
136
138
|
);
|
|
137
139
|
} catch (error) {
|
|
138
|
-
|
|
139
|
-
return json({
|
|
140
|
+
console.error('[terminals] Failed to create terminal:', toErrorMessage(error));
|
|
141
|
+
return json({ error: 'Failed to create terminal' }, { status: 500 });
|
|
140
142
|
}
|
|
141
143
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
2
|
import { ptyManager } from '$lib/modules/server/terminal/pty-manager.js';
|
|
3
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
3
4
|
import { json } from '@sveltejs/kit';
|
|
4
5
|
|
|
5
6
|
import type { RequestHandler } from './$types';
|
|
@@ -7,7 +8,9 @@ import type { RequestHandler } from './$types';
|
|
|
7
8
|
// GET /api/terminals/:id — Get terminal details by ID
|
|
8
9
|
export const GET: RequestHandler = ({ params, request }) => {
|
|
9
10
|
const authError = validateAuth(request);
|
|
10
|
-
if (authError) {
|
|
11
|
+
if (authError) {
|
|
12
|
+
return authError;
|
|
13
|
+
}
|
|
11
14
|
|
|
12
15
|
try {
|
|
13
16
|
const terminal = ptyManager.get(params.id);
|
|
@@ -25,7 +28,8 @@ export const GET: RequestHandler = ({ params, request }) => {
|
|
|
25
28
|
exitCode: terminal.exitCode,
|
|
26
29
|
exitedAt: terminal.exitedAt?.toISOString() ?? null,
|
|
27
30
|
id: terminal.id,
|
|
28
|
-
lastOutput:
|
|
31
|
+
lastOutput:
|
|
32
|
+
terminal.scrollback.length > 0 ? terminal.scrollback[terminal.scrollback.length - 1] : null,
|
|
29
33
|
pid: terminal.pid,
|
|
30
34
|
sessionWs: `/ws/session/${terminal.id}`,
|
|
31
35
|
status: terminal.status,
|
|
@@ -33,15 +37,17 @@ export const GET: RequestHandler = ({ params, request }) => {
|
|
|
33
37
|
ws: `/ws/terminal/${terminal.id}`,
|
|
34
38
|
});
|
|
35
39
|
} catch (error) {
|
|
36
|
-
|
|
37
|
-
return json({
|
|
40
|
+
console.error('[terminals] Failed to get terminal:', toErrorMessage(error));
|
|
41
|
+
return json({ error: 'Failed to get terminal' }, { status: 500 });
|
|
38
42
|
}
|
|
39
43
|
};
|
|
40
44
|
|
|
41
45
|
// DELETE /api/terminals/:id — Kill terminal by ID (SIGTERM)
|
|
42
46
|
export const DELETE: RequestHandler = ({ params, request }) => {
|
|
43
47
|
const authError = validateAuth(request);
|
|
44
|
-
if (authError) {
|
|
48
|
+
if (authError) {
|
|
49
|
+
return authError;
|
|
50
|
+
}
|
|
45
51
|
|
|
46
52
|
try {
|
|
47
53
|
const terminal = ptyManager.get(params.id);
|
|
@@ -69,7 +75,7 @@ export const DELETE: RequestHandler = ({ params, request }) => {
|
|
|
69
75
|
timestamp: new Date().toISOString(),
|
|
70
76
|
});
|
|
71
77
|
} catch (error) {
|
|
72
|
-
|
|
73
|
-
return json({
|
|
78
|
+
console.error('[terminals] Failed to kill terminal:', toErrorMessage(error));
|
|
79
|
+
return json({ error: 'Failed to kill terminal' }, { status: 500 });
|
|
74
80
|
}
|
|
75
81
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
2
3
|
import { json } from '@sveltejs/kit';
|
|
3
4
|
import { mkdirSync, writeFileSync } from 'fs';
|
|
4
5
|
|
|
@@ -6,56 +7,57 @@ import type { RequestHandler } from './$types';
|
|
|
6
7
|
|
|
7
8
|
// POST /api/terminals/[id]/paste-image — Write clipboard image for a terminal
|
|
8
9
|
export const POST: RequestHandler = async ({ params, request }) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
10
|
+
const authError = validateAuth(request);
|
|
11
|
+
if (authError) {
|
|
12
|
+
return authError;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const terminalId = params.id;
|
|
16
|
+
|
|
17
|
+
// Validate terminalId to prevent path traversal
|
|
18
|
+
if (!/^[A-Za-z0-9_-]+$/.test(terminalId)) {
|
|
19
|
+
return json({ error: 'Invalid terminal ID' }, { status: 400 });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let body: { image: string };
|
|
23
|
+
try {
|
|
24
|
+
body = (await request.json()) as { image: string };
|
|
25
|
+
} catch {
|
|
26
|
+
return json({ error: 'Invalid JSON' }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!body.image || typeof body.image !== 'string') {
|
|
30
|
+
return json({ error: 'image (base64) is required' }, { status: 400 });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Decode base64 image
|
|
34
|
+
let imageBuffer: Buffer;
|
|
35
|
+
try {
|
|
36
|
+
// Strip data URI prefix if present
|
|
37
|
+
const base64Data = body.image.replace(/^data:image\/\w+;base64,/, '');
|
|
38
|
+
|
|
39
|
+
// Validate base64 encoding via round-trip check
|
|
40
|
+
// Buffer.from silently ignores invalid chars, so verify re-encoding matches
|
|
41
|
+
const decoded = Buffer.from(base64Data, 'base64');
|
|
42
|
+
if (decoded.length === 0 || decoded.toString('base64') !== base64Data) {
|
|
43
|
+
return json({ error: 'Invalid base64 image data' }, { status: 400 });
|
|
44
|
+
}
|
|
45
|
+
imageBuffer = decoded;
|
|
46
|
+
} catch {
|
|
47
|
+
return json({ error: 'Invalid base64 image data' }, { status: 400 });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Write to per-terminal clipboard directory
|
|
51
|
+
const clipboardDir = `/tmp/shooter-clipboard-${terminalId}`;
|
|
52
|
+
const imagePath = `${clipboardDir}/image.png`;
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
mkdirSync(clipboardDir, { recursive: true });
|
|
56
|
+
writeFileSync(imagePath, imageBuffer);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error('[paste-image] Failed to write image:', toErrorMessage(err));
|
|
59
|
+
return json({ error: 'Failed to write image' }, { status: 500 });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return json({ size: imageBuffer.length, success: true });
|
|
61
63
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { validateAuth } from '$lib/modules/server/auth';
|
|
2
2
|
import { ptyManager } from '$lib/modules/server/terminal/pty-manager.js';
|
|
3
|
+
import { toErrorMessage } from '$lib/modules/server/utils/error';
|
|
3
4
|
import { json } from '@sveltejs/kit';
|
|
4
5
|
|
|
5
6
|
import type { RequestHandler } from './$types';
|
|
@@ -7,7 +8,9 @@ import type { RequestHandler } from './$types';
|
|
|
7
8
|
// POST /api/terminals/:id/resize — Resize terminal
|
|
8
9
|
export const POST: RequestHandler = async ({ params, request }) => {
|
|
9
10
|
const authError = validateAuth(request);
|
|
10
|
-
if (authError) {
|
|
11
|
+
if (authError) {
|
|
12
|
+
return authError;
|
|
13
|
+
}
|
|
11
14
|
|
|
12
15
|
let body: { cols?: number; rows?: number };
|
|
13
16
|
try {
|
|
@@ -54,7 +57,7 @@ export const POST: RequestHandler = async ({ params, request }) => {
|
|
|
54
57
|
timestamp: new Date().toISOString(),
|
|
55
58
|
});
|
|
56
59
|
} catch (error) {
|
|
57
|
-
|
|
58
|
-
return json({
|
|
60
|
+
console.error('[terminals] Failed to resize terminal:', toErrorMessage(error));
|
|
61
|
+
return json({ error: 'Failed to resize terminal' }, { status: 500 });
|
|
59
62
|
}
|
|
60
63
|
};
|