crca 1.4.0__py3-none-any.whl

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 (501) hide show
  1. .github/ISSUE_TEMPLATE/bug_report.md +65 -0
  2. .github/ISSUE_TEMPLATE/feature_request.md +41 -0
  3. .github/PULL_REQUEST_TEMPLATE.md +20 -0
  4. .github/workflows/publish-manual.yml +61 -0
  5. .github/workflows/publish.yml +64 -0
  6. .gitignore +214 -0
  7. CRCA.py +4156 -0
  8. LICENSE +201 -0
  9. MANIFEST.in +43 -0
  10. PKG-INFO +5035 -0
  11. README.md +4959 -0
  12. __init__.py +17 -0
  13. branches/CRCA-Q.py +2728 -0
  14. branches/crca_cg/corposwarm.py +9065 -0
  15. branches/crca_cg/fix_rancher_docker_creds.ps1 +155 -0
  16. branches/crca_cg/package.json +5 -0
  17. branches/crca_cg/test_bolt_integration.py +446 -0
  18. branches/crca_cg/test_corposwarm_comprehensive.py +773 -0
  19. branches/crca_cg/test_new_features.py +163 -0
  20. branches/crca_sd/__init__.py +149 -0
  21. branches/crca_sd/crca_sd_core.py +770 -0
  22. branches/crca_sd/crca_sd_governance.py +1325 -0
  23. branches/crca_sd/crca_sd_mpc.py +1130 -0
  24. branches/crca_sd/crca_sd_realtime.py +1844 -0
  25. branches/crca_sd/crca_sd_tui.py +1133 -0
  26. crca-1.4.0.dist-info/METADATA +5035 -0
  27. crca-1.4.0.dist-info/RECORD +501 -0
  28. crca-1.4.0.dist-info/WHEEL +4 -0
  29. crca-1.4.0.dist-info/licenses/LICENSE +201 -0
  30. docs/CRCA-Q.md +2333 -0
  31. examples/config.yaml.example +25 -0
  32. examples/crca_sd_example.py +513 -0
  33. examples/data_broker_example.py +294 -0
  34. examples/logistics_corporation.py +861 -0
  35. examples/palantir_example.py +299 -0
  36. examples/policy_bench.py +934 -0
  37. examples/pridnestrovia-sd.py +705 -0
  38. examples/pridnestrovia_realtime.py +1902 -0
  39. prompts/__init__.py +10 -0
  40. prompts/default_crca.py +101 -0
  41. pyproject.toml +151 -0
  42. requirements.txt +76 -0
  43. schemas/__init__.py +43 -0
  44. schemas/mcpSchemas.py +51 -0
  45. schemas/policy.py +458 -0
  46. templates/__init__.py +38 -0
  47. templates/base_specialized_agent.py +195 -0
  48. templates/drift_detection.py +325 -0
  49. templates/examples/causal_agent_template.py +309 -0
  50. templates/examples/drag_drop_example.py +213 -0
  51. templates/examples/logistics_agent_template.py +207 -0
  52. templates/examples/trading_agent_template.py +206 -0
  53. templates/feature_mixins.py +253 -0
  54. templates/graph_management.py +442 -0
  55. templates/llm_integration.py +194 -0
  56. templates/module_registry.py +276 -0
  57. templates/mpc_planner.py +280 -0
  58. templates/policy_loop.py +1168 -0
  59. templates/prediction_framework.py +448 -0
  60. templates/statistical_methods.py +778 -0
  61. tests/sanity.yml +31 -0
  62. tests/sanity_check +406 -0
  63. tests/test_core.py +47 -0
  64. tests/test_crca_excel.py +166 -0
  65. tests/test_crca_sd.py +780 -0
  66. tests/test_data_broker.py +424 -0
  67. tests/test_palantir.py +349 -0
  68. tools/__init__.py +38 -0
  69. tools/actuators.py +437 -0
  70. tools/bolt.diy/Dockerfile +103 -0
  71. tools/bolt.diy/app/components/@settings/core/AvatarDropdown.tsx +175 -0
  72. tools/bolt.diy/app/components/@settings/core/ControlPanel.tsx +345 -0
  73. tools/bolt.diy/app/components/@settings/core/constants.tsx +108 -0
  74. tools/bolt.diy/app/components/@settings/core/types.ts +114 -0
  75. tools/bolt.diy/app/components/@settings/index.ts +12 -0
  76. tools/bolt.diy/app/components/@settings/shared/components/TabTile.tsx +151 -0
  77. tools/bolt.diy/app/components/@settings/shared/service-integration/ConnectionForm.tsx +193 -0
  78. tools/bolt.diy/app/components/@settings/shared/service-integration/ConnectionTestIndicator.tsx +60 -0
  79. tools/bolt.diy/app/components/@settings/shared/service-integration/ErrorState.tsx +102 -0
  80. tools/bolt.diy/app/components/@settings/shared/service-integration/LoadingState.tsx +94 -0
  81. tools/bolt.diy/app/components/@settings/shared/service-integration/ServiceHeader.tsx +72 -0
  82. tools/bolt.diy/app/components/@settings/shared/service-integration/index.ts +6 -0
  83. tools/bolt.diy/app/components/@settings/tabs/data/DataTab.tsx +721 -0
  84. tools/bolt.diy/app/components/@settings/tabs/data/DataVisualization.tsx +384 -0
  85. tools/bolt.diy/app/components/@settings/tabs/event-logs/EventLogsTab.tsx +1013 -0
  86. tools/bolt.diy/app/components/@settings/tabs/features/FeaturesTab.tsx +295 -0
  87. tools/bolt.diy/app/components/@settings/tabs/github/GitHubTab.tsx +281 -0
  88. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubAuthDialog.tsx +173 -0
  89. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubCacheManager.tsx +367 -0
  90. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubConnection.tsx +233 -0
  91. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubErrorBoundary.tsx +105 -0
  92. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubProgressiveLoader.tsx +266 -0
  93. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubRepositoryCard.tsx +121 -0
  94. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubRepositorySelector.tsx +312 -0
  95. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubStats.tsx +291 -0
  96. tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubUserProfile.tsx +46 -0
  97. tools/bolt.diy/app/components/@settings/tabs/github/components/shared/GitHubStateIndicators.tsx +264 -0
  98. tools/bolt.diy/app/components/@settings/tabs/github/components/shared/RepositoryCard.tsx +361 -0
  99. tools/bolt.diy/app/components/@settings/tabs/github/components/shared/index.ts +11 -0
  100. tools/bolt.diy/app/components/@settings/tabs/gitlab/GitLabTab.tsx +305 -0
  101. tools/bolt.diy/app/components/@settings/tabs/gitlab/components/GitLabAuthDialog.tsx +186 -0
  102. tools/bolt.diy/app/components/@settings/tabs/gitlab/components/GitLabConnection.tsx +253 -0
  103. tools/bolt.diy/app/components/@settings/tabs/gitlab/components/GitLabRepositorySelector.tsx +358 -0
  104. tools/bolt.diy/app/components/@settings/tabs/gitlab/components/RepositoryCard.tsx +79 -0
  105. tools/bolt.diy/app/components/@settings/tabs/gitlab/components/RepositoryList.tsx +142 -0
  106. tools/bolt.diy/app/components/@settings/tabs/gitlab/components/StatsDisplay.tsx +91 -0
  107. tools/bolt.diy/app/components/@settings/tabs/gitlab/components/index.ts +4 -0
  108. tools/bolt.diy/app/components/@settings/tabs/mcp/McpServerList.tsx +99 -0
  109. tools/bolt.diy/app/components/@settings/tabs/mcp/McpServerListItem.tsx +70 -0
  110. tools/bolt.diy/app/components/@settings/tabs/mcp/McpStatusBadge.tsx +37 -0
  111. tools/bolt.diy/app/components/@settings/tabs/mcp/McpTab.tsx +239 -0
  112. tools/bolt.diy/app/components/@settings/tabs/netlify/NetlifyTab.tsx +1393 -0
  113. tools/bolt.diy/app/components/@settings/tabs/netlify/components/NetlifyConnection.tsx +990 -0
  114. tools/bolt.diy/app/components/@settings/tabs/netlify/components/index.ts +1 -0
  115. tools/bolt.diy/app/components/@settings/tabs/notifications/NotificationsTab.tsx +300 -0
  116. tools/bolt.diy/app/components/@settings/tabs/profile/ProfileTab.tsx +181 -0
  117. tools/bolt.diy/app/components/@settings/tabs/providers/cloud/CloudProvidersTab.tsx +308 -0
  118. tools/bolt.diy/app/components/@settings/tabs/providers/local/ErrorBoundary.tsx +68 -0
  119. tools/bolt.diy/app/components/@settings/tabs/providers/local/HealthStatusBadge.tsx +64 -0
  120. tools/bolt.diy/app/components/@settings/tabs/providers/local/LoadingSkeleton.tsx +107 -0
  121. tools/bolt.diy/app/components/@settings/tabs/providers/local/LocalProvidersTab.tsx +556 -0
  122. tools/bolt.diy/app/components/@settings/tabs/providers/local/ModelCard.tsx +106 -0
  123. tools/bolt.diy/app/components/@settings/tabs/providers/local/ProviderCard.tsx +120 -0
  124. tools/bolt.diy/app/components/@settings/tabs/providers/local/SetupGuide.tsx +671 -0
  125. tools/bolt.diy/app/components/@settings/tabs/providers/local/StatusDashboard.tsx +91 -0
  126. tools/bolt.diy/app/components/@settings/tabs/providers/local/types.ts +44 -0
  127. tools/bolt.diy/app/components/@settings/tabs/settings/SettingsTab.tsx +215 -0
  128. tools/bolt.diy/app/components/@settings/tabs/supabase/SupabaseTab.tsx +1089 -0
  129. tools/bolt.diy/app/components/@settings/tabs/vercel/VercelTab.tsx +909 -0
  130. tools/bolt.diy/app/components/@settings/tabs/vercel/components/VercelConnection.tsx +368 -0
  131. tools/bolt.diy/app/components/@settings/tabs/vercel/components/index.ts +1 -0
  132. tools/bolt.diy/app/components/@settings/utils/tab-helpers.ts +54 -0
  133. tools/bolt.diy/app/components/chat/APIKeyManager.tsx +169 -0
  134. tools/bolt.diy/app/components/chat/Artifact.tsx +296 -0
  135. tools/bolt.diy/app/components/chat/AssistantMessage.tsx +192 -0
  136. tools/bolt.diy/app/components/chat/BaseChat.module.scss +47 -0
  137. tools/bolt.diy/app/components/chat/BaseChat.tsx +522 -0
  138. tools/bolt.diy/app/components/chat/Chat.client.tsx +670 -0
  139. tools/bolt.diy/app/components/chat/ChatAlert.tsx +108 -0
  140. tools/bolt.diy/app/components/chat/ChatBox.tsx +334 -0
  141. tools/bolt.diy/app/components/chat/CodeBlock.module.scss +10 -0
  142. tools/bolt.diy/app/components/chat/CodeBlock.tsx +85 -0
  143. tools/bolt.diy/app/components/chat/DicussMode.tsx +17 -0
  144. tools/bolt.diy/app/components/chat/ExamplePrompts.tsx +37 -0
  145. tools/bolt.diy/app/components/chat/FilePreview.tsx +38 -0
  146. tools/bolt.diy/app/components/chat/GitCloneButton.tsx +327 -0
  147. tools/bolt.diy/app/components/chat/ImportFolderButton.tsx +141 -0
  148. tools/bolt.diy/app/components/chat/LLMApiAlert.tsx +109 -0
  149. tools/bolt.diy/app/components/chat/MCPTools.tsx +129 -0
  150. tools/bolt.diy/app/components/chat/Markdown.module.scss +171 -0
  151. tools/bolt.diy/app/components/chat/Markdown.spec.ts +48 -0
  152. tools/bolt.diy/app/components/chat/Markdown.tsx +252 -0
  153. tools/bolt.diy/app/components/chat/Messages.client.tsx +102 -0
  154. tools/bolt.diy/app/components/chat/ModelSelector.tsx +797 -0
  155. tools/bolt.diy/app/components/chat/NetlifyDeploymentLink.client.tsx +51 -0
  156. tools/bolt.diy/app/components/chat/ProgressCompilation.tsx +110 -0
  157. tools/bolt.diy/app/components/chat/ScreenshotStateManager.tsx +33 -0
  158. tools/bolt.diy/app/components/chat/SendButton.client.tsx +39 -0
  159. tools/bolt.diy/app/components/chat/SpeechRecognition.tsx +28 -0
  160. tools/bolt.diy/app/components/chat/StarterTemplates.tsx +38 -0
  161. tools/bolt.diy/app/components/chat/SupabaseAlert.tsx +199 -0
  162. tools/bolt.diy/app/components/chat/SupabaseConnection.tsx +339 -0
  163. tools/bolt.diy/app/components/chat/ThoughtBox.tsx +43 -0
  164. tools/bolt.diy/app/components/chat/ToolInvocations.tsx +409 -0
  165. tools/bolt.diy/app/components/chat/UserMessage.tsx +101 -0
  166. tools/bolt.diy/app/components/chat/VercelDeploymentLink.client.tsx +158 -0
  167. tools/bolt.diy/app/components/chat/chatExportAndImport/ExportChatButton.tsx +49 -0
  168. tools/bolt.diy/app/components/chat/chatExportAndImport/ImportButtons.tsx +96 -0
  169. tools/bolt.diy/app/components/deploy/DeployAlert.tsx +197 -0
  170. tools/bolt.diy/app/components/deploy/DeployButton.tsx +277 -0
  171. tools/bolt.diy/app/components/deploy/GitHubDeploy.client.tsx +171 -0
  172. tools/bolt.diy/app/components/deploy/GitHubDeploymentDialog.tsx +1041 -0
  173. tools/bolt.diy/app/components/deploy/GitLabDeploy.client.tsx +171 -0
  174. tools/bolt.diy/app/components/deploy/GitLabDeploymentDialog.tsx +764 -0
  175. tools/bolt.diy/app/components/deploy/NetlifyDeploy.client.tsx +246 -0
  176. tools/bolt.diy/app/components/deploy/VercelDeploy.client.tsx +235 -0
  177. tools/bolt.diy/app/components/editor/codemirror/BinaryContent.tsx +7 -0
  178. tools/bolt.diy/app/components/editor/codemirror/CodeMirrorEditor.tsx +555 -0
  179. tools/bolt.diy/app/components/editor/codemirror/EnvMasking.ts +80 -0
  180. tools/bolt.diy/app/components/editor/codemirror/cm-theme.ts +192 -0
  181. tools/bolt.diy/app/components/editor/codemirror/indent.ts +68 -0
  182. tools/bolt.diy/app/components/editor/codemirror/languages.ts +112 -0
  183. tools/bolt.diy/app/components/git/GitUrlImport.client.tsx +147 -0
  184. tools/bolt.diy/app/components/header/Header.tsx +42 -0
  185. tools/bolt.diy/app/components/header/HeaderActionButtons.client.tsx +54 -0
  186. tools/bolt.diy/app/components/mandate/MandateSubmission.tsx +167 -0
  187. tools/bolt.diy/app/components/observability/DeploymentStatus.tsx +168 -0
  188. tools/bolt.diy/app/components/observability/EventTimeline.tsx +119 -0
  189. tools/bolt.diy/app/components/observability/FileDiffViewer.tsx +121 -0
  190. tools/bolt.diy/app/components/observability/GovernanceStatus.tsx +197 -0
  191. tools/bolt.diy/app/components/observability/GovernorMetrics.tsx +246 -0
  192. tools/bolt.diy/app/components/observability/LogStream.tsx +244 -0
  193. tools/bolt.diy/app/components/observability/MandateDetails.tsx +201 -0
  194. tools/bolt.diy/app/components/observability/ObservabilityDashboard.tsx +200 -0
  195. tools/bolt.diy/app/components/sidebar/HistoryItem.tsx +187 -0
  196. tools/bolt.diy/app/components/sidebar/Menu.client.tsx +536 -0
  197. tools/bolt.diy/app/components/sidebar/date-binning.ts +59 -0
  198. tools/bolt.diy/app/components/txt +1 -0
  199. tools/bolt.diy/app/components/ui/BackgroundRays/index.tsx +18 -0
  200. tools/bolt.diy/app/components/ui/BackgroundRays/styles.module.scss +246 -0
  201. tools/bolt.diy/app/components/ui/Badge.tsx +53 -0
  202. tools/bolt.diy/app/components/ui/BranchSelector.tsx +270 -0
  203. tools/bolt.diy/app/components/ui/Breadcrumbs.tsx +101 -0
  204. tools/bolt.diy/app/components/ui/Button.tsx +46 -0
  205. tools/bolt.diy/app/components/ui/Card.tsx +55 -0
  206. tools/bolt.diy/app/components/ui/Checkbox.tsx +32 -0
  207. tools/bolt.diy/app/components/ui/CloseButton.tsx +49 -0
  208. tools/bolt.diy/app/components/ui/CodeBlock.tsx +103 -0
  209. tools/bolt.diy/app/components/ui/Collapsible.tsx +9 -0
  210. tools/bolt.diy/app/components/ui/ColorSchemeDialog.tsx +378 -0
  211. tools/bolt.diy/app/components/ui/Dialog.tsx +449 -0
  212. tools/bolt.diy/app/components/ui/Dropdown.tsx +63 -0
  213. tools/bolt.diy/app/components/ui/EmptyState.tsx +154 -0
  214. tools/bolt.diy/app/components/ui/FileIcon.tsx +346 -0
  215. tools/bolt.diy/app/components/ui/FilterChip.tsx +92 -0
  216. tools/bolt.diy/app/components/ui/GlowingEffect.tsx +192 -0
  217. tools/bolt.diy/app/components/ui/GradientCard.tsx +100 -0
  218. tools/bolt.diy/app/components/ui/IconButton.tsx +84 -0
  219. tools/bolt.diy/app/components/ui/Input.tsx +22 -0
  220. tools/bolt.diy/app/components/ui/Label.tsx +20 -0
  221. tools/bolt.diy/app/components/ui/LoadingDots.tsx +27 -0
  222. tools/bolt.diy/app/components/ui/LoadingOverlay.tsx +32 -0
  223. tools/bolt.diy/app/components/ui/PanelHeader.tsx +20 -0
  224. tools/bolt.diy/app/components/ui/PanelHeaderButton.tsx +36 -0
  225. tools/bolt.diy/app/components/ui/Popover.tsx +29 -0
  226. tools/bolt.diy/app/components/ui/Progress.tsx +22 -0
  227. tools/bolt.diy/app/components/ui/RepositoryStats.tsx +87 -0
  228. tools/bolt.diy/app/components/ui/ScrollArea.tsx +41 -0
  229. tools/bolt.diy/app/components/ui/SearchInput.tsx +80 -0
  230. tools/bolt.diy/app/components/ui/SearchResultItem.tsx +134 -0
  231. tools/bolt.diy/app/components/ui/Separator.tsx +22 -0
  232. tools/bolt.diy/app/components/ui/SettingsButton.tsx +35 -0
  233. tools/bolt.diy/app/components/ui/Slider.tsx +73 -0
  234. tools/bolt.diy/app/components/ui/StatusIndicator.tsx +90 -0
  235. tools/bolt.diy/app/components/ui/Switch.tsx +37 -0
  236. tools/bolt.diy/app/components/ui/Tabs.tsx +52 -0
  237. tools/bolt.diy/app/components/ui/TabsWithSlider.tsx +112 -0
  238. tools/bolt.diy/app/components/ui/ThemeSwitch.tsx +29 -0
  239. tools/bolt.diy/app/components/ui/Tooltip.tsx +122 -0
  240. tools/bolt.diy/app/components/ui/index.ts +38 -0
  241. tools/bolt.diy/app/components/ui/use-toast.ts +66 -0
  242. tools/bolt.diy/app/components/workbench/DiffView.tsx +796 -0
  243. tools/bolt.diy/app/components/workbench/EditorPanel.tsx +174 -0
  244. tools/bolt.diy/app/components/workbench/ExpoQrModal.tsx +55 -0
  245. tools/bolt.diy/app/components/workbench/FileBreadcrumb.tsx +150 -0
  246. tools/bolt.diy/app/components/workbench/FileTree.tsx +565 -0
  247. tools/bolt.diy/app/components/workbench/Inspector.tsx +126 -0
  248. tools/bolt.diy/app/components/workbench/InspectorPanel.tsx +146 -0
  249. tools/bolt.diy/app/components/workbench/LockManager.tsx +262 -0
  250. tools/bolt.diy/app/components/workbench/PortDropdown.tsx +91 -0
  251. tools/bolt.diy/app/components/workbench/Preview.tsx +1049 -0
  252. tools/bolt.diy/app/components/workbench/ScreenshotSelector.tsx +293 -0
  253. tools/bolt.diy/app/components/workbench/Search.tsx +257 -0
  254. tools/bolt.diy/app/components/workbench/Workbench.client.tsx +506 -0
  255. tools/bolt.diy/app/components/workbench/terminal/Terminal.tsx +131 -0
  256. tools/bolt.diy/app/components/workbench/terminal/TerminalManager.tsx +68 -0
  257. tools/bolt.diy/app/components/workbench/terminal/TerminalTabs.tsx +277 -0
  258. tools/bolt.diy/app/components/workbench/terminal/theme.ts +36 -0
  259. tools/bolt.diy/app/components/workflow/WorkflowPhase.tsx +109 -0
  260. tools/bolt.diy/app/components/workflow/WorkflowStatus.tsx +60 -0
  261. tools/bolt.diy/app/components/workflow/WorkflowTimeline.tsx +150 -0
  262. tools/bolt.diy/app/entry.client.tsx +7 -0
  263. tools/bolt.diy/app/entry.server.tsx +80 -0
  264. tools/bolt.diy/app/root.tsx +156 -0
  265. tools/bolt.diy/app/routes/_index.tsx +175 -0
  266. tools/bolt.diy/app/routes/api.bug-report.ts +254 -0
  267. tools/bolt.diy/app/routes/api.chat.ts +463 -0
  268. tools/bolt.diy/app/routes/api.check-env-key.ts +41 -0
  269. tools/bolt.diy/app/routes/api.configured-providers.ts +110 -0
  270. tools/bolt.diy/app/routes/api.corporate-swarm-status.ts +55 -0
  271. tools/bolt.diy/app/routes/api.enhancer.ts +137 -0
  272. tools/bolt.diy/app/routes/api.export-api-keys.ts +44 -0
  273. tools/bolt.diy/app/routes/api.git-info.ts +69 -0
  274. tools/bolt.diy/app/routes/api.git-proxy.$.ts +178 -0
  275. tools/bolt.diy/app/routes/api.github-branches.ts +166 -0
  276. tools/bolt.diy/app/routes/api.github-deploy.ts +67 -0
  277. tools/bolt.diy/app/routes/api.github-stats.ts +198 -0
  278. tools/bolt.diy/app/routes/api.github-template.ts +242 -0
  279. tools/bolt.diy/app/routes/api.github-user.ts +287 -0
  280. tools/bolt.diy/app/routes/api.gitlab-branches.ts +143 -0
  281. tools/bolt.diy/app/routes/api.gitlab-deploy.ts +67 -0
  282. tools/bolt.diy/app/routes/api.gitlab-projects.ts +105 -0
  283. tools/bolt.diy/app/routes/api.health.ts +8 -0
  284. tools/bolt.diy/app/routes/api.llmcall.ts +298 -0
  285. tools/bolt.diy/app/routes/api.mandate.ts +351 -0
  286. tools/bolt.diy/app/routes/api.mcp-check.ts +16 -0
  287. tools/bolt.diy/app/routes/api.mcp-update-config.ts +23 -0
  288. tools/bolt.diy/app/routes/api.models.$provider.ts +2 -0
  289. tools/bolt.diy/app/routes/api.models.ts +90 -0
  290. tools/bolt.diy/app/routes/api.netlify-deploy.ts +240 -0
  291. tools/bolt.diy/app/routes/api.netlify-user.ts +142 -0
  292. tools/bolt.diy/app/routes/api.supabase-user.ts +199 -0
  293. tools/bolt.diy/app/routes/api.supabase.query.ts +92 -0
  294. tools/bolt.diy/app/routes/api.supabase.ts +56 -0
  295. tools/bolt.diy/app/routes/api.supabase.variables.ts +32 -0
  296. tools/bolt.diy/app/routes/api.system.diagnostics.ts +142 -0
  297. tools/bolt.diy/app/routes/api.system.disk-info.ts +311 -0
  298. tools/bolt.diy/app/routes/api.system.git-info.ts +332 -0
  299. tools/bolt.diy/app/routes/api.update.ts +21 -0
  300. tools/bolt.diy/app/routes/api.vercel-deploy.ts +497 -0
  301. tools/bolt.diy/app/routes/api.vercel-user.ts +161 -0
  302. tools/bolt.diy/app/routes/api.workflow-status.$proposalId.ts +309 -0
  303. tools/bolt.diy/app/routes/chat.$id.tsx +8 -0
  304. tools/bolt.diy/app/routes/execute.$mandateId.tsx +432 -0
  305. tools/bolt.diy/app/routes/git.tsx +25 -0
  306. tools/bolt.diy/app/routes/observability.$mandateId.tsx +50 -0
  307. tools/bolt.diy/app/routes/webcontainer.connect.$id.tsx +32 -0
  308. tools/bolt.diy/app/routes/webcontainer.preview.$id.tsx +97 -0
  309. tools/bolt.diy/app/routes/workflow.$proposalId.tsx +170 -0
  310. tools/bolt.diy/app/styles/animations.scss +49 -0
  311. tools/bolt.diy/app/styles/components/code.scss +9 -0
  312. tools/bolt.diy/app/styles/components/editor.scss +135 -0
  313. tools/bolt.diy/app/styles/components/resize-handle.scss +30 -0
  314. tools/bolt.diy/app/styles/components/terminal.scss +3 -0
  315. tools/bolt.diy/app/styles/components/toast.scss +23 -0
  316. tools/bolt.diy/app/styles/diff-view.css +72 -0
  317. tools/bolt.diy/app/styles/index.scss +73 -0
  318. tools/bolt.diy/app/styles/variables.scss +255 -0
  319. tools/bolt.diy/app/styles/z-index.scss +37 -0
  320. tools/bolt.diy/app/types/GitHub.ts +182 -0
  321. tools/bolt.diy/app/types/GitLab.ts +103 -0
  322. tools/bolt.diy/app/types/actions.ts +85 -0
  323. tools/bolt.diy/app/types/artifact.ts +5 -0
  324. tools/bolt.diy/app/types/context.ts +26 -0
  325. tools/bolt.diy/app/types/design-scheme.ts +93 -0
  326. tools/bolt.diy/app/types/global.d.ts +13 -0
  327. tools/bolt.diy/app/types/mandate.ts +333 -0
  328. tools/bolt.diy/app/types/model.ts +25 -0
  329. tools/bolt.diy/app/types/netlify.ts +94 -0
  330. tools/bolt.diy/app/types/supabase.ts +54 -0
  331. tools/bolt.diy/app/types/template.ts +8 -0
  332. tools/bolt.diy/app/types/terminal.ts +9 -0
  333. tools/bolt.diy/app/types/theme.ts +1 -0
  334. tools/bolt.diy/app/types/vercel.ts +67 -0
  335. tools/bolt.diy/app/utils/buffer.ts +29 -0
  336. tools/bolt.diy/app/utils/classNames.ts +65 -0
  337. tools/bolt.diy/app/utils/constants.ts +147 -0
  338. tools/bolt.diy/app/utils/debounce.ts +13 -0
  339. tools/bolt.diy/app/utils/debugLogger.ts +1284 -0
  340. tools/bolt.diy/app/utils/diff.spec.ts +11 -0
  341. tools/bolt.diy/app/utils/diff.ts +117 -0
  342. tools/bolt.diy/app/utils/easings.ts +3 -0
  343. tools/bolt.diy/app/utils/fileLocks.ts +96 -0
  344. tools/bolt.diy/app/utils/fileUtils.ts +121 -0
  345. tools/bolt.diy/app/utils/folderImport.ts +73 -0
  346. tools/bolt.diy/app/utils/formatSize.ts +12 -0
  347. tools/bolt.diy/app/utils/getLanguageFromExtension.ts +24 -0
  348. tools/bolt.diy/app/utils/githubStats.ts +9 -0
  349. tools/bolt.diy/app/utils/gitlabStats.ts +54 -0
  350. tools/bolt.diy/app/utils/logger.ts +162 -0
  351. tools/bolt.diy/app/utils/markdown.ts +155 -0
  352. tools/bolt.diy/app/utils/mobile.ts +4 -0
  353. tools/bolt.diy/app/utils/os.ts +4 -0
  354. tools/bolt.diy/app/utils/path.ts +19 -0
  355. tools/bolt.diy/app/utils/projectCommands.ts +197 -0
  356. tools/bolt.diy/app/utils/promises.ts +19 -0
  357. tools/bolt.diy/app/utils/react.ts +6 -0
  358. tools/bolt.diy/app/utils/sampler.ts +49 -0
  359. tools/bolt.diy/app/utils/selectStarterTemplate.ts +255 -0
  360. tools/bolt.diy/app/utils/shell.ts +384 -0
  361. tools/bolt.diy/app/utils/stacktrace.ts +27 -0
  362. tools/bolt.diy/app/utils/stripIndent.ts +23 -0
  363. tools/bolt.diy/app/utils/terminal.ts +11 -0
  364. tools/bolt.diy/app/utils/unreachable.ts +3 -0
  365. tools/bolt.diy/app/vite-env.d.ts +2 -0
  366. tools/bolt.diy/assets/entitlements.mac.plist +25 -0
  367. tools/bolt.diy/assets/icons/icon.icns +0 -0
  368. tools/bolt.diy/assets/icons/icon.ico +0 -0
  369. tools/bolt.diy/assets/icons/icon.png +0 -0
  370. tools/bolt.diy/bindings.js +78 -0
  371. tools/bolt.diy/bindings.sh +33 -0
  372. tools/bolt.diy/docker-compose.yaml +145 -0
  373. tools/bolt.diy/electron/main/index.ts +201 -0
  374. tools/bolt.diy/electron/main/tsconfig.json +30 -0
  375. tools/bolt.diy/electron/main/ui/menu.ts +29 -0
  376. tools/bolt.diy/electron/main/ui/window.ts +54 -0
  377. tools/bolt.diy/electron/main/utils/auto-update.ts +110 -0
  378. tools/bolt.diy/electron/main/utils/constants.ts +4 -0
  379. tools/bolt.diy/electron/main/utils/cookie.ts +40 -0
  380. tools/bolt.diy/electron/main/utils/reload.ts +35 -0
  381. tools/bolt.diy/electron/main/utils/serve.ts +71 -0
  382. tools/bolt.diy/electron/main/utils/store.ts +3 -0
  383. tools/bolt.diy/electron/main/utils/vite-server.ts +44 -0
  384. tools/bolt.diy/electron/main/vite.config.ts +44 -0
  385. tools/bolt.diy/electron/preload/index.ts +22 -0
  386. tools/bolt.diy/electron/preload/tsconfig.json +7 -0
  387. tools/bolt.diy/electron/preload/vite.config.ts +31 -0
  388. tools/bolt.diy/electron-builder.yml +64 -0
  389. tools/bolt.diy/electron-update.yml +4 -0
  390. tools/bolt.diy/eslint.config.mjs +57 -0
  391. tools/bolt.diy/functions/[[path]].ts +12 -0
  392. tools/bolt.diy/icons/angular.svg +1 -0
  393. tools/bolt.diy/icons/astro.svg +8 -0
  394. tools/bolt.diy/icons/chat.svg +1 -0
  395. tools/bolt.diy/icons/expo-brand.svg +1 -0
  396. tools/bolt.diy/icons/expo.svg +4 -0
  397. tools/bolt.diy/icons/logo-text.svg +1 -0
  398. tools/bolt.diy/icons/logo.svg +4 -0
  399. tools/bolt.diy/icons/mcp.svg +1 -0
  400. tools/bolt.diy/icons/nativescript.svg +1 -0
  401. tools/bolt.diy/icons/netlify.svg +10 -0
  402. tools/bolt.diy/icons/nextjs.svg +1 -0
  403. tools/bolt.diy/icons/nuxt.svg +1 -0
  404. tools/bolt.diy/icons/qwik.svg +1 -0
  405. tools/bolt.diy/icons/react.svg +1 -0
  406. tools/bolt.diy/icons/remix.svg +24 -0
  407. tools/bolt.diy/icons/remotion.svg +1 -0
  408. tools/bolt.diy/icons/shadcn.svg +21 -0
  409. tools/bolt.diy/icons/slidev.svg +60 -0
  410. tools/bolt.diy/icons/solidjs.svg +1 -0
  411. tools/bolt.diy/icons/stars.svg +1 -0
  412. tools/bolt.diy/icons/svelte.svg +1 -0
  413. tools/bolt.diy/icons/typescript.svg +1 -0
  414. tools/bolt.diy/icons/vite.svg +1 -0
  415. tools/bolt.diy/icons/vue.svg +1 -0
  416. tools/bolt.diy/load-context.ts +9 -0
  417. tools/bolt.diy/notarize.cjs +31 -0
  418. tools/bolt.diy/package.json +218 -0
  419. tools/bolt.diy/playwright.config.preview.ts +35 -0
  420. tools/bolt.diy/pre-start.cjs +26 -0
  421. tools/bolt.diy/public/apple-touch-icon-precomposed.png +0 -0
  422. tools/bolt.diy/public/apple-touch-icon.png +0 -0
  423. tools/bolt.diy/public/favicon.ico +0 -0
  424. tools/bolt.diy/public/favicon.svg +4 -0
  425. tools/bolt.diy/public/icons/AmazonBedrock.svg +1 -0
  426. tools/bolt.diy/public/icons/Anthropic.svg +4 -0
  427. tools/bolt.diy/public/icons/Cohere.svg +4 -0
  428. tools/bolt.diy/public/icons/Deepseek.svg +5 -0
  429. tools/bolt.diy/public/icons/Default.svg +4 -0
  430. tools/bolt.diy/public/icons/Google.svg +4 -0
  431. tools/bolt.diy/public/icons/Groq.svg +4 -0
  432. tools/bolt.diy/public/icons/HuggingFace.svg +4 -0
  433. tools/bolt.diy/public/icons/Hyperbolic.svg +3 -0
  434. tools/bolt.diy/public/icons/LMStudio.svg +5 -0
  435. tools/bolt.diy/public/icons/Mistral.svg +4 -0
  436. tools/bolt.diy/public/icons/Ollama.svg +4 -0
  437. tools/bolt.diy/public/icons/OpenAI.svg +4 -0
  438. tools/bolt.diy/public/icons/OpenAILike.svg +4 -0
  439. tools/bolt.diy/public/icons/OpenRouter.svg +4 -0
  440. tools/bolt.diy/public/icons/Perplexity.svg +4 -0
  441. tools/bolt.diy/public/icons/Together.svg +4 -0
  442. tools/bolt.diy/public/icons/xAI.svg +5 -0
  443. tools/bolt.diy/public/inspector-script.js +292 -0
  444. tools/bolt.diy/public/logo-dark-styled.png +0 -0
  445. tools/bolt.diy/public/logo-dark.png +0 -0
  446. tools/bolt.diy/public/logo-light-styled.png +0 -0
  447. tools/bolt.diy/public/logo-light.png +0 -0
  448. tools/bolt.diy/public/logo.svg +15 -0
  449. tools/bolt.diy/public/social_preview_index.jpg +0 -0
  450. tools/bolt.diy/scripts/clean.js +45 -0
  451. tools/bolt.diy/scripts/electron-dev.mjs +181 -0
  452. tools/bolt.diy/scripts/setup-env.sh +41 -0
  453. tools/bolt.diy/scripts/update-imports.sh +7 -0
  454. tools/bolt.diy/scripts/update.sh +52 -0
  455. tools/bolt.diy/services/execution-governor/Dockerfile +41 -0
  456. tools/bolt.diy/services/execution-governor/config.ts +42 -0
  457. tools/bolt.diy/services/execution-governor/index.ts +683 -0
  458. tools/bolt.diy/services/execution-governor/metrics.ts +141 -0
  459. tools/bolt.diy/services/execution-governor/package.json +31 -0
  460. tools/bolt.diy/services/execution-governor/priority-queue.ts +139 -0
  461. tools/bolt.diy/services/execution-governor/tsconfig.json +21 -0
  462. tools/bolt.diy/services/execution-governor/types.ts +145 -0
  463. tools/bolt.diy/services/headless-executor/Dockerfile +43 -0
  464. tools/bolt.diy/services/headless-executor/executor.ts +210 -0
  465. tools/bolt.diy/services/headless-executor/index.ts +323 -0
  466. tools/bolt.diy/services/headless-executor/package.json +27 -0
  467. tools/bolt.diy/services/headless-executor/tsconfig.json +21 -0
  468. tools/bolt.diy/services/headless-executor/types.ts +38 -0
  469. tools/bolt.diy/test-workflows.sh +240 -0
  470. tools/bolt.diy/tests/integration/corporate-swarm.test.ts +208 -0
  471. tools/bolt.diy/tests/mandates/budget-limited.json +34 -0
  472. tools/bolt.diy/tests/mandates/complex.json +53 -0
  473. tools/bolt.diy/tests/mandates/constraint-enforced.json +36 -0
  474. tools/bolt.diy/tests/mandates/simple.json +35 -0
  475. tools/bolt.diy/tsconfig.json +37 -0
  476. tools/bolt.diy/types/istextorbinary.d.ts +15 -0
  477. tools/bolt.diy/uno.config.ts +279 -0
  478. tools/bolt.diy/vite-electron.config.ts +76 -0
  479. tools/bolt.diy/vite.config.ts +112 -0
  480. tools/bolt.diy/worker-configuration.d.ts +22 -0
  481. tools/bolt.diy/wrangler.toml +6 -0
  482. tools/code_generator.py +461 -0
  483. tools/file_operations.py +465 -0
  484. tools/mandate_generator.py +337 -0
  485. tools/mcpClientUtils.py +1216 -0
  486. tools/sensors.py +285 -0
  487. utils/Agent_types.py +15 -0
  488. utils/AnyToStr.py +0 -0
  489. utils/HHCS.py +277 -0
  490. utils/__init__.py +30 -0
  491. utils/agent.py +3627 -0
  492. utils/aop.py +2948 -0
  493. utils/canonical.py +143 -0
  494. utils/conversation.py +1195 -0
  495. utils/doctrine_versioning +230 -0
  496. utils/formatter.py +474 -0
  497. utils/ledger.py +311 -0
  498. utils/out_types.py +16 -0
  499. utils/rollback.py +339 -0
  500. utils/router.py +929 -0
  501. utils/tui.py +1908 -0
