wind-agent-cli 1.37.2 → 1.38.0

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.
Files changed (510) hide show
  1. package/LICENSE +718 -718
  2. package/README.md +17 -2
  3. package/dist/api-docs.html +901 -901
  4. package/dist/assets/{CodeEditor-B2Wf7Fg0.js → CodeEditor-FvgsnJ7J.js} +6 -6
  5. package/dist/assets/FileTree-NLULrBDi.js +1 -0
  6. package/dist/assets/GitPanel-51KUBbEW.js +4 -0
  7. package/dist/assets/{MarkdownPreview-C0tqYnVu.js → MarkdownPreview-PEEWVWeS.js} +17 -27
  8. package/dist/assets/Shell-BEx66cW_.js +76 -0
  9. package/dist/assets/Shell-DrlLKa8f.css +1 -0
  10. package/dist/assets/StandaloneShell-BkuUCPZP.js +1 -0
  11. package/dist/assets/TaskMasterPanel-DfQG80SF.js +2 -0
  12. package/dist/assets/abnfDiagram-N423BO3Z-Cc0ul87U.js +1 -0
  13. package/dist/assets/arc-BAuugHw_.js +1 -0
  14. package/dist/assets/architectureDiagram-T3A2C74G-DA3G7QZD.js +36 -0
  15. package/dist/assets/{blockDiagram-VBNYF7ZC-DpaEf3mv.js → blockDiagram-VBNYF7ZC-tJ12IJs3.js} +4 -4
  16. package/dist/assets/c4Diagram-5PPSVZJV-5BTMCXL4.js +10 -0
  17. package/dist/assets/channel-BGDgNNQz.js +1 -0
  18. package/dist/assets/{chunk-2GRJ4B5K-DoSdNo8u.js → chunk-2GRJ4B5K-BPaI06Ou.js} +1 -1
  19. package/dist/assets/{chunk-2Q5K7J3B-CE7I3uMn.js → chunk-2Q5K7J3B-HV4zmsEe.js} +1 -1
  20. package/dist/assets/chunk-5RXB4S5H-BAwutJoU.js +231 -0
  21. package/dist/assets/{chunk-5VM5RSS4-B55XgqHZ.js → chunk-5VM5RSS4-B9QAJPrv.js} +1 -1
  22. package/dist/assets/{chunk-6Q2QTUOP-BS1KpefW.js → chunk-6Q2QTUOP-BOIW8bzI.js} +1 -1
  23. package/dist/assets/chunk-GF5L2VYU-DD13o00-.js +206 -0
  24. package/dist/assets/{chunk-JWPE2WC7-DOtkNhMm.js → chunk-JWPE2WC7-CFBm23VK.js} +1 -1
  25. package/dist/assets/{chunk-KBJHAD2P-BXLjviqM.js → chunk-KBJHAD2P-C0i0v8Op.js} +1 -1
  26. package/dist/assets/{chunk-RYQCIY6F-C50fjNNz.js → chunk-RYQCIY6F-DfeK0taV.js} +1 -1
  27. package/dist/assets/{chunk-XXDRQBXY-QBYqCkb7.js → chunk-XXDRQBXY-BKWvf-QE.js} +1 -1
  28. package/dist/assets/classDiagram-JCYQIIEL-C2SNM4oy.js +1 -0
  29. package/dist/assets/classDiagram-v2-OCEON4UE-C2SNM4oy.js +1 -0
  30. package/dist/assets/cose-bilkent-JH36ORCC-CBE8oM7L.js +1 -0
  31. package/dist/assets/{cynefin-VYW2F7L2-DnJa_OlQ.js → cynefin-VYW2F7L2-DziGp35A.js} +11 -23
  32. package/dist/assets/cynefinDiagram-MW4NZA55-CNvtHl39.js +62 -0
  33. package/dist/assets/cytoscape.esm-yzknjiTM.js +321 -0
  34. package/dist/assets/dagre-VZM6K2ZE-Bz9lsU7m.js +4 -0
  35. package/dist/assets/{diagram-7IWD3JNH-pFzs9HEu.js → diagram-7IWD3JNH-CV7D3VSd.js} +5 -5
  36. package/dist/assets/{diagram-B4RE2ZJO-CcehQC7x.js → diagram-B4RE2ZJO-Dj4EjDNC.js} +2 -2
  37. package/dist/assets/diagram-LBJQPF4R-wJ6FHvf-.js +24 -0
  38. package/dist/assets/diagram-Q27KOJAE-DMFYMhOB.js +24 -0
  39. package/dist/assets/diagram-UB23O5K3-DeBSbWAI.js +41 -0
  40. package/dist/assets/ebnfDiagram-BXEA7PRR-2NnJSGhT.js +1 -0
  41. package/dist/assets/erDiagram-JOGREHBK-DrSlg8hr.js +85 -0
  42. package/dist/assets/feature-chat-CvOCyaLe.js +88 -0
  43. package/dist/assets/feature-workspace-CAB6bgPy.js +39 -0
  44. package/dist/assets/{flowDiagram-UKHOOZJN-CJV8fQPR.js → flowDiagram-UKHOOZJN-C0pejU6W.js} +4 -4
  45. package/dist/assets/ganttDiagram-PKOTCBZU-BM0VCUUz.js +292 -0
  46. package/dist/assets/gitGraphDiagram-DS77QQ5N-SbLG0c5_.js +106 -0
  47. package/dist/assets/graph-DOmOIIwC.js +1 -0
  48. package/dist/assets/{index-GFhXZyl2.js → index-BflGfU1C.js} +3 -3
  49. package/dist/assets/index-Btkf0_rU.js +1 -0
  50. package/dist/assets/index-Cr5MbHuj.css +1 -0
  51. package/dist/assets/index-Gqazqfs3.js +1 -0
  52. package/dist/assets/index-nyrkoQK6.js +35 -0
  53. package/dist/assets/infoDiagram-6WML65LV-Cf5DSa66.js +2 -0
  54. package/dist/assets/ishikawaDiagram-WSZJBQD7-DwyFutKy.js +70 -0
  55. package/dist/assets/journeyDiagram-NVQOT4AX-Df0FRhLo.js +139 -0
  56. package/dist/assets/{kanban-definition-27J2QSJJ-B3iL0ztJ.js → kanban-definition-27J2QSJJ-HmpbjrZz.js} +6 -6
  57. package/dist/assets/{layout-D6BstSzF.js → layout-D-LzfAck.js} +1 -1
  58. package/dist/assets/{linear-Cwe9dEKA.js → linear-DOM01LBe.js} +1 -1
  59. package/dist/assets/map-DxJ2ADlA.js +1 -0
  60. package/dist/assets/mermaid.core-C2Ma-_S6.js +306 -0
  61. package/dist/assets/{mindmap-definition-FAOFIHXS-BgfBYMzr.js → mindmap-definition-FAOFIHXS-B4GOIn76.js} +4 -4
  62. package/dist/assets/pegDiagram-VL7TDLO6-BHur7aH2.js +1 -0
  63. package/dist/assets/{pieDiagram-7S7Q4E2Y-DeSrxc4I.js → pieDiagram-7S7Q4E2Y-Cw0UELLV.js} +2 -2
  64. package/dist/assets/quadrantDiagram-CIZ2JOQS-CB2BrX3g.js +7 -0
  65. package/dist/assets/railroadDiagram-AXF67PYL-DPYZYmLX.js +1 -0
  66. package/dist/assets/requirementDiagram-LRYGKXZP-DSX4IJ1n.js +84 -0
  67. package/dist/assets/sankeyDiagram-W5VNT64P-TenC3ZQo.js +40 -0
  68. package/dist/assets/sequenceDiagram-SI44F4Z6-DltGsf3F.js +162 -0
  69. package/dist/assets/sizeCapture-X5ZJPWSS-D7llwbJZ.js +1 -0
  70. package/dist/assets/stateDiagram-OKZ733FA-C-hAvbnY.js +1 -0
  71. package/dist/assets/stateDiagram-v2-UEYNNEHI-DaYSFcRQ.js +1 -0
  72. package/dist/assets/swimlanes-SLNWSIFB-DWD30fv6.js +2 -0
  73. package/dist/assets/swimlanesDiagram-ULZ7WXOC-LTkF2T6t.js +8 -0
  74. package/dist/assets/timeline-definition-Z64GVDOM-quWmimSE.js +120 -0
  75. package/dist/assets/vendor-data-DsEZeNPr.js +4 -0
  76. package/dist/assets/vendor-i18n-B6HjLCnN.js +1 -0
  77. package/dist/assets/vendor-markdown-DkITEES2.js +298 -0
  78. package/dist/assets/vendor-react-C2GTiUCy.js +10 -0
  79. package/dist/assets/vendor-ui-CAUHSABu.js +49 -0
  80. package/dist/assets/vennDiagram-T6HMQDX7-aUQcm8h5.js +34 -0
  81. package/dist/assets/{wardleyDiagram-T6FBY63Y-BNCpsFZV.js → wardleyDiagram-T6FBY63Y-BZ0bwsFQ.js} +2 -2
  82. package/dist/assets/workbox-window.prod.es5-BBnX5xw4.js +2 -0
  83. package/dist/assets/xychartDiagram-ELKLHX3M-DOVzAq63.js +7 -0
  84. package/dist/clear-cache.html +85 -85
  85. package/dist/convert-icons.md +52 -52
  86. package/dist/favicon.png +0 -0
  87. package/dist/favicon.svg +8 -8
  88. package/dist/generate-icons.js +48 -48
  89. package/dist/icons/codex-white.svg +3 -3
  90. package/dist/icons/codex.svg +3 -3
  91. package/dist/icons/cursor-white.svg +11 -11
  92. package/dist/icons/icon-128x128.png +0 -0
  93. package/dist/icons/icon-128x128.svg +11 -11
  94. package/dist/icons/icon-144x144.png +0 -0
  95. package/dist/icons/icon-144x144.svg +11 -11
  96. package/dist/icons/icon-152x152.png +0 -0
  97. package/dist/icons/icon-152x152.svg +11 -11
  98. package/dist/icons/icon-180x180.png +0 -0
  99. package/dist/icons/icon-192x192.png +0 -0
  100. package/dist/icons/icon-192x192.svg +11 -11
  101. package/dist/icons/icon-384x384.png +0 -0
  102. package/dist/icons/icon-384x384.svg +11 -11
  103. package/dist/icons/icon-512x512.png +0 -0
  104. package/dist/icons/icon-512x512.svg +11 -11
  105. package/dist/icons/icon-72x72.png +0 -0
  106. package/dist/icons/icon-72x72.svg +11 -11
  107. package/dist/icons/icon-96x96.png +0 -0
  108. package/dist/icons/icon-96x96.svg +11 -11
  109. package/dist/icons/icon-maskable-192x192.png +0 -0
  110. package/dist/icons/icon-maskable-512x512.png +0 -0
  111. package/dist/icons/icon-template.svg +11 -11
  112. package/dist/icons/new-icon.png +0 -0
  113. package/dist/index.html +48 -58
  114. package/dist/logo-128.png +0 -0
  115. package/dist/logo-256.png +0 -0
  116. package/dist/logo.svg +17 -17
  117. package/dist/manifest.webmanifest +1 -0
  118. package/dist/push-sw.js +48 -0
  119. package/dist/screenshots/setup-screen-mobile.png +0 -0
  120. package/dist/screenshots/setup-screen.png +0 -0
  121. package/dist/sw.js +1 -124
  122. package/dist/workbox-ae5c0bb2.js +1 -0
  123. package/dist-server/server/index.js +1 -1
  124. package/dist-server/server/index.js.map +1 -1
  125. package/dist-server/server/load-env.js +4 -2
  126. package/dist-server/server/load-env.js.map +1 -1
  127. package/dist-server/server/modules/agent/agent.routes.js +1 -1
  128. package/dist-server/server/modules/agent/agent.routes.js.map +1 -1
  129. package/dist-server/server/modules/browser-use/browser-use.service.js +1 -1
  130. package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -1
  131. package/dist-server/server/modules/cli/cli.service.js +37 -37
  132. package/dist-server/server/modules/cli/cli.service.js.map +1 -1
  133. package/dist-server/server/modules/cli/sandbox.service.js +43 -43
  134. package/dist-server/server/modules/cli/sandbox.service.js.map +1 -1
  135. package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +74 -74
  136. package/dist-server/server/modules/commands/commands.routes.js +25 -25
  137. package/dist-server/server/modules/commands/commands.routes.js.map +1 -1
  138. package/dist-server/server/modules/commands/tests/commands.test.js +1 -1
  139. package/dist-server/server/modules/commands/tests/commands.test.js.map +1 -1
  140. package/dist-server/server/modules/database/connection.js +1 -1
  141. package/dist-server/server/modules/database/connection.js.map +1 -1
  142. package/dist-server/server/modules/database/migrations.js +190 -190
  143. package/dist-server/server/modules/database/repositories/api-keys.js +3 -3
  144. package/dist-server/server/modules/database/repositories/github-tokens.js +2 -2
  145. package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js +28 -28
  146. package/dist-server/server/modules/database/repositories/notification-preferences.js +4 -4
  147. package/dist-server/server/modules/database/repositories/projects.db.js +61 -61
  148. package/dist-server/server/modules/database/repositories/provider-models.js +35 -35
  149. package/dist-server/server/modules/database/repositories/push-subscriptions.js +5 -5
  150. package/dist-server/server/modules/database/repositories/scan-state.db.js +5 -5
  151. package/dist-server/server/modules/database/repositories/sessions.db.js +93 -93
  152. package/dist-server/server/modules/database/schema.js +177 -177
  153. package/dist-server/server/modules/database/tests/projects.db.integration.test.js +3 -2
  154. package/dist-server/server/modules/database/tests/projects.db.integration.test.js.map +1 -1
  155. package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +6 -6
  156. package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js +4 -3
  157. package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js.map +1 -1
  158. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js +2 -1
  159. package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -1
  160. package/dist-server/server/modules/git/git.routes.js +17 -17
  161. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +1 -1
  162. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js.map +1 -1
  163. package/dist-server/server/modules/notifications/vapid-keys.service.js +1 -1
  164. package/dist-server/server/modules/notifications/vapid-keys.service.js.map +1 -1
  165. package/dist-server/server/modules/projects/tests/project-management.service.test.js +2 -1
  166. package/dist-server/server/modules/projects/tests/project-management.service.test.js.map +1 -1
  167. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js +2 -2
  168. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js.map +1 -1
  169. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +1 -1
  170. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  171. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +1 -1
  172. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -1
  173. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -1
  174. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +13 -13
  175. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +9 -9
  176. package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +17 -17
  177. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +25 -25
  178. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +27 -27
  179. package/dist-server/server/modules/providers/services/provider-token-usage.service.js +9 -9
  180. package/dist-server/server/modules/providers/services/sessions.service.js +1 -1
  181. package/dist-server/server/modules/providers/tests/claude-auth.test.js +8 -0
  182. package/dist-server/server/modules/providers/tests/claude-auth.test.js.map +1 -1
  183. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +1 -1
  184. package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -1
  185. package/dist-server/server/modules/providers/tests/mcp.test.js +3 -3
  186. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +98 -98
  187. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
  188. package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +18 -18
  189. package/dist-server/server/modules/providers/tests/provider.routes.test.js +1 -1
  190. package/dist-server/server/modules/providers/tests/provider.routes.test.js.map +1 -1
  191. package/dist-server/server/modules/system/system.service.js +1 -1
  192. package/dist-server/server/modules/system/system.service.js.map +1 -1
  193. package/dist-server/server/modules/system/tests/system.service.test.js +1 -1
  194. package/dist-server/server/modules/system/tests/system.service.test.js.map +1 -1
  195. package/dist-server/server/modules/taskmaster/taskmaster.routes.js +423 -422
  196. package/dist-server/server/modules/taskmaster/taskmaster.routes.js.map +1 -1
  197. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +1 -1
  198. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  199. package/dist-server/server/modules/worktrees/services/worktree-list.service.js +1 -1
  200. package/dist-server/server/modules/worktrees/services/worktree-open.service.js +1 -1
  201. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js +1 -1
  202. package/electron/cloud.js +260 -260
  203. package/electron/desktopNotifications.js +378 -378
  204. package/electron/desktopWindow.js +766 -766
  205. package/electron/launcher/index.html +14 -14
  206. package/electron/launcher/launcher.css +801 -801
  207. package/electron/launcher/launcher.js +687 -687
  208. package/electron/localServer.js +549 -549
  209. package/electron/main.js +944 -944
  210. package/electron/preload.cjs +60 -60
  211. package/electron/scripts/generate-macos-icon.js +62 -62
  212. package/electron/serverInstaller.js +277 -277
  213. package/electron/tabs.js +87 -87
  214. package/electron/viewHost.js +331 -331
  215. package/package.json +262 -247
  216. package/public/api-docs.html +901 -901
  217. package/scripts/build-client.mjs +30 -0
  218. package/scripts/fix-node-pty.js +67 -67
  219. package/scripts/generate-pwa-icons.ps1 +33 -0
  220. package/scripts/promote-dist-server.mjs +50 -50
  221. package/scripts/release/build-server-bundle.js +176 -176
  222. package/scripts/release/prepare-desktop-app.js +152 -152
  223. package/scripts/verify-pwa-build.mjs +37 -0
  224. package/server/index.ts +399 -399
  225. package/server/load-env.ts +49 -47
  226. package/server/modules/agent/agent.module.ts +52 -52
  227. package/server/modules/agent/agent.routes.ts +1287 -1287
  228. package/server/modules/agent/index.ts +2 -2
  229. package/server/modules/agent/tests/agent.routes.test.ts +205 -205
  230. package/server/modules/assets/assets.routes.ts +150 -150
  231. package/server/modules/assets/index.ts +3 -3
  232. package/server/modules/assets/services/image-assets.service.ts +127 -127
  233. package/server/modules/assets/tests/image-assets.service.test.ts +74 -74
  234. package/server/modules/auth/auth.middleware.ts +163 -163
  235. package/server/modules/auth/auth.module.ts +38 -38
  236. package/server/modules/auth/auth.routes.ts +57 -57
  237. package/server/modules/auth/auth.service.ts +155 -155
  238. package/server/modules/auth/index.ts +9 -9
  239. package/server/modules/auth/tests/auth.service.test.ts +95 -95
  240. package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -120
  241. package/server/modules/browser-use/browser-use-mcp.ts +386 -386
  242. package/server/modules/browser-use/browser-use-runtime.ts +10 -10
  243. package/server/modules/browser-use/browser-use.routes.ts +96 -96
  244. package/server/modules/browser-use/browser-use.service.ts +836 -836
  245. package/server/modules/browser-use/index.ts +11 -11
  246. package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -10
  247. package/server/modules/cli/cli.module.ts +93 -93
  248. package/server/modules/cli/cli.service.ts +248 -248
  249. package/server/modules/cli/cli.ts +19 -19
  250. package/server/modules/cli/index.ts +2 -2
  251. package/server/modules/cli/sandbox.service.ts +398 -398
  252. package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +186 -186
  253. package/server/modules/cli/tests/cli.service.test.ts +86 -86
  254. package/server/modules/cli/tests/sandbox.service.test.ts +58 -58
  255. package/server/modules/commands/commands.module.ts +22 -22
  256. package/server/modules/commands/commands.routes.ts +587 -587
  257. package/server/modules/commands/index.ts +2 -2
  258. package/server/modules/commands/tests/commands.test.ts +110 -110
  259. package/server/modules/database/connection.ts +144 -143
  260. package/server/modules/database/index.ts +17 -17
  261. package/server/modules/database/init-db.ts +17 -17
  262. package/server/modules/database/migrations.ts +515 -515
  263. package/server/modules/database/repositories/api-keys.ts +119 -119
  264. package/server/modules/database/repositories/app-config.ts +53 -53
  265. package/server/modules/database/repositories/credentials.ts +106 -106
  266. package/server/modules/database/repositories/github-tokens.ts +100 -100
  267. package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -153
  268. package/server/modules/database/repositories/notification-preferences.ts +117 -117
  269. package/server/modules/database/repositories/projects.db.ts +196 -196
  270. package/server/modules/database/repositories/provider-models.ts +168 -168
  271. package/server/modules/database/repositories/push-subscriptions.ts +80 -80
  272. package/server/modules/database/repositories/scan-state.db.ts +42 -42
  273. package/server/modules/database/repositories/sessions.db.ts +524 -524
  274. package/server/modules/database/repositories/users.ts +140 -140
  275. package/server/modules/database/repositories/vapid-keys.ts +57 -57
  276. package/server/modules/database/schema.ts +210 -210
  277. package/server/modules/database/tests/projects.db.integration.test.ts +73 -72
  278. package/server/modules/database/tests/provider-models.db.integration.test.ts +125 -125
  279. package/server/modules/database/tests/sessions-provider-mapping.test.ts +110 -109
  280. package/server/modules/database/tests/sessions.db.integration.test.ts +117 -116
  281. package/server/modules/file-tree/file-tree.module.ts +116 -116
  282. package/server/modules/file-tree/file-tree.routes.ts +258 -258
  283. package/server/modules/file-tree/file-tree.service.ts +675 -675
  284. package/server/modules/file-tree/index.ts +2 -2
  285. package/server/modules/file-tree/tests/file-tree.routes.test.ts +157 -157
  286. package/server/modules/file-tree/tests/file-tree.service.test.ts +371 -371
  287. package/server/modules/git/git-branch.service.ts +43 -43
  288. package/server/modules/git/git-parsing.service.ts +66 -66
  289. package/server/modules/git/git.module.ts +22 -22
  290. package/server/modules/git/git.routes.ts +1596 -1596
  291. package/server/modules/git/index.ts +2 -2
  292. package/server/modules/git/tests/git-branch.service.test.ts +60 -60
  293. package/server/modules/git/tests/git-init.routes.test.ts +132 -132
  294. package/server/modules/git/tests/git.test.ts +106 -106
  295. package/server/modules/notifications/index.ts +24 -24
  296. package/server/modules/notifications/notifications.routes.ts +127 -127
  297. package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -124
  298. package/server/modules/notifications/services/notification-orchestrator.service.js +310 -310
  299. package/server/modules/notifications/tests/notification-orchestrator.integration.test.ts +55 -55
  300. package/server/modules/notifications/vapid-keys.service.ts +38 -38
  301. package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -109
  302. package/server/modules/plugins/index.ts +9 -9
  303. package/server/modules/plugins/plugin-process.service.ts +217 -217
  304. package/server/modules/plugins/plugin-registry.service.ts +459 -459
  305. package/server/modules/plugins/plugins.module.ts +33 -33
  306. package/server/modules/plugins/plugins.routes.ts +66 -66
  307. package/server/modules/plugins/plugins.service.ts +147 -147
  308. package/server/modules/plugins/tests/plugins.service.test.ts +32 -32
  309. package/server/modules/projects/index.ts +11 -11
  310. package/server/modules/projects/projects.routes.ts +273 -273
  311. package/server/modules/projects/services/project-clone.service.ts +323 -323
  312. package/server/modules/projects/services/project-delete.service.ts +90 -90
  313. package/server/modules/projects/services/project-management.service.ts +144 -144
  314. package/server/modules/projects/services/project-star.service.ts +78 -78
  315. package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -248
  316. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +314 -314
  317. package/server/modules/projects/tests/project-clone.service.test.ts +183 -183
  318. package/server/modules/projects/tests/project-management.service.test.ts +118 -117
  319. package/server/modules/projects/tests/project-star.service.test.ts +123 -123
  320. package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -105
  321. package/server/modules/providers/README.md +380 -380
  322. package/server/modules/providers/index.ts +10 -10
  323. package/server/modules/providers/list/claude/claude-auth.provider.ts +160 -160
  324. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
  325. package/server/modules/providers/list/claude/claude-models.provider.ts +294 -294
  326. package/server/modules/providers/list/claude/claude-runtime.provider.js +1068 -1068
  327. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +203 -203
  328. package/server/modules/providers/list/claude/claude-sessions.provider.ts +684 -684
  329. package/server/modules/providers/list/claude/claude-skills.provider.ts +265 -265
  330. package/server/modules/providers/list/claude/claude.provider.ts +30 -30
  331. package/server/modules/providers/list/codex/codex-app-server.client.ts +2 -2
  332. package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -100
  333. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
  334. package/server/modules/providers/list/codex/codex-models.provider.ts +123 -123
  335. package/server/modules/providers/list/codex/codex-runtime.provider.js +533 -533
  336. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +203 -203
  337. package/server/modules/providers/list/codex/codex-sessions.provider.ts +938 -938
  338. package/server/modules/providers/list/codex/codex-skills.provider.ts +73 -73
  339. package/server/modules/providers/list/codex/codex.provider.ts +28 -28
  340. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
  341. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
  342. package/server/modules/providers/list/cursor/cursor-models.provider.ts +119 -119
  343. package/server/modules/providers/list/cursor/cursor-runtime.provider.js +385 -385
  344. package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +158 -159
  345. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +654 -654
  346. package/server/modules/providers/list/cursor/cursor-skills.provider.ts +39 -39
  347. package/server/modules/providers/list/cursor/cursor.provider.ts +30 -30
  348. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +110 -110
  349. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -228
  350. package/server/modules/providers/list/opencode/opencode-models.provider.ts +203 -203
  351. package/server/modules/providers/list/opencode/opencode-runtime.provider.js +434 -434
  352. package/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +261 -261
  353. package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +179 -179
  354. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +500 -500
  355. package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -78
  356. package/server/modules/providers/list/opencode/opencode.provider.ts +30 -30
  357. package/server/modules/providers/provider.registry.ts +36 -36
  358. package/server/modules/providers/provider.routes.ts +877 -877
  359. package/server/modules/providers/services/mcp.service.ts +109 -109
  360. package/server/modules/providers/services/provider-auth.service.ts +26 -26
  361. package/server/modules/providers/services/provider-capabilities.service.ts +97 -97
  362. package/server/modules/providers/services/provider-models.service.ts +401 -401
  363. package/server/modules/providers/services/provider-runtime.service.ts +108 -108
  364. package/server/modules/providers/services/provider-token-usage.service.ts +357 -357
  365. package/server/modules/providers/services/session-conversations-search.service.ts +1321 -1321
  366. package/server/modules/providers/services/session-synchronizer.service.ts +74 -74
  367. package/server/modules/providers/services/sessions-watcher.service.ts +247 -247
  368. package/server/modules/providers/services/sessions.service.ts +471 -471
  369. package/server/modules/providers/services/skills.service.ts +39 -39
  370. package/server/modules/providers/shared/base/abstract.provider.ts +32 -32
  371. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
  372. package/server/modules/providers/shared/skills/skills.provider.ts +287 -287
  373. package/server/modules/providers/tests/claude-auth.test.ts +157 -150
  374. package/server/modules/providers/tests/claude-sessions.test.ts +61 -61
  375. package/server/modules/providers/tests/codex-sessions.test.ts +231 -231
  376. package/server/modules/providers/tests/mcp.test.ts +349 -349
  377. package/server/modules/providers/tests/opencode-models.test.ts +41 -41
  378. package/server/modules/providers/tests/opencode-sessions.test.ts +522 -522
  379. package/server/modules/providers/tests/provider-attachment-history.test.ts +247 -247
  380. package/server/modules/providers/tests/provider-models.service.test.ts +353 -353
  381. package/server/modules/providers/tests/provider-runtime.service.test.ts +138 -138
  382. package/server/modules/providers/tests/provider-token-usage.service.test.ts +186 -186
  383. package/server/modules/providers/tests/provider.routes.test.ts +244 -244
  384. package/server/modules/providers/tests/sessions-details.test.ts +73 -73
  385. package/server/modules/providers/tests/sessions.service.test.ts +127 -127
  386. package/server/modules/providers/tests/skills.test.ts +692 -692
  387. package/server/modules/settings/index.ts +2 -2
  388. package/server/modules/settings/settings.module.ts +50 -50
  389. package/server/modules/settings/settings.routes.ts +51 -51
  390. package/server/modules/settings/settings.service.ts +186 -186
  391. package/server/modules/settings/tests/settings.service.test.ts +54 -54
  392. package/server/modules/system/index.ts +2 -2
  393. package/server/modules/system/system.module.ts +62 -62
  394. package/server/modules/system/system.routes.ts +21 -21
  395. package/server/modules/system/system.service.ts +76 -76
  396. package/server/modules/system/tests/system.service.test.ts +118 -118
  397. package/server/modules/taskmaster/index.ts +2 -2
  398. package/server/modules/taskmaster/taskmaster.module.ts +24 -24
  399. package/server/modules/taskmaster/taskmaster.routes.ts +1483 -1482
  400. package/server/modules/taskmaster/taskmaster.service.ts +132 -132
  401. package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +144 -144
  402. package/server/modules/taskmaster/tests/taskmaster.service.test.ts +97 -97
  403. package/server/modules/user/index.ts +2 -2
  404. package/server/modules/user/tests/user.service.test.ts +61 -61
  405. package/server/modules/user/user.module.ts +58 -58
  406. package/server/modules/user/user.routes.ts +50 -50
  407. package/server/modules/user/user.service.ts +85 -85
  408. package/server/modules/voice/index.ts +2 -2
  409. package/server/modules/voice/tests/voice.service.test.ts +98 -98
  410. package/server/modules/voice/voice.module.ts +47 -47
  411. package/server/modules/voice/voice.routes.ts +113 -113
  412. package/server/modules/voice/voice.service.ts +192 -192
  413. package/server/modules/websocket/README.md +273 -273
  414. package/server/modules/websocket/index.ts +3 -3
  415. package/server/modules/websocket/services/chat-run-registry.service.ts +343 -343
  416. package/server/modules/websocket/services/chat-session-writer.service.ts +145 -145
  417. package/server/modules/websocket/services/chat-websocket.service.ts +425 -425
  418. package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -65
  419. package/server/modules/websocket/services/shell-websocket.service.ts +503 -503
  420. package/server/modules/websocket/services/websocket-auth.service.ts +59 -59
  421. package/server/modules/websocket/services/websocket-server.service.ts +124 -124
  422. package/server/modules/websocket/services/websocket-state.service.ts +16 -16
  423. package/server/modules/websocket/services/websocket-writer.service.ts +38 -38
  424. package/server/modules/websocket/tests/chat-attachment-filter.test.ts +59 -59
  425. package/server/modules/websocket/tests/chat-run-registry.test.ts +282 -282
  426. package/server/modules/websocket/tests/shell-websocket.service.test.ts +100 -100
  427. package/server/modules/websocket/tests/websocket-heartbeat.service.test.ts +78 -78
  428. package/server/modules/worktrees/index.ts +2 -2
  429. package/server/modules/worktrees/services/worktree-create-and-open.service.ts +53 -53
  430. package/server/modules/worktrees/services/worktree-create.service.ts +104 -104
  431. package/server/modules/worktrees/services/worktree-git.service.ts +207 -207
  432. package/server/modules/worktrees/services/worktree-list.service.ts +143 -143
  433. package/server/modules/worktrees/services/worktree-merge.service.ts +157 -157
  434. package/server/modules/worktrees/services/worktree-open.service.ts +85 -85
  435. package/server/modules/worktrees/services/worktree-remove.service.ts +88 -88
  436. package/server/modules/worktrees/tests/worktree-create-and-open.service.test.ts +68 -68
  437. package/server/modules/worktrees/tests/worktree-create.service.test.ts +142 -142
  438. package/server/modules/worktrees/tests/worktree-git.service.test.ts +84 -84
  439. package/server/modules/worktrees/tests/worktree-list.service.test.ts +45 -45
  440. package/server/modules/worktrees/tests/worktree-merge.service.test.ts +213 -213
  441. package/server/modules/worktrees/tests/worktree-open.service.test.ts +122 -122
  442. package/server/modules/worktrees/tests/worktree-remove.service.test.ts +227 -227
  443. package/server/modules/worktrees/tests/worktrees.routes.test.ts +199 -199
  444. package/server/modules/worktrees/worktrees.module.ts +113 -113
  445. package/server/modules/worktrees/worktrees.routes.ts +116 -116
  446. package/server/shared/claude-cli-path.ts +139 -139
  447. package/server/shared/frontmatter.ts +18 -18
  448. package/server/shared/image-attachments.ts +435 -435
  449. package/server/shared/interfaces.ts +179 -179
  450. package/server/shared/tests/claude-cli-path.test.ts +61 -61
  451. package/server/shared/tests/image-attachments.test.ts +353 -353
  452. package/server/shared/tests/slice-tail-page.test.ts +42 -42
  453. package/server/shared/types.ts +1228 -1228
  454. package/server/shared/utils.ts +1161 -1161
  455. package/server/tsconfig.json +40 -40
  456. package/shared/networkHosts.js +22 -22
  457. package/dist/assets/FileTree-N2IkkHlv.js +0 -127
  458. package/dist/assets/GitPanel-DZCeuFZ2.js +0 -29
  459. package/dist/assets/PluginTabContent-Bnuf-fb8.js +0 -1
  460. package/dist/assets/Shell-BfFnMZ-f.js +0 -81
  461. package/dist/assets/Shell-qxJ8_QYu.css +0 -32
  462. package/dist/assets/StandaloneShell-QmyYwNAl.js +0 -1
  463. package/dist/assets/TaskMasterPanel-fMsmvN9L.js +0 -32
  464. package/dist/assets/abnfDiagram-N423BO3Z-DjPU7HLs.js +0 -1
  465. package/dist/assets/arc-Pdq6Tvr3.js +0 -1
  466. package/dist/assets/architectureDiagram-T3A2C74G-D0JnT0Vh.js +0 -36
  467. package/dist/assets/c4Diagram-5PPSVZJV-MpqlPGFi.js +0 -10
  468. package/dist/assets/channel-Bm0ZLE4z.js +0 -1
  469. package/dist/assets/chunk-5RXB4S5H-B4UQ8snD.js +0 -231
  470. package/dist/assets/chunk-GF5L2VYU-DkEPedJP.js +0 -206
  471. package/dist/assets/classDiagram-JCYQIIEL-DqEOcNxw.js +0 -1
  472. package/dist/assets/classDiagram-v2-OCEON4UE-DqEOcNxw.js +0 -1
  473. package/dist/assets/code-xml-VK1YfShP.js +0 -6
  474. package/dist/assets/cose-bilkent-JH36ORCC-DrVTo1Nh.js +0 -1
  475. package/dist/assets/cynefinDiagram-MW4NZA55-CCxBjw9E.js +0 -62
  476. package/dist/assets/cytoscape.esm-C10L9Icf.js +0 -331
  477. package/dist/assets/dagre-VZM6K2ZE-C_GvE4lu.js +0 -4
  478. package/dist/assets/diagram-LBJQPF4R-hfKcrrxe.js +0 -24
  479. package/dist/assets/diagram-Q27KOJAE-C1semJfK.js +0 -24
  480. package/dist/assets/diagram-UB23O5K3-57hvXQXO.js +0 -41
  481. package/dist/assets/ebnfDiagram-BXEA7PRR-9KIAlAVw.js +0 -1
  482. package/dist/assets/erDiagram-JOGREHBK-B7OzJ767.js +0 -85
  483. package/dist/assets/ganttDiagram-PKOTCBZU-CbMNWWQu.js +0 -292
  484. package/dist/assets/gitGraphDiagram-DS77QQ5N-I_vZ5waO.js +0 -106
  485. package/dist/assets/graph-Cx-EqisW.js +0 -1
  486. package/dist/assets/index-DFnVoqpx.js +0 -1174
  487. package/dist/assets/index-DlSeAkw_.js +0 -11
  488. package/dist/assets/index-ZHwIojzi.js +0 -1
  489. package/dist/assets/index-t1w8KNxn.css +0 -1
  490. package/dist/assets/infoDiagram-6WML65LV-Dh20Tsbq.js +0 -2
  491. package/dist/assets/ishikawaDiagram-WSZJBQD7-DH2Sm3ko.js +0 -70
  492. package/dist/assets/journeyDiagram-NVQOT4AX-BNFQqlVu.js +0 -139
  493. package/dist/assets/map-CV9uif0g.js +0 -1
  494. package/dist/assets/mermaid.core-BYRQSshi.js +0 -312
  495. package/dist/assets/pegDiagram-VL7TDLO6-CNYpECr8.js +0 -1
  496. package/dist/assets/quadrantDiagram-CIZ2JOQS-BXVVQsa6.js +0 -7
  497. package/dist/assets/railroadDiagram-AXF67PYL-JTroIW8F.js +0 -1
  498. package/dist/assets/requirementDiagram-LRYGKXZP-C1Z_inLz.js +0 -84
  499. package/dist/assets/sankeyDiagram-W5VNT64P-DCJgKFUk.js +0 -40
  500. package/dist/assets/sequenceDiagram-SI44F4Z6-D8Wrx5Vc.js +0 -162
  501. package/dist/assets/sizeCapture-X5ZJPWSS-CXqD68vD.js +0 -1
  502. package/dist/assets/stateDiagram-OKZ733FA-CF0Ekqjo.js +0 -1
  503. package/dist/assets/stateDiagram-v2-UEYNNEHI-DARLpEFJ.js +0 -1
  504. package/dist/assets/swimlanes-SLNWSIFB-DVIax_k4.js +0 -2
  505. package/dist/assets/swimlanesDiagram-ULZ7WXOC-CrgDgaY8.js +0 -8
  506. package/dist/assets/timeline-definition-Z64GVDOM-DSqk3ApG.js +0 -120
  507. package/dist/assets/vendor-react-whEHfigN.js +0 -59
  508. package/dist/assets/vennDiagram-T6HMQDX7-DNbTqyG5.js +0 -34
  509. package/dist/assets/xychartDiagram-ELKLHX3M-XsVZphHr.js +0 -7
  510. package/dist/manifest.json +0 -61
