wind-agent-cli 1.37.2 → 1.37.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +718 -718
- package/README.md +1 -1
- package/dist/api-docs.html +901 -901
- package/dist/assets/{CodeEditor-B2Wf7Fg0.js → CodeEditor-BqmxpZ_D.js} +1 -1
- package/dist/assets/{FileTree-N2IkkHlv.js → FileTree-DLE7Ioai.js} +1 -1
- package/dist/assets/{GitPanel-DZCeuFZ2.js → GitPanel-f8RMRa8D.js} +1 -1
- package/dist/assets/{MarkdownPreview-C0tqYnVu.js → MarkdownPreview-93h_1tJa.js} +1 -1
- package/dist/assets/{PluginTabContent-Bnuf-fb8.js → PluginTabContent-DU1jjkXP.js} +1 -1
- package/dist/assets/{Shell-BfFnMZ-f.js → Shell-CN_2MRIM.js} +1 -1
- package/dist/assets/{StandaloneShell-QmyYwNAl.js → StandaloneShell-D0avS8UE.js} +1 -1
- package/dist/assets/{TaskMasterPanel-fMsmvN9L.js → TaskMasterPanel-Cpf1Q5Ph.js} +3 -3
- package/dist/assets/{abnfDiagram-N423BO3Z-DjPU7HLs.js → abnfDiagram-N423BO3Z-p3aJIm4T.js} +1 -1
- package/dist/assets/{arc-Pdq6Tvr3.js → arc-CTeud6Fl.js} +1 -1
- package/dist/assets/{architectureDiagram-T3A2C74G-D0JnT0Vh.js → architectureDiagram-T3A2C74G-CG7kRCJU.js} +1 -1
- package/dist/assets/{blockDiagram-VBNYF7ZC-DpaEf3mv.js → blockDiagram-VBNYF7ZC-oSjQ1SgE.js} +1 -1
- package/dist/assets/{c4Diagram-5PPSVZJV-MpqlPGFi.js → c4Diagram-5PPSVZJV-RkzF0DJV.js} +1 -1
- package/dist/assets/channel-BfQbarn9.js +1 -0
- package/dist/assets/{chunk-2GRJ4B5K-DoSdNo8u.js → chunk-2GRJ4B5K-B07uZ07O.js} +1 -1
- package/dist/assets/{chunk-2Q5K7J3B-CE7I3uMn.js → chunk-2Q5K7J3B-DNSfO7xS.js} +1 -1
- package/dist/assets/{chunk-5RXB4S5H-B4UQ8snD.js → chunk-5RXB4S5H-BTeYcgyb.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-B55XgqHZ.js → chunk-5VM5RSS4-B7vZV0zC.js} +1 -1
- package/dist/assets/{chunk-6Q2QTUOP-BS1KpefW.js → chunk-6Q2QTUOP-DuS_xUGG.js} +1 -1
- package/dist/assets/{chunk-GF5L2VYU-DkEPedJP.js → chunk-GF5L2VYU-CKLZ3iVD.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DOtkNhMm.js → chunk-JWPE2WC7-DD2hcXvs.js} +1 -1
- package/dist/assets/{chunk-KBJHAD2P-BXLjviqM.js → chunk-KBJHAD2P-Cz-l38qp.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-C50fjNNz.js → chunk-RYQCIY6F-DGFIU1YM.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-QBYqCkb7.js → chunk-XXDRQBXY-CmfzoYFl.js} +1 -1
- package/dist/assets/classDiagram-JCYQIIEL-Bpfe3kq7.js +1 -0
- package/dist/assets/classDiagram-v2-OCEON4UE-Bpfe3kq7.js +1 -0
- package/dist/assets/{code-xml-VK1YfShP.js → code-xml-CLpHzEOP.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-DrVTo1Nh.js → cose-bilkent-JH36ORCC-DlFcLXCB.js} +1 -1
- package/dist/assets/{cynefin-VYW2F7L2-DnJa_OlQ.js → cynefin-VYW2F7L2-P1HecReO.js} +1 -1
- package/dist/assets/{cynefinDiagram-MW4NZA55-CCxBjw9E.js → cynefinDiagram-MW4NZA55-COgduz5P.js} +1 -1
- package/dist/assets/{dagre-VZM6K2ZE-C_GvE4lu.js → dagre-VZM6K2ZE-Bbb-siGp.js} +1 -1
- package/dist/assets/{diagram-7IWD3JNH-pFzs9HEu.js → diagram-7IWD3JNH-9CWGFMYR.js} +1 -1
- package/dist/assets/{diagram-B4RE2ZJO-CcehQC7x.js → diagram-B4RE2ZJO-TWK59T6V.js} +1 -1
- package/dist/assets/{diagram-LBJQPF4R-hfKcrrxe.js → diagram-LBJQPF4R-ErMC9yaa.js} +1 -1
- package/dist/assets/{diagram-Q27KOJAE-C1semJfK.js → diagram-Q27KOJAE-Dt_-C7hV.js} +1 -1
- package/dist/assets/{diagram-UB23O5K3-57hvXQXO.js → diagram-UB23O5K3-BJ1DnRAF.js} +1 -1
- package/dist/assets/{ebnfDiagram-BXEA7PRR-9KIAlAVw.js → ebnfDiagram-BXEA7PRR-CE1YaQ9s.js} +1 -1
- package/dist/assets/{erDiagram-JOGREHBK-B7OzJ767.js → erDiagram-JOGREHBK-Bqk7N9aY.js} +1 -1
- package/dist/assets/{flowDiagram-UKHOOZJN-CJV8fQPR.js → flowDiagram-UKHOOZJN-DEr2II5V.js} +1 -1
- package/dist/assets/{ganttDiagram-PKOTCBZU-CbMNWWQu.js → ganttDiagram-PKOTCBZU-CWYAUeYN.js} +1 -1
- package/dist/assets/{gitGraphDiagram-DS77QQ5N-I_vZ5waO.js → gitGraphDiagram-DS77QQ5N-tdEcEIM6.js} +1 -1
- package/dist/assets/{index-ZHwIojzi.js → index-B-sTfSZq.js} +1 -1
- package/dist/assets/{index-GFhXZyl2.js → index-BSe3UiFA.js} +1 -1
- package/dist/assets/{index-DFnVoqpx.js → index-B_FDMWar.js} +5 -5
- package/dist/assets/{index-DlSeAkw_.js → index-CWJtg2pR.js} +1 -1
- package/dist/assets/{infoDiagram-6WML65LV-Dh20Tsbq.js → infoDiagram-6WML65LV-A3IqRUnO.js} +1 -1
- package/dist/assets/{ishikawaDiagram-WSZJBQD7-DH2Sm3ko.js → ishikawaDiagram-WSZJBQD7-B2uL6bkK.js} +1 -1
- package/dist/assets/{journeyDiagram-NVQOT4AX-BNFQqlVu.js → journeyDiagram-NVQOT4AX-D9JB-hRW.js} +1 -1
- package/dist/assets/{kanban-definition-27J2QSJJ-B3iL0ztJ.js → kanban-definition-27J2QSJJ-DmlgiV7K.js} +1 -1
- package/dist/assets/{linear-Cwe9dEKA.js → linear-Ct_eoJQk.js} +1 -1
- package/dist/assets/{mermaid.core-BYRQSshi.js → mermaid.core-CQ698HNn.js} +5 -5
- package/dist/assets/{mindmap-definition-FAOFIHXS-BgfBYMzr.js → mindmap-definition-FAOFIHXS-DGtMgQhf.js} +1 -1
- package/dist/assets/{pegDiagram-VL7TDLO6-CNYpECr8.js → pegDiagram-VL7TDLO6-CO6vP4n9.js} +1 -1
- package/dist/assets/{pieDiagram-7S7Q4E2Y-DeSrxc4I.js → pieDiagram-7S7Q4E2Y-DMkt_Zfr.js} +1 -1
- package/dist/assets/{quadrantDiagram-CIZ2JOQS-BXVVQsa6.js → quadrantDiagram-CIZ2JOQS-DgNxRz6t.js} +1 -1
- package/dist/assets/{railroadDiagram-AXF67PYL-JTroIW8F.js → railroadDiagram-AXF67PYL-DKz9UqA9.js} +1 -1
- package/dist/assets/{requirementDiagram-LRYGKXZP-C1Z_inLz.js → requirementDiagram-LRYGKXZP-L84XyGgV.js} +1 -1
- package/dist/assets/{sankeyDiagram-W5VNT64P-DCJgKFUk.js → sankeyDiagram-W5VNT64P-CQqWbJ3j.js} +1 -1
- package/dist/assets/{sequenceDiagram-SI44F4Z6-D8Wrx5Vc.js → sequenceDiagram-SI44F4Z6--tnzS2tb.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-CXqD68vD.js → sizeCapture-X5ZJPWSS-DujwEOtm.js} +1 -1
- package/dist/assets/{stateDiagram-OKZ733FA-CF0Ekqjo.js → stateDiagram-OKZ733FA-BK3TcZY2.js} +1 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-_medyomK.js +1 -0
- package/dist/assets/{swimlanes-SLNWSIFB-DVIax_k4.js → swimlanes-SLNWSIFB-naX-Uv1B.js} +2 -2
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-DstIv3TC.js +8 -0
- package/dist/assets/{timeline-definition-Z64GVDOM-DSqk3ApG.js → timeline-definition-Z64GVDOM-C-vP_ddU.js} +1 -1
- package/dist/assets/{vennDiagram-T6HMQDX7-DNbTqyG5.js → vennDiagram-T6HMQDX7-DN-I7o-7.js} +1 -1
- package/dist/assets/{wardleyDiagram-T6FBY63Y-BNCpsFZV.js → wardleyDiagram-T6FBY63Y-Db9dsaXv.js} +1 -1
- package/dist/assets/{xychartDiagram-ELKLHX3M-XsVZphHr.js → xychartDiagram-ELKLHX3M-DE6OxW_p.js} +1 -1
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/favicon.svg +8 -8
- package/dist/generate-icons.js +48 -48
- package/dist/icons/codex-white.svg +3 -3
- package/dist/icons/codex.svg +3 -3
- package/dist/icons/cursor-white.svg +11 -11
- package/dist/icons/icon-128x128.svg +11 -11
- package/dist/icons/icon-144x144.svg +11 -11
- package/dist/icons/icon-152x152.svg +11 -11
- package/dist/icons/icon-192x192.svg +11 -11
- package/dist/icons/icon-384x384.svg +11 -11
- package/dist/icons/icon-512x512.svg +11 -11
- package/dist/icons/icon-72x72.svg +11 -11
- package/dist/icons/icon-96x96.svg +11 -11
- package/dist/icons/icon-template.svg +11 -11
- package/dist/index.html +56 -56
- package/dist/logo.svg +17 -17
- package/dist/manifest.json +60 -60
- package/dist/sw.js +124 -124
- package/dist-server/server/modules/cli/cli.service.js +36 -36
- package/dist-server/server/modules/cli/sandbox.service.js +38 -38
- package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +74 -74
- package/dist-server/server/modules/commands/commands.routes.js +24 -24
- package/dist-server/server/modules/database/migrations.js +190 -190
- package/dist-server/server/modules/database/repositories/api-keys.js +3 -3
- package/dist-server/server/modules/database/repositories/github-tokens.js +2 -2
- package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js +28 -28
- package/dist-server/server/modules/database/repositories/notification-preferences.js +4 -4
- package/dist-server/server/modules/database/repositories/projects.db.js +61 -61
- package/dist-server/server/modules/database/repositories/provider-models.js +35 -35
- package/dist-server/server/modules/database/repositories/push-subscriptions.js +5 -5
- package/dist-server/server/modules/database/repositories/scan-state.db.js +5 -5
- package/dist-server/server/modules/database/repositories/sessions.db.js +92 -92
- package/dist-server/server/modules/database/schema.js +177 -177
- package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +6 -6
- package/dist-server/server/modules/git/git.routes.js +17 -17
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +12 -12
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +9 -9
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +17 -17
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +25 -25
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +27 -27
- package/dist-server/server/modules/providers/services/provider-token-usage.service.js +9 -9
- package/dist-server/server/modules/providers/tests/mcp.test.js +3 -3
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +96 -96
- package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +18 -18
- package/dist-server/server/modules/taskmaster/taskmaster.routes.js +419 -419
- package/electron/cloud.js +260 -260
- package/electron/desktopNotifications.js +378 -378
- package/electron/desktopWindow.js +766 -766
- package/electron/launcher/index.html +14 -14
- package/electron/launcher/launcher.css +801 -801
- package/electron/launcher/launcher.js +687 -687
- package/electron/localServer.js +549 -549
- package/electron/main.js +944 -944
- package/electron/preload.cjs +60 -60
- package/electron/scripts/generate-macos-icon.js +62 -62
- package/electron/serverInstaller.js +277 -277
- package/electron/tabs.js +87 -87
- package/electron/viewHost.js +331 -331
- package/package.json +250 -247
- package/public/api-docs.html +901 -901
- package/scripts/fix-node-pty.js +67 -67
- package/scripts/promote-dist-server.mjs +50 -50
- package/scripts/release/build-server-bundle.js +176 -176
- package/scripts/release/prepare-desktop-app.js +152 -152
- package/server/index.ts +399 -399
- package/server/load-env.ts +47 -47
- package/server/modules/agent/agent.module.ts +52 -52
- package/server/modules/agent/agent.routes.ts +1287 -1287
- package/server/modules/agent/index.ts +2 -2
- package/server/modules/agent/tests/agent.routes.test.ts +205 -205
- package/server/modules/assets/assets.routes.ts +150 -150
- package/server/modules/assets/index.ts +3 -3
- package/server/modules/assets/services/image-assets.service.ts +127 -127
- package/server/modules/assets/tests/image-assets.service.test.ts +74 -74
- package/server/modules/auth/auth.middleware.ts +163 -163
- package/server/modules/auth/auth.module.ts +38 -38
- package/server/modules/auth/auth.routes.ts +57 -57
- package/server/modules/auth/auth.service.ts +155 -155
- package/server/modules/auth/index.ts +9 -9
- package/server/modules/auth/tests/auth.service.test.ts +95 -95
- package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -120
- package/server/modules/browser-use/browser-use-mcp.ts +386 -386
- package/server/modules/browser-use/browser-use-runtime.ts +10 -10
- package/server/modules/browser-use/browser-use.routes.ts +96 -96
- package/server/modules/browser-use/browser-use.service.ts +836 -836
- package/server/modules/browser-use/index.ts +11 -11
- package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -10
- package/server/modules/cli/cli.module.ts +93 -93
- package/server/modules/cli/cli.service.ts +248 -248
- package/server/modules/cli/cli.ts +19 -19
- package/server/modules/cli/index.ts +2 -2
- package/server/modules/cli/sandbox.service.ts +398 -398
- package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +186 -186
- package/server/modules/cli/tests/cli.service.test.ts +86 -86
- package/server/modules/cli/tests/sandbox.service.test.ts +58 -58
- package/server/modules/commands/commands.module.ts +22 -22
- package/server/modules/commands/commands.routes.ts +586 -586
- package/server/modules/commands/index.ts +2 -2
- package/server/modules/commands/tests/commands.test.ts +109 -109
- package/server/modules/database/connection.ts +143 -143
- package/server/modules/database/index.ts +17 -17
- package/server/modules/database/init-db.ts +17 -17
- package/server/modules/database/migrations.ts +515 -515
- package/server/modules/database/repositories/api-keys.ts +119 -119
- package/server/modules/database/repositories/app-config.ts +53 -53
- package/server/modules/database/repositories/credentials.ts +106 -106
- package/server/modules/database/repositories/github-tokens.ts +100 -100
- package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -153
- package/server/modules/database/repositories/notification-preferences.ts +117 -117
- package/server/modules/database/repositories/projects.db.ts +196 -196
- package/server/modules/database/repositories/provider-models.ts +168 -168
- package/server/modules/database/repositories/push-subscriptions.ts +80 -80
- package/server/modules/database/repositories/scan-state.db.ts +42 -42
- package/server/modules/database/repositories/sessions.db.ts +524 -524
- package/server/modules/database/repositories/users.ts +140 -140
- package/server/modules/database/repositories/vapid-keys.ts +57 -57
- package/server/modules/database/schema.ts +210 -210
- package/server/modules/database/tests/projects.db.integration.test.ts +72 -72
- package/server/modules/database/tests/provider-models.db.integration.test.ts +125 -125
- package/server/modules/database/tests/sessions-provider-mapping.test.ts +109 -109
- package/server/modules/database/tests/sessions.db.integration.test.ts +116 -116
- package/server/modules/file-tree/file-tree.module.ts +116 -116
- package/server/modules/file-tree/file-tree.routes.ts +258 -258
- package/server/modules/file-tree/file-tree.service.ts +675 -675
- package/server/modules/file-tree/index.ts +2 -2
- package/server/modules/file-tree/tests/file-tree.routes.test.ts +157 -157
- package/server/modules/file-tree/tests/file-tree.service.test.ts +371 -371
- package/server/modules/git/git-branch.service.ts +43 -43
- package/server/modules/git/git-parsing.service.ts +66 -66
- package/server/modules/git/git.module.ts +22 -22
- package/server/modules/git/git.routes.ts +1596 -1596
- package/server/modules/git/index.ts +2 -2
- package/server/modules/git/tests/git-branch.service.test.ts +60 -60
- package/server/modules/git/tests/git-init.routes.test.ts +132 -132
- package/server/modules/git/tests/git.test.ts +106 -106
- package/server/modules/notifications/index.ts +24 -24
- package/server/modules/notifications/notifications.routes.ts +127 -127
- package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -124
- package/server/modules/notifications/services/notification-orchestrator.service.js +310 -310
- package/server/modules/notifications/tests/notification-orchestrator.integration.test.ts +55 -55
- package/server/modules/notifications/vapid-keys.service.ts +38 -38
- package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -109
- package/server/modules/plugins/index.ts +9 -9
- package/server/modules/plugins/plugin-process.service.ts +217 -217
- package/server/modules/plugins/plugin-registry.service.ts +459 -459
- package/server/modules/plugins/plugins.module.ts +33 -33
- package/server/modules/plugins/plugins.routes.ts +66 -66
- package/server/modules/plugins/plugins.service.ts +147 -147
- package/server/modules/plugins/tests/plugins.service.test.ts +32 -32
- package/server/modules/projects/index.ts +11 -11
- package/server/modules/projects/projects.routes.ts +273 -273
- package/server/modules/projects/services/project-clone.service.ts +323 -323
- package/server/modules/projects/services/project-delete.service.ts +90 -90
- package/server/modules/projects/services/project-management.service.ts +144 -144
- package/server/modules/projects/services/project-star.service.ts +78 -78
- package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -248
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +314 -314
- package/server/modules/projects/tests/project-clone.service.test.ts +183 -183
- package/server/modules/projects/tests/project-management.service.test.ts +117 -117
- package/server/modules/projects/tests/project-star.service.test.ts +123 -123
- package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -105
- package/server/modules/providers/README.md +380 -380
- package/server/modules/providers/index.ts +10 -10
- package/server/modules/providers/list/claude/claude-auth.provider.ts +160 -160
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
- package/server/modules/providers/list/claude/claude-models.provider.ts +294 -294
- package/server/modules/providers/list/claude/claude-runtime.provider.js +1068 -1068
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +203 -203
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +684 -684
- package/server/modules/providers/list/claude/claude-skills.provider.ts +265 -265
- package/server/modules/providers/list/claude/claude.provider.ts +30 -30
- package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -100
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
- package/server/modules/providers/list/codex/codex-models.provider.ts +123 -123
- package/server/modules/providers/list/codex/codex-runtime.provider.js +533 -533
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +203 -203
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +938 -938
- package/server/modules/providers/list/codex/codex-skills.provider.ts +73 -73
- package/server/modules/providers/list/codex/codex.provider.ts +28 -28
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
- package/server/modules/providers/list/cursor/cursor-models.provider.ts +119 -119
- package/server/modules/providers/list/cursor/cursor-runtime.provider.js +385 -385
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +159 -159
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +654 -654
- package/server/modules/providers/list/cursor/cursor-skills.provider.ts +39 -39
- package/server/modules/providers/list/cursor/cursor.provider.ts +30 -30
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +110 -110
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -228
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +203 -203
- package/server/modules/providers/list/opencode/opencode-runtime.provider.js +434 -434
- package/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +261 -261
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +179 -179
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +500 -500
- package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -78
- package/server/modules/providers/list/opencode/opencode.provider.ts +30 -30
- package/server/modules/providers/provider.registry.ts +36 -36
- package/server/modules/providers/provider.routes.ts +877 -877
- package/server/modules/providers/services/mcp.service.ts +109 -109
- package/server/modules/providers/services/provider-auth.service.ts +26 -26
- package/server/modules/providers/services/provider-capabilities.service.ts +97 -97
- package/server/modules/providers/services/provider-models.service.ts +401 -401
- package/server/modules/providers/services/provider-runtime.service.ts +108 -108
- package/server/modules/providers/services/provider-token-usage.service.ts +357 -357
- package/server/modules/providers/services/session-conversations-search.service.ts +1321 -1321
- package/server/modules/providers/services/session-synchronizer.service.ts +74 -74
- package/server/modules/providers/services/sessions-watcher.service.ts +247 -247
- package/server/modules/providers/services/sessions.service.ts +471 -471
- package/server/modules/providers/services/skills.service.ts +39 -39
- package/server/modules/providers/shared/base/abstract.provider.ts +32 -32
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
- package/server/modules/providers/shared/skills/skills.provider.ts +287 -287
- package/server/modules/providers/tests/claude-auth.test.ts +150 -150
- package/server/modules/providers/tests/claude-sessions.test.ts +61 -61
- package/server/modules/providers/tests/codex-sessions.test.ts +231 -231
- package/server/modules/providers/tests/mcp.test.ts +349 -349
- package/server/modules/providers/tests/opencode-models.test.ts +41 -41
- package/server/modules/providers/tests/opencode-sessions.test.ts +522 -522
- package/server/modules/providers/tests/provider-attachment-history.test.ts +247 -247
- package/server/modules/providers/tests/provider-models.service.test.ts +353 -353
- package/server/modules/providers/tests/provider-runtime.service.test.ts +138 -138
- package/server/modules/providers/tests/provider-token-usage.service.test.ts +186 -186
- package/server/modules/providers/tests/provider.routes.test.ts +244 -244
- package/server/modules/providers/tests/sessions-details.test.ts +73 -73
- package/server/modules/providers/tests/sessions.service.test.ts +127 -127
- package/server/modules/providers/tests/skills.test.ts +692 -692
- package/server/modules/settings/index.ts +2 -2
- package/server/modules/settings/settings.module.ts +50 -50
- package/server/modules/settings/settings.routes.ts +51 -51
- package/server/modules/settings/settings.service.ts +186 -186
- package/server/modules/settings/tests/settings.service.test.ts +54 -54
- package/server/modules/system/index.ts +2 -2
- package/server/modules/system/system.module.ts +62 -62
- package/server/modules/system/system.routes.ts +21 -21
- package/server/modules/system/system.service.ts +76 -76
- package/server/modules/system/tests/system.service.test.ts +118 -118
- package/server/modules/taskmaster/index.ts +2 -2
- package/server/modules/taskmaster/taskmaster.module.ts +24 -24
- package/server/modules/taskmaster/taskmaster.routes.ts +1482 -1482
- package/server/modules/taskmaster/taskmaster.service.ts +132 -132
- package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +144 -144
- package/server/modules/taskmaster/tests/taskmaster.service.test.ts +97 -97
- package/server/modules/user/index.ts +2 -2
- package/server/modules/user/tests/user.service.test.ts +61 -61
- package/server/modules/user/user.module.ts +58 -58
- package/server/modules/user/user.routes.ts +50 -50
- package/server/modules/user/user.service.ts +85 -85
- package/server/modules/voice/index.ts +2 -2
- package/server/modules/voice/tests/voice.service.test.ts +98 -98
- package/server/modules/voice/voice.module.ts +47 -47
- package/server/modules/voice/voice.routes.ts +113 -113
- package/server/modules/voice/voice.service.ts +192 -192
- package/server/modules/websocket/README.md +273 -273
- package/server/modules/websocket/index.ts +3 -3
- package/server/modules/websocket/services/chat-run-registry.service.ts +343 -343
- package/server/modules/websocket/services/chat-session-writer.service.ts +145 -145
- package/server/modules/websocket/services/chat-websocket.service.ts +425 -425
- package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -65
- package/server/modules/websocket/services/shell-websocket.service.ts +502 -502
- package/server/modules/websocket/services/websocket-auth.service.ts +59 -59
- package/server/modules/websocket/services/websocket-server.service.ts +124 -124
- package/server/modules/websocket/services/websocket-state.service.ts +16 -16
- package/server/modules/websocket/services/websocket-writer.service.ts +38 -38
- package/server/modules/websocket/tests/chat-attachment-filter.test.ts +59 -59
- package/server/modules/websocket/tests/chat-run-registry.test.ts +282 -282
- package/server/modules/websocket/tests/shell-websocket.service.test.ts +100 -100
- package/server/modules/websocket/tests/websocket-heartbeat.service.test.ts +78 -78
- package/server/modules/worktrees/index.ts +2 -2
- package/server/modules/worktrees/services/worktree-create-and-open.service.ts +53 -53
- package/server/modules/worktrees/services/worktree-create.service.ts +104 -104
- package/server/modules/worktrees/services/worktree-git.service.ts +207 -207
- package/server/modules/worktrees/services/worktree-list.service.ts +143 -143
- package/server/modules/worktrees/services/worktree-merge.service.ts +157 -157
- package/server/modules/worktrees/services/worktree-open.service.ts +85 -85
- package/server/modules/worktrees/services/worktree-remove.service.ts +88 -88
- package/server/modules/worktrees/tests/worktree-create-and-open.service.test.ts +68 -68
- package/server/modules/worktrees/tests/worktree-create.service.test.ts +142 -142
- package/server/modules/worktrees/tests/worktree-git.service.test.ts +84 -84
- package/server/modules/worktrees/tests/worktree-list.service.test.ts +45 -45
- package/server/modules/worktrees/tests/worktree-merge.service.test.ts +213 -213
- package/server/modules/worktrees/tests/worktree-open.service.test.ts +122 -122
- package/server/modules/worktrees/tests/worktree-remove.service.test.ts +227 -227
- package/server/modules/worktrees/tests/worktrees.routes.test.ts +199 -199
- package/server/modules/worktrees/worktrees.module.ts +113 -113
- package/server/modules/worktrees/worktrees.routes.ts +116 -116
- package/server/shared/claude-cli-path.ts +139 -139
- package/server/shared/frontmatter.ts +18 -18
- package/server/shared/image-attachments.ts +435 -435
- package/server/shared/interfaces.ts +179 -179
- package/server/shared/tests/claude-cli-path.test.ts +61 -61
- package/server/shared/tests/image-attachments.test.ts +353 -353
- package/server/shared/tests/slice-tail-page.test.ts +42 -42
- package/server/shared/types.ts +1226 -1226
- package/server/shared/utils.ts +1161 -1161
- package/server/tsconfig.json +40 -40
- package/shared/networkHosts.js +22 -22
- package/dist/assets/channel-Bm0ZLE4z.js +0 -1
- package/dist/assets/classDiagram-JCYQIIEL-DqEOcNxw.js +0 -1
- package/dist/assets/classDiagram-v2-OCEON4UE-DqEOcNxw.js +0 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-DARLpEFJ.js +0 -1
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-CrgDgaY8.js +0 -8
|
@@ -1,231 +1,231 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import test from 'node:test';
|
|
6
|
-
|
|
7
|
-
import { closeConnection, initializeDatabase, sessionsDb } from '@/modules/database/index.js';
|
|
8
|
-
import { CodexSessionSynchronizer } from '@/modules/providers/list/codex/codex-session-synchronizer.provider.js';
|
|
9
|
-
import { CodexSessionsProvider } from '@/modules/providers/list/codex/codex-sessions.provider.js';
|
|
10
|
-
|
|
11
|
-
const patchHomeDir = (nextHomeDir: string) => {
|
|
12
|
-
const original = os.homedir;
|
|
13
|
-
(os as any).homedir = () => nextHomeDir;
|
|
14
|
-
return () => {
|
|
15
|
-
(os as any).homedir = original;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
async function withIsolatedDatabase(runTest: () => void | Promise<void>): Promise<void> {
|
|
20
|
-
const previousDatabasePath = process.env.DATABASE_PATH;
|
|
21
|
-
const tempDirectory = await mkdtemp(path.join(os.tmpdir(), 'codex-provider-db-'));
|
|
22
|
-
const databasePath = path.join(tempDirectory, 'auth.db');
|
|
23
|
-
|
|
24
|
-
closeConnection();
|
|
25
|
-
process.env.DATABASE_PATH = databasePath;
|
|
26
|
-
await initializeDatabase();
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
await runTest();
|
|
30
|
-
} finally {
|
|
31
|
-
closeConnection();
|
|
32
|
-
if (previousDatabasePath === undefined) {
|
|
33
|
-
delete process.env.DATABASE_PATH;
|
|
34
|
-
} else {
|
|
35
|
-
process.env.DATABASE_PATH = previousDatabasePath;
|
|
36
|
-
}
|
|
37
|
-
await rm(tempDirectory, { recursive: true, force: true });
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Writes one Codex rollout transcript. `firstUserMessage` mirrors the
|
|
43
|
-
* `event_msg`/`user_message` payload the runtime records for the prompt the
|
|
44
|
-
* user typed; omitting it produces a transcript with no user turn.
|
|
45
|
-
*/
|
|
46
|
-
const writeCodexTranscript = async (
|
|
47
|
-
homeDir: string,
|
|
48
|
-
codexSessionId: string,
|
|
49
|
-
workspacePath: string,
|
|
50
|
-
firstUserMessage?: string,
|
|
51
|
-
): Promise<string> => {
|
|
52
|
-
const sessionsDir = path.join(homeDir, '.codex', 'sessions', '2026', '07', '07');
|
|
53
|
-
await mkdir(sessionsDir, { recursive: true });
|
|
54
|
-
|
|
55
|
-
const lines: string[] = [
|
|
56
|
-
JSON.stringify({ type: 'session_meta', payload: { id: codexSessionId, cwd: workspacePath } }),
|
|
57
|
-
];
|
|
58
|
-
if (firstUserMessage !== undefined) {
|
|
59
|
-
lines.push(JSON.stringify({ type: 'event_msg', payload: { type: 'user_message', message: firstUserMessage } }));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const filePath = path.join(sessionsDir, `rollout-${codexSessionId}.jsonl`);
|
|
63
|
-
await writeFile(filePath, `${lines.join('\n')}\n`, 'utf8');
|
|
64
|
-
return filePath;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
test('Codex synchronizer preserves the title assigned when CloudCLI creates a session', { concurrency: false }, async () => {
|
|
68
|
-
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-app-'));
|
|
69
|
-
const workspacePath = path.join(tempRoot, 'workspace');
|
|
70
|
-
await mkdir(workspacePath, { recursive: true });
|
|
71
|
-
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
await writeCodexTranscript(tempRoot, 'codex-app-1', workspacePath, 'Provider transcript title must not win');
|
|
75
|
-
await withIsolatedDatabase(async () => {
|
|
76
|
-
// The app allocates its own id and later maps the provider id onto it,
|
|
77
|
-
// exactly as a message sent from cloudcli does.
|
|
78
|
-
sessionsDb.createAppSession('app-1', 'codex', workspacePath, 'Fix the login redirect');
|
|
79
|
-
sessionsDb.assignProviderSessionId('app-1', 'codex-app-1');
|
|
80
|
-
|
|
81
|
-
const synchronizer = new CodexSessionSynchronizer();
|
|
82
|
-
await synchronizer.synchronize();
|
|
83
|
-
|
|
84
|
-
assert.equal(sessionsDb.getSessionById('app-1')?.custom_name, 'Fix the login redirect');
|
|
85
|
-
});
|
|
86
|
-
} finally {
|
|
87
|
-
restoreHomeDir();
|
|
88
|
-
await rm(tempRoot, { recursive: true, force: true });
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test('Codex synchronizer skips sub-agent rollout files', { concurrency: false }, async () => {
|
|
93
|
-
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-subagent-'));
|
|
94
|
-
const workspacePath = path.join(tempRoot, 'workspace');
|
|
95
|
-
await mkdir(workspacePath, { recursive: true });
|
|
96
|
-
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
// Codex >=0.144 spawn_agent threads write their own rollout files into the
|
|
100
|
-
// same sessions tree, marked via thread_source/source in session_meta.
|
|
101
|
-
const sessionsDir = path.join(tempRoot, '.codex', 'sessions', '2026', '07', '07');
|
|
102
|
-
await mkdir(sessionsDir, { recursive: true });
|
|
103
|
-
await writeFile(
|
|
104
|
-
path.join(sessionsDir, 'rollout-codex-subagent-1.jsonl'),
|
|
105
|
-
`${JSON.stringify({
|
|
106
|
-
type: 'session_meta',
|
|
107
|
-
payload: {
|
|
108
|
-
id: 'codex-subagent-1',
|
|
109
|
-
cwd: workspacePath,
|
|
110
|
-
thread_source: 'subagent',
|
|
111
|
-
parent_thread_id: 'codex-parent-1',
|
|
112
|
-
source: { subagent: { thread_spawn: { parent_thread_id: 'codex-parent-1', depth: 1 } } },
|
|
113
|
-
},
|
|
114
|
-
})}\n`,
|
|
115
|
-
'utf8'
|
|
116
|
-
);
|
|
117
|
-
await writeCodexTranscript(tempRoot, 'codex-parent-1', workspacePath);
|
|
118
|
-
|
|
119
|
-
await withIsolatedDatabase(async () => {
|
|
120
|
-
const synchronizer = new CodexSessionSynchronizer();
|
|
121
|
-
const processed = await synchronizer.synchronize();
|
|
122
|
-
|
|
123
|
-
assert.equal(processed, 1);
|
|
124
|
-
assert.ok(sessionsDb.getSessionById('codex-parent-1'));
|
|
125
|
-
assert.equal(sessionsDb.getSessionById('codex-subagent-1'), null);
|
|
126
|
-
});
|
|
127
|
-
} finally {
|
|
128
|
-
restoreHomeDir();
|
|
129
|
-
await rm(tempRoot, { recursive: true, force: true });
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
test('Codex synchronizer leaves indexed sessions untitled when no name is available', { concurrency: false }, async () => {
|
|
134
|
-
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-indexed-'));
|
|
135
|
-
const workspacePath = path.join(tempRoot, 'workspace');
|
|
136
|
-
await mkdir(workspacePath, { recursive: true });
|
|
137
|
-
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
// A CLI-created session has no app row; its first user message must NOT be
|
|
141
|
-
// used as the title, preserving the existing indexing behavior.
|
|
142
|
-
await writeCodexTranscript(tempRoot, 'codex-indexed-1', workspacePath, 'This prompt should be ignored');
|
|
143
|
-
await withIsolatedDatabase(async () => {
|
|
144
|
-
const synchronizer = new CodexSessionSynchronizer();
|
|
145
|
-
await synchronizer.synchronize();
|
|
146
|
-
|
|
147
|
-
assert.equal(sessionsDb.getSessionById('codex-indexed-1')?.custom_name, 'Untitled Codex Session');
|
|
148
|
-
});
|
|
149
|
-
} finally {
|
|
150
|
-
restoreHomeDir();
|
|
151
|
-
await rm(tempRoot, { recursive: true, force: true });
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test('Codex history preserves wrapped exec tool calls and results', { concurrency: false }, async () => {
|
|
156
|
-
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-exec-history-'));
|
|
157
|
-
const workspacePath = path.join(tempRoot, 'workspace');
|
|
158
|
-
await mkdir(workspacePath, { recursive: true });
|
|
159
|
-
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
const providerSessionId = 'codex-exec-1';
|
|
163
|
-
const transcriptPath = await writeCodexTranscript(tempRoot, providerSessionId, workspacePath);
|
|
164
|
-
const wrappedCalls = [
|
|
165
|
-
{
|
|
166
|
-
callId: 'shell-command-1',
|
|
167
|
-
input: 'const cmds = ["echo one", "echo two"]; await Promise.all(cmds.map(command => tools.shell_command({ command })));',
|
|
168
|
-
expectedToolName: 'Bash',
|
|
169
|
-
expectedToolInput: JSON.stringify({ command: 'echo one\necho two' }),
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
callId: 'json-shell-command-1',
|
|
173
|
-
input: 'const r = await tools.shell_command({"command":"Get-Content -Raw README.md","workdir":"C:\\\\workspace","timeout_ms":10000}); text(r)',
|
|
174
|
-
expectedToolName: 'Bash',
|
|
175
|
-
expectedToolInput: JSON.stringify({ command: 'Get-Content -Raw README.md' }),
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
callId: 'exec-command-1',
|
|
179
|
-
input: 'await tools.exec_command({"command":"echo current"});',
|
|
180
|
-
expectedToolName: 'Bash',
|
|
181
|
-
expectedToolInput: JSON.stringify({ command: 'echo current' }),
|
|
182
|
-
},
|
|
183
|
-
{ callId: 'apply-patch-1', input: 'await tools.apply_patch("*** Begin Patch\\n*** End Patch");' },
|
|
184
|
-
{ callId: 'web-run-1', input: 'await tools.web__run({ search_query: [{ q: "Codex" }] });' },
|
|
185
|
-
{ callId: 'update-plan-1', input: 'await tools.update_plan({ plan: [] });' },
|
|
186
|
-
{ callId: 'unknown-1', input: 'await tools.unknown_wrapper({ value: true });' },
|
|
187
|
-
];
|
|
188
|
-
const transcriptLines = [
|
|
189
|
-
JSON.stringify({ type: 'session_meta', payload: { id: providerSessionId, cwd: workspacePath } }),
|
|
190
|
-
];
|
|
191
|
-
for (const call of wrappedCalls) {
|
|
192
|
-
transcriptLines.push(
|
|
193
|
-
JSON.stringify({
|
|
194
|
-
type: 'response_item',
|
|
195
|
-
payload: { type: 'custom_tool_call', name: 'exec', call_id: call.callId, input: call.input },
|
|
196
|
-
}),
|
|
197
|
-
JSON.stringify({
|
|
198
|
-
type: 'response_item',
|
|
199
|
-
payload: { type: 'custom_tool_call_output', call_id: call.callId, output: `result:${call.callId}` },
|
|
200
|
-
}),
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
await writeFile(transcriptPath, `${transcriptLines.join('\n')}\n`, 'utf8');
|
|
204
|
-
|
|
205
|
-
await withIsolatedDatabase(async () => {
|
|
206
|
-
sessionsDb.createAppSession('app-exec-1', 'codex', workspacePath);
|
|
207
|
-
sessionsDb.assignProviderSessionId('app-exec-1', providerSessionId);
|
|
208
|
-
await new CodexSessionSynchronizer().synchronize();
|
|
209
|
-
|
|
210
|
-
const history = await new CodexSessionsProvider().fetchHistory('app-exec-1');
|
|
211
|
-
const toolUses = history.messages.filter((message) => message.kind === 'tool_use');
|
|
212
|
-
const toolResults = history.messages.filter((message) => message.kind === 'tool_result');
|
|
213
|
-
const toolUsesById = new Map(toolUses.map((message) => [message.toolId, message]));
|
|
214
|
-
const toolResultsById = new Map(toolResults.map((message) => [message.toolId, message]));
|
|
215
|
-
|
|
216
|
-
assert.equal(toolUses.length, wrappedCalls.length);
|
|
217
|
-
assert.equal(toolResults.length, wrappedCalls.length);
|
|
218
|
-
for (const call of wrappedCalls) {
|
|
219
|
-
const toolUse = toolUsesById.get(call.callId);
|
|
220
|
-
assert.ok(toolUse);
|
|
221
|
-
assert.equal(toolUse.toolName, call.expectedToolName || 'exec');
|
|
222
|
-
assert.equal(toolUse.toolInput, call.expectedToolInput || call.input);
|
|
223
|
-
assert.equal(toolUse.toolResult?.content, `result:${call.callId}`);
|
|
224
|
-
assert.equal(toolResultsById.get(call.callId)?.content, `result:${call.callId}`);
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
} finally {
|
|
228
|
-
restoreHomeDir();
|
|
229
|
-
await rm(tempRoot, { recursive: true, force: true });
|
|
230
|
-
}
|
|
231
|
-
});
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
|
|
7
|
+
import { closeConnection, initializeDatabase, sessionsDb } from '@/modules/database/index.js';
|
|
8
|
+
import { CodexSessionSynchronizer } from '@/modules/providers/list/codex/codex-session-synchronizer.provider.js';
|
|
9
|
+
import { CodexSessionsProvider } from '@/modules/providers/list/codex/codex-sessions.provider.js';
|
|
10
|
+
|
|
11
|
+
const patchHomeDir = (nextHomeDir: string) => {
|
|
12
|
+
const original = os.homedir;
|
|
13
|
+
(os as any).homedir = () => nextHomeDir;
|
|
14
|
+
return () => {
|
|
15
|
+
(os as any).homedir = original;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
async function withIsolatedDatabase(runTest: () => void | Promise<void>): Promise<void> {
|
|
20
|
+
const previousDatabasePath = process.env.DATABASE_PATH;
|
|
21
|
+
const tempDirectory = await mkdtemp(path.join(os.tmpdir(), 'codex-provider-db-'));
|
|
22
|
+
const databasePath = path.join(tempDirectory, 'auth.db');
|
|
23
|
+
|
|
24
|
+
closeConnection();
|
|
25
|
+
process.env.DATABASE_PATH = databasePath;
|
|
26
|
+
await initializeDatabase();
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
await runTest();
|
|
30
|
+
} finally {
|
|
31
|
+
closeConnection();
|
|
32
|
+
if (previousDatabasePath === undefined) {
|
|
33
|
+
delete process.env.DATABASE_PATH;
|
|
34
|
+
} else {
|
|
35
|
+
process.env.DATABASE_PATH = previousDatabasePath;
|
|
36
|
+
}
|
|
37
|
+
await rm(tempDirectory, { recursive: true, force: true });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Writes one Codex rollout transcript. `firstUserMessage` mirrors the
|
|
43
|
+
* `event_msg`/`user_message` payload the runtime records for the prompt the
|
|
44
|
+
* user typed; omitting it produces a transcript with no user turn.
|
|
45
|
+
*/
|
|
46
|
+
const writeCodexTranscript = async (
|
|
47
|
+
homeDir: string,
|
|
48
|
+
codexSessionId: string,
|
|
49
|
+
workspacePath: string,
|
|
50
|
+
firstUserMessage?: string,
|
|
51
|
+
): Promise<string> => {
|
|
52
|
+
const sessionsDir = path.join(homeDir, '.codex', 'sessions', '2026', '07', '07');
|
|
53
|
+
await mkdir(sessionsDir, { recursive: true });
|
|
54
|
+
|
|
55
|
+
const lines: string[] = [
|
|
56
|
+
JSON.stringify({ type: 'session_meta', payload: { id: codexSessionId, cwd: workspacePath } }),
|
|
57
|
+
];
|
|
58
|
+
if (firstUserMessage !== undefined) {
|
|
59
|
+
lines.push(JSON.stringify({ type: 'event_msg', payload: { type: 'user_message', message: firstUserMessage } }));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const filePath = path.join(sessionsDir, `rollout-${codexSessionId}.jsonl`);
|
|
63
|
+
await writeFile(filePath, `${lines.join('\n')}\n`, 'utf8');
|
|
64
|
+
return filePath;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
test('Codex synchronizer preserves the title assigned when CloudCLI creates a session', { concurrency: false }, async () => {
|
|
68
|
+
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-app-'));
|
|
69
|
+
const workspacePath = path.join(tempRoot, 'workspace');
|
|
70
|
+
await mkdir(workspacePath, { recursive: true });
|
|
71
|
+
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
await writeCodexTranscript(tempRoot, 'codex-app-1', workspacePath, 'Provider transcript title must not win');
|
|
75
|
+
await withIsolatedDatabase(async () => {
|
|
76
|
+
// The app allocates its own id and later maps the provider id onto it,
|
|
77
|
+
// exactly as a message sent from cloudcli does.
|
|
78
|
+
sessionsDb.createAppSession('app-1', 'codex', workspacePath, 'Fix the login redirect');
|
|
79
|
+
sessionsDb.assignProviderSessionId('app-1', 'codex-app-1');
|
|
80
|
+
|
|
81
|
+
const synchronizer = new CodexSessionSynchronizer();
|
|
82
|
+
await synchronizer.synchronize();
|
|
83
|
+
|
|
84
|
+
assert.equal(sessionsDb.getSessionById('app-1')?.custom_name, 'Fix the login redirect');
|
|
85
|
+
});
|
|
86
|
+
} finally {
|
|
87
|
+
restoreHomeDir();
|
|
88
|
+
await rm(tempRoot, { recursive: true, force: true });
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('Codex synchronizer skips sub-agent rollout files', { concurrency: false }, async () => {
|
|
93
|
+
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-subagent-'));
|
|
94
|
+
const workspacePath = path.join(tempRoot, 'workspace');
|
|
95
|
+
await mkdir(workspacePath, { recursive: true });
|
|
96
|
+
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
// Codex >=0.144 spawn_agent threads write their own rollout files into the
|
|
100
|
+
// same sessions tree, marked via thread_source/source in session_meta.
|
|
101
|
+
const sessionsDir = path.join(tempRoot, '.codex', 'sessions', '2026', '07', '07');
|
|
102
|
+
await mkdir(sessionsDir, { recursive: true });
|
|
103
|
+
await writeFile(
|
|
104
|
+
path.join(sessionsDir, 'rollout-codex-subagent-1.jsonl'),
|
|
105
|
+
`${JSON.stringify({
|
|
106
|
+
type: 'session_meta',
|
|
107
|
+
payload: {
|
|
108
|
+
id: 'codex-subagent-1',
|
|
109
|
+
cwd: workspacePath,
|
|
110
|
+
thread_source: 'subagent',
|
|
111
|
+
parent_thread_id: 'codex-parent-1',
|
|
112
|
+
source: { subagent: { thread_spawn: { parent_thread_id: 'codex-parent-1', depth: 1 } } },
|
|
113
|
+
},
|
|
114
|
+
})}\n`,
|
|
115
|
+
'utf8'
|
|
116
|
+
);
|
|
117
|
+
await writeCodexTranscript(tempRoot, 'codex-parent-1', workspacePath);
|
|
118
|
+
|
|
119
|
+
await withIsolatedDatabase(async () => {
|
|
120
|
+
const synchronizer = new CodexSessionSynchronizer();
|
|
121
|
+
const processed = await synchronizer.synchronize();
|
|
122
|
+
|
|
123
|
+
assert.equal(processed, 1);
|
|
124
|
+
assert.ok(sessionsDb.getSessionById('codex-parent-1'));
|
|
125
|
+
assert.equal(sessionsDb.getSessionById('codex-subagent-1'), null);
|
|
126
|
+
});
|
|
127
|
+
} finally {
|
|
128
|
+
restoreHomeDir();
|
|
129
|
+
await rm(tempRoot, { recursive: true, force: true });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('Codex synchronizer leaves indexed sessions untitled when no name is available', { concurrency: false }, async () => {
|
|
134
|
+
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-session-sync-indexed-'));
|
|
135
|
+
const workspacePath = path.join(tempRoot, 'workspace');
|
|
136
|
+
await mkdir(workspacePath, { recursive: true });
|
|
137
|
+
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
// A CLI-created session has no app row; its first user message must NOT be
|
|
141
|
+
// used as the title, preserving the existing indexing behavior.
|
|
142
|
+
await writeCodexTranscript(tempRoot, 'codex-indexed-1', workspacePath, 'This prompt should be ignored');
|
|
143
|
+
await withIsolatedDatabase(async () => {
|
|
144
|
+
const synchronizer = new CodexSessionSynchronizer();
|
|
145
|
+
await synchronizer.synchronize();
|
|
146
|
+
|
|
147
|
+
assert.equal(sessionsDb.getSessionById('codex-indexed-1')?.custom_name, 'Untitled Codex Session');
|
|
148
|
+
});
|
|
149
|
+
} finally {
|
|
150
|
+
restoreHomeDir();
|
|
151
|
+
await rm(tempRoot, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('Codex history preserves wrapped exec tool calls and results', { concurrency: false }, async () => {
|
|
156
|
+
const tempRoot = await mkdtemp(path.join(os.tmpdir(), 'codex-exec-history-'));
|
|
157
|
+
const workspacePath = path.join(tempRoot, 'workspace');
|
|
158
|
+
await mkdir(workspacePath, { recursive: true });
|
|
159
|
+
const restoreHomeDir = patchHomeDir(tempRoot);
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const providerSessionId = 'codex-exec-1';
|
|
163
|
+
const transcriptPath = await writeCodexTranscript(tempRoot, providerSessionId, workspacePath);
|
|
164
|
+
const wrappedCalls = [
|
|
165
|
+
{
|
|
166
|
+
callId: 'shell-command-1',
|
|
167
|
+
input: 'const cmds = ["echo one", "echo two"]; await Promise.all(cmds.map(command => tools.shell_command({ command })));',
|
|
168
|
+
expectedToolName: 'Bash',
|
|
169
|
+
expectedToolInput: JSON.stringify({ command: 'echo one\necho two' }),
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
callId: 'json-shell-command-1',
|
|
173
|
+
input: 'const r = await tools.shell_command({"command":"Get-Content -Raw README.md","workdir":"C:\\\\workspace","timeout_ms":10000}); text(r)',
|
|
174
|
+
expectedToolName: 'Bash',
|
|
175
|
+
expectedToolInput: JSON.stringify({ command: 'Get-Content -Raw README.md' }),
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
callId: 'exec-command-1',
|
|
179
|
+
input: 'await tools.exec_command({"command":"echo current"});',
|
|
180
|
+
expectedToolName: 'Bash',
|
|
181
|
+
expectedToolInput: JSON.stringify({ command: 'echo current' }),
|
|
182
|
+
},
|
|
183
|
+
{ callId: 'apply-patch-1', input: 'await tools.apply_patch("*** Begin Patch\\n*** End Patch");' },
|
|
184
|
+
{ callId: 'web-run-1', input: 'await tools.web__run({ search_query: [{ q: "Codex" }] });' },
|
|
185
|
+
{ callId: 'update-plan-1', input: 'await tools.update_plan({ plan: [] });' },
|
|
186
|
+
{ callId: 'unknown-1', input: 'await tools.unknown_wrapper({ value: true });' },
|
|
187
|
+
];
|
|
188
|
+
const transcriptLines = [
|
|
189
|
+
JSON.stringify({ type: 'session_meta', payload: { id: providerSessionId, cwd: workspacePath } }),
|
|
190
|
+
];
|
|
191
|
+
for (const call of wrappedCalls) {
|
|
192
|
+
transcriptLines.push(
|
|
193
|
+
JSON.stringify({
|
|
194
|
+
type: 'response_item',
|
|
195
|
+
payload: { type: 'custom_tool_call', name: 'exec', call_id: call.callId, input: call.input },
|
|
196
|
+
}),
|
|
197
|
+
JSON.stringify({
|
|
198
|
+
type: 'response_item',
|
|
199
|
+
payload: { type: 'custom_tool_call_output', call_id: call.callId, output: `result:${call.callId}` },
|
|
200
|
+
}),
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
await writeFile(transcriptPath, `${transcriptLines.join('\n')}\n`, 'utf8');
|
|
204
|
+
|
|
205
|
+
await withIsolatedDatabase(async () => {
|
|
206
|
+
sessionsDb.createAppSession('app-exec-1', 'codex', workspacePath);
|
|
207
|
+
sessionsDb.assignProviderSessionId('app-exec-1', providerSessionId);
|
|
208
|
+
await new CodexSessionSynchronizer().synchronize();
|
|
209
|
+
|
|
210
|
+
const history = await new CodexSessionsProvider().fetchHistory('app-exec-1');
|
|
211
|
+
const toolUses = history.messages.filter((message) => message.kind === 'tool_use');
|
|
212
|
+
const toolResults = history.messages.filter((message) => message.kind === 'tool_result');
|
|
213
|
+
const toolUsesById = new Map(toolUses.map((message) => [message.toolId, message]));
|
|
214
|
+
const toolResultsById = new Map(toolResults.map((message) => [message.toolId, message]));
|
|
215
|
+
|
|
216
|
+
assert.equal(toolUses.length, wrappedCalls.length);
|
|
217
|
+
assert.equal(toolResults.length, wrappedCalls.length);
|
|
218
|
+
for (const call of wrappedCalls) {
|
|
219
|
+
const toolUse = toolUsesById.get(call.callId);
|
|
220
|
+
assert.ok(toolUse);
|
|
221
|
+
assert.equal(toolUse.toolName, call.expectedToolName || 'exec');
|
|
222
|
+
assert.equal(toolUse.toolInput, call.expectedToolInput || call.input);
|
|
223
|
+
assert.equal(toolUse.toolResult?.content, `result:${call.callId}`);
|
|
224
|
+
assert.equal(toolResultsById.get(call.callId)?.content, `result:${call.callId}`);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
} finally {
|
|
228
|
+
restoreHomeDir();
|
|
229
|
+
await rm(tempRoot, { recursive: true, force: true });
|
|
230
|
+
}
|
|
231
|
+
});
|