@@ -0,0 +1,764 @@
1
+ import * as Dialog from '@radix-ui/react-dialog';
2
+ import { useState, useEffect } from 'react';
3
+ import { toast } from 'react-toastify';
4
+ import { motion } from 'framer-motion';
5
+ import { classNames } from '~/utils/classNames';
6
+ import { getLocalStorage } from '~/lib/persistence/localStorage';
7
+ import type { GitLabUserResponse, GitLabProjectInfo } from '~/types/GitLab';
8
+ import { logStore } from '~/lib/stores/logs';
9
+ import { chatId } from '~/lib/persistence/useChatHistory';
10
+ import { useStore } from '@nanostores/react';
11
+ import { GitLabApiService } from '~/lib/services/gitlabApiService';
12
+ import { SearchInput, EmptyState, StatusIndicator, Badge } from '~/components/ui';
13
+ import { formatSize } from '~/utils/formatSize';
14
+ import { GitLabAuthDialog } from '~/components/@settings/tabs/gitlab/components/GitLabAuthDialog';
15
+
16
+ interface GitLabDeploymentDialogProps {
17
+ isOpen: boolean;
18
+ onClose: () => void;
19
+ projectName: string;
20
+ files: Record<string, string>;
21
+ }
22
+
23
+ export function GitLabDeploymentDialog({ isOpen, onClose, projectName, files }: GitLabDeploymentDialogProps) {
24
+ const [repoName, setRepoName] = useState('');
25
+ const [isPrivate, setIsPrivate] = useState(false);
26
+ const [isLoading, setIsLoading] = useState(false);
27
+ const [user, setUser] = useState<GitLabUserResponse | null>(null);
28
+ const [recentRepos, setRecentRepos] = useState<GitLabProjectInfo[]>([]);
29
+ const [filteredRepos, setFilteredRepos] = useState<GitLabProjectInfo[]>([]);
30
+ const [repoSearchQuery, setRepoSearchQuery] = useState('');
31
+ const [isFetchingRepos, setIsFetchingRepos] = useState(false);
32
+ const [showSuccessDialog, setShowSuccessDialog] = useState(false);
33
+ const [createdRepoUrl, setCreatedRepoUrl] = useState('');
34
+ const [pushedFiles, setPushedFiles] = useState<{ path: string; size: number }[]>([]);
35
+ const [showAuthDialog, setShowAuthDialog] = useState(false);
36
+ const currentChatId = useStore(chatId);
37
+
38
+ // Load GitLab connection on mount
39
+ useEffect(() => {
40
+ if (isOpen) {
41
+ const connection = getLocalStorage('gitlab_connection');
42
+
43
+ // Set a default repository name based on the project name
44
+ setRepoName(projectName.replace(/\s+/g, '-').toLowerCase());
45
+
46
+ if (connection?.user && connection?.token) {
47
+ setUser(connection.user);
48
+
49
+ // Only fetch if we have both user and token
50
+ if (connection.token.trim()) {
51
+ fetchRecentRepos(connection.token, connection.gitlabUrl || 'https://gitlab.com');
52
+ }
53
+ }
54
+ }
55
+ }, [isOpen, projectName]);
56
+
57
+ // Filter repositories based on search query
58
+ useEffect(() => {
59
+ if (recentRepos.length === 0) {
60
+ setFilteredRepos([]);
61
+ return;
62
+ }
63
+
64
+ if (!repoSearchQuery.trim()) {
65
+ setFilteredRepos(recentRepos);
66
+ return;
67
+ }
68
+
69
+ const query = repoSearchQuery.toLowerCase().trim();
70
+ const filtered = recentRepos.filter(
71
+ (repo) =>
72
+ repo.name.toLowerCase().includes(query) || (repo.description && repo.description.toLowerCase().includes(query)),
73
+ );
74
+
75
+ setFilteredRepos(filtered);
76
+ }, [recentRepos, repoSearchQuery]);
77
+
78
+ const fetchRecentRepos = async (token: string, gitlabUrl = 'https://gitlab.com') => {
79
+ if (!token) {
80
+ logStore.logError('No GitLab token available');
81
+ toast.error('GitLab authentication required');
82
+
83
+ return;
84
+ }
85
+
86
+ try {
87
+ setIsFetchingRepos(true);
88
+
89
+ const apiService = new GitLabApiService(token, gitlabUrl);
90
+ const repos = await apiService.getProjects();
91
+ setRecentRepos(repos);
92
+ } catch (error) {
93
+ console.error('Failed to fetch GitLab repositories:', error);
94
+ logStore.logError('Failed to fetch GitLab repositories', { error });
95
+ toast.error('Failed to fetch recent repositories');
96
+ } finally {
97
+ setIsFetchingRepos(false);
98
+ }
99
+ };
100
+
101
+ // Function to create a new repository or push to an existing one
102
+ const handleSubmit = async (e: React.FormEvent) => {
103
+ e.preventDefault();
104
+
105
+ const connection = getLocalStorage('gitlab_connection');
106
+
107
+ if (!connection?.token || !connection?.user) {
108
+ toast.error('Please connect your GitLab account in Settings > Connections first');
109
+ return;
110
+ }
111
+
112
+ if (!repoName.trim()) {
113
+ toast.error('Repository name is required');
114
+ return;
115
+ }
116
+
117
+ setIsLoading(true);
118
+
119
+ // Sanitize repository name to match what the API will create
120
+ const sanitizedRepoName = repoName
121
+ .replace(/[^a-zA-Z0-9-_.]/g, '-')
122
+ .replace(/-+/g, '-')
123
+ .replace(/^-|-$/g, '')
124
+ .toLowerCase();
125
+
126
+ try {
127
+ const gitlabUrl = connection.gitlabUrl || 'https://gitlab.com';
128
+ const apiService = new GitLabApiService(connection.token, gitlabUrl);
129
+
130
+ // Warn user if repository name was changed
131
+ if (sanitizedRepoName !== repoName && sanitizedRepoName !== repoName.toLowerCase()) {
132
+ toast.info(`Repository name sanitized to "${sanitizedRepoName}" to meet GitLab requirements`);
133
+ }
134
+
135
+ // Check if project exists using the sanitized name
136
+ const projectPath = `${connection.user.username}/${sanitizedRepoName}`;
137
+ const existingProject = await apiService.getProjectByPath(projectPath);
138
+ const projectExists = existingProject !== null;
139
+
140
+ if (projectExists && existingProject) {
141
+ // Confirm overwrite
142
+ const visibilityChange =
143
+ existingProject.visibility !== (isPrivate ? 'private' : 'public')
144
+ ? `\n\nThis will also change the repository from ${existingProject.visibility} to ${isPrivate ? 'private' : 'public'}.`
145
+ : '';
146
+
147
+ const confirmOverwrite = window.confirm(
148
+ `Repository "${sanitizedRepoName}" already exists. Do you want to update it? This will add or modify files in the repository.${visibilityChange}`,
149
+ );
150
+
151
+ if (!confirmOverwrite) {
152
+ setIsLoading(false);
153
+ return;
154
+ }
155
+
156
+ // Update visibility if needed
157
+ if (existingProject.visibility !== (isPrivate ? 'private' : 'public')) {
158
+ toast.info('Updating repository visibility...');
159
+ await apiService.updateProjectVisibility(existingProject.id, isPrivate ? 'private' : 'public');
160
+ }
161
+
162
+ // Update project with files
163
+ toast.info('Uploading files to existing repository...');
164
+ await apiService.updateProjectWithFiles(existingProject.id, files);
165
+ setCreatedRepoUrl(existingProject.http_url_to_repo);
166
+ toast.success('Repository updated successfully!');
167
+ } else {
168
+ // Create new project with files
169
+ toast.info('Creating new repository...');
170
+
171
+ const newProject = await apiService.createProjectWithFiles(sanitizedRepoName, isPrivate, files);
172
+ setCreatedRepoUrl(newProject.http_url_to_repo);
173
+ toast.success('Repository created successfully!');
174
+ }
175
+
176
+ // Set pushed files for display
177
+ const fileList = Object.entries(files).map(([filePath, content]) => ({
178
+ path: filePath,
179
+ size: new TextEncoder().encode(content).length,
180
+ }));
181
+
182
+ setPushedFiles(fileList);
183
+ setShowSuccessDialog(true);
184
+
185
+ // Save repository info
186
+ localStorage.setItem(
187
+ `gitlab-repo-${currentChatId}`,
188
+ JSON.stringify({
189
+ owner: connection.user.username,
190
+ name: sanitizedRepoName,
191
+ url: createdRepoUrl,
192
+ }),
193
+ );
194
+
195
+ logStore.logInfo('GitLab deployment completed successfully', {
196
+ type: 'system',
197
+ message: `Successfully deployed ${fileList.length} files to ${projectExists ? 'existing' : 'new'} GitLab repository: ${projectPath}`,
198
+ repoName: sanitizedRepoName,
199
+ projectPath,
200
+ filesCount: fileList.length,
201
+ isNewProject: !projectExists,
202
+ });
203
+ } catch (error) {
204
+ console.error('Error pushing to GitLab:', error);
205
+
206
+ logStore.logError('GitLab deployment failed', {
207
+ error,
208
+ repoName: sanitizedRepoName,
209
+ projectPath: `${connection.user.username}/${sanitizedRepoName}`,
210
+ });
211
+
212
+ // Provide specific error messages based on error type
213
+ let errorMessage = 'Failed to push to GitLab';
214
+
215
+ if (error instanceof Error) {
216
+ const errorMsg = error.message.toLowerCase();
217
+
218
+ if (errorMsg.includes('404') || errorMsg.includes('not found')) {
219
+ errorMessage =
220
+ 'Repository or GitLab instance not found. Please check your GitLab URL and repository permissions.';
221
+ } else if (errorMsg.includes('401') || errorMsg.includes('unauthorized')) {
222
+ errorMessage = 'GitLab authentication failed. Please check your access token and permissions.';
223
+ } else if (errorMsg.includes('403') || errorMsg.includes('forbidden')) {
224
+ errorMessage =
225
+ 'Access denied. Your GitLab token may not have sufficient permissions to create/modify repositories.';
226
+ } else if (errorMsg.includes('network') || errorMsg.includes('fetch')) {
227
+ errorMessage = 'Network error. Please check your internet connection and try again.';
228
+ } else if (errorMsg.includes('timeout')) {
229
+ errorMessage = 'Request timed out. Please try again or check your connection.';
230
+ } else if (errorMsg.includes('rate limit')) {
231
+ errorMessage = 'GitLab API rate limit exceeded. Please wait a moment and try again.';
232
+ } else {
233
+ errorMessage = `GitLab error: ${error.message}`;
234
+ }
235
+ }
236
+
237
+ toast.error(errorMessage);
238
+ } finally {
239
+ setIsLoading(false);
240
+ }
241
+ };
242
+
243
+ const handleClose = () => {
244
+ setRepoName('');
245
+ setIsPrivate(false);
246
+ setShowSuccessDialog(false);
247
+ setCreatedRepoUrl('');
248
+ onClose();
249
+ };
250
+
251
+ const handleAuthDialogClose = () => {
252
+ setShowAuthDialog(false);
253
+
254
+ // Refresh user data after auth
255
+ const connection = getLocalStorage('gitlab_connection');
256
+
257
+ if (connection?.user && connection?.token) {
258
+ setUser(connection.user);
259
+ fetchRecentRepos(connection.token, connection.gitlabUrl || 'https://gitlab.com');
260
+ }
261
+ };
262
+
263
+ // Success Dialog
264
+ if (showSuccessDialog) {
265
+ return (
266
+ <Dialog.Root open={isOpen} onOpenChange={(open) => !open && handleClose()}>
267
+ <Dialog.Portal>
268
+ <Dialog.Overlay className="fixed inset-0 bg-black/50 backdrop-blur-sm z-[9999]" />
269
+ <div className="fixed inset-0 flex items-center justify-center z-[9999]">
270
+ <motion.div
271
+ initial={{ opacity: 0, scale: 0.95 }}
272
+ animate={{ opacity: 1, scale: 1 }}
273
+ exit={{ opacity: 0, scale: 0.95 }}
274
+ transition={{ duration: 0.2 }}
275
+ className="w-[90vw] md:w-[600px] max-h-[85vh] overflow-y-auto"
276
+ >
277
+ <Dialog.Content
278
+ className="bg-white dark:bg-bolt-elements-background-depth-1 rounded-lg border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark shadow-xl"
279
+ aria-describedby="success-dialog-description"
280
+ >
281
+ <Dialog.Title className="sr-only">Successfully pushed to GitLab</Dialog.Title>
282
+ <div className="p-6 space-y-4">
283
+ <div className="flex items-center justify-between">
284
+ <div className="flex items-center gap-3">
285
+ <div className="w-10 h-10 rounded-xl bg-green-500/10 flex items-center justify-center text-green-500">
286
+ <div className="i-ph:check-circle w-5 h-5" />
287
+ </div>
288
+ <div>
289
+ <h3 className="text-lg font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark">
290
+ Successfully pushed to GitLab
291
+ </h3>
292
+ <p
293
+ id="success-dialog-description"
294
+ className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark"
295
+ >
296
+ Your code is now available on GitLab
297
+ </p>
298
+ </div>
299
+ </div>
300
+ <Dialog.Close asChild>
301
+ <button
302
+ onClick={handleClose}
303
+ className="p-2 rounded-lg transition-all duration-200 ease-in-out bg-transparent text-bolt-elements-textTertiary hover:text-bolt-elements-textPrimary dark:text-bolt-elements-textTertiary-dark dark:hover:text-bolt-elements-textPrimary-dark hover:bg-bolt-elements-background-depth-2 dark:hover:bg-bolt-elements-background-depth-3 focus:outline-none focus:ring-2 focus:ring-bolt-elements-borderColor dark:focus:ring-bolt-elements-borderColor-dark"
304
+ >
305
+ <span className="i-ph:x block w-5 h-5" aria-hidden="true" />
306
+ <span className="sr-only">Close dialog</span>
307
+ </button>
308
+ </Dialog.Close>
309
+ </div>
310
+
311
+ <div className="bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 rounded-lg p-4 text-left border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark">
312
+ <p className="text-sm font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark mb-2 flex items-center gap-2">
313
+ <span className="i-ph:gitlab-logo w-4 h-4 text-orange-500" />
314
+ Repository URL
315
+ </p>
316
+ <div className="flex items-center gap-2">
317
+ <code className="flex-1 text-sm bg-bolt-elements-background-depth-1 dark:bg-bolt-elements-background-depth-4 px-3 py-2 rounded border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark font-mono">
318
+ {createdRepoUrl}
319
+ </code>
320
+ <motion.button
321
+ onClick={() => {
322
+ navigator.clipboard.writeText(createdRepoUrl);
323
+ toast.success('URL copied to clipboard');
324
+ }}
325
+ className="p-2 text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary dark:text-bolt-elements-textSecondary-dark dark:hover:text-bolt-elements-textPrimary-dark bg-bolt-elements-background-depth-1 dark:bg-bolt-elements-background-depth-4 rounded-lg border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark"
326
+ whileHover={{ scale: 1.05 }}
327
+ whileTap={{ scale: 0.95 }}
328
+ >
329
+ <div className="i-ph:copy w-4 h-4" />
330
+ </motion.button>
331
+ </div>
332
+ </div>
333
+
334
+ <div className="bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 rounded-lg p-4 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark">
335
+ <p className="text-sm font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark mb-2 flex items-center gap-2">
336
+ <span className="i-ph:files w-4 h-4 text-purple-500" />
337
+ Pushed Files ({pushedFiles.length})
338
+ </p>
339
+ <div className="max-h-[200px] overflow-y-auto custom-scrollbar pr-2">
340
+ {pushedFiles.slice(0, 100).map((file) => (
341
+ <div
342
+ key={file.path}
343
+ className="flex items-center justify-between py-1.5 text-sm text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark border-b border-bolt-elements-borderColor/30 dark:border-bolt-elements-borderColor-dark/30 last:border-0"
344
+ >
345
+ <span className="font-mono truncate flex-1 text-xs">{file.path}</span>
346
+ <span className="text-xs px-2 py-0.5 rounded-full bg-bolt-elements-background-depth-3 dark:bg-bolt-elements-background-depth-4 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark ml-2">
347
+ {formatSize(file.size)}
348
+ </span>
349
+ </div>
350
+ ))}
351
+ {pushedFiles.length > 100 && (
352
+ <div className="py-2 text-center text-xs text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark">
353
+ +{pushedFiles.length - 100} more files
354
+ </div>
355
+ )}
356
+ </div>
357
+ </div>
358
+
359
+ <div className="flex justify-end gap-2 pt-2">
360
+ <motion.a
361
+ href={createdRepoUrl}
362
+ target="_blank"
363
+ rel="noopener noreferrer"
364
+ className="px-4 py-2 rounded-lg bg-orange-500 text-white hover:bg-orange-600 text-sm inline-flex items-center gap-2"
365
+ whileHover={{ scale: 1.02 }}
366
+ whileTap={{ scale: 0.98 }}
367
+ >
368
+ <div className="i-ph:gitlab-logo w-4 h-4" />
369
+ View Repository
370
+ </motion.a>
371
+ <motion.button
372
+ onClick={() => {
373
+ navigator.clipboard.writeText(createdRepoUrl);
374
+ toast.success('URL copied to clipboard');
375
+ }}
376
+ className="px-4 py-2 rounded-lg bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark hover:bg-bolt-elements-background-depth-3 dark:hover:bg-bolt-elements-background-depth-4 text-sm inline-flex items-center gap-2 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark"
377
+ whileHover={{ scale: 1.02 }}
378
+ whileTap={{ scale: 0.98 }}
379
+ >
380
+ <div className="i-ph:copy w-4 h-4" />
381
+ Copy URL
382
+ </motion.button>
383
+ <motion.button
384
+ onClick={handleClose}
385
+ className="px-4 py-2 rounded-lg bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark hover:bg-bolt-elements-background-depth-3 dark:hover:bg-bolt-elements-background-depth-4 text-sm border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark"
386
+ whileHover={{ scale: 1.02 }}
387
+ whileTap={{ scale: 0.98 }}
388
+ >
389
+ Close
390
+ </motion.button>
391
+ </div>
392
+ </div>
393
+ </Dialog.Content>
394
+ </motion.div>
395
+ </div>
396
+ </Dialog.Portal>
397
+ </Dialog.Root>
398
+ );
399
+ }
400
+
401
+ if (!user) {
402
+ return (
403
+ <Dialog.Root open={isOpen} onOpenChange={(open) => !open && handleClose()}>
404
+ <Dialog.Portal>
405
+ <Dialog.Overlay className="fixed inset-0 bg-black/50 backdrop-blur-sm z-[9999]" />
406
+ <div className="fixed inset-0 flex items-center justify-center z-[9999]">
407
+ <motion.div
408
+ initial={{ opacity: 0, scale: 0.95 }}
409
+ animate={{ opacity: 1, scale: 1 }}
410
+ exit={{ opacity: 0, scale: 0.95 }}
411
+ transition={{ duration: 0.2 }}
412
+ className="w-[90vw] md:w-[500px]"
413
+ >
414
+ <Dialog.Content
415
+ className="bg-white dark:bg-bolt-elements-background-depth-1 rounded-lg p-6 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark shadow-xl"
416
+ aria-describedby="connection-required-description"
417
+ >
418
+ <Dialog.Title className="sr-only">GitLab Connection Required</Dialog.Title>
419
+ <div className="relative text-center space-y-4">
420
+ <Dialog.Close asChild>
421
+ <button
422
+ onClick={handleClose}
423
+ className="absolute right-0 top-0 p-2 rounded-lg transition-all duration-200 ease-in-out bg-transparent text-bolt-elements-textTertiary hover:text-bolt-elements-textPrimary dark:text-bolt-elements-textTertiary-dark dark:hover:text-bolt-elements-textPrimary-dark hover:bg-bolt-elements-background-depth-2 dark:hover:bg-bolt-elements-background-depth-3 focus:outline-none focus:ring-2 focus:ring-bolt-elements-borderColor dark:focus:ring-bolt-elements-borderColor-dark"
424
+ >
425
+ <span className="i-ph:x block w-5 h-5" aria-hidden="true" />
426
+ <span className="sr-only">Close dialog</span>
427
+ </button>
428
+ </Dialog.Close>
429
+ <motion.div
430
+ initial={{ scale: 0.8 }}
431
+ animate={{ scale: 1 }}
432
+ transition={{ delay: 0.1 }}
433
+ className="mx-auto w-16 h-16 rounded-xl bg-bolt-elements-background-depth-3 flex items-center justify-center text-orange-500"
434
+ >
435
+ <div className="i-ph:gitlab-logo w-8 h-8" />
436
+ </motion.div>
437
+ <h3 className="text-lg font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark">
438
+ GitLab Connection Required
439
+ </h3>
440
+ <p
441
+ id="connection-required-description"
442
+ className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark max-w-md mx-auto"
443
+ >
444
+ To deploy your code to GitLab, you need to connect your GitLab account first.
445
+ </p>
446
+ <div className="pt-2 flex justify-center gap-3">
447
+ <motion.button
448
+ className="px-4 py-2 rounded-lg bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark text-sm hover:bg-bolt-elements-background-depth-3 dark:hover:bg-bolt-elements-background-depth-4 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark"
449
+ whileHover={{ scale: 1.02 }}
450
+ whileTap={{ scale: 0.98 }}
451
+ onClick={handleClose}
452
+ >
453
+ Close
454
+ </motion.button>
455
+ <motion.button
456
+ onClick={() => setShowAuthDialog(true)}
457
+ className="px-4 py-2 rounded-lg bg-orange-500 text-white text-sm hover:bg-orange-600 inline-flex items-center gap-2"
458
+ whileHover={{ scale: 1.02 }}
459
+ whileTap={{ scale: 0.98 }}
460
+ >
461
+ <div className="i-ph:gitlab-logo w-4 h-4" />
462
+ Connect GitLab Account
463
+ </motion.button>
464
+ </div>
465
+ </div>
466
+ </Dialog.Content>
467
+ </motion.div>
468
+ </div>
469
+ </Dialog.Portal>
470
+
471
+ {/* GitLab Auth Dialog */}
472
+ <GitLabAuthDialog isOpen={showAuthDialog} onClose={handleAuthDialogClose} />
473
+ </Dialog.Root>
474
+ );
475
+ }
476
+
477
+ return (
478
+ <Dialog.Root open={isOpen} onOpenChange={(open) => !open && handleClose()}>
479
+ <Dialog.Portal>
480
+ <Dialog.Overlay className="fixed inset-0 bg-black/50 backdrop-blur-sm z-[9999]" />
481
+ <div className="fixed inset-0 flex items-center justify-center z-[9999]">
482
+ <motion.div
483
+ initial={{ opacity: 0, scale: 0.95 }}
484
+ animate={{ opacity: 1, scale: 1 }}
485
+ exit={{ opacity: 0, scale: 0.95 }}
486
+ transition={{ duration: 0.2 }}
487
+ className="w-[90vw] md:w-[500px]"
488
+ >
489
+ <Dialog.Content
490
+ className="bg-white dark:bg-bolt-elements-background-depth-1 rounded-lg border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark shadow-xl"
491
+ aria-describedby="push-dialog-description"
492
+ >
493
+ <div className="p-6">
494
+ <div className="flex items-center gap-4 mb-6">
495
+ <motion.div
496
+ initial={{ scale: 0.8 }}
497
+ animate={{ scale: 1 }}
498
+ transition={{ delay: 0.1 }}
499
+ className="w-10 h-10 rounded-xl bg-bolt-elements-background-depth-3 flex items-center justify-center text-orange-500"
500
+ >
501
+ <div className="i-ph:gitlab-logo w-5 h-5" />
502
+ </motion.div>
503
+ <div>
504
+ <Dialog.Title className="text-lg font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark">
505
+ Deploy to GitLab
506
+ </Dialog.Title>
507
+ <p
508
+ id="push-dialog-description"
509
+ className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark"
510
+ >
511
+ Deploy your code to a new or existing GitLab repository
512
+ </p>
513
+ </div>
514
+ <Dialog.Close asChild>
515
+ <button
516
+ onClick={handleClose}
517
+ className="ml-auto p-2 rounded-lg transition-all duration-200 ease-in-out bg-transparent text-bolt-elements-textTertiary hover:text-bolt-elements-textPrimary dark:text-bolt-elements-textTertiary-dark dark:hover:text-bolt-elements-textPrimary-dark hover:bg-bolt-elements-background-depth-2 dark:hover:bg-bolt-elements-background-depth-3 focus:outline-none focus:ring-2 focus:ring-bolt-elements-borderColor dark:focus:ring-bolt-elements-borderColor-dark"
518
+ >
519
+ <span className="i-ph:x block w-5 h-5" aria-hidden="true" />
520
+ <span className="sr-only">Close dialog</span>
521
+ </button>
522
+ </Dialog.Close>
523
+ </div>
524
+
525
+ <div className="flex items-center gap-3 mb-6 p-4 bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 rounded-lg border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark">
526
+ <div className="relative">
527
+ {user.avatar_url && user.avatar_url !== 'null' && user.avatar_url !== '' ? (
528
+ <img
529
+ src={user.avatar_url}
530
+ alt={user.username}
531
+ className="w-10 h-10 rounded-full object-cover"
532
+ crossOrigin="anonymous"
533
+ referrerPolicy="no-referrer"
534
+ onError={(e) => {
535
+ // Handle CORS/COEP errors by hiding the image and showing fallback
536
+ const target = e.target as HTMLImageElement;
537
+ target.style.display = 'none';
538
+
539
+ const fallback = target.parentElement?.querySelector('.avatar-fallback') as HTMLElement;
540
+
541
+ if (fallback) {
542
+ fallback.style.display = 'flex';
543
+ }
544
+ }}
545
+ onLoad={(e) => {
546
+ // Ensure fallback is hidden when image loads successfully
547
+ const target = e.target as HTMLImageElement;
548
+
549
+ const fallback = target.parentElement?.querySelector('.avatar-fallback') as HTMLElement;
550
+
551
+ if (fallback) {
552
+ fallback.style.display = 'none';
553
+ }
554
+ }}
555
+ />
556
+ ) : null}
557
+
558
+ <div
559
+ className="avatar-fallback w-10 h-10 rounded-full bg-bolt-elements-background-depth-4 flex items-center justify-center text-bolt-elements-textSecondary font-semibold text-sm"
560
+ style={{
561
+ display:
562
+ user.avatar_url && user.avatar_url !== 'null' && user.avatar_url !== '' ? 'none' : 'flex',
563
+ }}
564
+ >
565
+ {user.name ? (
566
+ user.name.charAt(0).toUpperCase()
567
+ ) : user.username ? (
568
+ user.username.charAt(0).toUpperCase()
569
+ ) : (
570
+ <div className="i-ph:user w-5 h-5" />
571
+ )}
572
+ </div>
573
+ <div className="absolute -bottom-1 -right-1 w-5 h-5 rounded-full bg-orange-500 flex items-center justify-center text-white">
574
+ <div className="i-ph:gitlab-logo w-3 h-3" />
575
+ </div>
576
+ </div>
577
+ <div>
578
+ <p className="text-sm font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark">
579
+ {user.name || user.username}
580
+ </p>
581
+ <p className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark">
582
+ @{user.username}
583
+ </p>
584
+ </div>
585
+ </div>
586
+
587
+ <form onSubmit={handleSubmit} className="space-y-4">
588
+ <div className="space-y-2">
589
+ <label
590
+ htmlFor="repoName"
591
+ className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark"
592
+ >
593
+ Repository Name
594
+ </label>
595
+ <div className="relative">
596
+ <div className="absolute left-3 top-1/2 -translate-y-1/2 text-bolt-elements-textTertiary dark:text-bolt-elements-textTertiary-dark">
597
+ <span className="i-ph:git-branch w-4 h-4" />
598
+ </div>
599
+ <input
600
+ id="repoName"
601
+ type="text"
602
+ value={repoName}
603
+ onChange={(e) => setRepoName(e.target.value)}
604
+ placeholder="my-awesome-project"
605
+ className="w-full pl-10 px-4 py-2 rounded-lg bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark placeholder-bolt-elements-textTertiary dark:placeholder-bolt-elements-textTertiary-dark focus:outline-none focus:ring-2 focus:ring-orange-500"
606
+ required
607
+ />
608
+ </div>
609
+ </div>
610
+
611
+ <div className="space-y-2">
612
+ <div className="flex items-center justify-between mb-2">
613
+ <label className="text-sm text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark">
614
+ Recent Repositories
615
+ </label>
616
+ <span className="text-xs text-bolt-elements-textTertiary dark:text-bolt-elements-textTertiary-dark">
617
+ {filteredRepos.length} of {recentRepos.length}
618
+ </span>
619
+ </div>
620
+
621
+ <div className="mb-2">
622
+ <SearchInput
623
+ placeholder="Search repositories..."
624
+ value={repoSearchQuery}
625
+ onChange={(e) => setRepoSearchQuery(e.target.value)}
626
+ onClear={() => setRepoSearchQuery('')}
627
+ className="bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark text-sm"
628
+ />
629
+ </div>
630
+
631
+ {recentRepos.length === 0 && !isFetchingRepos ? (
632
+ <EmptyState
633
+ icon="i-ph:gitlab-logo"
634
+ title="No repositories found"
635
+ description="We couldn't find any repositories in your GitLab account."
636
+ variant="compact"
637
+ />
638
+ ) : (
639
+ <div className="space-y-2 max-h-[200px] overflow-y-auto pr-2 custom-scrollbar">
640
+ {filteredRepos.length === 0 && repoSearchQuery.trim() !== '' ? (
641
+ <EmptyState
642
+ icon="i-ph:magnifying-glass"
643
+ title="No matching repositories"
644
+ description="Try a different search term"
645
+ variant="compact"
646
+ />
647
+ ) : (
648
+ filteredRepos.map((repo) => (
649
+ <motion.button
650
+ key={repo.id}
651
+ type="button"
652
+ onClick={() => setRepoName(repo.name)}
653
+ className="w-full p-3 text-left rounded-lg bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 hover:bg-bolt-elements-background-depth-3 dark:hover:bg-bolt-elements-background-depth-4 transition-colors group border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark hover:border-orange-500/30"
654
+ whileHover={{ scale: 1.01 }}
655
+ whileTap={{ scale: 0.99 }}
656
+ >
657
+ <div className="flex items-center justify-between">
658
+ <div className="flex items-center gap-2">
659
+ <div className="i-ph:git-branch w-4 h-4 text-orange-500" />
660
+ <span className="text-sm font-medium text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark group-hover:text-orange-500">
661
+ {repo.name}
662
+ </span>
663
+ </div>
664
+ {repo.visibility === 'private' && (
665
+ <Badge variant="primary" size="sm" icon="i-ph:lock w-3 h-3">
666
+ Private
667
+ </Badge>
668
+ )}
669
+ </div>
670
+ {repo.description && (
671
+ <p className="mt-1 text-xs text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark line-clamp-2">
672
+ {repo.description}
673
+ </p>
674
+ )}
675
+ <div className="mt-2 flex items-center gap-2 flex-wrap">
676
+ <Badge variant="subtle" size="sm" icon="i-ph:star w-3 h-3">
677
+ {repo.star_count.toLocaleString()}
678
+ </Badge>
679
+ <Badge variant="subtle" size="sm" icon="i-ph:git-fork w-3 h-3">
680
+ {repo.forks_count.toLocaleString()}
681
+ </Badge>
682
+ <Badge variant="subtle" size="sm" icon="i-ph:clock w-3 h-3">
683
+ {new Date(repo.updated_at).toLocaleDateString()}
684
+ </Badge>
685
+ </div>
686
+ </motion.button>
687
+ ))
688
+ )}
689
+ </div>
690
+ )}
691
+ </div>
692
+
693
+ {isFetchingRepos && (
694
+ <div className="flex items-center justify-center py-4">
695
+ <StatusIndicator status="loading" pulse={true} label="Loading repositories..." />
696
+ </div>
697
+ )}
698
+
699
+ <div className="p-3 bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 rounded-lg border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark">
700
+ <div className="flex items-center gap-2">
701
+ <input
702
+ type="checkbox"
703
+ id="private"
704
+ checked={isPrivate}
705
+ onChange={(e) => setIsPrivate(e.target.checked)}
706
+ className="rounded border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark text-orange-500 focus:ring-orange-500 dark:bg-bolt-elements-background-depth-3"
707
+ />
708
+ <label
709
+ htmlFor="private"
710
+ className="text-sm text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark"
711
+ >
712
+ Make repository private
713
+ </label>
714
+ </div>
715
+ <p className="text-xs text-bolt-elements-textTertiary dark:text-bolt-elements-textTertiary-dark mt-2 ml-6">
716
+ Private repositories are only visible to you and people you share them with
717
+ </p>
718
+ </div>
719
+
720
+ <div className="pt-4 flex gap-2">
721
+ <motion.button
722
+ type="button"
723
+ onClick={handleClose}
724
+ className="px-4 py-2 rounded-lg bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3 text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark hover:bg-bolt-elements-background-depth-3 dark:hover:bg-bolt-elements-background-depth-4 text-sm border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark"
725
+ whileHover={{ scale: 1.02 }}
726
+ whileTap={{ scale: 0.98 }}
727
+ >
728
+ Cancel
729
+ </motion.button>
730
+ <motion.button
731
+ type="submit"
732
+ disabled={isLoading}
733
+ className={classNames(
734
+ 'flex-1 px-4 py-2 bg-orange-500 text-white rounded-lg hover:bg-orange-600 text-sm inline-flex items-center justify-center gap-2',
735
+ isLoading ? 'opacity-50 cursor-not-allowed' : '',
736
+ )}
737
+ whileHover={!isLoading ? { scale: 1.02 } : {}}
738
+ whileTap={!isLoading ? { scale: 0.98 } : {}}
739
+ >
740
+ {isLoading ? (
741
+ <>
742
+ <div className="i-ph:spinner-gap animate-spin w-4 h-4" />
743
+ Deploying...
744
+ </>
745
+ ) : (
746
+ <>
747
+ <div className="i-ph:gitlab-logo w-4 h-4" />
748
+ Deploy to GitLab
749
+ </>
750
+ )}
751
+ </motion.button>
752
+ </div>
753
+ </form>
754
+ </div>
755
+ </Dialog.Content>
756
+ </motion.div>
757
+ </div>
758
+ </Dialog.Portal>
759
+
760
+ {/* GitLab Auth Dialog */}
761
+ <GitLabAuthDialog isOpen={showAuthDialog} onClose={handleAuthDialogClose} />
762
+ </Dialog.Root>
763
+ );
764
+ }