circuschief 0.1.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 (319) hide show
  1. package/package.json +33 -0
  2. package/packages/server/bin/cli.js +4 -0
  3. package/packages/server/src/agents/AgentGateway.js +64 -0
  4. package/packages/server/src/agents/BaseAgent.js +41 -0
  5. package/packages/server/src/agents/LoggingAgentWrapper.js +73 -0
  6. package/packages/server/src/agents/adapters/ClaudeCodeAdapter.js +33 -0
  7. package/packages/server/src/agents/adapters/CodexAdapter.js +26 -0
  8. package/packages/server/src/agents/types.js +43 -0
  9. package/packages/server/src/agents/vcr/CassetteStore.js +111 -0
  10. package/packages/server/src/agents/vcr/VCRAgentAdapter.js +126 -0
  11. package/packages/server/src/agents/vcr/VCRSummaryWrapper.js +71 -0
  12. package/packages/server/src/api/canvas-helpers.js +249 -0
  13. package/packages/server/src/api/canvas-trash-routes.js +205 -0
  14. package/packages/server/src/api/canvas.js +331 -0
  15. package/packages/server/src/api/commandButtons.js +312 -0
  16. package/packages/server/src/api/commands.js +169 -0
  17. package/packages/server/src/api/filesystem.js +62 -0
  18. package/packages/server/src/api/git.js +85 -0
  19. package/packages/server/src/api/index.js +44 -0
  20. package/packages/server/src/api/kanban.js +342 -0
  21. package/packages/server/src/api/metrics.js +194 -0
  22. package/packages/server/src/api/projects-helpers.js +43 -0
  23. package/packages/server/src/api/projects-session-helpers.js +295 -0
  24. package/packages/server/src/api/projects.js +384 -0
  25. package/packages/server/src/api/providers.js +249 -0
  26. package/packages/server/src/api/quickResponses.js +129 -0
  27. package/packages/server/src/api/sessions-archive.js +69 -0
  28. package/packages/server/src/api/sessions-commands.js +220 -0
  29. package/packages/server/src/api/sessions-conversations.js +168 -0
  30. package/packages/server/src/api/sessions-draft.js +72 -0
  31. package/packages/server/src/api/sessions-lifecycle.js +190 -0
  32. package/packages/server/src/api/sessions-messages.js +141 -0
  33. package/packages/server/src/api/sessions-notes.js +51 -0
  34. package/packages/server/src/api/sessions-patch.js +252 -0
  35. package/packages/server/src/api/sessions-streaming.js +86 -0
  36. package/packages/server/src/api/sessions.js +269 -0
  37. package/packages/server/src/api/settings.js +194 -0
  38. package/packages/server/src/api/templates.js +63 -0
  39. package/packages/server/src/app.js +51 -0
  40. package/packages/server/src/database.js +58 -0
  41. package/packages/server/src/db/AgentCallLogRepository.js +322 -0
  42. package/packages/server/src/db/AttachmentRepository.js +191 -0
  43. package/packages/server/src/db/BaseRepository.js +39 -0
  44. package/packages/server/src/db/CanvasItemRepository.js +315 -0
  45. package/packages/server/src/db/CommandButtonRepository.js +75 -0
  46. package/packages/server/src/db/CommandRunRepository.js +219 -0
  47. package/packages/server/src/db/ConversationRepository.js +379 -0
  48. package/packages/server/src/db/DatabaseManager.js +91 -0
  49. package/packages/server/src/db/KanbanBoardRepository.js +92 -0
  50. package/packages/server/src/db/KanbanCardRepository.js +286 -0
  51. package/packages/server/src/db/KanbanLaneRepository.js +279 -0
  52. package/packages/server/src/db/MessageRepository.js +156 -0
  53. package/packages/server/src/db/ProjectDefaultsRepository.js +173 -0
  54. package/packages/server/src/db/ProjectRepository.js +110 -0
  55. package/packages/server/src/db/ProviderRepository.js +307 -0
  56. package/packages/server/src/db/QuickResponseRepository.js +186 -0
  57. package/packages/server/src/db/SessionNoteRepository.js +60 -0
  58. package/packages/server/src/db/SessionRepository.js +314 -0
  59. package/packages/server/src/db/SessionSummaryRepository.js +200 -0
  60. package/packages/server/src/db/SessionTemplateRepository.js +171 -0
  61. package/packages/server/src/db/SettingsRepository.js +211 -0
  62. package/packages/server/src/db/TodoRepository.js +132 -0
  63. package/packages/server/src/db/WorkLogRepository.js +122 -0
  64. package/packages/server/src/db/conversation-helpers.js +119 -0
  65. package/packages/server/src/db/index.js +100 -0
  66. package/packages/server/src/db/migrations/canvasItemsMigrations.js +109 -0
  67. package/packages/server/src/db/migrations/conversationsMigrations.js +183 -0
  68. package/packages/server/src/db/migrations/index.js +199 -0
  69. package/packages/server/src/db/migrations/kanbanMigrations.js +99 -0
  70. package/packages/server/src/db/migrations/migrationUtils.js +55 -0
  71. package/packages/server/src/db/migrations/miscMigrations.js +242 -0
  72. package/packages/server/src/db/migrations/projectsMigrations.js +95 -0
  73. package/packages/server/src/db/migrations/sessionsMigrations.js +282 -0
  74. package/packages/server/src/db/session-helpers.js +150 -0
  75. package/packages/server/src/index.js +106 -0
  76. package/packages/server/src/logger.js +22 -0
  77. package/packages/server/src/middleware/sessionLookup.js +57 -0
  78. package/packages/server/src/middleware/upload.js +94 -0
  79. package/packages/server/src/schema.sql +363 -0
  80. package/packages/server/src/services/agentCallLogger.js +116 -0
  81. package/packages/server/src/services/canvasStore.js +56 -0
  82. package/packages/server/src/services/childSessionContext.js +61 -0
  83. package/packages/server/src/services/commandRunner.js +422 -0
  84. package/packages/server/src/services/conversationContext.js +72 -0
  85. package/packages/server/src/services/diffService.js +172 -0
  86. package/packages/server/src/services/draftSessionService.js +181 -0
  87. package/packages/server/src/services/encryption.js +134 -0
  88. package/packages/server/src/services/ghService.js +169 -0
  89. package/packages/server/src/services/gitService.js +520 -0
  90. package/packages/server/src/services/gitSessionSetup.js +48 -0
  91. package/packages/server/src/services/hookService.js +60 -0
  92. package/packages/server/src/services/kanbanService.js +262 -0
  93. package/packages/server/src/services/kanbanTriggers.js +273 -0
  94. package/packages/server/src/services/nodeSpawnHelper.js +63 -0
  95. package/packages/server/src/services/prStatusService.js +204 -0
  96. package/packages/server/src/services/prUrlService.js +224 -0
  97. package/packages/server/src/services/providerTestService.js +81 -0
  98. package/packages/server/src/services/scheduleService.js +110 -0
  99. package/packages/server/src/services/schedulerService.js +281 -0
  100. package/packages/server/src/services/sessionDuplicator.js +63 -0
  101. package/packages/server/src/services/sessionErrors.js +173 -0
  102. package/packages/server/src/services/sessionExecution.js +378 -0
  103. package/packages/server/src/services/sessionManager.js +356 -0
  104. package/packages/server/src/services/sessionPrompts.js +427 -0
  105. package/packages/server/src/services/sessionProvider.js +107 -0
  106. package/packages/server/src/services/slashCommandDiscovery.js +258 -0
  107. package/packages/server/src/services/slashCommandPluginDiscovery.js +216 -0
  108. package/packages/server/src/services/slashCommandService.js +306 -0
  109. package/packages/server/src/services/streamEventCallbacks.js +170 -0
  110. package/packages/server/src/services/streamEventHandler.js +488 -0
  111. package/packages/server/src/services/streamUsageHandler.js +228 -0
  112. package/packages/server/src/services/summaryBroadcast.js +61 -0
  113. package/packages/server/src/services/summaryClaudeClient.js +180 -0
  114. package/packages/server/src/services/summaryPrompts.js +169 -0
  115. package/packages/server/src/services/summaryService.js +552 -0
  116. package/packages/server/src/services/summaryStaleCheck.js +35 -0
  117. package/packages/server/src/services/systemMonitor.js +281 -0
  118. package/packages/server/src/services/templateTriggerService.js +197 -0
  119. package/packages/server/src/services/terminalOutput.js +160 -0
  120. package/packages/server/src/services/todoStore.js +58 -0
  121. package/packages/server/src/services/usageTracker.js +69 -0
  122. package/packages/server/src/services/withConcurrencyGuard.js +110 -0
  123. package/packages/server/src/websocket.js +10 -0
  124. package/packages/server/src/ws/WebSocketManager.js +240 -0
  125. package/packages/server/src/ws/index.js +50 -0
  126. package/packages/shared/package.json +27 -0
  127. package/packages/shared/src/constants.js +44 -0
  128. package/packages/shared/src/contracts/canvas.js +25 -0
  129. package/packages/shared/src/contracts/commandButtons.js +36 -0
  130. package/packages/shared/src/contracts/kanban.js +142 -0
  131. package/packages/shared/src/contracts/projects.js +63 -0
  132. package/packages/shared/src/contracts/providers.js +81 -0
  133. package/packages/shared/src/contracts/quickResponses.js +44 -0
  134. package/packages/shared/src/contracts/sessions.js +112 -0
  135. package/packages/shared/src/contracts/templates.js +51 -0
  136. package/packages/shared/src/index.js +5 -0
  137. package/packages/shared/src/protocol.js +76 -0
  138. package/packages/shared/src/routeParams.js +36 -0
  139. package/packages/shared/src/types.js +167 -0
  140. package/packages/shared/src/utils.js +101 -0
  141. package/packages/web/dist/assets/ActiveSessionsView-BQc76Jc8.js +1 -0
  142. package/packages/web/dist/assets/ActiveSessionsView-ofSvx-K1.css +1 -0
  143. package/packages/web/dist/assets/AgentLogsView-CTCjHjsu.js +2 -0
  144. package/packages/web/dist/assets/AgentLogsView-D90PnQVk.css +1 -0
  145. package/packages/web/dist/assets/ApiClient-Dbs1H78V.js +1 -0
  146. package/packages/web/dist/assets/ArchiveConfirmModal-CCxSZ52u.js +1 -0
  147. package/packages/web/dist/assets/ArchiveConfirmModal-CQZeuYBz.css +1 -0
  148. package/packages/web/dist/assets/CommandButtonDetailView-CF_-LXpU.js +1 -0
  149. package/packages/web/dist/assets/CommandButtonDetailView-DBm3rzhw.css +1 -0
  150. package/packages/web/dist/assets/EffortLevelSelector-BQaQmU2d.css +1 -0
  151. package/packages/web/dist/assets/EffortLevelSelector-DPofLvm-.js +1 -0
  152. package/packages/web/dist/assets/GeneralSettingsView-BCf53fpC.css +1 -0
  153. package/packages/web/dist/assets/GeneralSettingsView-BY1G-Kv8.js +1 -0
  154. package/packages/web/dist/assets/InterpolationHelp-CgdbNcJB.js +1 -0
  155. package/packages/web/dist/assets/InterpolationHelp-iNxTxmhs.css +1 -0
  156. package/packages/web/dist/assets/MarkdownEditor-CqT1U8lo.js +2 -0
  157. package/packages/web/dist/assets/MarkdownEditor-enuH2yvP.css +1 -0
  158. package/packages/web/dist/assets/ModelSelector-BBn_Ve0D.js +1 -0
  159. package/packages/web/dist/assets/ModelSelector-DPPD-92R.css +1 -0
  160. package/packages/web/dist/assets/NewSessionView-Bo5l49nu.js +3 -0
  161. package/packages/web/dist/assets/NewSessionView-Byoi1XdQ.css +1 -0
  162. package/packages/web/dist/assets/PathChooser-BoMGzeg2.css +1 -0
  163. package/packages/web/dist/assets/PathChooser-Cx9gQ-Qt.js +1 -0
  164. package/packages/web/dist/assets/ProjectEditView-BFuscj-V.js +1 -0
  165. package/packages/web/dist/assets/ProjectEditView-DNwBUNRk.css +1 -0
  166. package/packages/web/dist/assets/ProjectListView-C55H1JHQ.css +1 -0
  167. package/packages/web/dist/assets/ProjectListView-Dj0jBZ46.js +1 -0
  168. package/packages/web/dist/assets/ProjectNewView-Brdp-xUu.js +1 -0
  169. package/packages/web/dist/assets/ProjectNewView-CpgE4R-l.css +1 -0
  170. package/packages/web/dist/assets/ProvidersView-B_QQF3RM.css +1 -0
  171. package/packages/web/dist/assets/ProvidersView-Cxc-1skq.js +1 -0
  172. package/packages/web/dist/assets/QuickResponseSettings-B2eVAtHW.js +1 -0
  173. package/packages/web/dist/assets/QuickResponseSettings-B8188A1D.css +1 -0
  174. package/packages/web/dist/assets/QuickResponsesPanel-DIBQFj0W.css +1 -0
  175. package/packages/web/dist/assets/QuickResponsesPanel-lU8pW2B0.js +1 -0
  176. package/packages/web/dist/assets/ResizableTextarea-B5nAA0RV.css +1 -0
  177. package/packages/web/dist/assets/ResizableTextarea-DSy1mWGY.js +1 -0
  178. package/packages/web/dist/assets/SessionCard-BvjLwVYg.js +1 -0
  179. package/packages/web/dist/assets/SessionCard-D20G3bX8.css +1 -0
  180. package/packages/web/dist/assets/SessionDetailView-BQbPg-RJ.js +36 -0
  181. package/packages/web/dist/assets/SessionDetailView-BrMG4p2-.css +1 -0
  182. package/packages/web/dist/assets/SessionFormOptions-BgqFR-5f.js +1 -0
  183. package/packages/web/dist/assets/SessionFormOptions-BuLlDF-7.css +1 -0
  184. package/packages/web/dist/assets/SessionListView-BAIBtJF7.css +1 -0
  185. package/packages/web/dist/assets/SessionListView-CYIHI8qF.js +1 -0
  186. package/packages/web/dist/assets/SessionLogStream-B-FwUMJQ.js +18 -0
  187. package/packages/web/dist/assets/SessionLogStream-zPUTiGbe.css +1 -0
  188. package/packages/web/dist/assets/SettingsView-DC8-hTQ-.css +1 -0
  189. package/packages/web/dist/assets/SettingsView-fZxpiGp7.js +1 -0
  190. package/packages/web/dist/assets/SlashCommandWizard-BB30cSvo.css +1 -0
  191. package/packages/web/dist/assets/SlashCommandWizard-BgaOw9W3.js +1 -0
  192. package/packages/web/dist/assets/SummarySettingsView-DcsmSVJI.css +1 -0
  193. package/packages/web/dist/assets/SummarySettingsView-eeu1Xq86.js +1 -0
  194. package/packages/web/dist/assets/TemplateDetailView-DEPKSwDo.js +1 -0
  195. package/packages/web/dist/assets/TemplateDetailView-DT2m06W7.css +1 -0
  196. package/packages/web/dist/assets/apl-B4CMkyY2.js +1 -0
  197. package/packages/web/dist/assets/asciiarmor-Df11BRmG.js +1 -0
  198. package/packages/web/dist/assets/asn1-EdZsLKOL.js +1 -0
  199. package/packages/web/dist/assets/asterisk-B-8jnY81.js +1 -0
  200. package/packages/web/dist/assets/brainfuck-C4LP7Hcl.js +1 -0
  201. package/packages/web/dist/assets/clike-B9uivgTg.js +1 -0
  202. package/packages/web/dist/assets/clojure-BMjYHr_A.js +1 -0
  203. package/packages/web/dist/assets/cmake-BQqOBYOt.js +1 -0
  204. package/packages/web/dist/assets/cobol-CWcv1MsR.js +1 -0
  205. package/packages/web/dist/assets/coffeescript-S37ZYGWr.js +1 -0
  206. package/packages/web/dist/assets/commandButtons-DNSHH8IA.js +4 -0
  207. package/packages/web/dist/assets/commonlisp-DBKNyK5s.js +1 -0
  208. package/packages/web/dist/assets/crystal-SjHAIU92.js +1 -0
  209. package/packages/web/dist/assets/css-BnMrqG3P.js +1 -0
  210. package/packages/web/dist/assets/cypher-C_CwsFkJ.js +1 -0
  211. package/packages/web/dist/assets/d-pRatUO7H.js +1 -0
  212. package/packages/web/dist/assets/diff-DbItnlRl.js +1 -0
  213. package/packages/web/dist/assets/dockerfile-BKs6k2Af.js +1 -0
  214. package/packages/web/dist/assets/dtd-DF_7sFjM.js +1 -0
  215. package/packages/web/dist/assets/dylan-DwRh75JA.js +1 -0
  216. package/packages/web/dist/assets/ebnf-CDyGwa7X.js +1 -0
  217. package/packages/web/dist/assets/ecl-Cabwm37j.js +1 -0
  218. package/packages/web/dist/assets/eiffel-CnydiIhH.js +1 -0
  219. package/packages/web/dist/assets/elm-vLlmbW-K.js +1 -0
  220. package/packages/web/dist/assets/erlang-BNw1qcRV.js +1 -0
  221. package/packages/web/dist/assets/factor-kuTfRLto.js +1 -0
  222. package/packages/web/dist/assets/fcl-Kvtd6kyn.js +1 -0
  223. package/packages/web/dist/assets/forth-Ffai-XNe.js +1 -0
  224. package/packages/web/dist/assets/fortran-DYz_wnZ1.js +1 -0
  225. package/packages/web/dist/assets/gas-Bneqetm1.js +1 -0
  226. package/packages/web/dist/assets/gherkin-heZmZLOM.js +1 -0
  227. package/packages/web/dist/assets/groovy-D9Dt4D0W.js +1 -0
  228. package/packages/web/dist/assets/haskell-BWDZoCOh.js +1 -0
  229. package/packages/web/dist/assets/haxe-H-WmDvRZ.js +1 -0
  230. package/packages/web/dist/assets/http-DBlCnlav.js +1 -0
  231. package/packages/web/dist/assets/idl-BEugSyMb.js +1 -0
  232. package/packages/web/dist/assets/index-BZlHgDSz.js +1 -0
  233. package/packages/web/dist/assets/index-BhWX8AfE.js +2 -0
  234. package/packages/web/dist/assets/index-Bi3XvF_f.js +1 -0
  235. package/packages/web/dist/assets/index-BqXoPf_D.js +1 -0
  236. package/packages/web/dist/assets/index-CAuTOZSD.js +1 -0
  237. package/packages/web/dist/assets/index-CKYk-fkb.js +1 -0
  238. package/packages/web/dist/assets/index-CTumW_tV.js +318 -0
  239. package/packages/web/dist/assets/index-CVOJVSsC.js +82 -0
  240. package/packages/web/dist/assets/index-CXK2Z3_z.js +1 -0
  241. package/packages/web/dist/assets/index-CYllQ3Vd.js +1 -0
  242. package/packages/web/dist/assets/index-CpsfI08O.js +1 -0
  243. package/packages/web/dist/assets/index-DQkhDeTA.js +3 -0
  244. package/packages/web/dist/assets/index-DWP8iCBp.js +1 -0
  245. package/packages/web/dist/assets/index-DkVb9W_J.js +1 -0
  246. package/packages/web/dist/assets/index-DmKHPbIa.js +1 -0
  247. package/packages/web/dist/assets/index-DrlQi03X.js +1 -0
  248. package/packages/web/dist/assets/index-gmCCsCQ1.css +1 -0
  249. package/packages/web/dist/assets/index-prTEzzgO.js +1 -0
  250. package/packages/web/dist/assets/index-wqgejMCM.js +1 -0
  251. package/packages/web/dist/assets/index-yh0ZHIWw.js +7 -0
  252. package/packages/web/dist/assets/javascript-qCveANmP.js +1 -0
  253. package/packages/web/dist/assets/julia-DuME0IfC.js +1 -0
  254. package/packages/web/dist/assets/livescript-BwQOo05w.js +1 -0
  255. package/packages/web/dist/assets/lua-BgMRiT3U.js +1 -0
  256. package/packages/web/dist/assets/mathematica-DTrFuWx2.js +1 -0
  257. package/packages/web/dist/assets/mbox-CNhZ1qSd.js +1 -0
  258. package/packages/web/dist/assets/mirc-CjQqDB4T.js +1 -0
  259. package/packages/web/dist/assets/mllike-CXdrOF99.js +1 -0
  260. package/packages/web/dist/assets/modelica-Dc1JOy9r.js +1 -0
  261. package/packages/web/dist/assets/mscgen-BA5vi2Kp.js +1 -0
  262. package/packages/web/dist/assets/mumps-BT43cFF4.js +1 -0
  263. package/packages/web/dist/assets/nginx-DdIZxoE0.js +1 -0
  264. package/packages/web/dist/assets/nsis-LdVXkNf5.js +1 -0
  265. package/packages/web/dist/assets/ntriples-BfvgReVJ.js +1 -0
  266. package/packages/web/dist/assets/octave-Ck1zUtKM.js +1 -0
  267. package/packages/web/dist/assets/oz-BzwKVEFT.js +1 -0
  268. package/packages/web/dist/assets/pascal--L3eBynH.js +1 -0
  269. package/packages/web/dist/assets/perl-CdXCOZ3F.js +1 -0
  270. package/packages/web/dist/assets/pig-CevX1Tat.js +1 -0
  271. package/packages/web/dist/assets/powershell-CFHJl5sT.js +1 -0
  272. package/packages/web/dist/assets/projects-DbBQQH-V.js +1 -0
  273. package/packages/web/dist/assets/properties-C78fOPTZ.js +1 -0
  274. package/packages/web/dist/assets/protobuf-ChK-085T.js +1 -0
  275. package/packages/web/dist/assets/providers-ceCc4xRU.js +1 -0
  276. package/packages/web/dist/assets/pug-DukmZTjD.js +1 -0
  277. package/packages/web/dist/assets/puppet-DMA9R1ak.js +1 -0
  278. package/packages/web/dist/assets/python-BuPzkPfP.js +1 -0
  279. package/packages/web/dist/assets/q-pXgVlZs6.js +1 -0
  280. package/packages/web/dist/assets/r-DUYO_cvP.js +1 -0
  281. package/packages/web/dist/assets/rpm-CTu-6PCP.js +1 -0
  282. package/packages/web/dist/assets/ruby-B2Rjki9n.js +1 -0
  283. package/packages/web/dist/assets/sas-B4kiWyti.js +1 -0
  284. package/packages/web/dist/assets/scheme-C41bIUwD.js +1 -0
  285. package/packages/web/dist/assets/sessions-D681M81k.js +1 -0
  286. package/packages/web/dist/assets/settings-D0evez2V.js +1 -0
  287. package/packages/web/dist/assets/shell-CjFT_Tl9.js +1 -0
  288. package/packages/web/dist/assets/sieve-C3Gn_uJK.js +1 -0
  289. package/packages/web/dist/assets/simple-mode-GW_nhZxv.js +1 -0
  290. package/packages/web/dist/assets/smalltalk-CnHTOXQT.js +1 -0
  291. package/packages/web/dist/assets/solr-DehyRSwq.js +1 -0
  292. package/packages/web/dist/assets/sparql-DkYu6x3z.js +1 -0
  293. package/packages/web/dist/assets/spreadsheet-BCZA_wO0.js +1 -0
  294. package/packages/web/dist/assets/sql-D0XecflT.js +1 -0
  295. package/packages/web/dist/assets/stex-C3f8Ysf7.js +1 -0
  296. package/packages/web/dist/assets/style-BTin-zR_.css +1 -0
  297. package/packages/web/dist/assets/stylus-B533Al4x.js +1 -0
  298. package/packages/web/dist/assets/swift-BzpIVaGY.js +1 -0
  299. package/packages/web/dist/assets/tcl-DVfN8rqt.js +1 -0
  300. package/packages/web/dist/assets/textile-CnDTJFAw.js +1 -0
  301. package/packages/web/dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
  302. package/packages/web/dist/assets/tiki-DGYXhP31.js +1 -0
  303. package/packages/web/dist/assets/toml-Bm5Em-hy.js +1 -0
  304. package/packages/web/dist/assets/troff-wAsdV37c.js +1 -0
  305. package/packages/web/dist/assets/ttcn-CfJYG6tj.js +1 -0
  306. package/packages/web/dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  307. package/packages/web/dist/assets/turtle-B1tBg_DP.js +1 -0
  308. package/packages/web/dist/assets/vb-CmGdzxic.js +1 -0
  309. package/packages/web/dist/assets/vbscript-BuJXcnF6.js +1 -0
  310. package/packages/web/dist/assets/velocity-D8B20fx6.js +1 -0
  311. package/packages/web/dist/assets/verilog-C6RDOZhf.js +1 -0
  312. package/packages/web/dist/assets/vhdl-lSbBsy5d.js +1 -0
  313. package/packages/web/dist/assets/webidl-ZXfAyPTL.js +1 -0
  314. package/packages/web/dist/assets/xquery-CQfU5ijd.js +1 -0
  315. package/packages/web/dist/assets/yacas-BJ4BC0dw.js +1 -0
  316. package/packages/web/dist/assets/z80-Hz9HOZM7.js +1 -0
  317. package/packages/web/dist/favicon.png +0 -0
  318. package/packages/web/dist/index.html +17 -0
  319. package/packages/web/dist/logo.png +0 -0
