automagik-forge 0.1.11 → 0.1.13

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/.cargo/config.toml +13 -0
  2. package/.claude/commands/commit.md +376 -0
  3. package/.claude/commands/prompt.md +871 -0
  4. package/.env.example +20 -0
  5. package/.github/actions/setup-node/action.yml +29 -0
  6. package/.github/images/automagik-logo.png +0 -0
  7. package/.github/workflows/pre-release.yml +470 -0
  8. package/.github/workflows/publish.yml +145 -0
  9. package/.github/workflows/test.yml +63 -0
  10. package/.mcp.json +57 -0
  11. package/AGENT.md +40 -0
  12. package/CLAUDE.md +40 -0
  13. package/CODE-OF-CONDUCT.md +89 -0
  14. package/Cargo.toml +19 -0
  15. package/Dockerfile +43 -0
  16. package/LICENSE +201 -0
  17. package/Makefile +97 -0
  18. package/README.md +447 -143
  19. package/backend/.sqlx/query-01b7e2bac1261d8be3d03c03df3e5220590da6c31c77f161074fc62752d63881.json +12 -0
  20. package/backend/.sqlx/query-03f2b02ba6dc5ea2b3cf6b1004caea0ad6bcc10ebd63f441d321a389f026e263.json +12 -0
  21. package/backend/.sqlx/query-0923b77d137a29fc54d399a873ff15fc4af894490bc65a4d344a7575cb0d8643.json +12 -0
  22. package/backend/.sqlx/query-0f808bcdb63c5f180836e448dd64c435c51758b2fc54a52ce9e67495b1ab200e.json +68 -0
  23. package/backend/.sqlx/query-1268afe9ca849daa6722e3df7ca8e9e61f0d37052e782bb5452ab8e1018d9b63.json +12 -0
  24. package/backend/.sqlx/query-1b082630a9622f8667ee7a9aba2c2d3176019a68c6bb83d33008594821415a57.json +12 -0
  25. package/backend/.sqlx/query-1c7b06ba1e112abf6b945a2ff08a0b40ec23f3738c2e7399f067b558cf8d490e.json +12 -0
  26. package/backend/.sqlx/query-1f619f01f46859a64ded531dd0ef61abacfe62e758abe7030a6aa745140b95ca.json +104 -0
  27. package/backend/.sqlx/query-1fca1ce14b4b20205364cd1f1f45ebe1d2e30cd745e59e189d56487b5639dfbb.json +12 -0
  28. package/backend/.sqlx/query-212828320e8d871ab9d83705a040b23bcf0393dc7252177fc539a74657f578ef.json +32 -0
  29. package/backend/.sqlx/query-290ce5c152be8d36e58ff42570f9157beb07ab9e77a03ec6fc30b4f56f9b8f6b.json +56 -0
  30. package/backend/.sqlx/query-2b471d2c2e8ffbe0cd42d2a91b814c0d79f9d09200f147e3cea33ba4ce673c8a.json +68 -0
  31. package/backend/.sqlx/query-354a48c705bb9bb2048c1b7f10fcb714e23f9db82b7a4ea6932486197b2ede6a.json +92 -0
  32. package/backend/.sqlx/query-36c9e3dd10648e94b949db5c91a774ecb1e10a899ef95da74066eccedca4d8b2.json +12 -0
  33. package/backend/.sqlx/query-36e4ba7bbd81b402d5a20b6005755eafbb174c8dda442081823406ac32809a94.json +56 -0
  34. package/backend/.sqlx/query-3a5b3c98a55ca183ab20c74708e3d7e579dda37972c059e7515c4ceee4bd8dd3.json +62 -0
  35. package/backend/.sqlx/query-3d0a1cabf2a52e9d90cdfd29c509ca89aeb448d0c1d2446c65cd43db40735e86.json +62 -0
  36. package/backend/.sqlx/query-3d6bd16fbce59efe30b7f67ea342e0e4ea6d1432389c02468ad79f1f742d4031.json +56 -0
  37. package/backend/.sqlx/query-4049ca413b285a05aca6b25385e9c8185575f01e9069e4e8581aa45d713f612f.json +32 -0
  38. package/backend/.sqlx/query-412bacd3477d86369082e90f52240407abce436cb81292d42b2dbe1e5c18eea1.json +104 -0
  39. package/backend/.sqlx/query-417a8b1ff4e51de82aea0159a3b97932224dc325b23476cb84153d690227fd8b.json +62 -0
  40. package/backend/.sqlx/query-461cc1b0bb6fd909afc9dd2246e8526b3771cfbb0b22ae4b5d17b51af587b9e2.json +56 -0
  41. package/backend/.sqlx/query-58408c7a8cdeeda0bef359f1f9bd91299a339dc2b191462fc58c9736a56d5227.json +92 -0
  42. package/backend/.sqlx/query-5a886026d75d515c01f347cc203c8d99dd04c61dc468e2e4c5aa548436d13834.json +62 -0
  43. package/backend/.sqlx/query-5b902137b11022d2e1a5c4f6a9c83fec1a856c6a710aff831abd2382ede76b43.json +12 -0
  44. package/backend/.sqlx/query-5ed1238e52e59bb5f76c0f153fd99a14093f7ce2585bf9843585608f17ec575b.json +104 -0
  45. package/backend/.sqlx/query-6e8b860b14decfc2227dc57213f38442943d3fbef5c8418fd6b634c6e0f5e2ea.json +104 -0
  46. package/backend/.sqlx/query-6ec414276994c4ccb2433eaa5b1b342168557d17ddf5a52dac84cb1b59b9de8f.json +68 -0
  47. package/backend/.sqlx/query-6ecfa16d0cf825aacf233544b5baf151e9adfdca26c226ad71020d291fd802d5.json +62 -0
  48. package/backend/.sqlx/query-72509d252c39fce77520aa816cb2acbc1fb35dc2605e7be893610599b2427f2e.json +62 -0
  49. package/backend/.sqlx/query-75239b2da188f749707d77f3c1544332ca70db3d6d6743b2601dc0d167536437.json +62 -0
  50. package/backend/.sqlx/query-83d10e29f8478aff33434f9ac67068e013b888b953a2657e2bb72a6f619d04f2.json +50 -0
  51. package/backend/.sqlx/query-8610803360ea18b9b9d078a6981ea56abfbfe84e6354fc1d5ae4c622e01410ed.json +68 -0
  52. package/backend/.sqlx/query-86d03eb70eef39c59296416867f2ee66c9f7cd8b7f961fbda2f89fc0a1c442c2.json +12 -0
  53. package/backend/.sqlx/query-87d0feb5a6b442bad9c60068ea7569599cc6fc91a0e2692ecb42e93b03201b9d.json +68 -0
  54. package/backend/.sqlx/query-8a67b3b3337248f06a57bdf8a908f7ef23177431eaed82dc08c94c3e5944340e.json +12 -0
  55. package/backend/.sqlx/query-8f01ebd64bdcde6a090479f14810d73ba23020e76fd70854ac57f2da251702c3.json +12 -0
  56. package/backend/.sqlx/query-90fd607fcb2dca72239ff25e618e21e174b195991eaa33722cbf5f76da84cfab.json +62 -0
  57. package/backend/.sqlx/query-92e8bdbcd80c5ff3db7a35cf79492048803ef305cbdef0d0a1fe5dc881ca8c71.json +104 -0
  58. package/backend/.sqlx/query-93a1605f90e9672dad29b472b6ad85fa9a55ea3ffa5abcb8724b09d61be254ca.json +20 -0
  59. package/backend/.sqlx/query-9472c8fb477958167f5fae40b85ac44252468c5226b2cdd7770f027332eed6d7.json +104 -0
  60. package/backend/.sqlx/query-96036c4f9e0f48bdc5a4a4588f0c5f288ac7aaa5425cac40fc33f337e1a351f2.json +56 -0
  61. package/backend/.sqlx/query-9edb2c01e91fd0f0fe7b56e988c7ae0393150f50be3f419a981e035c0121dfc7.json +104 -0
  62. package/backend/.sqlx/query-a157cf00616f703bfba21927f1eb1c9eec2a81c02da15f66efdba0b6c375de1b.json +26 -0
  63. package/backend/.sqlx/query-a31fff84f3b8e532fd1160447d89d700f06ae08821fee00c9a5b60492b05259c.json +62 -0
  64. package/backend/.sqlx/query-a5ba908419fb3e456bdd2daca41ba06cc3212ffffb8520fc7dbbcc8b60ada314.json +12 -0
  65. package/backend/.sqlx/query-a6d2961718dbc3b1a925e549f49a159c561bef58c105529275f274b27e2eba5b.json +104 -0
  66. package/backend/.sqlx/query-a9e93d5b09b29faf66e387e4d7596a792d81e75c4d3726e83c2963e8d7c9b56f.json +104 -0
  67. package/backend/.sqlx/query-ac5247c8d7fb86e4650c4b0eb9420031614c831b7b085083bac20c1af314c538.json +12 -0
  68. package/backend/.sqlx/query-afef9467be74c411c4cb119a8b2b1aea53049877dfc30cc60b486134ba4b4c9f.json +68 -0
  69. package/backend/.sqlx/query-b2b2c6b4d0b1a347b5c4cb63c3a46a265d4db53be9554989a814b069d0af82f2.json +62 -0
  70. package/backend/.sqlx/query-c50d2ff0b12e5bcc81e371089ee2d007e233e7db93aefba4fef08e7aa68f5ab7.json +20 -0
  71. package/backend/.sqlx/query-c614e6056b244ca07f1b9d44e7edc9d5819225c6f8d9e077070c6e518a17f50b.json +12 -0
  72. package/backend/.sqlx/query-c67259be8bf4ee0cfd32167b2aa3b7fe9192809181a8171bf1c2d6df731967ae.json +12 -0
  73. package/backend/.sqlx/query-d2d0a1b985ebbca6a2b3e882a221a219f3199890fa640afc946ef1a792d6d8de.json +12 -0
  74. package/backend/.sqlx/query-d30aa5786757f32bf2b9c5fe51a45e506c71c28c5994e430d9b0546adb15ffa2.json +20 -0
  75. package/backend/.sqlx/query-d3b9ea1de1576af71b312924ce7f4ea8ae5dbe2ac138ea3b4470f2d5cd734846.json +12 -0
  76. package/backend/.sqlx/query-ed8456646fa69ddd412441955f06ff22bfb790f29466450735e0b8bb1bc4ec94.json +12 -0
  77. package/backend/Cargo.toml +71 -0
  78. package/backend/build.rs +32 -0
  79. package/backend/migrations/20250617183714_init.sql +44 -0
  80. package/backend/migrations/20250620212427_execution_processes.sql +25 -0
  81. package/backend/migrations/20250620214100_remove_stdout_stderr_from_task_attempts.sql +28 -0
  82. package/backend/migrations/20250621120000_relate_activities_to_execution_processes.sql +23 -0
  83. package/backend/migrations/20250623120000_executor_sessions.sql +17 -0
  84. package/backend/migrations/20250623130000_add_executor_type_to_execution_processes.sql +4 -0
  85. package/backend/migrations/20250625000000_add_dev_script_to_projects.sql +4 -0
  86. package/backend/migrations/20250701000000_add_branch_to_task_attempts.sql +2 -0
  87. package/backend/migrations/20250701000001_add_pr_tracking_to_task_attempts.sql +5 -0
  88. package/backend/migrations/20250701120000_add_assistant_message_to_executor_sessions.sql +2 -0
  89. package/backend/migrations/20250708000000_add_base_branch_to_task_attempts.sql +2 -0
  90. package/backend/migrations/20250709000000_add_worktree_deleted_flag.sql +2 -0
  91. package/backend/migrations/20250710000000_add_setup_completion.sql +3 -0
  92. package/backend/migrations/20250715154859_add_task_templates.sql +25 -0
  93. package/backend/migrations/20250716143725_add_default_templates.sql +174 -0
  94. package/backend/migrations/20250716161432_update_executor_names_to_kebab_case.sql +20 -0
  95. package/backend/migrations/20250716170000_add_parent_task_to_tasks.sql +7 -0
  96. package/backend/migrations/20250717000000_drop_task_attempt_activities.sql +9 -0
  97. package/backend/migrations/20250719000000_add_cleanup_script_to_projects.sql +2 -0
  98. package/backend/migrations/20250720000000_add_cleanupscript_to_process_type_constraint.sql +25 -0
  99. package/backend/migrations/20250723000000_add_wish_to_tasks.sql +7 -0
  100. package/backend/migrations/20250724000000_remove_unique_wish_constraint.sql +5 -0
  101. package/backend/scripts/toast-notification.ps1 +23 -0
  102. package/backend/sounds/abstract-sound1.wav +0 -0
  103. package/backend/sounds/abstract-sound2.wav +0 -0
  104. package/backend/sounds/abstract-sound3.wav +0 -0
  105. package/backend/sounds/abstract-sound4.wav +0 -0
  106. package/backend/sounds/cow-mooing.wav +0 -0
  107. package/backend/sounds/phone-vibration.wav +0 -0
  108. package/backend/sounds/rooster.wav +0 -0
  109. package/backend/src/app_state.rs +218 -0
  110. package/backend/src/bin/generate_types.rs +189 -0
  111. package/backend/src/bin/mcp_task_server.rs +191 -0
  112. package/backend/src/execution_monitor.rs +1193 -0
  113. package/backend/src/executor.rs +1053 -0
  114. package/backend/src/executors/amp.rs +697 -0
  115. package/backend/src/executors/ccr.rs +91 -0
  116. package/backend/src/executors/charm_opencode.rs +113 -0
  117. package/backend/src/executors/claude.rs +887 -0
  118. package/backend/src/executors/cleanup_script.rs +124 -0
  119. package/backend/src/executors/dev_server.rs +53 -0
  120. package/backend/src/executors/echo.rs +79 -0
  121. package/backend/src/executors/gemini/config.rs +67 -0
  122. package/backend/src/executors/gemini/streaming.rs +363 -0
  123. package/backend/src/executors/gemini.rs +765 -0
  124. package/backend/src/executors/mod.rs +23 -0
  125. package/backend/src/executors/opencode_ai.rs +113 -0
  126. package/backend/src/executors/setup_script.rs +130 -0
  127. package/backend/src/executors/sst_opencode/filter.rs +184 -0
  128. package/backend/src/executors/sst_opencode/tools.rs +139 -0
  129. package/backend/src/executors/sst_opencode.rs +756 -0
  130. package/backend/src/lib.rs +45 -0
  131. package/backend/src/main.rs +324 -0
  132. package/backend/src/mcp/mod.rs +1 -0
  133. package/backend/src/mcp/task_server.rs +850 -0
  134. package/backend/src/middleware/mod.rs +3 -0
  135. package/backend/src/middleware/model_loaders.rs +242 -0
  136. package/backend/src/models/api_response.rs +36 -0
  137. package/backend/src/models/config.rs +375 -0
  138. package/backend/src/models/execution_process.rs +430 -0
  139. package/backend/src/models/executor_session.rs +225 -0
  140. package/backend/src/models/mod.rs +12 -0
  141. package/backend/src/models/project.rs +356 -0
  142. package/backend/src/models/task.rs +345 -0
  143. package/backend/src/models/task_attempt.rs +1214 -0
  144. package/backend/src/models/task_template.rs +146 -0
  145. package/backend/src/openapi.rs +93 -0
  146. package/backend/src/routes/auth.rs +297 -0
  147. package/backend/src/routes/config.rs +385 -0
  148. package/backend/src/routes/filesystem.rs +228 -0
  149. package/backend/src/routes/health.rs +16 -0
  150. package/backend/src/routes/mod.rs +9 -0
  151. package/backend/src/routes/projects.rs +562 -0
  152. package/backend/src/routes/stream.rs +244 -0
  153. package/backend/src/routes/task_attempts.rs +1172 -0
  154. package/backend/src/routes/task_templates.rs +229 -0
  155. package/backend/src/routes/tasks.rs +353 -0
  156. package/backend/src/services/analytics.rs +216 -0
  157. package/backend/src/services/git_service.rs +1321 -0
  158. package/backend/src/services/github_service.rs +307 -0
  159. package/backend/src/services/mod.rs +13 -0
  160. package/backend/src/services/notification_service.rs +263 -0
  161. package/backend/src/services/pr_monitor.rs +214 -0
  162. package/backend/src/services/process_service.rs +940 -0
  163. package/backend/src/utils/path.rs +96 -0
  164. package/backend/src/utils/shell.rs +19 -0
  165. package/backend/src/utils/text.rs +24 -0
  166. package/backend/src/utils/worktree_manager.rs +578 -0
  167. package/backend/src/utils.rs +125 -0
  168. package/backend/test.db +0 -0
  169. package/build-npm-package.sh +61 -0
  170. package/dev_assets_seed/config.json +19 -0
  171. package/frontend/.eslintrc.json +25 -0
  172. package/frontend/.prettierrc.json +8 -0
  173. package/frontend/components.json +17 -0
  174. package/frontend/index.html +19 -0
  175. package/frontend/package-lock.json +7321 -0
  176. package/frontend/package.json +61 -0
  177. package/frontend/postcss.config.js +6 -0
  178. package/frontend/public/android-chrome-192x192.png +0 -0
  179. package/frontend/public/android-chrome-512x512.png +0 -0
  180. package/frontend/public/apple-touch-icon.png +0 -0
  181. package/frontend/public/automagik-forge-logo-dark.svg +3 -0
  182. package/frontend/public/automagik-forge-logo.svg +3 -0
  183. package/frontend/public/automagik-forge-screenshot-overview.png +0 -0
  184. package/frontend/public/favicon-16x16.png +0 -0
  185. package/frontend/public/favicon-32x32.png +0 -0
  186. package/frontend/public/favicon.ico +0 -0
  187. package/frontend/public/site.webmanifest +1 -0
  188. package/frontend/public/viba-kanban-favicon.png +0 -0
  189. package/frontend/src/App.tsx +157 -0
  190. package/frontend/src/components/DisclaimerDialog.tsx +106 -0
  191. package/frontend/src/components/GitHubLoginDialog.tsx +314 -0
  192. package/frontend/src/components/OnboardingDialog.tsx +185 -0
  193. package/frontend/src/components/PrivacyOptInDialog.tsx +130 -0
  194. package/frontend/src/components/ProvidePatDialog.tsx +98 -0
  195. package/frontend/src/components/TaskTemplateManager.tsx +336 -0
  196. package/frontend/src/components/config-provider.tsx +119 -0
  197. package/frontend/src/components/context/TaskDetailsContextProvider.tsx +470 -0
  198. package/frontend/src/components/context/taskDetailsContext.ts +125 -0
  199. package/frontend/src/components/keyboard-shortcuts-demo.tsx +35 -0
  200. package/frontend/src/components/layout/navbar.tsx +86 -0
  201. package/frontend/src/components/logo.tsx +44 -0
  202. package/frontend/src/components/projects/ProjectCard.tsx +155 -0
  203. package/frontend/src/components/projects/project-detail.tsx +251 -0
  204. package/frontend/src/components/projects/project-form-fields.tsx +238 -0
  205. package/frontend/src/components/projects/project-form.tsx +301 -0
  206. package/frontend/src/components/projects/project-list.tsx +200 -0
  207. package/frontend/src/components/projects/projects-page.tsx +20 -0
  208. package/frontend/src/components/tasks/BranchSelector.tsx +169 -0
  209. package/frontend/src/components/tasks/DeleteFileConfirmationDialog.tsx +94 -0
  210. package/frontend/src/components/tasks/EditorSelectionDialog.tsx +119 -0
  211. package/frontend/src/components/tasks/TaskCard.tsx +154 -0
  212. package/frontend/src/components/tasks/TaskDetails/CollapsibleToolbar.tsx +33 -0
  213. package/frontend/src/components/tasks/TaskDetails/DiffCard.tsx +109 -0
  214. package/frontend/src/components/tasks/TaskDetails/DiffChunkSection.tsx +135 -0
  215. package/frontend/src/components/tasks/TaskDetails/DiffFile.tsx +296 -0
  216. package/frontend/src/components/tasks/TaskDetails/DiffTab.tsx +32 -0
  217. package/frontend/src/components/tasks/TaskDetails/DisplayConversationEntry.tsx +392 -0
  218. package/frontend/src/components/tasks/TaskDetails/LogsTab/Conversation.tsx +256 -0
  219. package/frontend/src/components/tasks/TaskDetails/LogsTab/ConversationEntry.tsx +56 -0
  220. package/frontend/src/components/tasks/TaskDetails/LogsTab/NormalizedConversationViewer.tsx +92 -0
  221. package/frontend/src/components/tasks/TaskDetails/LogsTab/Prompt.tsx +22 -0
  222. package/frontend/src/components/tasks/TaskDetails/LogsTab/SetupScriptRunning.tsx +49 -0
  223. package/frontend/src/components/tasks/TaskDetails/LogsTab.tsx +186 -0
  224. package/frontend/src/components/tasks/TaskDetails/ProcessesTab.tsx +288 -0
  225. package/frontend/src/components/tasks/TaskDetails/RelatedTasksTab.tsx +216 -0
  226. package/frontend/src/components/tasks/TaskDetails/TabNavigation.tsx +93 -0
  227. package/frontend/src/components/tasks/TaskDetailsHeader.tsx +169 -0
  228. package/frontend/src/components/tasks/TaskDetailsPanel.tsx +126 -0
  229. package/frontend/src/components/tasks/TaskDetailsToolbar.tsx +302 -0
  230. package/frontend/src/components/tasks/TaskFollowUpSection.tsx +130 -0
  231. package/frontend/src/components/tasks/TaskFormDialog.tsx +400 -0
  232. package/frontend/src/components/tasks/TaskKanbanBoard.tsx +180 -0
  233. package/frontend/src/components/tasks/Toolbar/CreateAttempt.tsx +259 -0
  234. package/frontend/src/components/tasks/Toolbar/CreatePRDialog.tsx +243 -0
  235. package/frontend/src/components/tasks/Toolbar/CurrentAttempt.tsx +899 -0
  236. package/frontend/src/components/tasks/index.ts +2 -0
  237. package/frontend/src/components/theme-provider.tsx +82 -0
  238. package/frontend/src/components/theme-toggle.tsx +36 -0
  239. package/frontend/src/components/ui/alert.tsx +59 -0
  240. package/frontend/src/components/ui/auto-expanding-textarea.tsx +70 -0
  241. package/frontend/src/components/ui/badge.tsx +36 -0
  242. package/frontend/src/components/ui/button.tsx +56 -0
  243. package/frontend/src/components/ui/card.tsx +86 -0
  244. package/frontend/src/components/ui/checkbox.tsx +44 -0
  245. package/frontend/src/components/ui/chip.tsx +25 -0
  246. package/frontend/src/components/ui/dialog.tsx +124 -0
  247. package/frontend/src/components/ui/dropdown-menu.tsx +198 -0
  248. package/frontend/src/components/ui/file-search-textarea.tsx +292 -0
  249. package/frontend/src/components/ui/folder-picker.tsx +279 -0
  250. package/frontend/src/components/ui/input.tsx +25 -0
  251. package/frontend/src/components/ui/label.tsx +24 -0
  252. package/frontend/src/components/ui/loader.tsx +26 -0
  253. package/frontend/src/components/ui/markdown-renderer.tsx +75 -0
  254. package/frontend/src/components/ui/select.tsx +160 -0
  255. package/frontend/src/components/ui/separator.tsx +31 -0
  256. package/frontend/src/components/ui/shadcn-io/kanban/index.tsx +185 -0
  257. package/frontend/src/components/ui/table.tsx +117 -0
  258. package/frontend/src/components/ui/tabs.tsx +53 -0
  259. package/frontend/src/components/ui/textarea.tsx +22 -0
  260. package/frontend/src/components/ui/tooltip.tsx +28 -0
  261. package/frontend/src/hooks/useNormalizedConversation.ts +440 -0
  262. package/frontend/src/index.css +225 -0
  263. package/frontend/src/lib/api.ts +630 -0
  264. package/frontend/src/lib/keyboard-shortcuts.ts +266 -0
  265. package/frontend/src/lib/responsive-config.ts +70 -0
  266. package/frontend/src/lib/types.ts +39 -0
  267. package/frontend/src/lib/utils.ts +10 -0
  268. package/frontend/src/main.tsx +50 -0
  269. package/frontend/src/pages/McpServers.tsx +418 -0
  270. package/frontend/src/pages/Settings.tsx +610 -0
  271. package/frontend/src/pages/project-tasks.tsx +575 -0
  272. package/frontend/src/pages/projects.tsx +18 -0
  273. package/frontend/src/vite-env.d.ts +1 -0
  274. package/frontend/tailwind.config.js +125 -0
  275. package/frontend/tsconfig.json +26 -0
  276. package/frontend/tsconfig.node.json +10 -0
  277. package/frontend/vite.config.ts +33 -0
  278. package/npx-cli/README.md +159 -0
  279. package/npx-cli/automagik-forge-0.0.55.tgz +0 -0
  280. package/npx-cli/automagik-forge-0.1.0.tgz +0 -0
  281. package/{dist/linux-x64/automagik-forge.zip → npx-cli/automagik-forge-0.1.10.tgz} +0 -0
  282. package/npx-cli/package.json +17 -0
  283. package/npx-cli/vibe-kanban-0.0.55.tgz +0 -0
  284. package/package.json +23 -13
  285. package/pnpm-workspace.yaml +2 -0
  286. package/rust-toolchain.toml +11 -0
  287. package/rustfmt.toml +3 -0
  288. package/scripts/load-env.js +43 -0
  289. package/scripts/mcp_test.js +374 -0
  290. package/scripts/prepare-db.js +45 -0
  291. package/scripts/setup-dev-environment.js +274 -0
  292. package/scripts/start-mcp-sse.js +70 -0
  293. package/scripts/test-debug.js +32 -0
  294. package/scripts/test-mcp-sse.js +138 -0
  295. package/scripts/test-simple.js +44 -0
  296. package/scripts/test-wish-final.js +179 -0
  297. package/scripts/test-wish-system.js +221 -0
  298. package/shared/types.ts +182 -0
  299. package/test-npm-package.sh +42 -0
  300. package/dist/linux-x64/automagik-forge-mcp.zip +0 -0
  301. /package/{bin → npx-cli/bin}/cli.js +0 -0
