@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,25 +1,75 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
2
5
|
import test from 'node:test';
|
|
3
6
|
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
|
|
9
|
+
import { closeConnection, initializeDatabase } from '@/modules/database/index.js';
|
|
4
10
|
import {
|
|
5
11
|
OpenCodeProviderModels,
|
|
6
12
|
OPENCODE_PREDEFINED_MODELS,
|
|
7
13
|
} from '@/modules/providers/list/opencode/opencode-models.provider.js';
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
const adapter = new OpenCodeProviderModels();
|
|
15
|
+
const OPENCODE_ENV_KEYS = ['OPENCODE_API_KEY', 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY'];
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Runs one case against a throwaway OpenCode home, so the catalog the adapter
|
|
19
|
+
* reports depends on the fixture rather than on the providers the machine
|
|
20
|
+
* running the suite happens to be logged into.
|
|
21
|
+
*/
|
|
22
|
+
const withOpenCodeHome = async (
|
|
23
|
+
setUp: (homeDir: string) => Promise<void>,
|
|
24
|
+
runTest: (adapter: OpenCodeProviderModels) => Promise<void>,
|
|
25
|
+
): Promise<void> => {
|
|
26
|
+
const homeDir = await mkdtemp(path.join(os.tmpdir(), 'opencode-catalog-'));
|
|
27
|
+
const originalHomedir = os.homedir;
|
|
28
|
+
const originalEnv = OPENCODE_ENV_KEYS.map((key) => [key, process.env[key]] as const);
|
|
29
|
+
|
|
30
|
+
(os as any).homedir = () => homeDir;
|
|
31
|
+
for (const key of OPENCODE_ENV_KEYS) {
|
|
32
|
+
delete process.env[key];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await setUp(homeDir);
|
|
37
|
+
await runTest(new OpenCodeProviderModels());
|
|
38
|
+
} finally {
|
|
39
|
+
(os as any).homedir = originalHomedir;
|
|
40
|
+
for (const [key, value] of originalEnv) {
|
|
41
|
+
if (value === undefined) {
|
|
42
|
+
delete process.env[key];
|
|
43
|
+
} else {
|
|
44
|
+
process.env[key] = value;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
await rm(homeDir, { recursive: true, force: true });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const writeOpenCodeAuth = async (homeDir: string, auth: Record<string, unknown>): Promise<void> => {
|
|
52
|
+
const authDir = path.join(homeDir, '.local', 'share', 'opencode');
|
|
53
|
+
await mkdir(authDir, { recursive: true });
|
|
54
|
+
await writeFile(path.join(authDir, 'auth.json'), JSON.stringify(auth), 'utf8');
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
test('OpenCode exposes only the curated predefined catalog', async () => {
|
|
58
|
+
await withOpenCodeHome(async () => {}, async (adapter) => {
|
|
59
|
+
// Nothing readable about this install, so the picker keeps every option
|
|
60
|
+
// rather than coming up empty.
|
|
61
|
+
assert.deepEqual(await adapter.getSupportedModels(), OPENCODE_PREDEFINED_MODELS);
|
|
62
|
+
assert.equal(
|
|
63
|
+
(await adapter.getCurrentActiveModel()).model,
|
|
64
|
+
OPENCODE_PREDEFINED_MODELS.DEFAULT,
|
|
65
|
+
);
|
|
66
|
+
});
|
|
17
67
|
// OpenCode routes by `<providerID>/<modelID>`, so every option has to carry a
|
|
18
68
|
// provider prefix that `opencode models --verbose` reports.
|
|
19
69
|
const providerIds = new Set(
|
|
20
70
|
OPENCODE_PREDEFINED_MODELS.OPTIONS.map((option) => option.value.split('/')[0]),
|
|
21
71
|
);
|
|
22
|
-
assert.deepEqual([...providerIds].sort(), ['anthropic', 'opencode', 'openai'].sort());
|
|
72
|
+
assert.deepEqual([...providerIds].sort(), ['anthropic', 'opencode', 'opencode-go', 'openai'].sort());
|
|
23
73
|
assert.equal(
|
|
24
74
|
OPENCODE_PREDEFINED_MODELS.OPTIONS.every((option) => /^[a-z0-9-]+\/.+/.test(option.value)),
|
|
25
75
|
true,
|
|
@@ -38,4 +88,212 @@ test('OpenCode exposes only the curated predefined catalog', async () => {
|
|
|
38
88
|
assert.ok(
|
|
39
89
|
OPENCODE_PREDEFINED_MODELS.OPTIONS.some((option) => option.value === 'openai/gpt-5.6'),
|
|
40
90
|
);
|
|
91
|
+
// The Go gateway carries its own provider id, so its models must be curated
|
|
92
|
+
// too - a Go subscriber otherwise authenticates while the picker offers
|
|
93
|
+
// nothing they can run.
|
|
94
|
+
const opencodeGoOptions = OPENCODE_PREDEFINED_MODELS.OPTIONS.filter(
|
|
95
|
+
(option) => option.value.startsWith('opencode-go/'),
|
|
96
|
+
);
|
|
97
|
+
assert.equal(opencodeGoOptions.length, 27);
|
|
98
|
+
assert.ok(opencodeGoOptions.every((option) => option.description === 'OpenCode Go'));
|
|
99
|
+
const glmFlash = opencodeGoOptions.find(
|
|
100
|
+
(option) => option.value === 'opencode-go/glm-5.3-flash',
|
|
101
|
+
);
|
|
102
|
+
assert.ok(glmFlash);
|
|
103
|
+
// Effort choices come from `opencode models --verbose` variants; the runtime
|
|
104
|
+
// turns a selected value into `--variant`, so the values have to match the
|
|
105
|
+
// CLI's exactly.
|
|
106
|
+
assert.deepEqual(
|
|
107
|
+
glmFlash?.effort?.values.map((value) => value.value),
|
|
108
|
+
['low', 'high', 'max'],
|
|
109
|
+
);
|
|
110
|
+
assert.ok(
|
|
111
|
+
opencodeGoOptions
|
|
112
|
+
.filter((option) => !option.effort)
|
|
113
|
+
.every((option) =>
|
|
114
|
+
['glm-5.1', 'kimi-k2.6', 'kimi-k2.7-code', 'mimo-v2.5', 'mimo-v2.5-pro',
|
|
115
|
+
'minimax-m2.7', 'qwen3.6-plus', 'qwen3.7-max', 'qwen3.7-plus']
|
|
116
|
+
.includes(option.value.slice('opencode-go/'.length)),
|
|
117
|
+
),
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('OpenCode offers only models the install can route to', async () => {
|
|
122
|
+
// Asking for a provider the user never connected fails the whole run with
|
|
123
|
+
// "Model <id> is not valid", so an OpenCode Zen model must not be offered -
|
|
124
|
+
// or defaulted to - on a machine that only holds an Anthropic key.
|
|
125
|
+
await withOpenCodeHome(
|
|
126
|
+
(homeDir) => writeOpenCodeAuth(homeDir, { anthropic: { type: 'api', key: 'test' } }),
|
|
127
|
+
async (adapter) => {
|
|
128
|
+
const catalog = await adapter.getSupportedModels();
|
|
129
|
+
const providerIds = new Set(catalog.OPTIONS.map((option) => option.value.split('/')[0]));
|
|
130
|
+
|
|
131
|
+
assert.deepEqual([...providerIds], ['anthropic']);
|
|
132
|
+
assert.ok(catalog.OPTIONS.length > 0);
|
|
133
|
+
assert.equal(catalog.DEFAULT.startsWith('anthropic/'), true);
|
|
134
|
+
assert.ok(catalog.OPTIONS.some((option) => option.value === catalog.DEFAULT));
|
|
135
|
+
assert.equal((await adapter.getCurrentActiveModel()).model, catalog.DEFAULT);
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// A Go subscriber's auth store holds only `opencode-go`, so the whole catalog
|
|
140
|
+
// has to resolve to Go models and the default has to move onto one of them
|
|
141
|
+
// instead of the unreachable Zen default.
|
|
142
|
+
await withOpenCodeHome(
|
|
143
|
+
(homeDir) => writeOpenCodeAuth(homeDir, { 'opencode-go': { type: 'api', key: 'test' } }),
|
|
144
|
+
async (adapter) => {
|
|
145
|
+
const catalog = await adapter.getSupportedModels();
|
|
146
|
+
const providerIds = new Set(catalog.OPTIONS.map((option) => option.value.split('/')[0]));
|
|
147
|
+
|
|
148
|
+
assert.deepEqual([...providerIds], ['opencode-go']);
|
|
149
|
+
assert.equal(catalog.OPTIONS.length, 27);
|
|
150
|
+
assert.equal(catalog.DEFAULT, 'opencode-go/grok-4.6');
|
|
151
|
+
assert.ok(catalog.OPTIONS.some((option) => option.value === catalog.DEFAULT));
|
|
152
|
+
assert.equal((await adapter.getCurrentActiveModel()).model, catalog.DEFAULT);
|
|
153
|
+
},
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// The catalog default survives whenever its own provider is connected.
|
|
157
|
+
await withOpenCodeHome(
|
|
158
|
+
(homeDir) => writeOpenCodeAuth(homeDir, {
|
|
159
|
+
opencode: { type: 'api', key: 'test' },
|
|
160
|
+
openai: { type: 'oauth' },
|
|
161
|
+
}),
|
|
162
|
+
async (adapter) => {
|
|
163
|
+
const catalog = await adapter.getSupportedModels();
|
|
164
|
+
const providerIds = new Set(catalog.OPTIONS.map((option) => option.value.split('/')[0]));
|
|
165
|
+
|
|
166
|
+
assert.deepEqual([...providerIds].sort(), ['opencode', 'openai'].sort());
|
|
167
|
+
assert.equal(catalog.DEFAULT, OPENCODE_PREDEFINED_MODELS.DEFAULT);
|
|
168
|
+
},
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Providers configured rather than logged into count too.
|
|
172
|
+
await withOpenCodeHome(
|
|
173
|
+
async (homeDir) => {
|
|
174
|
+
const configDir = path.join(homeDir, '.config', 'opencode');
|
|
175
|
+
await mkdir(configDir, { recursive: true });
|
|
176
|
+
await writeFile(
|
|
177
|
+
path.join(configDir, 'opencode.json'),
|
|
178
|
+
JSON.stringify({ provider: { anthropic: { options: {} } } }),
|
|
179
|
+
'utf8',
|
|
180
|
+
);
|
|
181
|
+
},
|
|
182
|
+
async (adapter) => {
|
|
183
|
+
const catalog = await adapter.getSupportedModels();
|
|
184
|
+
const providerIds = new Set(catalog.OPTIONS.map((option) => option.value.split('/')[0]));
|
|
185
|
+
|
|
186
|
+
assert.deepEqual([...providerIds], ['anthropic']);
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// An API key in the environment is enough on its own.
|
|
191
|
+
await withOpenCodeHome(
|
|
192
|
+
async () => {
|
|
193
|
+
process.env.OPENAI_API_KEY = 'test';
|
|
194
|
+
},
|
|
195
|
+
async (adapter) => {
|
|
196
|
+
const catalog = await adapter.getSupportedModels();
|
|
197
|
+
const providerIds = new Set(catalog.OPTIONS.map((option) => option.value.split('/')[0]));
|
|
198
|
+
|
|
199
|
+
assert.deepEqual([...providerIds], ['openai']);
|
|
200
|
+
},
|
|
201
|
+
);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const writeOpenCodeSessionDatabase = async (homeDir: string, rows: Array<Record<string, unknown>>) => {
|
|
205
|
+
const dbPath = path.join(homeDir, '.local', 'share', 'opencode', 'opencode.db');
|
|
206
|
+
await mkdir(path.dirname(dbPath), { recursive: true });
|
|
207
|
+
const db = new Database(dbPath);
|
|
208
|
+
try {
|
|
209
|
+
db.exec(`
|
|
210
|
+
CREATE TABLE session (
|
|
211
|
+
id text PRIMARY KEY,
|
|
212
|
+
model text,
|
|
213
|
+
agent text,
|
|
214
|
+
directory text,
|
|
215
|
+
time_created integer NOT NULL,
|
|
216
|
+
time_updated integer NOT NULL
|
|
217
|
+
);
|
|
218
|
+
`);
|
|
219
|
+
const insert = db.prepare(
|
|
220
|
+
'INSERT INTO session (id, model, agent, directory, time_created, time_updated) VALUES (?, ?, ?, ?, ?, ?)',
|
|
221
|
+
);
|
|
222
|
+
for (const [index, row] of rows.entries()) {
|
|
223
|
+
insert.run(
|
|
224
|
+
row.id,
|
|
225
|
+
row.model,
|
|
226
|
+
row.agent ?? null,
|
|
227
|
+
row.directory ?? '/tmp/project',
|
|
228
|
+
row.timeCreated ?? 1700000000000,
|
|
229
|
+
row.timeUpdated ?? 1700000001000 + index,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
} finally {
|
|
233
|
+
db.close();
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
test('OpenCode composes the provider prefix into session model ids', async () => {
|
|
238
|
+
// The lookup translates the app session id through the sessions database,
|
|
239
|
+
// so point it at a throwaway file rather than the developer's real one.
|
|
240
|
+
const tempSessionsDirectory = await mkdtemp(path.join(os.tmpdir(), 'opencode-session-model-'));
|
|
241
|
+
const previousDatabasePath = process.env.DATABASE_PATH;
|
|
242
|
+
try {
|
|
243
|
+
closeConnection();
|
|
244
|
+
process.env.DATABASE_PATH = path.join(tempSessionsDirectory, 'auth.db');
|
|
245
|
+
await initializeDatabase();
|
|
246
|
+
// OpenCode stores the provider and model id in separate fields of the
|
|
247
|
+
// session row ({"id":"z-ai/glm-5.3-flash","providerID":"openrouter"}), but
|
|
248
|
+
// the CLI's `--model` flag only resolves the composed
|
|
249
|
+
// `<providerID>/<modelID>` form. Resuming such a session without the prefix
|
|
250
|
+
// fails with an unknown-model server error, which hits OpenRouter users
|
|
251
|
+
// hardest because their model ids carry a slash themselves.
|
|
252
|
+
await withOpenCodeHome(
|
|
253
|
+
(homeDir) => writeOpenCodeSessionDatabase(homeDir, [
|
|
254
|
+
{
|
|
255
|
+
id: 'ses_openrouter',
|
|
256
|
+
model: JSON.stringify({
|
|
257
|
+
id: 'z-ai/glm-5.3-flash',
|
|
258
|
+
providerID: 'openrouter',
|
|
259
|
+
variant: 'default',
|
|
260
|
+
}),
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: 'ses_qualified',
|
|
264
|
+
// An id that already carries the provider prefix must survive as-is.
|
|
265
|
+
model: JSON.stringify({
|
|
266
|
+
id: 'openrouter/z-ai/glm-5.3-flash',
|
|
267
|
+
providerID: 'openrouter',
|
|
268
|
+
}),
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
id: 'ses_plain_string',
|
|
272
|
+
model: 'opencode/gpt-5.6-terra',
|
|
273
|
+
},
|
|
274
|
+
]),
|
|
275
|
+
async (adapter) => {
|
|
276
|
+
assert.equal(
|
|
277
|
+
(await adapter.getCurrentActiveModel('ses_openrouter')).model,
|
|
278
|
+
'openrouter/z-ai/glm-5.3-flash',
|
|
279
|
+
);
|
|
280
|
+
assert.equal(
|
|
281
|
+
(await adapter.getCurrentActiveModel('ses_qualified')).model,
|
|
282
|
+
'openrouter/z-ai/glm-5.3-flash',
|
|
283
|
+
);
|
|
284
|
+
assert.equal(
|
|
285
|
+
(await adapter.getCurrentActiveModel('ses_plain_string')).model,
|
|
286
|
+
'opencode/gpt-5.6-terra',
|
|
287
|
+
);
|
|
288
|
+
},
|
|
289
|
+
);
|
|
290
|
+
} finally {
|
|
291
|
+
closeConnection();
|
|
292
|
+
if (previousDatabasePath === undefined) {
|
|
293
|
+
delete process.env.DATABASE_PATH;
|
|
294
|
+
} else {
|
|
295
|
+
process.env.DATABASE_PATH = previousDatabasePath;
|
|
296
|
+
}
|
|
297
|
+
await rm(tempSessionsDirectory, { recursive: true, force: true });
|
|
298
|
+
}
|
|
41
299
|
});
|
|
@@ -151,6 +151,30 @@ const createOpenCodeDatabase = async (homeDir: string, workspacePath: string): P
|
|
|
151
151
|
3,
|
|
152
152
|
2,
|
|
153
153
|
);
|
|
154
|
+
db.prepare(`
|
|
155
|
+
INSERT INTO session (
|
|
156
|
+
id, project_id, parent_id, slug, directory, title, version, time_created, time_updated,
|
|
157
|
+
time_archived, tokens_input, tokens_output, tokens_reasoning, tokens_cache_read,
|
|
158
|
+
tokens_cache_write
|
|
159
|
+
)
|
|
160
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
161
|
+
`).run(
|
|
162
|
+
'open-child-session-1',
|
|
163
|
+
'project-1',
|
|
164
|
+
'open-session-1',
|
|
165
|
+
'open-child-session-1',
|
|
166
|
+
workspacePath,
|
|
167
|
+
'OpenCode child session',
|
|
168
|
+
'0.0.0',
|
|
169
|
+
1_700_000_002_000,
|
|
170
|
+
1_700_000_005_000,
|
|
171
|
+
null,
|
|
172
|
+
5,
|
|
173
|
+
10,
|
|
174
|
+
2,
|
|
175
|
+
1,
|
|
176
|
+
1,
|
|
177
|
+
);
|
|
154
178
|
|
|
155
179
|
const userMessageData = JSON.stringify({
|
|
156
180
|
role: 'user',
|
|
@@ -255,16 +279,29 @@ test('OpenCode session synchronizer indexes sqlite sessions without deletable tr
|
|
|
255
279
|
try {
|
|
256
280
|
await createOpenCodeDatabase(tempRoot, workspacePath);
|
|
257
281
|
await withIsolatedDatabase(() => {
|
|
282
|
+
sessionsDb.createAppSession('app-child-session-1', 'opencode', workspacePath);
|
|
283
|
+
sessionsDb.assignProviderSessionId('app-child-session-1', 'open-child-session-1');
|
|
284
|
+
|
|
258
285
|
const synchronizer = new OpenCodeSessionSynchronizer();
|
|
259
286
|
const processed = synchronizer.synchronize();
|
|
260
287
|
|
|
261
|
-
return Promise.resolve(processed).then((count) => {
|
|
288
|
+
return Promise.resolve(processed).then(async (count) => {
|
|
262
289
|
assert.equal(count, 1);
|
|
263
290
|
const indexed = sessionsDb.getSessionById('open-session-1');
|
|
264
291
|
assert.equal(indexed?.provider, 'opencode');
|
|
265
292
|
assert.equal(indexed?.project_path, workspacePath);
|
|
266
293
|
assert.equal(indexed?.custom_name, 'OpenCode indexed title');
|
|
267
294
|
assert.equal(indexed?.jsonl_path, null);
|
|
295
|
+
assert.equal(sessionsDb.getSessionById('app-child-session-1'), null);
|
|
296
|
+
assert.equal(sessionsDb.getSessionByProviderSessionId('open-child-session-1'), null);
|
|
297
|
+
|
|
298
|
+
sessionsDb.createAppSession('app-child-session-2', 'opencode', workspacePath);
|
|
299
|
+
sessionsDb.assignProviderSessionId('app-child-session-2', 'open-child-session-1');
|
|
300
|
+
await synchronizer.synchronize(new Date(1_700_000_004_500));
|
|
301
|
+
assert.equal(
|
|
302
|
+
sessionsDb.getSessionById('app-child-session-2')?.provider_session_id,
|
|
303
|
+
'open-child-session-1',
|
|
304
|
+
);
|
|
268
305
|
});
|
|
269
306
|
});
|
|
270
307
|
} finally {
|
|
@@ -290,6 +327,7 @@ test('OpenCode session synchronizer returns the app session id once provider map
|
|
|
290
327
|
assert.equal(sessionId, 'app-session-1');
|
|
291
328
|
assert.equal(sessionsDb.getAllSessions().length, 1);
|
|
292
329
|
assert.equal(sessionsDb.getSessionById('app-session-1')?.provider_session_id, 'open-session-1');
|
|
330
|
+
assert.equal(sessionsDb.getSessionById('open-child-session-1'), null);
|
|
293
331
|
});
|
|
294
332
|
});
|
|
295
333
|
} finally {
|
|
@@ -438,6 +476,7 @@ const seedOpenCodeSession = async (
|
|
|
438
476
|
CREATE TABLE session (
|
|
439
477
|
id TEXT PRIMARY KEY,
|
|
440
478
|
project_id TEXT,
|
|
479
|
+
parent_id TEXT,
|
|
441
480
|
directory TEXT,
|
|
442
481
|
title TEXT,
|
|
443
482
|
time_created INTEGER,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { CLAUDE_PREDEFINED_MODELS } from '@/modules/providers/list/claude/claude-models.provider.js';
|
|
5
|
+
import { CODEX_PREDEFINED_MODELS } from '@/modules/providers/list/codex/codex-models.provider.js';
|
|
6
|
+
import { CURSOR_PREDEFINED_MODELS } from '@/modules/providers/list/cursor/cursor-models.provider.js';
|
|
7
|
+
import { OPENCODE_PREDEFINED_MODELS } from '@/modules/providers/list/opencode/opencode-models.provider.js';
|
|
8
|
+
import { providerCapabilitiesService } from '@/modules/providers/services/provider-capabilities.service.js';
|
|
9
|
+
import type { LLMProvider, ProviderModelsDefinition } from '@/shared/types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The full curated catalogs, before OpenCode narrows its list to the upstream
|
|
13
|
+
* providers a machine has connected.
|
|
14
|
+
*/
|
|
15
|
+
const CURATED_CATALOGS: Record<LLMProvider, ProviderModelsDefinition> = {
|
|
16
|
+
claude: CLAUDE_PREDEFINED_MODELS,
|
|
17
|
+
codex: CODEX_PREDEFINED_MODELS,
|
|
18
|
+
cursor: CURSOR_PREDEFINED_MODELS,
|
|
19
|
+
opencode: OPENCODE_PREDEFINED_MODELS,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
test('capability effort levels cover every level a curated model declares', () => {
|
|
23
|
+
// Custom models may declare only these levels, so a level added to a curated
|
|
24
|
+
// model has to be added here too, or users could not give it to their own.
|
|
25
|
+
for (const [provider, catalog] of Object.entries(CURATED_CATALOGS) as Array<[LLMProvider, ProviderModelsDefinition]>) {
|
|
26
|
+
const { effortLevels, supportsEffort } = providerCapabilitiesService.getProviderCapabilities(provider);
|
|
27
|
+
|
|
28
|
+
assert.equal(supportsEffort, effortLevels.length > 0, `${provider}: supportsEffort disagrees with effortLevels`);
|
|
29
|
+
assert.equal(new Set(effortLevels).size, effortLevels.length, `${provider}: effortLevels lists a level twice`);
|
|
30
|
+
|
|
31
|
+
const declaredLevels = new Set(
|
|
32
|
+
catalog.OPTIONS.flatMap((option) => option.effort?.values.map((level) => level.value) ?? []),
|
|
33
|
+
);
|
|
34
|
+
const missingLevels = [...declaredLevels].filter((level) => !effortLevels.includes(level));
|
|
35
|
+
assert.deepEqual(missingLevels, [], `${provider}: effortLevels misses curated levels`);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
@@ -69,6 +69,7 @@ const createCatalogStore = () => {
|
|
|
69
69
|
modelId: input.id,
|
|
70
70
|
model: input.model,
|
|
71
71
|
sortOrder: readRows(provider).length,
|
|
72
|
+
effort: input.effort ?? null,
|
|
72
73
|
};
|
|
73
74
|
rows.set(provider, [...readRows(provider), record]);
|
|
74
75
|
return record;
|
|
@@ -82,7 +83,13 @@ const createCatalogStore = () => {
|
|
|
82
83
|
if (!existing) {
|
|
83
84
|
return null;
|
|
84
85
|
}
|
|
85
|
-
const updated = {
|
|
86
|
+
const updated = {
|
|
87
|
+
...existing,
|
|
88
|
+
modelId: input.id,
|
|
89
|
+
model: input.model,
|
|
90
|
+
// Mirrors the repository: an omitted effort keeps the stored levels.
|
|
91
|
+
effort: input.effort === undefined ? existing.effort : input.effort,
|
|
92
|
+
};
|
|
86
93
|
rows.set(provider, readRows(provider).map((record) => (
|
|
87
94
|
record.recordId === recordId ? updated : record
|
|
88
95
|
)));
|
|
@@ -165,6 +172,97 @@ test('custom models can be created, edited, and deleted', async () => {
|
|
|
165
172
|
assert.equal(removed.models.OPTIONS.some((option) => option.recordId === recordId), false);
|
|
166
173
|
});
|
|
167
174
|
|
|
175
|
+
test('custom models carry declared effort levels into the merged catalog', async () => {
|
|
176
|
+
const { service } = createTestService();
|
|
177
|
+
|
|
178
|
+
const created = await service.createCustomModel('claude', {
|
|
179
|
+
model: 'My Custom Model',
|
|
180
|
+
id: 'my-custom-model',
|
|
181
|
+
effort: { values: ['low', 'max'], default: 'max' },
|
|
182
|
+
});
|
|
183
|
+
const expectedEffort = { default: 'max', values: [{ value: 'low' }, { value: 'max' }] };
|
|
184
|
+
assert.deepEqual(created.model.effort, expectedEffort);
|
|
185
|
+
|
|
186
|
+
const catalog = await service.getProviderModels('claude');
|
|
187
|
+
const merged = catalog.OPTIONS.find((option) => option.value === 'my-custom-model');
|
|
188
|
+
assert.deepEqual(merged?.effort, expectedEffort);
|
|
189
|
+
|
|
190
|
+
// A rename that does not mention effort (an older client) keeps the levels.
|
|
191
|
+
const renamed = await service.updateCustomModel('claude', created.model.recordId as number, {
|
|
192
|
+
model: 'Renamed',
|
|
193
|
+
id: 'my-custom-model',
|
|
194
|
+
});
|
|
195
|
+
assert.deepEqual(renamed.model.effort, expectedEffort);
|
|
196
|
+
|
|
197
|
+
const cleared = await service.updateCustomModel('claude', created.model.recordId as number, {
|
|
198
|
+
model: 'Renamed',
|
|
199
|
+
id: 'my-custom-model',
|
|
200
|
+
effort: null,
|
|
201
|
+
});
|
|
202
|
+
assert.equal('effort' in cleared.model, false);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test('custom models without declared effort levels expose no effort', async () => {
|
|
206
|
+
const { service } = createTestService();
|
|
207
|
+
|
|
208
|
+
const created = await service.createCustomModel('codex', { model: 'Plain', id: 'plain-model' });
|
|
209
|
+
|
|
210
|
+
assert.equal('effort' in created.model, false);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test('custom effort levels must be levels the provider supports', async () => {
|
|
214
|
+
const { service } = createTestService();
|
|
215
|
+
|
|
216
|
+
await assert.rejects(
|
|
217
|
+
() => service.createCustomModel('codex', {
|
|
218
|
+
model: 'Unknown level',
|
|
219
|
+
id: 'unknown-level',
|
|
220
|
+
effort: { values: ['low', 'turbo'] },
|
|
221
|
+
}),
|
|
222
|
+
(error) => error instanceof AppError
|
|
223
|
+
&& error.code === 'INVALID_MODEL_EFFORT'
|
|
224
|
+
&& error.statusCode === 400,
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
await assert.rejects(
|
|
228
|
+
() => service.createCustomModel('cursor', {
|
|
229
|
+
model: 'Cursor effort',
|
|
230
|
+
id: 'cursor-effort',
|
|
231
|
+
effort: { values: ['low'] },
|
|
232
|
+
}),
|
|
233
|
+
(error) => error instanceof AppError
|
|
234
|
+
&& error.code === 'MODEL_EFFORT_NOT_SUPPORTED'
|
|
235
|
+
&& error.statusCode === 400,
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('allowed effort levels come from the provider, not from the built-in models this machine sees', async () => {
|
|
240
|
+
// The fake adapters' built-in models declare no effort at all, which is what
|
|
241
|
+
// the real OpenCode adapter returns once it narrows its catalog to OpenCode
|
|
242
|
+
// Zen, Anthropic, or OpenAI: only its OpenCode Go models declare effort.
|
|
243
|
+
const { service } = createTestService();
|
|
244
|
+
|
|
245
|
+
const created = await service.createCustomModel('opencode', {
|
|
246
|
+
model: 'Router model',
|
|
247
|
+
id: 'openrouter/router-model',
|
|
248
|
+
effort: { values: ['none', 'high'] },
|
|
249
|
+
});
|
|
250
|
+
assert.deepEqual(created.model.effort, { values: [{ value: 'none' }, { value: 'high' }] });
|
|
251
|
+
|
|
252
|
+
// Every merged catalog carries the provider's levels for the model library,
|
|
253
|
+
// weakest first, and an empty list where effort is unsupported.
|
|
254
|
+
const expectedLevels: Record<LLMProvider, string[]> = {
|
|
255
|
+
claude: ['low', 'medium', 'high', 'xhigh', 'max', 'ultracode'],
|
|
256
|
+
codex: ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],
|
|
257
|
+
cursor: [],
|
|
258
|
+
opencode: ['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'thinking'],
|
|
259
|
+
};
|
|
260
|
+
for (const [provider, levels] of Object.entries(expectedLevels) as Array<[LLMProvider, string[]]>) {
|
|
261
|
+
assert.deepEqual((await service.getProviderModels(provider)).EFFORT_LEVELS, levels, provider);
|
|
262
|
+
}
|
|
263
|
+
assert.deepEqual(created.models.EFFORT_LEVELS, expectedLevels.opencode);
|
|
264
|
+
});
|
|
265
|
+
|
|
168
266
|
test('duplicate model ids are rejected within one provider', async () => {
|
|
169
267
|
const { service } = createTestService();
|
|
170
268
|
await service.createCustomModel('cursor', { model: 'First', id: 'custom-id' });
|