automagik-forge 0.1.13 → 0.1.14

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 (301) hide show
  1. package/README.md +143 -447
  2. package/dist/linux-x64/automagik-forge-mcp.zip +0 -0
  3. package/{npx-cli/automagik-forge-0.0.55.tgz → dist/linux-x64/automagik-forge.zip} +0 -0
  4. package/package.json +13 -23
  5. package/.cargo/config.toml +0 -13
  6. package/.claude/commands/commit.md +0 -376
  7. package/.claude/commands/prompt.md +0 -871
  8. package/.env.example +0 -20
  9. package/.github/actions/setup-node/action.yml +0 -29
  10. package/.github/images/automagik-logo.png +0 -0
  11. package/.github/workflows/pre-release.yml +0 -470
  12. package/.github/workflows/publish.yml +0 -145
  13. package/.github/workflows/test.yml +0 -63
  14. package/.mcp.json +0 -57
  15. package/AGENT.md +0 -40
  16. package/CLAUDE.md +0 -40
  17. package/CODE-OF-CONDUCT.md +0 -89
  18. package/Cargo.toml +0 -19
  19. package/Dockerfile +0 -43
  20. package/LICENSE +0 -201
  21. package/Makefile +0 -97
  22. package/backend/.sqlx/query-01b7e2bac1261d8be3d03c03df3e5220590da6c31c77f161074fc62752d63881.json +0 -12
  23. package/backend/.sqlx/query-03f2b02ba6dc5ea2b3cf6b1004caea0ad6bcc10ebd63f441d321a389f026e263.json +0 -12
  24. package/backend/.sqlx/query-0923b77d137a29fc54d399a873ff15fc4af894490bc65a4d344a7575cb0d8643.json +0 -12
  25. package/backend/.sqlx/query-0f808bcdb63c5f180836e448dd64c435c51758b2fc54a52ce9e67495b1ab200e.json +0 -68
  26. package/backend/.sqlx/query-1268afe9ca849daa6722e3df7ca8e9e61f0d37052e782bb5452ab8e1018d9b63.json +0 -12
  27. package/backend/.sqlx/query-1b082630a9622f8667ee7a9aba2c2d3176019a68c6bb83d33008594821415a57.json +0 -12
  28. package/backend/.sqlx/query-1c7b06ba1e112abf6b945a2ff08a0b40ec23f3738c2e7399f067b558cf8d490e.json +0 -12
  29. package/backend/.sqlx/query-1f619f01f46859a64ded531dd0ef61abacfe62e758abe7030a6aa745140b95ca.json +0 -104
  30. package/backend/.sqlx/query-1fca1ce14b4b20205364cd1f1f45ebe1d2e30cd745e59e189d56487b5639dfbb.json +0 -12
  31. package/backend/.sqlx/query-212828320e8d871ab9d83705a040b23bcf0393dc7252177fc539a74657f578ef.json +0 -32
  32. package/backend/.sqlx/query-290ce5c152be8d36e58ff42570f9157beb07ab9e77a03ec6fc30b4f56f9b8f6b.json +0 -56
  33. package/backend/.sqlx/query-2b471d2c2e8ffbe0cd42d2a91b814c0d79f9d09200f147e3cea33ba4ce673c8a.json +0 -68
  34. package/backend/.sqlx/query-354a48c705bb9bb2048c1b7f10fcb714e23f9db82b7a4ea6932486197b2ede6a.json +0 -92
  35. package/backend/.sqlx/query-36c9e3dd10648e94b949db5c91a774ecb1e10a899ef95da74066eccedca4d8b2.json +0 -12
  36. package/backend/.sqlx/query-36e4ba7bbd81b402d5a20b6005755eafbb174c8dda442081823406ac32809a94.json +0 -56
  37. package/backend/.sqlx/query-3a5b3c98a55ca183ab20c74708e3d7e579dda37972c059e7515c4ceee4bd8dd3.json +0 -62
  38. package/backend/.sqlx/query-3d0a1cabf2a52e9d90cdfd29c509ca89aeb448d0c1d2446c65cd43db40735e86.json +0 -62
  39. package/backend/.sqlx/query-3d6bd16fbce59efe30b7f67ea342e0e4ea6d1432389c02468ad79f1f742d4031.json +0 -56
  40. package/backend/.sqlx/query-4049ca413b285a05aca6b25385e9c8185575f01e9069e4e8581aa45d713f612f.json +0 -32
  41. package/backend/.sqlx/query-412bacd3477d86369082e90f52240407abce436cb81292d42b2dbe1e5c18eea1.json +0 -104
  42. package/backend/.sqlx/query-417a8b1ff4e51de82aea0159a3b97932224dc325b23476cb84153d690227fd8b.json +0 -62
  43. package/backend/.sqlx/query-461cc1b0bb6fd909afc9dd2246e8526b3771cfbb0b22ae4b5d17b51af587b9e2.json +0 -56
  44. package/backend/.sqlx/query-58408c7a8cdeeda0bef359f1f9bd91299a339dc2b191462fc58c9736a56d5227.json +0 -92
  45. package/backend/.sqlx/query-5a886026d75d515c01f347cc203c8d99dd04c61dc468e2e4c5aa548436d13834.json +0 -62
  46. package/backend/.sqlx/query-5b902137b11022d2e1a5c4f6a9c83fec1a856c6a710aff831abd2382ede76b43.json +0 -12
  47. package/backend/.sqlx/query-5ed1238e52e59bb5f76c0f153fd99a14093f7ce2585bf9843585608f17ec575b.json +0 -104
  48. package/backend/.sqlx/query-6e8b860b14decfc2227dc57213f38442943d3fbef5c8418fd6b634c6e0f5e2ea.json +0 -104
  49. package/backend/.sqlx/query-6ec414276994c4ccb2433eaa5b1b342168557d17ddf5a52dac84cb1b59b9de8f.json +0 -68
  50. package/backend/.sqlx/query-6ecfa16d0cf825aacf233544b5baf151e9adfdca26c226ad71020d291fd802d5.json +0 -62
  51. package/backend/.sqlx/query-72509d252c39fce77520aa816cb2acbc1fb35dc2605e7be893610599b2427f2e.json +0 -62
  52. package/backend/.sqlx/query-75239b2da188f749707d77f3c1544332ca70db3d6d6743b2601dc0d167536437.json +0 -62
  53. package/backend/.sqlx/query-83d10e29f8478aff33434f9ac67068e013b888b953a2657e2bb72a6f619d04f2.json +0 -50
  54. package/backend/.sqlx/query-8610803360ea18b9b9d078a6981ea56abfbfe84e6354fc1d5ae4c622e01410ed.json +0 -68
  55. package/backend/.sqlx/query-86d03eb70eef39c59296416867f2ee66c9f7cd8b7f961fbda2f89fc0a1c442c2.json +0 -12
  56. package/backend/.sqlx/query-87d0feb5a6b442bad9c60068ea7569599cc6fc91a0e2692ecb42e93b03201b9d.json +0 -68
  57. package/backend/.sqlx/query-8a67b3b3337248f06a57bdf8a908f7ef23177431eaed82dc08c94c3e5944340e.json +0 -12
  58. package/backend/.sqlx/query-8f01ebd64bdcde6a090479f14810d73ba23020e76fd70854ac57f2da251702c3.json +0 -12
  59. package/backend/.sqlx/query-90fd607fcb2dca72239ff25e618e21e174b195991eaa33722cbf5f76da84cfab.json +0 -62
  60. package/backend/.sqlx/query-92e8bdbcd80c5ff3db7a35cf79492048803ef305cbdef0d0a1fe5dc881ca8c71.json +0 -104
  61. package/backend/.sqlx/query-93a1605f90e9672dad29b472b6ad85fa9a55ea3ffa5abcb8724b09d61be254ca.json +0 -20
  62. package/backend/.sqlx/query-9472c8fb477958167f5fae40b85ac44252468c5226b2cdd7770f027332eed6d7.json +0 -104
  63. package/backend/.sqlx/query-96036c4f9e0f48bdc5a4a4588f0c5f288ac7aaa5425cac40fc33f337e1a351f2.json +0 -56
  64. package/backend/.sqlx/query-9edb2c01e91fd0f0fe7b56e988c7ae0393150f50be3f419a981e035c0121dfc7.json +0 -104
  65. package/backend/.sqlx/query-a157cf00616f703bfba21927f1eb1c9eec2a81c02da15f66efdba0b6c375de1b.json +0 -26
  66. package/backend/.sqlx/query-a31fff84f3b8e532fd1160447d89d700f06ae08821fee00c9a5b60492b05259c.json +0 -62
  67. package/backend/.sqlx/query-a5ba908419fb3e456bdd2daca41ba06cc3212ffffb8520fc7dbbcc8b60ada314.json +0 -12
  68. package/backend/.sqlx/query-a6d2961718dbc3b1a925e549f49a159c561bef58c105529275f274b27e2eba5b.json +0 -104
  69. package/backend/.sqlx/query-a9e93d5b09b29faf66e387e4d7596a792d81e75c4d3726e83c2963e8d7c9b56f.json +0 -104
  70. package/backend/.sqlx/query-ac5247c8d7fb86e4650c4b0eb9420031614c831b7b085083bac20c1af314c538.json +0 -12
  71. package/backend/.sqlx/query-afef9467be74c411c4cb119a8b2b1aea53049877dfc30cc60b486134ba4b4c9f.json +0 -68
  72. package/backend/.sqlx/query-b2b2c6b4d0b1a347b5c4cb63c3a46a265d4db53be9554989a814b069d0af82f2.json +0 -62
  73. package/backend/.sqlx/query-c50d2ff0b12e5bcc81e371089ee2d007e233e7db93aefba4fef08e7aa68f5ab7.json +0 -20
  74. package/backend/.sqlx/query-c614e6056b244ca07f1b9d44e7edc9d5819225c6f8d9e077070c6e518a17f50b.json +0 -12
  75. package/backend/.sqlx/query-c67259be8bf4ee0cfd32167b2aa3b7fe9192809181a8171bf1c2d6df731967ae.json +0 -12
  76. package/backend/.sqlx/query-d2d0a1b985ebbca6a2b3e882a221a219f3199890fa640afc946ef1a792d6d8de.json +0 -12
  77. package/backend/.sqlx/query-d30aa5786757f32bf2b9c5fe51a45e506c71c28c5994e430d9b0546adb15ffa2.json +0 -20
  78. package/backend/.sqlx/query-d3b9ea1de1576af71b312924ce7f4ea8ae5dbe2ac138ea3b4470f2d5cd734846.json +0 -12
  79. package/backend/.sqlx/query-ed8456646fa69ddd412441955f06ff22bfb790f29466450735e0b8bb1bc4ec94.json +0 -12
  80. package/backend/Cargo.toml +0 -71
  81. package/backend/build.rs +0 -32
  82. package/backend/migrations/20250617183714_init.sql +0 -44
  83. package/backend/migrations/20250620212427_execution_processes.sql +0 -25
  84. package/backend/migrations/20250620214100_remove_stdout_stderr_from_task_attempts.sql +0 -28
  85. package/backend/migrations/20250621120000_relate_activities_to_execution_processes.sql +0 -23
  86. package/backend/migrations/20250623120000_executor_sessions.sql +0 -17
  87. package/backend/migrations/20250623130000_add_executor_type_to_execution_processes.sql +0 -4
  88. package/backend/migrations/20250625000000_add_dev_script_to_projects.sql +0 -4
  89. package/backend/migrations/20250701000000_add_branch_to_task_attempts.sql +0 -2
  90. package/backend/migrations/20250701000001_add_pr_tracking_to_task_attempts.sql +0 -5
  91. package/backend/migrations/20250701120000_add_assistant_message_to_executor_sessions.sql +0 -2
  92. package/backend/migrations/20250708000000_add_base_branch_to_task_attempts.sql +0 -2
  93. package/backend/migrations/20250709000000_add_worktree_deleted_flag.sql +0 -2
  94. package/backend/migrations/20250710000000_add_setup_completion.sql +0 -3
  95. package/backend/migrations/20250715154859_add_task_templates.sql +0 -25
  96. package/backend/migrations/20250716143725_add_default_templates.sql +0 -174
  97. package/backend/migrations/20250716161432_update_executor_names_to_kebab_case.sql +0 -20
  98. package/backend/migrations/20250716170000_add_parent_task_to_tasks.sql +0 -7
  99. package/backend/migrations/20250717000000_drop_task_attempt_activities.sql +0 -9
  100. package/backend/migrations/20250719000000_add_cleanup_script_to_projects.sql +0 -2
  101. package/backend/migrations/20250720000000_add_cleanupscript_to_process_type_constraint.sql +0 -25
  102. package/backend/migrations/20250723000000_add_wish_to_tasks.sql +0 -7
  103. package/backend/migrations/20250724000000_remove_unique_wish_constraint.sql +0 -5
  104. package/backend/scripts/toast-notification.ps1 +0 -23
  105. package/backend/sounds/abstract-sound1.wav +0 -0
  106. package/backend/sounds/abstract-sound2.wav +0 -0
  107. package/backend/sounds/abstract-sound3.wav +0 -0
  108. package/backend/sounds/abstract-sound4.wav +0 -0
  109. package/backend/sounds/cow-mooing.wav +0 -0
  110. package/backend/sounds/phone-vibration.wav +0 -0
  111. package/backend/sounds/rooster.wav +0 -0
  112. package/backend/src/app_state.rs +0 -218
  113. package/backend/src/bin/generate_types.rs +0 -189
  114. package/backend/src/bin/mcp_task_server.rs +0 -191
  115. package/backend/src/execution_monitor.rs +0 -1193
  116. package/backend/src/executor.rs +0 -1053
  117. package/backend/src/executors/amp.rs +0 -697
  118. package/backend/src/executors/ccr.rs +0 -91
  119. package/backend/src/executors/charm_opencode.rs +0 -113
  120. package/backend/src/executors/claude.rs +0 -887
  121. package/backend/src/executors/cleanup_script.rs +0 -124
  122. package/backend/src/executors/dev_server.rs +0 -53
  123. package/backend/src/executors/echo.rs +0 -79
  124. package/backend/src/executors/gemini/config.rs +0 -67
  125. package/backend/src/executors/gemini/streaming.rs +0 -363
  126. package/backend/src/executors/gemini.rs +0 -765
  127. package/backend/src/executors/mod.rs +0 -23
  128. package/backend/src/executors/opencode_ai.rs +0 -113
  129. package/backend/src/executors/setup_script.rs +0 -130
  130. package/backend/src/executors/sst_opencode/filter.rs +0 -184
  131. package/backend/src/executors/sst_opencode/tools.rs +0 -139
  132. package/backend/src/executors/sst_opencode.rs +0 -756
  133. package/backend/src/lib.rs +0 -45
  134. package/backend/src/main.rs +0 -324
  135. package/backend/src/mcp/mod.rs +0 -1
  136. package/backend/src/mcp/task_server.rs +0 -850
  137. package/backend/src/middleware/mod.rs +0 -3
  138. package/backend/src/middleware/model_loaders.rs +0 -242
  139. package/backend/src/models/api_response.rs +0 -36
  140. package/backend/src/models/config.rs +0 -375
  141. package/backend/src/models/execution_process.rs +0 -430
  142. package/backend/src/models/executor_session.rs +0 -225
  143. package/backend/src/models/mod.rs +0 -12
  144. package/backend/src/models/project.rs +0 -356
  145. package/backend/src/models/task.rs +0 -345
  146. package/backend/src/models/task_attempt.rs +0 -1214
  147. package/backend/src/models/task_template.rs +0 -146
  148. package/backend/src/openapi.rs +0 -93
  149. package/backend/src/routes/auth.rs +0 -297
  150. package/backend/src/routes/config.rs +0 -385
  151. package/backend/src/routes/filesystem.rs +0 -228
  152. package/backend/src/routes/health.rs +0 -16
  153. package/backend/src/routes/mod.rs +0 -9
  154. package/backend/src/routes/projects.rs +0 -562
  155. package/backend/src/routes/stream.rs +0 -244
  156. package/backend/src/routes/task_attempts.rs +0 -1172
  157. package/backend/src/routes/task_templates.rs +0 -229
  158. package/backend/src/routes/tasks.rs +0 -353
  159. package/backend/src/services/analytics.rs +0 -216
  160. package/backend/src/services/git_service.rs +0 -1321
  161. package/backend/src/services/github_service.rs +0 -307
  162. package/backend/src/services/mod.rs +0 -13
  163. package/backend/src/services/notification_service.rs +0 -263
  164. package/backend/src/services/pr_monitor.rs +0 -214
  165. package/backend/src/services/process_service.rs +0 -940
  166. package/backend/src/utils/path.rs +0 -96
  167. package/backend/src/utils/shell.rs +0 -19
  168. package/backend/src/utils/text.rs +0 -24
  169. package/backend/src/utils/worktree_manager.rs +0 -578
  170. package/backend/src/utils.rs +0 -125
  171. package/backend/test.db +0 -0
  172. package/build-npm-package.sh +0 -61
  173. package/dev_assets_seed/config.json +0 -19
  174. package/frontend/.eslintrc.json +0 -25
  175. package/frontend/.prettierrc.json +0 -8
  176. package/frontend/components.json +0 -17
  177. package/frontend/index.html +0 -19
  178. package/frontend/package-lock.json +0 -7321
  179. package/frontend/package.json +0 -61
  180. package/frontend/postcss.config.js +0 -6
  181. package/frontend/public/android-chrome-192x192.png +0 -0
  182. package/frontend/public/android-chrome-512x512.png +0 -0
  183. package/frontend/public/apple-touch-icon.png +0 -0
  184. package/frontend/public/automagik-forge-logo-dark.svg +0 -3
  185. package/frontend/public/automagik-forge-logo.svg +0 -3
  186. package/frontend/public/automagik-forge-screenshot-overview.png +0 -0
  187. package/frontend/public/favicon-16x16.png +0 -0
  188. package/frontend/public/favicon-32x32.png +0 -0
  189. package/frontend/public/favicon.ico +0 -0
  190. package/frontend/public/site.webmanifest +0 -1
  191. package/frontend/public/viba-kanban-favicon.png +0 -0
  192. package/frontend/src/App.tsx +0 -157
  193. package/frontend/src/components/DisclaimerDialog.tsx +0 -106
  194. package/frontend/src/components/GitHubLoginDialog.tsx +0 -314
  195. package/frontend/src/components/OnboardingDialog.tsx +0 -185
  196. package/frontend/src/components/PrivacyOptInDialog.tsx +0 -130
  197. package/frontend/src/components/ProvidePatDialog.tsx +0 -98
  198. package/frontend/src/components/TaskTemplateManager.tsx +0 -336
  199. package/frontend/src/components/config-provider.tsx +0 -119
  200. package/frontend/src/components/context/TaskDetailsContextProvider.tsx +0 -470
  201. package/frontend/src/components/context/taskDetailsContext.ts +0 -125
  202. package/frontend/src/components/keyboard-shortcuts-demo.tsx +0 -35
  203. package/frontend/src/components/layout/navbar.tsx +0 -86
  204. package/frontend/src/components/logo.tsx +0 -44
  205. package/frontend/src/components/projects/ProjectCard.tsx +0 -155
  206. package/frontend/src/components/projects/project-detail.tsx +0 -251
  207. package/frontend/src/components/projects/project-form-fields.tsx +0 -238
  208. package/frontend/src/components/projects/project-form.tsx +0 -301
  209. package/frontend/src/components/projects/project-list.tsx +0 -200
  210. package/frontend/src/components/projects/projects-page.tsx +0 -20
  211. package/frontend/src/components/tasks/BranchSelector.tsx +0 -169
  212. package/frontend/src/components/tasks/DeleteFileConfirmationDialog.tsx +0 -94
  213. package/frontend/src/components/tasks/EditorSelectionDialog.tsx +0 -119
  214. package/frontend/src/components/tasks/TaskCard.tsx +0 -154
  215. package/frontend/src/components/tasks/TaskDetails/CollapsibleToolbar.tsx +0 -33
  216. package/frontend/src/components/tasks/TaskDetails/DiffCard.tsx +0 -109
  217. package/frontend/src/components/tasks/TaskDetails/DiffChunkSection.tsx +0 -135
  218. package/frontend/src/components/tasks/TaskDetails/DiffFile.tsx +0 -296
  219. package/frontend/src/components/tasks/TaskDetails/DiffTab.tsx +0 -32
  220. package/frontend/src/components/tasks/TaskDetails/DisplayConversationEntry.tsx +0 -392
  221. package/frontend/src/components/tasks/TaskDetails/LogsTab/Conversation.tsx +0 -256
  222. package/frontend/src/components/tasks/TaskDetails/LogsTab/ConversationEntry.tsx +0 -56
  223. package/frontend/src/components/tasks/TaskDetails/LogsTab/NormalizedConversationViewer.tsx +0 -92
  224. package/frontend/src/components/tasks/TaskDetails/LogsTab/Prompt.tsx +0 -22
  225. package/frontend/src/components/tasks/TaskDetails/LogsTab/SetupScriptRunning.tsx +0 -49
  226. package/frontend/src/components/tasks/TaskDetails/LogsTab.tsx +0 -186
  227. package/frontend/src/components/tasks/TaskDetails/ProcessesTab.tsx +0 -288
  228. package/frontend/src/components/tasks/TaskDetails/RelatedTasksTab.tsx +0 -216
  229. package/frontend/src/components/tasks/TaskDetails/TabNavigation.tsx +0 -93
  230. package/frontend/src/components/tasks/TaskDetailsHeader.tsx +0 -169
  231. package/frontend/src/components/tasks/TaskDetailsPanel.tsx +0 -126
  232. package/frontend/src/components/tasks/TaskDetailsToolbar.tsx +0 -302
  233. package/frontend/src/components/tasks/TaskFollowUpSection.tsx +0 -130
  234. package/frontend/src/components/tasks/TaskFormDialog.tsx +0 -400
  235. package/frontend/src/components/tasks/TaskKanbanBoard.tsx +0 -180
  236. package/frontend/src/components/tasks/Toolbar/CreateAttempt.tsx +0 -259
  237. package/frontend/src/components/tasks/Toolbar/CreatePRDialog.tsx +0 -243
  238. package/frontend/src/components/tasks/Toolbar/CurrentAttempt.tsx +0 -899
  239. package/frontend/src/components/tasks/index.ts +0 -2
  240. package/frontend/src/components/theme-provider.tsx +0 -82
  241. package/frontend/src/components/theme-toggle.tsx +0 -36
  242. package/frontend/src/components/ui/alert.tsx +0 -59
  243. package/frontend/src/components/ui/auto-expanding-textarea.tsx +0 -70
  244. package/frontend/src/components/ui/badge.tsx +0 -36
  245. package/frontend/src/components/ui/button.tsx +0 -56
  246. package/frontend/src/components/ui/card.tsx +0 -86
  247. package/frontend/src/components/ui/checkbox.tsx +0 -44
  248. package/frontend/src/components/ui/chip.tsx +0 -25
  249. package/frontend/src/components/ui/dialog.tsx +0 -124
  250. package/frontend/src/components/ui/dropdown-menu.tsx +0 -198
  251. package/frontend/src/components/ui/file-search-textarea.tsx +0 -292
  252. package/frontend/src/components/ui/folder-picker.tsx +0 -279
  253. package/frontend/src/components/ui/input.tsx +0 -25
  254. package/frontend/src/components/ui/label.tsx +0 -24
  255. package/frontend/src/components/ui/loader.tsx +0 -26
  256. package/frontend/src/components/ui/markdown-renderer.tsx +0 -75
  257. package/frontend/src/components/ui/select.tsx +0 -160
  258. package/frontend/src/components/ui/separator.tsx +0 -31
  259. package/frontend/src/components/ui/shadcn-io/kanban/index.tsx +0 -185
  260. package/frontend/src/components/ui/table.tsx +0 -117
  261. package/frontend/src/components/ui/tabs.tsx +0 -53
  262. package/frontend/src/components/ui/textarea.tsx +0 -22
  263. package/frontend/src/components/ui/tooltip.tsx +0 -28
  264. package/frontend/src/hooks/useNormalizedConversation.ts +0 -440
  265. package/frontend/src/index.css +0 -225
  266. package/frontend/src/lib/api.ts +0 -630
  267. package/frontend/src/lib/keyboard-shortcuts.ts +0 -266
  268. package/frontend/src/lib/responsive-config.ts +0 -70
  269. package/frontend/src/lib/types.ts +0 -39
  270. package/frontend/src/lib/utils.ts +0 -10
  271. package/frontend/src/main.tsx +0 -50
  272. package/frontend/src/pages/McpServers.tsx +0 -418
  273. package/frontend/src/pages/Settings.tsx +0 -610
  274. package/frontend/src/pages/project-tasks.tsx +0 -575
  275. package/frontend/src/pages/projects.tsx +0 -18
  276. package/frontend/src/vite-env.d.ts +0 -1
  277. package/frontend/tailwind.config.js +0 -125
  278. package/frontend/tsconfig.json +0 -26
  279. package/frontend/tsconfig.node.json +0 -10
  280. package/frontend/vite.config.ts +0 -33
  281. package/npx-cli/README.md +0 -159
  282. package/npx-cli/automagik-forge-0.1.0.tgz +0 -0
  283. package/npx-cli/automagik-forge-0.1.10.tgz +0 -0
  284. package/npx-cli/package.json +0 -17
  285. package/npx-cli/vibe-kanban-0.0.55.tgz +0 -0
  286. package/pnpm-workspace.yaml +0 -2
  287. package/rust-toolchain.toml +0 -11
  288. package/rustfmt.toml +0 -3
  289. package/scripts/load-env.js +0 -43
  290. package/scripts/mcp_test.js +0 -374
  291. package/scripts/prepare-db.js +0 -45
  292. package/scripts/setup-dev-environment.js +0 -274
  293. package/scripts/start-mcp-sse.js +0 -70
  294. package/scripts/test-debug.js +0 -32
  295. package/scripts/test-mcp-sse.js +0 -138
  296. package/scripts/test-simple.js +0 -44
  297. package/scripts/test-wish-final.js +0 -179
  298. package/scripts/test-wish-system.js +0 -221
  299. package/shared/types.ts +0 -182
  300. package/test-npm-package.sh +0 -42
  301. /package/{npx-cli/bin → bin}/cli.js +0 -0