@@ -0,0 +1,314 @@
1
+ import { useEffect, useState } from 'react';
2
+ import {
3
+ Dialog,
4
+ DialogContent,
5
+ DialogDescription,
6
+ DialogFooter,
7
+ DialogHeader,
8
+ DialogTitle,
9
+ } from './ui/dialog';
10
+ import { Button } from './ui/button';
11
+ import { useConfig } from './config-provider';
12
+ import { Check, Clipboard, Github } from 'lucide-react';
13
+ import { Loader } from './ui/loader';
14
+ import { githubAuthApi } from '../lib/api';
15
+ import { DeviceStartResponse } from 'shared/types.ts';
16
+ import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
17
+
18
+ export function GitHubLoginDialog({
19
+ open,
20
+ onOpenChange,
21
+ }: {
22
+ open: boolean;
23
+ onOpenChange: (open: boolean) => void;
24
+ }) {
25
+ const { config, loading, githubTokenInvalid } = useConfig();
26
+ const [fetching, setFetching] = useState(false);
27
+ const [error, setError] = useState<string | null>(null);
28
+ const [deviceState, setDeviceState] = useState<null | DeviceStartResponse>(
29
+ null
30
+ );
31
+ const [polling, setPolling] = useState(false);
32
+ const [copied, setCopied] = useState(false);
33
+
34
+ const isAuthenticated =
35
+ !!(config?.github?.username && config?.github?.token) &&
36
+ !githubTokenInvalid;
37
+
38
+ const handleLogin = async () => {
39
+ setFetching(true);
40
+ setError(null);
41
+ setDeviceState(null);
42
+ try {
43
+ const data = await githubAuthApi.start();
44
+ setDeviceState(data);
45
+ setPolling(true);
46
+ } catch (e: any) {
47
+ console.error(e);
48
+ setError(e?.message || 'Network error');
49
+ } finally {
50
+ setFetching(false);
51
+ }
52
+ };
53
+
54
+ // Poll for completion
55
+ useEffect(() => {
56
+ let timer: number;
57
+ if (polling && deviceState) {
58
+ const poll = async () => {
59
+ try {
60
+ await githubAuthApi.poll(deviceState.device_code);
61
+ setPolling(false);
62
+ setDeviceState(null);
63
+ setError(null);
64
+ onOpenChange(false);
65
+ } catch (e: any) {
66
+ if (e?.message === 'authorization_pending') {
67
+ timer = setTimeout(poll, (deviceState.interval || 5) * 1000);
68
+ } else if (e?.message === 'slow_down') {
69
+ timer = setTimeout(poll, (deviceState.interval + 5) * 1000);
70
+ } else if (e?.message === 'expired_token') {
71
+ setPolling(false);
72
+ setError('Device code expired. Please try again.');
73
+ setDeviceState(null);
74
+ } else {
75
+ setPolling(false);
76
+ setError(e?.message || 'Login failed.');
77
+ setDeviceState(null);
78
+ }
79
+ }
80
+ };
81
+ timer = setTimeout(poll, deviceState.interval * 1000);
82
+ }
83
+ return () => {
84
+ if (timer) clearTimeout(timer);
85
+ };
86
+ }, [polling, deviceState]);
87
+
88
+ // Automatically copy code to clipboard when deviceState is set
89
+ useEffect(() => {
90
+ if (deviceState?.user_code) {
91
+ copyToClipboard(deviceState.user_code);
92
+ }
93
+ }, [deviceState?.user_code]);
94
+
95
+ const copyToClipboard = async (text: string) => {
96
+ try {
97
+ if (navigator.clipboard && navigator.clipboard.writeText) {
98
+ await navigator.clipboard.writeText(text);
99
+ setCopied(true);
100
+ setTimeout(() => setCopied(false), 2000);
101
+ } else {
102
+ // Fallback for environments where clipboard API is not available
103
+ const textArea = document.createElement('textarea');
104
+ textArea.value = text;
105
+ textArea.style.position = 'fixed';
106
+ textArea.style.left = '-999999px';
107
+ textArea.style.top = '-999999px';
108
+ document.body.appendChild(textArea);
109
+ textArea.focus();
110
+ textArea.select();
111
+ try {
112
+ document.execCommand('copy');
113
+ setCopied(true);
114
+ setTimeout(() => setCopied(false), 2000);
115
+ } catch (err) {
116
+ console.warn('Copy to clipboard failed:', err);
117
+ }
118
+ document.body.removeChild(textArea);
119
+ }
120
+ } catch (err) {
121
+ console.warn('Copy to clipboard failed:', err);
122
+ }
123
+ };
124
+
125
+ return (
126
+ <Dialog open={open} onOpenChange={onOpenChange}>
127
+ <DialogContent>
128
+ <DialogHeader>
129
+ <div className="flex items-center gap-3">
130
+ <Github className="h-6 w-6 text-primary" />
131
+ <DialogTitle>Sign in with GitHub</DialogTitle>
132
+ </div>
133
+ <DialogDescription className="text-left pt-1">
134
+ Connect your GitHub account to create and manage pull requests
135
+ directly from Automagik Forge.
136
+ </DialogDescription>
137
+ </DialogHeader>
138
+ {loading ? (
139
+ <Loader message="Loading…" size={32} className="py-8" />
140
+ ) : isAuthenticated ? (
141
+ <div className="space-y-4 py-3">
142
+ <Card>
143
+ <CardContent className="text-center py-8">
144
+ <div className="flex items-center justify-center gap-3 mb-4">
145
+ <Check className="h-8 w-8 text-green-500" />
146
+ <Github className="h-8 w-8 text-gray-600" />
147
+ </div>
148
+ <div className="text-lg font-medium text-gray-900 mb-1">
149
+ Successfully connected!
150
+ </div>
151
+ <div className="text-sm text-muted-foreground">
152
+ You are signed in as <b>{config?.github?.username ?? ''}</b>
153
+ </div>
154
+ </CardContent>
155
+ </Card>
156
+ <DialogFooter>
157
+ <Button onClick={() => onOpenChange(false)} className="w-full">
158
+ Close
159
+ </Button>
160
+ </DialogFooter>
161
+ </div>
162
+ ) : deviceState ? (
163
+ <div className="space-y-4 py-3">
164
+ <Card>
165
+ <CardHeader className="pb-3">
166
+ <CardTitle className="text-base">
167
+ Complete GitHub Authorization
168
+ </CardTitle>
169
+ </CardHeader>
170
+ <CardContent className="space-y-4 pt-0">
171
+ <div className="flex items-start gap-3">
172
+ <span className="flex-shrink-0 w-6 h-6 bg-blue-100 text-blue-700 rounded-full flex items-center justify-center text-sm font-semibold">
173
+ 1
174
+ </span>
175
+ <div>
176
+ <p className="text-sm font-medium text-gray-900 mb-1">
177
+ Go to GitHub Device Authorization
178
+ </p>
179
+ <a
180
+ href={deviceState.verification_uri}
181
+ target="_blank"
182
+ rel="noopener noreferrer"
183
+ className="text-blue-600 hover:text-blue-800 text-sm underline"
184
+ >
185
+ {deviceState.verification_uri}
186
+ </a>
187
+ </div>
188
+ </div>
189
+
190
+ <div className="flex items-start gap-3">
191
+ <span className="flex-shrink-0 w-6 h-6 bg-blue-100 text-blue-700 rounded-full flex items-center justify-center text-sm font-semibold">
192
+ 2
193
+ </span>
194
+ <div className="flex-1">
195
+ <p className="text-sm font-medium text-gray-900 mb-3">
196
+ Enter this code:
197
+ </p>
198
+ <div className="flex items-center gap-3">
199
+ <span className="text-xl font-mono font-bold tracking-[0.2em] bg-gray-50 border rounded-lg px-4 py-2 text-gray-900">
200
+ {deviceState.user_code}
201
+ </span>
202
+ <Button
203
+ variant="outline"
204
+ size="sm"
205
+ onClick={() => copyToClipboard(deviceState.user_code)}
206
+ disabled={copied}
207
+ >
208
+ {copied ? (
209
+ <>
210
+ <Check className="w-4 h-4 mr-1" />
211
+ Copied
212
+ </>
213
+ ) : (
214
+ <>
215
+ <Clipboard className="w-4 h-4 mr-1" />
216
+ Copy
217
+ </>
218
+ )}
219
+ </Button>
220
+ </div>
221
+ </div>
222
+ </div>
223
+ </CardContent>
224
+ </Card>
225
+
226
+ <div className="flex items-center gap-2 text-xs text-muted-foreground bg-muted/50 p-2 rounded-lg">
227
+ <Github className="h-3 w-3 flex-shrink-0" />
228
+ <span>
229
+ {copied
230
+ ? 'Code copied to clipboard! Complete the authorization on GitHub.'
231
+ : 'Waiting for you to authorize this application on GitHub...'}
232
+ </span>
233
+ </div>
234
+
235
+ {error && (
236
+ <div className="p-3 bg-red-50 border border-red-200 rounded-lg">
237
+ <div className="text-red-600 text-sm">{error}</div>
238
+ </div>
239
+ )}
240
+
241
+ <DialogFooter>
242
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
243
+ Skip
244
+ </Button>
245
+ </DialogFooter>
246
+ </div>
247
+ ) : (
248
+ <div className="space-y-4 py-3">
249
+ <Card>
250
+ <CardHeader className="pb-3">
251
+ <CardTitle className="text-base">
252
+ Why do you need GitHub access?
253
+ </CardTitle>
254
+ </CardHeader>
255
+ <CardContent className="space-y-3 pt-0">
256
+ <div className="flex items-start gap-3">
257
+ <Check className="h-4 w-4 text-green-500 mt-0.5 flex-shrink-0" />
258
+ <div>
259
+ <p className="text-sm font-medium">Create pull requests</p>
260
+ <p className="text-xs text-muted-foreground">
261
+ Generate PRs directly from your task attempts
262
+ </p>
263
+ </div>
264
+ </div>
265
+ <div className="flex items-start gap-3">
266
+ <Check className="h-4 w-4 text-green-500 mt-0.5 flex-shrink-0" />
267
+ <div>
268
+ <p className="text-sm font-medium">Manage repositories</p>
269
+ <p className="text-xs text-muted-foreground">
270
+ Access your repos to push changes and create branches
271
+ </p>
272
+ </div>
273
+ </div>
274
+ <div className="flex items-start gap-3">
275
+ <Check className="h-4 w-4 text-green-500 mt-0.5 flex-shrink-0" />
276
+ <div>
277
+ <p className="text-sm font-medium">Streamline workflow</p>
278
+ <p className="text-xs text-muted-foreground">
279
+ Skip manual PR creation and focus on coding
280
+ </p>
281
+ </div>
282
+ </div>
283
+ </CardContent>
284
+ </Card>
285
+
286
+ {error && (
287
+ <div className="p-3 bg-red-50 border border-red-200 rounded-lg">
288
+ <div className="text-red-600 text-sm">{error}</div>
289
+ </div>
290
+ )}
291
+
292
+ <DialogFooter className="gap-3 flex-col sm:flex-row">
293
+ <Button
294
+ variant="outline"
295
+ onClick={() => onOpenChange(false)}
296
+ className="flex-1"
297
+ >
298
+ Skip
299
+ </Button>
300
+ <Button
301
+ onClick={handleLogin}
302
+ disabled={fetching}
303
+ className="flex-1"
304
+ >
305
+ <Github className="h-4 w-4 mr-2" />
306
+ {fetching ? 'Starting…' : 'Sign in with GitHub'}
307
+ </Button>
308
+ </DialogFooter>
309
+ </div>
310
+ )}
311
+ </DialogContent>
312
+ </Dialog>
313
+ );
314
+ }
@@ -0,0 +1,185 @@
1
+ import { useState } from 'react';
2
+ import {
3
+ Dialog,
4
+ DialogContent,
5
+ DialogDescription,
6
+ DialogFooter,
7
+ DialogHeader,
8
+ DialogTitle,
9
+ } from '@/components/ui/dialog';
10
+ import { Button } from '@/components/ui/button';
11
+ import {
12
+ Select,
13
+ SelectContent,
14
+ SelectItem,
15
+ SelectTrigger,
16
+ SelectValue,
17
+ } from '@/components/ui/select';
18
+ import { Label } from '@/components/ui/label';
19
+ import { Input } from '@/components/ui/input';
20
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
21
+ import { Sparkles, Code } from 'lucide-react';
22
+ import type { EditorType, ExecutorConfig } from 'shared/types';
23
+ import {
24
+ EXECUTOR_TYPES,
25
+ EDITOR_TYPES,
26
+ EXECUTOR_LABELS,
27
+ EDITOR_LABELS,
28
+ } from 'shared/types';
29
+
30
+ interface OnboardingDialogProps {
31
+ open: boolean;
32
+ onComplete: (config: {
33
+ executor: ExecutorConfig;
34
+ editor: { editor_type: EditorType; custom_command: string | null };
35
+ }) => void;
36
+ }
37
+
38
+ export function OnboardingDialog({ open, onComplete }: OnboardingDialogProps) {
39
+ const [executor, setExecutor] = useState<ExecutorConfig>({ type: 'claude' });
40
+ const [editorType, setEditorType] = useState<EditorType>('vscode');
41
+ const [customCommand, setCustomCommand] = useState<string>('');
42
+
43
+ const handleComplete = () => {
44
+ onComplete({
45
+ executor,
46
+ editor: {
47
+ editor_type: editorType,
48
+ custom_command: editorType === 'custom' ? customCommand || null : null,
49
+ },
50
+ });
51
+ };
52
+
53
+ const isValid =
54
+ editorType !== 'custom' ||
55
+ (editorType === 'custom' && customCommand.trim() !== '');
56
+
57
+ return (
58
+ <Dialog open={open} onOpenChange={() => {}}>
59
+ <DialogContent className="sm:max-w-[600px]">
60
+ <DialogHeader>
61
+ <div className="flex items-center gap-3">
62
+ <Sparkles className="h-6 w-6 text-primary" />
63
+ <DialogTitle>Welcome to Automagik Forge</DialogTitle>
64
+ </div>
65
+ <DialogDescription className="text-left pt-2">
66
+ Let's set up your coding preferences. You can always change these
67
+ later in Settings.
68
+ </DialogDescription>
69
+ </DialogHeader>
70
+
71
+ <div className="space-y-6 py-4">
72
+ <Card>
73
+ <CardHeader>
74
+ <CardTitle className="flex items-center gap-2">
75
+ <Sparkles className="h-4 w-4" />
76
+ Choose Your Coding Agent
77
+ </CardTitle>
78
+ </CardHeader>
79
+ <CardContent className="space-y-4">
80
+ <div className="space-y-2">
81
+ <Label htmlFor="executor">Default Executor</Label>
82
+ <Select
83
+ value={executor.type}
84
+ onValueChange={(value) => setExecutor({ type: value as any })}
85
+ >
86
+ <SelectTrigger id="executor">
87
+ <SelectValue placeholder="Select your preferred coding agent" />
88
+ </SelectTrigger>
89
+ <SelectContent>
90
+ {EXECUTOR_TYPES.map((type) => (
91
+ <SelectItem key={type} value={type}>
92
+ {EXECUTOR_LABELS[type]}
93
+ </SelectItem>
94
+ ))}
95
+ </SelectContent>
96
+ </Select>
97
+ <p className="text-sm text-muted-foreground">
98
+ {executor.type === 'claude' && 'Claude Code from Anthropic'}
99
+ {executor.type === 'amp' && 'From Sourcegraph'}
100
+ {executor.type === 'gemini' && 'Google Gemini from Bloop'}
101
+ {executor.type === 'opencode-ai' && (
102
+ <span>
103
+ OpenCode AI terminal assistant{' '}
104
+ <a
105
+ href="https://github.com/opencode-ai/opencode"
106
+ target="_blank"
107
+ rel="noopener noreferrer"
108
+ className="underline hover:text-blue-600"
109
+ >
110
+ (GitHub)
111
+ </a>
112
+ </span>
113
+ )}
114
+ {executor.type === 'claude-code-router' &&
115
+ 'Claude Code Router'}
116
+ {executor.type === 'echo' &&
117
+ 'This is just for debugging automagik-forge itself'}
118
+ </p>
119
+ </div>
120
+ </CardContent>
121
+ </Card>
122
+
123
+ <Card>
124
+ <CardHeader>
125
+ <CardTitle className="flex items-center gap-2">
126
+ <Code className="h-4 w-4" />
127
+ Choose Your Code Editor
128
+ </CardTitle>
129
+ </CardHeader>
130
+ <CardContent className="space-y-4">
131
+ <div className="space-y-2">
132
+ <Label htmlFor="editor">Preferred Editor</Label>
133
+ <Select
134
+ value={editorType}
135
+ onValueChange={(value: EditorType) => setEditorType(value)}
136
+ >
137
+ <SelectTrigger id="editor">
138
+ <SelectValue placeholder="Select your preferred editor" />
139
+ </SelectTrigger>
140
+ <SelectContent>
141
+ {EDITOR_TYPES.map((type) => (
142
+ <SelectItem key={type} value={type}>
143
+ {EDITOR_LABELS[type]}
144
+ </SelectItem>
145
+ ))}
146
+ </SelectContent>
147
+ </Select>
148
+ <p className="text-sm text-muted-foreground">
149
+ This editor will be used to open task attempts and project
150
+ files.
151
+ </p>
152
+ </div>
153
+
154
+ {editorType === 'custom' && (
155
+ <div className="space-y-2">
156
+ <Label htmlFor="custom-command">Custom Command</Label>
157
+ <Input
158
+ id="custom-command"
159
+ placeholder="e.g., code, subl, vim"
160
+ value={customCommand}
161
+ onChange={(e) => setCustomCommand(e.target.value)}
162
+ />
163
+ <p className="text-sm text-muted-foreground">
164
+ Enter the command to run your custom editor. Use spaces for
165
+ arguments (e.g., "code --wait").
166
+ </p>
167
+ </div>
168
+ )}
169
+ </CardContent>
170
+ </Card>
171
+ </div>
172
+
173
+ <DialogFooter>
174
+ <Button
175
+ onClick={handleComplete}
176
+ disabled={!isValid}
177
+ className="w-full"
178
+ >
179
+ Continue
180
+ </Button>
181
+ </DialogFooter>
182
+ </DialogContent>
183
+ </Dialog>
184
+ );
185
+ }
@@ -0,0 +1,130 @@
1
+ import {
2
+ Dialog,
3
+ DialogContent,
4
+ DialogDescription,
5
+ DialogFooter,
6
+ DialogHeader,
7
+ DialogTitle,
8
+ } from '@/components/ui/dialog';
9
+ import { Button } from '@/components/ui/button';
10
+ import { Shield, CheckCircle, XCircle, Settings } from 'lucide-react';
11
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
12
+ import { useConfig } from '@/components/config-provider';
13
+
14
+ interface PrivacyOptInDialogProps {
15
+ open: boolean;
16
+ onComplete: (telemetryEnabled: boolean) => void;
17
+ }
18
+
19
+ export function PrivacyOptInDialog({
20
+ open,
21
+ onComplete,
22
+ }: PrivacyOptInDialogProps) {
23
+ const { config } = useConfig();
24
+
25
+ // Check if user is authenticated with GitHub
26
+ const isGitHubAuthenticated =
27
+ config?.github?.username && config?.github?.token;
28
+
29
+ const handleOptIn = () => {
30
+ onComplete(true);
31
+ };
32
+
33
+ const handleOptOut = () => {
34
+ onComplete(false);
35
+ };
36
+
37
+ return (
38
+ <Dialog open={open} onOpenChange={() => {}}>
39
+ <DialogContent className="sm:max-w-[700px]">
40
+ <DialogHeader>
41
+ <div className="flex items-center gap-3">
42
+ <Shield className="h-6 w-6 text-primary" />
43
+ <DialogTitle>Feedback Opt-In</DialogTitle>
44
+ </div>
45
+ <DialogDescription className="text-left pt-1">
46
+ Help us improve Automagik Forge by sharing usage data and allowing us to
47
+ contact you if needed.
48
+ </DialogDescription>
49
+ </DialogHeader>
50
+
51
+ <div className="space-y-3 py-3">
52
+ <Card>
53
+ <CardHeader className="pb-3">
54
+ <CardTitle className="text-base">
55
+ What data do we collect?
56
+ </CardTitle>
57
+ </CardHeader>
58
+ <CardContent className="space-y-2 pt-0">
59
+ {isGitHubAuthenticated && (
60
+ <div className="flex items-start gap-2">
61
+ <CheckCircle className="h-4 w-4 text-green-500 mt-0.5 flex-shrink-0" />
62
+ <div className="min-w-0">
63
+ <p className="text-sm font-medium">
64
+ GitHub profile information
65
+ </p>
66
+ <p className="text-xs text-muted-foreground">
67
+ Username and email address to send you only very important
68
+ updates about the project. We promise not to abuse this
69
+ </p>
70
+ </div>
71
+ </div>
72
+ )}
73
+ <div className="flex items-start gap-2">
74
+ <CheckCircle className="h-4 w-4 text-green-500 mt-0.5 flex-shrink-0" />
75
+ <div className="min-w-0">
76
+ <p className="text-sm font-medium">
77
+ High-level usage metrics
78
+ </p>
79
+ <p className="text-xs text-muted-foreground">
80
+ Number of tasks created, projects managed, feature usage
81
+ </p>
82
+ </div>
83
+ </div>
84
+ <div className="flex items-start gap-2">
85
+ <CheckCircle className="h-4 w-4 text-green-500 mt-0.5 flex-shrink-0" />
86
+ <div className="min-w-0">
87
+ <p className="text-sm font-medium">
88
+ Performance and error data
89
+ </p>
90
+ <p className="text-xs text-muted-foreground">
91
+ Application crashes, response times, technical issues
92
+ </p>
93
+ </div>
94
+ </div>
95
+ <div className="flex items-start gap-2">
96
+ <XCircle className="h-4 w-4 text-red-500 mt-0.5 flex-shrink-0" />
97
+ <div className="min-w-0">
98
+ <p className="text-sm font-medium">We do NOT collect</p>
99
+ <p className="text-xs text-muted-foreground">
100
+ Task contents, code snippets, project names, or other
101
+ personal data
102
+ </p>
103
+ </div>
104
+ </div>
105
+ </CardContent>
106
+ </Card>
107
+
108
+ <div className="flex items-center gap-2 text-xs text-muted-foreground bg-muted/50 p-2 rounded-lg">
109
+ <Settings className="h-3 w-3 flex-shrink-0" />
110
+ <span>
111
+ This helps us prioritize improvements. You can change this
112
+ preference anytime in Settings.
113
+ </span>
114
+ </div>
115
+ </div>
116
+
117
+ <DialogFooter className="gap-3 flex-col sm:flex-row pt-2">
118
+ <Button variant="outline" onClick={handleOptOut} className="flex-1">
119
+ <XCircle className="h-4 w-4 mr-2" />
120
+ No thanks
121
+ </Button>
122
+ <Button onClick={handleOptIn} className="flex-1">
123
+ <CheckCircle className="h-4 w-4 mr-2" />
124
+ Yes, help improve Automagik Forge
125
+ </Button>
126
+ </DialogFooter>
127
+ </DialogContent>
128
+ </Dialog>
129
+ );
130
+ }