@@ -0,0 +1,262 @@
1
+ import {
2
+ kanbanBoards,
3
+ kanbanLanes,
4
+ kanbanCards,
5
+ sessions,
6
+ sessionTemplates,
7
+ projects,
8
+ } from '../database.js';
9
+ import { broadcastToProject } from '../websocket.js';
10
+ import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
11
+ import { triggerOnEnterTemplate, triggerOnEnterPrompt } from './kanbanTriggers.js';
12
+
13
+ /**
14
+ * Helper to build full board response with lanes and cards
15
+ */
16
+ function buildFullBoardResponse(board) {
17
+ if (!board) return null;
18
+
19
+ const lanes = kanbanLanes.getByBoardId(board.id);
20
+ const allCards = kanbanCards.getByBoardId(board.id);
21
+
22
+ // Group cards by lane
23
+ const cardsByLane = {};
24
+ for (const lane of lanes) {
25
+ cardsByLane[lane.id] = [];
26
+ }
27
+ for (const card of allCards) {
28
+ if (cardsByLane[card.laneId]) {
29
+ cardsByLane[card.laneId].push(card);
30
+ }
31
+ }
32
+
33
+ return {
34
+ id: board.id,
35
+ projectId: board.projectId,
36
+ lanes: lanes.map((lane) => ({
37
+ ...lane,
38
+ cards: cardsByLane[lane.id] || [],
39
+ })),
40
+ createdAt: board.createdAt,
41
+ updatedAt: board.updatedAt,
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Get the full board with all lanes and cards for a project.
47
+ * Lazy-creates the board with default lanes if it doesn't exist.
48
+ *
49
+ * @param {string} projectId - The project ID
50
+ * @returns {Object|null} Full board with lanes and cards, or null if kanban is disabled
51
+ */
52
+ export function getFullBoard(projectId) {
53
+ const project = projects.getById(projectId);
54
+ if (!project) {
55
+ return null;
56
+ }
57
+
58
+ // If kanban is disabled, return null
59
+ if (!project.kanbanEnabled) {
60
+ return null;
61
+ }
62
+
63
+ const board = kanbanBoards.getOrCreateForProject(projectId);
64
+ return buildFullBoardResponse(board);
65
+ }
66
+
67
+ /**
68
+ * Add a session to the kanban board.
69
+ *
70
+ * @param {string} sessionId - The session ID
71
+ * @param {string} laneId - The lane to add the session to
72
+ * @param {Object} [options] - Options
73
+ * @param {number} [options.sortOrder] - Optional sort order
74
+ * @returns {Object} The created card
75
+ * @throws {Error} If session already has a card on the board
76
+ */
77
+ export function addSessionToBoard(sessionId, laneId, options = {}) {
78
+ // Check if session already has a card
79
+ const existingCard = kanbanCards.getBySessionId(sessionId);
80
+ if (existingCard) {
81
+ throw new Error('Session already has a card on the board');
82
+ }
83
+
84
+ const card = kanbanCards.create(laneId, sessionId, options);
85
+
86
+ // Get session to find project ID for broadcast
87
+ const session = sessions.getById(sessionId);
88
+ if (session) {
89
+ broadcastToProject(session.projectId, WS_MESSAGE_TYPES.KANBAN_CARD_ADDED, {
90
+ projectId: session.projectId,
91
+ card,
92
+ laneId,
93
+ });
94
+ }
95
+
96
+ return card;
97
+ }
98
+
99
+ /**
100
+ * Move a card to a different lane, optionally triggering the on-enter template.
101
+ *
102
+ * @param {string} cardId - The card ID
103
+ * @param {string} targetLaneId - The target lane ID
104
+ * @param {Object} [options] - Options
105
+ * @param {number} [options.sortOrder] - Optional sort order in target lane
106
+ * @param {boolean} [options.runOnEnterTemplate=true] - Whether to run the on-enter template
107
+ * @param {number} [options.depth=0] - Current recursion depth for template triggers
108
+ * @returns {Promise<Object>} The moved card
109
+ */
110
+ export async function moveCard(cardId, targetLaneId, options = {}) {
111
+ const { sortOrder, runOnEnterTemplate = true, depth = 0 } = options;
112
+
113
+ const card = kanbanCards.getByIdWithLane(cardId);
114
+ if (!card) {
115
+ throw new Error('Card not found');
116
+ }
117
+
118
+ const fromLaneId = card.laneId;
119
+
120
+ // Move the card
121
+ const movedCard = kanbanCards.moveToLane(cardId, targetLaneId, sortOrder);
122
+
123
+ // Get session for project ID and broadcast
124
+ const sessionId = card.sessions?.[0]?.id;
125
+ const session = sessionId ? sessions.getById(sessionId) : null;
126
+
127
+ if (session) {
128
+ broadcastToProject(session.projectId, WS_MESSAGE_TYPES.KANBAN_CARD_MOVED, {
129
+ projectId: session.projectId,
130
+ cardId,
131
+ fromLaneId,
132
+ toLaneId: targetLaneId,
133
+ card: movedCard,
134
+ });
135
+
136
+ // Trigger on-enter automation if configured (template or custom prompt)
137
+ if (runOnEnterTemplate) {
138
+ const targetLane = kanbanLanes.getByIdWithTemplate(targetLaneId);
139
+ if (targetLane?.onEnterTemplateId) {
140
+ await triggerOnEnterTemplate(sessionId, targetLane, { depth });
141
+ } else if (targetLane?.onEnterPrompt) {
142
+ await triggerOnEnterPrompt(sessionId, targetLane, { depth });
143
+ }
144
+ }
145
+ }
146
+
147
+ return movedCard;
148
+ }
149
+
150
+ /**
151
+ * Handle turn completion for a session.
152
+ * If the session has a target_lane_id set, move its card to that lane.
153
+ *
154
+ * @param {string} sessionId - The session that just completed its turn
155
+ */
156
+ export async function handleTurnCompletion(sessionId) {
157
+ const session = sessions.getById(sessionId);
158
+ if (!session) {
159
+ return;
160
+ }
161
+
162
+ // Check if session has a target lane
163
+ if (!session.targetLaneId) {
164
+ return;
165
+ }
166
+
167
+ console.log(
168
+ `Kanban: Handling turn completion for session ${sessionId}, target lane: ${session.targetLaneId}`
169
+ );
170
+
171
+ // Find or create the card for this session
172
+ let card = kanbanCards.getBySessionId(sessionId);
173
+
174
+ if (!card) {
175
+ // Session doesn't have a card yet, create one in the target lane
176
+ const lane = kanbanLanes.getById(session.targetLaneId);
177
+ if (!lane) {
178
+ console.warn(`Kanban: Target lane ${session.targetLaneId} not found for session ${sessionId}`);
179
+ // Clear the invalid target lane
180
+ sessions.update(sessionId, { targetLaneId: null });
181
+ return;
182
+ }
183
+
184
+ card = kanbanCards.create(session.targetLaneId, sessionId);
185
+
186
+ broadcastToProject(session.projectId, WS_MESSAGE_TYPES.KANBAN_CARD_ADDED, {
187
+ projectId: session.projectId,
188
+ card,
189
+ laneId: session.targetLaneId,
190
+ });
191
+ } else {
192
+ // Move existing card to target lane
193
+ const fromLaneId = card.laneId;
194
+
195
+ if (fromLaneId !== session.targetLaneId) {
196
+ await moveCard(card.id, session.targetLaneId, {
197
+ runOnEnterTemplate: true,
198
+ depth: session.laneTriggerDepth || 0,
199
+ });
200
+ }
201
+ }
202
+
203
+ // Clear the target lane now that we've processed it
204
+ sessions.update(sessionId, { targetLaneId: null });
205
+ }
206
+
207
+ /**
208
+ * Remove a session from the board (called when session is deleted).
209
+ *
210
+ * @param {string} sessionId - The session ID
211
+ */
212
+ export function removeSessionFromBoard(sessionId) {
213
+ const card = kanbanCards.getBySessionId(sessionId);
214
+ if (!card) {
215
+ return; // Session wasn't on the board
216
+ }
217
+
218
+ const laneId = card.laneId;
219
+ const session = sessions.getById(sessionId);
220
+ const projectId = session?.projectId;
221
+
222
+ kanbanCards.delete(card.id);
223
+
224
+ if (projectId) {
225
+ broadcastToProject(projectId, WS_MESSAGE_TYPES.KANBAN_CARD_REMOVED, {
226
+ projectId,
227
+ cardId: card.id,
228
+ laneId,
229
+ });
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Add a session to its template's target lane if configured.
235
+ * Called after session creation from a template.
236
+ *
237
+ * @param {string} sessionId - The newly created session ID
238
+ * @param {string} templateId - The template ID used to create the session
239
+ */
240
+ export function addSessionToTemplateTargetLane(sessionId, templateId) {
241
+ const template = sessionTemplates.getById(templateId);
242
+ if (!template?.targetLaneId) {
243
+ return;
244
+ }
245
+
246
+ const lane = kanbanLanes.getById(template.targetLaneId);
247
+ if (!lane) {
248
+ console.warn(
249
+ `Kanban: Template target lane ${template.targetLaneId} not found for session ${sessionId}`
250
+ );
251
+ return;
252
+ }
253
+
254
+ try {
255
+ addSessionToBoard(sessionId, template.targetLaneId);
256
+ console.log(
257
+ `Kanban: Added session ${sessionId} to lane "${lane.name}" based on template target`
258
+ );
259
+ } catch (error) {
260
+ console.warn(`Kanban: Failed to add session ${sessionId} to board:`, error.message);
261
+ }
262
+ }
@@ -0,0 +1,273 @@
1
+ import {
2
+ sessions,
3
+ sessionTemplates,
4
+ sessionSummaries,
5
+ projects,
6
+ } from '../database.js';
7
+ import { broadcastToProject } from '../websocket.js';
8
+ import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
9
+ import { renderTemplatePrompt, getRootSession } from './templateTriggerService.js';
10
+ import { setupGitForSession } from './gitSessionSetup.js';
11
+ import { runSession } from './sessionManager.js';
12
+
13
+ // Maximum depth for recursive lane-entry template triggers
14
+ export const MAX_LANE_TRIGGER_DEPTH = 5;
15
+
16
+ /**
17
+ * Get session and project for lane trigger, returning null if not found.
18
+ * @param {string} sessionId
19
+ * @returns {{session: Object, project: Object}|null}
20
+ */
21
+ export function getSessionAndProjectForTrigger(sessionId) {
22
+ const session = sessions.getById(sessionId);
23
+ if (!session) {
24
+ console.warn(`Kanban: Session ${sessionId} not found for on-enter trigger`);
25
+ return null;
26
+ }
27
+ const project = projects.getById(session.projectId);
28
+ if (!project) {
29
+ console.warn(`Kanban: Project ${session.projectId} not found for session ${sessionId}`);
30
+ return null;
31
+ }
32
+ return { session, project };
33
+ }
34
+
35
+ /**
36
+ * Determine working directory for child session, inheriting parent's worktree if present.
37
+ * @param {Object} parentSession
38
+ * @param {Object} project
39
+ * @param {Object} [gitOptions]
40
+ * @param {string} [gitOptions.gitMode]
41
+ * @param {string} [gitOptions.gitBranch]
42
+ * @param {string} [gitOptions.sessionId]
43
+ * @returns {Promise<{workingDirectory: string, gitWorktree: string|null}>}
44
+ */
45
+ export async function determineWorkingDirectory(parentSession, project, gitOptions = {}) {
46
+ if (parentSession.gitWorktree) {
47
+ console.log(`Kanban: Inheriting parent worktree: ${parentSession.gitWorktree}`);
48
+ return { workingDirectory: parentSession.gitWorktree, gitWorktree: parentSession.gitWorktree };
49
+ }
50
+
51
+ if (gitOptions.sessionId) {
52
+ const gitSetup = await setupGitForSession({
53
+ projectDir: project.workingDirectory,
54
+ gitMode: gitOptions.gitMode || null,
55
+ gitBranch: gitOptions.gitBranch || null,
56
+ sessionId: gitOptions.sessionId,
57
+ });
58
+ return { workingDirectory: gitSetup.workingDirectory, gitWorktree: gitSetup.gitWorktree };
59
+ }
60
+
61
+ return { workingDirectory: project.workingDirectory, gitWorktree: null };
62
+ }
63
+
64
+ /**
65
+ * Start a child session and handle errors via broadcast.
66
+ * @param {Object} newSession
67
+ * @param {string} prompt
68
+ * @param {string} workingDirectory
69
+ * @param {Object} options
70
+ */
71
+ export function startChildSession(newSession, prompt, workingDirectory, options) {
72
+ runSession(newSession.id, prompt, workingDirectory, options).catch((error) => {
73
+ console.error(`Kanban: Error running on-enter session ${newSession.id}:`, error);
74
+ const errorSession = sessions.update(newSession.id, { status: 'error', error: error.message });
75
+ broadcastToProject(newSession.projectId, WS_MESSAGE_TYPES.SESSION_UPDATED, {
76
+ projectId: newSession.projectId,
77
+ sessionId: newSession.id,
78
+ session: errorSession,
79
+ });
80
+ });
81
+ }
82
+
83
+ /**
84
+ * Get lane session settings from lane or inherit from parent session.
85
+ * @param {Object} lane
86
+ * @param {Object} session
87
+ * @returns {Object}
88
+ */
89
+ export function getLaneSessionSettings(lane, session) {
90
+ return {
91
+ thinkingEnabled: lane.onEnterThinkingEnabled ?? session.thinkingEnabled,
92
+ model: lane.onEnterModel || session.model,
93
+ mode: lane.onEnterMode || session.mode,
94
+ effortLevel: lane.onEnterEffortLevel || session.effortLevel || null,
95
+ gitBranch: session.gitBranch,
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Get template session settings from template or inherit from parent session.
101
+ * @param {Object} template
102
+ * @param {Object} session
103
+ * @returns {Object}
104
+ */
105
+ export function getTemplateSessionSettings(template, session) {
106
+ return {
107
+ thinkingEnabled: template.thinkingEnabled !== null ? template.thinkingEnabled : session.thinkingEnabled,
108
+ model: template.model || session.model,
109
+ mode: template.mode || session.mode,
110
+ gitBranch: template.gitBranch || session.gitBranch,
111
+ gitMode: template.gitMode || null,
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Trigger the on-enter template for a lane.
117
+ *
118
+ * @param {string} sessionId - The session that entered the lane
119
+ * @param {Object} lane - The lane with template info
120
+ * @param {Object} [options] - Options
121
+ * @param {number} [options.depth=0] - Current recursion depth
122
+ */
123
+ export async function triggerOnEnterTemplate(sessionId, lane, options = {}) {
124
+ const { depth = 0 } = options;
125
+
126
+ if (depth >= MAX_LANE_TRIGGER_DEPTH) {
127
+ console.warn(`Lane trigger depth limit reached for session ${sessionId} in lane ${lane.id}`);
128
+ return;
129
+ }
130
+
131
+ const template = sessionTemplates.getById(lane.onEnterTemplateId);
132
+ if (!template) {
133
+ console.warn(`Kanban: On-enter template ${lane.onEnterTemplateId} not found for lane ${lane.id}`);
134
+ return;
135
+ }
136
+
137
+ const context = getSessionAndProjectForTrigger(sessionId);
138
+ if (!context) return;
139
+ const { session, project } = context;
140
+
141
+ console.log(`Kanban: Triggering on-enter template "${template.name}" for session "${session.name}" entering lane "${lane.name}"`);
142
+
143
+ try {
144
+ // Render prompt with session context
145
+ const parentSummary = sessionSummaries.getBySessionId(sessionId);
146
+ const rootSession = getRootSession(session);
147
+ const rootSummary = sessionSummaries.getBySessionId(rootSession.id);
148
+ const renderedPrompt = await renderTemplatePrompt(
149
+ template.prompt,
150
+ { parentSession: session, parentSummary, rootSession, rootSummary }
151
+ );
152
+
153
+ // Get settings and create session
154
+ const settings = getTemplateSessionSettings(template, session);
155
+ const newSession = sessions.create(session.projectId, `${template.name} (lane: ${lane.name})`, renderedPrompt, {
156
+ mode: settings.mode,
157
+ thinkingEnabled: settings.thinkingEnabled,
158
+ gitBranch: settings.gitBranch,
159
+ status: 'starting',
160
+ model: settings.model,
161
+ });
162
+
163
+ // Configure session
164
+ sessions.update(newSession.id, {
165
+ parentSessionId: session.id,
166
+ nextTemplateId: template.nextTemplateId || null,
167
+ targetLaneId: template.targetLaneId || null,
168
+ laneTriggerDepth: depth + 1,
169
+ });
170
+
171
+ // Determine working directory
172
+ const { workingDirectory, gitWorktree } = await determineWorkingDirectory(session, project, {
173
+ gitMode: settings.gitMode,
174
+ gitBranch: settings.gitBranch,
175
+ sessionId: newSession.id,
176
+ });
177
+ if (gitWorktree) {
178
+ sessions.update(newSession.id, { gitWorktree });
179
+ }
180
+
181
+ // Broadcast and start
182
+ broadcastToProject(session.projectId, WS_MESSAGE_TYPES.SESSION_CREATED, {
183
+ projectId: session.projectId,
184
+ session: sessions.getById(newSession.id),
185
+ });
186
+
187
+ startChildSession(newSession, renderedPrompt, workingDirectory, {
188
+ systemPrompt: project.systemPrompt,
189
+ model: settings.model,
190
+ });
191
+
192
+ console.log(`Kanban: Created and started on-enter session ${newSession.id}`);
193
+ } catch (error) {
194
+ console.error(`Kanban: Failed to trigger on-enter template for session ${sessionId}:`, error);
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Trigger a custom prompt for a lane when a session enters it.
200
+ *
201
+ * @param {string} sessionId - The session that entered the lane
202
+ * @param {Object} lane - The lane with prompt info
203
+ * @param {Object} [options] - Options
204
+ * @param {number} [options.depth=0] - Current recursion depth
205
+ */
206
+ export async function triggerOnEnterPrompt(sessionId, lane, options = {}) {
207
+ const { depth = 0 } = options;
208
+
209
+ if (depth >= MAX_LANE_TRIGGER_DEPTH) {
210
+ console.warn(`Lane trigger depth limit reached for session ${sessionId} in lane ${lane.id}`);
211
+ return;
212
+ }
213
+
214
+ const context = getSessionAndProjectForTrigger(sessionId);
215
+ if (!context) return;
216
+ const { session, project } = context;
217
+
218
+ console.log(`Kanban: Triggering on-enter prompt for session "${session.name}" entering lane "${lane.name}"`);
219
+
220
+ try {
221
+ // Render prompt with session context
222
+ const parentSummary = sessionSummaries.getBySessionId(sessionId);
223
+ const rootSession = getRootSession(session);
224
+ const rootSummary = sessionSummaries.getBySessionId(rootSession.id);
225
+ const renderedPrompt = await renderTemplatePrompt(
226
+ lane.onEnterPrompt,
227
+ { parentSession: session, parentSummary, rootSession, rootSummary }
228
+ );
229
+
230
+ // Get settings and create session
231
+ const settings = getLaneSessionSettings(lane, session);
232
+ const newSession = sessions.create(session.projectId, `Lane prompt (lane: ${lane.name})`, renderedPrompt, {
233
+ ...settings,
234
+ status: 'starting',
235
+ });
236
+
237
+ // Configure session
238
+ const sessionUpdates = { parentSessionId: session.id, laneTriggerDepth: depth + 1 };
239
+ if (lane.onEnterAutoRescheduleEnabled) {
240
+ Object.assign(sessionUpdates, {
241
+ autoRescheduleEnabled: true,
242
+ rescheduleDelayMinutes: lane.onEnterRescheduleDelayMinutes || 15,
243
+ rescheduleOnTokenLimit: lane.onEnterRescheduleOnTokenLimit ?? true,
244
+ rescheduleOnServiceError: lane.onEnterRescheduleOnServiceError ?? true,
245
+ maxRescheduleCount: lane.onEnterMaxRescheduleCount || null,
246
+ maxTotalTokens: lane.onEnterMaxTotalTokens || null,
247
+ rescheduleAtTokenCount: lane.onEnterRescheduleAtTokenCount || null,
248
+ });
249
+ }
250
+ sessions.update(newSession.id, sessionUpdates);
251
+
252
+ // Determine working directory
253
+ const { workingDirectory, gitWorktree } = await determineWorkingDirectory(session, project);
254
+ if (gitWorktree) {
255
+ sessions.update(newSession.id, { gitWorktree });
256
+ }
257
+
258
+ // Broadcast and start
259
+ broadcastToProject(session.projectId, WS_MESSAGE_TYPES.SESSION_CREATED, {
260
+ projectId: session.projectId,
261
+ session: sessions.getById(newSession.id),
262
+ });
263
+
264
+ startChildSession(newSession, renderedPrompt, workingDirectory, {
265
+ systemPrompt: project.systemPrompt,
266
+ model: settings.model,
267
+ });
268
+
269
+ console.log(`Kanban: Created and started on-enter prompt session ${newSession.id}`);
270
+ } catch (error) {
271
+ console.error(`Kanban: Failed to trigger on-enter prompt for session ${sessionId}:`, error);
272
+ }
273
+ }
@@ -0,0 +1,63 @@
1
+ import { spawn } from 'child_process';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Get the directory containing the current Node.js executable.
6
+ * Used to ensure child processes can find node even when using version managers.
7
+ * @returns {string} Path to the directory containing the Node binary
8
+ */
9
+ export function getNodeBinDir() {
10
+ return path.dirname(process.execPath);
11
+ }
12
+
13
+ /**
14
+ * Create environment with guaranteed Node.js in PATH.
15
+ * Prepends the Node binary directory to PATH to ensure child processes can find node.
16
+ * This is critical for npx users with nvm/fnm/volta where 'node' may not be in system PATH.
17
+ *
18
+ * @param {Object} [baseEnv=process.env] - Base environment to extend
19
+ * @returns {Object} Environment object with robust PATH
20
+ */
21
+ export function createRobustEnv(baseEnv = process.env) {
22
+ const nodeBinDir = getNodeBinDir();
23
+ const pathSeparator = process.platform === 'win32' ? ';' : ':';
24
+ const currentPath = baseEnv.PATH || baseEnv.Path || '';
25
+
26
+ return {
27
+ ...baseEnv,
28
+ PATH: `${nodeBinDir}${pathSeparator}${currentPath}`,
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Create a custom spawn function for the Claude Agent SDK.
34
+ * Replaces 'node' command with process.execPath and ensures PATH is correct.
35
+ *
36
+ * This solves the "spawn node ENOENT" error that occurs when:
37
+ * - Users run the app via npx with Node version managers (nvm, fnm, volta)
38
+ * - The system PATH doesn't include the Node binary directory
39
+ *
40
+ * @returns {Function} Spawn function compatible with SDK's spawnClaudeCodeProcess option
41
+ */
42
+ export function createClaudeCodeSpawner() {
43
+ return (options) => {
44
+ const { command, args, cwd, env, signal } = options;
45
+
46
+ // Replace 'node' with the absolute path to the current Node executable
47
+ // This ensures we use the same Node that's running our app
48
+ const actualCommand = command === 'node' ? process.execPath : command;
49
+
50
+ // Ensure PATH includes the directory containing Node
51
+ const robustEnv = createRobustEnv(env);
52
+
53
+ const stderrMode = robustEnv.DEBUG_CLAUDE_AGENT_SDK ? 'pipe' : 'ignore';
54
+
55
+ return spawn(actualCommand, args, {
56
+ cwd,
57
+ stdio: ['pipe', 'pipe', stderrMode],
58
+ signal,
59
+ env: robustEnv,
60
+ windowsHide: true,
61
+ });
62
+ };
63
+ }