wind-agent-cli 1.37.2 → 1.37.3
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/LICENSE +718 -718
- package/README.md +1 -1
- package/dist/api-docs.html +901 -901
- package/dist/assets/{CodeEditor-B2Wf7Fg0.js → CodeEditor-BqmxpZ_D.js} +1 -1
- package/dist/assets/{FileTree-N2IkkHlv.js → FileTree-DLE7Ioai.js} +1 -1
- package/dist/assets/{GitPanel-DZCeuFZ2.js → GitPanel-f8RMRa8D.js} +1 -1
- package/dist/assets/{MarkdownPreview-C0tqYnVu.js → MarkdownPreview-93h_1tJa.js} +1 -1
- package/dist/assets/{PluginTabContent-Bnuf-fb8.js → PluginTabContent-DU1jjkXP.js} +1 -1
- package/dist/assets/{Shell-BfFnMZ-f.js → Shell-CN_2MRIM.js} +1 -1
- package/dist/assets/{StandaloneShell-QmyYwNAl.js → StandaloneShell-D0avS8UE.js} +1 -1
- package/dist/assets/{TaskMasterPanel-fMsmvN9L.js → TaskMasterPanel-Cpf1Q5Ph.js} +3 -3
- package/dist/assets/{abnfDiagram-N423BO3Z-DjPU7HLs.js → abnfDiagram-N423BO3Z-p3aJIm4T.js} +1 -1
- package/dist/assets/{arc-Pdq6Tvr3.js → arc-CTeud6Fl.js} +1 -1
- package/dist/assets/{architectureDiagram-T3A2C74G-D0JnT0Vh.js → architectureDiagram-T3A2C74G-CG7kRCJU.js} +1 -1
- package/dist/assets/{blockDiagram-VBNYF7ZC-DpaEf3mv.js → blockDiagram-VBNYF7ZC-oSjQ1SgE.js} +1 -1
- package/dist/assets/{c4Diagram-5PPSVZJV-MpqlPGFi.js → c4Diagram-5PPSVZJV-RkzF0DJV.js} +1 -1
- package/dist/assets/channel-BfQbarn9.js +1 -0
- package/dist/assets/{chunk-2GRJ4B5K-DoSdNo8u.js → chunk-2GRJ4B5K-B07uZ07O.js} +1 -1
- package/dist/assets/{chunk-2Q5K7J3B-CE7I3uMn.js → chunk-2Q5K7J3B-DNSfO7xS.js} +1 -1
- package/dist/assets/{chunk-5RXB4S5H-B4UQ8snD.js → chunk-5RXB4S5H-BTeYcgyb.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-B55XgqHZ.js → chunk-5VM5RSS4-B7vZV0zC.js} +1 -1
- package/dist/assets/{chunk-6Q2QTUOP-BS1KpefW.js → chunk-6Q2QTUOP-DuS_xUGG.js} +1 -1
- package/dist/assets/{chunk-GF5L2VYU-DkEPedJP.js → chunk-GF5L2VYU-CKLZ3iVD.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DOtkNhMm.js → chunk-JWPE2WC7-DD2hcXvs.js} +1 -1
- package/dist/assets/{chunk-KBJHAD2P-BXLjviqM.js → chunk-KBJHAD2P-Cz-l38qp.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-C50fjNNz.js → chunk-RYQCIY6F-DGFIU1YM.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-QBYqCkb7.js → chunk-XXDRQBXY-CmfzoYFl.js} +1 -1
- package/dist/assets/classDiagram-JCYQIIEL-Bpfe3kq7.js +1 -0
- package/dist/assets/classDiagram-v2-OCEON4UE-Bpfe3kq7.js +1 -0
- package/dist/assets/{code-xml-VK1YfShP.js → code-xml-CLpHzEOP.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-DrVTo1Nh.js → cose-bilkent-JH36ORCC-DlFcLXCB.js} +1 -1
- package/dist/assets/{cynefin-VYW2F7L2-DnJa_OlQ.js → cynefin-VYW2F7L2-P1HecReO.js} +1 -1
- package/dist/assets/{cynefinDiagram-MW4NZA55-CCxBjw9E.js → cynefinDiagram-MW4NZA55-COgduz5P.js} +1 -1
- package/dist/assets/{dagre-VZM6K2ZE-C_GvE4lu.js → dagre-VZM6K2ZE-Bbb-siGp.js} +1 -1
- package/dist/assets/{diagram-7IWD3JNH-pFzs9HEu.js → diagram-7IWD3JNH-9CWGFMYR.js} +1 -1
- package/dist/assets/{diagram-B4RE2ZJO-CcehQC7x.js → diagram-B4RE2ZJO-TWK59T6V.js} +1 -1
- package/dist/assets/{diagram-LBJQPF4R-hfKcrrxe.js → diagram-LBJQPF4R-ErMC9yaa.js} +1 -1
- package/dist/assets/{diagram-Q27KOJAE-C1semJfK.js → diagram-Q27KOJAE-Dt_-C7hV.js} +1 -1
- package/dist/assets/{diagram-UB23O5K3-57hvXQXO.js → diagram-UB23O5K3-BJ1DnRAF.js} +1 -1
- package/dist/assets/{ebnfDiagram-BXEA7PRR-9KIAlAVw.js → ebnfDiagram-BXEA7PRR-CE1YaQ9s.js} +1 -1
- package/dist/assets/{erDiagram-JOGREHBK-B7OzJ767.js → erDiagram-JOGREHBK-Bqk7N9aY.js} +1 -1
- package/dist/assets/{flowDiagram-UKHOOZJN-CJV8fQPR.js → flowDiagram-UKHOOZJN-DEr2II5V.js} +1 -1
- package/dist/assets/{ganttDiagram-PKOTCBZU-CbMNWWQu.js → ganttDiagram-PKOTCBZU-CWYAUeYN.js} +1 -1
- package/dist/assets/{gitGraphDiagram-DS77QQ5N-I_vZ5waO.js → gitGraphDiagram-DS77QQ5N-tdEcEIM6.js} +1 -1
- package/dist/assets/{index-ZHwIojzi.js → index-B-sTfSZq.js} +1 -1
- package/dist/assets/{index-GFhXZyl2.js → index-BSe3UiFA.js} +1 -1
- package/dist/assets/{index-DFnVoqpx.js → index-B_FDMWar.js} +5 -5
- package/dist/assets/{index-DlSeAkw_.js → index-CWJtg2pR.js} +1 -1
- package/dist/assets/{infoDiagram-6WML65LV-Dh20Tsbq.js → infoDiagram-6WML65LV-A3IqRUnO.js} +1 -1
- package/dist/assets/{ishikawaDiagram-WSZJBQD7-DH2Sm3ko.js → ishikawaDiagram-WSZJBQD7-B2uL6bkK.js} +1 -1
- package/dist/assets/{journeyDiagram-NVQOT4AX-BNFQqlVu.js → journeyDiagram-NVQOT4AX-D9JB-hRW.js} +1 -1
- package/dist/assets/{kanban-definition-27J2QSJJ-B3iL0ztJ.js → kanban-definition-27J2QSJJ-DmlgiV7K.js} +1 -1
- package/dist/assets/{linear-Cwe9dEKA.js → linear-Ct_eoJQk.js} +1 -1
- package/dist/assets/{mermaid.core-BYRQSshi.js → mermaid.core-CQ698HNn.js} +5 -5
- package/dist/assets/{mindmap-definition-FAOFIHXS-BgfBYMzr.js → mindmap-definition-FAOFIHXS-DGtMgQhf.js} +1 -1
- package/dist/assets/{pegDiagram-VL7TDLO6-CNYpECr8.js → pegDiagram-VL7TDLO6-CO6vP4n9.js} +1 -1
- package/dist/assets/{pieDiagram-7S7Q4E2Y-DeSrxc4I.js → pieDiagram-7S7Q4E2Y-DMkt_Zfr.js} +1 -1
- package/dist/assets/{quadrantDiagram-CIZ2JOQS-BXVVQsa6.js → quadrantDiagram-CIZ2JOQS-DgNxRz6t.js} +1 -1
- package/dist/assets/{railroadDiagram-AXF67PYL-JTroIW8F.js → railroadDiagram-AXF67PYL-DKz9UqA9.js} +1 -1
- package/dist/assets/{requirementDiagram-LRYGKXZP-C1Z_inLz.js → requirementDiagram-LRYGKXZP-L84XyGgV.js} +1 -1
- package/dist/assets/{sankeyDiagram-W5VNT64P-DCJgKFUk.js → sankeyDiagram-W5VNT64P-CQqWbJ3j.js} +1 -1
- package/dist/assets/{sequenceDiagram-SI44F4Z6-D8Wrx5Vc.js → sequenceDiagram-SI44F4Z6--tnzS2tb.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-CXqD68vD.js → sizeCapture-X5ZJPWSS-DujwEOtm.js} +1 -1
- package/dist/assets/{stateDiagram-OKZ733FA-CF0Ekqjo.js → stateDiagram-OKZ733FA-BK3TcZY2.js} +1 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-_medyomK.js +1 -0
- package/dist/assets/{swimlanes-SLNWSIFB-DVIax_k4.js → swimlanes-SLNWSIFB-naX-Uv1B.js} +2 -2
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-DstIv3TC.js +8 -0
- package/dist/assets/{timeline-definition-Z64GVDOM-DSqk3ApG.js → timeline-definition-Z64GVDOM-C-vP_ddU.js} +1 -1
- package/dist/assets/{vennDiagram-T6HMQDX7-DNbTqyG5.js → vennDiagram-T6HMQDX7-DN-I7o-7.js} +1 -1
- package/dist/assets/{wardleyDiagram-T6FBY63Y-BNCpsFZV.js → wardleyDiagram-T6FBY63Y-Db9dsaXv.js} +1 -1
- package/dist/assets/{xychartDiagram-ELKLHX3M-XsVZphHr.js → xychartDiagram-ELKLHX3M-DE6OxW_p.js} +1 -1
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/favicon.svg +8 -8
- package/dist/generate-icons.js +48 -48
- package/dist/icons/codex-white.svg +3 -3
- package/dist/icons/codex.svg +3 -3
- package/dist/icons/cursor-white.svg +11 -11
- package/dist/icons/icon-128x128.svg +11 -11
- package/dist/icons/icon-144x144.svg +11 -11
- package/dist/icons/icon-152x152.svg +11 -11
- package/dist/icons/icon-192x192.svg +11 -11
- package/dist/icons/icon-384x384.svg +11 -11
- package/dist/icons/icon-512x512.svg +11 -11
- package/dist/icons/icon-72x72.svg +11 -11
- package/dist/icons/icon-96x96.svg +11 -11
- package/dist/icons/icon-template.svg +11 -11
- package/dist/index.html +56 -56
- package/dist/logo.svg +17 -17
- package/dist/manifest.json +60 -60
- package/dist/sw.js +124 -124
- package/dist-server/server/modules/cli/cli.service.js +36 -36
- package/dist-server/server/modules/cli/sandbox.service.js +38 -38
- package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +74 -74
- package/dist-server/server/modules/commands/commands.routes.js +24 -24
- package/dist-server/server/modules/database/migrations.js +190 -190
- package/dist-server/server/modules/database/repositories/api-keys.js +3 -3
- package/dist-server/server/modules/database/repositories/github-tokens.js +2 -2
- package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js +28 -28
- package/dist-server/server/modules/database/repositories/notification-preferences.js +4 -4
- package/dist-server/server/modules/database/repositories/projects.db.js +61 -61
- package/dist-server/server/modules/database/repositories/provider-models.js +35 -35
- package/dist-server/server/modules/database/repositories/push-subscriptions.js +5 -5
- package/dist-server/server/modules/database/repositories/scan-state.db.js +5 -5
- package/dist-server/server/modules/database/repositories/sessions.db.js +92 -92
- package/dist-server/server/modules/database/schema.js +177 -177
- package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +6 -6
- package/dist-server/server/modules/git/git.routes.js +17 -17
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +12 -12
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +9 -9
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +17 -17
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +25 -25
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +27 -27
- package/dist-server/server/modules/providers/services/provider-token-usage.service.js +9 -9
- package/dist-server/server/modules/providers/tests/mcp.test.js +3 -3
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +96 -96
- package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +18 -18
- package/dist-server/server/modules/taskmaster/taskmaster.routes.js +419 -419
- package/electron/cloud.js +260 -260
- package/electron/desktopNotifications.js +378 -378
- package/electron/desktopWindow.js +766 -766
- package/electron/launcher/index.html +14 -14
- package/electron/launcher/launcher.css +801 -801
- package/electron/launcher/launcher.js +687 -687
- package/electron/localServer.js +549 -549
- package/electron/main.js +944 -944
- package/electron/preload.cjs +60 -60
- package/electron/scripts/generate-macos-icon.js +62 -62
- package/electron/serverInstaller.js +277 -277
- package/electron/tabs.js +87 -87
- package/electron/viewHost.js +331 -331
- package/package.json +250 -247
- package/public/api-docs.html +901 -901
- package/scripts/fix-node-pty.js +67 -67
- package/scripts/promote-dist-server.mjs +50 -50
- package/scripts/release/build-server-bundle.js +176 -176
- package/scripts/release/prepare-desktop-app.js +152 -152
- package/server/index.ts +399 -399
- package/server/load-env.ts +47 -47
- package/server/modules/agent/agent.module.ts +52 -52
- package/server/modules/agent/agent.routes.ts +1287 -1287
- package/server/modules/agent/index.ts +2 -2
- package/server/modules/agent/tests/agent.routes.test.ts +205 -205
- package/server/modules/assets/assets.routes.ts +150 -150
- package/server/modules/assets/index.ts +3 -3
- package/server/modules/assets/services/image-assets.service.ts +127 -127
- package/server/modules/assets/tests/image-assets.service.test.ts +74 -74
- package/server/modules/auth/auth.middleware.ts +163 -163
- package/server/modules/auth/auth.module.ts +38 -38
- package/server/modules/auth/auth.routes.ts +57 -57
- package/server/modules/auth/auth.service.ts +155 -155
- package/server/modules/auth/index.ts +9 -9
- package/server/modules/auth/tests/auth.service.test.ts +95 -95
- package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -120
- package/server/modules/browser-use/browser-use-mcp.ts +386 -386
- package/server/modules/browser-use/browser-use-runtime.ts +10 -10
- package/server/modules/browser-use/browser-use.routes.ts +96 -96
- package/server/modules/browser-use/browser-use.service.ts +836 -836
- package/server/modules/browser-use/index.ts +11 -11
- package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -10
- package/server/modules/cli/cli.module.ts +93 -93
- package/server/modules/cli/cli.service.ts +248 -248
- package/server/modules/cli/cli.ts +19 -19
- package/server/modules/cli/index.ts +2 -2
- package/server/modules/cli/sandbox.service.ts +398 -398
- package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +186 -186
- package/server/modules/cli/tests/cli.service.test.ts +86 -86
- package/server/modules/cli/tests/sandbox.service.test.ts +58 -58
- package/server/modules/commands/commands.module.ts +22 -22
- package/server/modules/commands/commands.routes.ts +586 -586
- package/server/modules/commands/index.ts +2 -2
- package/server/modules/commands/tests/commands.test.ts +109 -109
- package/server/modules/database/connection.ts +143 -143
- package/server/modules/database/index.ts +17 -17
- package/server/modules/database/init-db.ts +17 -17
- package/server/modules/database/migrations.ts +515 -515
- package/server/modules/database/repositories/api-keys.ts +119 -119
- package/server/modules/database/repositories/app-config.ts +53 -53
- package/server/modules/database/repositories/credentials.ts +106 -106
- package/server/modules/database/repositories/github-tokens.ts +100 -100
- package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -153
- package/server/modules/database/repositories/notification-preferences.ts +117 -117
- package/server/modules/database/repositories/projects.db.ts +196 -196
- package/server/modules/database/repositories/provider-models.ts +168 -168
- package/server/modules/database/repositories/push-subscriptions.ts +80 -80
- package/server/modules/database/repositories/scan-state.db.ts +42 -42
- package/server/modules/database/repositories/sessions.db.ts +524 -524
- package/server/modules/database/repositories/users.ts +140 -140
- package/server/modules/database/repositories/vapid-keys.ts +57 -57
- package/server/modules/database/schema.ts +210 -210
- package/server/modules/database/tests/projects.db.integration.test.ts +72 -72
- package/server/modules/database/tests/provider-models.db.integration.test.ts +125 -125
- package/server/modules/database/tests/sessions-provider-mapping.test.ts +109 -109
- package/server/modules/database/tests/sessions.db.integration.test.ts +116 -116
- package/server/modules/file-tree/file-tree.module.ts +116 -116
- package/server/modules/file-tree/file-tree.routes.ts +258 -258
- package/server/modules/file-tree/file-tree.service.ts +675 -675
- package/server/modules/file-tree/index.ts +2 -2
- package/server/modules/file-tree/tests/file-tree.routes.test.ts +157 -157
- package/server/modules/file-tree/tests/file-tree.service.test.ts +371 -371
- package/server/modules/git/git-branch.service.ts +43 -43
- package/server/modules/git/git-parsing.service.ts +66 -66
- package/server/modules/git/git.module.ts +22 -22
- package/server/modules/git/git.routes.ts +1596 -1596
- package/server/modules/git/index.ts +2 -2
- package/server/modules/git/tests/git-branch.service.test.ts +60 -60
- package/server/modules/git/tests/git-init.routes.test.ts +132 -132
- package/server/modules/git/tests/git.test.ts +106 -106
- package/server/modules/notifications/index.ts +24 -24
- package/server/modules/notifications/notifications.routes.ts +127 -127
- package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -124
- package/server/modules/notifications/services/notification-orchestrator.service.js +310 -310
- package/server/modules/notifications/tests/notification-orchestrator.integration.test.ts +55 -55
- package/server/modules/notifications/vapid-keys.service.ts +38 -38
- package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -109
- package/server/modules/plugins/index.ts +9 -9
- package/server/modules/plugins/plugin-process.service.ts +217 -217
- package/server/modules/plugins/plugin-registry.service.ts +459 -459
- package/server/modules/plugins/plugins.module.ts +33 -33
- package/server/modules/plugins/plugins.routes.ts +66 -66
- package/server/modules/plugins/plugins.service.ts +147 -147
- package/server/modules/plugins/tests/plugins.service.test.ts +32 -32
- package/server/modules/projects/index.ts +11 -11
- package/server/modules/projects/projects.routes.ts +273 -273
- package/server/modules/projects/services/project-clone.service.ts +323 -323
- package/server/modules/projects/services/project-delete.service.ts +90 -90
- package/server/modules/projects/services/project-management.service.ts +144 -144
- package/server/modules/projects/services/project-star.service.ts +78 -78
- package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -248
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +314 -314
- package/server/modules/projects/tests/project-clone.service.test.ts +183 -183
- package/server/modules/projects/tests/project-management.service.test.ts +117 -117
- package/server/modules/projects/tests/project-star.service.test.ts +123 -123
- package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -105
- package/server/modules/providers/README.md +380 -380
- package/server/modules/providers/index.ts +10 -10
- package/server/modules/providers/list/claude/claude-auth.provider.ts +160 -160
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
- package/server/modules/providers/list/claude/claude-models.provider.ts +294 -294
- package/server/modules/providers/list/claude/claude-runtime.provider.js +1068 -1068
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +203 -203
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +684 -684
- package/server/modules/providers/list/claude/claude-skills.provider.ts +265 -265
- package/server/modules/providers/list/claude/claude.provider.ts +30 -30
- package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -100
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
- package/server/modules/providers/list/codex/codex-models.provider.ts +123 -123
- package/server/modules/providers/list/codex/codex-runtime.provider.js +533 -533
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +203 -203
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +938 -938
- package/server/modules/providers/list/codex/codex-skills.provider.ts +73 -73
- package/server/modules/providers/list/codex/codex.provider.ts +28 -28
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
- package/server/modules/providers/list/cursor/cursor-models.provider.ts +119 -119
- package/server/modules/providers/list/cursor/cursor-runtime.provider.js +385 -385
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +159 -159
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +654 -654
- package/server/modules/providers/list/cursor/cursor-skills.provider.ts +39 -39
- package/server/modules/providers/list/cursor/cursor.provider.ts +30 -30
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +110 -110
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -228
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +203 -203
- package/server/modules/providers/list/opencode/opencode-runtime.provider.js +434 -434
- package/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +261 -261
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +179 -179
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +500 -500
- package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -78
- package/server/modules/providers/list/opencode/opencode.provider.ts +30 -30
- package/server/modules/providers/provider.registry.ts +36 -36
- package/server/modules/providers/provider.routes.ts +877 -877
- package/server/modules/providers/services/mcp.service.ts +109 -109
- package/server/modules/providers/services/provider-auth.service.ts +26 -26
- package/server/modules/providers/services/provider-capabilities.service.ts +97 -97
- package/server/modules/providers/services/provider-models.service.ts +401 -401
- package/server/modules/providers/services/provider-runtime.service.ts +108 -108
- package/server/modules/providers/services/provider-token-usage.service.ts +357 -357
- package/server/modules/providers/services/session-conversations-search.service.ts +1321 -1321
- package/server/modules/providers/services/session-synchronizer.service.ts +74 -74
- package/server/modules/providers/services/sessions-watcher.service.ts +247 -247
- package/server/modules/providers/services/sessions.service.ts +471 -471
- package/server/modules/providers/services/skills.service.ts +39 -39
- package/server/modules/providers/shared/base/abstract.provider.ts +32 -32
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
- package/server/modules/providers/shared/skills/skills.provider.ts +287 -287
- package/server/modules/providers/tests/claude-auth.test.ts +150 -150
- package/server/modules/providers/tests/claude-sessions.test.ts +61 -61
- package/server/modules/providers/tests/codex-sessions.test.ts +231 -231
- package/server/modules/providers/tests/mcp.test.ts +349 -349
- package/server/modules/providers/tests/opencode-models.test.ts +41 -41
- package/server/modules/providers/tests/opencode-sessions.test.ts +522 -522
- package/server/modules/providers/tests/provider-attachment-history.test.ts +247 -247
- package/server/modules/providers/tests/provider-models.service.test.ts +353 -353
- package/server/modules/providers/tests/provider-runtime.service.test.ts +138 -138
- package/server/modules/providers/tests/provider-token-usage.service.test.ts +186 -186
- package/server/modules/providers/tests/provider.routes.test.ts +244 -244
- package/server/modules/providers/tests/sessions-details.test.ts +73 -73
- package/server/modules/providers/tests/sessions.service.test.ts +127 -127
- package/server/modules/providers/tests/skills.test.ts +692 -692
- package/server/modules/settings/index.ts +2 -2
- package/server/modules/settings/settings.module.ts +50 -50
- package/server/modules/settings/settings.routes.ts +51 -51
- package/server/modules/settings/settings.service.ts +186 -186
- package/server/modules/settings/tests/settings.service.test.ts +54 -54
- package/server/modules/system/index.ts +2 -2
- package/server/modules/system/system.module.ts +62 -62
- package/server/modules/system/system.routes.ts +21 -21
- package/server/modules/system/system.service.ts +76 -76
- package/server/modules/system/tests/system.service.test.ts +118 -118
- package/server/modules/taskmaster/index.ts +2 -2
- package/server/modules/taskmaster/taskmaster.module.ts +24 -24
- package/server/modules/taskmaster/taskmaster.routes.ts +1482 -1482
- package/server/modules/taskmaster/taskmaster.service.ts +132 -132
- package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +144 -144
- package/server/modules/taskmaster/tests/taskmaster.service.test.ts +97 -97
- package/server/modules/user/index.ts +2 -2
- package/server/modules/user/tests/user.service.test.ts +61 -61
- package/server/modules/user/user.module.ts +58 -58
- package/server/modules/user/user.routes.ts +50 -50
- package/server/modules/user/user.service.ts +85 -85
- package/server/modules/voice/index.ts +2 -2
- package/server/modules/voice/tests/voice.service.test.ts +98 -98
- package/server/modules/voice/voice.module.ts +47 -47
- package/server/modules/voice/voice.routes.ts +113 -113
- package/server/modules/voice/voice.service.ts +192 -192
- package/server/modules/websocket/README.md +273 -273
- package/server/modules/websocket/index.ts +3 -3
- package/server/modules/websocket/services/chat-run-registry.service.ts +343 -343
- package/server/modules/websocket/services/chat-session-writer.service.ts +145 -145
- package/server/modules/websocket/services/chat-websocket.service.ts +425 -425
- package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -65
- package/server/modules/websocket/services/shell-websocket.service.ts +502 -502
- package/server/modules/websocket/services/websocket-auth.service.ts +59 -59
- package/server/modules/websocket/services/websocket-server.service.ts +124 -124
- package/server/modules/websocket/services/websocket-state.service.ts +16 -16
- package/server/modules/websocket/services/websocket-writer.service.ts +38 -38
- package/server/modules/websocket/tests/chat-attachment-filter.test.ts +59 -59
- package/server/modules/websocket/tests/chat-run-registry.test.ts +282 -282
- package/server/modules/websocket/tests/shell-websocket.service.test.ts +100 -100
- package/server/modules/websocket/tests/websocket-heartbeat.service.test.ts +78 -78
- package/server/modules/worktrees/index.ts +2 -2
- package/server/modules/worktrees/services/worktree-create-and-open.service.ts +53 -53
- package/server/modules/worktrees/services/worktree-create.service.ts +104 -104
- package/server/modules/worktrees/services/worktree-git.service.ts +207 -207
- package/server/modules/worktrees/services/worktree-list.service.ts +143 -143
- package/server/modules/worktrees/services/worktree-merge.service.ts +157 -157
- package/server/modules/worktrees/services/worktree-open.service.ts +85 -85
- package/server/modules/worktrees/services/worktree-remove.service.ts +88 -88
- package/server/modules/worktrees/tests/worktree-create-and-open.service.test.ts +68 -68
- package/server/modules/worktrees/tests/worktree-create.service.test.ts +142 -142
- package/server/modules/worktrees/tests/worktree-git.service.test.ts +84 -84
- package/server/modules/worktrees/tests/worktree-list.service.test.ts +45 -45
- package/server/modules/worktrees/tests/worktree-merge.service.test.ts +213 -213
- package/server/modules/worktrees/tests/worktree-open.service.test.ts +122 -122
- package/server/modules/worktrees/tests/worktree-remove.service.test.ts +227 -227
- package/server/modules/worktrees/tests/worktrees.routes.test.ts +199 -199
- package/server/modules/worktrees/worktrees.module.ts +113 -113
- package/server/modules/worktrees/worktrees.routes.ts +116 -116
- package/server/shared/claude-cli-path.ts +139 -139
- package/server/shared/frontmatter.ts +18 -18
- package/server/shared/image-attachments.ts +435 -435
- package/server/shared/interfaces.ts +179 -179
- package/server/shared/tests/claude-cli-path.test.ts +61 -61
- package/server/shared/tests/image-attachments.test.ts +353 -353
- package/server/shared/tests/slice-tail-page.test.ts +42 -42
- package/server/shared/types.ts +1226 -1226
- package/server/shared/utils.ts +1161 -1161
- package/server/tsconfig.json +40 -40
- package/shared/networkHosts.js +22 -22
- package/dist/assets/channel-Bm0ZLE4z.js +0 -1
- package/dist/assets/classDiagram-JCYQIIEL-DqEOcNxw.js +0 -1
- package/dist/assets/classDiagram-v2-OCEON4UE-DqEOcNxw.js +0 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-DARLpEFJ.js +0 -1
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-CrgDgaY8.js +0 -8
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import type { VerifyClientCallbackSync } from 'ws';
|
|
2
|
-
|
|
3
|
-
import type { AuthenticatedWebSocketRequest } from '@/shared/types.js';
|
|
4
|
-
|
|
5
|
-
type WebSocketAuthDependencies = {
|
|
6
|
-
isPlatform: boolean;
|
|
7
|
-
authenticateWebSocket: (token: string | null) => {
|
|
8
|
-
id?: string | number;
|
|
9
|
-
userId?: string | number;
|
|
10
|
-
username?: string;
|
|
11
|
-
[key: string]: unknown;
|
|
12
|
-
} | null;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Authenticates websocket upgrade requests before the `connection` handler runs.
|
|
17
|
-
*/
|
|
18
|
-
export function verifyWebSocketClient(
|
|
19
|
-
info: Parameters<VerifyClientCallbackSync<AuthenticatedWebSocketRequest>>[0],
|
|
20
|
-
dependencies: WebSocketAuthDependencies
|
|
21
|
-
): boolean {
|
|
22
|
-
const request = info.req as AuthenticatedWebSocketRequest;
|
|
23
|
-
const upgradeUrl = new URL(request.url ?? '/', 'http://localhost');
|
|
24
|
-
const loggedUrl = new URL(upgradeUrl);
|
|
25
|
-
if (loggedUrl.searchParams.has('token')) {
|
|
26
|
-
loggedUrl.searchParams.set('token', 'REDACTED');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
console.log('WebSocket connection attempt to:', `${loggedUrl.pathname}${loggedUrl.search}`);
|
|
30
|
-
|
|
31
|
-
// Platform mode: use the first DB user and skip token checks.
|
|
32
|
-
if (dependencies.isPlatform) {
|
|
33
|
-
const user = dependencies.authenticateWebSocket(null);
|
|
34
|
-
if (!user) {
|
|
35
|
-
console.log('[WARN] Platform mode: No user found in database');
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
request.user = user;
|
|
40
|
-
console.log('[OK] Platform mode WebSocket authenticated for user:', user.username);
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// OSS mode: read JWT from query string first, then Authorization header.
|
|
45
|
-
const token =
|
|
46
|
-
upgradeUrl.searchParams.get('token') ??
|
|
47
|
-
request.headers.authorization?.split(' ')[1] ??
|
|
48
|
-
null;
|
|
49
|
-
|
|
50
|
-
const user = dependencies.authenticateWebSocket(token);
|
|
51
|
-
if (!user) {
|
|
52
|
-
console.log('[WARN] WebSocket authentication failed');
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
request.user = user;
|
|
57
|
-
console.log('[OK] WebSocket authenticated for user:', user.username);
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
1
|
+
import type { VerifyClientCallbackSync } from 'ws';
|
|
2
|
+
|
|
3
|
+
import type { AuthenticatedWebSocketRequest } from '@/shared/types.js';
|
|
4
|
+
|
|
5
|
+
type WebSocketAuthDependencies = {
|
|
6
|
+
isPlatform: boolean;
|
|
7
|
+
authenticateWebSocket: (token: string | null) => {
|
|
8
|
+
id?: string | number;
|
|
9
|
+
userId?: string | number;
|
|
10
|
+
username?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
} | null;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Authenticates websocket upgrade requests before the `connection` handler runs.
|
|
17
|
+
*/
|
|
18
|
+
export function verifyWebSocketClient(
|
|
19
|
+
info: Parameters<VerifyClientCallbackSync<AuthenticatedWebSocketRequest>>[0],
|
|
20
|
+
dependencies: WebSocketAuthDependencies
|
|
21
|
+
): boolean {
|
|
22
|
+
const request = info.req as AuthenticatedWebSocketRequest;
|
|
23
|
+
const upgradeUrl = new URL(request.url ?? '/', 'http://localhost');
|
|
24
|
+
const loggedUrl = new URL(upgradeUrl);
|
|
25
|
+
if (loggedUrl.searchParams.has('token')) {
|
|
26
|
+
loggedUrl.searchParams.set('token', 'REDACTED');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log('WebSocket connection attempt to:', `${loggedUrl.pathname}${loggedUrl.search}`);
|
|
30
|
+
|
|
31
|
+
// Platform mode: use the first DB user and skip token checks.
|
|
32
|
+
if (dependencies.isPlatform) {
|
|
33
|
+
const user = dependencies.authenticateWebSocket(null);
|
|
34
|
+
if (!user) {
|
|
35
|
+
console.log('[WARN] Platform mode: No user found in database');
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
request.user = user;
|
|
40
|
+
console.log('[OK] Platform mode WebSocket authenticated for user:', user.username);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// OSS mode: read JWT from query string first, then Authorization header.
|
|
45
|
+
const token =
|
|
46
|
+
upgradeUrl.searchParams.get('token') ??
|
|
47
|
+
request.headers.authorization?.split(' ')[1] ??
|
|
48
|
+
null;
|
|
49
|
+
|
|
50
|
+
const user = dependencies.authenticateWebSocket(token);
|
|
51
|
+
if (!user) {
|
|
52
|
+
console.log('[WARN] WebSocket authentication failed');
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
request.user = user;
|
|
57
|
+
console.log('[OK] WebSocket authenticated for user:', user.username);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
import type { Server as HttpServer } from 'node:http';
|
|
2
|
-
|
|
3
|
-
import { WebSocket, WebSocketServer, type VerifyClientCallbackSync } from 'ws';
|
|
4
|
-
|
|
5
|
-
import { handleChatConnection } from '@/modules/websocket/services/chat-websocket.service.js';
|
|
6
|
-
import { verifyWebSocketClient } from '@/modules/websocket/services/websocket-auth.service.js';
|
|
7
|
-
import { handlePluginWsProxy } from '@/modules/websocket/services/plugin-websocket-proxy.service.js';
|
|
8
|
-
import { handleShellConnection } from '@/modules/websocket/services/shell-websocket.service.js';
|
|
9
|
-
import { handleDesktopNotificationsConnection } from '@/modules/notifications/index.js';
|
|
10
|
-
import type { AuthenticatedWebSocketRequest } from '@/shared/types.js';
|
|
11
|
-
|
|
12
|
-
type WebSocketServerDependencies = {
|
|
13
|
-
verifyClient: Parameters<typeof verifyWebSocketClient>[1];
|
|
14
|
-
chat: Parameters<typeof handleChatConnection>[2];
|
|
15
|
-
shell: Parameters<typeof handleShellConnection>[1];
|
|
16
|
-
getPluginPort: Parameters<typeof handlePluginWsProxy>[2];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Used by this module's websocket gateway to keep active transports alive and
|
|
21
|
-
* close half-open connections so their route-specific clients can reconnect.
|
|
22
|
-
*/
|
|
23
|
-
export function attachWebSocketHeartbeat(
|
|
24
|
-
ws: WebSocket,
|
|
25
|
-
intervalMs = 30_000,
|
|
26
|
-
scheduler = {
|
|
27
|
-
setInterval,
|
|
28
|
-
clearInterval,
|
|
29
|
-
},
|
|
30
|
-
): () => void {
|
|
31
|
-
let isAlive = true;
|
|
32
|
-
let stopped = false;
|
|
33
|
-
|
|
34
|
-
const markAlive = () => {
|
|
35
|
-
isAlive = true;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const stopHeartbeat = () => {
|
|
39
|
-
if (stopped) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
stopped = true;
|
|
44
|
-
scheduler.clearInterval(heartbeat);
|
|
45
|
-
ws.off('pong', markAlive);
|
|
46
|
-
ws.off('close', stopHeartbeat);
|
|
47
|
-
ws.off('error', stopHeartbeat);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
ws.on('pong', markAlive);
|
|
51
|
-
ws.on('close', stopHeartbeat);
|
|
52
|
-
ws.on('error', stopHeartbeat);
|
|
53
|
-
|
|
54
|
-
const heartbeat = scheduler.setInterval(() => {
|
|
55
|
-
if (ws.readyState !== WebSocket.OPEN) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// A socket that did not answer the previous ping is half-open from the
|
|
60
|
-
// server's perspective. Terminating it emits close and lets clients resume.
|
|
61
|
-
if (!isAlive) {
|
|
62
|
-
stopHeartbeat();
|
|
63
|
-
ws.terminate();
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
isAlive = false;
|
|
68
|
-
try {
|
|
69
|
-
ws.ping();
|
|
70
|
-
} catch {
|
|
71
|
-
stopHeartbeat();
|
|
72
|
-
ws.terminate();
|
|
73
|
-
}
|
|
74
|
-
}, intervalMs);
|
|
75
|
-
|
|
76
|
-
return stopHeartbeat;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Creates and wires the server-wide websocket gateway used for chat, shell, and
|
|
81
|
-
* plugin proxy routes. Exported through the websocket module for server startup.
|
|
82
|
-
*/
|
|
83
|
-
export function createWebSocketServer(
|
|
84
|
-
server: HttpServer,
|
|
85
|
-
dependencies: WebSocketServerDependencies
|
|
86
|
-
): WebSocketServer {
|
|
1
|
+
import type { Server as HttpServer } from 'node:http';
|
|
2
|
+
|
|
3
|
+
import { WebSocket, WebSocketServer, type VerifyClientCallbackSync } from 'ws';
|
|
4
|
+
|
|
5
|
+
import { handleChatConnection } from '@/modules/websocket/services/chat-websocket.service.js';
|
|
6
|
+
import { verifyWebSocketClient } from '@/modules/websocket/services/websocket-auth.service.js';
|
|
7
|
+
import { handlePluginWsProxy } from '@/modules/websocket/services/plugin-websocket-proxy.service.js';
|
|
8
|
+
import { handleShellConnection } from '@/modules/websocket/services/shell-websocket.service.js';
|
|
9
|
+
import { handleDesktopNotificationsConnection } from '@/modules/notifications/index.js';
|
|
10
|
+
import type { AuthenticatedWebSocketRequest } from '@/shared/types.js';
|
|
11
|
+
|
|
12
|
+
type WebSocketServerDependencies = {
|
|
13
|
+
verifyClient: Parameters<typeof verifyWebSocketClient>[1];
|
|
14
|
+
chat: Parameters<typeof handleChatConnection>[2];
|
|
15
|
+
shell: Parameters<typeof handleShellConnection>[1];
|
|
16
|
+
getPluginPort: Parameters<typeof handlePluginWsProxy>[2];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Used by this module's websocket gateway to keep active transports alive and
|
|
21
|
+
* close half-open connections so their route-specific clients can reconnect.
|
|
22
|
+
*/
|
|
23
|
+
export function attachWebSocketHeartbeat(
|
|
24
|
+
ws: WebSocket,
|
|
25
|
+
intervalMs = 30_000,
|
|
26
|
+
scheduler = {
|
|
27
|
+
setInterval,
|
|
28
|
+
clearInterval,
|
|
29
|
+
},
|
|
30
|
+
): () => void {
|
|
31
|
+
let isAlive = true;
|
|
32
|
+
let stopped = false;
|
|
33
|
+
|
|
34
|
+
const markAlive = () => {
|
|
35
|
+
isAlive = true;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const stopHeartbeat = () => {
|
|
39
|
+
if (stopped) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
stopped = true;
|
|
44
|
+
scheduler.clearInterval(heartbeat);
|
|
45
|
+
ws.off('pong', markAlive);
|
|
46
|
+
ws.off('close', stopHeartbeat);
|
|
47
|
+
ws.off('error', stopHeartbeat);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
ws.on('pong', markAlive);
|
|
51
|
+
ws.on('close', stopHeartbeat);
|
|
52
|
+
ws.on('error', stopHeartbeat);
|
|
53
|
+
|
|
54
|
+
const heartbeat = scheduler.setInterval(() => {
|
|
55
|
+
if (ws.readyState !== WebSocket.OPEN) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// A socket that did not answer the previous ping is half-open from the
|
|
60
|
+
// server's perspective. Terminating it emits close and lets clients resume.
|
|
61
|
+
if (!isAlive) {
|
|
62
|
+
stopHeartbeat();
|
|
63
|
+
ws.terminate();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
isAlive = false;
|
|
68
|
+
try {
|
|
69
|
+
ws.ping();
|
|
70
|
+
} catch {
|
|
71
|
+
stopHeartbeat();
|
|
72
|
+
ws.terminate();
|
|
73
|
+
}
|
|
74
|
+
}, intervalMs);
|
|
75
|
+
|
|
76
|
+
return stopHeartbeat;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Creates and wires the server-wide websocket gateway used for chat, shell, and
|
|
81
|
+
* plugin proxy routes. Exported through the websocket module for server startup.
|
|
82
|
+
*/
|
|
83
|
+
export function createWebSocketServer(
|
|
84
|
+
server: HttpServer,
|
|
85
|
+
dependencies: WebSocketServerDependencies
|
|
86
|
+
): WebSocketServer {
|
|
87
87
|
const wss = new WebSocketServer({
|
|
88
88
|
server,
|
|
89
89
|
perMessageDeflate: false,
|
|
90
|
-
verifyClient: ((
|
|
91
|
-
info: Parameters<VerifyClientCallbackSync<AuthenticatedWebSocketRequest>>[0]
|
|
92
|
-
) => verifyWebSocketClient(info, dependencies.verifyClient)),
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
wss.on('connection', (ws, request) => {
|
|
96
|
-
attachWebSocketHeartbeat(ws);
|
|
97
|
-
|
|
98
|
-
const incomingRequest = request as AuthenticatedWebSocketRequest;
|
|
99
|
-
const url = incomingRequest.url ?? '/';
|
|
100
|
-
const pathname = new URL(url, 'http://localhost').pathname;
|
|
101
|
-
|
|
102
|
-
if (pathname === '/shell') {
|
|
103
|
-
handleShellConnection(ws, dependencies.shell);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (pathname === '/ws') {
|
|
108
|
-
handleChatConnection(ws, incomingRequest, dependencies.chat);
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (pathname === '/desktop-notifications') {
|
|
113
|
-
handleDesktopNotificationsConnection(ws, incomingRequest);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (pathname.startsWith('/plugin-ws/')) {
|
|
118
|
-
handlePluginWsProxy(ws, pathname, dependencies.getPluginPort);
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
console.log('[WARN] Unknown WebSocket path:', pathname);
|
|
123
|
-
ws.close();
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return wss;
|
|
127
|
-
}
|
|
90
|
+
verifyClient: ((
|
|
91
|
+
info: Parameters<VerifyClientCallbackSync<AuthenticatedWebSocketRequest>>[0]
|
|
92
|
+
) => verifyWebSocketClient(info, dependencies.verifyClient)),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
wss.on('connection', (ws, request) => {
|
|
96
|
+
attachWebSocketHeartbeat(ws);
|
|
97
|
+
|
|
98
|
+
const incomingRequest = request as AuthenticatedWebSocketRequest;
|
|
99
|
+
const url = incomingRequest.url ?? '/';
|
|
100
|
+
const pathname = new URL(url, 'http://localhost').pathname;
|
|
101
|
+
|
|
102
|
+
if (pathname === '/shell') {
|
|
103
|
+
handleShellConnection(ws, dependencies.shell);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (pathname === '/ws') {
|
|
108
|
+
handleChatConnection(ws, incomingRequest, dependencies.chat);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (pathname === '/desktop-notifications') {
|
|
113
|
+
handleDesktopNotificationsConnection(ws, incomingRequest);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (pathname.startsWith('/plugin-ws/')) {
|
|
118
|
+
handlePluginWsProxy(ws, pathname, dependencies.getPluginPort);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log('[WARN] Unknown WebSocket path:', pathname);
|
|
123
|
+
ws.close();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return wss;
|
|
127
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type { RealtimeClientConnection } from '@/shared/types.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Numeric readyState for an open WebSocket connection.
|
|
5
|
-
*
|
|
6
|
-
* We keep this in module state so services that broadcast updates do not need
|
|
7
|
-
* to import `ws` directly just to compare open/closed state.
|
|
8
|
-
*/
|
|
9
|
-
export const WS_OPEN_STATE = 1;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Shared registry of active chat WebSocket connections.
|
|
13
|
-
*
|
|
14
|
-
* Project/session services publish realtime updates by iterating this set.
|
|
15
|
-
*/
|
|
16
|
-
export const connectedClients = new Set<RealtimeClientConnection>();
|
|
1
|
+
import type { RealtimeClientConnection } from '@/shared/types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Numeric readyState for an open WebSocket connection.
|
|
5
|
+
*
|
|
6
|
+
* We keep this in module state so services that broadcast updates do not need
|
|
7
|
+
* to import `ws` directly just to compare open/closed state.
|
|
8
|
+
*/
|
|
9
|
+
export const WS_OPEN_STATE = 1;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Shared registry of active chat WebSocket connections.
|
|
13
|
+
*
|
|
14
|
+
* Project/session services publish realtime updates by iterating this set.
|
|
15
|
+
*/
|
|
16
|
+
export const connectedClients = new Set<RealtimeClientConnection>();
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import { WS_OPEN_STATE } from '@/modules/websocket/services/websocket-state.service.js';
|
|
2
|
-
import type { RealtimeClientConnection } from '@/shared/types.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Thin transport adapter that gives WebSocket connections the same interface as
|
|
6
|
-
* SSE writers used by API routes (`send`, `setSessionId`, `getSessionId`).
|
|
7
|
-
*/
|
|
8
|
-
export class WebSocketWriter {
|
|
9
|
-
ws: RealtimeClientConnection;
|
|
10
|
-
sessionId: string | null;
|
|
11
|
-
userId: string | number | null;
|
|
12
|
-
isWebSocketWriter: boolean;
|
|
13
|
-
|
|
14
|
-
constructor(ws: RealtimeClientConnection, userId: string | number | null = null) {
|
|
15
|
-
this.ws = ws;
|
|
16
|
-
this.sessionId = null;
|
|
17
|
-
this.userId = userId;
|
|
18
|
-
this.isWebSocketWriter = true;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
send(data: unknown): void {
|
|
22
|
-
if (this.ws.readyState === WS_OPEN_STATE) {
|
|
23
|
-
this.ws.send(JSON.stringify(data));
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
updateWebSocket(newRawWs: RealtimeClientConnection): void {
|
|
28
|
-
this.ws = newRawWs;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
setSessionId(sessionId: string): void {
|
|
32
|
-
this.sessionId = sessionId;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
getSessionId(): string | null {
|
|
36
|
-
return this.sessionId;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
1
|
+
import { WS_OPEN_STATE } from '@/modules/websocket/services/websocket-state.service.js';
|
|
2
|
+
import type { RealtimeClientConnection } from '@/shared/types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Thin transport adapter that gives WebSocket connections the same interface as
|
|
6
|
+
* SSE writers used by API routes (`send`, `setSessionId`, `getSessionId`).
|
|
7
|
+
*/
|
|
8
|
+
export class WebSocketWriter {
|
|
9
|
+
ws: RealtimeClientConnection;
|
|
10
|
+
sessionId: string | null;
|
|
11
|
+
userId: string | number | null;
|
|
12
|
+
isWebSocketWriter: boolean;
|
|
13
|
+
|
|
14
|
+
constructor(ws: RealtimeClientConnection, userId: string | number | null = null) {
|
|
15
|
+
this.ws = ws;
|
|
16
|
+
this.sessionId = null;
|
|
17
|
+
this.userId = userId;
|
|
18
|
+
this.isWebSocketWriter = true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
send(data: unknown): void {
|
|
22
|
+
if (this.ws.readyState === WS_OPEN_STATE) {
|
|
23
|
+
this.ws.send(JSON.stringify(data));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
updateWebSocket(newRawWs: RealtimeClientConnection): void {
|
|
28
|
+
this.ws = newRawWs;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setSessionId(sessionId: string): void {
|
|
32
|
+
this.sessionId = sessionId;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getSessionId(): string | null {
|
|
36
|
+
return this.sessionId;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import os from 'node:os';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import test from 'node:test';
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
filterAttachmentsToUploadStore,
|
|
8
|
-
filterImagesToUploadStore,
|
|
9
|
-
} from '@/modules/websocket/services/chat-websocket.service.js';
|
|
10
|
-
|
|
11
|
-
const STORE = path.join(os.tmpdir(), 'cloudcli-assets-store');
|
|
12
|
-
|
|
13
|
-
test('images inside the upload store pass through', () => {
|
|
14
|
-
const inside = path.join(STORE, 'shot.png');
|
|
15
|
-
const result = filterImagesToUploadStore(
|
|
16
|
-
[{ path: inside, name: 'shot.png', mimeType: 'image/png' }],
|
|
17
|
-
STORE,
|
|
18
|
-
);
|
|
19
|
-
assert.equal(result.length, 1);
|
|
20
|
-
assert.equal(result[0].path, inside);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('bare filenames are anchored inside the store', () => {
|
|
24
|
-
const result = filterImagesToUploadStore(['shot.png'], STORE);
|
|
25
|
-
assert.equal(result.length, 1);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test('paths outside the store, traversal, and subdirs are dropped', () => {
|
|
29
|
-
const result = filterImagesToUploadStore(
|
|
30
|
-
[
|
|
31
|
-
{ path: 'C:/Users/victim/.ssh/id_rsa' },
|
|
32
|
-
{ path: '/etc/passwd' },
|
|
33
|
-
{ path: '../outside.png' },
|
|
34
|
-
{ path: path.join(STORE, '..', 'escaped.png') },
|
|
35
|
-
{ path: path.join(STORE, 'nested', 'deep.png') },
|
|
36
|
-
{ path: STORE }, // the store folder itself is not a file
|
|
37
|
-
],
|
|
38
|
-
STORE,
|
|
39
|
-
);
|
|
40
|
-
assert.deepEqual(result, []);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('malformed payloads yield no attachments', () => {
|
|
44
|
-
assert.deepEqual(filterImagesToUploadStore(undefined, STORE), []);
|
|
45
|
-
assert.deepEqual(filterImagesToUploadStore('nope', STORE), []);
|
|
46
|
-
assert.deepEqual(filterImagesToUploadStore([{ name: 'no-path' }, 42], STORE), []);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test('general files inside the upload store preserve their metadata', () => {
|
|
50
|
-
const inside = path.join(STORE, 'brief.pdf');
|
|
51
|
-
const result = filterAttachmentsToUploadStore(
|
|
52
|
-
[{ path: inside, name: 'brief.pdf', mimeType: 'application/pdf', size: 2048 }],
|
|
53
|
-
STORE,
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
assert.deepEqual(result, [
|
|
57
|
-
{ path: inside, name: 'brief.pdf', mimeType: 'application/pdf', size: 2048 },
|
|
58
|
-
]);
|
|
59
|
-
});
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import test from 'node:test';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
filterAttachmentsToUploadStore,
|
|
8
|
+
filterImagesToUploadStore,
|
|
9
|
+
} from '@/modules/websocket/services/chat-websocket.service.js';
|
|
10
|
+
|
|
11
|
+
const STORE = path.join(os.tmpdir(), 'cloudcli-assets-store');
|
|
12
|
+
|
|
13
|
+
test('images inside the upload store pass through', () => {
|
|
14
|
+
const inside = path.join(STORE, 'shot.png');
|
|
15
|
+
const result = filterImagesToUploadStore(
|
|
16
|
+
[{ path: inside, name: 'shot.png', mimeType: 'image/png' }],
|
|
17
|
+
STORE,
|
|
18
|
+
);
|
|
19
|
+
assert.equal(result.length, 1);
|
|
20
|
+
assert.equal(result[0].path, inside);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('bare filenames are anchored inside the store', () => {
|
|
24
|
+
const result = filterImagesToUploadStore(['shot.png'], STORE);
|
|
25
|
+
assert.equal(result.length, 1);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('paths outside the store, traversal, and subdirs are dropped', () => {
|
|
29
|
+
const result = filterImagesToUploadStore(
|
|
30
|
+
[
|
|
31
|
+
{ path: 'C:/Users/victim/.ssh/id_rsa' },
|
|
32
|
+
{ path: '/etc/passwd' },
|
|
33
|
+
{ path: '../outside.png' },
|
|
34
|
+
{ path: path.join(STORE, '..', 'escaped.png') },
|
|
35
|
+
{ path: path.join(STORE, 'nested', 'deep.png') },
|
|
36
|
+
{ path: STORE }, // the store folder itself is not a file
|
|
37
|
+
],
|
|
38
|
+
STORE,
|
|
39
|
+
);
|
|
40
|
+
assert.deepEqual(result, []);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('malformed payloads yield no attachments', () => {
|
|
44
|
+
assert.deepEqual(filterImagesToUploadStore(undefined, STORE), []);
|
|
45
|
+
assert.deepEqual(filterImagesToUploadStore('nope', STORE), []);
|
|
46
|
+
assert.deepEqual(filterImagesToUploadStore([{ name: 'no-path' }, 42], STORE), []);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('general files inside the upload store preserve their metadata', () => {
|
|
50
|
+
const inside = path.join(STORE, 'brief.pdf');
|
|
51
|
+
const result = filterAttachmentsToUploadStore(
|
|
52
|
+
[{ path: inside, name: 'brief.pdf', mimeType: 'application/pdf', size: 2048 }],
|
|
53
|
+
STORE,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
assert.deepEqual(result, [
|
|
57
|
+
{ path: inside, name: 'brief.pdf', mimeType: 'application/pdf', size: 2048 },
|
|
58
|
+
]);
|
|
59
|
+
});
|