@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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AnyRecord,
|
|
3
|
+
BackgroundTaskSummary,
|
|
3
4
|
FetchHistoryOptions,
|
|
4
5
|
FetchHistoryResult,
|
|
5
6
|
LLMProvider,
|
|
@@ -17,6 +18,7 @@ import type {
|
|
|
17
18
|
ProviderRuntimePermissionGateway,
|
|
18
19
|
ProviderRuntimeWriter,
|
|
19
20
|
UpsertProviderMcpServerInput,
|
|
21
|
+
WorkflowAgentActivity,
|
|
20
22
|
} from '@/shared/types.js';
|
|
21
23
|
|
|
22
24
|
//----------------- PROVIDER CONTRACT INTERFACES ------------
|
|
@@ -36,6 +38,19 @@ export interface IProviderRuntime {
|
|
|
36
38
|
): Promise<unknown>;
|
|
37
39
|
abort(sessionId: string): boolean | Promise<boolean>;
|
|
38
40
|
permissions?: ProviderRuntimePermissionGateway;
|
|
41
|
+
/**
|
|
42
|
+
* Sessions with background tasks still outstanding, whether or not their
|
|
43
|
+
* turn has ended. Only a runtime that keeps its process open past a turn for
|
|
44
|
+
* such work has anything to report; the others leave this undefined and the
|
|
45
|
+
* running-sessions list falls back to chat runs alone.
|
|
46
|
+
*/
|
|
47
|
+
listBackgroundWork?(): Array<{ sessionId: string; tasks: BackgroundTaskSummary[] }>;
|
|
48
|
+
/**
|
|
49
|
+
* Stops one outstanding background task. Resolves false when the session has
|
|
50
|
+
* no live process or that process is not tracking the task — it already
|
|
51
|
+
* settled, or the id was never one of its own.
|
|
52
|
+
*/
|
|
53
|
+
stopBackgroundTask?(sessionId: string, taskId: string): Promise<boolean>;
|
|
39
54
|
}
|
|
40
55
|
|
|
41
56
|
/**
|
|
@@ -216,6 +231,20 @@ export interface IProviderSessions {
|
|
|
216
231
|
* gateway branches on.
|
|
217
232
|
*/
|
|
218
233
|
rewindSession?(sessionId: string, keepThroughId: string | null): Promise<void>;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Reads what one agent of a workflow run did, from the transcript the run
|
|
237
|
+
* wrote for it, with the status its journal gives it. Returns `null` when the
|
|
238
|
+
* run left no transcript for that agent.
|
|
239
|
+
*
|
|
240
|
+
* Implemented only by providers whose runtime spawns workflow agents; its
|
|
241
|
+
* absence is what makes an agent's timeline unavailable in the card.
|
|
242
|
+
*/
|
|
243
|
+
readWorkflowAgentActivity?(
|
|
244
|
+
sessionId: string,
|
|
245
|
+
runId: string,
|
|
246
|
+
agentId: string,
|
|
247
|
+
): Promise<WorkflowAgentActivity | null>;
|
|
219
248
|
}
|
|
220
249
|
|
|
221
250
|
// ---------------------------
|
|
@@ -322,7 +322,7 @@ function truncateOutput(value: string): string {
|
|
|
322
322
|
* only a single oversized string — a file body or an encoded image — is ever
|
|
323
323
|
* the thing making it large.
|
|
324
324
|
*/
|
|
325
|
-
function truncateNestedOutput(value: unknown): unknown {
|
|
325
|
+
export function truncateNestedOutput(value: unknown): unknown {
|
|
326
326
|
if (typeof value === 'string') {
|
|
327
327
|
return truncateOutput(value);
|
|
328
328
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdir, mkdtemp, realpath, rm, symlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test, { after } from 'node:test';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
// The Claude projects root is derived from `os.homedir()` when the utils module
|
|
9
|
+
// is first imported, so HOME has to point at the fixture home *before* that
|
|
10
|
+
// import runs. The fixture lives beside this file rather than under the temp
|
|
11
|
+
// directory: a home under `/tmp` would put everything under a read-only root
|
|
12
|
+
// and make the escape tests pass for the wrong reason.
|
|
13
|
+
const testDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const fixtureRoot = await realpath(await mkdtemp(path.join(testDirectory, 'read-only-roots-fixture-')));
|
|
15
|
+
const fixtureHome = path.join(fixtureRoot, 'home');
|
|
16
|
+
const claudeProjectsRoot = path.join(fixtureHome, '.claude', 'projects');
|
|
17
|
+
// Under no read-only root: not the temp directory, not the Claude projects dir.
|
|
18
|
+
const outsideDirectory = path.join(fixtureRoot, 'outside');
|
|
19
|
+
await mkdir(claudeProjectsRoot, { recursive: true });
|
|
20
|
+
await mkdir(outsideDirectory);
|
|
21
|
+
|
|
22
|
+
const previousHome = process.env.HOME;
|
|
23
|
+
const previousUserProfile = process.env.USERPROFILE;
|
|
24
|
+
process.env.HOME = fixtureHome;
|
|
25
|
+
process.env.USERPROFILE = fixtureHome;
|
|
26
|
+
|
|
27
|
+
const { resolvePathUnderRoots, resolveReadOnlyRootPath, validateWorkspacePath } = await import('@/shared/utils.js');
|
|
28
|
+
|
|
29
|
+
after(async () => {
|
|
30
|
+
if (previousHome === undefined) {
|
|
31
|
+
delete process.env.HOME;
|
|
32
|
+
} else {
|
|
33
|
+
process.env.HOME = previousHome;
|
|
34
|
+
}
|
|
35
|
+
if (previousUserProfile === undefined) {
|
|
36
|
+
delete process.env.USERPROFILE;
|
|
37
|
+
} else {
|
|
38
|
+
process.env.USERPROFILE = previousUserProfile;
|
|
39
|
+
}
|
|
40
|
+
await rm(fixtureRoot, { recursive: true, force: true });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('a path under the system temp directory resolves as readable', async () => {
|
|
44
|
+
const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const filePath = path.join(temporaryDirectory, 'agent.output');
|
|
48
|
+
await writeFile(filePath, 'agent output', 'utf8');
|
|
49
|
+
|
|
50
|
+
// A background command's log is quoted straight out of the transcript, so
|
|
51
|
+
// this exact shape has to resolve.
|
|
52
|
+
const resolvedDirectory = await resolveReadOnlyRootPath(temporaryDirectory);
|
|
53
|
+
assert.ok(resolvedDirectory);
|
|
54
|
+
assert.equal(await resolveReadOnlyRootPath(filePath), path.join(resolvedDirectory, 'agent.output'));
|
|
55
|
+
} finally {
|
|
56
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('a background agent output link resolves to its transcript under the Claude projects directory', async () => {
|
|
61
|
+
const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
// Claude writes `/tmp/claude-<uid>/<project>/<session>/tasks/<task>.output`
|
|
65
|
+
// as a symlink to the agent's transcript under `~/.claude/projects`.
|
|
66
|
+
const transcriptDirectory = path.join(claudeProjectsRoot, '-home-user-project', 'session-1', 'subagents');
|
|
67
|
+
await mkdir(transcriptDirectory, { recursive: true });
|
|
68
|
+
const transcriptPath = path.join(transcriptDirectory, 'agent-1.jsonl');
|
|
69
|
+
await writeFile(transcriptPath, '{"type":"assistant"}\n', 'utf8');
|
|
70
|
+
|
|
71
|
+
const tasksDirectory = path.join(temporaryDirectory, 'tasks');
|
|
72
|
+
await mkdir(tasksDirectory);
|
|
73
|
+
const outputLink = path.join(tasksDirectory, 'task-1.output');
|
|
74
|
+
await symlink(transcriptPath, outputLink);
|
|
75
|
+
|
|
76
|
+
assert.equal(await resolveReadOnlyRootPath(outputLink), transcriptPath);
|
|
77
|
+
assert.equal(await resolveReadOnlyRootPath(transcriptPath), transcriptPath);
|
|
78
|
+
} finally {
|
|
79
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('the temp directory stays read-only: it is still not a valid workspace location', async () => {
|
|
84
|
+
const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
// Being browsable must not make it writable — the write policy is
|
|
88
|
+
// `validateWorkspacePath` and it does not consult the read-only roots.
|
|
89
|
+
const validation = await validateWorkspacePath(temporaryDirectory);
|
|
90
|
+
assert.equal(validation.valid, false);
|
|
91
|
+
} finally {
|
|
92
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('paths outside the read-only roots do not resolve', async () => {
|
|
97
|
+
assert.equal(await resolveReadOnlyRootPath(outsideDirectory), null);
|
|
98
|
+
assert.equal(await resolveReadOnlyRootPath('/etc/passwd'), null);
|
|
99
|
+
assert.equal(await resolveReadOnlyRootPath('relative/path'), null);
|
|
100
|
+
assert.equal(await resolveReadOnlyRootPath(''), null);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('a symlink planted in the temp directory cannot read outside every root', async () => {
|
|
104
|
+
const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
await writeFile(path.join(outsideDirectory, 'secret.txt'), 'secret', 'utf8');
|
|
108
|
+
const escapeLink = path.join(temporaryDirectory, 'escape');
|
|
109
|
+
await symlink(outsideDirectory, escapeLink);
|
|
110
|
+
|
|
111
|
+
// The name is under a read-only root but the file is not, so resolving the
|
|
112
|
+
// link before comparing is what keeps this closed.
|
|
113
|
+
assert.equal(await resolveReadOnlyRootPath(escapeLink), null);
|
|
114
|
+
assert.equal(await resolveReadOnlyRootPath(path.join(escapeLink, 'secret.txt')), null);
|
|
115
|
+
} finally {
|
|
116
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('a root that does not exist does not stop later roots from matching', async () => {
|
|
121
|
+
const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), 'read-only-root-'));
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
// `/tmp` does not exist on Windows; the temp directory listed after it
|
|
125
|
+
// must still be checked rather than the whole search giving up.
|
|
126
|
+
const missingRoot = path.join(fixtureRoot, 'missing');
|
|
127
|
+
assert.equal(await resolvePathUnderRoots(temporaryDirectory, [missingRoot]), null);
|
|
128
|
+
assert.equal(
|
|
129
|
+
await resolvePathUnderRoots(temporaryDirectory, [missingRoot, os.tmpdir()]),
|
|
130
|
+
await realpath(temporaryDirectory),
|
|
131
|
+
);
|
|
132
|
+
} finally {
|
|
133
|
+
await rm(temporaryDirectory, { recursive: true, force: true });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('traversal out of the temp directory does not resolve', async () => {
|
|
138
|
+
assert.equal(await resolveReadOnlyRootPath(`${os.tmpdir()}/../etc/passwd`), null);
|
|
139
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { stripAnsiSequences } from '@/shared/utils.js';
|
|
5
|
+
|
|
6
|
+
test('strips the SGR colors a CLI writes around its own warnings', () => {
|
|
7
|
+
const styled = '\u001B[93m\u001B[1m! \u001B[0m\u001B[0mpermission requested: external_directory';
|
|
8
|
+
assert.equal(stripAnsiSequences(styled), '! permission requested: external_directory');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('strips CSI cursor control, including the 8-bit introducer', () => {
|
|
12
|
+
assert.equal(stripAnsiSequences('a\u001B[2Kb\u001B[?25lc'), 'abc');
|
|
13
|
+
assert.equal(stripAnsiSequences('a\u009B31mb'), 'ab');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('strips an OSC sequence with either terminator, without eating the rest', () => {
|
|
17
|
+
assert.equal(stripAnsiSequences('\u001B]0;title\u0007done'), 'done');
|
|
18
|
+
assert.equal(stripAnsiSequences('\u001B]8;;https://example.com\u001B\\link'), 'link');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('strips other ECMA-48 escape sequences such as charset selection', () => {
|
|
22
|
+
assert.equal(stripAnsiSequences('\u001B(Bplain'), 'plain');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('leaves text without escape sequences untouched', () => {
|
|
26
|
+
assert.equal(stripAnsiSequences('plain [93m-looking text'), 'plain [93m-looking text');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('strips a CSI sequence that carries a private parameter byte', () => {
|
|
30
|
+
assert.equal(stripAnsiSequences('a\u001B[>cb'), 'ab');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('stops an unterminated OSC at the next escape, so later styling still strips', () => {
|
|
34
|
+
assert.equal(
|
|
35
|
+
stripAnsiSequences('\u001B]0;unterminated\u001B[31mred\u001B[0m'),
|
|
36
|
+
'0;unterminatedred',
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('reduces a styling-only chunk to an empty string', () => {
|
|
41
|
+
assert.equal(stripAnsiSequences('\u001B[0m\u001B[2K'), '');
|
|
42
|
+
});
|
package/server/shared/types.ts
CHANGED
|
@@ -94,6 +94,13 @@ export type ProviderModelOption = {
|
|
|
94
94
|
export type ProviderModelsDefinition = {
|
|
95
95
|
OPTIONS: ProviderModelOption[];
|
|
96
96
|
DEFAULT: string;
|
|
97
|
+
/**
|
|
98
|
+
* Reasoning-effort levels a custom entry of this catalog may declare, weakest
|
|
99
|
+
* first; empty for providers without effort support. The Providers service
|
|
100
|
+
* sets it on merged catalogs from the capability matrix, so the model
|
|
101
|
+
* library offers the same levels on every machine. Adapter catalogs omit it.
|
|
102
|
+
*/
|
|
103
|
+
EFFORT_LEVELS?: string[];
|
|
97
104
|
};
|
|
98
105
|
|
|
99
106
|
/**
|
|
@@ -110,6 +117,22 @@ export type CustomProviderModelRecord = {
|
|
|
110
117
|
modelId: string;
|
|
111
118
|
model: string;
|
|
112
119
|
sortOrder: number;
|
|
120
|
+
/** NULL for rows that never declared effort levels, including pre-existing rows. */
|
|
121
|
+
effort: CustomProviderModelEffort | null;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Reasoning-effort levels a user declared for one custom model.
|
|
126
|
+
*
|
|
127
|
+
* `values` holds unique, non-empty level ids drawn from the levels the
|
|
128
|
+
* provider's predefined models declare, and is never empty (an empty
|
|
129
|
+
* declaration is stored as NULL). `default`, when present, is one of `values`
|
|
130
|
+
* and documents the level the provider applies when the composer sends
|
|
131
|
+
* `Default`, mirroring `ProviderModelOption['effort'].default`.
|
|
132
|
+
*/
|
|
133
|
+
export type CustomProviderModelEffort = {
|
|
134
|
+
values: string[];
|
|
135
|
+
default?: string;
|
|
113
136
|
};
|
|
114
137
|
|
|
115
138
|
/**
|
|
@@ -122,6 +145,12 @@ export type CustomProviderModelRecord = {
|
|
|
122
145
|
export type CustomProviderModelInput = {
|
|
123
146
|
id: string;
|
|
124
147
|
model: string;
|
|
148
|
+
/**
|
|
149
|
+
* Optional reasoning-effort declaration. `undefined` leaves stored metadata
|
|
150
|
+
* untouched on update (and stores none on create) so clients that predate
|
|
151
|
+
* effort metadata keep working; `null` clears it.
|
|
152
|
+
*/
|
|
153
|
+
effort?: CustomProviderModelEffort | null;
|
|
125
154
|
};
|
|
126
155
|
|
|
127
156
|
// ---------------------------
|
|
@@ -190,7 +219,8 @@ export type MessageKind =
|
|
|
190
219
|
| 'permission_cancelled'
|
|
191
220
|
| 'session_created'
|
|
192
221
|
| 'history_truncated'
|
|
193
|
-
| 'task_notification'
|
|
222
|
+
| 'task_notification'
|
|
223
|
+
| 'task_status';
|
|
194
224
|
|
|
195
225
|
/**
|
|
196
226
|
* Event kinds added by the chat gateway layer on top of provider message kinds.
|
|
@@ -258,6 +288,24 @@ export type SessionUpsertedEvent = {
|
|
|
258
288
|
* Every provider-specific message must be converted into this shape before being
|
|
259
289
|
* emitted outside provider-specific modules.
|
|
260
290
|
*/
|
|
291
|
+
/**
|
|
292
|
+
* A compaction, as the transcript records it.
|
|
293
|
+
*
|
|
294
|
+
* `running` is the status the CLI sends when it starts compacting, `done` the
|
|
295
|
+
* boundary it sends when it has, `failed` a compaction that did not finish.
|
|
296
|
+
* The token counts and duration only come with a boundary.
|
|
297
|
+
*/
|
|
298
|
+
export type CompactionInfo = {
|
|
299
|
+
phase: 'running' | 'done' | 'failed';
|
|
300
|
+
/** Whether the user asked for it or the context window did. */
|
|
301
|
+
trigger?: 'manual' | 'auto';
|
|
302
|
+
/** Tokens the conversation held before and after, when the boundary reports them. */
|
|
303
|
+
preTokens?: number;
|
|
304
|
+
postTokens?: number;
|
|
305
|
+
durationMs?: number;
|
|
306
|
+
error?: string | null;
|
|
307
|
+
};
|
|
308
|
+
|
|
261
309
|
export type NormalizedMessage = {
|
|
262
310
|
id: string;
|
|
263
311
|
/**
|
|
@@ -280,6 +328,15 @@ export type NormalizedMessage = {
|
|
|
280
328
|
seq?: number;
|
|
281
329
|
role?: 'user' | 'assistant';
|
|
282
330
|
content?: string;
|
|
331
|
+
/**
|
|
332
|
+
* The model that produced this assistant message, as the provider reported
|
|
333
|
+
* it on the transcript row (today: Claude's `message.model`, e.g.
|
|
334
|
+
* `claude-opus-5`). Absent on user turns — no provider records which model a
|
|
335
|
+
* request went out with — and absent when the provider named a placeholder
|
|
336
|
+
* such as `<synthetic>`, so a locally-fabricated notice is never labelled
|
|
337
|
+
* with a model it did not run on.
|
|
338
|
+
*/
|
|
339
|
+
model?: string;
|
|
283
340
|
/**
|
|
284
341
|
* Optional display-oriented metadata used by providers that need to expose
|
|
285
342
|
* richer transcript artifacts without introducing a brand-new message kind.
|
|
@@ -295,6 +352,8 @@ export type NormalizedMessage = {
|
|
|
295
352
|
isLocalCommand?: boolean;
|
|
296
353
|
isLocalCommandStdout?: boolean;
|
|
297
354
|
isCompactSummary?: boolean;
|
|
355
|
+
/** Set on the row that stands in for a compaction, so the UI can draw it as one. */
|
|
356
|
+
compact?: CompactionInfo;
|
|
298
357
|
images?: unknown;
|
|
299
358
|
/** Non-image files attached to a user turn after provider history normalization. */
|
|
300
359
|
files?: unknown;
|
|
@@ -326,14 +385,149 @@ export type NormalizedMessage = {
|
|
|
326
385
|
subagentTools?: SubagentActivity[];
|
|
327
386
|
/** Identity and lifecycle of the subagent this `tool_use` spawned. */
|
|
328
387
|
subagent?: SubagentInfo;
|
|
388
|
+
/** The workflow run this `tool_use` launched, read from its journal on disk. */
|
|
389
|
+
workflow?: WorkflowInfo;
|
|
329
390
|
/** Stored memory the reply drew on, when the provider reports it. */
|
|
330
391
|
memoryCitations?: MemoryCitation[];
|
|
331
392
|
toolUseResult?: unknown;
|
|
332
393
|
sequence?: number;
|
|
333
394
|
rowid?: number;
|
|
395
|
+
/**
|
|
396
|
+
* `task_status` fields: one lifecycle event of a background task the live
|
|
397
|
+
* run is tracking. `taskId` is the provider's task handle; `toolUseId` names
|
|
398
|
+
* the call that launched it and is absent on `updated`, which the SDK keys by
|
|
399
|
+
* task id alone. `status` and `summary` above carry the event's own.
|
|
400
|
+
*/
|
|
401
|
+
event?: 'started' | 'progress' | 'updated' | 'notification';
|
|
402
|
+
taskId?: string;
|
|
403
|
+
toolUseId?: string;
|
|
404
|
+
taskType?: string;
|
|
405
|
+
workflowName?: string;
|
|
406
|
+
description?: string;
|
|
407
|
+
usage?: TaskUsage;
|
|
408
|
+
outputFile?: string;
|
|
409
|
+
/** A workflow's `progress` only: where each agent the run spawned stands. */
|
|
410
|
+
agents?: WorkflowAgentProgress[];
|
|
334
411
|
[key: string]: unknown;
|
|
335
412
|
};
|
|
336
413
|
|
|
414
|
+
/**
|
|
415
|
+
* What a background task has spent so far, as the CLI reports it on
|
|
416
|
+
* `task_progress` and `task_notification`.
|
|
417
|
+
*/
|
|
418
|
+
export type TaskUsage = {
|
|
419
|
+
totalTokens: number;
|
|
420
|
+
toolUses: number;
|
|
421
|
+
durationMs: number;
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* One background task a live session still has outstanding — a spawned
|
|
426
|
+
* agent, a workflow run or a backgrounded command — as the runtime tracks it
|
|
427
|
+
* from the stream's `task_started` until the event that settles it.
|
|
428
|
+
*
|
|
429
|
+
* `taskId` is the handle a stop request names; `toolUseId` is the call that
|
|
430
|
+
* launched it, which is how the client pairs the task with its card.
|
|
431
|
+
* `startedAt` is the server clock at `task_started`, so a session whose turn
|
|
432
|
+
* has ended can still report how long its work has been going.
|
|
433
|
+
*/
|
|
434
|
+
export type BackgroundTaskSummary = {
|
|
435
|
+
taskId: string;
|
|
436
|
+
toolUseId: string;
|
|
437
|
+
taskType: string;
|
|
438
|
+
description: string;
|
|
439
|
+
workflowName?: string;
|
|
440
|
+
startedAt: number;
|
|
441
|
+
/**
|
|
442
|
+
* The task was launched by a subagent or workflow agent, not by the
|
|
443
|
+
* session's own turn: its `toolUseId` names a call in that agent's
|
|
444
|
+
* transcript, so no card in this session's transcript matches it. Listed so
|
|
445
|
+
* it can still be stopped; not counted as the session's own work.
|
|
446
|
+
*/
|
|
447
|
+
nested?: boolean;
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Where one agent of a running workflow stands, as the SDK reports it on the
|
|
452
|
+
* run's `task_progress` events.
|
|
453
|
+
*
|
|
454
|
+
* An entry the script has queued but not yet started has no `agentId` and is
|
|
455
|
+
* identified by `index` alone; once the agent runs, `agentId` names the
|
|
456
|
+
* transcript it writes. `lastToolName` and `lastToolSummary` are the agent's
|
|
457
|
+
* own latest tool call — unlike the event's task-level `last_tool_name`, which
|
|
458
|
+
* for a workflow is the current agent's label.
|
|
459
|
+
*/
|
|
460
|
+
export type WorkflowAgentProgress = {
|
|
461
|
+
index: number;
|
|
462
|
+
label?: string;
|
|
463
|
+
/** The title of the script phase the agent runs under, when it has one. */
|
|
464
|
+
phase?: string;
|
|
465
|
+
agentId?: string;
|
|
466
|
+
model?: string;
|
|
467
|
+
state: 'queued' | 'running' | 'done' | 'failed';
|
|
468
|
+
startedAt?: number;
|
|
469
|
+
lastToolName?: string;
|
|
470
|
+
lastToolSummary?: string;
|
|
471
|
+
promptPreview?: string;
|
|
472
|
+
tokens?: number;
|
|
473
|
+
toolCalls?: number;
|
|
474
|
+
durationMs?: number;
|
|
475
|
+
resultPreview?: string;
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* One workflow agent's recorded timeline, read from its transcript on demand
|
|
480
|
+
* when the card is opened — the SDK never streams an agent's own rows to the
|
|
481
|
+
* parent session, so this is the only way to see what it did.
|
|
482
|
+
*
|
|
483
|
+
* `activityCount` is the full length of the timeline; `activity` is capped
|
|
484
|
+
* for transport like a subagent's `subagentTools`.
|
|
485
|
+
*/
|
|
486
|
+
export type WorkflowAgentActivity = {
|
|
487
|
+
agent: {
|
|
488
|
+
id: string;
|
|
489
|
+
label?: string;
|
|
490
|
+
model?: string;
|
|
491
|
+
status: 'running' | 'completed' | 'failed' | 'stopped';
|
|
492
|
+
};
|
|
493
|
+
activity: SubagentActivity[];
|
|
494
|
+
activityCount: number;
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* One agent a workflow run spawned, as its journal records it.
|
|
499
|
+
*
|
|
500
|
+
* `label` and `phase` are whatever the script passed when it spawned the
|
|
501
|
+
* agent; older scripts passed neither. An agent with a `started` record and no
|
|
502
|
+
* `result` or `failed` one is still running as far as the journal knows.
|
|
503
|
+
*/
|
|
504
|
+
export type WorkflowAgentInfo = {
|
|
505
|
+
id: string;
|
|
506
|
+
label?: string;
|
|
507
|
+
phase?: string;
|
|
508
|
+
/** `stopped` is an agent the journal never settled although the run itself has — abandoned by a stop or a resume that re-ran the step. */
|
|
509
|
+
status: 'running' | 'completed' | 'failed' | 'stopped';
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* A `Workflow` tool call's run, attached to the `tool_use` that launched it.
|
|
514
|
+
*
|
|
515
|
+
* `status` follows the same rule as a background agent's: the task
|
|
516
|
+
* notification's word when one exists, else `running` only while the process
|
|
517
|
+
* that launched it is still up, else `stopped`. The agent list and counts come
|
|
518
|
+
* from `<transcriptDir>/journal.jsonl`; both are empty when the run left no
|
|
519
|
+
* journal behind (a fork copies only the parent's transcript).
|
|
520
|
+
*/
|
|
521
|
+
export type WorkflowInfo = {
|
|
522
|
+
runId: string;
|
|
523
|
+
name: string;
|
|
524
|
+
description?: string;
|
|
525
|
+
status: 'running' | 'completed' | 'failed' | 'stopped';
|
|
526
|
+
agents: WorkflowAgentInfo[];
|
|
527
|
+
agentCounts: { total: number; completed: number; failed: number; running: number; stopped: number };
|
|
528
|
+
scriptPath?: string;
|
|
529
|
+
};
|
|
530
|
+
|
|
337
531
|
/**
|
|
338
532
|
* One stored memory an assistant reply drew on.
|
|
339
533
|
*
|
|
@@ -380,7 +574,8 @@ export type SubagentActivity = {
|
|
|
380
574
|
* that it is whatever the provider reported — Claude's task notification
|
|
381
575
|
* carries one — and `completed` when the provider reported nothing. A failed
|
|
382
576
|
* tool call *inside* the agent is not a failed agent, so it is never inferred
|
|
383
|
-
* from the transcript.
|
|
577
|
+
* from the transcript. A background agent whose session process ended before
|
|
578
|
+
* it reported is `stopped`: no outcome exists and none is coming.
|
|
384
579
|
*/
|
|
385
580
|
export type SubagentInfo = {
|
|
386
581
|
/** Provider-native agent id — Claude `agentId`, Codex `agent_thread_id`. */
|
|
@@ -391,7 +586,7 @@ export type SubagentInfo = {
|
|
|
391
586
|
type?: string;
|
|
392
587
|
/** One-line task summary shown in the collapsed header. */
|
|
393
588
|
description?: string;
|
|
394
|
-
status: 'running' | 'completed' | 'failed';
|
|
589
|
+
status: 'running' | 'completed' | 'failed' | 'stopped';
|
|
395
590
|
/** Model the subagent ran on, when the provider records it. */
|
|
396
591
|
model?: string;
|
|
397
592
|
/**
|
|
@@ -413,7 +608,6 @@ export type ProviderRuntimeWriter = {
|
|
|
413
608
|
setSessionId?(sessionId: string): void;
|
|
414
609
|
userId?: string | number | null;
|
|
415
610
|
isWebSocketWriter?: boolean;
|
|
416
|
-
isSSEStreamWriter?: boolean;
|
|
417
611
|
};
|
|
418
612
|
|
|
419
613
|
export type ProviderPermissionDecision = {
|
|
@@ -443,6 +637,15 @@ export type ProviderRuntimeContext = {
|
|
|
443
637
|
getProviderModels(): Promise<ProviderModelsDefinition>;
|
|
444
638
|
normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
|
|
445
639
|
isProviderInstalled(): Promise<boolean>;
|
|
640
|
+
/**
|
|
641
|
+
* Builds the SDK query for a run. Production leaves this unset and the
|
|
642
|
+
* runtime uses the SDK's own; tests supply a scripted stream so the hold
|
|
643
|
+
* and background-work paths can be driven without a CLI process.
|
|
644
|
+
*/
|
|
645
|
+
createQuery?: (input: { prompt: AsyncIterable<unknown>; options: AnyRecord }) => AsyncIterable<unknown> & {
|
|
646
|
+
interrupt(): Promise<void>;
|
|
647
|
+
stopTask?(taskId: string): Promise<void>;
|
|
648
|
+
};
|
|
446
649
|
};
|
|
447
650
|
|
|
448
651
|
export type ProviderRunFunction = (
|
|
@@ -667,6 +870,29 @@ export type UpsertProviderMcpServerInput = {
|
|
|
667
870
|
|
|
668
871
|
// ---------------------------
|
|
669
872
|
//----------------- PROVIDER AUTH TYPES ------------
|
|
873
|
+
/**
|
|
874
|
+
* Records that an API-key style credential is taking precedence over a
|
|
875
|
+
* still-valid subscription login in `~/.claude/.credentials.json`.
|
|
876
|
+
*
|
|
877
|
+
* Claude Code always prefers `ANTHROPIC_AUTH_TOKEN` / `ANTHROPIC_API_KEY` over
|
|
878
|
+
* the OAuth login written by `claude /login`, so when both exist every request
|
|
879
|
+
* is billed to the key (pay-as-you-go) rather than the subscription — usually
|
|
880
|
+
* without the user realising it. The Claude auth provider fills this in so the
|
|
881
|
+
* settings UI can say which variable won and where it was found; the fix
|
|
882
|
+
* differs per source (unset the variable and restart the server for
|
|
883
|
+
* `process_env`, edit the `env` block of `~/.claude/settings.json` for
|
|
884
|
+
* `settings_file`). It is never set when the login in the credentials file is
|
|
885
|
+
* missing or expired, because then nothing is being bypassed.
|
|
886
|
+
*/
|
|
887
|
+
export type ProviderAuthSubscriptionOverride = {
|
|
888
|
+
/** The environment variable Claude Code is using instead of the login. */
|
|
889
|
+
variable: 'ANTHROPIC_API_KEY' | 'ANTHROPIC_AUTH_TOKEN';
|
|
890
|
+
/** Where that variable was found: the server process env or the settings.json env block. */
|
|
891
|
+
source: 'process_env' | 'settings_file';
|
|
892
|
+
/** Email recorded in the credentials file for the bypassed login, when known. */
|
|
893
|
+
subscriptionEmail: string | null;
|
|
894
|
+
};
|
|
895
|
+
|
|
670
896
|
/**
|
|
671
897
|
* Authentication status result returned by provider health checks.
|
|
672
898
|
*
|
|
@@ -680,6 +906,12 @@ export type ProviderAuthStatus = {
|
|
|
680
906
|
email: string | null;
|
|
681
907
|
method: string | null;
|
|
682
908
|
error?: string;
|
|
909
|
+
/**
|
|
910
|
+
* Present only when `method` is `api_key` and a valid subscription login is
|
|
911
|
+
* being bypassed; see ProviderAuthSubscriptionOverride. Omitted otherwise so
|
|
912
|
+
* existing consumers that never look for it are unaffected.
|
|
913
|
+
*/
|
|
914
|
+
subscriptionOverride?: ProviderAuthSubscriptionOverride;
|
|
683
915
|
};
|
|
684
916
|
|
|
685
917
|
// ---------------------------
|
|
@@ -763,12 +995,13 @@ export type WorkspacePathValidationResult = {
|
|
|
763
995
|
};
|
|
764
996
|
|
|
765
997
|
// ---------------------------
|
|
766
|
-
//----------------- GIT WORKTREE MANAGEMENT ------------
|
|
998
|
+
//----------------- GIT COMMAND EXECUTION AND WORKTREE MANAGEMENT ------------
|
|
767
999
|
/**
|
|
768
1000
|
* Captured output of one completed `git` invocation.
|
|
769
1001
|
*
|
|
770
|
-
* Returned by `GitCommandRunner` implementations so
|
|
771
|
-
* both streams without caring about
|
|
1002
|
+
* Returned by `GitCommandRunner` and `GitProcessRunner` implementations so the
|
|
1003
|
+
* git and worktree services can read both streams without caring about
|
|
1004
|
+
* process plumbing.
|
|
772
1005
|
*/
|
|
773
1006
|
export type GitCommandResult = {
|
|
774
1007
|
stdout: string;
|
|
@@ -785,6 +1018,20 @@ export type GitCommandResult = {
|
|
|
785
1018
|
*/
|
|
786
1019
|
export type GitCommandRunner = (args: string[], cwd: string) => Promise<GitCommandResult>;
|
|
787
1020
|
|
|
1021
|
+
/**
|
|
1022
|
+
* Executes `command args...` inside `options.cwd` and resolves with the captured output.
|
|
1023
|
+
*
|
|
1024
|
+
* This is the `spawnAsync` shape the Git routes module injects into its typed
|
|
1025
|
+
* services (branch deletion, branch compare) so their tests can substitute a
|
|
1026
|
+
* fake runner. Like `GitCommandRunner`, the promise must reject on a non-zero
|
|
1027
|
+
* exit code, with `stderr` attached to the error when available.
|
|
1028
|
+
*/
|
|
1029
|
+
export type GitProcessRunner = (
|
|
1030
|
+
command: string,
|
|
1031
|
+
args: string[],
|
|
1032
|
+
options: { cwd: string },
|
|
1033
|
+
) => Promise<GitCommandResult>;
|
|
1034
|
+
|
|
788
1035
|
/**
|
|
789
1036
|
* One entry parsed from `git worktree list --porcelain`.
|
|
790
1037
|
*
|
|
@@ -1108,6 +1355,13 @@ export type FileTreeProjectGateway = {
|
|
|
1108
1355
|
export type FileTreeWorkspaceGateway = {
|
|
1109
1356
|
rootPath: string;
|
|
1110
1357
|
validatePath(candidatePath: string): Promise<WorkspacePathValidationResult>;
|
|
1358
|
+
/**
|
|
1359
|
+
* Resolves a path readable outside the workspace root — the system temp
|
|
1360
|
+
* directory and the Claude projects directory — or `null` when it is not
|
|
1361
|
+
* one. Read-only: the write policy is `validatePath` and it does not consult
|
|
1362
|
+
* this.
|
|
1363
|
+
*/
|
|
1364
|
+
resolveReadOnlyRootPath(candidatePath: string): Promise<string | null>;
|
|
1111
1365
|
};
|
|
1112
1366
|
|
|
1113
1367
|
/**
|