@@ -1,298 +1,298 @@
1
- import type { IncomingMessage } from 'node:http';
2
- import type { Readable } from 'node:stream';
3
-
4
- //----------------- HTTP RESPONSE SHAPES ------------
5
- /**
6
- * Canonical success envelope used by backend APIs that return a structured payload.
7
- *
8
- * Use this for route handlers that need a stable `success/data` shape so frontend
9
- * consumers can parse responses consistently across endpoints.
10
- */
11
- export type ApiSuccessShape<TData = unknown> = {
12
- success: true;
13
- data: TData;
14
- };
15
-
16
- /**
17
- * Generic plain-object record used when parsing loosely typed JSON payloads.
18
- *
19
- * Use this only after runtime shape checks, not as a replacement for validated
20
- * domain models.
21
- */
22
- export type AnyRecord = Record<string, any>;
23
-
24
- // ---------------------------
25
- //----------------- WEBSOCKET TRANSPORT TYPES ------------
26
- /**
27
- * Minimal websocket client contract used by backend broadcaster services.
28
- *
29
- * Any transport object added to `connectedClients` must implement these two
30
- * members so shared services can safely send JSON strings and check whether the
31
- * socket is still open before broadcasting.
32
- */
33
- export type RealtimeClientConnection = {
34
- readyState: number;
35
- send(data: string): void;
36
- };
37
-
38
- /**
39
- * Authenticated user payload attached to websocket upgrade requests.
40
- *
41
- * Platform and OSS auth flows currently use either `id` or `userId`; both are
42
- * represented here so websocket handlers can resolve a stable writer user id.
43
- */
44
- export type AuthenticatedWebSocketUser = {
45
- id?: string | number;
46
- userId?: string | number;
47
- username?: string;
48
- [key: string]: unknown;
49
- };
50
-
51
- /**
52
- * HTTP upgrade request shape after websocket authentication succeeds.
53
- *
54
- * `verifyClient` populates `request.user` with the authenticated payload, and
55
- * downstream websocket handlers rely on this extended request type.
56
- */
57
- export type AuthenticatedWebSocketRequest = IncomingMessage & {
58
- user?: AuthenticatedWebSocketUser;
59
- };
60
-
61
- // ---------------------------
62
- //----------------- PROVIDER MESSAGE MODEL ------------
63
- /**
64
- * Providers supported by the unified server runtime.
65
- *
66
- * Use this as the source of truth whenever a function or payload needs to identify
67
- * a specific LLM integration.
68
- */
69
- export type LLMProvider = 'claude' | 'codex' | 'cursor' | 'opencode';
70
-
71
- /**
72
- * One selectable model row in a provider model catalog.
73
- */
74
- export type ProviderModelOption = {
75
- value: string;
76
- label: string;
77
- description?: string;
78
- /** Stable SQLite row id used only by model-management actions. */
79
- recordId?: number;
80
- /** True for user-created rows; false for immutable CloudCLI defaults. */
81
- isCustom?: boolean;
82
- effort?: {
83
- default?: string;
84
- values: {
85
- value: string;
86
- description?: string;
87
- }[];
88
- };
89
- };
90
-
91
- /**
92
- * Provider model catalog returned by `GET /api/providers/:provider/models`.
93
- */
94
- export type ProviderModelsDefinition = {
95
- OPTIONS: ProviderModelOption[];
96
- DEFAULT: string;
97
- };
98
-
99
- /**
100
- * One persisted custom-model row in the provider model library.
101
- *
102
- * Provider modules use this shape at the database boundary. Predefined models
103
- * never use this type because they remain source-controlled in provider
104
- * adapters. `modelId` is sent to the provider runtime, while `model` is the
105
- * user-supplied display name shown in pickers.
106
- */
107
- export type CustomProviderModelRecord = {
108
- recordId: number;
109
- provider: LLMProvider;
110
- modelId: string;
111
- model: string;
112
- sortOrder: number;
113
- };
114
-
115
- /**
116
- * User-editable values accepted when creating or changing a custom model.
117
- *
118
- * `id` must be the exact provider-facing model identifier and cannot contain
119
- * whitespace. `model` is a concise display name. The provider is supplied by
120
- * the route path so a row can never be moved across providers accidentally.
121
- */
122
- export type CustomProviderModelInput = {
123
- id: string;
124
- model: string;
125
- };
126
-
127
- // ---------------------------
128
- //----------------- PROVIDER ACTIVE MODEL TYPES ------------
129
- /**
130
- * Provider-neutral result for the model that is actively driving a session or
131
- * provider runtime at the time of lookup.
132
- *
133
- * `model` must always be populated. Provider adapters should use the
134
- * provider-specific lookup method requested by the caller, and only fall back
135
- * to the provider catalog `DEFAULT` value when the active model cannot be read.
136
- */
137
- export type ProviderCurrentActiveModel = {
138
- model: string;
139
- };
140
-
141
- /**
142
- * Where a resolved session model came from.
143
- *
144
- * `session` means the app has recorded a model for this session (the user
145
- * picked one, or the session has been sent on at least once) and that value is
146
- * authoritative. `provider` means the session predates any app-recorded model
147
- * and the value was read back from the provider's own session state — the case
148
- * for sessions started directly in a provider CLI. `default` means neither was
149
- * available and the catalog default is standing in.
150
- *
151
- * Routes surface this so the frontend can tell a real selection apart from a
152
- * placeholder without re-deriving the precedence chain.
153
- */
154
- export type ProviderSessionModelSource = 'session' | 'provider' | 'default';
155
-
156
- /**
157
- * The model one session runs with, its persisted reasoning effort when one has
158
- * been recorded, and where the model answer came from.
159
- *
160
- * Returned by `providerModelsService.resolveSessionModel` and used by the
161
- * `/models`, `/cost` and `/status` commands, the active-model route, and the
162
- * composer's model picker so every surface agrees on one answer.
163
- */
164
- export type ProviderSessionModel = {
165
- provider: LLMProvider;
166
- sessionId: string | null;
167
- model: string;
168
- /** NULL means this session has not recorded an effort choice yet. */
169
- effort: string | null;
170
- source: ProviderSessionModelSource;
171
- };
172
-
173
- /**
174
- * Message/event variants emitted by provider adapters and normalized transports.
175
- *
176
- * Keep this union in sync with event kinds produced by provider session adapters.
177
- */
178
- export type MessageKind =
179
- | 'text'
180
- | 'tool_use'
181
- | 'tool_result'
182
- | 'thinking'
183
- | 'stream_delta'
184
- | 'stream_end'
185
- | 'error'
186
- | 'complete'
187
- | 'status'
188
- | 'permission_request'
189
- | 'permission_cancelled'
190
- | 'session_created'
191
- | 'interactive_prompt'
192
- | 'task_notification';
193
-
194
- /**
195
- * Event kinds added by the chat gateway layer on top of provider message kinds.
196
- *
197
- * These are app-level realtime events (subscription acks, sidebar deltas,
198
- * project loading progress, protocol failures) that are not produced by any
199
- * provider adapter. Together with `MessageKind` they form the complete set of
200
- * `kind` values a websocket client can receive, so the frontend only ever
201
- * needs one kind-based switch.
202
- */
203
- export type GatewayEventKind =
204
- | 'chat_subscribed'
205
- | 'session_upserted'
206
- | 'loading_progress'
207
- | 'protocol_error';
208
-
209
- /**
210
- * Complete set of `kind` values emitted to websocket clients.
211
- *
212
- * Every server-to-client websocket frame carries a `kind` from this union.
213
- * Provider runtimes emit `MessageKind` values; gateway services emit
214
- * `GatewayEventKind` values.
215
- */
216
- export type ServerEventKind = MessageKind | GatewayEventKind;
217
-
218
- /**
219
- * Provider-neutral message envelope used in REST responses and realtime channels.
220
- *
221
- * Every provider-specific message must be converted into this shape before being
222
- * emitted outside provider-specific modules.
223
- */
224
- export type NormalizedMessage = {
225
- id: string;
226
- sessionId: string;
227
- timestamp: string;
228
- provider: LLMProvider;
229
- kind: MessageKind;
230
- /**
231
- * Monotonic per-run sequence number assigned by the chat run registry when a
232
- * live event is forwarded to the websocket. History messages loaded over
233
- * REST do not carry it. Clients use it with `chat.subscribe` to replay only
234
- * the live events they missed across websocket reconnects.
235
- */
236
- seq?: number;
237
- role?: 'user' | 'assistant';
238
- content?: string;
239
- /**
240
- * Optional display-oriented metadata used by providers that need to expose
241
- * richer transcript artifacts without introducing a brand-new message kind.
242
- *
243
- * Current Claude usage:
244
- * - local slash commands expose parsed command fields
245
- * - compact summaries are flagged so the UI can treat them differently later
246
- */
247
- displayText?: string;
248
- commandName?: string;
249
- commandMessage?: string;
250
- commandArgs?: string;
251
- isLocalCommand?: boolean;
252
- isLocalCommandStdout?: boolean;
253
- isCompactSummary?: boolean;
254
- images?: unknown;
255
- /** Non-image files attached to a user turn after provider history normalization. */
256
- files?: unknown;
257
- toolName?: string;
258
- toolInput?: unknown;
259
- toolId?: string;
260
- toolResult?: {
261
- content?: string;
262
- isError?: boolean;
263
- toolUseResult?: unknown;
264
- };
265
- isError?: boolean;
266
- text?: string;
267
- tokens?: number;
268
- canInterrupt?: boolean;
269
- requestId?: string;
270
- input?: unknown;
271
- context?: unknown;
272
- reason?: string;
273
- newSessionId?: string;
274
- status?: string;
275
- summary?: string;
276
- tokenBudget?: unknown;
277
- subagentTools?: unknown;
278
- toolUseResult?: unknown;
279
- sequence?: number;
280
- rowid?: number;
281
- [key: string]: unknown;
282
- };
283
-
284
- /**
285
- * Output gateway shared by WebSocket and SSE provider runs.
286
- *
287
- * Runtime adapters only depend on this structural surface, which keeps them
288
- * independent from the transport that ultimately delivers normalized events.
289
- */
1
+ import type { IncomingMessage } from 'node:http';
2
+ import type { Readable } from 'node:stream';
3
+
4
+ //----------------- HTTP RESPONSE SHAPES ------------
5
+ /**
6
+ * Canonical success envelope used by backend APIs that return a structured payload.
7
+ *
8
+ * Use this for route handlers that need a stable `success/data` shape so frontend
9
+ * consumers can parse responses consistently across endpoints.
10
+ */
11
+ export type ApiSuccessShape<TData = unknown> = {
12
+ success: true;
13
+ data: TData;
14
+ };
15
+
16
+ /**
17
+ * Generic plain-object record used when parsing loosely typed JSON payloads.
18
+ *
19
+ * Use this only after runtime shape checks, not as a replacement for validated
20
+ * domain models.
21
+ */
22
+ export type AnyRecord = Record<string, any>;
23
+
24
+ // ---------------------------
25
+ //----------------- WEBSOCKET TRANSPORT TYPES ------------
26
+ /**
27
+ * Minimal websocket client contract used by backend broadcaster services.
28
+ *
29
+ * Any transport object added to `connectedClients` must implement these two
30
+ * members so shared services can safely send JSON strings and check whether the
31
+ * socket is still open before broadcasting.
32
+ */
33
+ export type RealtimeClientConnection = {
34
+ readyState: number;
35
+ send(data: string): void;
36
+ };
37
+
38
+ /**
39
+ * Authenticated user payload attached to websocket upgrade requests.
40
+ *
41
+ * Platform and OSS auth flows currently use either `id` or `userId`; both are
42
+ * represented here so websocket handlers can resolve a stable writer user id.
43
+ */
44
+ export type AuthenticatedWebSocketUser = {
45
+ id?: string | number;
46
+ userId?: string | number;
47
+ username?: string;
48
+ [key: string]: unknown;
49
+ };
50
+
51
+ /**
52
+ * HTTP upgrade request shape after websocket authentication succeeds.
53
+ *
54
+ * `verifyClient` populates `request.user` with the authenticated payload, and
55
+ * downstream websocket handlers rely on this extended request type.
56
+ */
57
+ export type AuthenticatedWebSocketRequest = IncomingMessage & {
58
+ user?: AuthenticatedWebSocketUser;
59
+ };
60
+
61
+ // ---------------------------
62
+ //----------------- PROVIDER MESSAGE MODEL ------------
63
+ /**
64
+ * Providers supported by the unified server runtime.
65
+ *
66
+ * Use this as the source of truth whenever a function or payload needs to identify
67
+ * a specific LLM integration.
68
+ */
69
+ export type LLMProvider = 'claude' | 'codex' | 'cursor' | 'opencode';
70
+
71
+ /**
72
+ * One selectable model row in a provider model catalog.
73
+ */
74
+ export type ProviderModelOption = {
75
+ value: string;
76
+ label: string;
77
+ description?: string;
78
+ /** Stable SQLite row id used only by model-management actions. */
79
+ recordId?: number;
80
+ /** True for user-created rows; false for immutable WindCli defaults. */
81
+ isCustom?: boolean;
82
+ effort?: {
83
+ default?: string;
84
+ values: {
85
+ value: string;
86
+ description?: string;
87
+ }[];
88
+ };
89
+ };
90
+
91
+ /**
92
+ * Provider model catalog returned by `GET /api/providers/:provider/models`.
93
+ */
94
+ export type ProviderModelsDefinition = {
95
+ OPTIONS: ProviderModelOption[];
96
+ DEFAULT: string;
97
+ };
98
+
99
+ /**
100
+ * One persisted custom-model row in the provider model library.
101
+ *
102
+ * Provider modules use this shape at the database boundary. Predefined models
103
+ * never use this type because they remain source-controlled in provider
104
+ * adapters. `modelId` is sent to the provider runtime, while `model` is the
105
+ * user-supplied display name shown in pickers.
106
+ */
107
+ export type CustomProviderModelRecord = {
108
+ recordId: number;
109
+ provider: LLMProvider;
110
+ modelId: string;
111
+ model: string;
112
+ sortOrder: number;
113
+ };
114
+
115
+ /**
116
+ * User-editable values accepted when creating or changing a custom model.
117
+ *
118
+ * `id` must be the exact provider-facing model identifier and cannot contain
119
+ * whitespace. `model` is a concise display name. The provider is supplied by
120
+ * the route path so a row can never be moved across providers accidentally.
121
+ */
122
+ export type CustomProviderModelInput = {
123
+ id: string;
124
+ model: string;
125
+ };
126
+
127
+ // ---------------------------
128
+ //----------------- PROVIDER ACTIVE MODEL TYPES ------------
129
+ /**
130
+ * Provider-neutral result for the model that is actively driving a session or
131
+ * provider runtime at the time of lookup.
132
+ *
133
+ * `model` must always be populated. Provider adapters should use the
134
+ * provider-specific lookup method requested by the caller, and only fall back
135
+ * to the provider catalog `DEFAULT` value when the active model cannot be read.
136
+ */
137
+ export type ProviderCurrentActiveModel = {
138
+ model: string;
139
+ };
140
+
141
+ /**
142
+ * Where a resolved session model came from.
143
+ *
144
+ * `session` means the app has recorded a model for this session (the user
145
+ * picked one, or the session has been sent on at least once) and that value is
146
+ * authoritative. `provider` means the session predates any app-recorded model
147
+ * and the value was read back from the provider's own session state — the case
148
+ * for sessions started directly in a provider CLI. `default` means neither was
149
+ * available and the catalog default is standing in.
150
+ *
151
+ * Routes surface this so the frontend can tell a real selection apart from a
152
+ * placeholder without re-deriving the precedence chain.
153
+ */
154
+ export type ProviderSessionModelSource = 'session' | 'provider' | 'default';
155
+
156
+ /**
157
+ * The model one session runs with, its persisted reasoning effort when one has
158
+ * been recorded, and where the model answer came from.
159
+ *
160
+ * Returned by `providerModelsService.resolveSessionModel` and used by the
161
+ * `/models`, `/cost` and `/status` commands, the active-model route, and the
162
+ * composer's model picker so every surface agrees on one answer.
163
+ */
164
+ export type ProviderSessionModel = {
165
+ provider: LLMProvider;
166
+ sessionId: string | null;
167
+ model: string;
168
+ /** NULL means this session has not recorded an effort choice yet. */
169
+ effort: string | null;
170
+ source: ProviderSessionModelSource;
171
+ };
172
+
173
+ /**
174
+ * Message/event variants emitted by provider adapters and normalized transports.
175
+ *
176
+ * Keep this union in sync with event kinds produced by provider session adapters.
177
+ */
178
+ export type MessageKind =
179
+ | 'text'
180
+ | 'tool_use'
181
+ | 'tool_result'
182
+ | 'thinking'
183
+ | 'stream_delta'
184
+ | 'stream_end'
185
+ | 'error'
186
+ | 'complete'
187
+ | 'status'
188
+ | 'permission_request'
189
+ | 'permission_cancelled'
190
+ | 'session_created'
191
+ | 'interactive_prompt'
192
+ | 'task_notification';
193
+
194
+ /**
195
+ * Event kinds added by the chat gateway layer on top of provider message kinds.
196
+ *
197
+ * These are app-level realtime events (subscription acks, sidebar deltas,
198
+ * project loading progress, protocol failures) that are not produced by any
199
+ * provider adapter. Together with `MessageKind` they form the complete set of
200
+ * `kind` values a websocket client can receive, so the frontend only ever
201
+ * needs one kind-based switch.
202
+ */
203
+ export type GatewayEventKind =
204
+ | 'chat_subscribed'
205
+ | 'session_upserted'
206
+ | 'loading_progress'
207
+ | 'protocol_error';
208
+
209
+ /**
210
+ * Complete set of `kind` values emitted to websocket clients.
211
+ *
212
+ * Every server-to-client websocket frame carries a `kind` from this union.
213
+ * Provider runtimes emit `MessageKind` values; gateway services emit
214
+ * `GatewayEventKind` values.
215
+ */
216
+ export type ServerEventKind = MessageKind | GatewayEventKind;
217
+
218
+ /**
219
+ * Provider-neutral message envelope used in REST responses and realtime channels.
220
+ *
221
+ * Every provider-specific message must be converted into this shape before being
222
+ * emitted outside provider-specific modules.
223
+ */
224
+ export type NormalizedMessage = {
225
+ id: string;
226
+ sessionId: string;
227
+ timestamp: string;
228
+ provider: LLMProvider;
229
+ kind: MessageKind;
230
+ /**
231
+ * Monotonic per-run sequence number assigned by the chat run registry when a
232
+ * live event is forwarded to the websocket. History messages loaded over
233
+ * REST do not carry it. Clients use it with `chat.subscribe` to replay only
234
+ * the live events they missed across websocket reconnects.
235
+ */
236
+ seq?: number;
237
+ role?: 'user' | 'assistant';
238
+ content?: string;
239
+ /**
240
+ * Optional display-oriented metadata used by providers that need to expose
241
+ * richer transcript artifacts without introducing a brand-new message kind.
242
+ *
243
+ * Current Claude usage:
244
+ * - local slash commands expose parsed command fields
245
+ * - compact summaries are flagged so the UI can treat them differently later
246
+ */
247
+ displayText?: string;
248
+ commandName?: string;
249
+ commandMessage?: string;
250
+ commandArgs?: string;
251
+ isLocalCommand?: boolean;
252
+ isLocalCommandStdout?: boolean;
253
+ isCompactSummary?: boolean;
254
+ images?: unknown;
255
+ /** Non-image files attached to a user turn after provider history normalization. */
256
+ files?: unknown;
257
+ toolName?: string;
258
+ toolInput?: unknown;
259
+ toolId?: string;
260
+ toolResult?: {
261
+ content?: string;
262
+ isError?: boolean;
263
+ toolUseResult?: unknown;
264
+ };
265
+ isError?: boolean;
266
+ text?: string;
267
+ tokens?: number;
268
+ canInterrupt?: boolean;
269
+ requestId?: string;
270
+ input?: unknown;
271
+ context?: unknown;
272
+ reason?: string;
273
+ newSessionId?: string;
274
+ status?: string;
275
+ summary?: string;
276
+ tokenBudget?: unknown;
277
+ subagentTools?: unknown;
278
+ toolUseResult?: unknown;
279
+ sequence?: number;
280
+ rowid?: number;
281
+ [key: string]: unknown;
282
+ };
283
+
284
+ /**
285
+ * Output gateway shared by WebSocket and SSE provider runs.
286
+ *
287
+ * Runtime adapters only depend on this structural surface, which keeps them
288
+ * independent from the transport that ultimately delivers normalized events.
289
+ */
290
290
  export type ProviderRuntimeWriter = {
291
- send(data: unknown): void;
292
- setSessionId?(sessionId: string): void;
293
- userId?: string | number | null;
294
- isWebSocketWriter?: boolean;
295
- isSSEStreamWriter?: boolean;
291
+ send(data: unknown): void;
292
+ setSessionId?(sessionId: string): void;
293
+ userId?: string | number | null;
294
+ isWebSocketWriter?: boolean;
295
+ isSSEStreamWriter?: boolean;
296
296
  };
