@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
|
@@ -69,13 +69,24 @@ function resolveClaudeWrapperBinary(
|
|
|
69
69
|
return null;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Windows has no PATH lookup to fall back on: the SDK spawns the path we hand
|
|
74
|
+
* it with a raw `child_process.spawn`, which never consults PATH or PATHEXT.
|
|
75
|
+
* A bare `claude` therefore fails with "native binary not found at claude"
|
|
76
|
+
* even on a machine where the CLI is installed and on PATH, so an unresolved
|
|
77
|
+
* default returns undefined and lets the SDK use its own bundled binary.
|
|
78
|
+
*/
|
|
72
79
|
function resolveWindowsClaudeExecutablePath(
|
|
73
80
|
configuredPath: string,
|
|
81
|
+
configuredExplicitly: boolean,
|
|
74
82
|
deps: Required<ResolveClaudeCodeExecutablePathDependencies>,
|
|
75
|
-
): string {
|
|
83
|
+
): string | undefined {
|
|
76
84
|
const pathApi = getPathApi(deps.platform);
|
|
77
85
|
const extension = pathApi.extname(configuredPath).toLowerCase();
|
|
78
86
|
const explicitPath = isPathLike(configuredPath) || pathApi.isAbsolute(configuredPath);
|
|
87
|
+
// An explicit CLAUDE_CLI_PATH is the operator's call even when we cannot
|
|
88
|
+
// verify it; only our own `claude` default defers to the SDK.
|
|
89
|
+
const unresolved = configuredExplicitly ? configuredPath : undefined;
|
|
79
90
|
|
|
80
91
|
if (CLAUDE_SCRIPT_EXTENSIONS.has(extension)) {
|
|
81
92
|
return configuredPath;
|
|
@@ -86,7 +97,7 @@ function resolveWindowsClaudeExecutablePath(
|
|
|
86
97
|
}
|
|
87
98
|
|
|
88
99
|
if (explicitPath) {
|
|
89
|
-
return resolveClaudeWrapperBinary(configuredPath, deps) ??
|
|
100
|
+
return resolveClaudeWrapperBinary(configuredPath, deps) ?? unresolved;
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
try {
|
|
@@ -113,16 +124,22 @@ function resolveWindowsClaudeExecutablePath(
|
|
|
113
124
|
}
|
|
114
125
|
}
|
|
115
126
|
} catch {
|
|
116
|
-
return
|
|
127
|
+
return unresolved;
|
|
117
128
|
}
|
|
118
129
|
|
|
119
|
-
return
|
|
130
|
+
return unresolved;
|
|
120
131
|
}
|
|
121
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Resolves the Claude Code executable to hand the SDK.
|
|
135
|
+
*
|
|
136
|
+
* Returns undefined when no real executable could be found and the caller did
|
|
137
|
+
* not configure one, which means "let the SDK pick its own bundled binary".
|
|
138
|
+
*/
|
|
122
139
|
export function resolveClaudeCodeExecutablePath(
|
|
123
140
|
configuredPath: string | undefined = process.env.CLAUDE_CLI_PATH,
|
|
124
141
|
dependencies: ResolveClaudeCodeExecutablePathDependencies = {},
|
|
125
|
-
): string {
|
|
142
|
+
): string | undefined {
|
|
126
143
|
const deps: Required<ResolveClaudeCodeExecutablePathDependencies> = {
|
|
127
144
|
execFileSync: dependencies.execFileSync ?? execFileSync,
|
|
128
145
|
existsSync: dependencies.existsSync ?? fs.existsSync,
|
|
@@ -130,10 +147,11 @@ export function resolveClaudeCodeExecutablePath(
|
|
|
130
147
|
readFileSync: dependencies.readFileSync ?? fs.readFileSync,
|
|
131
148
|
};
|
|
132
149
|
|
|
150
|
+
const configuredExplicitly = Boolean(stripWrappingQuotes(configuredPath || ''));
|
|
133
151
|
const normalizedPath = stripWrappingQuotes(configuredPath || DEFAULT_CLAUDE_COMMAND);
|
|
134
152
|
if (deps.platform !== 'win32') {
|
|
135
153
|
return normalizedPath;
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
return resolveWindowsClaudeExecutablePath(normalizedPath, deps);
|
|
156
|
+
return resolveWindowsClaudeExecutablePath(normalizedPath, configuredExplicitly, deps);
|
|
139
157
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { appendFilesInputTag, buildCodexInputItems, normalizeImageDescriptors } from './image-attachments.js';
|
|
2
|
+
export { createCompleteMessage, createNormalizedMessage } from './utils.js';
|
|
3
|
+
export type { AnyRecord, ProviderRuntimeContext, ProviderRuntimeWriter } from './types.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AnyRecord,
|
|
3
|
+
BackgroundTaskSummary,
|
|
3
4
|
FetchHistoryOptions,
|
|
4
5
|
FetchHistoryResult,
|
|
5
6
|
LLMProvider,
|
|
@@ -17,6 +18,7 @@ import type {
|
|
|
17
18
|
ProviderRuntimePermissionGateway,
|
|
18
19
|
ProviderRuntimeWriter,
|
|
19
20
|
UpsertProviderMcpServerInput,
|
|
21
|
+
WorkflowAgentActivity,
|
|
20
22
|
} from '@/shared/types.js';
|
|
21
23
|
|
|
22
24
|
//----------------- PROVIDER CONTRACT INTERFACES ------------
|
|
@@ -36,6 +38,19 @@ export interface IProviderRuntime {
|
|
|
36
38
|
): Promise<unknown>;
|
|
37
39
|
abort(sessionId: string): boolean | Promise<boolean>;
|
|
38
40
|
permissions?: ProviderRuntimePermissionGateway;
|
|
41
|
+
/**
|
|
42
|
+
* Sessions with background tasks still outstanding, whether or not their
|
|
43
|
+
* turn has ended. Only a runtime that keeps its process open past a turn for
|
|
44
|
+
* such work has anything to report; the others leave this undefined and the
|
|
45
|
+
* running-sessions list falls back to chat runs alone.
|
|
46
|
+
*/
|
|
47
|
+
listBackgroundWork?(): Array<{ sessionId: string; tasks: BackgroundTaskSummary[] }>;
|
|
48
|
+
/**
|
|
49
|
+
* Stops one outstanding background task. Resolves false when the session has
|
|
50
|
+
* no live process or that process is not tracking the task — it already
|
|
51
|
+
* settled, or the id was never one of its own.
|
|
52
|
+
*/
|
|
53
|
+
stopBackgroundTask?(sessionId: string, taskId: string): Promise<boolean>;
|
|
39
54
|
}
|
|
40
55
|
|
|
41
56
|
/**
|
|
@@ -53,6 +68,36 @@ export interface IProvider {
|
|
|
53
68
|
readonly skills: IProviderSkills;
|
|
54
69
|
readonly sessions: IProviderSessions;
|
|
55
70
|
readonly sessionSynchronizer: IProviderSessionSynchronizer;
|
|
71
|
+
/**
|
|
72
|
+
* Transcript branching. Present only for providers that can materialise a
|
|
73
|
+
* prefix of one conversation as an independent, resumable provider session;
|
|
74
|
+
* its absence is what makes "fork session" unavailable.
|
|
75
|
+
*/
|
|
76
|
+
readonly fork?: IProviderFork;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---------------------------
|
|
80
|
+
//----------------- PROVIDER FORK INTERFACE ------------
|
|
81
|
+
/**
|
|
82
|
+
* Transcript-branching contract for one provider.
|
|
83
|
+
*/
|
|
84
|
+
export interface IProviderFork {
|
|
85
|
+
/**
|
|
86
|
+
* Copies a session's transcript, up to and including `upToAnchorId` (the
|
|
87
|
+
* whole conversation when omitted), into a brand-new provider session.
|
|
88
|
+
*
|
|
89
|
+
* Returns the new provider-native id and the path of the artifact it wrote,
|
|
90
|
+
* so the caller can insert the database row before the filesystem watcher
|
|
91
|
+
* notices the file and indexes it as an unrelated session.
|
|
92
|
+
*/
|
|
93
|
+
forkSession(input: {
|
|
94
|
+
providerSessionId: string;
|
|
95
|
+
jsonlPath: string;
|
|
96
|
+
/** The session's working directory — how providers scope a session lookup. */
|
|
97
|
+
projectPath: string;
|
|
98
|
+
upToAnchorId?: string;
|
|
99
|
+
title?: string;
|
|
100
|
+
}): Promise<{ providerSessionId: string; jsonlPath: string }>;
|
|
56
101
|
}
|
|
57
102
|
|
|
58
103
|
// ---------------------------
|
|
@@ -154,6 +199,52 @@ export interface IProviderMcp {
|
|
|
154
199
|
export interface IProviderSessions {
|
|
155
200
|
normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
|
|
156
201
|
fetchHistory(sessionId: string, options?: FetchHistoryOptions): Promise<FetchHistoryResult>;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Resolves where a conversation must resume from so that the turn identified
|
|
205
|
+
* by `anchorId`, and everything after it, is replaced.
|
|
206
|
+
*
|
|
207
|
+
* `resumeThroughId` is the last transcript row to KEEP — resuming is
|
|
208
|
+
* inclusive of it — or `null` when the edited turn is the first prompt and
|
|
209
|
+
* the conversation should start over. `found` is false when `anchorId` is not
|
|
210
|
+
* in the transcript, which the caller must report rather than guess at.
|
|
211
|
+
*
|
|
212
|
+
* Implemented only by providers whose transcripts have stable per-row
|
|
213
|
+
* identity; its absence is what makes "edit this message" unavailable.
|
|
214
|
+
*/
|
|
215
|
+
resolveEditAnchor?(
|
|
216
|
+
sessionId: string,
|
|
217
|
+
anchorId: string,
|
|
218
|
+
): Promise<{ found: boolean; resumeThroughId: string | null }>;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Rewinds the session so `keepThroughId` is the last row of its
|
|
222
|
+
* conversation, and points the session at whatever provider session now
|
|
223
|
+
* holds it. `null` keeps nothing: the conversation starts over.
|
|
224
|
+
*
|
|
225
|
+
* Implemented only by providers whose runtime cannot resume a transcript
|
|
226
|
+
* partway and have to branch instead. Codex is one — it has no
|
|
227
|
+
* resume-at-a-row, so the rewind is a `thread/fork` that leaves the pre-edit
|
|
228
|
+
* thread on disk and moves the session onto the copy. Providers that can
|
|
229
|
+
* resume partway leave this undefined, and the anchor is handed to their
|
|
230
|
+
* runtime as a resume option instead; that is the difference the edit
|
|
231
|
+
* gateway branches on.
|
|
232
|
+
*/
|
|
233
|
+
rewindSession?(sessionId: string, keepThroughId: string | null): Promise<void>;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Reads what one agent of a workflow run did, from the transcript the run
|
|
237
|
+
* wrote for it, with the status its journal gives it. Returns `null` when the
|
|
238
|
+
* run left no transcript for that agent.
|
|
239
|
+
*
|
|
240
|
+
* Implemented only by providers whose runtime spawns workflow agents; its
|
|
241
|
+
* absence is what makes an agent's timeline unavailable in the card.
|
|
242
|
+
*/
|
|
243
|
+
readWorkflowAgentActivity?(
|
|
244
|
+
sessionId: string,
|
|
245
|
+
runId: string,
|
|
246
|
+
agentId: string,
|
|
247
|
+
): Promise<WorkflowAgentActivity | null>;
|
|
157
248
|
}
|
|
158
249
|
|
|
159
250
|
// ---------------------------
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import type { AnyRecord, NormalizedMessage } from '@/shared/types.js';
|
|
2
|
+
import { readObjectRecord } from '@/shared/utils.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cross-provider unification of the two interaction surfaces that Claude and
|
|
6
|
+
* Codex both have but spell differently: the running checklist and the
|
|
7
|
+
* ask-the-user round trip.
|
|
8
|
+
*
|
|
9
|
+
* Each provider parses its own transcript format first; this pass runs once the
|
|
10
|
+
* tool results have been attached and rewrites those rows onto a single
|
|
11
|
+
* canonical shape, so the chat needs exactly one renderer per surface:
|
|
12
|
+
*
|
|
13
|
+
* - checklist → a `TodoWrite` call whose input is the full list at that point
|
|
14
|
+
* - question → an `AskUserQuestion` call whose input carries the chosen answers
|
|
15
|
+
*
|
|
16
|
+
* Doing it here rather than in each provider is what keeps the two feeling like
|
|
17
|
+
* one product: Claude's incremental `TaskCreate`/`TaskUpdate` calls and Codex's
|
|
18
|
+
* whole-list `update_plan` calls both come out as the same evolving checklist.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
//----------------- CANONICAL TOOL NAMES ------------
|
|
22
|
+
|
|
23
|
+
/** The one tool name every provider's checklist is rewritten onto. */
|
|
24
|
+
const CHECKLIST_TOOL = 'TodoWrite';
|
|
25
|
+
|
|
26
|
+
/** The one tool name every provider's user-question call is rewritten onto. */
|
|
27
|
+
const ASK_TOOL = 'AskUserQuestion';
|
|
28
|
+
|
|
29
|
+
/** Provider spellings of the ask-the-user tool. Codex calls it `request_user_input`. */
|
|
30
|
+
const ASK_TOOL_ALIASES = new Set([ASK_TOOL, 'request_user_input']);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Claude's incremental task tracker. Each call mutates one entry of a list the
|
|
34
|
+
* transcript never states in full, so the list is rebuilt here and every call
|
|
35
|
+
* is replaced by the resulting snapshot.
|
|
36
|
+
*/
|
|
37
|
+
const TASK_TOOLS = new Set(['TaskCreate', 'TaskUpdate', 'TaskList', 'TaskGet']);
|
|
38
|
+
|
|
39
|
+
//----------------- SHARED PAYLOAD READERS ------------
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Reads a tool payload that providers store either as an object (Claude) or as
|
|
43
|
+
* the raw JSON string it arrived as (Codex).
|
|
44
|
+
*/
|
|
45
|
+
function readToolPayload(value: unknown): AnyRecord | null {
|
|
46
|
+
if (typeof value === 'string') {
|
|
47
|
+
const trimmed = value.trim();
|
|
48
|
+
if (!trimmed.startsWith('{')) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return readObjectRecord(JSON.parse(trimmed));
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return readObjectRecord(value);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function readNonEmptyString(value: unknown): string {
|
|
62
|
+
return typeof value === 'string' && value.trim() ? value : '';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//----------------- ASK-THE-USER ANSWERS ------------
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Flattens one answer value into the comma-joined label list the question view
|
|
69
|
+
* renders. Claude stores the labels already joined, Codex stores them as
|
|
70
|
+
* `{ answers: [...] }`, and a multi-select answer is an array either way.
|
|
71
|
+
*/
|
|
72
|
+
function readAnswerLabels(value: unknown): string {
|
|
73
|
+
if (typeof value === 'string') {
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
return value.filter((entry): entry is string => typeof entry === 'string').join(', ');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const record = readObjectRecord(value);
|
|
82
|
+
return record ? readAnswerLabels(record.answers) : '';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Recovers the answers from Claude's acknowledgement sentence.
|
|
87
|
+
*
|
|
88
|
+
* A live turn only carries the prose result — `Your questions have been
|
|
89
|
+
* answered: "<question>"="<answer>".` — because the structured `toolUseResult`
|
|
90
|
+
* is written when the transcript is persisted, not when the tool returns. The
|
|
91
|
+
* selection would otherwise be invisible for the whole run.
|
|
92
|
+
*/
|
|
93
|
+
function readAnswersFromAcknowledgement(content: string): Record<string, string> {
|
|
94
|
+
if (!content.includes('questions have been answered')) {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const answers: Record<string, string> = {};
|
|
99
|
+
const pattern = /"([^"]+)"\s*=\s*"([^"]*)"/g;
|
|
100
|
+
let match = pattern.exec(content);
|
|
101
|
+
while (match) {
|
|
102
|
+
answers[match[1]] = match[2];
|
|
103
|
+
match = pattern.exec(content);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return answers;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Rewrites answers onto the question text they belong to.
|
|
111
|
+
*
|
|
112
|
+
* Codex keys its answers by the question's `id`; Claude keys them by the
|
|
113
|
+
* question text. Settling on the text means the renderer needs no provider
|
|
114
|
+
* knowledge to pair a question with its answer.
|
|
115
|
+
*/
|
|
116
|
+
function keyAnswersByQuestion(questions: unknown, rawAnswers: AnyRecord): Record<string, string> {
|
|
117
|
+
const questionById = new Map<string, string>();
|
|
118
|
+
if (Array.isArray(questions)) {
|
|
119
|
+
for (const entry of questions) {
|
|
120
|
+
const question = readObjectRecord(entry);
|
|
121
|
+
const id = readNonEmptyString(question?.id);
|
|
122
|
+
const text = readNonEmptyString(question?.question);
|
|
123
|
+
if (id && text) {
|
|
124
|
+
questionById.set(id, text);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const answers: Record<string, string> = {};
|
|
130
|
+
for (const [key, value] of Object.entries(rawAnswers)) {
|
|
131
|
+
const labels = readAnswerLabels(value);
|
|
132
|
+
if (labels) {
|
|
133
|
+
answers[questionById.get(key) ?? key] = labels;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return answers;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Pulls the answer map out of whichever result shape the provider produced. */
|
|
141
|
+
function readAskAnswers(message: NormalizedMessage): AnyRecord | null {
|
|
142
|
+
const structured = readObjectRecord(readObjectRecord(message.toolResult?.toolUseResult)?.answers);
|
|
143
|
+
if (structured) {
|
|
144
|
+
return structured;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const content = readNonEmptyString(message.toolResult?.content);
|
|
148
|
+
if (!content) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const fromPayload = readObjectRecord(readToolPayload(content)?.answers);
|
|
153
|
+
if (fromPayload) {
|
|
154
|
+
return fromPayload;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const fromSentence = readAnswersFromAcknowledgement(content);
|
|
158
|
+
return Object.keys(fromSentence).length > 0 ? fromSentence : null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Normalizes one ask-the-user call: canonical name, and the answers folded into
|
|
163
|
+
* the input so the question and what was picked render as one card instead of a
|
|
164
|
+
* question card followed by an unreadable result blob.
|
|
165
|
+
*/
|
|
166
|
+
function unifyAskCall(message: NormalizedMessage): void {
|
|
167
|
+
message.toolName = ASK_TOOL;
|
|
168
|
+
|
|
169
|
+
const input = readToolPayload(message.toolInput);
|
|
170
|
+
if (!input || !Array.isArray(input.questions)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const rawAnswers = readAskAnswers(message);
|
|
175
|
+
message.toolInput = rawAnswers
|
|
176
|
+
? { ...input, answers: keyAnswersByQuestion(input.questions, rawAnswers) }
|
|
177
|
+
: input;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
//----------------- RUNNING CHECKLIST ------------
|
|
181
|
+
|
|
182
|
+
type ChecklistEntry = {
|
|
183
|
+
id: string;
|
|
184
|
+
content: string;
|
|
185
|
+
status: string;
|
|
186
|
+
activeForm?: string;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/** Claude's task statuses already match the todo vocabulary; anything else is pending. */
|
|
190
|
+
function readTaskStatus(value: unknown): string {
|
|
191
|
+
const status = readNonEmptyString(value);
|
|
192
|
+
return status === 'in_progress' || status === 'completed' ? status : 'pending';
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Replays Claude's task-tracker calls into the list they describe.
|
|
197
|
+
*
|
|
198
|
+
* `TaskCreate` returns the id the tracker assigned, so entries are keyed by it
|
|
199
|
+
* and later `TaskUpdate` calls land on the right row. A create whose result has
|
|
200
|
+
* not arrived yet is keyed by its tool call id, which is unique for the same
|
|
201
|
+
* reason an assigned id would be.
|
|
202
|
+
*/
|
|
203
|
+
class ChecklistState {
|
|
204
|
+
private readonly entries = new Map<string, ChecklistEntry>();
|
|
205
|
+
|
|
206
|
+
applyTaskCall(message: NormalizedMessage): void {
|
|
207
|
+
const input = readToolPayload(message.toolInput) ?? {};
|
|
208
|
+
const result = readObjectRecord(message.toolResult?.toolUseResult);
|
|
209
|
+
|
|
210
|
+
// A listing restates the whole tracker, which is the most reliable source
|
|
211
|
+
// there is — adopt it wholesale. It omits the present-tense wording each
|
|
212
|
+
// task was created with, so that is carried over from what is already known.
|
|
213
|
+
const listed = result?.tasks;
|
|
214
|
+
if (Array.isArray(listed)) {
|
|
215
|
+
const known = new Map(this.entries);
|
|
216
|
+
this.entries.clear();
|
|
217
|
+
for (const entry of listed) {
|
|
218
|
+
const task = readObjectRecord(entry);
|
|
219
|
+
const activeForm = known.get(readNonEmptyString(task?.id))?.activeForm ?? '';
|
|
220
|
+
this.upsertTask(task, { content: '', activeForm });
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const single = readObjectRecord(result?.task);
|
|
226
|
+
if (single) {
|
|
227
|
+
this.upsertTask(single, {
|
|
228
|
+
content: readNonEmptyString(input.subject),
|
|
229
|
+
activeForm: readNonEmptyString(input.activeForm),
|
|
230
|
+
});
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const id = readNonEmptyString(input.taskId) || readNonEmptyString(message.toolId);
|
|
235
|
+
if (!id) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const existing = this.entries.get(id);
|
|
240
|
+
this.entries.set(id, {
|
|
241
|
+
id,
|
|
242
|
+
content: readNonEmptyString(input.subject) || existing?.content || id,
|
|
243
|
+
status: input.status === undefined ? existing?.status ?? 'pending' : readTaskStatus(input.status),
|
|
244
|
+
activeForm: readNonEmptyString(input.activeForm) || existing?.activeForm,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private upsertTask(task: AnyRecord | null, defaults: { content: string; activeForm: string } = { content: '', activeForm: '' }): void {
|
|
249
|
+
if (!task) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const id = readNonEmptyString(task.id);
|
|
254
|
+
if (!id) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const existing = this.entries.get(id);
|
|
259
|
+
this.entries.set(id, {
|
|
260
|
+
id,
|
|
261
|
+
content: readNonEmptyString(task.subject) || defaults.content || existing?.content || id,
|
|
262
|
+
status: task.status === undefined ? existing?.status ?? 'pending' : readTaskStatus(task.status),
|
|
263
|
+
activeForm: defaults.activeForm || existing?.activeForm,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
snapshot(): ChecklistEntry[] {
|
|
268
|
+
return [...this.entries.values()].map((entry) => ({ ...entry }));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** True for a tool row that already carries a whole checklist in its input. */
|
|
273
|
+
function isChecklistSnapshot(message: NormalizedMessage): boolean {
|
|
274
|
+
return message.kind === 'tool_use' && message.toolName === CHECKLIST_TOOL;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Identity of a checklist as it is drawn: the steps and their states, and
|
|
279
|
+
* nothing else. Two snapshots with the same signature look identical on screen,
|
|
280
|
+
* so only the first is worth keeping.
|
|
281
|
+
*/
|
|
282
|
+
function readChecklistSignature(message: NormalizedMessage): string {
|
|
283
|
+
const todos = readToolPayload(message.toolInput)?.todos;
|
|
284
|
+
if (!Array.isArray(todos)) {
|
|
285
|
+
return '';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return JSON.stringify(todos.map((todo) => {
|
|
289
|
+
const entry = readObjectRecord(todo);
|
|
290
|
+
return [readNonEmptyString(entry?.content), readTaskStatus(entry?.status)];
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
//----------------- TOOL OUTPUT SIZE ------------
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Longest tool output one transcript row carries.
|
|
298
|
+
*
|
|
299
|
+
* A provider records whatever the tool returned, which for a `Read` of a
|
|
300
|
+
* screenshot is a base64 image and for a long test run is the whole log. The
|
|
301
|
+
* transcript shows that output inside a collapsed section, so past roughly a
|
|
302
|
+
* screenful of scrolling nobody reads further — but every byte is parsed,
|
|
303
|
+
* stored and held in memory for the life of the session. Real Claude sessions
|
|
304
|
+
* ship megabytes per page this way.
|
|
305
|
+
*/
|
|
306
|
+
const MAX_TOOL_RESULT_CONTENT = 40_000;
|
|
307
|
+
|
|
308
|
+
function truncateOutput(value: string): string {
|
|
309
|
+
if (value.length <= MAX_TOOL_RESULT_CONTENT) {
|
|
310
|
+
return value;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const omitted = value.length - MAX_TOOL_RESULT_CONTENT;
|
|
314
|
+
return `${value.slice(0, MAX_TOOL_RESULT_CONTENT)}\n… ${omitted} more characters`;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Applies the same cap to every string inside a provider's structured result.
|
|
319
|
+
*
|
|
320
|
+
* The structure is preserved rather than dropped wholesale because the
|
|
321
|
+
* transcript reads small fields out of it (a search's file list, for one), and
|
|
322
|
+
* only a single oversized string — a file body or an encoded image — is ever
|
|
323
|
+
* the thing making it large.
|
|
324
|
+
*/
|
|
325
|
+
export function truncateNestedOutput(value: unknown): unknown {
|
|
326
|
+
if (typeof value === 'string') {
|
|
327
|
+
return truncateOutput(value);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (Array.isArray(value)) {
|
|
331
|
+
return value.map(truncateNestedOutput);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const record = readObjectRecord(value);
|
|
335
|
+
if (!record) {
|
|
336
|
+
return value;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const truncated: AnyRecord = {};
|
|
340
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
341
|
+
truncated[key] = truncateNestedOutput(entry);
|
|
342
|
+
}
|
|
343
|
+
return truncated;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function capToolResult(message: NormalizedMessage): void {
|
|
347
|
+
const result = message.toolResult;
|
|
348
|
+
if (!result) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (typeof result.content === 'string') {
|
|
353
|
+
result.content = truncateOutput(result.content);
|
|
354
|
+
}
|
|
355
|
+
if (result.toolUseResult !== undefined) {
|
|
356
|
+
result.toolUseResult = truncateNestedOutput(result.toolUseResult);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
//----------------- TRANSCRIPT PASS ------------
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Turns one loaded history into exactly the rows the transcript draws.
|
|
364
|
+
*
|
|
365
|
+
* Three things happen here:
|
|
366
|
+
*
|
|
367
|
+
* 1. Provider-specific interaction rows are rewritten onto the canonical
|
|
368
|
+
* shapes described above.
|
|
369
|
+
* 2. Checklist snapshots that a later snapshot supersedes are dropped.
|
|
370
|
+
* Consecutive snapshots are the normal case once incremental task calls are
|
|
371
|
+
* replayed — three `TaskCreate` calls in a row describe one list, not three
|
|
372
|
+
* — and keeping only the last of a run turns a wall of near-identical cards
|
|
373
|
+
* into the single checklist the model was actually building. Snapshots
|
|
374
|
+
* separated by real work are all kept, so the list still reappears wherever
|
|
375
|
+
* it changed.
|
|
376
|
+
* 3. Standalone tool-result rows are dropped, because the provider has already
|
|
377
|
+
* attached each result to the call it belongs to and the chat draws it
|
|
378
|
+
* there. Shipping the row twice is half of everything a tool-heavy Claude
|
|
379
|
+
* session sends.
|
|
380
|
+
* 4. Tool output is capped, so one `Read` of an image cannot cost the session
|
|
381
|
+
* a megabyte of memory for content nothing renders.
|
|
382
|
+
*
|
|
383
|
+
* Mutates and returns the given array; callers own it.
|
|
384
|
+
*/
|
|
385
|
+
export function prepareTranscriptMessages(messages: NormalizedMessage[]): NormalizedMessage[] {
|
|
386
|
+
const checklist = new ChecklistState();
|
|
387
|
+
|
|
388
|
+
for (const message of messages) {
|
|
389
|
+
if (message.kind !== 'tool_use' || !message.toolName) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (ASK_TOOL_ALIASES.has(message.toolName)) {
|
|
394
|
+
unifyAskCall(message);
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (TASK_TOOLS.has(message.toolName)) {
|
|
399
|
+
checklist.applyTaskCall(message);
|
|
400
|
+
message.toolName = CHECKLIST_TOOL;
|
|
401
|
+
message.toolInput = { todos: checklist.snapshot() };
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// After the rewrites, so a folded-in answer is read from the full result.
|
|
406
|
+
for (const message of messages) {
|
|
407
|
+
capToolResult(message);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const superseded = new Set<number>();
|
|
411
|
+
let openSnapshotIndex = -1;
|
|
412
|
+
let keptSignature: string | null = null;
|
|
413
|
+
|
|
414
|
+
messages.forEach((message, index) => {
|
|
415
|
+
// A result row renders as part of its call, so it must not break a run of
|
|
416
|
+
// snapshots apart — the results of the calls being folded away sit exactly
|
|
417
|
+
// between them.
|
|
418
|
+
if (message.kind === 'tool_result') {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (!isChecklistSnapshot(message)) {
|
|
423
|
+
openSnapshotIndex = -1;
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Restating a checklist that has not moved since it was last drawn adds
|
|
428
|
+
// nothing, however far apart the two calls are.
|
|
429
|
+
const signature = readChecklistSignature(message);
|
|
430
|
+
if (signature === keptSignature) {
|
|
431
|
+
superseded.add(index);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (openSnapshotIndex !== -1) {
|
|
436
|
+
superseded.add(openSnapshotIndex);
|
|
437
|
+
}
|
|
438
|
+
openSnapshotIndex = index;
|
|
439
|
+
keptSignature = signature;
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// A result that names its call is only ever drawn through that call. The one
|
|
443
|
+
// shape worth keeping is a result with no call to attach to, which the chat
|
|
444
|
+
// renders on its own.
|
|
445
|
+
return messages.filter((message, index) => (
|
|
446
|
+
!superseded.has(index)
|
|
447
|
+
&& !(message.kind === 'tool_result' && message.toolId)
|
|
448
|
+
));
|
|
449
|
+
}
|