@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
|
@@ -7,6 +7,14 @@ import type { ProviderRunFunction } from '@/shared/types.js';
|
|
|
7
7
|
|
|
8
8
|
import { normalizeProjectPath } from '../../shared/utils.js';
|
|
9
9
|
|
|
10
|
+
/** What the route reads off a session row it continues: the row, not the request, says which provider and project a session belongs to. */
|
|
11
|
+
type AgentSessionRow = {
|
|
12
|
+
session_id: string;
|
|
13
|
+
provider: string;
|
|
14
|
+
provider_session_id: string | null;
|
|
15
|
+
project_path: string | null;
|
|
16
|
+
};
|
|
17
|
+
|
|
10
18
|
type AgentRouterDependencies = {
|
|
11
19
|
fileSystem: typeof import('node:fs/promises');
|
|
12
20
|
crypto: typeof import('node:crypto');
|
|
@@ -18,6 +26,14 @@ type AgentRouterDependencies = {
|
|
|
18
26
|
githubTokens: { getActiveGithubToken(userId: number): string | null };
|
|
19
27
|
projects: { createProjectPath(projectPath: string, customName: string | null): unknown };
|
|
20
28
|
models: typeof import('../providers/index.js').providerModelsService;
|
|
29
|
+
/** The session gateway: an API run gets an app session row like a chat send, so the UI can list, open and subscribe to it. */
|
|
30
|
+
sessions: {
|
|
31
|
+
getSessionById(sessionId: string): AgentSessionRow | null;
|
|
32
|
+
getSessionByProviderSessionId(providerSessionId: string): AgentSessionRow | null;
|
|
33
|
+
createAppSession(provider: string, projectPath: string, initialMessage: string): { sessionId: string };
|
|
34
|
+
};
|
|
35
|
+
/** The live-run registry the chat socket uses; registering here is what puts an API run on the running-sessions list. */
|
|
36
|
+
runs: Pick<typeof import('../websocket/index.js').chatRunRegistry, 'startRun' | 'completeRunIfCurrent' | 'isProcessing'>;
|
|
21
37
|
queryClaude: ProviderRunFunction;
|
|
22
38
|
queryCursor: ProviderRunFunction;
|
|
23
39
|
queryCodex: ProviderRunFunction;
|
|
@@ -40,6 +56,8 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
40
56
|
const githubTokensDb = dependencies.githubTokens;
|
|
41
57
|
const projectsDb = dependencies.projects;
|
|
42
58
|
const providerModelsService = dependencies.models;
|
|
59
|
+
const sessionGateway = dependencies.sessions;
|
|
60
|
+
const runRegistry = dependencies.runs;
|
|
43
61
|
const queryClaudeSDK = dependencies.queryClaude;
|
|
44
62
|
const spawnCursor = dependencies.queryCursor;
|
|
45
63
|
const queryCodex = dependencies.queryCodex;
|
|
@@ -384,13 +402,15 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
384
402
|
console.log('🔄 Cloning repository:', githubUrl);
|
|
385
403
|
console.log('📁 Destination:', cloneDir);
|
|
386
404
|
|
|
387
|
-
// Execute git clone
|
|
405
|
+
// Execute git clone. The host was validated above; the helper is
|
|
406
|
+
// still scoped to github.com over https so the token can answer no
|
|
407
|
+
// other challenge (a redirect, say).
|
|
388
408
|
const gitEnvironment = githubToken ? {
|
|
389
409
|
...process.env,
|
|
390
410
|
GIT_CONFIG_COUNT: '2',
|
|
391
411
|
GIT_CONFIG_KEY_0: 'credential.helper',
|
|
392
412
|
GIT_CONFIG_VALUE_0: '',
|
|
393
|
-
GIT_CONFIG_KEY_1: 'credential.helper',
|
|
413
|
+
GIT_CONFIG_KEY_1: 'credential.https://github.com.helper',
|
|
394
414
|
GIT_CONFIG_VALUE_1: '!f() { echo username=x-access-token; echo "password=$CLOUDCLI_GITHUB_TOKEN"; }; f',
|
|
395
415
|
CLOUDCLI_GITHUB_TOKEN: githubToken,
|
|
396
416
|
GIT_TERMINAL_PROMPT: '0'
|
|
@@ -474,14 +494,22 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
474
494
|
}
|
|
475
495
|
|
|
476
496
|
/**
|
|
477
|
-
* SSE Stream Writer -
|
|
497
|
+
* SSE Stream Writer - the HTTP response as one audience of a registered run.
|
|
498
|
+
*
|
|
499
|
+
* The provider runtime no longer writes here directly: it writes to the
|
|
500
|
+
* run's gateway writer, which remaps, sequences and buffers every event
|
|
501
|
+
* and forwards it — as a JSON string, the way it reaches a websocket — to
|
|
502
|
+
* each connection watching the run, this one included. The route's own
|
|
503
|
+
* events (status, session-id, GitHub results, done) are objects.
|
|
478
504
|
*/
|
|
479
505
|
class SSEStreamWriter {
|
|
480
|
-
constructor(res
|
|
506
|
+
constructor(res) {
|
|
481
507
|
this.res = res;
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/** What the gateway writer checks before forwarding: open until the response has ended. */
|
|
511
|
+
get readyState() {
|
|
512
|
+
return this.res.writableEnded ? 3 : 1;
|
|
485
513
|
}
|
|
486
514
|
|
|
487
515
|
send(data) {
|
|
@@ -489,8 +517,7 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
489
517
|
return;
|
|
490
518
|
}
|
|
491
519
|
|
|
492
|
-
|
|
493
|
-
this.res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
520
|
+
this.res.write(`data: ${typeof data === 'string' ? data : JSON.stringify(data)}\n\n`);
|
|
494
521
|
}
|
|
495
522
|
|
|
496
523
|
end() {
|
|
@@ -499,133 +526,72 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
499
526
|
this.res.end();
|
|
500
527
|
}
|
|
501
528
|
}
|
|
502
|
-
|
|
503
|
-
setSessionId(sessionId) {
|
|
504
|
-
this.sessionId = sessionId;
|
|
505
|
-
this.send({ type: 'session-id', sessionId });
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
getSessionId() {
|
|
509
|
-
return this.sessionId;
|
|
510
|
-
}
|
|
511
529
|
}
|
|
512
530
|
|
|
513
531
|
/**
|
|
514
|
-
* Non-streaming response collector
|
|
532
|
+
* Non-streaming response collector - the same audience role, kept in
|
|
533
|
+
* memory until the run ends.
|
|
515
534
|
*/
|
|
516
535
|
class ResponseCollector {
|
|
517
|
-
constructor(
|
|
536
|
+
constructor() {
|
|
518
537
|
this.messages = [];
|
|
519
|
-
this.sessionId = null;
|
|
520
|
-
this.userId = userId;
|
|
521
538
|
}
|
|
522
539
|
|
|
523
|
-
|
|
524
|
-
// Store ALL messages for now - we'll filter when returning
|
|
525
|
-
this.messages.push(data);
|
|
540
|
+
readyState = 1;
|
|
526
541
|
|
|
527
|
-
|
|
542
|
+
send(data) {
|
|
543
|
+
// The run's events arrive as JSON strings; the route's own as objects.
|
|
544
|
+
// Stored as objects either way so the filters below read one shape.
|
|
545
|
+
let record = data;
|
|
528
546
|
if (typeof data === 'string') {
|
|
529
547
|
try {
|
|
530
|
-
|
|
531
|
-
if (parsed.sessionId) {
|
|
532
|
-
this.sessionId = parsed.sessionId;
|
|
533
|
-
}
|
|
548
|
+
record = JSON.parse(data);
|
|
534
549
|
} catch (e) {
|
|
535
|
-
// Not JSON,
|
|
550
|
+
// Not JSON, keep as is
|
|
536
551
|
}
|
|
537
|
-
} else if (data && data.sessionId) {
|
|
538
|
-
this.sessionId = data.sessionId;
|
|
539
552
|
}
|
|
553
|
+
this.messages.push(record);
|
|
540
554
|
}
|
|
541
555
|
|
|
542
556
|
end() {
|
|
543
557
|
// Do nothing - we'll collect all messages
|
|
544
558
|
}
|
|
545
559
|
|
|
546
|
-
setSessionId(sessionId) {
|
|
547
|
-
this.sessionId = sessionId;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
getSessionId() {
|
|
551
|
-
return this.sessionId;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
560
|
getMessages() {
|
|
555
561
|
return this.messages;
|
|
556
562
|
}
|
|
557
563
|
|
|
558
564
|
/**
|
|
559
|
-
*
|
|
565
|
+
* The assistant's replies, as the normalized `text` events the run
|
|
566
|
+
* produced. (Earlier versions filtered a `claude-response` shape no
|
|
567
|
+
* runtime has emitted since the providers were unified, so this was
|
|
568
|
+
* always empty.)
|
|
560
569
|
*/
|
|
561
570
|
getAssistantMessages() {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
for (const msg of this.messages) {
|
|
565
|
-
// Skip initial status message
|
|
566
|
-
if (msg && msg.type === 'status') {
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// Handle JSON strings
|
|
571
|
-
if (typeof msg === 'string') {
|
|
572
|
-
try {
|
|
573
|
-
const parsed = JSON.parse(msg);
|
|
574
|
-
// Only include claude-response messages with assistant type
|
|
575
|
-
if (parsed.type === 'claude-response' && parsed.data && parsed.data.type === 'assistant') {
|
|
576
|
-
assistantMessages.push(parsed.data);
|
|
577
|
-
}
|
|
578
|
-
} catch (e) {
|
|
579
|
-
// Not JSON, skip
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
return assistantMessages;
|
|
571
|
+
return this.messages.filter((msg) => msg && msg.kind === 'text' && msg.role === 'assistant');
|
|
585
572
|
}
|
|
586
573
|
|
|
587
574
|
/**
|
|
588
|
-
*
|
|
575
|
+
* The run's token usage, from the last context-window report the
|
|
576
|
+
* runtime streamed (`status` / `token_budget`, which the Claude and Codex
|
|
577
|
+
* runtimes emit per assistant message); zeros for a runtime that
|
|
578
|
+
* reports none.
|
|
589
579
|
*/
|
|
590
580
|
getTotalTokens() {
|
|
591
|
-
let
|
|
592
|
-
let totalOutput = 0;
|
|
593
|
-
let totalCacheRead = 0;
|
|
594
|
-
let totalCacheCreation = 0;
|
|
595
|
-
|
|
581
|
+
let budget = null;
|
|
596
582
|
for (const msg of this.messages) {
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
// Parse if string
|
|
600
|
-
if (typeof msg === 'string') {
|
|
601
|
-
try {
|
|
602
|
-
data = JSON.parse(msg);
|
|
603
|
-
} catch (e) {
|
|
604
|
-
continue;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// Extract usage from claude-response messages
|
|
609
|
-
if (data && data.type === 'claude-response' && data.data) {
|
|
610
|
-
const msgData = data.data;
|
|
611
|
-
if (msgData.message && msgData.message.usage) {
|
|
612
|
-
const usage = msgData.message.usage;
|
|
613
|
-
totalInput += usage.input_tokens || 0;
|
|
614
|
-
totalOutput += usage.output_tokens || 0;
|
|
615
|
-
totalCacheRead += usage.cache_read_input_tokens || 0;
|
|
616
|
-
totalCacheCreation += usage.cache_creation_input_tokens || 0;
|
|
617
|
-
}
|
|
583
|
+
if (msg && msg.kind === 'status' && msg.text === 'token_budget' && msg.tokenBudget) {
|
|
584
|
+
budget = msg.tokenBudget;
|
|
618
585
|
}
|
|
619
586
|
}
|
|
620
|
-
|
|
621
|
-
const
|
|
622
|
-
|
|
587
|
+
const inputTokens = budget?.inputTokens ?? 0;
|
|
588
|
+
const outputTokens = budget?.outputTokens ?? 0;
|
|
623
589
|
return {
|
|
624
590
|
inputTokens,
|
|
625
|
-
outputTokens
|
|
626
|
-
cacheReadTokens:
|
|
627
|
-
cacheCreationTokens:
|
|
628
|
-
totalTokens: inputTokens +
|
|
591
|
+
outputTokens,
|
|
592
|
+
cacheReadTokens: budget?.cacheReadTokens ?? 0,
|
|
593
|
+
cacheCreationTokens: budget?.cacheCreationTokens ?? 0,
|
|
594
|
+
totalTokens: inputTokens + outputTokens
|
|
629
595
|
};
|
|
630
596
|
}
|
|
631
597
|
}
|
|
@@ -670,6 +636,11 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
670
636
|
* - true: Returns text/event-stream with incremental updates
|
|
671
637
|
* - false: Returns complete JSON response after completion
|
|
672
638
|
*
|
|
639
|
+
* @param {string} sessionId - (Optional) Continue an existing session: the id an earlier
|
|
640
|
+
* response reported as `sessionId` / in its `session-id` event.
|
|
641
|
+
* A session already mid-run is refused (409); an unknown id, 404.
|
|
642
|
+
* Omitted: a new session is created for the run.
|
|
643
|
+
*
|
|
673
644
|
* @param {string} model - (Optional) Model identifier for providers.
|
|
674
645
|
*
|
|
675
646
|
* Claude models: 'default', 'sonnet', 'opus', 'haiku', 'sonnet[1m]', 'opus[1m]', 'fable'
|
|
@@ -807,11 +778,21 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
807
778
|
* RESPONSE FORMATS
|
|
808
779
|
* ================================================================================================
|
|
809
780
|
*
|
|
781
|
+
* Every run is registered with the chat run registry like a message sent
|
|
782
|
+
* from the UI: it is on GET /api/providers/sessions/running while it goes,
|
|
783
|
+
* a tab that opens the session subscribes to it live, and its events
|
|
784
|
+
* reach this response the way they reach a tab — `sessionId` is the app
|
|
785
|
+
* session id, each event carries a `seq`, and the provider's own
|
|
786
|
+
* `session_created` is folded into the session row instead of forwarded.
|
|
787
|
+
*
|
|
810
788
|
* Streaming Response (stream=true):
|
|
811
789
|
* Content-Type: text/event-stream
|
|
812
790
|
* Events:
|
|
813
791
|
* - { type: "status", message: "...", projectPath: "..." }
|
|
814
|
-
* - { type: "
|
|
792
|
+
* - { type: "session-id", sessionId: "..." } // the app session id, usable as `sessionId` later
|
|
793
|
+
* - { kind: "text" | "tool_use" | ... , sessionId, seq, ... } // the provider's normalized events
|
|
794
|
+
* - { kind: "complete", ... }
|
|
795
|
+
* - { type: "status", message: "Run aborted", aborted: true } // only when a tab aborted the run; no branch/PR follows
|
|
815
796
|
* - { type: "github-branch", branch: { name: "...", url: "..." } }
|
|
816
797
|
* - { type: "github-pr", pullRequest: { number: 42, url: "..." } }
|
|
817
798
|
* - { type: "github-error", error: "..." }
|
|
@@ -820,9 +801,10 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
820
801
|
* Non-Streaming Response (stream=false):
|
|
821
802
|
* Content-Type: application/json
|
|
822
803
|
* {
|
|
823
|
-
* success: true,
|
|
824
|
-
* sessionId: "session-123",
|
|
825
|
-
*
|
|
804
|
+
* success: true, // false, with aborted: true, when a tab aborted the run
|
|
805
|
+
* sessionId: "session-123", // the app session id; pass it back as `sessionId` to continue
|
|
806
|
+
* providerSessionId: "native-id", // the provider's own id, for tooling that drives the CLI directly
|
|
807
|
+
* messages: [...], // The assistant's replies: the run's normalized `text` events
|
|
826
808
|
* tokens: {
|
|
827
809
|
* inputTokens: 150,
|
|
828
810
|
* outputTokens: 50,
|
|
@@ -842,7 +824,7 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
842
824
|
* }
|
|
843
825
|
*
|
|
844
826
|
* Error Response:
|
|
845
|
-
* HTTP Status: 400, 401, 500
|
|
827
|
+
* HTTP Status: 400, 401, 404 (unknown sessionId), 409 (session already mid-run), 500
|
|
846
828
|
* Content-Type: application/json
|
|
847
829
|
* { success: false, error: "Error description" }
|
|
848
830
|
*
|
|
@@ -874,7 +856,15 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
874
856
|
* }
|
|
875
857
|
*/
|
|
876
858
|
router.post('/', validateExternalApiKey, async (req, res) => {
|
|
877
|
-
const { githubUrl, projectPath, message,
|
|
859
|
+
const { githubUrl, projectPath, message, model, githubToken, branchName } = req.body;
|
|
860
|
+
// Transport input is typed here, before anything binds it to a query:
|
|
861
|
+
// the lookup below runs outside the try, where a throw would be an
|
|
862
|
+
// unhandled rejection.
|
|
863
|
+
if (req.body.sessionId !== undefined && req.body.sessionId !== null && typeof req.body.sessionId !== 'string') {
|
|
864
|
+
return res.status(400).json({ error: 'sessionId must be a string' });
|
|
865
|
+
}
|
|
866
|
+
const sessionId = typeof req.body.sessionId === 'string' && req.body.sessionId.trim() ? req.body.sessionId.trim() : null;
|
|
867
|
+
const requestedProvider = req.body.provider === undefined || req.body.provider === null ? null : req.body.provider;
|
|
878
868
|
const effort = typeof req.body.effort === 'string' && req.body.effort.trim()
|
|
879
869
|
? req.body.effort.trim()
|
|
880
870
|
: undefined;
|
|
@@ -896,7 +886,7 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
896
886
|
return res.status(400).json({ error: 'message is required' });
|
|
897
887
|
}
|
|
898
888
|
|
|
899
|
-
if (!['claude', 'cursor', 'codex', 'opencode'].includes(
|
|
889
|
+
if (requestedProvider !== null && !['claude', 'cursor', 'codex', 'opencode'].includes(requestedProvider)) {
|
|
900
890
|
return res.status(400).json({ error: 'provider must be "claude", "cursor", "codex", or "opencode"' });
|
|
901
891
|
}
|
|
902
892
|
|
|
@@ -906,9 +896,34 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
906
896
|
return res.status(400).json({ error: 'createBranch and createPR require either githubUrl or projectPath with a GitHub remote' });
|
|
907
897
|
}
|
|
908
898
|
|
|
899
|
+
// A run continues a session the caller names, by its app id or — for a
|
|
900
|
+
// caller that stored what an earlier response called `sessionId` — the
|
|
901
|
+
// provider-native one, which the row is also keyed by once indexed. The
|
|
902
|
+
// row, not the request, says which provider the session belongs to, as
|
|
903
|
+
// it does for a chat send; a request that names another is refused.
|
|
904
|
+
let sessionRow = null;
|
|
905
|
+
if (sessionId) {
|
|
906
|
+
sessionRow = sessionGateway.getSessionById(sessionId) ?? sessionGateway.getSessionByProviderSessionId(sessionId);
|
|
907
|
+
if (!sessionRow) {
|
|
908
|
+
return res.status(404).json({ error: `Session "${sessionId}" was not found` });
|
|
909
|
+
}
|
|
910
|
+
if (requestedProvider !== null && requestedProvider !== sessionRow.provider) {
|
|
911
|
+
return res.status(400).json({ error: `Session "${sessionRow.session_id}" belongs to provider "${sessionRow.provider}"` });
|
|
912
|
+
}
|
|
913
|
+
// Refused before any side effect — a clone per retry would pile up
|
|
914
|
+
// under external-projects. startRun below still has the last word.
|
|
915
|
+
if (runRegistry.isProcessing(sessionRow.session_id)) {
|
|
916
|
+
return res.status(409).json({ error: `Session "${sessionRow.session_id}" already has a run in progress` });
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
const provider = sessionRow?.provider ?? requestedProvider ?? 'claude';
|
|
920
|
+
|
|
909
921
|
let finalProjectPath = null;
|
|
910
922
|
let clonedProjectCreated = false;
|
|
911
923
|
let writer = null;
|
|
924
|
+
// The run as the chat socket registers one: on the running-sessions
|
|
925
|
+
// list, subscribable from any tab, and completed on every exit path.
|
|
926
|
+
let run = null;
|
|
912
927
|
|
|
913
928
|
try {
|
|
914
929
|
// Determine the final project path
|
|
@@ -942,6 +957,12 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
942
957
|
|
|
943
958
|
finalProjectPath = normalizeProjectPath(finalProjectPath);
|
|
944
959
|
|
|
960
|
+
// A continued session runs where it lives, as a chat send does; a
|
|
961
|
+
// request that resolved to another directory is not that session.
|
|
962
|
+
if (sessionRow && sessionRow.project_path && normalizeProjectPath(sessionRow.project_path) !== finalProjectPath) {
|
|
963
|
+
throw new Error(`Session "${sessionRow.session_id}" belongs to project ${sessionRow.project_path}, not ${finalProjectPath}`);
|
|
964
|
+
}
|
|
965
|
+
|
|
945
966
|
// Register project path in DB (or reuse existing active registration)
|
|
946
967
|
const registrationResult = projectsDb.createProjectPath(finalProjectPath, null);
|
|
947
968
|
if (registrationResult.outcome === 'active_conflict') {
|
|
@@ -950,36 +971,53 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
950
971
|
console.log('Project registered:', registrationResult.project);
|
|
951
972
|
}
|
|
952
973
|
|
|
953
|
-
//
|
|
974
|
+
// A brand-new run gets its app session row first, as a chat send does:
|
|
975
|
+
// the id is stable for the conversation, the sidebar can list it, and
|
|
976
|
+
// the provider-native id is mapped onto it when the runtime announces it.
|
|
977
|
+
const appSessionId = sessionRow
|
|
978
|
+
? sessionRow.session_id
|
|
979
|
+
: sessionGateway.createAppSession(provider, finalProjectPath, message.trim()).sessionId;
|
|
980
|
+
|
|
981
|
+
// Registered before any header goes out, so a session already mid-run
|
|
982
|
+
// is refused with a plain 409 rather than an empty stream. The HTTP
|
|
983
|
+
// response is the run's first audience; a tab that opens the session
|
|
984
|
+
// subscribes as another, and replays what it missed.
|
|
985
|
+
const audience = stream ? new SSEStreamWriter(res) : new ResponseCollector();
|
|
986
|
+
run = runRegistry.startRun({
|
|
987
|
+
appSessionId,
|
|
988
|
+
provider,
|
|
989
|
+
providerSessionId: sessionRow?.provider_session_id ?? null,
|
|
990
|
+
connection: audience,
|
|
991
|
+
userId: req.user.id,
|
|
992
|
+
});
|
|
993
|
+
if (!run) {
|
|
994
|
+
if (cleanup && githubUrl && clonedProjectCreated) {
|
|
995
|
+
cleanupProject(finalProjectPath, null);
|
|
996
|
+
}
|
|
997
|
+
return res.status(409).json({ error: `Session "${appSessionId}" already has a run in progress` });
|
|
998
|
+
}
|
|
999
|
+
writer = audience;
|
|
1000
|
+
|
|
954
1001
|
if (stream) {
|
|
955
1002
|
// Set up SSE headers for streaming
|
|
956
1003
|
res.setHeader('Content-Type', 'text/event-stream');
|
|
957
1004
|
res.setHeader('Cache-Control', 'no-cache');
|
|
958
1005
|
res.setHeader('Connection', 'keep-alive');
|
|
959
1006
|
res.setHeader('X-Accel-Buffering', 'no'); // Disable nginx buffering
|
|
960
|
-
|
|
961
|
-
writer = new SSEStreamWriter(res, req.user.id);
|
|
962
|
-
|
|
963
|
-
// Send initial status
|
|
964
|
-
writer.send({
|
|
965
|
-
type: 'status',
|
|
966
|
-
message: githubUrl ? 'Repository cloned and session started' : 'Session started',
|
|
967
|
-
projectPath: finalProjectPath
|
|
968
|
-
});
|
|
969
|
-
} else {
|
|
970
|
-
// Non-streaming mode: collect messages
|
|
971
|
-
writer = new ResponseCollector(req.user.id);
|
|
972
|
-
|
|
973
|
-
// Collect initial status message
|
|
974
|
-
writer.send({
|
|
975
|
-
type: 'status',
|
|
976
|
-
message: githubUrl ? 'Repository cloned and session started' : 'Session started',
|
|
977
|
-
projectPath: finalProjectPath
|
|
978
|
-
});
|
|
979
1007
|
}
|
|
980
1008
|
|
|
981
|
-
|
|
982
|
-
|
|
1009
|
+
// The route's own opening events. `session-id` is the app session id:
|
|
1010
|
+
// what the UI opens the conversation under, and what a later request
|
|
1011
|
+
// passes back as `sessionId` to continue it.
|
|
1012
|
+
writer.send({
|
|
1013
|
+
type: 'status',
|
|
1014
|
+
message: githubUrl ? 'Repository cloned and session started' : 'Session started',
|
|
1015
|
+
projectPath: finalProjectPath
|
|
1016
|
+
});
|
|
1017
|
+
writer.send({ type: 'session-id', sessionId: appSessionId });
|
|
1018
|
+
|
|
1019
|
+
const codexModels = await providerModelsService.getProviderModels('codex');
|
|
1020
|
+
const opencodeModels = await providerModelsService.getProviderModels('opencode');
|
|
983
1021
|
|
|
984
1022
|
// Start the appropriate session
|
|
985
1023
|
if (provider === 'claude') {
|
|
@@ -988,11 +1026,11 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
988
1026
|
await queryClaudeSDK(message.trim(), {
|
|
989
1027
|
projectPath: finalProjectPath,
|
|
990
1028
|
cwd: finalProjectPath,
|
|
991
|
-
sessionId:
|
|
1029
|
+
sessionId: appSessionId,
|
|
992
1030
|
model: model,
|
|
993
1031
|
effort,
|
|
994
1032
|
permissionMode: 'bypassPermissions' // Bypass all permissions for API calls
|
|
995
|
-
}, writer);
|
|
1033
|
+
}, run.writer);
|
|
996
1034
|
|
|
997
1035
|
} else if (provider === 'cursor') {
|
|
998
1036
|
console.log('🖱️ Starting Cursor CLI session');
|
|
@@ -1000,39 +1038,47 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
1000
1038
|
await spawnCursor(message.trim(), {
|
|
1001
1039
|
projectPath: finalProjectPath,
|
|
1002
1040
|
cwd: finalProjectPath,
|
|
1003
|
-
sessionId:
|
|
1041
|
+
sessionId: appSessionId,
|
|
1004
1042
|
model: model || undefined,
|
|
1005
1043
|
skipPermissions: true // Bypass permissions for Cursor
|
|
1006
|
-
}, writer);
|
|
1044
|
+
}, run.writer);
|
|
1007
1045
|
} else if (provider === 'codex') {
|
|
1008
1046
|
console.log('🤖 Starting Codex SDK session');
|
|
1009
1047
|
|
|
1010
1048
|
await queryCodex(message.trim(), {
|
|
1011
1049
|
projectPath: finalProjectPath,
|
|
1012
1050
|
cwd: finalProjectPath,
|
|
1013
|
-
sessionId:
|
|
1051
|
+
sessionId: appSessionId,
|
|
1014
1052
|
model: model || codexModels.DEFAULT,
|
|
1015
1053
|
effort,
|
|
1016
1054
|
permissionMode: 'bypassPermissions'
|
|
1017
|
-
}, writer);
|
|
1055
|
+
}, run.writer);
|
|
1018
1056
|
} else if (provider === 'opencode') {
|
|
1019
1057
|
console.log('Starting OpenCode CLI session');
|
|
1020
1058
|
|
|
1021
1059
|
await spawnOpenCode(message.trim(), {
|
|
1022
1060
|
projectPath: finalProjectPath,
|
|
1023
1061
|
cwd: finalProjectPath,
|
|
1024
|
-
sessionId:
|
|
1062
|
+
sessionId: appSessionId,
|
|
1025
1063
|
model: model || opencodeModels.DEFAULT,
|
|
1026
1064
|
effort,
|
|
1027
1065
|
permissionMode: 'bypassPermissions' // Agent runs are non-interactive, like the other providers above
|
|
1028
|
-
}, writer);
|
|
1066
|
+
}, run.writer);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
// A tab can now abort the run (`chat.abort`), on which the runtime
|
|
1070
|
+
// returns as it does on completion. What the interrupted agent left
|
|
1071
|
+
// behind is not a result to branch or open a PR from.
|
|
1072
|
+
const aborted = run.events.some((event) => event.kind === 'complete' && event.aborted === true);
|
|
1073
|
+
if (aborted) {
|
|
1074
|
+
writer.send({ type: 'status', message: 'Run aborted', aborted: true });
|
|
1029
1075
|
}
|
|
1030
1076
|
|
|
1031
1077
|
// Handle GitHub branch and PR creation after successful agent completion
|
|
1032
1078
|
let branchInfo = null;
|
|
1033
1079
|
let prInfo = null;
|
|
1034
1080
|
|
|
1035
|
-
if (createBranch || createPR) {
|
|
1081
|
+
if (!aborted && (createBranch || createPR)) {
|
|
1036
1082
|
try {
|
|
1037
1083
|
console.log('🔄 Starting GitHub branch/PR creation workflow...');
|
|
1038
1084
|
|
|
@@ -1219,8 +1265,12 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
1219
1265
|
const tokenSummary = writer.getTotalTokens();
|
|
1220
1266
|
|
|
1221
1267
|
const response = {
|
|
1222
|
-
success:
|
|
1223
|
-
|
|
1268
|
+
success: !aborted,
|
|
1269
|
+
...(aborted ? { aborted: true } : {}),
|
|
1270
|
+
sessionId: appSessionId,
|
|
1271
|
+
// The provider-native id, for a caller that drives the CLI itself
|
|
1272
|
+
// (`claude --resume`); `sessionId` is what this API and the UI use.
|
|
1273
|
+
providerSessionId: run.writer.getSessionId(),
|
|
1224
1274
|
messages: assistantMessages,
|
|
1225
1275
|
tokens: tokenSummary,
|
|
1226
1276
|
projectPath: finalProjectPath
|
|
@@ -1240,7 +1290,7 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
1240
1290
|
// Clean up if requested
|
|
1241
1291
|
if (cleanup && githubUrl && clonedProjectCreated) {
|
|
1242
1292
|
// Only cleanup if we cloned a repo (not for existing project paths)
|
|
1243
|
-
const sessionIdForCleanup = writer.getSessionId();
|
|
1293
|
+
const sessionIdForCleanup = run.writer.getSessionId();
|
|
1244
1294
|
setTimeout(() => {
|
|
1245
1295
|
cleanupProject(finalProjectPath, sessionIdForCleanup);
|
|
1246
1296
|
}, 5000);
|
|
@@ -1251,7 +1301,7 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
1251
1301
|
|
|
1252
1302
|
// Clean up on error
|
|
1253
1303
|
if (finalProjectPath && cleanup && githubUrl && clonedProjectCreated) {
|
|
1254
|
-
const sessionIdForCleanup =
|
|
1304
|
+
const sessionIdForCleanup = run ? run.writer.getSessionId() : null;
|
|
1255
1305
|
cleanupProject(finalProjectPath, sessionIdForCleanup);
|
|
1256
1306
|
}
|
|
1257
1307
|
|
|
@@ -1263,7 +1313,7 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
1263
1313
|
res.setHeader('Cache-Control', 'no-cache');
|
|
1264
1314
|
res.setHeader('Connection', 'keep-alive');
|
|
1265
1315
|
res.setHeader('X-Accel-Buffering', 'no');
|
|
1266
|
-
writer = new SSEStreamWriter(res
|
|
1316
|
+
writer = new SSEStreamWriter(res);
|
|
1267
1317
|
}
|
|
1268
1318
|
|
|
1269
1319
|
if (!res.writableEnded) {
|
|
@@ -1280,6 +1330,14 @@ export function createAgentRouter(dependencies: AgentRouterDependencies): expres
|
|
|
1280
1330
|
error: error.message
|
|
1281
1331
|
});
|
|
1282
1332
|
}
|
|
1333
|
+
} finally {
|
|
1334
|
+
// Safety net, as for a chat send: a runtime that threw or resolved
|
|
1335
|
+
// without its terminal `complete` would leave the session listed as
|
|
1336
|
+
// running in every tab. Scoped to this run, so a run the session
|
|
1337
|
+
// started meanwhile is left alone.
|
|
1338
|
+
if (run) {
|
|
1339
|
+
runRegistry.completeRunIfCurrent(run, { exitCode: 1 });
|
|
1340
|
+
}
|
|
1283
1341
|
}
|
|
1284
1342
|
});
|
|
1285
1343
|
|