297
297
 
298
298
  //----------------- CODEX APP-SERVER PROTOCOL EVENTS ------------
@@ -302,7 +302,7 @@ export type ProviderRuntimeWriter = {
302
302
  *
303
303
  * The Codex JSON-RPC client emits this shape to its runtime adapter. Method and
304
304
  * parameter validation stays in the adapter because the protocol can add new
305
- * notification variants independently of CloudCLI releases.
305
+ * notification variants independently of WindCli releases.
306
306
  */
307
307
  export type CodexAppServerNotification = {
308
308
  method: string;
@@ -313,7 +313,7 @@ export type CodexAppServerNotification = {
313
313
  * Server-initiated Codex JSON-RPC request that may require a UI response.
314
314
  *
315
315
  * The Codex client forwards approval-capable requests to the runtime while it
316
- * rejects request methods that CloudCLI does not implement.
316
+ * rejects request methods that WindCli does not implement.
317
317
  */
318
318
  export type CodexAppServerRequest = {
319
319
  id: number;
@@ -334,935 +334,935 @@ export type CodexAppServerExit = {
334
334
  // ---------------------------
335
335
 
336
336
  export type ProviderPermissionDecision = {
337
- allow: boolean;
338
- updatedInput?: unknown;
339
- message?: string;
340
- rememberEntry?: unknown;
341
- };
342
-
343
- export type ProviderRuntimePermissionGateway = {
344
- resolve(requestId: string, decision: ProviderPermissionDecision): void;
345
- listPending(sessionId: string): unknown[];
346
- };
347
-
348
- /**
349
- * Provider-scoped application capabilities supplied to a runtime for one run.
350
- *
351
- * Keeping these lookups outside concrete SDK/CLI adapters prevents the
352
- * adapters from importing services that resolve back through providerRegistry.
353
- */
354
- export type ProviderRuntimeContext = {
355
- resolveProviderSessionId(sessionId: string | null | undefined): string | null;
356
- resolveResumeModel(
357
- sessionId: string | undefined,
358
- requestedModel?: string | null,
359
- ): Promise<string | undefined>;
360
- getProviderModels(): Promise<ProviderModelsDefinition>;
361
- normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
362
- isProviderInstalled(): Promise<boolean>;
363
- };
364
-
365
- export type ProviderRunFunction = (
366
- command: string,
367
- options: AnyRecord,
368
- writer: ProviderRuntimeWriter,
369
- ) => Promise<unknown>;
370
-
371
- /**
372
- * Shared options used to fetch historical provider messages.
373
- *
374
- * Consumers should pass provider-specific lookup hints (`projectPath`) only
375
- * when the selected provider requires them.
376
- *
377
- * `providerSessionId` is the provider-native session id from the sessions
378
- * index (transcript file name / provider database key). Provider adapters
379
- * must use it — never the app-facing session id they were called with — when
380
- * matching transcript rows on disk, because app-created sessions use an
381
- * app-allocated id that the provider has never seen.
382
- */
383
- export type FetchHistoryOptions = {
384
- projectPath?: string;
385
- limit?: number | null;
386
- offset?: number;
387
- providerSessionId?: string;
388
- };
389
-
390
- /**
391
- * Standardized response payload returned from provider history readers.
392
- *
393
- * Use this as the contract for APIs that return paginated conversation history.
394
- */
395
- export type FetchHistoryResult = {
396
- messages: NormalizedMessage[];
397
- total: number;
398
- hasMore: boolean;
399
- offset: number;
400
- limit: number | null;
401
- tokenUsage?: unknown;
402
- };
403
-
404
- // ---------------------------
405
- //----------------- PROVIDER SKILL TYPES ------------
406
- /**
407
- * Scope where a provider skill definition was discovered.
408
- *
409
- * Provider skill adapters should use this to describe the origin of each
410
- * skill markdown file without leaking provider-specific folder names into route
411
- * contracts. `repo` is used for Codex repository lookup locations, while
412
- * `project` is used for providers that treat workspace-local skills as project
413
- * scoped.
414
- */
415
- export type ProviderSkillScope = 'user' | 'project' | 'plugin' | 'repo' | 'admin' | 'system';
416
-
417
- /**
418
- * Shared input accepted by provider skill listing operations.
419
- *
420
- * Routes pass `workspacePath` when a caller wants project/repository skills for
421
- * a specific folder. Providers should fall back to the backend process cwd when
422
- * this option is omitted.
423
- */
424
- export type ProviderSkillListOptions = {
425
- workspacePath?: string;
426
- };
427
-
428
- /**
429
- * One supporting file bundled with an uploaded provider skill.
430
- *
431
- * `relativePath` is resolved below the installed skill directory and must never
432
- * be absolute or contain traversal segments. Text files may use `utf8`; binary
433
- * scripts and assets should use `base64` so JSON transport does not corrupt
434
- * their bytes.
435
- */
436
- export type ProviderSkillCreateFile = {
437
- relativePath: string;
438
- content: string;
439
- encoding: 'utf8' | 'base64';
440
- };
441
-
442
- /**
443
- * One skill markdown payload submitted for provider-managed installation.
444
- *
445
- * `content` is the raw markdown body that will be written to `SKILL.md`.
446
- * `directoryName` lets callers control the target folder name explicitly when
447
- * they want stable filesystem paths that differ from the markdown front matter
448
- * `name` field. `fileName` is optional upload metadata used only as a final
449
- * fallback when no directory name or front matter name is present. `files`
450
- * carries scripts, references, and other files from a complete skill folder.
451
- */
452
- export type ProviderSkillCreateEntry = {
453
- content: string;
454
- directoryName?: string;
455
- fileName?: string;
456
- files?: ProviderSkillCreateFile[];
457
- };
458
-
459
- /**
460
- * Shared input accepted by provider skill creation operations.
461
- *
462
- * The service layer batches multiple skill definitions in one request. Each
463
- * entry can contain only markdown or a complete skill folder.
464
- */
465
- export type ProviderSkillCreateInput = {
466
- entries: ProviderSkillCreateEntry[];
467
- };
468
-
469
- export type ProviderSkillRemoveInput = {
470
- directoryName: string;
471
- };
472
-
473
- /**
474
- * Normalized skill record returned by provider skill adapters.
475
- *
476
- * The `command` value is the exact invocation text the selected provider expects
477
- * for this skill. Claude plugin skills use a namespaced command such as
478
- * `/plugin-name:skill-name`, while Codex skills use the `$skill-name` form.
479
- * `sourcePath` points to the skill markdown file that produced the record so
480
- * callers can distinguish duplicate skill names across scopes.
481
- */
482
- export type ProviderSkill = {
483
- provider: LLMProvider;
484
- name: string;
485
- description: string;
486
- command: string;
487
- scope: ProviderSkillScope;
488
- sourcePath: string;
489
- pluginName?: string;
490
- pluginId?: string;
491
- };
492
-
493
- /**
494
- * Internal source descriptor consumed by shared provider skill discovery logic.
495
- *
496
- * Concrete provider adapters build these records from their native lookup rules.
497
- * The shared skills provider then scans `rootDir` for child skill markdown files
498
- * and uses `commandForSkill` or `commandPrefix` to produce the provider-specific
499
- * invocation command. Set `recursive` only when a provider stores skills under
500
- * arbitrary nested folders below the source root.
501
- */
502
- export type ProviderSkillSource = {
503
- scope: ProviderSkillScope;
504
- rootDir: string;
505
- recursive?: boolean;
506
- commandPrefix?: '/' | '$';
507
- commandForSkill?: (skillName: string) => string;
508
- pluginName?: string;
509
- pluginId?: string;
510
- };
511
-
512
- // ---------------------------
513
- //----------------- SHARED ERROR TYPES ------------
514
- /**
515
- * Optional metadata used when constructing application-level errors.
516
- *
517
- * `statusCode` should reflect the HTTP response status, while `code` identifies
518
- * the stable machine-readable error category.
519
- */
520
- export type AppErrorOptions = {
521
- code?: string;
522
- statusCode?: number;
523
- details?: unknown;
524
- };
525
-
526
- // ---------------------------
527
- //----------------- MCP TYPES ------------
528
- /**
529
- * Scope where an MCP server definition is stored and resolved.
530
- *
531
- * `user` is global for a user account, `local` is provider-local, and `project`
532
- * is tied to a specific project path.
533
- */
534
- export type McpScope = 'user' | 'local' | 'project';
535
-
536
- /**
537
- * Transport protocol used by an MCP server definition.
538
- */
539
- export type McpTransport = 'stdio' | 'http' | 'sse';
540
-
541
- /**
542
- * Normalized MCP server model exposed to frontend and route handlers.
543
- *
544
- * Provider adapters should map provider-native config to this structure before
545
- * returning results.
546
- */
547
- export type ProviderMcpServer = {
548
- provider: LLMProvider;
549
- name: string;
550
- scope: McpScope;
551
- transport: McpTransport;
552
- command?: string;
553
- args?: string[];
554
- env?: Record<string, string>;
555
- cwd?: string;
556
- url?: string;
557
- headers?: Record<string, string>;
558
- envVars?: string[];
559
- bearerTokenEnvVar?: string;
560
- envHttpHeaders?: Record<string, string>;
561
- };
562
-
563
- /**
564
- * Payload for create/update MCP server operations.
565
- *
566
- * Routes and services should accept this type, validate it, and then persist it
567
- * through provider-specific MCP repositories.
568
- */
569
- export type UpsertProviderMcpServerInput = {
570
- name: string;
571
- scope?: McpScope;
572
- transport: McpTransport;
573
- workspacePath?: string;
574
- command?: string;
575
- args?: string[];
576
- env?: Record<string, string>;
577
- cwd?: string;
578
- url?: string;
579
- headers?: Record<string, string>;
580
- envVars?: string[];
581
- bearerTokenEnvVar?: string;
582
- envHttpHeaders?: Record<string, string>;
583
- };
584
-
585
- // ---------------------------
586
- //----------------- PROVIDER AUTH TYPES ------------
587
- /**
588
- * Authentication status result returned by provider health checks.
589
- *
590
- * This shape is consumed by settings/status endpoints to report installation and
591
- * credential state for each provider.
592
- */
593
- export type ProviderAuthStatus = {
594
- installed: boolean;
595
- provider: LLMProvider;
596
- authenticated: boolean;
597
- email: string | null;
598
- method: string | null;
599
- error?: string;
600
- };
601
-
602
- // ---------------------------
603
- //----------------- SHARED DATABASE CREDENTIAL TYPES ------------
604
- /**
605
- * Safe credential view returned by credential listing APIs.
606
- *
607
- * This intentionally excludes the raw credential secret while still exposing
608
- * metadata needed for UI rendering and management operations.
609
- */
610
- export type CredentialPublicRow = {
611
- id: number;
612
- credential_name: string;
613
- credential_type: string;
614
- description: string | null;
615
- created_at: string;
616
- is_active: number;
617
- };
618
-
619
- /**
620
- * Result returned after creating a credential record.
621
- *
622
- * Use this return shape when callers need the created id and display metadata,
623
- * but must never receive the stored secret value.
624
- */
625
- export type CreateCredentialResult = {
626
- id: number | bigint;
627
- credentialName: string;
628
- credentialType: string;
629
- };
630
-
631
- // ---------------------------
632
- //----------------- PROJECT PERSISTENCE TYPES ------------
633
- /**
634
- * Canonical project row shape returned by the projects repository.
635
- *
636
- * Use this type whenever backend services need to pass around one database
637
- * project record without leaking raw SQL row typing across modules.
638
- */
639
- export type ProjectRepositoryRow = {
640
- project_id: string;
641
- project_path: string;
642
- custom_project_name: string | null;
643
- isStarred: number;
644
- isArchived: number;
645
- };
646
-
647
- /**
648
- * Result category returned by `projectsDb.createProjectPath`.
649
- *
650
- * `created` means a fresh row was inserted, `reactivated_archived` means an
651
- * existing archived path was accepted and updated, and `active_conflict` means
652
- * an already-active path blocked project creation.
653
- */
654
- export type CreateProjectPathOutcome =
655
- | 'created'
656
- | 'reactivated_archived'
657
- | 'active_conflict';
658
-
659
- /**
660
- * Structured result returned by project-path upsert operations.
661
- *
662
- * Services should use this result to decide whether a request succeeded,
663
- * should return a conflict, or needs follow-up retrieval of row metadata.
664
- */
665
- export type CreateProjectPathResult = {
666
- outcome: CreateProjectPathOutcome;
667
- project: ProjectRepositoryRow | null;
668
- };
669
-
670
- /**
671
- * Validation result for user-supplied workspace/project paths.
672
- *
673
- * `resolvedPath` is present only when validation succeeds. `error` is present
674
- * only when validation fails and is suitable for user-facing diagnostics.
675
- */
676
- export type WorkspacePathValidationResult = {
677
- valid: boolean;
678
- resolvedPath?: string;
679
- error?: string;
680
- };
681
-
682
- // ---------------------------
683
- //----------------- GIT WORKTREE MANAGEMENT ------------
684
- /**
685
- * Captured output of one completed `git` invocation.
686
- *
687
- * Returned by `GitCommandRunner` implementations so worktree services can read
688
- * both streams without caring about process plumbing.
689
- */
690
- export type GitCommandResult = {
691
- stdout: string;
692
- stderr: string;
693
- };
694
-
695
- /**
696
- * Executes `git <args>` inside `cwd` and resolves with the captured output.
697
- *
698
- * All worktree services receive their git access through this contract so
699
- * tests can inject a fake runner instead of spawning real processes. The
700
- * promise must reject (with `stderr` attached when available) on a non-zero
701
- * exit code.
702
- */
703
- export type GitCommandRunner = (args: string[], cwd: string) => Promise<GitCommandResult>;
704
-
705
- /**
706
- * One entry parsed from `git worktree list --porcelain`.
707
- *
708
- * This is the raw repository-level view (path/HEAD/branch/flags) before any
709
- * enrichment with project links or ahead/behind counts. `branch` is null for
710
- * detached-HEAD worktrees.
711
- */
712
- export type WorktreePorcelainEntry = {
713
- path: string;
714
- headSha: string | null;
715
- branch: string | null;
716
- isDetached: boolean;
717
- isLocked: boolean;
718
- isPrunable: boolean;
719
- };
720
-
721
- /**
722
- * Fully enriched worktree row served to the UI.
723
- *
724
- * Extends the porcelain entry with everything the Worktrees panel renders:
725
- * dirty-file count, ahead/behind relative to the base branch (the branch
726
- * checked out in the main worktree), last-commit metadata, and the CloudCLI
727
- * project row linked to the worktree directory (if one was registered).
728
- */
729
- export type WorktreeDescriptor = {
730
- path: string;
731
- branch: string | null;
732
- headSha: string | null;
733
- isMain: boolean;
734
- isCurrent: boolean;
735
- isLocked: boolean;
736
- isDetached: boolean;
737
- changedFileCount: number;
738
- ahead: number;
739
- behind: number;
740
- lastCommitSubject: string | null;
741
- lastCommitDate: string | null;
742
- linkedProjectId: string | null;
743
- linkedProjectArchived: boolean;
744
- };
745
-
746
- /**
747
- * Response payload of `GET /api/worktrees`.
748
- *
749
- * `baseBranch` is the branch checked out in the main worktree — the merge
750
- * target offered by the UI. `worktrees` always lists the main worktree first.
751
- */
752
- export type WorktreeListResult = {
753
- repositoryRoot: string;
754
- baseBranch: string | null;
755
- worktrees: WorktreeDescriptor[];
756
- };
757
-
758
- // ---------------------------
759
- //----------------- WORKTREE SERVICE INPUTS AND RESULTS ------------
760
- /**
761
- * Input accepted by the worktree-listing workflow.
762
- *
763
- * `projectPath` may point at the main checkout or any linked worktree. The
764
- * service uses Git to resolve the complete repository-level worktree list.
765
- */
766
- export type ListWorktreesInput = {
767
- projectPath: string;
768
- };
769
-
770
- /**
771
- * Input accepted when creating a linked Git worktree.
772
- *
773
- * `branch` is checked out when it already exists, otherwise it is created from
774
- * `baseBranch`. When `baseBranch` is omitted, the main worktree branch is used.
775
- */
776
- export type CreateWorktreeInput = {
777
- projectPath: string;
778
- branch: string;
779
- baseBranch?: string | null;
780
- };
781
-
782
- /**
783
- * Result of successfully creating a linked Git worktree.
784
- *
785
- * `createdBranch` distinguishes a new branch from an existing branch checkout,
786
- * allowing API clients to accurately describe what Git changed.
787
- */
788
- export type CreateWorktreeResult = {
789
- worktreePath: string;
790
- branch: string;
791
- createdBranch: boolean;
792
- };
793
-
794
- /**
795
- * Result of atomically creating and registering a worktree for project use.
796
- *
797
- * The Worktrees application service compensates the Git creation if project
798
- * registration fails, so routes only receive this shape after both steps pass.
799
- */
800
- export type CreateAndOpenWorktreeResult = CreateWorktreeResult & {
801
- project: WorktreeProjectView;
802
- };
803
-
804
- /**
805
- * Input accepted when registering an existing worktree as a CloudCLI project.
806
- *
807
- * The service verifies that `worktreePath` belongs to the repository containing
808
- * `projectPath` before it creates or restores any project record.
809
- */
810
- export type OpenWorktreeInput = {
811
- projectPath: string;
812
- worktreePath: string;
813
- };
814
-
815
- /**
816
- * Project view returned after a worktree is opened in CloudCLI.
817
- *
818
- * This deliberately mirrors the project-selection payload used by the Projects
819
- * module so the frontend can switch to the worktree without another lookup.
820
- */
821
- export type WorktreeProjectView = {
822
- projectId: string;
823
- path: string;
824
- fullPath: string;
825
- displayName: string;
826
- isStarred: boolean;
827
- sessions: [];
828
- sessionMeta: { hasMore: false; total: 0 };
829
- };
830
-
831
- /**
832
- * Input accepted when removing a linked Git worktree.
833
- *
834
- * `force` permits removal with local changes. `deleteBranch` requests
835
- * best-effort branch cleanup after the worktree directory is removed.
836
- */
837
- export type RemoveWorktreeInput = {
838
- projectPath: string;
839
- worktreePath: string;
840
- force?: boolean;
841
- deleteBranch?: boolean;
842
- };
843
-
844
- /**
845
- * Result of removing a linked Git worktree.
846
- *
847
- * `archivalError` reports best-effort project archival failure after Git has
848
- * already removed the worktree, allowing callers to represent partial success.
849
- */
850
- export type RemoveWorktreeResult = {
851
- removedPath: string;
852
- branch: string | null;
853
- branchDeleted: boolean;
854
- archivedProjectId: string | null;
855
- archivalError: string | null;
856
- };
857
-
858
- /**
859
- * Input accepted when merging a linked worktree into the main worktree branch.
860
- *
861
- * The service verifies both worktrees are clean, supports squash and regular
862
- * merges, and may remove the source worktree after a successful merge.
863
- */
864
- export type MergeWorktreeInput = {
865
- projectPath: string;
866
- worktreePath: string;
867
- squash?: boolean;
868
- message?: string | null;
869
- removeAfterMerge?: boolean;
870
- };
871
-
872
- /**
873
- * Result of a completed worktree merge.
874
- *
875
- * `removedWorktree` is populated only when post-merge removal succeeds.
876
- * `cleanupError` reports failed optional removal without misrepresenting the
877
- * already-completed merge as a failure.
878
- */
879
- export type MergeWorktreeResult = {
880
- mergedBranch: string;
881
- targetBranch: string;
882
- squash: boolean;
883
- removedWorktree: RemoveWorktreeResult | null;
884
- cleanupError: string | null;
885
- };
886
-
887
- // ---------------------------
888
- //----------------- WORKTREE MODULE DEPENDENCY CONTRACTS ------------
889
- /**
890
- * Filesystem capability required by the Worktrees module.
891
- *
892
- * Production wiring checks the real filesystem; unit tests provide a small
893
- * deterministic fake so worktree creation never touches developer directories.
894
- */
895
- export type WorktreeFileSystem = {
896
- pathExists(candidatePath: string): Promise<boolean>;
897
- };
898
-
899
- /**
900
- * Project-management boundary consumed by Worktrees workflows.
901
- *
902
- * The Worktrees module uses this contract instead of importing Database or
903
- * Projects internals. Production adapters delegate through those modules'
904
- * `index.ts` barrels, while unit tests supply in-memory functions.
905
- */
906
- export type WorktreeProjectGateway = {
907
- getProjectPathById(projectId: string): string | null;
908
- getProjectByPath(projectPath: string): ProjectRepositoryRow | null;
909
- createProject(input: {
910
- projectPath: string;
911
- customName: string;
912
- }): Promise<{
913
- outcome: 'created' | 'reactivated_archived';
914
- project: { projectId: string };
915
- }>;
916
- restoreProject(projectId: string): void | Promise<void>;
917
- archiveProject(projectId: string): void | Promise<void>;
918
- };
919
-
920
- /**
921
- * Complete application-service surface used by the Worktrees HTTP router.
922
- *
923
- * Routes parse transport values and call these functions; they do not import
924
- * repositories, filesystem adapters, Git runners, or individual service files.
925
- */
926
- export type WorktreeServices = {
927
- resolveProjectPath(projectId: string): string;
928
- list(input: ListWorktreesInput): Promise<WorktreeListResult>;
929
- create(input: CreateWorktreeInput): Promise<CreateWorktreeResult>;
930
- createAndOpen(input: CreateWorktreeInput): Promise<CreateAndOpenWorktreeResult>;
931
- open(input: OpenWorktreeInput): Promise<WorktreeProjectView>;
932
- merge(input: MergeWorktreeInput): Promise<MergeWorktreeResult>;
933
- remove(input: RemoveWorktreeInput): Promise<RemoveWorktreeResult>;
934
- };
935
-
936
- // ---------------------------
937
- //----------------- FILE TREE MODULE CONTRACTS ------------
938
- /**
939
- * One filesystem item returned by the File Tree API.
940
- *
941
- * The service populates metadata without following symlinks and recursively
942
- * attaches `children` only while the requested depth permits traversal. The
943
- * frontend uses the absolute `path` as the stable identifier for editor and
944
- * file-operation requests.
945
- */
946
- export type FileTreeNode = {
947
- name: string;
948
- path: string;
949
- type: 'file' | 'directory';
950
- size: number;
951
- modified: string | null;
952
- permissions: string;
953
- permissionsRwx: string;
954
- isSymlink?: boolean;
955
- children?: FileTreeNode[];
956
- };
957
-
958
- /**
959
- * Minimal directory-entry shape required during File Tree traversal.
960
- *
961
- * Production adapts Node `Dirent` objects to this structural contract. Tests
962
- * provide small handwritten entries and therefore never read real directories.
963
- */
964
- export type FileTreeDirectoryEntry = {
965
- name: string;
966
- isDirectory(): boolean;
967
- };
968
-
969
- /**
970
- * Minimal file-stat shape used for tree metadata and delete decisions.
971
- *
972
- * The numeric mode is converted to octal and rwx strings for the UI. `lstat`
973
- * supplies symlink state while `stat` is used when deciding file versus folder
974
- * deletion behavior.
975
- */
976
- export type FileTreeStats = {
977
- size: number;
978
- mtime: Date;
979
- mode: number;
980
- isDirectory(): boolean;
981
- isSymbolicLink(): boolean;
982
- };
983
-
984
- /**
985
- * Complete filesystem capability injected into File Tree services.
986
- *
987
- * The production composition root delegates these operations to Node's fs
988
- * APIs. Unit tests provide deterministic path-keyed fakes so service tests
989
- * cannot inspect, write, rename, or delete developer files.
990
- */
991
- export type FileTreeFileSystem = {
992
- access(candidatePath: string): Promise<void>;
993
- stat(candidatePath: string): Promise<FileTreeStats>;
994
- lstat(candidatePath: string): Promise<FileTreeStats>;
995
- // Streamed rather than returned as an array so a directory with millions of
996
- // children is abandoned at the entry limit instead of being materialized.
997
- openDirectory(directoryPath: string): AsyncIterable<FileTreeDirectoryEntry>;
998
- realpath(candidatePath: string): Promise<string>;
999
- readTextFile(filePath: string): Promise<string>;
1000
- writeTextFile(filePath: string, content: string): Promise<void>;
1001
- makeDirectory(directoryPath: string, recursive: boolean): Promise<void>;
1002
- rename(oldPath: string, newPath: string): Promise<void>;
1003
- removeDirectory(directoryPath: string): Promise<void>;
1004
- unlink(filePath: string): Promise<void>;
1005
- copyFile(sourcePath: string, destinationPath: string): Promise<void>;
1006
- createReadStream(filePath: string): Readable;
1007
- };
1008
-
1009
- /**
1010
- * Project lookup boundary consumed by File Tree workflows.
1011
- *
1012
- * File Tree services resolve DB-assigned project ids through this contract and
1013
- * never import the Database module or its repositories directly.
1014
- */
1015
- export type FileTreeProjectGateway = {
1016
- getProjectPathById(projectId: string): string | null | Promise<string | null>;
1017
- };
1018
-
1019
- /**
1020
- * Workspace validation boundary used by filesystem browsing and folder creation.
1021
- *
1022
- * The injected validator enforces the configured workspace root and resolves
1023
- * symlinks before the File Tree service exposes or mutates paths.
1024
- */
1025
- export type FileTreeWorkspaceGateway = {
1026
- rootPath: string;
1027
- validatePath(candidatePath: string): Promise<WorkspacePathValidationResult>;
1028
- };
1029
-
1030
- /**
1031
- * Uploaded-file record passed from the Multer transport adapter into the File
1032
- * Tree service.
1033
- *
1034
- * Transport-specific field names are normalized so upload workflows do not
1035
- * depend on Express or Multer types.
1036
- */
1037
- export type FileTreeUploadedFile = {
1038
- originalName: string;
1039
- temporaryPath: string;
1040
- size: number;
1041
- mimeType: string;
1042
- };
1043
-
1044
- /**
1045
- * Logger boundary for expected File Tree diagnostics.
1046
- *
1047
- * Production delegates to the server console. Unit tests use no-op or captured
1048
- * loggers and never patch the global console singleton.
1049
- */
1050
- export type FileTreeLogger = {
1051
- error(message: string, error?: unknown): void;
1052
- };
1053
-
1054
- /**
1055
- * Required production dependencies for the File Tree application service.
1056
- *
1057
- * Filesystem, project lookup, workspace policy, MIME detection, concurrency,
1058
- * and logging are all explicit so service construction has no hidden process,
1059
- * repository, or machine-wide defaults.
1060
- */
1061
- export type FileTreeServiceDependencies = {
1062
- fileSystem: FileTreeFileSystem;
1063
- projects: FileTreeProjectGateway;
1064
- workspace: FileTreeWorkspaceGateway;
1065
- resolveMimeType(filePath: string): string;
1066
- fileSystemConcurrency: number;
1067
- logger: FileTreeLogger;
1068
- };
1069
-
1070
- /**
1071
- * Complete File Tree application-service surface consumed by HTTP routes.
1072
- *
1073
- * Routes parse transport inputs and call these methods; they never resolve
1074
- * project repositories, validate filesystem ownership, or perform filesystem
1075
- * mutations themselves.
1076
- */
1077
- export type FileTreeServices = {
1078
- browseWorkspace(inputPath: string | null): Promise<{
1079
- path: string;
1080
- suggestions: Array<{ path: string; name: string; type: 'directory' }>;
1081
- }>;
1082
- createWorkspaceFolder(folderPath: string): Promise<{ success: true; path: string }>;
1083
- readTextFile(projectId: string, filePath: string): Promise<{ content: string; path: string }>;
1084
- openFile(projectId: string, filePath: string): Promise<{ contentType: string; stream: Readable }>;
1085
- saveTextFile(projectId: string, filePath: string, content: string): Promise<{
1086
- success: true;
1087
- path: string;
1088
- message: string;
1089
- }>;
1090
- listProjectFiles(
1091
- projectId: string,
1092
- options?: { respectGitignore: boolean },
1093
- ): Promise<FileTreeNode[]>;
1094
- createEntry(input: {
1095
- projectId: string;
1096
- parentPath: string;
1097
- type: 'file' | 'directory';
1098
- name: string;
1099
- }): Promise<{ success: true; path: string; name: string; type: 'file' | 'directory'; message: string }>;
1100
- renameEntry(input: { projectId: string; oldPath: string; newName: string }): Promise<{
1101
- success: true;
1102
- oldPath: string;
1103
- newPath: string;
1104
- newName: string;
1105
- message: string;
1106
- }>;
1107
- deleteEntry(input: { projectId: string; targetPath: string }): Promise<{
1108
- success: true;
1109
- path: string;
1110
- type: 'file' | 'directory';
1111
- message: string;
1112
- }>;
1113
- storeUploadedFiles(input: {
1114
- projectId: string;
1115
- targetPath: string;
1116
- relativePaths: string[];
1117
- requestedFileCount: number;
1118
- files: FileTreeUploadedFile[];
1119
- }): Promise<{
1120
- success: true;
1121
- files: Array<{ name: string; path: string; size: number; mimeType: string }>;
1122
- uploadedCount: number;
1123
- requestedFileCount: number;
1124
- targetPath: string;
1125
- message: string;
1126
- }>;
1127
- };
1128
-
1129
- // ---------------------------
1130
- //----------------- VOICE MODULE CONTRACTS ------------
1131
- /**
1132
- * Per-request voice settings parsed from authenticated HTTP headers.
1133
- *
1134
- * The Voice routes create this value from the optional `x-voice-*` headers and
1135
- * pass it to the Voice service. Empty values mean "use the server-configured
1136
- * default"; the backend base URL is intentionally absent because clients must
1137
- * never control the server's outbound destination.
1138
- */
1139
- export type VoiceRequestOverrides = {
1140
- apiKey?: string;
1141
- sttModel?: string;
1142
- ttsModel?: string;
1143
- ttsVoice?: string;
1144
- ttsFormat?: string;
1145
- };
1146
-
1147
- /**
1148
- * Uploaded audio accepted by the Voice transcription service.
1149
- *
1150
- * Routes translate Multer's transport-specific file object into this minimal
1151
- * shape so the service does not depend on Express or Multer types.
1152
- */
1153
- export type VoiceAudioUpload = {
1154
- bytes: Buffer;
1155
- mimeType: string;
1156
- fileName: string;
1157
- };
1158
-
1159
- /**
1160
- * Successful speech payload returned by the Voice service.
1161
- *
1162
- * The route copies `contentType` to the client response and pipes `body`
1163
- * without buffering the complete synthesized audio in application memory.
1164
- */
1165
- export type VoiceSpeechPayload = {
1166
- contentType: string;
1167
- body: ReadableStream<Uint8Array> | null;
1168
- };
1169
-
1170
- /**
1171
- * Explicit service result used by Voice routes instead of transport-aware
1172
- * exceptions.
1173
- *
1174
- * Services return `ok: false` with the exact client status/message for expected
1175
- * backend, validation, and timeout failures. Routes only translate the result
1176
- * into HTTP output, while unexpected programming errors still reject normally.
1177
- */
1178
- export type VoiceServiceResult<TValue> =
1179
- | { ok: true; value: TValue }
1180
- | { ok: false; status: number; error: string };
1181
-
1182
- /**
1183
- * Complete application-service surface consumed by the Voice HTTP router.
1184
- *
1185
- * The composition root supplies a concrete implementation with environment
1186
- * configuration and an injected outbound HTTP adapter. Unit tests use the same
1187
- * contract with handwritten fetch fakes and never patch global state.
1188
- */
1189
- export type VoiceService = {
1190
- getHealth(): { configured: boolean };
1191
- transcribe(input: {
1192
- audio: VoiceAudioUpload;
1193
- overrides: VoiceRequestOverrides;
1194
- }): Promise<VoiceServiceResult<{ text: string }>>;
1195
- synthesizeSpeech(input: {
1196
- text: string;
1197
- overrides: VoiceRequestOverrides;
1198
- }): Promise<VoiceServiceResult<VoiceSpeechPayload>>;
1199
- };
1200
-
1201
- // ---------------------------
1202
- //----------------- CLI MODULE CONTRACTS ------------
1203
- /**
1204
- * Output boundary used by the CLI and Sandbox services.
1205
- *
1206
- * Production wiring delegates to the real console. Unit tests collect these
1207
- * calls in arrays, which keeps command assertions deterministic and avoids
1208
- * monkey-patching the global console singleton.
1209
- */
1210
- export type CliOutput = {
1211
- log(message?: string): void;
1212
- error(message?: string): void;
1213
- };
1214
-
1215
- /**
1216
- * Minimal synchronous filesystem surface shared by CLI status reporting and
1217
- * sandbox workspace validation.
1218
- *
1219
- * The production composition root adapts Node's filesystem module. Tests supply
1220
- * path-keyed fakes, so service tests never inspect or modify the real machine.
1221
- */
1222
- export type CliFileSystem = {
1223
- pathExists(filePath: string): boolean;
1224
- getFileStats(filePath: string): { size: number; modifiedAt: Date };
1225
- };
1226
-
1227
- /**
1228
- * Mutable environment view owned by the CLI application.
1229
- *
1230
- * CLI options update this object before the server starts. Production passes
1231
- * `process.env`; tests pass a plain record to verify option precedence without
1232
- * changing process-wide environment state.
1233
- */
1234
- export type CliEnvironment = Record<string, string | undefined>;
1235
-
1236
- /**
1237
- * Package metadata displayed by CLI help, status, version, and update commands.
1238
- *
1239
- * The composition root reads this once from the application package file and
1240
- * injects only the fields the service needs.
1241
- */
1242
- export type CliPackageMetadata = {
1243
- version: string;
1244
- homepage?: string;
1245
- bugsUrl?: string;
1246
- };
1247
-
1248
- /**
1249
- * Executable CLI application returned by the CLI composition root.
1250
- *
1251
- * The thin executable entrypoint passes `process.argv` arguments to `run` and
1252
- * copies the returned code to `process.exitCode`. Tests invoke the same method
1253
- * directly with isolated dependencies.
1254
- */
1255
- export type CliApplication = {
1256
- run(argumentsList: string[]): Promise<number>;
1257
- };
1258
-
1259
- /**
1260
- * Sandbox command service consumed by the top-level CLI command dispatcher.
1261
- *
1262
- * Keeping this behind one required dependency lets CLI tests use a tiny fake,
1263
- * while focused Sandbox tests exercise subprocess and filesystem behavior with
1264
- * their own handwritten adapters.
1265
- */
1266
- export type SandboxCommandService = {
1267
- execute(argumentsList: string[]): Promise<number>;
1268
- };
337
+ allow: boolean;
338
+ updatedInput?: unknown;
339
+ message?: string;
340
+ rememberEntry?: unknown;
341
+ };
342
+
343
+ export type ProviderRuntimePermissionGateway = {
344
+ resolve(requestId: string, decision: ProviderPermissionDecision): void;
345
+ listPending(sessionId: string): unknown[];
346
+ };
347
+
348
+ /**
349
+ * Provider-scoped application capabilities supplied to a runtime for one run.
350
+ *
351
+ * Keeping these lookups outside concrete SDK/CLI adapters prevents the
352
+ * adapters from importing services that resolve back through providerRegistry.
353
+ */
354
+ export type ProviderRuntimeContext = {
355
+ resolveProviderSessionId(sessionId: string | null | undefined): string | null;
356
+ resolveResumeModel(
357
+ sessionId: string | undefined,
358
+ requestedModel?: string | null,
359
+ ): Promise<string | undefined>;
360
+ getProviderModels(): Promise<ProviderModelsDefinition>;
361
+ normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
362
+ isProviderInstalled(): Promise<boolean>;
363
+ };
364
+
365
+ export type ProviderRunFunction = (
366
+ command: string,
367
+ options: AnyRecord,
368
+ writer: ProviderRuntimeWriter,
369
+ ) => Promise<unknown>;
370
+
371
+ /**
372
+ * Shared options used to fetch historical provider messages.
373
+ *
374
+ * Consumers should pass provider-specific lookup hints (`projectPath`) only
375
+ * when the selected provider requires them.
376
+ *
377
+ * `providerSessionId` is the provider-native session id from the sessions
378
+ * index (transcript file name / provider database key). Provider adapters
379
+ * must use it — never the app-facing session id they were called with — when
380
+ * matching transcript rows on disk, because app-created sessions use an
381
+ * app-allocated id that the provider has never seen.
382
+ */
383
+ export type FetchHistoryOptions = {
384
+ projectPath?: string;
385
+ limit?: number | null;
386
+ offset?: number;
387
+ providerSessionId?: string;
388
+ };
389
+
390
+ /**
391
+ * Standardized response payload returned from provider history readers.
392
+ *
393
+ * Use this as the contract for APIs that return paginated conversation history.
394
+ */
395
+ export type FetchHistoryResult = {
396
+ messages: NormalizedMessage[];
397
+ total: number;
398
+ hasMore: boolean;
399
+ offset: number;
400
+ limit: number | null;
401
+ tokenUsage?: unknown;
402
+ };
403
+
404
+ // ---------------------------
405
+ //----------------- PROVIDER SKILL TYPES ------------
406
+ /**
407
+ * Scope where a provider skill definition was discovered.
408
+ *
409
+ * Provider skill adapters should use this to describe the origin of each
410
+ * skill markdown file without leaking provider-specific folder names into route
411
+ * contracts. `repo` is used for Codex repository lookup locations, while
412
+ * `project` is used for providers that treat workspace-local skills as project
413
+ * scoped.
414
+ */
415
+ export type ProviderSkillScope = 'user' | 'project' | 'plugin' | 'repo' | 'admin' | 'system';
416
+
417
+ /**
418
+ * Shared input accepted by provider skill listing operations.
419
+ *
420
+ * Routes pass `workspacePath` when a caller wants project/repository skills for
421
+ * a specific folder. Providers should fall back to the backend process cwd when
422
+ * this option is omitted.
423
+ */
424
+ export type ProviderSkillListOptions = {
425
+ workspacePath?: string;
426
+ };
427
+
428
+ /**
429
+ * One supporting file bundled with an uploaded provider skill.
430
+ *
431
+ * `relativePath` is resolved below the installed skill directory and must never
432
+ * be absolute or contain traversal segments. Text files may use `utf8`; binary
433
+ * scripts and assets should use `base64` so JSON transport does not corrupt
434
+ * their bytes.
435
+ */
436
+ export type ProviderSkillCreateFile = {
437
+ relativePath: string;
438
+ content: string;
439
+ encoding: 'utf8' | 'base64';
440
+ };
441
+
442
+ /**
443
+ * One skill markdown payload submitted for provider-managed installation.
444
+ *
445
+ * `content` is the raw markdown body that will be written to `SKILL.md`.
446
+ * `directoryName` lets callers control the target folder name explicitly when
447
+ * they want stable filesystem paths that differ from the markdown front matter
448
+ * `name` field. `fileName` is optional upload metadata used only as a final
449
+ * fallback when no directory name or front matter name is present. `files`
450
+ * carries scripts, references, and other files from a complete skill folder.
451
+ */
452
+ export type ProviderSkillCreateEntry = {
453
+ content: string;
454
+ directoryName?: string;
455
+ fileName?: string;
456
+ files?: ProviderSkillCreateFile[];
457
+ };
458
+
459
+ /**
460
+ * Shared input accepted by provider skill creation operations.
461
+ *
462
+ * The service layer batches multiple skill definitions in one request. Each
463
+ * entry can contain only markdown or a complete skill folder.
464
+ */
465
+ export type ProviderSkillCreateInput = {
466
+ entries: ProviderSkillCreateEntry[];
467
+ };
468
+
469
+ export type ProviderSkillRemoveInput = {
470
+ directoryName: string;
471
+ };
472
+
473
+ /**
474
+ * Normalized skill record returned by provider skill adapters.
475
+ *
476
+ * The `command` value is the exact invocation text the selected provider expects
477
+ * for this skill. Claude plugin skills use a namespaced command such as
478
+ * `/plugin-name:skill-name`, while Codex skills use the `$skill-name` form.
479
+ * `sourcePath` points to the skill markdown file that produced the record so
480
+ * callers can distinguish duplicate skill names across scopes.
481
+ */
482
+ export type ProviderSkill = {
483
+ provider: LLMProvider;
484
+ name: string;
485
+ description: string;
486
+ command: string;
487
+ scope: ProviderSkillScope;
488
+ sourcePath: string;
489
+ pluginName?: string;
490
+ pluginId?: string;
491
+ };
492
+
493
+ /**
494
+ * Internal source descriptor consumed by shared provider skill discovery logic.
495
+ *
496
+ * Concrete provider adapters build these records from their native lookup rules.
497
+ * The shared skills provider then scans `rootDir` for child skill markdown files
498
+ * and uses `commandForSkill` or `commandPrefix` to produce the provider-specific
499
+ * invocation command. Set `recursive` only when a provider stores skills under
500
+ * arbitrary nested folders below the source root.
501
+ */
502
+ export type ProviderSkillSource = {
503
+ scope: ProviderSkillScope;
504
+ rootDir: string;
505
+ recursive?: boolean;
506
+ commandPrefix?: '/' | '$';
507
+ commandForSkill?: (skillName: string) => string;
508
+ pluginName?: string;
509
+ pluginId?: string;
510
+ };
511
+
512
+ // ---------------------------
513
+ //----------------- SHARED ERROR TYPES ------------
514
+ /**
515
+ * Optional metadata used when constructing application-level errors.
516
+ *
517
+ * `statusCode` should reflect the HTTP response status, while `code` identifies
518
+ * the stable machine-readable error category.
519
+ */
520
+ export type AppErrorOptions = {
521
+ code?: string;
522
+ statusCode?: number;
523
+ details?: unknown;
524
+ };
525
+
526
+ // ---------------------------
527
+ //----------------- MCP TYPES ------------
528
+ /**
529
+ * Scope where an MCP server definition is stored and resolved.
530
+ *
531
+ * `user` is global for a user account, `local` is provider-local, and `project`
532
+ * is tied to a specific project path.
533
+ */
534
+ export type McpScope = 'user' | 'local' | 'project';
535
+
536
+ /**
537
+ * Transport protocol used by an MCP server definition.
538
+ */
539
+ export type McpTransport = 'stdio' | 'http' | 'sse';
540
+
541
+ /**
542
+ * Normalized MCP server model exposed to frontend and route handlers.
543
+ *
544
+ * Provider adapters should map provider-native config to this structure before
545
+ * returning results.
546
+ */
547
+ export type ProviderMcpServer = {
548
+ provider: LLMProvider;
549
+ name: string;
550
+ scope: McpScope;
551
+ transport: McpTransport;
552
+ command?: string;
553
+ args?: string[];
554
+ env?: Record<string, string>;
555
+ cwd?: string;
556
+ url?: string;
557
+ headers?: Record<string, string>;
558
+ envVars?: string[];
559
+ bearerTokenEnvVar?: string;
560
+ envHttpHeaders?: Record<string, string>;
561
+ };
562
+
563
+ /**
564
+ * Payload for create/update MCP server operations.
565
+ *
566
+ * Routes and services should accept this type, validate it, and then persist it
567
+ * through provider-specific MCP repositories.
568
+ */
569
+ export type UpsertProviderMcpServerInput = {
570
+ name: string;
571
+ scope?: McpScope;
572
+ transport: McpTransport;
573
+ workspacePath?: string;
574
+ command?: string;
575
+ args?: string[];
576
+ env?: Record<string, string>;
577
+ cwd?: string;
578
+ url?: string;
579
+ headers?: Record<string, string>;
580
+ envVars?: string[];
581
+ bearerTokenEnvVar?: string;
582
+ envHttpHeaders?: Record<string, string>;
583
+ };
584
+
585
+ // ---------------------------
586
+ //----------------- PROVIDER AUTH TYPES ------------
587
+ /**
588
+ * Authentication status result returned by provider health checks.
589
+ *
590
+ * This shape is consumed by settings/status endpoints to report installation and
591
+ * credential state for each provider.
592
+ */
593
+ export type ProviderAuthStatus = {
594
+ installed: boolean;
595
+ provider: LLMProvider;
596
+ authenticated: boolean;
597
+ email: string | null;
598
+ method: string | null;
599
+ error?: string;
600
+ };
601
+
602
+ // ---------------------------
603
+ //----------------- SHARED DATABASE CREDENTIAL TYPES ------------
604
+ /**
605
+ * Safe credential view returned by credential listing APIs.
606
+ *
607
+ * This intentionally excludes the raw credential secret while still exposing
608
+ * metadata needed for UI rendering and management operations.
609
+ */
610
+ export type CredentialPublicRow = {
611
+ id: number;
612
+ credential_name: string;
613
+ credential_type: string;
614
+ description: string | null;
615
+ created_at: string;
616
+ is_active: number;
617
+ };
618
+
619
+ /**
620
+ * Result returned after creating a credential record.
621
+ *
622
+ * Use this return shape when callers need the created id and display metadata,
623
+ * but must never receive the stored secret value.
624
+ */
625
+ export type CreateCredentialResult = {
626
+ id: number | bigint;
627
+ credentialName: string;
628
+ credentialType: string;
629
+ };
630
+
631
+ // ---------------------------
632
+ //----------------- PROJECT PERSISTENCE TYPES ------------
633
+ /**
634
+ * Canonical project row shape returned by the projects repository.
635
+ *
636
+ * Use this type whenever backend services need to pass around one database
637
+ * project record without leaking raw SQL row typing across modules.
638
+ */
639
+ export type ProjectRepositoryRow = {
640
+ project_id: string;
641
+ project_path: string;
642
+ custom_project_name: string | null;
643
+ isStarred: number;
644
+ isArchived: number;
645
+ };
646
+
647
+ /**
648
+ * Result category returned by `projectsDb.createProjectPath`.
649
+ *
650
+ * `created` means a fresh row was inserted, `reactivated_archived` means an
651
+ * existing archived path was accepted and updated, and `active_conflict` means
652
+ * an already-active path blocked project creation.
653
+ */
654
+ export type CreateProjectPathOutcome =
655
+ | 'created'
656
+ | 'reactivated_archived'
657
+ | 'active_conflict';
658
+
659
+ /**
660
+ * Structured result returned by project-path upsert operations.
661
+ *
662
+ * Services should use this result to decide whether a request succeeded,
663
+ * should return a conflict, or needs follow-up retrieval of row metadata.
664
+ */
665
+ export type CreateProjectPathResult = {
666
+ outcome: CreateProjectPathOutcome;
667
+ project: ProjectRepositoryRow | null;
668
+ };
669
+
670
+ /**
671
+ * Validation result for user-supplied workspace/project paths.
672
+ *
673
+ * `resolvedPath` is present only when validation succeeds. `error` is present
674
+ * only when validation fails and is suitable for user-facing diagnostics.
675
+ */
676
+ export type WorkspacePathValidationResult = {
677
+ valid: boolean;
678
+ resolvedPath?: string;
679
+ error?: string;
680
+ };
681
+
682
+ // ---------------------------
683
+ //----------------- GIT WORKTREE MANAGEMENT ------------
684
+ /**
685
+ * Captured output of one completed `git` invocation.
686
+ *
687
+ * Returned by `GitCommandRunner` implementations so worktree services can read
688
+ * both streams without caring about process plumbing.
689
+ */
690
+ export type GitCommandResult = {
691
+ stdout: string;
692
+ stderr: string;
693
+ };
694
+
695
+ /**
696
+ * Executes `git <args>` inside `cwd` and resolves with the captured output.
697
+ *
698
+ * All worktree services receive their git access through this contract so
699
+ * tests can inject a fake runner instead of spawning real processes. The
700
+ * promise must reject (with `stderr` attached when available) on a non-zero
701
+ * exit code.
702
+ */
703
+ export type GitCommandRunner = (args: string[], cwd: string) => Promise<GitCommandResult>;
704
+
705
+ /**
706
+ * One entry parsed from `git worktree list --porcelain`.
707
+ *
708
+ * This is the raw repository-level view (path/HEAD/branch/flags) before any
709
+ * enrichment with project links or ahead/behind counts. `branch` is null for
710
+ * detached-HEAD worktrees.
711
+ */
712
+ export type WorktreePorcelainEntry = {
713
+ path: string;
714
+ headSha: string | null;
715
+ branch: string | null;
716
+ isDetached: boolean;
717
+ isLocked: boolean;
718
+ isPrunable: boolean;
719
+ };
720
+
721
+ /**
722
+ * Fully enriched worktree row served to the UI.
723
+ *
724
+ * Extends the porcelain entry with everything the Worktrees panel renders:
725
+ * dirty-file count, ahead/behind relative to the base branch (the branch
726
+ * checked out in the main worktree), last-commit metadata, and the WindCli
727
+ * project row linked to the worktree directory (if one was registered).
728
+ */
729
+ export type WorktreeDescriptor = {
730
+ path: string;
731
+ branch: string | null;
732
+ headSha: string | null;
733
+ isMain: boolean;
734
+ isCurrent: boolean;
735
+ isLocked: boolean;
736
+ isDetached: boolean;
737
+ changedFileCount: number;
738
+ ahead: number;
739
+ behind: number;
740
+ lastCommitSubject: string | null;
741
+ lastCommitDate: string | null;
742
+ linkedProjectId: string | null;
743
+ linkedProjectArchived: boolean;
744
+ };
745
+
746
+ /**
747
+ * Response payload of `GET /api/worktrees`.
748
+ *
749
+ * `baseBranch` is the branch checked out in the main worktree — the merge
750
+ * target offered by the UI. `worktrees` always lists the main worktree first.
751
+ */
752
+ export type WorktreeListResult = {
753
+ repositoryRoot: string;
754
+ baseBranch: string | null;
755
+ worktrees: WorktreeDescriptor[];
756
+ };
757
+
758
+ // ---------------------------
759
+ //----------------- WORKTREE SERVICE INPUTS AND RESULTS ------------
760
+ /**
761
+ * Input accepted by the worktree-listing workflow.
762
+ *
763
+ * `projectPath` may point at the main checkout or any linked worktree. The
764
+ * service uses Git to resolve the complete repository-level worktree list.
765
+ */
766
+ export type ListWorktreesInput = {
767
+ projectPath: string;
768
+ };
769
+
770
+ /**
771
+ * Input accepted when creating a linked Git worktree.
772
+ *
773
+ * `branch` is checked out when it already exists, otherwise it is created from
774
+ * `baseBranch`. When `baseBranch` is omitted, the main worktree branch is used.
775
+ */
776
+ export type CreateWorktreeInput = {
777
+ projectPath: string;
778
+ branch: string;
779
+ baseBranch?: string | null;
780
+ };
781
+
782
+ /**
783
+ * Result of successfully creating a linked Git worktree.
784
+ *
785
+ * `createdBranch` distinguishes a new branch from an existing branch checkout,
786
+ * allowing API clients to accurately describe what Git changed.
787
+ */
788
+ export type CreateWorktreeResult = {
789
+ worktreePath: string;
790
+ branch: string;
791
+ createdBranch: boolean;
792
+ };
793
+
794
+ /**
795
+ * Result of atomically creating and registering a worktree for project use.
796
+ *
797
+ * The Worktrees application service compensates the Git creation if project
798
+ * registration fails, so routes only receive this shape after both steps pass.
799
+ */
800
+ export type CreateAndOpenWorktreeResult = CreateWorktreeResult & {
801
+ project: WorktreeProjectView;
802
+ };
803
+
804
+ /**
805
+ * Input accepted when registering an existing worktree as a WindCli project.
806
+ *
807
+ * The service verifies that `worktreePath` belongs to the repository containing
808
+ * `projectPath` before it creates or restores any project record.
809
+ */
810
+ export type OpenWorktreeInput = {
811
+ projectPath: string;
812
+ worktreePath: string;
813
+ };
814
+
815
+ /**
816
+ * Project view returned after a worktree is opened in WindCli.
817
+ *
818
+ * This deliberately mirrors the project-selection payload used by the Projects
819
+ * module so the frontend can switch to the worktree without another lookup.
820
+ */
821
+ export type WorktreeProjectView = {
822
+ projectId: string;
823
+ path: string;
824
+ fullPath: string;
825
+ displayName: string;
826
+ isStarred: boolean;
827
+ sessions: [];
828
+ sessionMeta: { hasMore: false; total: 0 };
829
+ };
830
+
831
+ /**
832
+ * Input accepted when removing a linked Git worktree.
833
+ *
834
+ * `force` permits removal with local changes. `deleteBranch` requests
835
+ * best-effort branch cleanup after the worktree directory is removed.
836
+ */
837
+ export type RemoveWorktreeInput = {
838
+ projectPath: string;
839
+ worktreePath: string;
840
+ force?: boolean;
841
+ deleteBranch?: boolean;
842
+ };
843
+
844
+ /**
845
+ * Result of removing a linked Git worktree.
846
+ *
847
+ * `archivalError` reports best-effort project archival failure after Git has
848
+ * already removed the worktree, allowing callers to represent partial success.
849
+ */
850
+ export type RemoveWorktreeResult = {
851
+ removedPath: string;
852
+ branch: string | null;
853
+ branchDeleted: boolean;
854
+ archivedProjectId: string | null;
855
+ archivalError: string | null;
856
+ };
857
+
858
+ /**
859
+ * Input accepted when merging a linked worktree into the main worktree branch.
860
+ *
861
+ * The service verifies both worktrees are clean, supports squash and regular
862
+ * merges, and may remove the source worktree after a successful merge.
863
+ */
864
+ export type MergeWorktreeInput = {
865
+ projectPath: string;
866
+ worktreePath: string;
867
+ squash?: boolean;
868
+ message?: string | null;
869
+ removeAfterMerge?: boolean;
870
+ };
871
+
872
+ /**
873
+ * Result of a completed worktree merge.
874
+ *
875
+ * `removedWorktree` is populated only when post-merge removal succeeds.
876
+ * `cleanupError` reports failed optional removal without misrepresenting the
877
+ * already-completed merge as a failure.
878
+ */
879
+ export type MergeWorktreeResult = {
880
+ mergedBranch: string;
881
+ targetBranch: string;
882
+ squash: boolean;
883
+ removedWorktree: RemoveWorktreeResult | null;
884
+ cleanupError: string | null;
885
+ };
886
+
887
+ // ---------------------------
888
+ //----------------- WORKTREE MODULE DEPENDENCY CONTRACTS ------------
889
+ /**
890
+ * Filesystem capability required by the Worktrees module.
891
+ *
892
+ * Production wiring checks the real filesystem; unit tests provide a small
893
+ * deterministic fake so worktree creation never touches developer directories.
894
+ */
895
+ export type WorktreeFileSystem = {
896
+ pathExists(candidatePath: string): Promise<boolean>;
897
+ };
898
+
899
+ /**
900
+ * Project-management boundary consumed by Worktrees workflows.
901
+ *
902
+ * The Worktrees module uses this contract instead of importing Database or
903
+ * Projects internals. Production adapters delegate through those modules'
904
+ * `index.ts` barrels, while unit tests supply in-memory functions.
905
+ */
906
+ export type WorktreeProjectGateway = {
907
+ getProjectPathById(projectId: string): string | null;
908
+ getProjectByPath(projectPath: string): ProjectRepositoryRow | null;
909
+ createProject(input: {
910
+ projectPath: string;
911
+ customName: string;
912
+ }): Promise<{
913
+ outcome: 'created' | 'reactivated_archived';
914
+ project: { projectId: string };
915
+ }>;
916
+ restoreProject(projectId: string): void | Promise<void>;
917
+ archiveProject(projectId: string): void | Promise<void>;
918
+ };
919
+
920
+ /**
921
+ * Complete application-service surface used by the Worktrees HTTP router.
922
+ *
923
+ * Routes parse transport values and call these functions; they do not import
924
+ * repositories, filesystem adapters, Git runners, or individual service files.
925
+ */
926
+ export type WorktreeServices = {
927
+ resolveProjectPath(projectId: string): string;
928
+ list(input: ListWorktreesInput): Promise<WorktreeListResult>;
929
+ create(input: CreateWorktreeInput): Promise<CreateWorktreeResult>;
930
+ createAndOpen(input: CreateWorktreeInput): Promise<CreateAndOpenWorktreeResult>;
931
+ open(input: OpenWorktreeInput): Promise<WorktreeProjectView>;
932
+ merge(input: MergeWorktreeInput): Promise<MergeWorktreeResult>;
933
+ remove(input: RemoveWorktreeInput): Promise<RemoveWorktreeResult>;
934
+ };
935
+
936
+ // ---------------------------
937
+ //----------------- FILE TREE MODULE CONTRACTS ------------
938
+ /**
939
+ * One filesystem item returned by the File Tree API.
940
+ *
941
+ * The service populates metadata without following symlinks and recursively
942
+ * attaches `children` only while the requested depth permits traversal. The
943
+ * frontend uses the absolute `path` as the stable identifier for editor and
944
+ * file-operation requests.
945
+ */
946
+ export type FileTreeNode = {
947
+ name: string;
948
+ path: string;
949
+ type: 'file' | 'directory';
950
+ size: number;
951
+ modified: string | null;
952
+ permissions: string;
953
+ permissionsRwx: string;
954
+ isSymlink?: boolean;
955
+ children?: FileTreeNode[];
956
+ };
957
+
958
+ /**
959
+ * Minimal directory-entry shape required during File Tree traversal.
960
+ *
961
+ * Production adapts Node `Dirent` objects to this structural contract. Tests
962
+ * provide small handwritten entries and therefore never read real directories.
963
+ */
964
+ export type FileTreeDirectoryEntry = {
965
+ name: string;
966
+ isDirectory(): boolean;
967
+ };
968
+
969
+ /**
970
+ * Minimal file-stat shape used for tree metadata and delete decisions.
971
+ *
972
+ * The numeric mode is converted to octal and rwx strings for the UI. `lstat`
973
+ * supplies symlink state while `stat` is used when deciding file versus folder
974
+ * deletion behavior.
975
+ */
976
+ export type FileTreeStats = {
977
+ size: number;
978
+ mtime: Date;
979
+ mode: number;
980
+ isDirectory(): boolean;
981
+ isSymbolicLink(): boolean;
982
+ };
983
+
984
+ /**
985
+ * Complete filesystem capability injected into File Tree services.
986
+ *
987
+ * The production composition root delegates these operations to Node's fs
988
+ * APIs. Unit tests provide deterministic path-keyed fakes so service tests
989
+ * cannot inspect, write, rename, or delete developer files.
990
+ */
991
+ export type FileTreeFileSystem = {
992
+ access(candidatePath: string): Promise<void>;
993
+ stat(candidatePath: string): Promise<FileTreeStats>;
994
+ lstat(candidatePath: string): Promise<FileTreeStats>;
995
+ // Streamed rather than returned as an array so a directory with millions of
996
+ // children is abandoned at the entry limit instead of being materialized.
997
+ openDirectory(directoryPath: string): AsyncIterable<FileTreeDirectoryEntry>;
998
+ realpath(candidatePath: string): Promise<string>;
999
+ readTextFile(filePath: string): Promise<string>;
1000
+ writeTextFile(filePath: string, content: string): Promise<void>;
1001
+ makeDirectory(directoryPath: string, recursive: boolean): Promise<void>;
1002
+ rename(oldPath: string, newPath: string): Promise<void>;
1003
+ removeDirectory(directoryPath: string): Promise<void>;
1004
+ unlink(filePath: string): Promise<void>;
1005
+ copyFile(sourcePath: string, destinationPath: string): Promise<void>;
1006
+ createReadStream(filePath: string): Readable;
1007
+ };
1008
+
1009
+ /**
1010
+ * Project lookup boundary consumed by File Tree workflows.
1011
+ *
1012
+ * File Tree services resolve DB-assigned project ids through this contract and
1013
+ * never import the Database module or its repositories directly.
1014
+ */
1015
+ export type FileTreeProjectGateway = {
1016
+ getProjectPathById(projectId: string): string | null | Promise<string | null>;
1017
+ };
1018
+
1019
+ /**
1020
+ * Workspace validation boundary used by filesystem browsing and folder creation.
1021
+ *
1022
+ * The injected validator enforces the configured workspace root and resolves
1023
+ * symlinks before the File Tree service exposes or mutates paths.
1024
+ */
1025
+ export type FileTreeWorkspaceGateway = {
1026
+ rootPath: string;
1027
+ validatePath(candidatePath: string): Promise<WorkspacePathValidationResult>;
1028
+ };
1029
+
1030
+ /**
1031
+ * Uploaded-file record passed from the Multer transport adapter into the File
1032
+ * Tree service.
1033
+ *
1034
+ * Transport-specific field names are normalized so upload workflows do not
1035
+ * depend on Express or Multer types.
1036
+ */
1037
+ export type FileTreeUploadedFile = {
1038
+ originalName: string;
1039
+ temporaryPath: string;
1040
+ size: number;
1041
+ mimeType: string;
1042
+ };
1043
+
1044
+ /**
1045
+ * Logger boundary for expected File Tree diagnostics.
1046
+ *
1047
+ * Production delegates to the server console. Unit tests use no-op or captured
1048
+ * loggers and never patch the global console singleton.
1049
+ */
1050
+ export type FileTreeLogger = {
1051
+ error(message: string, error?: unknown): void;
1052
+ };
1053
+
1054
+ /**
1055
+ * Required production dependencies for the File Tree application service.
1056
+ *
1057
+ * Filesystem, project lookup, workspace policy, MIME detection, concurrency,
1058
+ * and logging are all explicit so service construction has no hidden process,
1059
+ * repository, or machine-wide defaults.
1060
+ */
1061
+ export type FileTreeServiceDependencies = {
1062
+ fileSystem: FileTreeFileSystem;
1063
+ projects: FileTreeProjectGateway;
1064
+ workspace: FileTreeWorkspaceGateway;
1065
+ resolveMimeType(filePath: string): string;
1066
+ fileSystemConcurrency: number;
1067
+ logger: FileTreeLogger;
1068
+ };
1069
+
1070
+ /**
1071
+ * Complete File Tree application-service surface consumed by HTTP routes.
1072
+ *
1073
+ * Routes parse transport inputs and call these methods; they never resolve
1074
+ * project repositories, validate filesystem ownership, or perform filesystem
1075
+ * mutations themselves.
1076
+ */
1077
+ export type FileTreeServices = {
1078
+ browseWorkspace(inputPath: string | null): Promise<{
1079
+ path: string;
1080
+ suggestions: Array<{ path: string; name: string; type: 'directory' }>;
1081
+ }>;
1082
+ createWorkspaceFolder(folderPath: string): Promise<{ success: true; path: string }>;
1083
+ readTextFile(projectId: string, filePath: string): Promise<{ content: string; path: string }>;
1084
+ openFile(projectId: string, filePath: string): Promise<{ contentType: string; stream: Readable }>;
1085
+ saveTextFile(projectId: string, filePath: string, content: string): Promise<{
1086
+ success: true;
1087
+ path: string;
1088
+ message: string;
1089
+ }>;
1090
+ listProjectFiles(
1091
+ projectId: string,
1092
+ options?: { respectGitignore: boolean },
1093
+ ): Promise<FileTreeNode[]>;
1094
+ createEntry(input: {
1095
+ projectId: string;
1096
+ parentPath: string;
1097
+ type: 'file' | 'directory';
1098
+ name: string;
1099
+ }): Promise<{ success: true; path: string; name: string; type: 'file' | 'directory'; message: string }>;
1100
+ renameEntry(input: { projectId: string; oldPath: string; newName: string }): Promise<{
1101
+ success: true;
1102
+ oldPath: string;
1103
+ newPath: string;
1104
+ newName: string;
1105
+ message: string;
1106
+ }>;
1107
+ deleteEntry(input: { projectId: string; targetPath: string }): Promise<{
1108
+ success: true;
1109
+ path: string;
1110
+ type: 'file' | 'directory';
1111
+ message: string;
1112
+ }>;
1113
+ storeUploadedFiles(input: {
1114
+ projectId: string;
1115
+ targetPath: string;
1116
+ relativePaths: string[];
1117
+ requestedFileCount: number;
1118
+ files: FileTreeUploadedFile[];
1119
+ }): Promise<{
1120
+ success: true;
1121
+ files: Array<{ name: string; path: string; size: number; mimeType: string }>;
1122
+ uploadedCount: number;
1123
+ requestedFileCount: number;
1124
+ targetPath: string;
1125
+ message: string;
1126
+ }>;
1127
+ };
1128
+
1129
+ // ---------------------------
1130
+ //----------------- VOICE MODULE CONTRACTS ------------
1131
+ /**
1132
+ * Per-request voice settings parsed from authenticated HTTP headers.
1133
+ *
1134
+ * The Voice routes create this value from the optional `x-voice-*` headers and
1135
+ * pass it to the Voice service. Empty values mean "use the server-configured
1136
+ * default"; the backend base URL is intentionally absent because clients must
1137
+ * never control the server's outbound destination.
1138
+ */
1139
+ export type VoiceRequestOverrides = {
1140
+ apiKey?: string;
1141
+ sttModel?: string;
1142
+ ttsModel?: string;
1143
+ ttsVoice?: string;
1144
+ ttsFormat?: string;
1145
+ };
1146
+
1147
+ /**
1148
+ * Uploaded audio accepted by the Voice transcription service.
1149
+ *
1150
+ * Routes translate Multer's transport-specific file object into this minimal
1151
+ * shape so the service does not depend on Express or Multer types.
1152
+ */
1153
+ export type VoiceAudioUpload = {
1154
+ bytes: Buffer;
1155
+ mimeType: string;
1156
+ fileName: string;
1157
+ };
1158
+
1159
+ /**
1160
+ * Successful speech payload returned by the Voice service.
1161
+ *
1162
+ * The route copies `contentType` to the client response and pipes `body`
1163
+ * without buffering the complete synthesized audio in application memory.
1164
+ */
1165
+ export type VoiceSpeechPayload = {
1166
+ contentType: string;
1167
+ body: ReadableStream<Uint8Array> | null;
1168
+ };
1169
+
1170
+ /**
1171
+ * Explicit service result used by Voice routes instead of transport-aware
1172
+ * exceptions.
1173
+ *
1174
+ * Services return `ok: false` with the exact client status/message for expected
1175
+ * backend, validation, and timeout failures. Routes only translate the result
1176
+ * into HTTP output, while unexpected programming errors still reject normally.
1177
+ */
1178
+ export type VoiceServiceResult<TValue> =
1179
+ | { ok: true; value: TValue }
1180
+ | { ok: false; status: number; error: string };
1181
+
1182
+ /**
1183
+ * Complete application-service surface consumed by the Voice HTTP router.
1184
+ *
1185
+ * The composition root supplies a concrete implementation with environment
1186
+ * configuration and an injected outbound HTTP adapter. Unit tests use the same
1187
+ * contract with handwritten fetch fakes and never patch global state.
1188
+ */
1189
+ export type VoiceService = {
1190
+ getHealth(): { configured: boolean };
1191
+ transcribe(input: {
1192
+ audio: VoiceAudioUpload;
1193
+ overrides: VoiceRequestOverrides;
1194
+ }): Promise<VoiceServiceResult<{ text: string }>>;
1195
+ synthesizeSpeech(input: {
1196
+ text: string;
1197
+ overrides: VoiceRequestOverrides;
1198
+ }): Promise<VoiceServiceResult<VoiceSpeechPayload>>;
1199
+ };
1200
+
1201
+ // ---------------------------
1202
+ //----------------- CLI MODULE CONTRACTS ------------
1203
+ /**
1204
+ * Output boundary used by the CLI and Sandbox services.
1205
+ *
1206
+ * Production wiring delegates to the real console. Unit tests collect these
1207
+ * calls in arrays, which keeps command assertions deterministic and avoids
1208
+ * monkey-patching the global console singleton.
1209
+ */
1210
+ export type CliOutput = {
1211
+ log(message?: string): void;
1212
+ error(message?: string): void;
1213
+ };
1214
+
1215
+ /**
1216
+ * Minimal synchronous filesystem surface shared by CLI status reporting and
1217
+ * sandbox workspace validation.
1218
+ *
1219
+ * The production composition root adapts Node's filesystem module. Tests supply
1220
+ * path-keyed fakes, so service tests never inspect or modify the real machine.
1221
+ */
1222
+ export type CliFileSystem = {
1223
+ pathExists(filePath: string): boolean;
1224
+ getFileStats(filePath: string): { size: number; modifiedAt: Date };
1225
+ };
1226
+
1227
+ /**
1228
+ * Mutable environment view owned by the CLI application.
1229
+ *
1230
+ * CLI options update this object before the server starts. Production passes
1231
+ * `process.env`; tests pass a plain record to verify option precedence without
1232
+ * changing process-wide environment state.
1233
+ */
1234
+ export type CliEnvironment = Record<string, string | undefined>;
1235
+
1236
+ /**
1237
+ * Package metadata displayed by CLI help, status, version, and update commands.
1238
+ *
1239
+ * The composition root reads this once from the application package file and
1240
+ * injects only the fields the service needs.
1241
+ */
1242
+ export type CliPackageMetadata = {
1243
+ version: string;
1244
+ homepage?: string;
1245
+ bugsUrl?: string;
1246
+ };
1247
+
1248
+ /**
1249
+ * Executable CLI application returned by the CLI composition root.
1250
+ *
1251
+ * The thin executable entrypoint passes `process.argv` arguments to `run` and
1252
+ * copies the returned code to `process.exitCode`. Tests invoke the same method
1253
+ * directly with isolated dependencies.
1254
+ */
1255
+ export type CliApplication = {
1256
+ run(argumentsList: string[]): Promise<number>;
1257
+ };
1258
+
1259
+ /**
1260
+ * Sandbox command service consumed by the top-level CLI command dispatcher.
1261
+ *
1262
+ * Keeping this behind one required dependency lets CLI tests use a tiny fake,
1263
+ * while focused Sandbox tests exercise subprocess and filesystem behavior with
1264
+ * their own handwritten adapters.
1265
+ */
1266
+ export type SandboxCommandService = {
1267
+ execute(argumentsList: string[]): Promise<number>;
1268
+ };