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,899 +0,0 @@
1
- import {
2
- Check,
3
- ExternalLink,
4
- GitBranch as GitBranchIcon,
5
- GitPullRequest,
6
- History,
7
- Play,
8
- Plus,
9
- RefreshCw,
10
- Settings,
11
- StopCircle,
12
- } from 'lucide-react';
13
- import { is_planning_executor_type } from '@/lib/utils';
14
- import {
15
- Tooltip,
16
- TooltipContent,
17
- TooltipProvider,
18
- TooltipTrigger,
19
- } from '@/components/ui/tooltip.tsx';
20
- import { Button } from '@/components/ui/button.tsx';
21
- import {
22
- DropdownMenu,
23
- DropdownMenuContent,
24
- DropdownMenuItem,
25
- DropdownMenuTrigger,
26
- } from '@/components/ui/dropdown-menu.tsx';
27
- import {
28
- Dialog,
29
- DialogContent,
30
- DialogDescription,
31
- DialogFooter,
32
- DialogHeader,
33
- DialogTitle,
34
- } from '@/components/ui/dialog.tsx';
35
- import BranchSelector from '@/components/tasks/BranchSelector.tsx';
36
- import {
37
- attemptsApi,
38
- executionProcessesApi,
39
- makeRequest,
40
- FollowUpResponse,
41
- ApiResponse,
42
- } from '@/lib/api.ts';
43
- import {
44
- Dispatch,
45
- SetStateAction,
46
- useCallback,
47
- useContext,
48
- useEffect,
49
- useMemo,
50
- useState,
51
- } from 'react';
52
- import type {
53
- BranchStatus,
54
- ExecutionProcess,
55
- GitBranch,
56
- TaskAttempt,
57
- } from 'shared/types.ts';
58
- import {
59
- TaskAttemptDataContext,
60
- TaskAttemptStoppingContext,
61
- TaskDetailsContext,
62
- TaskExecutionStateContext,
63
- TaskRelatedTasksContext,
64
- TaskSelectedAttemptContext,
65
- } from '@/components/context/taskDetailsContext.ts';
66
- import { useConfig } from '@/components/config-provider.tsx';
67
- import { useKeyboardShortcuts } from '@/lib/keyboard-shortcuts.ts';
68
- import { useNavigate } from 'react-router-dom';
69
-
70
- // Helper function to get the display name for different editor types
71
- function getEditorDisplayName(editorType: string): string {
72
- switch (editorType) {
73
- case 'vscode':
74
- return 'Visual Studio Code';
75
- case 'cursor':
76
- return 'Cursor';
77
- case 'windsurf':
78
- return 'Windsurf';
79
- case 'intellij':
80
- return 'IntelliJ IDEA';
81
- case 'zed':
82
- return 'Zed';
83
- case 'custom':
84
- return 'Custom Editor';
85
- default:
86
- return 'Editor';
87
- }
88
- }
89
-
90
- type Props = {
91
- setError: Dispatch<SetStateAction<string | null>>;
92
- setShowCreatePRDialog: Dispatch<SetStateAction<boolean>>;
93
- selectedBranch: string | null;
94
- selectedAttempt: TaskAttempt;
95
- taskAttempts: TaskAttempt[];
96
- creatingPR: boolean;
97
- handleEnterCreateAttemptMode: () => void;
98
- availableExecutors: {
99
- id: string;
100
- name: string;
101
- }[];
102
- branches: GitBranch[];
103
- };
104
-
105
- function CurrentAttempt({
106
- setError,
107
- setShowCreatePRDialog,
108
- selectedBranch,
109
- selectedAttempt,
110
- taskAttempts,
111
- creatingPR,
112
- handleEnterCreateAttemptMode,
113
- availableExecutors,
114
- branches,
115
- }: Props) {
116
- const { task, projectId, handleOpenInEditor, projectHasDevScript } =
117
- useContext(TaskDetailsContext);
118
- const { config } = useConfig();
119
- const { setSelectedAttempt } = useContext(TaskSelectedAttemptContext);
120
- const navigate = useNavigate();
121
- const { isStopping, setIsStopping } = useContext(TaskAttemptStoppingContext);
122
- const { attemptData, fetchAttemptData, isAttemptRunning } = useContext(
123
- TaskAttemptDataContext
124
- );
125
- const { relatedTasks } = useContext(TaskRelatedTasksContext);
126
- const { executionState, fetchExecutionState } = useContext(
127
- TaskExecutionStateContext
128
- );
129
-
130
- const [isStartingDevServer, setIsStartingDevServer] = useState(false);
131
- const [merging, setMerging] = useState(false);
132
- const [rebasing, setRebasing] = useState(false);
133
- const [devServerDetails, setDevServerDetails] =
134
- useState<ExecutionProcess | null>(null);
135
- const [isHoveringDevServer, setIsHoveringDevServer] = useState(false);
136
- const [branchStatus, setBranchStatus] = useState<BranchStatus | null>(null);
137
- const [branchStatusLoading, setBranchStatusLoading] = useState(false);
138
- const [showRebaseDialog, setShowRebaseDialog] = useState(false);
139
- const [selectedRebaseBranch, setSelectedRebaseBranch] = useState<string>('');
140
- const [showStopConfirmation, setShowStopConfirmation] = useState(false);
141
- const [isApprovingPlan, setIsApprovingPlan] = useState(false);
142
- const [copied, setCopied] = useState(false);
143
-
144
- const processedDevServerLogs = useMemo(() => {
145
- if (!devServerDetails) return 'No output yet...';
146
-
147
- const stdout = devServerDetails.stdout || '';
148
- const stderr = devServerDetails.stderr || '';
149
- const allOutput = stdout + (stderr ? '\n' + stderr : '');
150
- const lines = allOutput.split('\n').filter((line) => line.trim());
151
- const lastLines = lines.slice(-10);
152
- return lastLines.length > 0 ? lastLines.join('\n') : 'No output yet...';
153
- }, [devServerDetails]);
154
-
155
- // Find running dev server in current project
156
- const runningDevServer = useMemo(() => {
157
- return attemptData.processes.find(
158
- (process) =>
159
- process.process_type === 'devserver' && process.status === 'running'
160
- );
161
- }, [attemptData.processes]);
162
-
163
- // Check if plan approval is needed
164
- const isPlanTask = useMemo(() => {
165
- return !!(
166
- selectedAttempt.executor &&
167
- is_planning_executor_type(selectedAttempt.executor)
168
- );
169
- }, [selectedAttempt.executor]);
170
-
171
- const fetchDevServerDetails = useCallback(async () => {
172
- if (!runningDevServer || !task || !selectedAttempt) return;
173
-
174
- try {
175
- const result = await executionProcessesApi.getDetails(
176
- runningDevServer.id
177
- );
178
- setDevServerDetails(result);
179
- } catch (err) {
180
- console.error('Failed to fetch dev server details:', err);
181
- }
182
- }, [runningDevServer, task, selectedAttempt, projectId]);
183
-
184
- useEffect(() => {
185
- if (!isHoveringDevServer || !runningDevServer) {
186
- setDevServerDetails(null);
187
- return;
188
- }
189
-
190
- fetchDevServerDetails();
191
- const interval = setInterval(fetchDevServerDetails, 2000);
192
- return () => clearInterval(interval);
193
- }, [isHoveringDevServer, runningDevServer, fetchDevServerDetails]);
194
-
195
- const startDevServer = async () => {
196
- if (!task || !selectedAttempt) return;
197
-
198
- setIsStartingDevServer(true);
199
-
200
- try {
201
- await attemptsApi.startDevServer(
202
- projectId,
203
- selectedAttempt.task_id,
204
- selectedAttempt.id
205
- );
206
- fetchAttemptData(selectedAttempt.id, selectedAttempt.task_id);
207
- } catch (err) {
208
- console.error('Failed to start dev server:', err);
209
- } finally {
210
- setIsStartingDevServer(false);
211
- }
212
- };
213
-
214
- const stopDevServer = async () => {
215
- if (!task || !selectedAttempt || !runningDevServer) return;
216
-
217
- setIsStartingDevServer(true);
218
-
219
- try {
220
- await attemptsApi.stopExecutionProcess(
221
- projectId,
222
- selectedAttempt.task_id,
223
- selectedAttempt.id,
224
- runningDevServer.id
225
- );
226
- fetchAttemptData(selectedAttempt.id, selectedAttempt.task_id);
227
- } catch (err) {
228
- console.error('Failed to stop dev server:', err);
229
- } finally {
230
- setIsStartingDevServer(false);
231
- }
232
- };
233
-
234
- const stopAllExecutions = useCallback(async () => {
235
- if (!task || !selectedAttempt || !isAttemptRunning) return;
236
-
237
- try {
238
- setIsStopping(true);
239
- await attemptsApi.stop(
240
- projectId,
241
- selectedAttempt.task_id,
242
- selectedAttempt.id
243
- );
244
- await fetchAttemptData(selectedAttempt.id, selectedAttempt.task_id);
245
- setTimeout(() => {
246
- fetchAttemptData(selectedAttempt.id, selectedAttempt.task_id);
247
- }, 1000);
248
- } catch (err) {
249
- console.error('Failed to stop executions:', err);
250
- } finally {
251
- setIsStopping(false);
252
- }
253
- }, [
254
- task,
255
- selectedAttempt,
256
- projectId,
257
- fetchAttemptData,
258
- setIsStopping,
259
- isAttemptRunning,
260
- ]);
261
-
262
- useKeyboardShortcuts({
263
- stopExecution: () => setShowStopConfirmation(true),
264
- newAttempt: !isAttemptRunning ? handleEnterCreateAttemptMode : () => {},
265
- hasOpenDialog: showStopConfirmation,
266
- closeDialog: () => setShowStopConfirmation(false),
267
- onEnter: () => {
268
- setShowStopConfirmation(false);
269
- stopAllExecutions();
270
- },
271
- });
272
-
273
- const handleAttemptChange = useCallback(
274
- (attempt: TaskAttempt) => {
275
- setSelectedAttempt(attempt);
276
- fetchAttemptData(attempt.id, attempt.task_id);
277
- fetchExecutionState(attempt.id, attempt.task_id);
278
- },
279
- [fetchAttemptData, fetchExecutionState, setSelectedAttempt]
280
- );
281
-
282
- const handleMergeClick = async () => {
283
- if (!projectId || !selectedAttempt?.id || !selectedAttempt?.task_id) return;
284
-
285
- // Directly perform merge without checking branch status
286
- await performMerge();
287
- };
288
-
289
- const fetchBranchStatus = useCallback(async () => {
290
- if (!projectId || !selectedAttempt?.id || !selectedAttempt?.task_id) return;
291
-
292
- try {
293
- setBranchStatusLoading(true);
294
- const result = await attemptsApi.getBranchStatus(
295
- projectId,
296
- selectedAttempt.task_id,
297
- selectedAttempt.id
298
- );
299
- setBranchStatus((prev) => {
300
- if (JSON.stringify(prev) === JSON.stringify(result)) return prev;
301
- return result;
302
- });
303
- } catch (err) {
304
- setError('Failed to load branch status');
305
- } finally {
306
- setBranchStatusLoading(false);
307
- }
308
- }, [projectId, selectedAttempt?.id, selectedAttempt?.task_id, setError]);
309
-
310
- // Fetch branch status when selected attempt changes
311
- useEffect(() => {
312
- if (selectedAttempt) {
313
- fetchBranchStatus();
314
- }
315
- }, [selectedAttempt, fetchBranchStatus]);
316
-
317
- const performMerge = async () => {
318
- if (!projectId || !selectedAttempt?.id || !selectedAttempt?.task_id) return;
319
-
320
- try {
321
- setMerging(true);
322
- await attemptsApi.merge(
323
- projectId,
324
- selectedAttempt.task_id,
325
- selectedAttempt.id
326
- );
327
- // Refetch branch status to show updated state
328
- fetchBranchStatus();
329
- } catch (error) {
330
- console.error('Failed to merge changes:', error);
331
- // @ts-expect-error it is type ApiError
332
- setError(error.message || 'Failed to merge changes');
333
- } finally {
334
- setMerging(false);
335
- }
336
- };
337
-
338
- const handleRebaseClick = async () => {
339
- if (!projectId || !selectedAttempt?.id || !selectedAttempt?.task_id) return;
340
-
341
- try {
342
- setRebasing(true);
343
- await attemptsApi.rebase(
344
- projectId,
345
- selectedAttempt.task_id,
346
- selectedAttempt.id
347
- );
348
- // Refresh branch status after rebase
349
- fetchBranchStatus();
350
- } catch (err) {
351
- setError(err instanceof Error ? err.message : 'Failed to rebase branch');
352
- } finally {
353
- setRebasing(false);
354
- }
355
- };
356
-
357
- const handleRebaseWithNewBranch = async (newBaseBranch: string) => {
358
- if (!projectId || !selectedAttempt?.id || !selectedAttempt?.task_id) return;
359
-
360
- try {
361
- setRebasing(true);
362
- await attemptsApi.rebase(
363
- projectId,
364
- selectedAttempt.task_id,
365
- selectedAttempt.id,
366
- newBaseBranch
367
- );
368
- // Refresh branch status after rebase
369
- fetchBranchStatus();
370
- setShowRebaseDialog(false);
371
- } catch (err) {
372
- setError(err instanceof Error ? err.message : 'Failed to rebase branch');
373
- } finally {
374
- setRebasing(false);
375
- }
376
- };
377
-
378
- const handleRebaseDialogConfirm = () => {
379
- if (selectedRebaseBranch) {
380
- handleRebaseWithNewBranch(selectedRebaseBranch);
381
- }
382
- };
383
-
384
- const handleRebaseDialogOpen = () => {
385
- setSelectedRebaseBranch('');
386
- setShowRebaseDialog(true);
387
- };
388
-
389
- const handleCreatePRClick = async () => {
390
- if (!projectId || !selectedAttempt?.id || !selectedAttempt?.task_id) return;
391
-
392
- // If PR already exists, open it
393
- if (selectedAttempt.pr_url) {
394
- window.open(selectedAttempt.pr_url, '_blank');
395
- return;
396
- }
397
-
398
- setShowCreatePRDialog(true);
399
- };
400
-
401
- const handlePlanApproval = async () => {
402
- if (!task || !selectedAttempt || !isPlanTask) return;
403
-
404
- setIsApprovingPlan(true);
405
- try {
406
- const response = await makeRequest(
407
- `/api/projects/${projectId}/tasks/${task.id}/attempts/${selectedAttempt.id}/approve-plan`,
408
- {
409
- method: 'POST',
410
- // No body needed - endpoint only handles approval now
411
- }
412
- );
413
-
414
- if (response.ok) {
415
- const result: ApiResponse<FollowUpResponse> = await response.json();
416
- if (result.success && result.data) {
417
- console.log('Plan approved successfully:', result.message);
418
-
419
- // If a new task was created, navigate to it
420
- if (result.data.created_new_attempt) {
421
- const newTaskId = result.data.actual_attempt_id;
422
- console.log('Navigating to new task:', newTaskId);
423
- navigate(`/projects/${projectId}/tasks/${newTaskId}`);
424
- } else {
425
- // Otherwise, just refresh the current task data
426
- fetchAttemptData(selectedAttempt.id, selectedAttempt.task_id);
427
- }
428
- } else {
429
- setError(`Failed to approve plan: ${result.message}`);
430
- }
431
- } else {
432
- setError('Failed to approve plan');
433
- }
434
- } catch (error) {
435
- setError(
436
- `Error approving plan: ${error instanceof Error ? error.message : 'Unknown error'}`
437
- );
438
- } finally {
439
- setIsApprovingPlan(false);
440
- }
441
- };
442
-
443
- // Get display name for selected branch
444
- const selectedBranchDisplayName = useMemo(() => {
445
- if (!selectedBranch) return 'current';
446
-
447
- // For remote branches, show just the branch name without the remote prefix
448
- if (selectedBranch.includes('/')) {
449
- const parts = selectedBranch.split('/');
450
- return parts[parts.length - 1];
451
- }
452
- return selectedBranch;
453
- }, [selectedBranch]);
454
-
455
- // Get display name for the configured editor
456
- const editorDisplayName = useMemo(() => {
457
- if (!config?.editor?.editor_type) return 'Editor';
458
- return getEditorDisplayName(config.editor.editor_type);
459
- }, [config?.editor?.editor_type]);
460
-
461
- const handleCopyWorktreePath = useCallback(async () => {
462
- try {
463
- await navigator.clipboard.writeText(selectedAttempt.worktree_path);
464
- setCopied(true);
465
- setTimeout(() => setCopied(false), 2000);
466
- } catch (err) {
467
- console.error('Failed to copy worktree path:', err);
468
- }
469
- }, [selectedAttempt.worktree_path]);
470
-
471
- return (
472
- <div className="space-y-2">
473
- <div className="grid grid-cols-4 gap-3 items-start">
474
- <div>
475
- <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1">
476
- Started
477
- </div>
478
- <div className="text-sm font-medium">
479
- {new Date(selectedAttempt.created_at).toLocaleDateString()}{' '}
480
- {new Date(selectedAttempt.created_at).toLocaleTimeString([], {
481
- hour: '2-digit',
482
- minute: '2-digit',
483
- })}
484
- </div>
485
- </div>
486
-
487
- <div>
488
- <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1">
489
- Agent
490
- </div>
491
- <div className="text-sm font-medium">
492
- {availableExecutors.find((e) => e.id === selectedAttempt.executor)
493
- ?.name ||
494
- selectedAttempt.executor ||
495
- 'Unknown'}
496
- </div>
497
- </div>
498
-
499
- <div>
500
- <div className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1">
501
- <span>Base Branch</span>
502
- <TooltipProvider>
503
- <Tooltip>
504
- <TooltipTrigger asChild>
505
- <Button
506
- variant="ghost"
507
- size="sm"
508
- onClick={handleRebaseDialogOpen}
509
- disabled={
510
- rebasing ||
511
- branchStatusLoading ||
512
- isAttemptRunning ||
513
- isPlanTask
514
- }
515
- className="h-4 w-4 p-0 hover:bg-muted"
516
- >
517
- <Settings className="h-3 w-3" />
518
- </Button>
519
- </TooltipTrigger>
520
- <TooltipContent>
521
- <p>Change base branch</p>
522
- </TooltipContent>
523
- </Tooltip>
524
- </TooltipProvider>
525
- </div>
526
- <div className="flex items-center gap-1.5">
527
- <GitBranchIcon className="h-3 w-3 text-muted-foreground" />
528
- <span className="text-sm font-medium">
529
- {branchStatus?.base_branch_name || selectedBranchDisplayName}
530
- </span>
531
- </div>
532
- </div>
533
-
534
- <div>
535
- <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1">
536
- {isPlanTask ? 'Plan Status' : 'Merge Status'}
537
- </div>
538
- <div className="flex items-center gap-1.5">
539
- {isPlanTask ? (
540
- // Plan status for planning tasks
541
- relatedTasks && relatedTasks.length > 0 ? (
542
- <div className="flex items-center gap-1.5">
543
- <div className="h-2 w-2 bg-green-500 rounded-full" />
544
- <span className="text-sm font-medium text-green-700">
545
- Task Created
546
- </span>
547
- </div>
548
- ) : (
549
- <div className="flex items-center gap-1.5">
550
- <div className="h-2 w-2 bg-gray-500 rounded-full" />
551
- <span className="text-sm font-medium text-gray-700">
552
- Draft
553
- </span>
554
- </div>
555
- )
556
- ) : // Merge status for regular tasks
557
- selectedAttempt.merge_commit ? (
558
- <div className="flex items-center gap-1.5">
559
- <div className="h-2 w-2 bg-green-500 rounded-full" />
560
- <span className="text-sm font-medium text-green-700">
561
- Merged
562
- </span>
563
- <span className="text-xs font-mono text-muted-foreground">
564
- ({selectedAttempt.merge_commit.slice(0, 8)})
565
- </span>
566
- </div>
567
- ) : (
568
- <div className="flex items-center gap-1.5">
569
- <div className="h-2 w-2 bg-yellow-500 rounded-full" />
570
- <span className="text-sm font-medium text-yellow-700">
571
- Not merged
572
- </span>
573
- </div>
574
- )}
575
- </div>
576
- </div>
577
- </div>
578
-
579
- <div className="col-span-4">
580
- <div className="flex items-center gap-1.5 mb-1">
581
- <div className="text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1">
582
- Worktree Path
583
- </div>
584
- <Button
585
- variant="ghost"
586
- size="sm"
587
- onClick={() => handleOpenInEditor()}
588
- className="h-6 px-2 text-xs hover:bg-muted gap-1"
589
- >
590
- <ExternalLink className="h-3 w-3" />
591
- Open in {editorDisplayName}
592
- </Button>
593
- </div>
594
- <div
595
- className={`text-xs font-mono px-2 py-1 rounded break-all cursor-pointer transition-all duration-300 flex items-center gap-2 ${
596
- copied
597
- ? 'bg-green-100 text-green-800 border border-green-300'
598
- : 'text-muted-foreground bg-muted hover:bg-muted/80'
599
- }`}
600
- onClick={handleCopyWorktreePath}
601
- title={copied ? 'Copied!' : 'Click to copy worktree path'}
602
- >
603
- {copied && <Check className="h-3 w-3 text-green-600" />}
604
- <span className={copied ? 'text-green-800' : ''}>
605
- {selectedAttempt.worktree_path}
606
- </span>
607
- {copied && (
608
- <span className="text-green-700 font-medium">Copied!</span>
609
- )}
610
- </div>
611
- </div>
612
-
613
- <div className="col-span-4 flex flex-wrap items-center justify-between gap-2">
614
- <div className="flex items-center gap-2 flex-wrap">
615
- <TooltipProvider>
616
- <Tooltip>
617
- <TooltipTrigger asChild>
618
- <div
619
- className={!projectHasDevScript ? 'cursor-not-allowed' : ''}
620
- onMouseEnter={() => setIsHoveringDevServer(true)}
621
- onMouseLeave={() => setIsHoveringDevServer(false)}
622
- >
623
- <Button
624
- variant={runningDevServer ? 'destructive' : 'outline'}
625
- size="sm"
626
- onClick={runningDevServer ? stopDevServer : startDevServer}
627
- disabled={isStartingDevServer || !projectHasDevScript}
628
- className="gap-1"
629
- >
630
- {runningDevServer ? (
631
- <>
632
- <StopCircle className="h-3 w-3" />
633
- Stop Dev
634
- </>
635
- ) : (
636
- <>
637
- <Play className="h-3 w-3" />
638
- Dev Server
639
- </>
640
- )}
641
- </Button>
642
- </div>
643
- </TooltipTrigger>
644
- <TooltipContent
645
- className={runningDevServer ? 'max-w-2xl p-4' : ''}
646
- side="top"
647
- align="center"
648
- avoidCollisions={true}
649
- >
650
- {!projectHasDevScript ? (
651
- <p>
652
- Add a dev server script in project settings to enable this
653
- feature
654
- </p>
655
- ) : runningDevServer && devServerDetails ? (
656
- <div className="space-y-2">
657
- <p className="text-sm font-medium">
658
- Dev Server Logs (Last 10 lines):
659
- </p>
660
- <pre className="text-xs bg-muted p-2 rounded max-h-64 overflow-y-auto whitespace-pre-wrap">
661
- {processedDevServerLogs}
662
- </pre>
663
- </div>
664
- ) : runningDevServer ? (
665
- <p>Stop the running dev server</p>
666
- ) : (
667
- <p>Start the dev server</p>
668
- )}
669
- </TooltipContent>
670
- </Tooltip>
671
- </TooltipProvider>
672
- </div>
673
-
674
- <div className="flex items-center gap-2 flex-wrap">
675
- {taskAttempts.length > 1 && (
676
- <DropdownMenu>
677
- <TooltipProvider>
678
- <Tooltip>
679
- <TooltipTrigger asChild>
680
- <DropdownMenuTrigger asChild>
681
- <Button variant="outline" size="sm" className="gap-2">
682
- <History className="h-4 w-4" />
683
- History
684
- </Button>
685
- </DropdownMenuTrigger>
686
- </TooltipTrigger>
687
- <TooltipContent>
688
- <p>View attempt history</p>
689
- </TooltipContent>
690
- </Tooltip>
691
- </TooltipProvider>
692
- <DropdownMenuContent align="start" className="w-64">
693
- {taskAttempts.map((attempt) => (
694
- <DropdownMenuItem
695
- key={attempt.id}
696
- onClick={() => handleAttemptChange(attempt)}
697
- className={
698
- selectedAttempt?.id === attempt.id ? 'bg-accent' : ''
699
- }
700
- >
701
- <div className="flex flex-col w-full">
702
- <span className="font-medium text-sm">
703
- {new Date(attempt.created_at).toLocaleDateString()}{' '}
704
- {new Date(attempt.created_at).toLocaleTimeString()}
705
- </span>
706
- <span className="text-xs text-muted-foreground">
707
- {attempt.executor || 'executor'}
708
- </span>
709
- </div>
710
- </DropdownMenuItem>
711
- ))}
712
- </DropdownMenuContent>
713
- </DropdownMenu>
714
- )}
715
-
716
- {/* Git Operations */}
717
- {selectedAttempt && branchStatus && (
718
- <>
719
- {branchStatus.is_behind &&
720
- !branchStatus.merged &&
721
- !isPlanTask && (
722
- <Button
723
- onClick={handleRebaseClick}
724
- disabled={
725
- rebasing || branchStatusLoading || isAttemptRunning
726
- }
727
- variant="outline"
728
- size="sm"
729
- className="border-orange-300 text-orange-700 hover:bg-orange-50 gap-1"
730
- >
731
- <RefreshCw
732
- className={`h-3 w-3 ${rebasing ? 'animate-spin' : ''}`}
733
- />
734
- {rebasing ? 'Rebasing...' : `Rebase`}
735
- </Button>
736
- )}
737
- {isPlanTask ? (
738
- // Plan tasks: show approval button
739
- <Button
740
- onClick={handlePlanApproval}
741
- disabled={
742
- isAttemptRunning ||
743
- executionState?.execution_state === 'CodingAgentFailed' ||
744
- executionState?.execution_state === 'SetupFailed'
745
- }
746
- size="sm"
747
- className="bg-green-600 hover:bg-green-700 disabled:bg-gray-400 gap-1"
748
- >
749
- <GitBranchIcon className="h-3 w-3" />
750
- {isApprovingPlan ? 'Approving...' : 'Create Task'}
751
- </Button>
752
- ) : (
753
- // Normal merge and PR buttons for regular tasks
754
- !branchStatus.merged && (
755
- <>
756
- <Button
757
- onClick={handleCreatePRClick}
758
- disabled={
759
- creatingPR ||
760
- Boolean(branchStatus.is_behind) ||
761
- isAttemptRunning
762
- }
763
- variant="outline"
764
- size="sm"
765
- className="border-blue-300 text-blue-700 hover:bg-blue-50 gap-1"
766
- >
767
- <GitPullRequest className="h-3 w-3" />
768
- {selectedAttempt.pr_url
769
- ? 'Open PR'
770
- : creatingPR
771
- ? 'Creating...'
772
- : 'Create PR'}
773
- </Button>
774
- <Button
775
- onClick={handleMergeClick}
776
- disabled={
777
- merging ||
778
- Boolean(branchStatus.is_behind) ||
779
- isAttemptRunning
780
- }
781
- size="sm"
782
- className="bg-green-600 hover:bg-green-700 disabled:bg-gray-400 gap-1"
783
- >
784
- <GitBranchIcon className="h-3 w-3" />
785
- {merging ? 'Merging...' : 'Merge'}
786
- </Button>
787
- </>
788
- )
789
- )}
790
- </>
791
- )}
792
-
793
- {isStopping || isAttemptRunning ? (
794
- <Button
795
- variant="destructive"
796
- size="sm"
797
- onClick={stopAllExecutions}
798
- disabled={isStopping}
799
- className="gap-2"
800
- >
801
- <StopCircle className="h-4 w-4" />
802
- {isStopping ? 'Stopping...' : 'Stop Attempt'}
803
- </Button>
804
- ) : (
805
- <Button
806
- variant="outline"
807
- size="sm"
808
- onClick={handleEnterCreateAttemptMode}
809
- className="gap-2"
810
- >
811
- <Plus className="h-4 w-4" />
812
- New Attempt
813
- </Button>
814
- )}
815
- </div>
816
- </div>
817
-
818
- {/* Rebase Dialog */}
819
- <Dialog open={showRebaseDialog} onOpenChange={setShowRebaseDialog}>
820
- <DialogContent className="sm:max-w-md">
821
- <DialogHeader>
822
- <DialogTitle>Rebase Task Attempt</DialogTitle>
823
- <DialogDescription>
824
- Choose a new base branch to rebase this task attempt onto.
825
- </DialogDescription>
826
- </DialogHeader>
827
-
828
- <div className="space-y-4">
829
- <div className="space-y-2">
830
- <label htmlFor="base-branch" className="text-sm font-medium">
831
- Base Branch
832
- </label>
833
- <BranchSelector
834
- branches={branches}
835
- selectedBranch={selectedRebaseBranch}
836
- onBranchSelect={setSelectedRebaseBranch}
837
- placeholder="Select a base branch"
838
- excludeCurrentBranch={false}
839
- />
840
- </div>
841
- </div>
842
-
843
- <DialogFooter>
844
- <Button
845
- variant="outline"
846
- onClick={() => setShowRebaseDialog(false)}
847
- disabled={rebasing}
848
- >
849
- Cancel
850
- </Button>
851
- <Button
852
- onClick={handleRebaseDialogConfirm}
853
- disabled={rebasing || !selectedRebaseBranch}
854
- >
855
- {rebasing ? 'Rebasing...' : 'Rebase'}
856
- </Button>
857
- </DialogFooter>
858
- </DialogContent>
859
- </Dialog>
860
-
861
- {/* Stop Execution Confirmation Dialog */}
862
- <Dialog
863
- open={showStopConfirmation}
864
- onOpenChange={setShowStopConfirmation}
865
- >
866
- <DialogContent className="sm:max-w-md">
867
- <DialogHeader>
868
- <DialogTitle>Stop Current Attempt?</DialogTitle>
869
- <DialogDescription>
870
- Are you sure you want to stop the current execution? This action
871
- cannot be undone.
872
- </DialogDescription>
873
- </DialogHeader>
874
- <DialogFooter>
875
- <Button
876
- variant="outline"
877
- onClick={() => setShowStopConfirmation(false)}
878
- disabled={isStopping}
879
- >
880
- Cancel
881
- </Button>
882
- <Button
883
- variant="destructive"
884
- onClick={async () => {
885
- setShowStopConfirmation(false);
886
- await stopAllExecutions();
887
- }}
888
- disabled={isStopping}
889
- >
890
- {isStopping ? 'Stopping...' : 'Stop'}
891
- </Button>
892
- </DialogFooter>
893
- </DialogContent>
894
- </Dialog>
895
- </div>
896
- );
897
- }
898
-
899
- export default CurrentAttempt;