@@ -1,940 +0,0 @@
1
- use sqlx::SqlitePool;
2
- use tracing::{debug, info};
3
- use uuid::Uuid;
4
-
5
- use crate::{
6
- executor::Executor,
7
- models::{
8
- execution_process::{CreateExecutionProcess, ExecutionProcess, ExecutionProcessType},
9
- executor_session::{CreateExecutorSession, ExecutorSession},
10
- project::Project,
11
- task::Task,
12
- task_attempt::{TaskAttempt, TaskAttemptError},
13
- },
14
- utils::shell::get_shell_command,
15
- };
16
-
17
- /// Service responsible for managing process execution lifecycle
18
- pub struct ProcessService;
19
-
20
- impl ProcessService {
21
- /// Run cleanup script if project has one configured
22
- pub async fn run_cleanup_script_if_configured(
23
- pool: &SqlitePool,
24
- app_state: &crate::app_state::AppState,
25
- attempt_id: Uuid,
26
- task_id: Uuid,
27
- project_id: Uuid,
28
- ) -> Result<(), TaskAttemptError> {
29
- // Get project to check if cleanup script exists
30
- let project = Project::find_by_id(pool, project_id)
31
- .await?
32
- .ok_or(TaskAttemptError::ProjectNotFound)?;
33
-
34
- if Self::should_run_cleanup_script(&project) {
35
- // Get worktree path
36
- let task_attempt = TaskAttempt::find_by_id(pool, attempt_id).await?.ok_or(
37
- TaskAttemptError::ValidationError("Task attempt not found".to_string()),
38
- )?;
39
-
40
- tracing::info!(
41
- "Running cleanup script for project {} in attempt {}",
42
- project_id,
43
- attempt_id
44
- );
45
-
46
- Self::start_cleanup_script(
47
- pool,
48
- app_state,
49
- attempt_id,
50
- task_id,
51
- &project,
52
- &task_attempt.worktree_path,
53
- )
54
- .await?;
55
- } else {
56
- tracing::debug!("No cleanup script configured for project {}", project_id);
57
- }
58
-
59
- Ok(())
60
- }
61
-
62
- /// Automatically run setup if needed, then continue with the specified operation
63
- pub async fn auto_setup_and_execute(
64
- pool: &SqlitePool,
65
- app_state: &crate::app_state::AppState,
66
- attempt_id: Uuid,
67
- task_id: Uuid,
68
- project_id: Uuid,
69
- operation: &str, // "dev_server", "coding_agent", or "followup"
70
- operation_params: Option<serde_json::Value>,
71
- ) -> Result<(), TaskAttemptError> {
72
- // Check if setup is completed for this worktree
73
- let setup_completed = TaskAttempt::is_setup_completed(pool, attempt_id).await?;
74
-
75
- // Get project to check if setup script exists
76
- let project = Project::find_by_id(pool, project_id)
77
- .await?
78
- .ok_or(TaskAttemptError::ProjectNotFound)?;
79
-
80
- let needs_setup = Self::should_run_setup_script(&project) && !setup_completed;
81
-
82
- if needs_setup {
83
- // Run setup with delegation to the original operation
84
- Self::execute_setup_with_delegation(
85
- pool,
86
- app_state,
87
- attempt_id,
88
- task_id,
89
- project_id,
90
- operation,
91
- operation_params,
92
- )
93
- .await
94
- } else {
95
- // Setup not needed or already completed, continue with original operation
96
- match operation {
97
- "dev_server" => {
98
- Self::start_dev_server_direct(pool, app_state, attempt_id, task_id, project_id)
99
- .await
100
- }
101
- "coding_agent" => {
102
- Self::start_coding_agent(pool, app_state, attempt_id, task_id, project_id).await
103
- }
104
- "followup" => {
105
- let prompt = operation_params
106
- .as_ref()
107
- .and_then(|p| p.get("prompt"))
108
- .and_then(|p| p.as_str())
109
- .unwrap_or("");
110
- Self::start_followup_execution_direct(
111
- pool, app_state, attempt_id, task_id, project_id, prompt,
112
- )
113
- .await
114
- .map(|_| ())
115
- }
116
- _ => Err(TaskAttemptError::ValidationError(format!(
117
- "Unknown operation: {}",
118
- operation
119
- ))),
120
- }
121
- }
122
- }
123
-
124
- /// Execute setup script with delegation context for continuing after completion
125
- async fn execute_setup_with_delegation(
126
- pool: &SqlitePool,
127
- app_state: &crate::app_state::AppState,
128
- attempt_id: Uuid,
129
- task_id: Uuid,
130
- project_id: Uuid,
131
- delegate_to: &str,
132
- operation_params: Option<serde_json::Value>,
133
- ) -> Result<(), TaskAttemptError> {
134
- let (task_attempt, project) =
135
- Self::load_execution_context(pool, attempt_id, project_id).await?;
136
-
137
- // Create delegation context for execution monitor
138
- let delegation_context = serde_json::json!({
139
- "delegate_to": delegate_to,
140
- "operation_params": {
141
- "task_id": task_id,
142
- "project_id": project_id,
143
- "attempt_id": attempt_id,
144
- "additional": operation_params
145
- }
146
- });
147
-
148
- // Create modified setup script execution with delegation context in args
149
- let setup_script = project.setup_script.as_ref().unwrap();
150
- let process_id = Uuid::new_v4();
151
-
152
- // Create execution process record with delegation context
153
- let _execution_process = Self::create_execution_process_record_with_delegation(
154
- pool,
155
- attempt_id,
156
- process_id,
157
- setup_script,
158
- &task_attempt.worktree_path,
159
- delegation_context,
160
- )
161
- .await?;
162
-
163
- // Setup script starting with delegation
164
-
165
- tracing::info!(
166
- "Starting setup script with delegation to {} for task attempt {}",
167
- delegate_to,
168
- attempt_id
169
- );
170
-
171
- // Execute the setup script
172
- let child = Self::execute_setup_script_process(
173
- setup_script,
174
- pool,
175
- task_id,
176
- attempt_id,
177
- process_id,
178
- &task_attempt.worktree_path,
179
- )
180
- .await?;
181
-
182
- // Register for monitoring
183
- Self::register_for_monitoring(
184
- app_state,
185
- process_id,
186
- attempt_id,
187
- &ExecutionProcessType::SetupScript,
188
- child,
189
- )
190
- .await;
191
-
192
- tracing::info!(
193
- "Started setup execution with delegation {} for task attempt {}",
194
- process_id,
195
- attempt_id
196
- );
197
- Ok(())
198
- }
199
-
200
- /// Start the execution flow for a task attempt (setup script + executor)
201
- pub async fn start_execution(
202
- pool: &SqlitePool,
203
- app_state: &crate::app_state::AppState,
204
- attempt_id: Uuid,
205
- task_id: Uuid,
206
- project_id: Uuid,
207
- ) -> Result<(), TaskAttemptError> {
208
- use crate::models::task::{Task, TaskStatus};
209
-
210
- // Load required entities
211
- let (task_attempt, project) =
212
- Self::load_execution_context(pool, attempt_id, project_id).await?;
213
-
214
- // Update task status to indicate execution has started
215
- Task::update_status(pool, task_id, project_id, TaskStatus::InProgress).await?;
216
-
217
- // Determine execution sequence based on project configuration
218
- if Self::should_run_setup_script(&project) {
219
- Self::start_setup_script(
220
- pool,
221
- app_state,
222
- attempt_id,
223
- task_id,
224
- &project,
225
- &task_attempt.worktree_path,
226
- )
227
- .await
228
- } else {
229
- Self::start_coding_agent(pool, app_state, attempt_id, task_id, project_id).await
230
- }
231
- }
232
-
233
- /// Start the coding agent after setup is complete or if no setup is needed
234
- pub async fn start_coding_agent(
235
- pool: &SqlitePool,
236
- app_state: &crate::app_state::AppState,
237
- attempt_id: Uuid,
238
- task_id: Uuid,
239
- _project_id: Uuid,
240
- ) -> Result<(), TaskAttemptError> {
241
- let task_attempt = TaskAttempt::find_by_id(pool, attempt_id)
242
- .await?
243
- .ok_or(TaskAttemptError::TaskNotFound)?;
244
-
245
- let executor_config = Self::resolve_executor_config(&task_attempt.executor);
246
-
247
- Self::start_process_execution(
248
- pool,
249
- app_state,
250
- attempt_id,
251
- task_id,
252
- crate::executor::ExecutorType::CodingAgent {
253
- config: executor_config,
254
- follow_up: None,
255
- },
256
- "Starting executor".to_string(),
257
- ExecutionProcessType::CodingAgent,
258
- &task_attempt.worktree_path,
259
- )
260
- .await
261
- }
262
-
263
- /// Start a dev server for this task attempt (with automatic setup)
264
- pub async fn start_dev_server(
265
- pool: &SqlitePool,
266
- app_state: &crate::app_state::AppState,
267
- attempt_id: Uuid,
268
- task_id: Uuid,
269
- project_id: Uuid,
270
- ) -> Result<(), TaskAttemptError> {
271
- // Ensure worktree exists (recreate if needed for cold task support)
272
- let _worktree_path =
273
- TaskAttempt::ensure_worktree_exists(pool, attempt_id, project_id, "dev server").await?;
274
-
275
- // Use automatic setup logic
276
- Self::auto_setup_and_execute(
277
- pool,
278
- app_state,
279
- attempt_id,
280
- task_id,
281
- project_id,
282
- "dev_server",
283
- None,
284
- )
285
- .await
286
- }
287
-
288
- /// Start a dev server directly without setup check (internal method)
289
- pub async fn start_dev_server_direct(
290
- pool: &SqlitePool,
291
- app_state: &crate::app_state::AppState,
292
- attempt_id: Uuid,
293
- task_id: Uuid,
294
- project_id: Uuid,
295
- ) -> Result<(), TaskAttemptError> {
296
- // Ensure worktree exists (recreate if needed for cold task support)
297
- let worktree_path =
298
- TaskAttempt::ensure_worktree_exists(pool, attempt_id, project_id, "dev server").await?;
299
-
300
- // Get the project to access the dev_script
301
- let project = Project::find_by_id(pool, project_id)
302
- .await?
303
- .ok_or(TaskAttemptError::TaskNotFound)?;
304
-
305
- let dev_script = project.dev_script.ok_or_else(|| {
306
- TaskAttemptError::ValidationError(
307
- "No dev script configured for this project".to_string(),
308
- )
309
- })?;
310
-
311
- if dev_script.trim().is_empty() {
312
- return Err(TaskAttemptError::ValidationError(
313
- "Dev script is empty".to_string(),
314
- ));
315
- }
316
-
317
- let result = Self::start_process_execution(
318
- pool,
319
- app_state,
320
- attempt_id,
321
- task_id,
322
- crate::executor::ExecutorType::DevServer(dev_script),
323
- "Starting dev server".to_string(),
324
- ExecutionProcessType::DevServer,
325
- &worktree_path,
326
- )
327
- .await;
328
-
329
- if result.is_ok() {
330
- app_state
331
- .track_analytics_event(
332
- "dev_server_started",
333
- Some(serde_json::json!({
334
- "task_id": task_id.to_string(),
335
- "project_id": project_id.to_string(),
336
- "attempt_id": attempt_id.to_string()
337
- })),
338
- )
339
- .await;
340
- }
341
-
342
- result
343
- }
344
-
345
- /// Start a follow-up execution using the same executor type as the first process (with automatic setup)
346
- /// Returns the attempt_id that was actually used (always the original attempt_id for session continuity)
347
- pub async fn start_followup_execution(
348
- pool: &SqlitePool,
349
- app_state: &crate::app_state::AppState,
350
- attempt_id: Uuid,
351
- task_id: Uuid,
352
- project_id: Uuid,
353
- prompt: &str,
354
- ) -> Result<Uuid, TaskAttemptError> {
355
- use crate::models::task::{Task, TaskStatus};
356
-
357
- // Get the current task attempt to check if worktree is deleted
358
- let current_attempt = TaskAttempt::find_by_id(pool, attempt_id)
359
- .await?
360
- .ok_or(TaskAttemptError::TaskNotFound)?;
361
-
362
- let actual_attempt_id = attempt_id;
363
-
364
- if current_attempt.worktree_deleted {
365
- info!(
366
- "Resurrecting deleted attempt {} (branch: {}) for followup execution - maintaining session continuity",
367
- attempt_id, current_attempt.branch
368
- );
369
- } else {
370
- info!(
371
- "Continuing followup execution on active attempt {} (branch: {})",
372
- attempt_id, current_attempt.branch
373
- );
374
- }
375
-
376
- // Update task status to indicate follow-up execution has started
377
- Task::update_status(pool, task_id, project_id, TaskStatus::InProgress).await?;
378
-
379
- // Ensure worktree exists (recreate if needed for cold task support)
380
- // This will resurrect the worktree at the exact same path for session continuity
381
- let _worktree_path =
382
- TaskAttempt::ensure_worktree_exists(pool, actual_attempt_id, project_id, "followup")
383
- .await?;
384
-
385
- // Use automatic setup logic with followup parameters
386
- let operation_params = serde_json::json!({
387
- "prompt": prompt
388
- });
389
-
390
- Self::auto_setup_and_execute(
391
- pool,
392
- app_state,
393
- attempt_id,
394
- task_id,
395
- project_id,
396
- "followup",
397
- Some(operation_params),
398
- )
399
- .await?;
400
-
401
- Ok(actual_attempt_id)
402
- }
403
-
404
- /// Start a follow-up execution directly without setup check (internal method)
405
- pub async fn start_followup_execution_direct(
406
- pool: &SqlitePool,
407
- app_state: &crate::app_state::AppState,
408
- attempt_id: Uuid,
409
- task_id: Uuid,
410
- project_id: Uuid,
411
- prompt: &str,
412
- ) -> Result<Uuid, TaskAttemptError> {
413
- // Ensure worktree exists (recreate if needed for cold task support)
414
- // This will resurrect the worktree at the exact same path for session continuity
415
- let worktree_path =
416
- TaskAttempt::ensure_worktree_exists(pool, attempt_id, project_id, "followup").await?;
417
-
418
- // Find the most recent coding agent execution process to get the executor type
419
- // Look up processes from the ORIGINAL attempt to find the session
420
- let execution_processes =
421
- ExecutionProcess::find_by_task_attempt_id(pool, attempt_id).await?;
422
- let most_recent_coding_agent = execution_processes
423
- .iter()
424
- .rev() // Reverse to get most recent first (since they're ordered by created_at ASC)
425
- .find(|p| matches!(p.process_type, ExecutionProcessType::CodingAgent))
426
- .ok_or_else(|| {
427
- tracing::error!(
428
- "No previous coding agent execution found for task attempt {}. Found {} processes: {:?}",
429
- attempt_id,
430
- execution_processes.len(),
431
- execution_processes.iter().map(|p| format!("{:?}", p.process_type)).collect::<Vec<_>>()
432
- );
433
- TaskAttemptError::ValidationError("No previous coding agent execution found for follow-up".to_string())
434
- })?;
435
-
436
- // Get the executor session to find the session ID
437
- // This looks up the session from the original attempt's processes
438
- let executor_session =
439
- ExecutorSession::find_by_execution_process_id(pool, most_recent_coding_agent.id)
440
- .await?
441
- .ok_or_else(|| {
442
- tracing::error!(
443
- "No executor session found for execution process {} (task attempt {})",
444
- most_recent_coding_agent.id,
445
- attempt_id
446
- );
447
- TaskAttemptError::ValidationError(
448
- "No executor session found for follow-up".to_string(),
449
- )
450
- })?;
451
-
452
- let executor_config: crate::executor::ExecutorConfig = match most_recent_coding_agent
453
- .executor_type
454
- .as_deref()
455
- {
456
- Some(executor_str) => executor_str.parse().unwrap(),
457
- _ => {
458
- tracing::error!(
459
- "Invalid or missing executor type '{}' for execution process {} (task attempt {})",
460
- most_recent_coding_agent.executor_type.as_deref().unwrap_or("None"),
461
- most_recent_coding_agent.id,
462
- attempt_id
463
- );
464
- return Err(TaskAttemptError::ValidationError(format!(
465
- "Invalid executor type for follow-up: {}",
466
- most_recent_coding_agent
467
- .executor_type
468
- .as_deref()
469
- .unwrap_or("None")
470
- )));
471
- }
472
- };
473
-
474
- // Try to use follow-up with session ID, but fall back to new session if it fails
475
- let followup_executor = if let Some(session_id) = &executor_session.session_id {
476
- // First try with session ID for continuation
477
- debug!(
478
- "SESSION_FOLLOWUP: Attempting follow-up execution with session ID: {} (attempt: {}, worktree: {})",
479
- session_id, attempt_id, worktree_path
480
- );
481
- crate::executor::ExecutorType::CodingAgent {
482
- config: executor_config.clone(),
483
- follow_up: Some(crate::executor::FollowUpInfo {
484
- session_id: session_id.clone(),
485
- prompt: prompt.to_string(),
486
- }),
487
- }
488
- } else {
489
- // No session ID available, start new session
490
- tracing::warn!(
491
- "SESSION_FOLLOWUP: No session ID available for follow-up execution on attempt {}, starting new session (worktree: {})",
492
- attempt_id, worktree_path
493
- );
494
- crate::executor::ExecutorType::CodingAgent {
495
- config: executor_config.clone(),
496
- follow_up: None,
497
- }
498
- };
499
-
500
- // Try to start the follow-up execution
501
- let execution_result = Self::start_process_execution(
502
- pool,
503
- app_state,
504
- attempt_id,
505
- task_id,
506
- followup_executor,
507
- "Starting follow-up executor".to_string(),
508
- ExecutionProcessType::CodingAgent,
509
- &worktree_path,
510
- )
511
- .await;
512
-
513
- // If follow-up execution failed and we tried to use a session ID,
514
- // fall back to a new session
515
- if execution_result.is_err() && executor_session.session_id.is_some() {
516
- tracing::warn!(
517
- "SESSION_FOLLOWUP: Follow-up execution with session ID '{}' failed for attempt {}, falling back to new session. Error: {:?}",
518
- executor_session.session_id.as_ref().unwrap(),
519
- attempt_id,
520
- execution_result.as_ref().err()
521
- );
522
-
523
- // Create a new session instead of trying to resume
524
- let new_session_executor = crate::executor::ExecutorType::CodingAgent {
525
- config: executor_config,
526
- follow_up: None,
527
- };
528
-
529
- Self::start_process_execution(
530
- pool,
531
- app_state,
532
- attempt_id,
533
- task_id,
534
- new_session_executor,
535
- "Starting new executor session (follow-up session failed)".to_string(),
536
- ExecutionProcessType::CodingAgent,
537
- &worktree_path,
538
- )
539
- .await?;
540
- } else {
541
- // Either it succeeded or we already tried without session ID
542
- execution_result?;
543
- }
544
-
545
- Ok(attempt_id)
546
- }
547
-
548
- /// Unified function to start any type of process execution
549
- #[allow(clippy::too_many_arguments)]
550
- pub async fn start_process_execution(
551
- pool: &SqlitePool,
552
- app_state: &crate::app_state::AppState,
553
- attempt_id: Uuid,
554
- task_id: Uuid,
555
- executor_type: crate::executor::ExecutorType,
556
- activity_note: String,
557
- process_type: ExecutionProcessType,
558
- worktree_path: &str,
559
- ) -> Result<(), TaskAttemptError> {
560
- let process_id = Uuid::new_v4();
561
-
562
- // Create execution process record
563
- let _execution_process = Self::create_execution_process_record(
564
- pool,
565
- attempt_id,
566
- process_id,
567
- &executor_type,
568
- process_type.clone(),
569
- worktree_path,
570
- )
571
- .await?;
572
-
573
- // Create executor session for coding agents
574
- if matches!(process_type, ExecutionProcessType::CodingAgent) {
575
- // Extract follow-up prompt if this is a follow-up execution
576
- let followup_prompt = match &executor_type {
577
- crate::executor::ExecutorType::CodingAgent {
578
- follow_up: Some(ref info),
579
- ..
580
- } => Some(info.prompt.clone()),
581
- _ => None,
582
- };
583
- Self::create_executor_session_record(
584
- pool,
585
- attempt_id,
586
- task_id,
587
- process_id,
588
- followup_prompt,
589
- )
590
- .await?;
591
- }
592
-
593
- // Process started successfully
594
-
595
- tracing::info!("Starting {} for task attempt {}", activity_note, attempt_id);
596
-
597
- // Execute the process
598
- let child = Self::execute_process(
599
- &executor_type,
600
- pool,
601
- task_id,
602
- attempt_id,
603
- process_id,
604
- worktree_path,
605
- )
606
- .await?;
607
-
608
- // Register for monitoring
609
- Self::register_for_monitoring(app_state, process_id, attempt_id, &process_type, child)
610
- .await;
611
-
612
- tracing::info!(
613
- "Started execution {} for task attempt {}",
614
- process_id,
615
- attempt_id
616
- );
617
- Ok(())
618
- }
619
-
620
- /// Load the execution context (task attempt and project) with validation
621
- async fn load_execution_context(
622
- pool: &SqlitePool,
623
- attempt_id: Uuid,
624
- project_id: Uuid,
625
- ) -> Result<(TaskAttempt, Project), TaskAttemptError> {
626
- let task_attempt = TaskAttempt::find_by_id(pool, attempt_id)
627
- .await?
628
- .ok_or(TaskAttemptError::TaskNotFound)?;
629
-
630
- let project = Project::find_by_id(pool, project_id)
631
- .await?
632
- .ok_or(TaskAttemptError::ProjectNotFound)?;
633
-
634
- Ok((task_attempt, project))
635
- }
636
-
637
- /// Check if setup script should be executed
638
- fn should_run_setup_script(project: &Project) -> bool {
639
- project
640
- .setup_script
641
- .as_ref()
642
- .map(|script| !script.trim().is_empty())
643
- .unwrap_or(false)
644
- }
645
-
646
- fn should_run_cleanup_script(project: &Project) -> bool {
647
- project
648
- .cleanup_script
649
- .as_ref()
650
- .map(|script| !script.trim().is_empty())
651
- .unwrap_or(false)
652
- }
653
-
654
- /// Start the setup script execution
655
- async fn start_setup_script(
656
- pool: &SqlitePool,
657
- app_state: &crate::app_state::AppState,
658
- attempt_id: Uuid,
659
- task_id: Uuid,
660
- project: &Project,
661
- worktree_path: &str,
662
- ) -> Result<(), TaskAttemptError> {
663
- let setup_script = project.setup_script.as_ref().unwrap();
664
-
665
- Self::start_process_execution(
666
- pool,
667
- app_state,
668
- attempt_id,
669
- task_id,
670
- crate::executor::ExecutorType::SetupScript(setup_script.clone()),
671
- "Starting setup script".to_string(),
672
- ExecutionProcessType::SetupScript,
673
- worktree_path,
674
- )
675
- .await
676
- }
677
-
678
- /// Start the cleanup script execution
679
- async fn start_cleanup_script(
680
- pool: &SqlitePool,
681
- app_state: &crate::app_state::AppState,
682
- attempt_id: Uuid,
683
- task_id: Uuid,
684
- project: &Project,
685
- worktree_path: &str,
686
- ) -> Result<(), TaskAttemptError> {
687
- let cleanup_script = project.cleanup_script.as_ref().unwrap();
688
-
689
- Self::start_process_execution(
690
- pool,
691
- app_state,
692
- attempt_id,
693
- task_id,
694
- crate::executor::ExecutorType::CleanupScript(cleanup_script.clone()),
695
- "Starting cleanup script".to_string(),
696
- ExecutionProcessType::CleanupScript,
697
- worktree_path,
698
- )
699
- .await
700
- }
701
-
702
- /// Resolve executor configuration from string name
703
- fn resolve_executor_config(executor_name: &Option<String>) -> crate::executor::ExecutorConfig {
704
- match executor_name.as_ref().map(|s| s.as_str()) {
705
- Some("claude") => crate::executor::ExecutorConfig::Claude,
706
- Some("claude-plan") => crate::executor::ExecutorConfig::ClaudePlan,
707
- Some("claude-code-router") => crate::executor::ExecutorConfig::ClaudeCodeRouter,
708
- Some("amp") => crate::executor::ExecutorConfig::Amp,
709
- Some("gemini") => crate::executor::ExecutorConfig::Gemini,
710
- Some("charm-opencode") => crate::executor::ExecutorConfig::CharmOpencode,
711
- Some("sst-opencode") => crate::executor::ExecutorConfig::SstOpencode,
712
- Some("opencode-ai") => crate::executor::ExecutorConfig::OpencodeAi,
713
- _ => crate::executor::ExecutorConfig::Echo, // Default for "echo" or None
714
- }
715
- }
716
-
717
- /// Create execution process database record
718
- async fn create_execution_process_record(
719
- pool: &SqlitePool,
720
- attempt_id: Uuid,
721
- process_id: Uuid,
722
- executor_type: &crate::executor::ExecutorType,
723
- process_type: ExecutionProcessType,
724
- worktree_path: &str,
725
- ) -> Result<ExecutionProcess, TaskAttemptError> {
726
- let (shell_cmd, shell_arg) = get_shell_command();
727
- let (command, args, executor_type_string) = match executor_type {
728
- crate::executor::ExecutorType::SetupScript(_) => (
729
- shell_cmd.to_string(),
730
- Some(serde_json::to_string(&[shell_arg, "setup-script"]).unwrap()),
731
- Some("setup-script".to_string()),
732
- ),
733
- crate::executor::ExecutorType::CleanupScript(_) => (
734
- shell_cmd.to_string(),
735
- Some(serde_json::to_string(&[shell_arg, "cleanup-script"]).unwrap()),
736
- Some("cleanup-script".to_string()),
737
- ),
738
- crate::executor::ExecutorType::DevServer(_) => (
739
- shell_cmd.to_string(),
740
- Some(serde_json::to_string(&[shell_arg, "dev_server"]).unwrap()),
741
- None, // Dev servers don't have an executor type
742
- ),
743
- crate::executor::ExecutorType::CodingAgent { config, follow_up } => {
744
- let command = if follow_up.is_some() {
745
- "followup_executor".to_string()
746
- } else {
747
- "executor".to_string()
748
- };
749
- (command, None, Some(format!("{}", config)))
750
- }
751
- };
752
-
753
- let create_process = CreateExecutionProcess {
754
- task_attempt_id: attempt_id,
755
- process_type,
756
- executor_type: executor_type_string,
757
- command,
758
- args,
759
- working_directory: worktree_path.to_string(),
760
- };
761
-
762
- ExecutionProcess::create(pool, &create_process, process_id)
763
- .await
764
- .map_err(TaskAttemptError::from)
765
- }
766
-
767
- /// Create executor session record for coding agents
768
- async fn create_executor_session_record(
769
- pool: &SqlitePool,
770
- attempt_id: Uuid,
771
- task_id: Uuid,
772
- process_id: Uuid,
773
- followup_prompt: Option<String>,
774
- ) -> Result<(), TaskAttemptError> {
775
- // Use follow-up prompt if provided, otherwise get the task to create prompt
776
- let prompt = if let Some(followup_prompt) = followup_prompt {
777
- followup_prompt
778
- } else {
779
- let task = Task::find_by_id(pool, task_id)
780
- .await?
781
- .ok_or(TaskAttemptError::TaskNotFound)?;
782
- format!("{}\n\n{}", task.title, task.description.unwrap_or_default())
783
- };
784
-
785
- let session_id = Uuid::new_v4();
786
- let create_session = CreateExecutorSession {
787
- task_attempt_id: attempt_id,
788
- execution_process_id: process_id,
789
- prompt: Some(prompt),
790
- };
791
-
792
- ExecutorSession::create(pool, &create_session, session_id)
793
- .await
794
- .map(|_| ())
795
- .map_err(TaskAttemptError::from)
796
- }
797
-
798
- /// Execute the process based on type
799
- async fn execute_process(
800
- executor_type: &crate::executor::ExecutorType,
801
- pool: &SqlitePool,
802
- task_id: Uuid,
803
- attempt_id: Uuid,
804
- process_id: Uuid,
805
- worktree_path: &str,
806
- ) -> Result<command_group::AsyncGroupChild, TaskAttemptError> {
807
- use crate::executors::{CleanupScriptExecutor, DevServerExecutor, SetupScriptExecutor};
808
-
809
- let result = match executor_type {
810
- crate::executor::ExecutorType::SetupScript(script) => {
811
- let executor = SetupScriptExecutor {
812
- script: script.clone(),
813
- };
814
- executor
815
- .execute_streaming(pool, task_id, attempt_id, process_id, worktree_path)
816
- .await
817
- }
818
- crate::executor::ExecutorType::CleanupScript(script) => {
819
- let executor = CleanupScriptExecutor {
820
- script: script.clone(),
821
- };
822
- executor
823
- .execute_streaming(pool, task_id, attempt_id, process_id, worktree_path)
824
- .await
825
- }
826
- crate::executor::ExecutorType::DevServer(script) => {
827
- let executor = DevServerExecutor {
828
- script: script.clone(),
829
- };
830
- executor
831
- .execute_streaming(pool, task_id, attempt_id, process_id, worktree_path)
832
- .await
833
- }
834
- crate::executor::ExecutorType::CodingAgent { config, follow_up } => {
835
- let executor = config.create_executor();
836
-
837
- if let Some(ref follow_up_info) = follow_up {
838
- executor
839
- .execute_followup_streaming(
840
- pool,
841
- task_id,
842
- attempt_id,
843
- process_id,
844
- &follow_up_info.session_id,
845
- &follow_up_info.prompt,
846
- worktree_path,
847
- )
848
- .await
849
- } else {
850
- executor
851
- .execute_streaming(pool, task_id, attempt_id, process_id, worktree_path)
852
- .await
853
- }
854
- }
855
- };
856
-
857
- result.map_err(|e| TaskAttemptError::Git(git2::Error::from_str(&e.to_string())))
858
- }
859
-
860
- /// Register process for monitoring
861
- async fn register_for_monitoring(
862
- app_state: &crate::app_state::AppState,
863
- process_id: Uuid,
864
- attempt_id: Uuid,
865
- process_type: &ExecutionProcessType,
866
- child: command_group::AsyncGroupChild,
867
- ) {
868
- let execution_type = match process_type {
869
- ExecutionProcessType::SetupScript => crate::app_state::ExecutionType::SetupScript,
870
- ExecutionProcessType::CleanupScript => crate::app_state::ExecutionType::CleanupScript,
871
- ExecutionProcessType::CodingAgent => crate::app_state::ExecutionType::CodingAgent,
872
- ExecutionProcessType::DevServer => crate::app_state::ExecutionType::DevServer,
873
- };
874
-
875
- app_state
876
- .add_running_execution(
877
- process_id,
878
- crate::app_state::RunningExecution {
879
- task_attempt_id: attempt_id,
880
- _execution_type: execution_type,
881
- child,
882
- },
883
- )
884
- .await;
885
- }
886
-
887
- /// Create execution process database record with delegation context
888
- async fn create_execution_process_record_with_delegation(
889
- pool: &SqlitePool,
890
- attempt_id: Uuid,
891
- process_id: Uuid,
892
- _setup_script: &str,
893
- worktree_path: &str,
894
- delegation_context: serde_json::Value,
895
- ) -> Result<ExecutionProcess, TaskAttemptError> {
896
- let (shell_cmd, shell_arg) = get_shell_command();
897
-
898
- // Store delegation context in args for execution monitor to read
899
- let args_with_delegation = serde_json::json!([
900
- shell_arg,
901
- "setup-script",
902
- "--delegation-context",
903
- delegation_context.to_string()
904
- ]);
905
-
906
- let create_process = CreateExecutionProcess {
907
- task_attempt_id: attempt_id,
908
- process_type: ExecutionProcessType::SetupScript,
909
- executor_type: Some("setup-script".to_string()),
910
- command: shell_cmd.to_string(),
911
- args: Some(args_with_delegation.to_string()),
912
- working_directory: worktree_path.to_string(),
913
- };
914
-
915
- ExecutionProcess::create(pool, &create_process, process_id)
916
- .await
917
- .map_err(TaskAttemptError::from)
918
- }
919
-
920
- /// Execute setup script process specifically
921
- async fn execute_setup_script_process(
922
- setup_script: &str,
923
- pool: &SqlitePool,
924
- task_id: Uuid,
925
- attempt_id: Uuid,
926
- process_id: Uuid,
927
- worktree_path: &str,
928
- ) -> Result<command_group::AsyncGroupChild, TaskAttemptError> {
929
- use crate::executors::SetupScriptExecutor;
930
-
931
- let executor = SetupScriptExecutor {
932
- script: setup_script.to_string(),
933
- };
934
-
935
- executor
936
- .execute_streaming(pool, task_id, attempt_id, process_id, worktree_path)
937
- .await
938
- .map_err(|e| TaskAttemptError::Git(git2::Error::from_str(&e.to_string())))
939
- }
940
- }