@cloudcli-ai/cloudcli 1.37.2 → 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 +269 -0
- package/dist/assets/{abnfDiagram-N423BO3Z-C4UAoHJb.js → abnfDiagram-N423BO3Z-Dmkwx38H.js} +1 -1
- package/dist/assets/{arc-B8jF-ja9.js → arc-DLe9AYuO.js} +1 -1
- package/dist/assets/{architectureDiagram-T3A2C74G-C_Wur_CU.js → architectureDiagram-T3A2C74G-CBbbbNUW.js} +1 -1
- package/dist/assets/{blockDiagram-VBNYF7ZC-Cq4P1i8t.js → blockDiagram-VBNYF7ZC-CaMEaWu4.js} +1 -1
- package/dist/assets/{c4Diagram-5PPSVZJV-C1wG4eUj.js → c4Diagram-5PPSVZJV-DhjMgNnR.js} +1 -1
- package/dist/assets/channel-CWrmwsir.js +1 -0
- package/dist/assets/{chunk-2GRJ4B5K-B8fnBG6E.js → chunk-2GRJ4B5K-yjl3-F-i.js} +1 -1
- package/dist/assets/{chunk-2Q5K7J3B-WdfPooPJ.js → chunk-2Q5K7J3B-DsAYaWEP.js} +1 -1
- package/dist/assets/{chunk-5RXB4S5H-DhZJuG2E.js → chunk-5RXB4S5H-Bt5qmqOX.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-B0rjslal.js → chunk-5VM5RSS4-yWrWVvUt.js} +1 -1
- package/dist/assets/{chunk-6Q2QTUOP-CG2Oj4jL.js → chunk-6Q2QTUOP-Dt66K5xb.js} +1 -1
- package/dist/assets/{chunk-GF5L2VYU-rrl2lRxY.js → chunk-GF5L2VYU-DA0vzaj4.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-CjVbrVMA.js → chunk-JWPE2WC7-CUkbx96V.js} +1 -1
- package/dist/assets/{chunk-KBJHAD2P-CRzKgU8S.js → chunk-KBJHAD2P-DWKxx1WH.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-DBz4GTZF.js → chunk-RYQCIY6F-BqluplN0.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-wHxalsXk.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-s1hygY8e.js → cose-bilkent-JH36ORCC-DHV93-Em.js} +1 -1
- package/dist/assets/{cynefin-VYW2F7L2-C4LGV15i.js → cynefin-VYW2F7L2-B9HZgoGX.js} +1 -1
- package/dist/assets/{cynefinDiagram-MW4NZA55-C5uhu7B3.js → cynefinDiagram-MW4NZA55-hFjjEQg8.js} +1 -1
- package/dist/assets/{dagre-VZM6K2ZE-B-OBTewm.js → dagre-VZM6K2ZE-CpeVOC7V.js} +1 -1
- package/dist/assets/{diagram-7IWD3JNH-BjGKQxih.js → diagram-7IWD3JNH-D0H1UoRA.js} +1 -1
- package/dist/assets/{diagram-B4RE2ZJO-BMKz1X2L.js → diagram-B4RE2ZJO-6Y7BQUup.js} +1 -1
- package/dist/assets/{diagram-LBJQPF4R-DNh-GhKC.js → diagram-LBJQPF4R-C0nNOwht.js} +1 -1
- package/dist/assets/{diagram-Q27KOJAE-BaTG9jPT.js → diagram-Q27KOJAE-En6QlOVX.js} +1 -1
- package/dist/assets/{diagram-UB23O5K3-BUwo2OvJ.js → diagram-UB23O5K3-CmPiNeGD.js} +1 -1
- package/dist/assets/{ebnfDiagram-BXEA7PRR-DAZgfzX2.js → ebnfDiagram-BXEA7PRR-Bygzp1Qt.js} +1 -1
- package/dist/assets/{erDiagram-JOGREHBK-1w1CcGEb.js → erDiagram-JOGREHBK-CwScRfzl.js} +1 -1
- package/dist/assets/{flowDiagram-UKHOOZJN-D4EII8Jj.js → flowDiagram-UKHOOZJN-bKX-0xP6.js} +1 -1
- package/dist/assets/{ganttDiagram-PKOTCBZU-ChvJZAgB.js → ganttDiagram-PKOTCBZU-DtZPKXGd.js} +1 -1
- package/dist/assets/{gitGraphDiagram-DS77QQ5N-DtOn41S8.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-DN_PVEJZ.js → infoDiagram-6WML65LV-ciRQTS0h.js} +1 -1
- package/dist/assets/{ishikawaDiagram-WSZJBQD7-DbkF1kXb.js → ishikawaDiagram-WSZJBQD7-CgjhQZ84.js} +1 -1
- package/dist/assets/{journeyDiagram-NVQOT4AX-pJwmhddE.js → journeyDiagram-NVQOT4AX-BsbQSeIW.js} +1 -1
- package/dist/assets/{kanban-definition-27J2QSJJ-PPAPgNp5.js → kanban-definition-27J2QSJJ-CrwzY9Jw.js} +1 -1
- package/dist/assets/{linear-iPR-J9f7.js → linear-BUaCDr6l.js} +1 -1
- package/dist/assets/{mermaid.core-BEUL86Z6.js → mermaid.core-ClgdUU0j.js} +5 -5
- package/dist/assets/{mindmap-definition-FAOFIHXS-BvZoBib7.js → mindmap-definition-FAOFIHXS-BictljY1.js} +1 -1
- package/dist/assets/{pegDiagram-VL7TDLO6-DhYreaUd.js → pegDiagram-VL7TDLO6-BXdByy_U.js} +1 -1
- package/dist/assets/{pieDiagram-7S7Q4E2Y-CrOHlyD0.js → pieDiagram-7S7Q4E2Y-uZsMfkRX.js} +1 -1
- package/dist/assets/{quadrantDiagram-CIZ2JOQS-D4g5yH3t.js → quadrantDiagram-CIZ2JOQS-7lCv4QIj.js} +1 -1
- package/dist/assets/{railroadDiagram-AXF67PYL-Dj39lHlf.js → railroadDiagram-AXF67PYL-07dxIWbi.js} +1 -1
- package/dist/assets/{requirementDiagram-LRYGKXZP-1AS4Zgm_.js → requirementDiagram-LRYGKXZP-Cb31Yv1_.js} +1 -1
- package/dist/assets/{sankeyDiagram-W5VNT64P-CKlMn19P.js → sankeyDiagram-W5VNT64P-X0YPSyF9.js} +1 -1
- package/dist/assets/{sequenceDiagram-SI44F4Z6-B_j3qyvo.js → sequenceDiagram-SI44F4Z6-BdBxSIlP.js} +1 -1
- package/dist/assets/server.browser-CtX3Hdl5.js +27 -0
- package/dist/assets/{sizeCapture-X5ZJPWSS-Bp2Op16v.js → sizeCapture-X5ZJPWSS-DQM5xAyD.js} +1 -1
- package/dist/assets/{stateDiagram-OKZ733FA-C0cN6DoY.js → stateDiagram-OKZ733FA-DJ3xkLUF.js} +1 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-vAaE4zNo.js +1 -0
- package/dist/assets/{swimlanes-SLNWSIFB-BEvXOV9b.js → swimlanes-SLNWSIFB-rjfYdW0w.js} +2 -2
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-TV2IF4Nq.js +8 -0
- package/dist/assets/{timeline-definition-Z64GVDOM-zdJQinvZ.js → timeline-definition-Z64GVDOM-DZMra5do.js} +1 -1
- package/dist/assets/{vendor-codemirror-OwyKSvPE.js → vendor-codemirror-CYrSt7-U.js} +18 -18
- package/dist/assets/{vennDiagram-T6HMQDX7-DuF1uZMY.js → vennDiagram-T6HMQDX7-BevD8uu0.js} +1 -1
- package/dist/assets/{wardleyDiagram-T6FBY63Y-B9AlLQup.js → wardleyDiagram-T6FBY63Y-DsIyXB7z.js} +1 -1
- package/dist/assets/{xychartDiagram-ELKLHX3M-DTJX48Qg.js → xychartDiagram-ELKLHX3M-G3PlF3ko.js} +1 -1
- package/dist/index.html +3 -3
- package/dist-server/server/index.js +11 -4
- 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 +177 -130
- 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 +48 -2
- package/dist-server/server/modules/agent/tests/agent.routes.test.js.map +1 -1
- package/dist-server/server/modules/browser-use/browser-use.routes.js +39 -33
- package/dist-server/server/modules/browser-use/browser-use.routes.js.map +1 -1
- package/dist-server/server/modules/database/connection.js +1 -1
- package/dist-server/server/modules/database/connection.js.map +1 -1
- package/dist-server/server/modules/database/index.js +5 -0
- package/dist-server/server/modules/database/index.js.map +1 -1
- package/dist-server/server/modules/database/migrations.js +45 -1
- 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/scheduled-messages.db.js +71 -0
- package/dist-server/server/modules/database/repositories/scheduled-messages.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/session-drafts.db.js +105 -0
- package/dist-server/server/modules/database/repositories/session-drafts.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js +144 -5
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
- package/dist-server/server/modules/database/repositories/user-preferences.db.js +65 -0
- package/dist-server/server/modules/database/repositories/user-preferences.db.js.map +1 -0
- package/dist-server/server/modules/database/schema.js +99 -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/database/tests/sessions.db.integration.test.js +39 -0
- package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -1
- package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js +105 -0
- package/dist-server/server/modules/database/tests/user-preferences.db.integration.test.js.map +1 -0
- 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/services/project-delete.service.js +12 -1
- package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -1
- package/dist-server/server/modules/projects/services/project-star.service.js +2 -2
- package/dist-server/server/modules/projects/services/project-star.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/index.js +3 -0
- package/dist-server/server/modules/providers/index.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +62 -9
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js +46 -0
- package/dist-server/server/modules/providers/list/claude/claude-fork.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +31 -12
- 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 +472 -53
- 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 +1007 -60
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +4 -1
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js +204 -0
- package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js +32 -0
- package/dist-server/server/modules/providers/list/codex/codex-fork.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +47 -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 +71 -53
- package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +8 -0
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +1621 -431
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
- package/dist-server/server/modules/providers/list/codex/codex.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 +16 -8
- package/dist-server/server/modules/providers/list/cursor/cursor-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +274 -9
- 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 +134 -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 +23 -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/provider-token-usage.service.js +139 -35
- package/dist-server/server/modules/providers/services/provider-token-usage.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 +91 -0
- package/dist-server/server/modules/providers/services/session-history-cache.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js +105 -32
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js +3 -60
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions.service.js +252 -12
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/tests/claude-auth.test.js +183 -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-models.test.js +39 -0
- package/dist-server/server/modules/providers/tests/claude-models.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 +1815 -33
- 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/claude-subagent-echo.test.js +16 -0
- package/dist-server/server/modules/providers/tests/claude-subagent-echo.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/claude-token-budget.test.js +85 -0
- package/dist-server/server/modules/providers/tests/claude-token-budget.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/codex-message-editing.test.js +338 -0
- package/dist-server/server/modules/providers/tests/codex-message-editing.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 +83 -0
- package/dist-server/server/modules/providers/tests/codex-runtime.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/codex-session-fork.test.js +54 -0
- package/dist-server/server/modules/providers/tests/codex-session-fork.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js +354 -15
- 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 +196 -4
- 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-token-usage.service.test.js +164 -1
- package/dist-server/server/modules/providers/tests/provider-token-usage.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-fork.test.js +113 -0
- package/dist-server/server/modules/providers/tests/session-fork.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js +139 -0
- package/dist-server/server/modules/providers/tests/session-history-cache.service.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js +90 -0
- package/dist-server/server/modules/providers/tests/session-orphan-prune.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js +122 -0
- package/dist-server/server/modules/providers/tests/session-synchronizer-coalescing.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/sessions.service.test.js +219 -1
- package/dist-server/server/modules/providers/tests/sessions.service.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/skills.test.js +15 -3
- package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
- package/dist-server/server/modules/scheduled-messages/index.js +5 -0
- package/dist-server/server/modules/scheduled-messages/index.js.map +1 -0
- package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js +47 -0
- package/dist-server/server/modules/scheduled-messages/scheduled-messages.routes.js.map +1 -0
- package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js +175 -0
- package/dist-server/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.js.map +1 -0
- package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js +95 -0
- package/dist-server/server/modules/scheduled-messages/services/scheduled-messages.service.js.map +1 -0
- package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js +290 -0
- package/dist-server/server/modules/scheduled-messages/tests/scheduled-messages.test.js.map +1 -0
- package/dist-server/server/modules/taskmaster/taskmaster.routes.js +23 -23
- package/dist-server/server/modules/taskmaster/taskmaster.routes.js.map +1 -1
- package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js +48 -0
- package/dist-server/server/modules/taskmaster/tests/taskmaster.routes.test.js.map +1 -1
- package/dist-server/server/modules/user/tests/user.service.test.js +70 -0
- package/dist-server/server/modules/user/tests/user.service.test.js.map +1 -1
- package/dist-server/server/modules/user/user.module.js +10 -1
- package/dist-server/server/modules/user/user.module.js.map +1 -1
- package/dist-server/server/modules/user/user.routes.js +44 -0
- package/dist-server/server/modules/user/user.routes.js.map +1 -1
- package/dist-server/server/modules/user/user.service.js +75 -0
- package/dist-server/server/modules/user/user.service.js.map +1 -1
- package/dist-server/server/modules/voice/tests/voice.service.test.js +3 -2
- package/dist-server/server/modules/voice/tests/voice.service.test.js.map +1 -1
- package/dist-server/server/modules/websocket/index.js +7 -0
- package/dist-server/server/modules/websocket/index.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +37 -49
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +35 -5
- package/dist-server/server/modules/websocket/services/chat-session-writer.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +204 -10
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js +94 -0
- package/dist-server/server/modules/websocket/services/session-upsert-broadcast.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +236 -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-edit-send.test.js +263 -0
- package/dist-server/server/modules/websocket/tests/chat-edit-send.test.js.map +1 -0
- package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +29 -3
- package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -1
- 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/session-upsert-broadcast.test.js +106 -0
- package/dist-server/server/modules/websocket/tests/session-upsert-broadcast.test.js.map +1 -0
- package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js +500 -0
- package/dist-server/server/modules/websocket/tests/shell-websocket.service.test.js.map +1 -1
- package/dist-server/server/shared/claude-cli-path.js +22 -5
- package/dist-server/server/shared/claude-cli-path.js.map +1 -1
- package/dist-server/server/shared/index.js +3 -0
- package/dist-server/server/shared/index.js.map +1 -0
- package/dist-server/server/shared/message-unification.js +376 -0
- package/dist-server/server/shared/message-unification.js.map +1 -0
- package/dist-server/server/shared/tests/claude-cli-path.test.js +45 -1
- package/dist-server/server/shared/tests/claude-cli-path.test.js.map +1 -1
- package/dist-server/server/shared/tests/message-unification.test.js +174 -0
- package/dist-server/server/shared/tests/message-unification.test.js.map +1 -0
- 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 +160 -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 +20 -17
- package/server/index.ts +16 -5
- package/server/modules/agent/agent.module.ts +11 -1
- package/server/modules/agent/agent.routes.ts +200 -142
- package/server/modules/agent/tests/agent-run-registration.test.ts +348 -0
- package/server/modules/agent/tests/agent.routes.test.ts +51 -2
- package/server/modules/browser-use/browser-use.routes.ts +96 -33
- package/server/modules/database/connection.ts +2 -1
- package/server/modules/database/index.ts +10 -0
- package/server/modules/database/migrations.ts +51 -0
- package/server/modules/database/repositories/provider-models.ts +79 -6
- package/server/modules/database/repositories/scheduled-messages.db.ts +127 -0
- package/server/modules/database/repositories/session-drafts.db.ts +171 -0
- package/server/modules/database/repositories/sessions.db.ts +204 -3
- package/server/modules/database/repositories/user-preferences.db.ts +80 -0
- package/server/modules/database/schema.ts +103 -0
- package/server/modules/database/tests/provider-models.db.integration.test.ts +113 -0
- package/server/modules/database/tests/sessions.db.integration.test.ts +52 -0
- package/server/modules/database/tests/user-preferences.db.integration.test.ts +135 -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/services/project-delete.service.ts +13 -1
- package/server/modules/projects/services/project-star.service.ts +2 -2
- 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/index.ts +4 -0
- package/server/modules/providers/list/claude/claude-auth.provider.ts +81 -11
- package/server/modules/providers/list/claude/claude-fork.provider.ts +57 -0
- package/server/modules/providers/list/claude/claude-models.provider.ts +37 -17
- package/server/modules/providers/list/claude/claude-runtime.provider.js +510 -54
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +40 -14
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +1195 -63
- package/server/modules/providers/list/claude/claude-skills.provider.ts +4 -1
- package/server/modules/providers/list/claude/claude.provider.ts +3 -0
- package/server/modules/providers/list/codex/codex-app-server.client.ts +243 -0
- package/server/modules/providers/list/codex/codex-fork.provider.ts +40 -0
- package/server/modules/providers/list/codex/codex-models.provider.ts +47 -0
- package/server/modules/providers/list/codex/{codex-runtime.provider.js → codex-runtime.provider.ts} +105 -70
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +9 -0
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +1847 -455
- package/server/modules/providers/list/codex/codex.provider.ts +3 -0
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +10 -2
- package/server/modules/providers/list/cursor/cursor-runtime.provider.js +17 -8
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +0 -1
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +297 -9
- 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 +162 -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 +40 -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/provider-token-usage.service.ts +166 -39
- package/server/modules/providers/services/session-conversations-search.service.ts +2 -5
- package/server/modules/providers/services/session-history-cache.service.ts +150 -0
- package/server/modules/providers/services/session-synchronizer.service.ts +125 -38
- package/server/modules/providers/services/sessions-watcher.service.ts +3 -64
- package/server/modules/providers/services/sessions.service.ts +309 -17
- package/server/modules/providers/tests/claude-auth.test.ts +208 -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-models.test.ts +87 -0
- package/server/modules/providers/tests/claude-runtime-hold.test.ts +309 -0
- package/server/modules/providers/tests/claude-sessions.test.ts +2167 -37
- package/server/modules/providers/tests/claude-settings-permissions.test.ts +271 -0
- package/server/modules/providers/tests/claude-subagent-echo.test.ts +25 -0
- package/server/modules/providers/tests/claude-token-budget.test.ts +104 -0
- package/server/modules/providers/tests/codex-message-editing.test.ts +419 -0
- package/server/modules/providers/tests/codex-models.test.ts +37 -0
- package/server/modules/providers/tests/codex-runtime.test.ts +94 -0
- package/server/modules/providers/tests/codex-session-fork.test.ts +59 -0
- package/server/modules/providers/tests/codex-sessions.test.ts +396 -15
- package/server/modules/providers/tests/cursor-auth.test.ts +187 -0
- package/server/modules/providers/tests/opencode-models.test.ts +266 -8
- 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-token-usage.service.test.ts +188 -1
- package/server/modules/providers/tests/provider.routes.test.ts +230 -1
- package/server/modules/providers/tests/session-fork.test.ts +173 -0
- package/server/modules/providers/tests/session-history-cache.service.test.ts +165 -0
- package/server/modules/providers/tests/session-orphan-prune.test.ts +107 -0
- package/server/modules/providers/tests/session-synchronizer-coalescing.test.ts +136 -0
- package/server/modules/providers/tests/sessions.service.test.ts +303 -1
- package/server/modules/providers/tests/skills.test.ts +21 -5
- package/server/modules/scheduled-messages/index.ts +8 -0
- package/server/modules/scheduled-messages/scheduled-messages.routes.ts +68 -0
- package/server/modules/scheduled-messages/services/scheduled-message-dispatcher.service.ts +216 -0
- package/server/modules/scheduled-messages/services/scheduled-messages.service.ts +121 -0
- package/server/modules/scheduled-messages/tests/scheduled-messages.test.ts +354 -0
- package/server/modules/taskmaster/taskmaster.routes.ts +23 -33
- package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +57 -0
- package/server/modules/user/tests/user.service.test.ts +90 -0
- package/server/modules/user/user.module.ts +10 -1
- package/server/modules/user/user.routes.ts +44 -0
- package/server/modules/user/user.service.ts +105 -0
- package/server/modules/voice/tests/voice.service.test.ts +3 -2
- package/server/modules/websocket/README.md +4 -2
- package/server/modules/websocket/index.ts +8 -0
- package/server/modules/websocket/services/chat-run-registry.service.ts +45 -54
- package/server/modules/websocket/services/chat-session-writer.service.ts +36 -6
- package/server/modules/websocket/services/chat-websocket.service.ts +302 -16
- package/server/modules/websocket/services/session-upsert-broadcast.service.ts +108 -0
- package/server/modules/websocket/services/shell-websocket.service.ts +276 -22
- package/server/modules/websocket/tests/chat-background-subscribe.test.ts +167 -0
- package/server/modules/websocket/tests/chat-edit-send.test.ts +309 -0
- package/server/modules/websocket/tests/chat-run-registry.test.ts +34 -3
- package/server/modules/websocket/tests/chat-stop-task.test.ts +127 -0
- package/server/modules/websocket/tests/session-upsert-broadcast.test.ts +138 -0
- package/server/modules/websocket/tests/shell-websocket.service.test.ts +629 -0
- package/server/shared/claude-cli-path.ts +24 -6
- package/server/shared/index.ts +3 -0
- package/server/shared/interfaces.ts +91 -0
- package/server/shared/message-unification.ts +449 -0
- package/server/shared/tests/claude-cli-path.test.ts +58 -1
- package/server/shared/tests/message-unification.test.ts +218 -0
- 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 +382 -7
- package/server/shared/utils.ts +176 -0
- package/dist/assets/channel-_falYbU1.js +0 -1
- package/dist/assets/classDiagram-JCYQIIEL-Dn-3CfpR.js +0 -1
- package/dist/assets/classDiagram-v2-OCEON4UE-Dn-3CfpR.js +0 -1
- package/dist/assets/index-CzPLBvXT.css +0 -32
- package/dist/assets/index-DFkBBuSA.js +0 -1549
- package/dist/assets/stateDiagram-v2-UEYNNEHI-BvBxUUrZ.js +0 -1
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-CsE-x4YK.js +0 -8
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import express, { type Request, type Response } from 'express';
|
|
2
2
|
|
|
3
3
|
import { providerAuthService } from '@/modules/providers/services/provider-auth.service.js';
|
|
4
|
+
import { claudeSettingsPermissionsService } from '@/modules/providers/services/claude-settings-permissions.service.js';
|
|
4
5
|
import { providerCapabilitiesService } from '@/modules/providers/services/provider-capabilities.service.js';
|
|
5
6
|
import { providerMcpService } from '@/modules/providers/services/mcp.service.js';
|
|
6
7
|
import { providerModelsService } from '@/modules/providers/services/provider-models.service.js';
|
|
@@ -9,6 +10,7 @@ import { providerSkillsService } from '@/modules/providers/services/skills.servi
|
|
|
9
10
|
import { sessionConversationsSearchService } from '@/modules/providers/services/session-conversations-search.service.js';
|
|
10
11
|
import { sessionsService } from '@/modules/providers/services/sessions.service.js';
|
|
11
12
|
import type {
|
|
13
|
+
CustomProviderModelEffort,
|
|
12
14
|
CustomProviderModelInput,
|
|
13
15
|
LLMProvider,
|
|
14
16
|
McpScope,
|
|
@@ -53,6 +55,35 @@ const parseSessionId = (value: unknown): string => {
|
|
|
53
55
|
return sessionId;
|
|
54
56
|
};
|
|
55
57
|
|
|
58
|
+
/** A workflow run id as the harness mints one (`wf_16fbf852-274`). */
|
|
59
|
+
const WORKFLOW_RUN_ID_PATTERN = /^wf_[A-Za-z0-9-]+$/;
|
|
60
|
+
/** A workflow agent id as the CLI mints one: `a` and sixteen hex digits. */
|
|
61
|
+
const WORKFLOW_AGENT_ID_PATTERN = /^a[0-9a-f]{16}$/;
|
|
62
|
+
|
|
63
|
+
// Both ids name a file under the session's transcript directory, so nothing
|
|
64
|
+
// outside these shapes may reach the filesystem.
|
|
65
|
+
const parseWorkflowRunId = (value: unknown): string => {
|
|
66
|
+
const runId = readPathParam(value, 'runId');
|
|
67
|
+
if (!WORKFLOW_RUN_ID_PATTERN.test(runId)) {
|
|
68
|
+
throw new AppError('Invalid workflow run id.', {
|
|
69
|
+
code: 'INVALID_WORKFLOW_RUN_ID',
|
|
70
|
+
statusCode: 400,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return runId;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const parseWorkflowAgentId = (value: unknown): string => {
|
|
77
|
+
const agentId = readPathParam(value, 'agentId');
|
|
78
|
+
if (!WORKFLOW_AGENT_ID_PATTERN.test(agentId)) {
|
|
79
|
+
throw new AppError('Invalid workflow agent id.', {
|
|
80
|
+
code: 'INVALID_WORKFLOW_AGENT_ID',
|
|
81
|
+
statusCode: 400,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return agentId;
|
|
85
|
+
};
|
|
86
|
+
|
|
56
87
|
const readOptionalQueryString = (value: unknown): string | undefined => {
|
|
57
88
|
if (typeof value !== 'string') {
|
|
58
89
|
return undefined;
|
|
@@ -297,6 +328,28 @@ const parseProvider = (value: unknown): LLMProvider => {
|
|
|
297
328
|
});
|
|
298
329
|
};
|
|
299
330
|
|
|
331
|
+
/** Both fields are optional: an empty body forks the whole conversation. */
|
|
332
|
+
const parseSessionForkPayload = (payload: unknown): { upToAnchorId?: string; title?: string } => {
|
|
333
|
+
if (payload === undefined || payload === null) {
|
|
334
|
+
return {};
|
|
335
|
+
}
|
|
336
|
+
if (typeof payload !== 'object') {
|
|
337
|
+
throw new AppError('Request body must be an object.', {
|
|
338
|
+
code: 'INVALID_REQUEST_BODY',
|
|
339
|
+
statusCode: 400,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const body = payload as Record<string, unknown>;
|
|
344
|
+
const upToAnchorId = typeof body.upToAnchorId === 'string' ? body.upToAnchorId.trim() : '';
|
|
345
|
+
const title = typeof body.title === 'string' ? body.title.trim() : '';
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
...(upToAnchorId ? { upToAnchorId } : {}),
|
|
349
|
+
...(title ? { title } : {}),
|
|
350
|
+
};
|
|
351
|
+
};
|
|
352
|
+
|
|
300
353
|
const parseSessionRenameSummary = (payload: unknown): string => {
|
|
301
354
|
if (!payload || typeof payload !== 'object') {
|
|
302
355
|
throw new AppError('Request body must be an object.', {
|
|
@@ -443,6 +496,78 @@ const parseModelRecordId = (value: unknown): number => {
|
|
|
443
496
|
return recordId;
|
|
444
497
|
};
|
|
445
498
|
|
|
499
|
+
const invalidModelEffort = (message: string): AppError => new AppError(message, {
|
|
500
|
+
code: 'INVALID_MODEL_EFFORT',
|
|
501
|
+
statusCode: 400,
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Upper bound on declared effort levels, far above any provider's level set.
|
|
506
|
+
* Checked before the per-entry loop so an oversized body (the JSON parser
|
|
507
|
+
* accepts up to 50 MB) is rejected at once instead of being walked in full.
|
|
508
|
+
*/
|
|
509
|
+
const MAX_MODEL_EFFORT_LEVELS = 32;
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Parses the optional `effort` field of a custom-model payload.
|
|
513
|
+
*
|
|
514
|
+
* Only the shape is checked here (unique, trimmed, non-empty level ids and a
|
|
515
|
+
* default drawn from them); which levels a provider accepts is decided by the
|
|
516
|
+
* Providers service. `undefined` means "not sent" and `null` or an empty
|
|
517
|
+
* `values` list means "no effort levels".
|
|
518
|
+
*/
|
|
519
|
+
const parseCustomProviderModelEffort = (
|
|
520
|
+
value: unknown,
|
|
521
|
+
): CustomProviderModelEffort | null | undefined => {
|
|
522
|
+
if (value === undefined) {
|
|
523
|
+
return undefined;
|
|
524
|
+
}
|
|
525
|
+
if (value === null) {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
529
|
+
throw invalidModelEffort('effort must be an object with a values array.');
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const effort = value as Record<string, unknown>;
|
|
533
|
+
if (!Array.isArray(effort.values)) {
|
|
534
|
+
throw invalidModelEffort('effort.values must be an array of effort levels.');
|
|
535
|
+
}
|
|
536
|
+
if (effort.values.length > MAX_MODEL_EFFORT_LEVELS) {
|
|
537
|
+
throw invalidModelEffort(`effort.values can list at most ${MAX_MODEL_EFFORT_LEVELS} effort levels.`);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const values: string[] = [];
|
|
541
|
+
const seenLevels = new Set<string>();
|
|
542
|
+
for (const entry of effort.values) {
|
|
543
|
+
const level = typeof entry === 'string' ? entry.trim() : '';
|
|
544
|
+
if (!level || level.length > 40) {
|
|
545
|
+
throw invalidModelEffort('effort.values must contain non-empty strings of 40 characters or fewer.');
|
|
546
|
+
}
|
|
547
|
+
if (seenLevels.has(level)) {
|
|
548
|
+
throw invalidModelEffort(`effort.values contains "${level}" more than once.`);
|
|
549
|
+
}
|
|
550
|
+
seenLevels.add(level);
|
|
551
|
+
values.push(level);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (effort.default !== undefined && effort.default !== null && typeof effort.default !== 'string') {
|
|
555
|
+
throw invalidModelEffort('effort.default must be a string.');
|
|
556
|
+
}
|
|
557
|
+
const defaultLevel = readOptionalQueryString(effort.default);
|
|
558
|
+
if (values.length === 0) {
|
|
559
|
+
if (defaultLevel) {
|
|
560
|
+
throw invalidModelEffort('effort.default requires at least one effort level.');
|
|
561
|
+
}
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
if (defaultLevel && !values.includes(defaultLevel)) {
|
|
565
|
+
throw invalidModelEffort('effort.default must be one of effort.values.');
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return defaultLevel ? { values, default: defaultLevel } : { values };
|
|
569
|
+
};
|
|
570
|
+
|
|
446
571
|
const parseCustomProviderModelPayload = (payload: unknown): CustomProviderModelInput => {
|
|
447
572
|
if (!payload || typeof payload !== 'object') {
|
|
448
573
|
throw new AppError('Request body must be an object.', {
|
|
@@ -479,7 +604,8 @@ const parseCustomProviderModelPayload = (payload: unknown): CustomProviderModelI
|
|
|
479
604
|
});
|
|
480
605
|
}
|
|
481
606
|
|
|
482
|
-
|
|
607
|
+
const effort = parseCustomProviderModelEffort(body.effort);
|
|
608
|
+
return effort === undefined ? { model, id } : { model, id, effort };
|
|
483
609
|
};
|
|
484
610
|
|
|
485
611
|
router.get(
|
|
@@ -695,6 +821,15 @@ router.get(
|
|
|
695
821
|
}),
|
|
696
822
|
);
|
|
697
823
|
|
|
824
|
+
// Read-only: the rules Claude's own settings files add on top of the UI's lists.
|
|
825
|
+
router.get(
|
|
826
|
+
'/claude/settings-permissions',
|
|
827
|
+
asyncHandler(async (_req: Request, res: Response) => {
|
|
828
|
+
const sources = await claudeSettingsPermissionsService.listRuleSources();
|
|
829
|
+
res.json(createApiSuccessResponse({ sources }));
|
|
830
|
+
}),
|
|
831
|
+
);
|
|
832
|
+
|
|
698
833
|
// ----------------- Session routes -----------------
|
|
699
834
|
/**
|
|
700
835
|
* Session gateway entry point: allocates the stable app-facing session id for
|
|
@@ -717,7 +852,7 @@ router.post(
|
|
|
717
852
|
router.get(
|
|
718
853
|
'/sessions/running',
|
|
719
854
|
asyncHandler(async (_req: Request, res: Response) => {
|
|
720
|
-
const sessions = sessionsService.listRunningSessions();
|
|
855
|
+
const sessions = await sessionsService.listRunningSessions();
|
|
721
856
|
res.json(createApiSuccessResponse({ sessions }));
|
|
722
857
|
}),
|
|
723
858
|
);
|
|
@@ -792,6 +927,15 @@ router.post(
|
|
|
792
927
|
}),
|
|
793
928
|
);
|
|
794
929
|
|
|
930
|
+
router.post(
|
|
931
|
+
'/sessions/:sessionId/fork',
|
|
932
|
+
asyncHandler(async (req: Request, res: Response) => {
|
|
933
|
+
const sessionId = parseSessionId(req.params.sessionId);
|
|
934
|
+
const result = await sessionsService.forkSessionById(sessionId, parseSessionForkPayload(req.body));
|
|
935
|
+
res.status(201).json(createApiSuccessResponse(result));
|
|
936
|
+
}),
|
|
937
|
+
);
|
|
938
|
+
|
|
795
939
|
router.put(
|
|
796
940
|
'/sessions/:sessionId',
|
|
797
941
|
asyncHandler(async (req: Request, res: Response) => {
|
|
@@ -817,6 +961,22 @@ router.get(
|
|
|
817
961
|
}),
|
|
818
962
|
);
|
|
819
963
|
|
|
964
|
+
/**
|
|
965
|
+
* One workflow agent's timeline, read on demand when its row in the workflow
|
|
966
|
+
* card is opened. History does not carry it: a run can spawn a dozen agents
|
|
967
|
+
* with hundreds of tool calls each, and the card only lists them.
|
|
968
|
+
*/
|
|
969
|
+
router.get(
|
|
970
|
+
'/sessions/:sessionId/workflows/:runId/agents/:agentId',
|
|
971
|
+
asyncHandler(async (req: Request, res: Response) => {
|
|
972
|
+
const sessionId = parseSessionId(req.params.sessionId);
|
|
973
|
+
const runId = parseWorkflowRunId(req.params.runId);
|
|
974
|
+
const agentId = parseWorkflowAgentId(req.params.agentId);
|
|
975
|
+
const result = await sessionsService.readWorkflowAgentActivity(sessionId, runId, agentId);
|
|
976
|
+
res.json(createApiSuccessResponse(result));
|
|
977
|
+
}),
|
|
978
|
+
);
|
|
979
|
+
|
|
820
980
|
router.get('/search/sessions', asyncHandler(async (req: Request, res: Response) => {
|
|
821
981
|
const query = parseSessionSearchQuery(req.query.q);
|
|
822
982
|
const limit = parseSessionSearchLimit(req.query.limit);
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One Claude CLI process that is currently producing a response.
|
|
7
|
+
*
|
|
8
|
+
* `providerSessionId` is Claude's own session id, which is what the registry
|
|
9
|
+
* records; callers map it onto an app session themselves.
|
|
10
|
+
*/
|
|
11
|
+
type LiveClaudeCliSession = {
|
|
12
|
+
providerSessionId: string;
|
|
13
|
+
startedAt: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Claude Code keeps one file per running session here, named `<pid>.json`.
|
|
18
|
+
* The directory belongs to the CLI, not to CloudCLI: it is only ever read.
|
|
19
|
+
*/
|
|
20
|
+
const registryDirectory = () => path.join(os.homedir(), '.claude', 'sessions');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Upper bound on registry files inspected per poll.
|
|
24
|
+
*
|
|
25
|
+
* The running-sessions endpoint is polled continuously, so a directory left
|
|
26
|
+
* full of stale files by repeated crashes must not turn every poll into
|
|
27
|
+
* unbounded filesystem work. Real installations hold a handful of entries.
|
|
28
|
+
*/
|
|
29
|
+
const MAX_REGISTRY_FILES = 256;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether `pid` is still the process the registry recorded.
|
|
33
|
+
*
|
|
34
|
+
* A registry file outlives a crash, so its mere presence proves nothing. The
|
|
35
|
+
* signal-0 probe answers "does this pid exist" (EPERM means it exists but is
|
|
36
|
+
* owned by someone else, which still counts), and on Linux the recorded
|
|
37
|
+
* `procStart` is compared against the kernel's start-time for that pid so a
|
|
38
|
+
* reused pid cannot be mistaken for the original process.
|
|
39
|
+
*/
|
|
40
|
+
async function isRecordedProcessAlive(pid: number, procStart: unknown): Promise<boolean> {
|
|
41
|
+
try {
|
|
42
|
+
process.kill(pid, 0);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if ((error as NodeJS.ErrnoException)?.code !== 'EPERM') {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (process.platform !== 'linux' || typeof procStart !== 'string' || !procStart) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const stat = await fsp.readFile(`/proc/${pid}/stat`, 'utf8');
|
|
55
|
+
// The comm field is parenthesised and may itself contain spaces, so the
|
|
56
|
+
// fields are counted from the last ')'. starttime is the 22nd field
|
|
57
|
+
// overall, i.e. the 20th of what follows the comm field.
|
|
58
|
+
const fields = stat.slice(stat.lastIndexOf(')') + 2).split(' ');
|
|
59
|
+
return fields[19] === procStart;
|
|
60
|
+
} catch {
|
|
61
|
+
// No procfs entry means the process is gone between the two checks.
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Reads one registry file, returning null for anything that is not a live busy session. */
|
|
67
|
+
async function readLiveBusySession(filePath: string): Promise<LiveClaudeCliSession | null> {
|
|
68
|
+
let parsed: unknown;
|
|
69
|
+
try {
|
|
70
|
+
parsed = JSON.parse(await fsp.readFile(filePath, 'utf8'));
|
|
71
|
+
} catch {
|
|
72
|
+
// Unreadable, half-written or malformed entries are simply not evidence
|
|
73
|
+
// of a running session.
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const record = parsed as Record<string, unknown> | null;
|
|
78
|
+
if (!record || typeof record !== 'object') {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const providerSessionId = typeof record.sessionId === 'string' ? record.sessionId : '';
|
|
83
|
+
const pid = typeof record.pid === 'number' ? record.pid : NaN;
|
|
84
|
+
if (!providerSessionId || !Number.isInteger(pid) || pid <= 0 || record.status !== 'busy') {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!(await isRecordedProcessAlive(pid, record.procStart))) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const startedAt = typeof record.startedAt === 'number' ? record.startedAt : Date.now();
|
|
93
|
+
return { providerSessionId, startedAt };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Lists the Claude CLI sessions that are mid-turn right now.
|
|
98
|
+
*
|
|
99
|
+
* Used by the providers module's sessions service so the running-sessions poll
|
|
100
|
+
* also reports turns driven outside CloudCLI's own chat runs — including the
|
|
101
|
+
* `claude` processes CloudCLI itself spawns for the Shell view, which live in
|
|
102
|
+
* the PTY map rather than the chat-run registry. Liveness is ephemeral, so it
|
|
103
|
+
* is recomputed on every read instead of being cached or persisted.
|
|
104
|
+
*/
|
|
105
|
+
export async function listBusyClaudeCliSessions(): Promise<LiveClaudeCliSession[]> {
|
|
106
|
+
let entries: string[];
|
|
107
|
+
try {
|
|
108
|
+
entries = await fsp.readdir(registryDirectory());
|
|
109
|
+
} catch {
|
|
110
|
+
// No registry directory at all is the normal case for an install that has
|
|
111
|
+
// never run the CLI, and an unreadable one is not worth failing a poll for.
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const registryFiles = entries.filter((entry) => entry.endsWith('.json')).slice(0, MAX_REGISTRY_FILES);
|
|
116
|
+
const sessions = await Promise.all(
|
|
117
|
+
registryFiles.map((entry) => readLiveBusySession(path.join(registryDirectory(), entry))),
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return sessions.filter((session): session is LiveClaudeCliSession => session !== null);
|
|
121
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
import { readObjectRecord, readStringArray } from '@/shared/utils.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The permission rules one Claude settings file contributes.
|
|
9
|
+
*
|
|
10
|
+
* `status` says whether the rules could be read at all: `missing` means there
|
|
11
|
+
* is no such file, `invalid` means it exists but the CLI would not load it
|
|
12
|
+
* either (unreadable, over its size cap, or not a JSON object). Both report
|
|
13
|
+
* empty rule lists rather than failing the request, so one bad file never hides
|
|
14
|
+
* the others.
|
|
15
|
+
*/
|
|
16
|
+
type ClaudeSettingsPermissionSource = {
|
|
17
|
+
scope: 'user' | 'managed';
|
|
18
|
+
path: string;
|
|
19
|
+
status: 'ok' | 'missing' | 'invalid';
|
|
20
|
+
allow: string[];
|
|
21
|
+
deny: string[];
|
|
22
|
+
ask: string[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The user's own settings file. The CLI reads it from `CLAUDE_CONFIG_DIR` when
|
|
27
|
+
* that is set, and the server forwards its whole env to every CLI it spawns,
|
|
28
|
+
* so the same override has to apply here.
|
|
29
|
+
*/
|
|
30
|
+
const userSettingsPath = (): string => {
|
|
31
|
+
const configDirectory = process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
32
|
+
const baseDirectory = configDirectory && path.isAbsolute(configDirectory)
|
|
33
|
+
? configDirectory
|
|
34
|
+
: path.join(os.homedir(), '.claude');
|
|
35
|
+
return path.join(baseDirectory, 'settings.json');
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** The administrator-managed settings file, at the fixed path the CLI uses per OS. */
|
|
39
|
+
const managedSettingsPath = (): string => {
|
|
40
|
+
if (process.platform === 'darwin') {
|
|
41
|
+
return '/Library/Application Support/ClaudeCode/managed-settings.json';
|
|
42
|
+
}
|
|
43
|
+
if (process.platform === 'win32') {
|
|
44
|
+
return 'C:\\Program Files\\ClaudeCode\\managed-settings.json';
|
|
45
|
+
}
|
|
46
|
+
return '/etc/claude-code/managed-settings.json';
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// The CLI refuses to load a settings file larger than this (2 MB).
|
|
50
|
+
const MAX_SETTINGS_FILE_BYTES = 2 * 1024 * 1024;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Decodes a settings file the way the CLI does: UTF-16LE when it starts with
|
|
54
|
+
* that byte order mark, UTF-8 otherwise, without the leading BOM. Windows
|
|
55
|
+
* editors and PowerShell often save one, and the CLI still applies such files.
|
|
56
|
+
*/
|
|
57
|
+
const decodeSettingsFile = (bytes: Buffer): string => {
|
|
58
|
+
const isUtf16LittleEndian = bytes.length >= 2 && bytes[0] === 0xff && bytes[1] === 0xfe;
|
|
59
|
+
return bytes.toString(isUtf16LittleEndian ? 'utf16le' : 'utf8').replace(/^\uFEFF/, '');
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** Keeps non-empty string rules only, without duplicates, in file order. */
|
|
63
|
+
const readRuleList = (value: unknown): string[] => [
|
|
64
|
+
...new Set((readStringArray(value) ?? []).map((rule) => rule.trim()).filter(Boolean)),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
async function readPermissionSource(
|
|
68
|
+
scope: ClaudeSettingsPermissionSource['scope'],
|
|
69
|
+
filePath: string,
|
|
70
|
+
): Promise<ClaudeSettingsPermissionSource> {
|
|
71
|
+
const empty = { scope, path: filePath, allow: [], deny: [], ask: [] };
|
|
72
|
+
|
|
73
|
+
let content: string;
|
|
74
|
+
try {
|
|
75
|
+
if ((await stat(filePath)).size > MAX_SETTINGS_FILE_BYTES) {
|
|
76
|
+
return { ...empty, status: 'invalid' };
|
|
77
|
+
}
|
|
78
|
+
content = decodeSettingsFile(await readFile(filePath));
|
|
79
|
+
} catch (error) {
|
|
80
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
81
|
+
return { ...empty, status: code === 'ENOENT' || code === 'ENOTDIR' ? 'missing' : 'invalid' };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The CLI loads an empty or whitespace-only file as `{}`.
|
|
85
|
+
if (!content.trim()) {
|
|
86
|
+
return { ...empty, status: 'ok' };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let settings: Record<string, unknown> | null;
|
|
90
|
+
try {
|
|
91
|
+
settings = readObjectRecord(JSON.parse(content));
|
|
92
|
+
} catch {
|
|
93
|
+
settings = null;
|
|
94
|
+
}
|
|
95
|
+
if (!settings) {
|
|
96
|
+
return { ...empty, status: 'invalid' };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// A file without a `permissions` block is perfectly valid; it just adds no rules.
|
|
100
|
+
const permissions = readObjectRecord(settings.permissions) ?? {};
|
|
101
|
+
return {
|
|
102
|
+
...empty,
|
|
103
|
+
status: 'ok',
|
|
104
|
+
allow: readRuleList(permissions.allow),
|
|
105
|
+
deny: readRuleList(permissions.deny),
|
|
106
|
+
ask: readRuleList(permissions.ask),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Read-only view of the permission rules the Claude CLI applies from its own
|
|
112
|
+
* settings files, on top of the allowed/blocked lists CloudCLI passes it.
|
|
113
|
+
*
|
|
114
|
+
* Used by provider.routes.ts for the Claude permissions panel in Settings.
|
|
115
|
+
* Project-level files are left out on purpose: the panel has no project, and
|
|
116
|
+
* those files only apply to chats started inside their project. CloudCLI never
|
|
117
|
+
* writes to any of these files.
|
|
118
|
+
*/
|
|
119
|
+
export const claudeSettingsPermissionsService = {
|
|
120
|
+
/** `managedPath` is only overridden by tests, which cannot write to the system path. */
|
|
121
|
+
async listRuleSources(managedPath: string = managedSettingsPath()): Promise<ClaudeSettingsPermissionSource[]> {
|
|
122
|
+
return Promise.all([
|
|
123
|
+
readPermissionSource('user', userSettingsPath()),
|
|
124
|
+
readPermissionSource('managed', managedPath),
|
|
125
|
+
]);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
@@ -25,6 +25,23 @@ type ProviderCapabilities = {
|
|
|
25
25
|
supportsTokenUsage: boolean;
|
|
26
26
|
/** Whether the provider runtime can accept model-level reasoning effort. */
|
|
27
27
|
supportsEffort: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Reasoning-effort levels the runtime can pass on, weakest first, and so the
|
|
30
|
+
* levels a custom model-library entry may declare. Empty exactly when
|
|
31
|
+
* `supportsEffort` is false. Covers every level a predefined model declares
|
|
32
|
+
* (a providers test enforces this) and, unlike the model catalog, does not
|
|
33
|
+
* depend on which upstream providers this machine has connected.
|
|
34
|
+
*/
|
|
35
|
+
effortLevels: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Whether an already-sent message can be replaced, which requires the
|
|
38
|
+
* provider to re-run a conversation truncated at a chosen point.
|
|
39
|
+
*/
|
|
40
|
+
supportsMessageEditing: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether a session's transcript can be branched into an independent one.
|
|
43
|
+
*/
|
|
44
|
+
supportsSessionForking: boolean;
|
|
28
45
|
};
|
|
29
46
|
|
|
30
47
|
/**
|
|
@@ -44,6 +61,11 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
44
61
|
supportsPermissionRequests: true,
|
|
45
62
|
supportsTokenUsage: true,
|
|
46
63
|
supportsEffort: true,
|
|
64
|
+
effortLevels: ['low', 'medium', 'high', 'xhigh', 'max', 'ultracode'],
|
|
65
|
+
// `resumeSessionAt` re-runs a conversation truncated at a message, and
|
|
66
|
+
// `forkSession` copies a transcript prefix into a new session file.
|
|
67
|
+
supportsMessageEditing: true,
|
|
68
|
+
supportsSessionForking: true,
|
|
47
69
|
},
|
|
48
70
|
cursor: {
|
|
49
71
|
provider: 'cursor',
|
|
@@ -55,6 +77,9 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
55
77
|
supportsPermissionRequests: false,
|
|
56
78
|
supportsTokenUsage: false,
|
|
57
79
|
supportsEffort: false,
|
|
80
|
+
effortLevels: [],
|
|
81
|
+
supportsMessageEditing: false,
|
|
82
|
+
supportsSessionForking: false,
|
|
58
83
|
},
|
|
59
84
|
codex: {
|
|
60
85
|
provider: 'codex',
|
|
@@ -66,6 +91,13 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
66
91
|
supportsPermissionRequests: false,
|
|
67
92
|
supportsTokenUsage: true,
|
|
68
93
|
supportsEffort: true,
|
|
94
|
+
effortLevels: ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],
|
|
95
|
+
// Not from the Codex SDK, which only starts and resumes threads: both ride
|
|
96
|
+
// the same CLI's `app-server` protocol, whose `thread/fork` copies a
|
|
97
|
+
// thread up to a chosen turn. Editing is that fork plus a new prompt,
|
|
98
|
+
// which is how Codex's own IDE clients do it.
|
|
99
|
+
supportsMessageEditing: true,
|
|
100
|
+
supportsSessionForking: true,
|
|
69
101
|
},
|
|
70
102
|
opencode: {
|
|
71
103
|
provider: 'opencode',
|
|
@@ -80,11 +112,18 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
80
112
|
supportsPermissionRequests: false,
|
|
81
113
|
supportsTokenUsage: true,
|
|
82
114
|
supportsEffort: true,
|
|
115
|
+
// Passed on as OpenCode's `--variant`. `thinking` (MiniMax's on/off
|
|
116
|
+
// variant, paired with `none`) is not a strength, so it sorts last.
|
|
117
|
+
effortLevels: ['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'thinking'],
|
|
118
|
+
supportsMessageEditing: false,
|
|
119
|
+
supportsSessionForking: false,
|
|
83
120
|
},
|
|
84
121
|
};
|
|
85
122
|
|
|
86
123
|
/**
|
|
87
|
-
* Application service exposing the provider capability matrix.
|
|
124
|
+
* Application service exposing the provider capability matrix. Used by the
|
|
125
|
+
* Providers routes (the capabilities endpoints) and by the Providers model
|
|
126
|
+
* service, which reads `effortLevels` to validate custom-model effort.
|
|
88
127
|
*/
|
|
89
128
|
export const providerCapabilitiesService = {
|
|
90
129
|
getProviderCapabilities(provider: LLMProvider): ProviderCapabilities {
|