@cloudcli-ai/cloudcli 1.37.2 → 1.37.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +269 -0
- package/dist/assets/{abnfDiagram-N423BO3Z-C4UAoHJb.js → abnfDiagram-N423BO3Z-CJntskwA.js} +1 -1
- package/dist/assets/{arc-B8jF-ja9.js → arc-CIfH4uMN.js} +1 -1
- package/dist/assets/{architectureDiagram-T3A2C74G-C_Wur_CU.js → architectureDiagram-T3A2C74G-_IpEkukg.js} +1 -1
- package/dist/assets/{blockDiagram-VBNYF7ZC-Cq4P1i8t.js → blockDiagram-VBNYF7ZC-BttxrpgZ.js} +1 -1
- package/dist/assets/{c4Diagram-5PPSVZJV-C1wG4eUj.js → c4Diagram-5PPSVZJV-g51dSRr1.js} +1 -1
- package/dist/assets/channel-C5xU9jMw.js +1 -0
- package/dist/assets/{chunk-2GRJ4B5K-B8fnBG6E.js → chunk-2GRJ4B5K-D_-LbQUa.js} +1 -1
- package/dist/assets/{chunk-2Q5K7J3B-WdfPooPJ.js → chunk-2Q5K7J3B-BtlHzwaO.js} +1 -1
- package/dist/assets/{chunk-5RXB4S5H-DhZJuG2E.js → chunk-5RXB4S5H-UzkpvpAT.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-B0rjslal.js → chunk-5VM5RSS4-BKwx5Gag.js} +1 -1
- package/dist/assets/{chunk-6Q2QTUOP-CG2Oj4jL.js → chunk-6Q2QTUOP-D_KEBH5f.js} +1 -1
- package/dist/assets/{chunk-GF5L2VYU-rrl2lRxY.js → chunk-GF5L2VYU-rK2DGyto.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-CjVbrVMA.js → chunk-JWPE2WC7-CeBl_N9i.js} +1 -1
- package/dist/assets/{chunk-KBJHAD2P-CRzKgU8S.js → chunk-KBJHAD2P-BiQLWVIr.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-DBz4GTZF.js → chunk-RYQCIY6F-C1knVGV5.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-wHxalsXk.js → chunk-XXDRQBXY-CtKbJkvF.js} +1 -1
- package/dist/assets/classDiagram-JCYQIIEL-CRrL3vp7.js +1 -0
- package/dist/assets/classDiagram-v2-OCEON4UE-CRrL3vp7.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-s1hygY8e.js → cose-bilkent-JH36ORCC-DjX8y40Z.js} +1 -1
- package/dist/assets/{cynefin-VYW2F7L2-C4LGV15i.js → cynefin-VYW2F7L2-DM6YeRba.js} +1 -1
- package/dist/assets/{cynefinDiagram-MW4NZA55-C5uhu7B3.js → cynefinDiagram-MW4NZA55-wZJ-vy5B.js} +1 -1
- package/dist/assets/{dagre-VZM6K2ZE-B-OBTewm.js → dagre-VZM6K2ZE-BzP0ejkH.js} +1 -1
- package/dist/assets/{diagram-7IWD3JNH-BjGKQxih.js → diagram-7IWD3JNH-BTL_j23J.js} +1 -1
- package/dist/assets/{diagram-B4RE2ZJO-BMKz1X2L.js → diagram-B4RE2ZJO-Cf1Norgu.js} +1 -1
- package/dist/assets/{diagram-LBJQPF4R-DNh-GhKC.js → diagram-LBJQPF4R-DPiUEKr-.js} +1 -1
- package/dist/assets/{diagram-Q27KOJAE-BaTG9jPT.js → diagram-Q27KOJAE-CTcTpiz5.js} +1 -1
- package/dist/assets/{diagram-UB23O5K3-BUwo2OvJ.js → diagram-UB23O5K3-DPMSdYm0.js} +1 -1
- package/dist/assets/{ebnfDiagram-BXEA7PRR-DAZgfzX2.js → ebnfDiagram-BXEA7PRR-7yvD6uiF.js} +1 -1
- package/dist/assets/{erDiagram-JOGREHBK-1w1CcGEb.js → erDiagram-JOGREHBK-CfgeDoV6.js} +1 -1
- package/dist/assets/{flowDiagram-UKHOOZJN-D4EII8Jj.js → flowDiagram-UKHOOZJN-B27ng5zu.js} +1 -1
- package/dist/assets/{ganttDiagram-PKOTCBZU-ChvJZAgB.js → ganttDiagram-PKOTCBZU-CcC6b_7t.js} +1 -1
- package/dist/assets/{gitGraphDiagram-DS77QQ5N-DtOn41S8.js → gitGraphDiagram-DS77QQ5N-BX5kPGrO.js} +1 -1
- package/dist/assets/index-BTDHQ6Id.css +32 -0
- package/dist/assets/index-sFfz8iBR.js +4931 -0
- package/dist/assets/{infoDiagram-6WML65LV-DN_PVEJZ.js → infoDiagram-6WML65LV-CUP-SlN4.js} +1 -1
- package/dist/assets/{ishikawaDiagram-WSZJBQD7-DbkF1kXb.js → ishikawaDiagram-WSZJBQD7-BTTDhOpX.js} +1 -1
- package/dist/assets/{journeyDiagram-NVQOT4AX-pJwmhddE.js → journeyDiagram-NVQOT4AX-ARXcc61m.js} +1 -1
- package/dist/assets/{kanban-definition-27J2QSJJ-PPAPgNp5.js → kanban-definition-27J2QSJJ-BieMpqMA.js} +1 -1
- package/dist/assets/{linear-iPR-J9f7.js → linear-61vxjRnP.js} +1 -1
- package/dist/assets/{mermaid.core-BEUL86Z6.js → mermaid.core-nhnwkfQx.js} +5 -5
- package/dist/assets/{mindmap-definition-FAOFIHXS-BvZoBib7.js → mindmap-definition-FAOFIHXS-Cm6x5vT1.js} +1 -1
- package/dist/assets/{pegDiagram-VL7TDLO6-DhYreaUd.js → pegDiagram-VL7TDLO6-CcYBq_9H.js} +1 -1
- package/dist/assets/{pieDiagram-7S7Q4E2Y-CrOHlyD0.js → pieDiagram-7S7Q4E2Y-CfvIjfzo.js} +1 -1
- package/dist/assets/{quadrantDiagram-CIZ2JOQS-D4g5yH3t.js → quadrantDiagram-CIZ2JOQS-SgYoWPNb.js} +1 -1
- package/dist/assets/{railroadDiagram-AXF67PYL-Dj39lHlf.js → railroadDiagram-AXF67PYL-D2Mu5E_f.js} +1 -1
- package/dist/assets/{requirementDiagram-LRYGKXZP-1AS4Zgm_.js → requirementDiagram-LRYGKXZP-Azwe_k4Q.js} +1 -1
- package/dist/assets/{sankeyDiagram-W5VNT64P-CKlMn19P.js → sankeyDiagram-W5VNT64P-DN1Ju3PA.js} +1 -1
- package/dist/assets/{sequenceDiagram-SI44F4Z6-B_j3qyvo.js → sequenceDiagram-SI44F4Z6-Bj4qC34S.js} +1 -1
- package/dist/assets/server.browser-CtX3Hdl5.js +27 -0
- package/dist/assets/{sizeCapture-X5ZJPWSS-Bp2Op16v.js → sizeCapture-X5ZJPWSS-Co4PdklG.js} +1 -1
- package/dist/assets/{stateDiagram-OKZ733FA-C0cN6DoY.js → stateDiagram-OKZ733FA-nOvL9dRC.js} +1 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-DNv8ppw7.js +1 -0
- package/dist/assets/{swimlanes-SLNWSIFB-BEvXOV9b.js → swimlanes-SLNWSIFB-CCK3wMid.js} +2 -2
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-DnfbNQEp.js +8 -0
- package/dist/assets/{timeline-definition-Z64GVDOM-zdJQinvZ.js → timeline-definition-Z64GVDOM-BC29RNFm.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-pZlZCtEo.js} +1 -1
- package/dist/assets/{wardleyDiagram-T6FBY63Y-B9AlLQup.js → wardleyDiagram-T6FBY63Y-De8k2-zM.js} +1 -1
- package/dist/assets/{xychartDiagram-ELKLHX3M-DTJX48Qg.js → xychartDiagram-ELKLHX3M-Bk8ykH0w.js} +1 -1
- package/dist/index.html +3 -3
- package/dist-server/server/index.js +7 -3
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/agent/agent.routes.js +2 -2
- package/dist-server/server/modules/agent/agent.routes.js.map +1 -1
- package/dist-server/server/modules/agent/tests/agent.routes.test.js +30 -1
- 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 +32 -1
- package/dist-server/server/modules/database/migrations.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 +137 -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 +92 -0
- package/dist-server/server/modules/database/schema.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/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/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 +20 -1
- 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 +35 -6
- 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 +168 -38
- package/dist-server/server/modules/providers/list/claude/claude-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +388 -50
- 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 +16 -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 +60 -49
- 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 +1565 -432
- 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-runtime.provider.js +8 -6
- 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 +258 -6
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +24 -0
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-capabilities.service.js +14 -0
- package/dist-server/server/modules/providers/services/provider-capabilities.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-history-cache.service.js +87 -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 +179 -9
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/tests/claude-auth.test.js +52 -0
- package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -1
- 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-sessions.test.js +465 -39
- package/dist-server/server/modules/providers/tests/claude-sessions.test.js.map +1 -1
- 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-runtime.test.js +51 -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 +304 -15
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-models.test.js +117 -4
- package/dist-server/server/modules/providers/tests/opencode-models.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/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 +120 -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 +45 -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 +163 -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 +255 -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 +10 -44
- 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 +166 -9
- 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 +9 -3
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
- 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/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 +80 -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/utils.js +34 -0
- package/dist-server/server/shared/utils.js.map +1 -1
- package/package.json +19 -16
- package/server/index.ts +11 -4
- package/server/modules/agent/agent.routes.ts +2 -2
- package/server/modules/agent/tests/agent.routes.test.ts +33 -1
- 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 +37 -0
- 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 +196 -3
- package/server/modules/database/repositories/user-preferences.db.ts +80 -0
- package/server/modules/database/schema.ts +96 -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/projects/services/project-delete.service.ts +13 -1
- package/server/modules/projects/services/project-star.service.ts +2 -2
- package/server/modules/providers/index.ts +4 -0
- package/server/modules/providers/list/claude/claude-auth.provider.ts +21 -1
- package/server/modules/providers/list/claude/claude-fork.provider.ts +57 -0
- package/server/modules/providers/list/claude/claude-models.provider.ts +38 -6
- package/server/modules/providers/list/claude/claude-runtime.provider.js +188 -39
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +478 -54
- 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 +16 -0
- package/server/modules/providers/list/codex/{codex-runtime.provider.js → codex-runtime.provider.ts} +93 -66
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +9 -0
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +1806 -477
- package/server/modules/providers/list/codex/codex.provider.ts +3 -0
- package/server/modules/providers/list/cursor/cursor-runtime.provider.js +8 -6
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +0 -1
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +279 -6
- package/server/modules/providers/provider.routes.ts +31 -0
- package/server/modules/providers/services/provider-capabilities.service.ts +23 -0
- package/server/modules/providers/services/provider-token-usage.service.ts +166 -39
- package/server/modules/providers/services/session-history-cache.service.ts +139 -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 +201 -9
- package/server/modules/providers/tests/claude-auth.test.ts +58 -0
- package/server/modules/providers/tests/claude-models.test.ts +87 -0
- package/server/modules/providers/tests/claude-sessions.test.ts +552 -40
- 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-runtime.test.ts +58 -0
- package/server/modules/providers/tests/codex-session-fork.test.ts +59 -0
- package/server/modules/providers/tests/codex-sessions.test.ts +337 -15
- package/server/modules/providers/tests/opencode-models.test.ts +166 -8
- package/server/modules/providers/tests/provider-token-usage.service.test.ts +188 -1
- package/server/modules/providers/tests/session-fork.test.ts +173 -0
- package/server/modules/providers/tests/session-history-cache.service.test.ts +143 -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 +67 -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 +203 -0
- package/server/modules/scheduled-messages/services/scheduled-messages.service.ts +121 -0
- package/server/modules/scheduled-messages/tests/scheduled-messages.test.ts +310 -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/index.ts +8 -0
- package/server/modules/websocket/services/chat-run-registry.service.ts +17 -50
- package/server/modules/websocket/services/chat-session-writer.service.ts +36 -6
- package/server/modules/websocket/services/chat-websocket.service.ts +244 -15
- package/server/modules/websocket/services/session-upsert-broadcast.service.ts +108 -0
- package/server/modules/websocket/services/shell-websocket.service.ts +10 -3
- 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/session-upsert-broadcast.test.ts +138 -0
- package/server/modules/websocket/tests/shell-websocket.service.test.ts +108 -0
- package/server/shared/claude-cli-path.ts +24 -6
- package/server/shared/index.ts +3 -0
- package/server/shared/interfaces.ts +62 -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/types.ts +123 -2
- package/server/shared/utils.ts +40 -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,5 +1,6 @@
|
|
|
1
1
|
import { AbstractProvider } from '@/modules/providers/shared/base/abstract.provider.js';
|
|
2
2
|
import { CodexProviderAuth } from '@/modules/providers/list/codex/codex-auth.provider.js';
|
|
3
|
+
import { CodexForkProvider } from '@/modules/providers/list/codex/codex-fork.provider.js';
|
|
3
4
|
import { CodexProviderModels } from '@/modules/providers/list/codex/codex-models.provider.js';
|
|
4
5
|
import { codexRuntime } from '@/modules/providers/list/codex/codex-runtime.provider.js';
|
|
5
6
|
import { CodexMcpProvider } from '@/modules/providers/list/codex/codex-mcp.provider.js';
|
|
@@ -8,6 +9,7 @@ import { CodexSessionsProvider } from '@/modules/providers/list/codex/codex-sess
|
|
|
8
9
|
import { CodexSkillsProvider } from '@/modules/providers/list/codex/codex-skills.provider.js';
|
|
9
10
|
import type {
|
|
10
11
|
IProviderAuth,
|
|
12
|
+
IProviderFork,
|
|
11
13
|
IProviderModels,
|
|
12
14
|
IProviderRuntime,
|
|
13
15
|
IProviderSessionSynchronizer,
|
|
@@ -22,6 +24,7 @@ export class CodexProvider extends AbstractProvider {
|
|
|
22
24
|
readonly auth: IProviderAuth = new CodexProviderAuth();
|
|
23
25
|
readonly skills: IProviderSkills = new CodexSkillsProvider();
|
|
24
26
|
readonly sessions: IProviderSessions = new CodexSessionsProvider();
|
|
27
|
+
readonly fork: IProviderFork = new CodexForkProvider();
|
|
25
28
|
readonly sessionSynchronizer: IProviderSessionSynchronizer = new CodexSessionSynchronizer();
|
|
26
29
|
|
|
27
30
|
constructor() {
|
|
@@ -30,22 +30,24 @@ function isWorkspaceTrustPrompt(text = '') {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async function spawnCursor(command, options = {}, ws, context) {
|
|
33
|
-
|
|
33
|
+
// Callers pass the stable app session id; the CLI resumes with the
|
|
34
|
+
// provider-native id recorded on the session row. Both lookups run before the
|
|
35
|
+
// promise is created: inside an async executor a rejected `resolveResumeModel`
|
|
36
|
+
// would be swallowed and leave the returned promise pending forever.
|
|
37
|
+
const providerSessionId = context.resolveProviderSessionId(options.sessionId);
|
|
38
|
+
const resolvedModel = await context.resolveResumeModel(options.sessionId, options.model);
|
|
39
|
+
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
34
41
|
const {
|
|
35
42
|
sessionId,
|
|
36
43
|
projectPath,
|
|
37
44
|
cwd,
|
|
38
45
|
toolsSettings,
|
|
39
46
|
skipPermissions,
|
|
40
|
-
model,
|
|
41
47
|
sessionSummary,
|
|
42
48
|
images,
|
|
43
49
|
files
|
|
44
50
|
} = options;
|
|
45
|
-
// Callers pass the stable app session id; the CLI resumes with the
|
|
46
|
-
// provider-native id recorded on the session row.
|
|
47
|
-
const providerSessionId = context.resolveProviderSessionId(sessionId);
|
|
48
|
-
const resolvedModel = await context.resolveResumeModel(sessionId, model);
|
|
49
51
|
let capturedSessionId = providerSessionId; // Track the provider-native session id throughout the process
|
|
50
52
|
let sessionCreatedSent = false; // Track if we've already sent session-created event
|
|
51
53
|
let hasRetriedWithTrust = false;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
1
5
|
import Database from 'better-sqlite3';
|
|
2
6
|
|
|
3
7
|
import { sessionsDb } from '@/modules/database/index.js';
|
|
@@ -17,9 +21,9 @@ import {
|
|
|
17
21
|
* Curated OpenCode catalog shipped as immutable CloudCLI defaults.
|
|
18
22
|
*
|
|
19
23
|
* OpenCode routes by `<providerID>/<modelID>`, so this list mirrors the
|
|
20
|
-
* providers `opencode models --verbose` reports: the OpenCode Zen gateway
|
|
21
|
-
* the Anthropic and OpenAI providers
|
|
22
|
-
* user's own credentials.
|
|
24
|
+
* providers `opencode models --verbose` reports: the OpenCode Zen gateway, the
|
|
25
|
+
* OpenCode Go subscription gateway, and the Anthropic and OpenAI providers
|
|
26
|
+
* OpenCode can address directly with the user's own credentials.
|
|
23
27
|
*/
|
|
24
28
|
export const OPENCODE_PREDEFINED_MODELS: ProviderModelsDefinition = {
|
|
25
29
|
OPTIONS: [
|
|
@@ -77,6 +81,178 @@ export const OPENCODE_PREDEFINED_MODELS: ProviderModelsDefinition = {
|
|
|
77
81
|
{ value: 'opencode/north-mini-code-free', label: 'North Mini Code Free', description: 'OpenCode Zen · Free' },
|
|
78
82
|
{ value: 'opencode/nemotron-3-ultra-free', label: 'Nemotron 3 Ultra Free', description: 'OpenCode Zen · Free' },
|
|
79
83
|
{ value: 'opencode/deepseek-v4-flash-free', label: 'DeepSeek V4 Flash Free', description: 'OpenCode Zen · Free' },
|
|
84
|
+
{
|
|
85
|
+
value: 'opencode-go/grok-4.6',
|
|
86
|
+
label: 'Grok 4.6',
|
|
87
|
+
description: 'OpenCode Go',
|
|
88
|
+
effort: {
|
|
89
|
+
values: [{ value: 'low' }, { value: 'medium' }, { value: 'high' }, { value: 'xhigh' }],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
value: 'opencode-go/glm-5.3-flash',
|
|
94
|
+
label: 'GLM 5.3 Flash',
|
|
95
|
+
description: 'OpenCode Go',
|
|
96
|
+
effort: {
|
|
97
|
+
values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
value: 'opencode-go/glm-5.3',
|
|
102
|
+
label: 'GLM 5.3',
|
|
103
|
+
description: 'OpenCode Go',
|
|
104
|
+
effort: {
|
|
105
|
+
values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
value: 'opencode-go/glm-5.2',
|
|
110
|
+
label: 'GLM 5.2',
|
|
111
|
+
description: 'OpenCode Go',
|
|
112
|
+
effort: {
|
|
113
|
+
values: [{ value: 'high' }, { value: 'max' }],
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{ value: 'opencode-go/glm-5.1', label: 'GLM 5.1', description: 'OpenCode Go' },
|
|
117
|
+
{
|
|
118
|
+
value: 'opencode-go/gpt-5.6-luna',
|
|
119
|
+
label: 'GPT 5.6 Luna',
|
|
120
|
+
description: 'OpenCode Go',
|
|
121
|
+
effort: {
|
|
122
|
+
values: [
|
|
123
|
+
{ value: 'none' },
|
|
124
|
+
{ value: 'low' },
|
|
125
|
+
{ value: 'medium' },
|
|
126
|
+
{ value: 'high' },
|
|
127
|
+
{ value: 'xhigh' },
|
|
128
|
+
{ value: 'max' },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
value: 'opencode-go/kimi-k3',
|
|
134
|
+
label: 'Kimi K3',
|
|
135
|
+
description: 'OpenCode Go',
|
|
136
|
+
effort: {
|
|
137
|
+
values: [{ value: 'max' }],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{ value: 'opencode-go/kimi-k2.7-code', label: 'Kimi K2.7 Code', description: 'OpenCode Go' },
|
|
141
|
+
{ value: 'opencode-go/kimi-k2.6', label: 'Kimi K2.6', description: 'OpenCode Go' },
|
|
142
|
+
{
|
|
143
|
+
value: 'opencode-go/longcat-2.0',
|
|
144
|
+
label: 'LongCat 2.0',
|
|
145
|
+
description: 'OpenCode Go',
|
|
146
|
+
effort: {
|
|
147
|
+
values: [{ value: 'low' }, { value: 'medium' }, { value: 'high' }],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{ value: 'opencode-go/mimo-v2.5', label: 'MiMo V2.5', description: 'OpenCode Go' },
|
|
151
|
+
{ value: 'opencode-go/mimo-v2.5-pro', label: 'MiMo V2.5 Pro', description: 'OpenCode Go' },
|
|
152
|
+
{
|
|
153
|
+
value: 'opencode-go/minimax-m3',
|
|
154
|
+
label: 'MiniMax M3',
|
|
155
|
+
description: 'OpenCode Go',
|
|
156
|
+
effort: {
|
|
157
|
+
values: [{ value: 'none' }, { value: 'thinking' }],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{ value: 'opencode-go/minimax-m2.7', label: 'MiniMax M2.7', description: 'OpenCode Go' },
|
|
161
|
+
{
|
|
162
|
+
value: 'opencode-go/muse-spark-1.3-contributor',
|
|
163
|
+
label: 'Muse Spark 1.3 Contributor',
|
|
164
|
+
description: 'OpenCode Go',
|
|
165
|
+
effort: {
|
|
166
|
+
values: [
|
|
167
|
+
{ value: 'minimal' },
|
|
168
|
+
{ value: 'low' },
|
|
169
|
+
{ value: 'medium' },
|
|
170
|
+
{ value: 'high' },
|
|
171
|
+
{ value: 'xhigh' },
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
value: 'opencode-go/muse-spark-1.2-contributor',
|
|
177
|
+
label: 'Muse Spark 1.2 Contributor',
|
|
178
|
+
description: 'OpenCode Go',
|
|
179
|
+
effort: {
|
|
180
|
+
values: [
|
|
181
|
+
{ value: 'minimal' },
|
|
182
|
+
{ value: 'low' },
|
|
183
|
+
{ value: 'medium' },
|
|
184
|
+
{ value: 'high' },
|
|
185
|
+
{ value: 'xhigh' },
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
value: 'opencode-go/qwen3.8-max',
|
|
191
|
+
label: 'Qwen3.8 Max',
|
|
192
|
+
description: 'OpenCode Go',
|
|
193
|
+
effort: {
|
|
194
|
+
values: [{ value: 'low' }, { value: 'medium' }, { value: 'xhigh' }],
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
value: 'opencode-go/qwen3.8-flash',
|
|
199
|
+
label: 'Qwen3.8 Flash',
|
|
200
|
+
description: 'OpenCode Go',
|
|
201
|
+
effort: {
|
|
202
|
+
values: [{ value: 'low' }, { value: 'medium' }, { value: 'xhigh' }],
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
{ value: 'opencode-go/qwen3.7-max', label: 'Qwen3.7 Max', description: 'OpenCode Go' },
|
|
206
|
+
{ value: 'opencode-go/qwen3.7-plus', label: 'Qwen3.7 Plus', description: 'OpenCode Go' },
|
|
207
|
+
{ value: 'opencode-go/qwen3.6-plus', label: 'Qwen3.6 Plus', description: 'OpenCode Go' },
|
|
208
|
+
{
|
|
209
|
+
value: 'opencode-go/deepseek-v4-pro',
|
|
210
|
+
label: 'DeepSeek V4 Pro',
|
|
211
|
+
description: 'OpenCode Go',
|
|
212
|
+
effort: {
|
|
213
|
+
values: [{ value: 'high' }, { value: 'max' }],
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
value: 'opencode-go/deepseek-v4-flash',
|
|
218
|
+
label: 'DeepSeek V4 Flash',
|
|
219
|
+
description: 'OpenCode Go',
|
|
220
|
+
effort: {
|
|
221
|
+
values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
value: 'opencode-go/deepseek-v4-flash-vision-exp',
|
|
226
|
+
label: 'DeepSeek V4 Flash Vision Exp',
|
|
227
|
+
description: 'OpenCode Go',
|
|
228
|
+
effort: {
|
|
229
|
+
values: [{ value: 'low' }, { value: 'high' }, { value: 'max' }],
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
value: 'opencode-go/hy4-preview',
|
|
234
|
+
label: 'Hy4 Preview',
|
|
235
|
+
description: 'OpenCode Go',
|
|
236
|
+
effort: {
|
|
237
|
+
values: [{ value: 'none' }, { value: 'high' }],
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
value: 'opencode-go/hy3',
|
|
242
|
+
label: 'Hy3',
|
|
243
|
+
description: 'OpenCode Go',
|
|
244
|
+
effort: {
|
|
245
|
+
values: [{ value: 'none' }, { value: 'low' }, { value: 'high' }],
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
value: 'opencode-go/omen-alpha',
|
|
250
|
+
label: 'Omen Alpha',
|
|
251
|
+
description: 'OpenCode Go',
|
|
252
|
+
effort: {
|
|
253
|
+
values: [{ value: 'low' }, { value: 'high' }],
|
|
254
|
+
},
|
|
255
|
+
},
|
|
80
256
|
{ value: 'anthropic/claude-opus-5', label: 'Claude Opus 5', description: 'Anthropic' },
|
|
81
257
|
{ value: 'anthropic/claude-opus-5-fast', label: 'Claude Opus 5 Fast', description: 'Anthropic' },
|
|
82
258
|
{ value: 'anthropic/claude-fable-5', label: 'Claude Fable 5', description: 'Anthropic' },
|
|
@@ -117,6 +293,100 @@ export const OPENCODE_PREDEFINED_MODELS: ProviderModelsDefinition = {
|
|
|
117
293
|
DEFAULT: 'opencode/gpt-5.6-terra',
|
|
118
294
|
};
|
|
119
295
|
|
|
296
|
+
/** Global OpenCode config files, in the order the CLI loads them. */
|
|
297
|
+
const OPENCODE_CONFIG_FILES = ['config.json', 'opencode.json', 'opencode.jsonc'];
|
|
298
|
+
|
|
299
|
+
/** Provider API keys OpenCode reads straight from the environment. */
|
|
300
|
+
const OPENCODE_ENV_PROVIDER_IDS: Record<string, string> = {
|
|
301
|
+
OPENCODE_API_KEY: 'opencode',
|
|
302
|
+
ANTHROPIC_API_KEY: 'anthropic',
|
|
303
|
+
OPENAI_API_KEY: 'openai',
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const readOpenCodeJsonFile = async (filePath: string): Promise<Record<string, unknown> | null> => {
|
|
307
|
+
try {
|
|
308
|
+
return readObjectRecord(JSON.parse(await readFile(filePath, 'utf8')));
|
|
309
|
+
} catch {
|
|
310
|
+
// Missing, unreadable, or comment-bearing (.jsonc) files simply contribute
|
|
311
|
+
// nothing; the auth store is the authoritative source below.
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Lists the upstream providers this OpenCode install can actually route to.
|
|
318
|
+
*
|
|
319
|
+
* OpenCode resolves `<providerID>/<modelID>` against the providers the user has
|
|
320
|
+
* connected, and rejects anything else outright - `Model
|
|
321
|
+
* opencode/claude-sonnet-4-6 is not valid` is what a run gets for asking for an
|
|
322
|
+
* OpenCode Zen model on a machine that only has an Anthropic key. The curated
|
|
323
|
+
* catalog spans every provider OpenCode can address, so it has to be narrowed
|
|
324
|
+
* to this machine's providers before it reaches the model picker.
|
|
325
|
+
*
|
|
326
|
+
* Returns null when nothing can be read, so the caller keeps the full catalog
|
|
327
|
+
* rather than leaving the picker empty. Providers declared only in a
|
|
328
|
+
* project-level `opencode.json` are not visible here; the null fallback and the
|
|
329
|
+
* env-key sweep keep those installs on the full list.
|
|
330
|
+
*/
|
|
331
|
+
const readConnectedOpenCodeProviderIds = async (): Promise<Set<string> | null> => {
|
|
332
|
+
const providerIds = new Set<string>();
|
|
333
|
+
const configDir = path.join(os.homedir(), '.config', 'opencode');
|
|
334
|
+
|
|
335
|
+
const auth = await readOpenCodeJsonFile(
|
|
336
|
+
path.join(os.homedir(), '.local', 'share', 'opencode', 'auth.json'),
|
|
337
|
+
);
|
|
338
|
+
for (const [providerId, credential] of Object.entries(auth ?? {})) {
|
|
339
|
+
if (readObjectRecord(credential)) {
|
|
340
|
+
providerIds.add(providerId);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
for (const configFile of OPENCODE_CONFIG_FILES) {
|
|
345
|
+
const config = await readOpenCodeJsonFile(path.join(configDir, configFile));
|
|
346
|
+
for (const providerId of Object.keys(readObjectRecord(config?.provider) ?? {})) {
|
|
347
|
+
providerIds.add(providerId);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
for (const [envKey, providerId] of Object.entries(OPENCODE_ENV_PROVIDER_IDS)) {
|
|
352
|
+
if (readOptionalString(process.env[envKey])) {
|
|
353
|
+
providerIds.add(providerId);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return providerIds.size > 0 ? providerIds : null;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Narrows the curated catalog to the providers OpenCode can route to.
|
|
362
|
+
*
|
|
363
|
+
* The default has to move with the list: leaving it on an OpenCode Zen model
|
|
364
|
+
* would hand every new session a model the CLI refuses to run.
|
|
365
|
+
*/
|
|
366
|
+
const filterOpenCodeModelsByProvider = (
|
|
367
|
+
definition: ProviderModelsDefinition,
|
|
368
|
+
connectedProviderIds: Set<string> | null,
|
|
369
|
+
): ProviderModelsDefinition => {
|
|
370
|
+
if (!connectedProviderIds) {
|
|
371
|
+
return definition;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const options = definition.OPTIONS.filter(
|
|
375
|
+
(option) => connectedProviderIds.has(option.value.split('/')[0]),
|
|
376
|
+
);
|
|
377
|
+
if (options.length === 0) {
|
|
378
|
+
return definition;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return {
|
|
382
|
+
...definition,
|
|
383
|
+
OPTIONS: options,
|
|
384
|
+
DEFAULT: options.some((option) => option.value === definition.DEFAULT)
|
|
385
|
+
? definition.DEFAULT
|
|
386
|
+
: options[0].value,
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
|
|
120
390
|
const parseOpenCodeSessionModelValue = (rawModel: unknown): string | null => {
|
|
121
391
|
if (typeof rawModel === 'string') {
|
|
122
392
|
const trimmed = rawModel.trim();
|
|
@@ -146,12 +416,15 @@ const parseOpenCodeSessionModelValue = (rawModel: unknown): string | null => {
|
|
|
146
416
|
/** Provider registry model adapter for OpenCode predefined models and session metadata. */
|
|
147
417
|
export class OpenCodeProviderModels implements IProviderModels {
|
|
148
418
|
async getSupportedModels(): Promise<ProviderModelsDefinition> {
|
|
149
|
-
return
|
|
419
|
+
return filterOpenCodeModelsByProvider(
|
|
420
|
+
OPENCODE_PREDEFINED_MODELS,
|
|
421
|
+
await readConnectedOpenCodeProviderIds(),
|
|
422
|
+
);
|
|
150
423
|
}
|
|
151
424
|
|
|
152
425
|
async getCurrentActiveModel(sessionId?: string): Promise<ProviderCurrentActiveModel> {
|
|
153
426
|
if (!sessionId?.trim()) {
|
|
154
|
-
return buildDefaultProviderCurrentActiveModel(
|
|
427
|
+
return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
|
|
155
428
|
}
|
|
156
429
|
|
|
157
430
|
// OpenCode's `session` table is keyed by its own session id, so the stable
|
|
@@ -198,6 +471,6 @@ export class OpenCodeProviderModels implements IProviderModels {
|
|
|
198
471
|
// Fall through to the curated default when OpenCode session lookup fails.
|
|
199
472
|
}
|
|
200
473
|
|
|
201
|
-
return buildDefaultProviderCurrentActiveModel(
|
|
474
|
+
return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
|
|
202
475
|
}
|
|
203
476
|
}
|
|
@@ -297,6 +297,28 @@ const parseProvider = (value: unknown): LLMProvider => {
|
|
|
297
297
|
});
|
|
298
298
|
};
|
|
299
299
|
|
|
300
|
+
/** Both fields are optional: an empty body forks the whole conversation. */
|
|
301
|
+
const parseSessionForkPayload = (payload: unknown): { upToAnchorId?: string; title?: string } => {
|
|
302
|
+
if (payload === undefined || payload === null) {
|
|
303
|
+
return {};
|
|
304
|
+
}
|
|
305
|
+
if (typeof payload !== 'object') {
|
|
306
|
+
throw new AppError('Request body must be an object.', {
|
|
307
|
+
code: 'INVALID_REQUEST_BODY',
|
|
308
|
+
statusCode: 400,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const body = payload as Record<string, unknown>;
|
|
313
|
+
const upToAnchorId = typeof body.upToAnchorId === 'string' ? body.upToAnchorId.trim() : '';
|
|
314
|
+
const title = typeof body.title === 'string' ? body.title.trim() : '';
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
...(upToAnchorId ? { upToAnchorId } : {}),
|
|
318
|
+
...(title ? { title } : {}),
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
|
|
300
322
|
const parseSessionRenameSummary = (payload: unknown): string => {
|
|
301
323
|
if (!payload || typeof payload !== 'object') {
|
|
302
324
|
throw new AppError('Request body must be an object.', {
|
|
@@ -792,6 +814,15 @@ router.post(
|
|
|
792
814
|
}),
|
|
793
815
|
);
|
|
794
816
|
|
|
817
|
+
router.post(
|
|
818
|
+
'/sessions/:sessionId/fork',
|
|
819
|
+
asyncHandler(async (req: Request, res: Response) => {
|
|
820
|
+
const sessionId = parseSessionId(req.params.sessionId);
|
|
821
|
+
const result = await sessionsService.forkSessionById(sessionId, parseSessionForkPayload(req.body));
|
|
822
|
+
res.status(201).json(createApiSuccessResponse(result));
|
|
823
|
+
}),
|
|
824
|
+
);
|
|
825
|
+
|
|
795
826
|
router.put(
|
|
796
827
|
'/sessions/:sessionId',
|
|
797
828
|
asyncHandler(async (req: Request, res: Response) => {
|
|
@@ -25,6 +25,15 @@ type ProviderCapabilities = {
|
|
|
25
25
|
supportsTokenUsage: boolean;
|
|
26
26
|
/** Whether the provider runtime can accept model-level reasoning effort. */
|
|
27
27
|
supportsEffort: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Whether an already-sent message can be replaced, which requires the
|
|
30
|
+
* provider to re-run a conversation truncated at a chosen point.
|
|
31
|
+
*/
|
|
32
|
+
supportsMessageEditing: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Whether a session's transcript can be branched into an independent one.
|
|
35
|
+
*/
|
|
36
|
+
supportsSessionForking: boolean;
|
|
28
37
|
};
|
|
29
38
|
|
|
30
39
|
/**
|
|
@@ -44,6 +53,10 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
44
53
|
supportsPermissionRequests: true,
|
|
45
54
|
supportsTokenUsage: true,
|
|
46
55
|
supportsEffort: true,
|
|
56
|
+
// `resumeSessionAt` re-runs a conversation truncated at a message, and
|
|
57
|
+
// `forkSession` copies a transcript prefix into a new session file.
|
|
58
|
+
supportsMessageEditing: true,
|
|
59
|
+
supportsSessionForking: true,
|
|
47
60
|
},
|
|
48
61
|
cursor: {
|
|
49
62
|
provider: 'cursor',
|
|
@@ -55,6 +68,8 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
55
68
|
supportsPermissionRequests: false,
|
|
56
69
|
supportsTokenUsage: false,
|
|
57
70
|
supportsEffort: false,
|
|
71
|
+
supportsMessageEditing: false,
|
|
72
|
+
supportsSessionForking: false,
|
|
58
73
|
},
|
|
59
74
|
codex: {
|
|
60
75
|
provider: 'codex',
|
|
@@ -66,6 +81,12 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
66
81
|
supportsPermissionRequests: false,
|
|
67
82
|
supportsTokenUsage: true,
|
|
68
83
|
supportsEffort: true,
|
|
84
|
+
// Not from the Codex SDK, which only starts and resumes threads: both ride
|
|
85
|
+
// the same CLI's `app-server` protocol, whose `thread/fork` copies a
|
|
86
|
+
// thread up to a chosen turn. Editing is that fork plus a new prompt,
|
|
87
|
+
// which is how Codex's own IDE clients do it.
|
|
88
|
+
supportsMessageEditing: true,
|
|
89
|
+
supportsSessionForking: true,
|
|
69
90
|
},
|
|
70
91
|
opencode: {
|
|
71
92
|
provider: 'opencode',
|
|
@@ -80,6 +101,8 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
80
101
|
supportsPermissionRequests: false,
|
|
81
102
|
supportsTokenUsage: true,
|
|
82
103
|
supportsEffort: true,
|
|
104
|
+
supportsMessageEditing: false,
|
|
105
|
+
supportsSessionForking: false,
|
|
83
106
|
},
|
|
84
107
|
};
|
|
85
108
|
|