@cloudcli-ai/cloudcli 1.37.3 → 1.37.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/assets/{abnfDiagram-N423BO3Z-CJntskwA.js → abnfDiagram-N423BO3Z-Dmkwx38H.js} +1 -1
- package/dist/assets/{arc-CIfH4uMN.js → arc-DLe9AYuO.js} +1 -1
- package/dist/assets/{architectureDiagram-T3A2C74G-_IpEkukg.js → architectureDiagram-T3A2C74G-CBbbbNUW.js} +1 -1
- package/dist/assets/{blockDiagram-VBNYF7ZC-BttxrpgZ.js → blockDiagram-VBNYF7ZC-CaMEaWu4.js} +1 -1
- package/dist/assets/{c4Diagram-5PPSVZJV-g51dSRr1.js → c4Diagram-5PPSVZJV-DhjMgNnR.js} +1 -1
- package/dist/assets/channel-CWrmwsir.js +1 -0
- package/dist/assets/{chunk-2GRJ4B5K-D_-LbQUa.js → chunk-2GRJ4B5K-yjl3-F-i.js} +1 -1
- package/dist/assets/{chunk-2Q5K7J3B-BtlHzwaO.js → chunk-2Q5K7J3B-DsAYaWEP.js} +1 -1
- package/dist/assets/{chunk-5RXB4S5H-UzkpvpAT.js → chunk-5RXB4S5H-Bt5qmqOX.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-BKwx5Gag.js → chunk-5VM5RSS4-yWrWVvUt.js} +1 -1
- package/dist/assets/{chunk-6Q2QTUOP-D_KEBH5f.js → chunk-6Q2QTUOP-Dt66K5xb.js} +1 -1
- package/dist/assets/{chunk-GF5L2VYU-rK2DGyto.js → chunk-GF5L2VYU-DA0vzaj4.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-CeBl_N9i.js → chunk-JWPE2WC7-CUkbx96V.js} +1 -1
- package/dist/assets/{chunk-KBJHAD2P-BiQLWVIr.js → chunk-KBJHAD2P-DWKxx1WH.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-C1knVGV5.js → chunk-RYQCIY6F-BqluplN0.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-CtKbJkvF.js → chunk-XXDRQBXY-DelKg3Xf.js} +1 -1
- package/dist/assets/classDiagram-JCYQIIEL-COAGCC6w.js +1 -0
- package/dist/assets/classDiagram-v2-OCEON4UE-COAGCC6w.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-DjX8y40Z.js → cose-bilkent-JH36ORCC-DHV93-Em.js} +1 -1
- package/dist/assets/{cynefin-VYW2F7L2-DM6YeRba.js → cynefin-VYW2F7L2-B9HZgoGX.js} +1 -1
- package/dist/assets/{cynefinDiagram-MW4NZA55-wZJ-vy5B.js → cynefinDiagram-MW4NZA55-hFjjEQg8.js} +1 -1
- package/dist/assets/{dagre-VZM6K2ZE-BzP0ejkH.js → dagre-VZM6K2ZE-CpeVOC7V.js} +1 -1
- package/dist/assets/{diagram-7IWD3JNH-BTL_j23J.js → diagram-7IWD3JNH-D0H1UoRA.js} +1 -1
- package/dist/assets/{diagram-B4RE2ZJO-Cf1Norgu.js → diagram-B4RE2ZJO-6Y7BQUup.js} +1 -1
- package/dist/assets/{diagram-LBJQPF4R-DPiUEKr-.js → diagram-LBJQPF4R-C0nNOwht.js} +1 -1
- package/dist/assets/{diagram-Q27KOJAE-CTcTpiz5.js → diagram-Q27KOJAE-En6QlOVX.js} +1 -1
- package/dist/assets/{diagram-UB23O5K3-DPMSdYm0.js → diagram-UB23O5K3-CmPiNeGD.js} +1 -1
- package/dist/assets/{ebnfDiagram-BXEA7PRR-7yvD6uiF.js → ebnfDiagram-BXEA7PRR-Bygzp1Qt.js} +1 -1
- package/dist/assets/{erDiagram-JOGREHBK-CfgeDoV6.js → erDiagram-JOGREHBK-CwScRfzl.js} +1 -1
- package/dist/assets/{flowDiagram-UKHOOZJN-B27ng5zu.js → flowDiagram-UKHOOZJN-bKX-0xP6.js} +1 -1
- package/dist/assets/{ganttDiagram-PKOTCBZU-CcC6b_7t.js → ganttDiagram-PKOTCBZU-DtZPKXGd.js} +1 -1
- package/dist/assets/{gitGraphDiagram-DS77QQ5N-BX5kPGrO.js → gitGraphDiagram-DS77QQ5N-CUOtdL1o.js} +1 -1
- package/dist/assets/index-CdjIFxM2.js +5004 -0
- package/dist/assets/index-DgafhGTF.css +32 -0
- package/dist/assets/{infoDiagram-6WML65LV-CUP-SlN4.js → infoDiagram-6WML65LV-ciRQTS0h.js} +1 -1
- package/dist/assets/{ishikawaDiagram-WSZJBQD7-BTTDhOpX.js → ishikawaDiagram-WSZJBQD7-CgjhQZ84.js} +1 -1
- package/dist/assets/{journeyDiagram-NVQOT4AX-ARXcc61m.js → journeyDiagram-NVQOT4AX-BsbQSeIW.js} +1 -1
- package/dist/assets/{kanban-definition-27J2QSJJ-BieMpqMA.js → kanban-definition-27J2QSJJ-CrwzY9Jw.js} +1 -1
- package/dist/assets/{linear-61vxjRnP.js → linear-BUaCDr6l.js} +1 -1
- package/dist/assets/{mermaid.core-nhnwkfQx.js → mermaid.core-ClgdUU0j.js} +5 -5
- package/dist/assets/{mindmap-definition-FAOFIHXS-Cm6x5vT1.js → mindmap-definition-FAOFIHXS-BictljY1.js} +1 -1
- package/dist/assets/{pegDiagram-VL7TDLO6-CcYBq_9H.js → pegDiagram-VL7TDLO6-BXdByy_U.js} +1 -1
- package/dist/assets/{pieDiagram-7S7Q4E2Y-CfvIjfzo.js → pieDiagram-7S7Q4E2Y-uZsMfkRX.js} +1 -1
- package/dist/assets/{quadrantDiagram-CIZ2JOQS-SgYoWPNb.js → quadrantDiagram-CIZ2JOQS-7lCv4QIj.js} +1 -1
- package/dist/assets/{railroadDiagram-AXF67PYL-D2Mu5E_f.js → railroadDiagram-AXF67PYL-07dxIWbi.js} +1 -1
- package/dist/assets/{requirementDiagram-LRYGKXZP-Azwe_k4Q.js → requirementDiagram-LRYGKXZP-Cb31Yv1_.js} +1 -1
- package/dist/assets/{sankeyDiagram-W5VNT64P-DN1Ju3PA.js → sankeyDiagram-W5VNT64P-X0YPSyF9.js} +1 -1
- package/dist/assets/{sequenceDiagram-SI44F4Z6-Bj4qC34S.js → sequenceDiagram-SI44F4Z6-BdBxSIlP.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-Co4PdklG.js → sizeCapture-X5ZJPWSS-DQM5xAyD.js} +1 -1
- package/dist/assets/{stateDiagram-OKZ733FA-nOvL9dRC.js → stateDiagram-OKZ733FA-DJ3xkLUF.js} +1 -1
- package/dist/assets/{stateDiagram-v2-UEYNNEHI-DNv8ppw7.js → stateDiagram-v2-UEYNNEHI-vAaE4zNo.js} +1 -1
- package/dist/assets/{swimlanes-SLNWSIFB-CCK3wMid.js → swimlanes-SLNWSIFB-rjfYdW0w.js} +2 -2
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-TV2IF4Nq.js +8 -0
- package/dist/assets/{timeline-definition-Z64GVDOM-BC29RNFm.js → timeline-definition-Z64GVDOM-DZMra5do.js} +1 -1
- package/dist/assets/{vennDiagram-T6HMQDX7-pZlZCtEo.js → vennDiagram-T6HMQDX7-BevD8uu0.js} +1 -1
- package/dist/assets/{wardleyDiagram-T6FBY63Y-De8k2-zM.js → wardleyDiagram-T6FBY63Y-DsIyXB7z.js} +1 -1
- package/dist/assets/{xychartDiagram-ELKLHX3M-Bk8ykH0w.js → xychartDiagram-ELKLHX3M-G3PlF3ko.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/server/index.js +4 -1
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/agent/agent.module.js +9 -2
- package/dist-server/server/modules/agent/agent.module.js.map +1 -1
- package/dist-server/server/modules/agent/agent.routes.js +175 -128
- package/dist-server/server/modules/agent/agent.routes.js.map +1 -1
- package/dist-server/server/modules/agent/tests/agent-run-registration.test.js +306 -0
- package/dist-server/server/modules/agent/tests/agent-run-registration.test.js.map +1 -0
- package/dist-server/server/modules/agent/tests/agent.routes.test.js +18 -1
- package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -1
- package/dist-server/server/modules/database/migrations.js +13 -0
- package/dist-server/server/modules/database/migrations.js.map +1 -1
- package/dist-server/server/modules/database/repositories/provider-models.js +60 -6
- package/dist-server/server/modules/database/repositories/provider-models.js.map +1 -1
- package/dist-server/server/modules/database/repositories/sessions.db.js +7 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
- package/dist-server/server/modules/database/schema.js +7 -0
- package/dist-server/server/modules/database/schema.js.map +1 -1
- package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +99 -0
- package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js.map +1 -1
- package/dist-server/server/modules/file-tree/file-tree.module.js +2 -1
- package/dist-server/server/modules/file-tree/file-tree.module.js.map +1 -1
- package/dist-server/server/modules/file-tree/file-tree.service.js +44 -7
- package/dist-server/server/modules/file-tree/file-tree.service.js.map +1 -1
- package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js +126 -1
- package/dist-server/server/modules/file-tree/tests/file-tree.service.test.js.map +1 -1
- package/dist-server/server/modules/git/git-branch-diff.service.js +142 -0
- package/dist-server/server/modules/git/git-branch-diff.service.js.map +1 -0
- package/dist-server/server/modules/git/git-branch.service.js.map +1 -1
- package/dist-server/server/modules/git/git.routes.js +92 -5
- package/dist-server/server/modules/git/git.routes.js.map +1 -1
- package/dist-server/server/modules/git/tests/git-branch-diff.service.test.js +160 -0
- package/dist-server/server/modules/git/tests/git-branch-diff.service.test.js.map +1 -0
- package/dist-server/server/modules/projects/project-clone.routes.js +108 -0
- package/dist-server/server/modules/projects/project-clone.routes.js.map +1 -0
- package/dist-server/server/modules/projects/projects.routes.js +13 -66
- package/dist-server/server/modules/projects/projects.routes.js.map +1 -1
- package/dist-server/server/modules/projects/services/project-clone-request.service.js +36 -0
- package/dist-server/server/modules/projects/services/project-clone-request.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-clone.service.js +86 -32
- package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -1
- package/dist-server/server/modules/projects/tests/project-clone.routes.test.js +191 -0
- package/dist-server/server/modules/projects/tests/project-clone.routes.test.js.map +1 -0
- package/dist-server/server/modules/projects/tests/project-clone.service.test.js +275 -0
- package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +42 -8
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +6 -16
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js +305 -16
- package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +38 -11
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +686 -77
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +31 -0
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js +11 -4
- package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +57 -0
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +9 -2
- package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js +8 -2
- package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +16 -3
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +5 -2
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +19 -2
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +110 -2
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/claude-cli-liveness.service.js +100 -0
- package/dist-server/server/modules/providers/services/claude-cli-liveness.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/claude-settings-permissions.service.js +97 -0
- package/dist-server/server/modules/providers/services/claude-settings-permissions.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/provider-capabilities.service.js +9 -1
- package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-models.service.js +59 -5
- package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-runtime.service.js +8 -0
- package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js +2 -4
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/session-history-cache.service.js +4 -0
- package/dist-server/server/modules/providers/services/session-history-cache.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions.service.js +73 -3
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/tests/claude-auth.test.js +131 -0
- package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/claude-background-work.test.js +172 -0
- package/dist-server/server/modules/providers/tests/claude-background-work.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/claude-compaction.test.js +84 -0
- package/dist-server/server/modules/providers/tests/claude-compaction.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/claude-message-model.test.js +123 -0
- package/dist-server/server/modules/providers/tests/claude-message-model.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/claude-runtime-hold.test.js +265 -0
- package/dist-server/server/modules/providers/tests/claude-runtime-hold.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/claude-sessions.test.js +1368 -12
- package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/claude-settings-permissions.test.js +228 -0
- package/dist-server/server/modules/providers/tests/claude-settings-permissions.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/codex-models.test.js +25 -0
- package/dist-server/server/modules/providers/tests/codex-models.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/codex-runtime.test.js +32 -0
- package/dist-server/server/modules/providers/tests/codex-runtime.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js +50 -0
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/cursor-auth.test.js +167 -0
- package/dist-server/server/modules/providers/tests/cursor-auth.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/opencode-models.test.js +79 -0
- package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +19 -1
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/provider-capabilities.service.test.js +30 -0
- package/dist-server/server/modules/providers/tests/provider-capabilities.service.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js +79 -1
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/provider.routes.test.js +190 -1
- package/dist-server/server/modules/providers/tests/provider.routes.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js +19 -0
- package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/sessions.service.test.js +175 -1
- package/dist-server/server/modules/providers/tests/sessions.service.test.js.map +1 -1
- package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js +13 -1
- package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js.map +1 -1
- package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js +36 -1
- package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +27 -5
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +38 -1
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +230 -20
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/tests/chat-background-subscribe.test.js +137 -0
- package/dist-server/server/modules/websocket/tests/chat-background-subscribe.test.js.map +1 -0
- package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js +96 -0
- package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js.map +1 -0
- package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +420 -0
- package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -1
- package/dist-server/server/shared/message-unification.js +1 -1
- package/dist-server/server/shared/message-unification.js.map +1 -1
- package/dist-server/server/shared/tests/read-only-roots.test.js +124 -0
- package/dist-server/server/shared/tests/read-only-roots.test.js.map +1 -0
- package/dist-server/server/shared/tests/strip-ansi-sequences.test.js +31 -0
- package/dist-server/server/shared/tests/strip-ansi-sequences.test.js.map +1 -0
- package/dist-server/server/shared/utils.js +126 -0
- package/dist-server/server/shared/utils.js.map +1 -1
- package/electron/desktopWindow.js +6 -0
- package/electron/viewHost.js +25 -2
- package/package.json +4 -4
- package/server/index.ts +5 -1
- package/server/modules/agent/agent.module.ts +11 -1
- package/server/modules/agent/agent.routes.ts +198 -140
- package/server/modules/agent/tests/agent-run-registration.test.ts +348 -0
- package/server/modules/agent/tests/agent.routes.test.ts +18 -1
- package/server/modules/database/migrations.ts +14 -0
- package/server/modules/database/repositories/provider-models.ts +79 -6
- package/server/modules/database/repositories/sessions.db.ts +8 -0
- package/server/modules/database/schema.ts +7 -0
- package/server/modules/database/tests/provider-models.db.integration.test.ts +113 -0
- package/server/modules/file-tree/file-tree.module.ts +2 -1
- package/server/modules/file-tree/file-tree.service.ts +49 -7
- package/server/modules/file-tree/tests/file-tree.service.test.ts +163 -1
- package/server/modules/git/git-branch-diff.service.ts +204 -0
- package/server/modules/git/git-branch.service.ts +2 -12
- package/server/modules/git/git.routes.ts +100 -6
- package/server/modules/git/tests/git-branch-diff.service.test.ts +210 -0
- package/server/modules/projects/project-clone.routes.ts +142 -0
- package/server/modules/projects/projects.routes.ts +16 -81
- package/server/modules/projects/services/project-clone-request.service.ts +56 -0
- package/server/modules/projects/services/project-clone.service.ts +102 -34
- package/server/modules/projects/tests/project-clone.routes.test.ts +246 -0
- package/server/modules/projects/tests/project-clone.service.test.ts +376 -0
- package/server/modules/providers/list/claude/claude-auth.provider.ts +60 -10
- package/server/modules/providers/list/claude/claude-models.provider.ts +10 -22
- package/server/modules/providers/list/claude/claude-runtime.provider.js +322 -15
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +40 -14
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +796 -88
- package/server/modules/providers/list/codex/codex-models.provider.ts +31 -0
- package/server/modules/providers/list/codex/codex-runtime.provider.ts +12 -4
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +63 -0
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +10 -2
- package/server/modules/providers/list/cursor/cursor-runtime.provider.js +9 -2
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +18 -3
- package/server/modules/providers/list/opencode/opencode-runtime.provider.js +5 -2
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +30 -2
- package/server/modules/providers/provider.routes.ts +131 -2
- package/server/modules/providers/services/claude-cli-liveness.service.ts +121 -0
- package/server/modules/providers/services/claude-settings-permissions.service.ts +127 -0
- package/server/modules/providers/services/provider-capabilities.service.ts +17 -1
- package/server/modules/providers/services/provider-models.service.ts +71 -4
- package/server/modules/providers/services/provider-runtime.service.ts +11 -0
- package/server/modules/providers/services/session-conversations-search.service.ts +2 -5
- package/server/modules/providers/services/session-history-cache.service.ts +13 -2
- package/server/modules/providers/services/sessions.service.ts +108 -8
- package/server/modules/providers/tests/claude-auth.test.ts +150 -0
- package/server/modules/providers/tests/claude-background-work.test.ts +213 -0
- package/server/modules/providers/tests/claude-compaction.test.ts +101 -0
- package/server/modules/providers/tests/claude-message-model.test.ts +160 -0
- package/server/modules/providers/tests/claude-runtime-hold.test.ts +309 -0
- package/server/modules/providers/tests/claude-sessions.test.ts +1630 -12
- package/server/modules/providers/tests/claude-settings-permissions.test.ts +271 -0
- package/server/modules/providers/tests/codex-models.test.ts +37 -0
- package/server/modules/providers/tests/codex-runtime.test.ts +36 -0
- package/server/modules/providers/tests/codex-sessions.test.ts +59 -0
- package/server/modules/providers/tests/cursor-auth.test.ts +187 -0
- package/server/modules/providers/tests/opencode-models.test.ts +100 -0
- package/server/modules/providers/tests/opencode-sessions.test.ts +40 -1
- package/server/modules/providers/tests/provider-capabilities.service.test.ts +37 -0
- package/server/modules/providers/tests/provider-models.service.test.ts +99 -1
- package/server/modules/providers/tests/provider.routes.test.ts +230 -1
- package/server/modules/providers/tests/session-history-cache.service.test.ts +22 -0
- package/server/modules/providers/tests/sessions.service.test.ts +237 -1
- package/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.ts +14 -1
- package/server/modules/scheduled-messages/tests/scheduled-messages.test.ts +45 -1
- package/server/modules/websocket/README.md +4 -2
- package/server/modules/websocket/services/chat-run-registry.service.ts +29 -5
- package/server/modules/websocket/services/chat-websocket.service.ts +58 -1
- package/server/modules/websocket/services/shell-websocket.service.ts +269 -22
- package/server/modules/websocket/tests/chat-background-subscribe.test.ts +167 -0
- package/server/modules/websocket/tests/chat-stop-task.test.ts +127 -0
- package/server/modules/websocket/tests/shell-websocket.service.test.ts +521 -0
- package/server/shared/interfaces.ts +29 -0
- package/server/shared/message-unification.ts +1 -1
- package/server/shared/tests/read-only-roots.test.ts +139 -0
- package/server/shared/tests/strip-ansi-sequences.test.ts +42 -0
- package/server/shared/types.ts +261 -7
- package/server/shared/utils.ts +136 -0
- package/dist/assets/channel-C5xU9jMw.js +0 -1
- package/dist/assets/classDiagram-JCYQIIEL-CRrL3vp7.js +0 -1
- package/dist/assets/classDiagram-v2-OCEON4UE-CRrL3vp7.js +0 -1
- package/dist/assets/index-BTDHQ6Id.css +0 -32
- package/dist/assets/index-sFfz8iBR.js +0 -4931
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-DnfbNQEp.js +0 -8
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
|
|
7
|
+
import { ClaudeSessionsProvider } from '@/modules/providers/list/claude/claude-sessions.provider.js';
|
|
8
|
+
import { CLAUDE_PREDEFINED_MODELS } from '@/modules/providers/list/claude/claude-models.provider.js';
|
|
9
|
+
import {
|
|
10
|
+
listClaudeSDKBackgroundWork,
|
|
11
|
+
queryClaudeSDK,
|
|
12
|
+
stopClaudeSDKTask,
|
|
13
|
+
} from '@/modules/providers/list/claude/claude-runtime.provider.js';
|
|
14
|
+
import type { NormalizedMessage, ProviderRuntimeContext } from '@/shared/types.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The runtime keeps the CLI's stdin open after a turn's `result` while the
|
|
18
|
+
* turn's background work is outstanding, and lets go when that work has
|
|
19
|
+
* reported. These drive `queryClaudeSDK` with a scripted SDK stream — the
|
|
20
|
+
* seam is `context.createQuery` — and watch the held prompt stream: the CLI
|
|
21
|
+
* exits when it ends, so "released" is the whole outcome.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const SESSION_ID = 'app-hold-session';
|
|
25
|
+
const NATIVE_ID = 'native-hold-session';
|
|
26
|
+
|
|
27
|
+
type Scripted = {
|
|
28
|
+
emit: (message: Record<string, unknown>) => void;
|
|
29
|
+
end: () => void;
|
|
30
|
+
released: () => boolean;
|
|
31
|
+
stopped: string[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** A stand-in for the SDK query: yields what the test emits, and reads the held prompt to notice its release. */
|
|
35
|
+
function createScriptedQuery(): { createQuery: NonNullable<ProviderRuntimeContext['createQuery']>; script: Scripted } {
|
|
36
|
+
const queue: Array<Record<string, unknown> | null> = [];
|
|
37
|
+
let wake: (() => void) | null = null;
|
|
38
|
+
let released = false;
|
|
39
|
+
const stopped: string[] = [];
|
|
40
|
+
|
|
41
|
+
const script: Scripted = {
|
|
42
|
+
emit: (message) => { queue.push(message); wake?.(); },
|
|
43
|
+
end: () => { queue.push(null); wake?.(); },
|
|
44
|
+
released: () => released,
|
|
45
|
+
stopped,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const createQuery: NonNullable<ProviderRuntimeContext['createQuery']> = ({ prompt }) => {
|
|
49
|
+
void (async () => {
|
|
50
|
+
for await (const _message of prompt) { /* the CLI reads its stdin */ }
|
|
51
|
+
released = true;
|
|
52
|
+
})();
|
|
53
|
+
|
|
54
|
+
const iterator = (async function* () {
|
|
55
|
+
for (;;) {
|
|
56
|
+
if (queue.length === 0) {
|
|
57
|
+
await new Promise<void>((resolve) => { wake = resolve; });
|
|
58
|
+
wake = null;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const next = queue.shift();
|
|
62
|
+
if (next === null || next === undefined) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
yield next;
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
|
|
69
|
+
return Object.assign(iterator, {
|
|
70
|
+
interrupt: async () => {},
|
|
71
|
+
stopTask: async (taskId: string) => { stopped.push(taskId); },
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return { createQuery, script };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function withRun(
|
|
79
|
+
runTest: (context: { script: Scripted; sent: NormalizedMessage[]; done: Promise<unknown> }) => Promise<void>,
|
|
80
|
+
): Promise<void> {
|
|
81
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), 'claude-runtime-hold-'));
|
|
82
|
+
const { createQuery, script } = createScriptedQuery();
|
|
83
|
+
const sent: NormalizedMessage[] = [];
|
|
84
|
+
const writer = { send: (message: NormalizedMessage) => { sent.push(message); }, userId: null };
|
|
85
|
+
const sessions = new ClaudeSessionsProvider({ getLiveRunStartTime: () => null });
|
|
86
|
+
const context: ProviderRuntimeContext = {
|
|
87
|
+
resolveProviderSessionId: () => null,
|
|
88
|
+
resolveResumeModel: async () => undefined,
|
|
89
|
+
getProviderModels: async () => CLAUDE_PREDEFINED_MODELS as never,
|
|
90
|
+
normalizeMessage: (raw, sessionId) => sessions.normalizeMessage(raw, sessionId),
|
|
91
|
+
isProviderInstalled: async () => true,
|
|
92
|
+
createQuery,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
const done = queryClaudeSDK('hello', { sessionId: SESSION_ID, cwd }, writer as never, context);
|
|
97
|
+
await runTest({ script, sent, done });
|
|
98
|
+
script.end();
|
|
99
|
+
await done;
|
|
100
|
+
} finally {
|
|
101
|
+
await rm(cwd, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const settle = () => new Promise((resolve) => { setTimeout(resolve, 25); });
|
|
106
|
+
|
|
107
|
+
// A fixed settle can be too short on a loaded machine; the supersede tests
|
|
108
|
+
// wait for the run to have actually processed its turn instead.
|
|
109
|
+
async function waitFor(condition: () => boolean): Promise<void> {
|
|
110
|
+
for (let attempt = 0; attempt < 200 && !condition(); attempt += 1) {
|
|
111
|
+
await settle();
|
|
112
|
+
}
|
|
113
|
+
assert.ok(condition(), 'condition never became true');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const init = () => ({ type: 'system', subtype: 'init', session_id: NATIVE_ID });
|
|
117
|
+
const toolUse = (id: string, name: string, input: Record<string, unknown>) => ({
|
|
118
|
+
type: 'assistant', session_id: NATIVE_ID, parent_tool_use_id: null,
|
|
119
|
+
message: { role: 'assistant', content: [{ type: 'tool_use', id, name, input }] },
|
|
120
|
+
});
|
|
121
|
+
const ack = (id: string, text: string, toolUseResult: Record<string, unknown>) => ({
|
|
122
|
+
type: 'user', session_id: NATIVE_ID, parent_tool_use_id: null,
|
|
123
|
+
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: id, content: text }] },
|
|
124
|
+
tool_use_result: toolUseResult,
|
|
125
|
+
});
|
|
126
|
+
const taskStarted = (taskId: string, toolUseId: string, taskType: string) => ({
|
|
127
|
+
type: 'system', subtype: 'task_started', session_id: NATIVE_ID, task_id: taskId, tool_use_id: toolUseId, description: `Task ${taskId}`, task_type: taskType,
|
|
128
|
+
});
|
|
129
|
+
const taskNotification = (taskId: string, toolUseId: string, status: string) => ({
|
|
130
|
+
type: 'system', subtype: 'task_notification', session_id: NATIVE_ID, task_id: taskId, tool_use_id: toolUseId, status, summary: `Task ${taskId} ${status}`, output_file: '',
|
|
131
|
+
});
|
|
132
|
+
const result = () => ({ type: 'result', subtype: 'success', session_id: NATIVE_ID, result: 'launched', duration_ms: 1, num_turns: 1 });
|
|
133
|
+
|
|
134
|
+
test('stopping the last outstanding task releases the held process', async () => {
|
|
135
|
+
await withRun(async ({ script, sent, done }) => {
|
|
136
|
+
script.emit(init());
|
|
137
|
+
script.emit(toolUse('toolu_wf', 'Workflow', { script: 'export const meta = {}' }));
|
|
138
|
+
script.emit(taskStarted('wf1', 'toolu_wf', 'local_workflow'));
|
|
139
|
+
script.emit(ack('toolu_wf', 'Workflow launched in background. Task ID: wf1', { status: 'async_launched', taskId: 'wf1', taskType: 'local_workflow' }));
|
|
140
|
+
script.emit(result());
|
|
141
|
+
await settle();
|
|
142
|
+
|
|
143
|
+
// The turn is over for the client, the process is held for the workflow.
|
|
144
|
+
assert.ok(sent.some((message) => message.kind === 'complete'));
|
|
145
|
+
assert.deepEqual(listClaudeSDKBackgroundWork().map((entry) => [entry.sessionId, entry.tasks.map((task) => task.taskId)]), [[SESSION_ID, ['wf1']]]);
|
|
146
|
+
assert.equal(script.released(), false, 'stdin stays open while the workflow runs');
|
|
147
|
+
|
|
148
|
+
// The user stops it. The CLI answers with a `stopped` notification and
|
|
149
|
+
// pushes no follow-up turn, so nothing else would ever end the hold.
|
|
150
|
+
assert.equal(await stopClaudeSDKTask(SESSION_ID, 'wf1'), true);
|
|
151
|
+
assert.deepEqual(script.stopped, ['wf1']);
|
|
152
|
+
script.emit(taskNotification('wf1', 'toolu_wf', 'stopped'));
|
|
153
|
+
await settle();
|
|
154
|
+
|
|
155
|
+
assert.deepEqual(listClaudeSDKBackgroundWork(), []);
|
|
156
|
+
assert.equal(script.released(), true, 'the process is let go once nothing is outstanding');
|
|
157
|
+
void done;
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('a task that reported completed keeps the hold for the turn that relays its result', async () => {
|
|
162
|
+
await withRun(async ({ script }) => {
|
|
163
|
+
script.emit(init());
|
|
164
|
+
script.emit(toolUse('toolu_wf', 'Workflow', { script: 'export const meta = {}' }));
|
|
165
|
+
script.emit(taskStarted('wf1', 'toolu_wf', 'local_workflow'));
|
|
166
|
+
script.emit(ack('toolu_wf', 'Workflow launched in background. Task ID: wf1', { status: 'async_launched', taskId: 'wf1', taskType: 'local_workflow' }));
|
|
167
|
+
script.emit(result());
|
|
168
|
+
await settle();
|
|
169
|
+
|
|
170
|
+
// Completed, unlike stopped, is followed by a turn the CLI pushes to relay
|
|
171
|
+
// the result; closing stdin at the notification would cut it short.
|
|
172
|
+
script.emit(taskNotification('wf1', 'toolu_wf', 'completed'));
|
|
173
|
+
await settle();
|
|
174
|
+
assert.equal(script.released(), false);
|
|
175
|
+
|
|
176
|
+
script.emit(result());
|
|
177
|
+
await settle();
|
|
178
|
+
assert.equal(script.released(), true, 'the follow-up turn\'s result ends the hold');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('an agent that ran in the foreground and settled before the result does not hold the process', async () => {
|
|
183
|
+
await withRun(async ({ script }) => {
|
|
184
|
+
// An Agent call without `run_in_background` is scored as background by
|
|
185
|
+
// the static rule, but the CLI ran it in the foreground: its task started
|
|
186
|
+
// and settled before the turn ended. The task events know that.
|
|
187
|
+
script.emit(init());
|
|
188
|
+
script.emit(toolUse('toolu_agent', 'Agent', { prompt: 'Return the word FOUR', subagent_type: 'general-purpose' }));
|
|
189
|
+
script.emit(taskStarted('a1', 'toolu_agent', 'local_agent'));
|
|
190
|
+
script.emit(taskNotification('a1', 'toolu_agent', 'completed'));
|
|
191
|
+
script.emit(ack('toolu_agent', 'FOUR', { status: 'completed', agentId: 'a1' }));
|
|
192
|
+
script.emit(result());
|
|
193
|
+
await settle();
|
|
194
|
+
|
|
195
|
+
assert.deepEqual(listClaudeSDKBackgroundWork(), []);
|
|
196
|
+
assert.equal(script.released(), true, 'nothing is outstanding, so nothing to hold for');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('a new turn stops the tasks the held process still has going before letting it go', async () => {
|
|
201
|
+
// Two runs on one session, each with its own scripted CLI: the first is
|
|
202
|
+
// held for a background agent, the second is the user's next message.
|
|
203
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), 'claude-runtime-hold-'));
|
|
204
|
+
const first = createScriptedQuery();
|
|
205
|
+
const second = createScriptedQuery();
|
|
206
|
+
const sent: NormalizedMessage[] = [];
|
|
207
|
+
const writer = { send: (message: NormalizedMessage) => { sent.push(message); }, userId: null };
|
|
208
|
+
const sessions = new ClaudeSessionsProvider({ getLiveRunStartTime: () => null });
|
|
209
|
+
const context: Omit<ProviderRuntimeContext, 'createQuery'> = {
|
|
210
|
+
resolveProviderSessionId: () => null,
|
|
211
|
+
resolveResumeModel: async () => undefined,
|
|
212
|
+
getProviderModels: async () => CLAUDE_PREDEFINED_MODELS as never,
|
|
213
|
+
normalizeMessage: (raw, sessionId) => sessions.normalizeMessage(raw, sessionId),
|
|
214
|
+
isProviderInstalled: async () => true,
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
const firstRun = queryClaudeSDK('start an agent', { sessionId: SESSION_ID, cwd }, writer as never, { ...context, createQuery: first.createQuery });
|
|
219
|
+
await settle();
|
|
220
|
+
first.script.emit(init());
|
|
221
|
+
first.script.emit(toolUse('toolu_agent', 'Agent', { prompt: 'sleep 90', subagent_type: 'general-purpose', run_in_background: true }));
|
|
222
|
+
first.script.emit(taskStarted('a1', 'toolu_agent', 'local_agent'));
|
|
223
|
+
first.script.emit(ack('toolu_agent', 'Async agent launched successfully.', { status: 'async_launched', agentId: 'a1' }));
|
|
224
|
+
first.script.emit(result());
|
|
225
|
+
await waitFor(() => sent.some((message) => message.kind === 'complete'));
|
|
226
|
+
assert.equal(first.script.released(), false, 'the first process is held for its agent');
|
|
227
|
+
|
|
228
|
+
// Closing stdin alone would leave the CLI waiting for the agent, so the
|
|
229
|
+
// superseded process would live on next to the new one for as long as
|
|
230
|
+
// the agent runs. The stop has to reach it before stdin ends, because the
|
|
231
|
+
// SDK drops control requests written to an ended stdin.
|
|
232
|
+
const secondRun = queryClaudeSDK('Continue', { sessionId: SESSION_ID, cwd }, writer as never, { ...context, createQuery: second.createQuery });
|
|
233
|
+
await settle();
|
|
234
|
+
assert.deepEqual(first.script.stopped, ['a1'], 'the held process is told to stop its agent');
|
|
235
|
+
assert.equal(first.script.released(), true, 'and is then let go');
|
|
236
|
+
assert.deepEqual(second.script.stopped, [], 'the new process is untouched');
|
|
237
|
+
|
|
238
|
+
first.script.emit(taskNotification('a1', 'toolu_agent', 'stopped'));
|
|
239
|
+
first.script.end();
|
|
240
|
+
await firstRun;
|
|
241
|
+
second.script.emit(init());
|
|
242
|
+
second.script.emit(result());
|
|
243
|
+
second.script.end();
|
|
244
|
+
await secondRun;
|
|
245
|
+
assert.deepEqual(listClaudeSDKBackgroundWork(), []);
|
|
246
|
+
} finally {
|
|
247
|
+
await rm(cwd, { recursive: true, force: true });
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test('a held process is still let go when stopping its tasks throws', async () => {
|
|
252
|
+
// Stopping is best effort; a stop that throws on the spot must not keep the
|
|
253
|
+
// held process alive or take the new turn down with it.
|
|
254
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), 'claude-runtime-hold-'));
|
|
255
|
+
const first = createScriptedQuery();
|
|
256
|
+
const second = createScriptedQuery();
|
|
257
|
+
const sent: NormalizedMessage[] = [];
|
|
258
|
+
const writer = { send: (message: NormalizedMessage) => { sent.push(message); }, userId: null };
|
|
259
|
+
const sessions = new ClaudeSessionsProvider({ getLiveRunStartTime: () => null });
|
|
260
|
+
const context: Omit<ProviderRuntimeContext, 'createQuery'> = {
|
|
261
|
+
resolveProviderSessionId: () => null,
|
|
262
|
+
resolveResumeModel: async () => undefined,
|
|
263
|
+
getProviderModels: async () => CLAUDE_PREDEFINED_MODELS as never,
|
|
264
|
+
normalizeMessage: (raw, sessionId) => sessions.normalizeMessage(raw, sessionId),
|
|
265
|
+
isProviderInstalled: async () => true,
|
|
266
|
+
};
|
|
267
|
+
const throwingStop: NonNullable<ProviderRuntimeContext['createQuery']> = (options) =>
|
|
268
|
+
Object.assign(first.createQuery(options), {
|
|
269
|
+
stopTask: () => { throw new Error('stop failed'); },
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const firstRun = queryClaudeSDK('start an agent', { sessionId: SESSION_ID, cwd }, writer as never, { ...context, createQuery: throwingStop });
|
|
274
|
+
await settle();
|
|
275
|
+
first.script.emit(init());
|
|
276
|
+
first.script.emit(toolUse('toolu_agent', 'Agent', { prompt: 'sleep 90', subagent_type: 'general-purpose', run_in_background: true }));
|
|
277
|
+
first.script.emit(taskStarted('a1', 'toolu_agent', 'local_agent'));
|
|
278
|
+
first.script.emit(ack('toolu_agent', 'Async agent launched successfully.', { status: 'async_launched', agentId: 'a1' }));
|
|
279
|
+
first.script.emit(result());
|
|
280
|
+
await waitFor(() => sent.some((message) => message.kind === 'complete'));
|
|
281
|
+
assert.equal(first.script.released(), false, 'the first process is held for its agent');
|
|
282
|
+
|
|
283
|
+
const secondRun = queryClaudeSDK('Continue', { sessionId: SESSION_ID, cwd }, writer as never, { ...context, createQuery: second.createQuery });
|
|
284
|
+
await settle();
|
|
285
|
+
assert.equal(first.script.released(), true, 'the held process is let go anyway');
|
|
286
|
+
|
|
287
|
+
first.script.end();
|
|
288
|
+
await firstRun;
|
|
289
|
+
second.script.emit(init());
|
|
290
|
+
second.script.emit(result());
|
|
291
|
+
second.script.end();
|
|
292
|
+
await secondRun;
|
|
293
|
+
assert.equal(second.script.released(), true, 'the new turn ran to completion');
|
|
294
|
+
} finally {
|
|
295
|
+
await rm(cwd, { recursive: true, force: true });
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test('a turn whose tool emits no task events still holds on the static rule', async () => {
|
|
300
|
+
await withRun(async ({ script }) => {
|
|
301
|
+
script.emit(init());
|
|
302
|
+
script.emit(toolUse('toolu_monitor', 'Monitor', { command: 'tail -f x', description: 'watch', timeout_ms: 1000 }));
|
|
303
|
+
script.emit(ack('toolu_monitor', 'Monitor started', {}));
|
|
304
|
+
script.emit(result());
|
|
305
|
+
await settle();
|
|
306
|
+
|
|
307
|
+
assert.equal(script.released(), false, 'Monitor reports no task, so the launch rule decides');
|
|
308
|
+
});
|
|
309
|
+
});
|