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,255 @@
1
+ import ignore from 'ignore';
2
+ import type { ProviderInfo } from '~/types/model';
3
+ import type { Template } from '~/types/template';
4
+ import { STARTER_TEMPLATES } from './constants';
5
+
6
+ const starterTemplateSelectionPrompt = (templates: Template[]) => `
7
+ You are an experienced developer who helps people choose the best starter template for their projects.
8
+ IMPORTANT: Vite is preferred
9
+ IMPORTANT: Only choose shadcn templates if the user explicitly asks for shadcn.
10
+
11
+ Available templates:
12
+ <template>
13
+ <name>blank</name>
14
+ <description>Empty starter for simple scripts and trivial tasks that don't require a full template setup</description>
15
+ <tags>basic, script</tags>
16
+ </template>
17
+ ${templates
18
+ .map(
19
+ (template) => `
20
+ <template>
21
+ <name>${template.name}</name>
22
+ <description>${template.description}</description>
23
+ ${template.tags ? `<tags>${template.tags.join(', ')}</tags>` : ''}
24
+ </template>
25
+ `,
26
+ )
27
+ .join('\n')}
28
+
29
+ Response Format:
30
+ <selection>
31
+ <templateName>{selected template name}</templateName>
32
+ <title>{a proper title for the project}</title>
33
+ </selection>
34
+
35
+ Examples:
36
+
37
+ <example>
38
+ User: I need to build a todo app
39
+ Response:
40
+ <selection>
41
+ <templateName>react-basic-starter</templateName>
42
+ <title>Simple React todo application</title>
43
+ </selection>
44
+ </example>
45
+
46
+ <example>
47
+ User: Write a script to generate numbers from 1 to 100
48
+ Response:
49
+ <selection>
50
+ <templateName>blank</templateName>
51
+ <title>script to generate numbers from 1 to 100</title>
52
+ </selection>
53
+ </example>
54
+
55
+ Instructions:
56
+ 1. For trivial tasks and simple scripts, always recommend the blank template
57
+ 2. For more complex projects, recommend templates from the provided list
58
+ 3. Follow the exact XML format
59
+ 4. Consider both technical requirements and tags
60
+ 5. If no perfect match exists, recommend the closest option
61
+
62
+ Important: Provide only the selection tags in your response, no additional text.
63
+ MOST IMPORTANT: YOU DONT HAVE TIME TO THINK JUST START RESPONDING BASED ON HUNCH
64
+ `;
65
+
66
+ const templates: Template[] = STARTER_TEMPLATES.filter((t) => !t.name.includes('shadcn'));
67
+
68
+ const parseSelectedTemplate = (llmOutput: string): { template: string; title: string } | null => {
69
+ try {
70
+ // Extract content between <templateName> tags
71
+ const templateNameMatch = llmOutput.match(/<templateName>(.*?)<\/templateName>/);
72
+ const titleMatch = llmOutput.match(/<title>(.*?)<\/title>/);
73
+
74
+ if (!templateNameMatch) {
75
+ return null;
76
+ }
77
+
78
+ return { template: templateNameMatch[1].trim(), title: titleMatch?.[1].trim() || 'Untitled Project' };
79
+ } catch (error) {
80
+ console.error('Error parsing template selection:', error);
81
+ return null;
82
+ }
83
+ };
84
+
85
+ export const selectStarterTemplate = async (options: { message: string; model: string; provider: ProviderInfo }) => {
86
+ const { message, model, provider } = options;
87
+ const requestBody = {
88
+ message,
89
+ model,
90
+ provider,
91
+ system: starterTemplateSelectionPrompt(templates),
92
+ };
93
+ const response = await fetch('/api/llmcall', {
94
+ method: 'POST',
95
+ body: JSON.stringify(requestBody),
96
+ });
97
+ const respJson: { text: string } = await response.json();
98
+ console.log(respJson);
99
+
100
+ const { text } = respJson;
101
+ const selectedTemplate = parseSelectedTemplate(text);
102
+
103
+ if (selectedTemplate) {
104
+ return selectedTemplate;
105
+ } else {
106
+ console.log('No template selected, using blank template');
107
+
108
+ return {
109
+ template: 'blank',
110
+ title: '',
111
+ };
112
+ }
113
+ };
114
+
115
+ const getGitHubRepoContent = async (repoName: string): Promise<{ name: string; path: string; content: string }[]> => {
116
+ try {
117
+ // Instead of directly fetching from GitHub, use our own API endpoint as a proxy
118
+ const response = await fetch(`/api/github-template?repo=${encodeURIComponent(repoName)}`);
119
+
120
+ if (!response.ok) {
121
+ throw new Error(`HTTP error! status: ${response.status}`);
122
+ }
123
+
124
+ // Our API will return the files in the format we need
125
+ const files = (await response.json()) as any;
126
+
127
+ return files;
128
+ } catch (error) {
129
+ console.error('Error fetching release contents:', error);
130
+ throw error;
131
+ }
132
+ };
133
+
134
+ export async function getTemplates(templateName: string, title?: string) {
135
+ const template = STARTER_TEMPLATES.find((t) => t.name == templateName);
136
+
137
+ if (!template) {
138
+ return null;
139
+ }
140
+
141
+ const githubRepo = template.githubRepo;
142
+ const files = await getGitHubRepoContent(githubRepo);
143
+
144
+ let filteredFiles = files;
145
+
146
+ /*
147
+ * ignoring common unwanted files
148
+ * exclude .git
149
+ */
150
+ filteredFiles = filteredFiles.filter((x) => x.path.startsWith('.git') == false);
151
+
152
+ /*
153
+ * exclude lock files
154
+ * WE NOW INCLUDE LOCK FILES FOR IMPROVED INSTALL TIMES
155
+ */
156
+ {
157
+ /*
158
+ *const comminLockFiles = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml'];
159
+ *filteredFiles = filteredFiles.filter((x) => comminLockFiles.includes(x.name) == false);
160
+ */
161
+ }
162
+
163
+ // exclude .bolt
164
+ filteredFiles = filteredFiles.filter((x) => x.path.startsWith('.bolt') == false);
165
+
166
+ // check for ignore file in .bolt folder
167
+ const templateIgnoreFile = files.find((x) => x.path.startsWith('.bolt') && x.name == 'ignore');
168
+
169
+ const filesToImport = {
170
+ files: filteredFiles,
171
+ ignoreFile: [] as typeof filteredFiles,
172
+ };
173
+
174
+ if (templateIgnoreFile) {
175
+ // redacting files specified in ignore file
176
+ const ignorepatterns = templateIgnoreFile.content.split('\n').map((x) => x.trim());
177
+ const ig = ignore().add(ignorepatterns);
178
+
179
+ // filteredFiles = filteredFiles.filter(x => !ig.ignores(x.path))
180
+ const ignoredFiles = filteredFiles.filter((x) => ig.ignores(x.path));
181
+
182
+ filesToImport.files = filteredFiles;
183
+ filesToImport.ignoreFile = ignoredFiles;
184
+ }
185
+
186
+ const assistantMessage = `
187
+ Bolt is initializing your project with the required files using the ${template.name} template.
188
+ <boltArtifact id="imported-files" title="${title || 'Create initial files'}" type="bundled">
189
+ ${filesToImport.files
190
+ .map(
191
+ (file) =>
192
+ `<boltAction type="file" filePath="${file.path}">
193
+ ${file.content}
194
+ </boltAction>`,
195
+ )
196
+ .join('\n')}
197
+ </boltArtifact>
198
+ `;
199
+ let userMessage = ``;
200
+ const templatePromptFile = files.filter((x) => x.path.startsWith('.bolt')).find((x) => x.name == 'prompt');
201
+
202
+ if (templatePromptFile) {
203
+ userMessage = `
204
+ TEMPLATE INSTRUCTIONS:
205
+ ${templatePromptFile.content}
206
+
207
+ ---
208
+ `;
209
+ }
210
+
211
+ if (filesToImport.ignoreFile.length > 0) {
212
+ userMessage =
213
+ userMessage +
214
+ `
215
+ STRICT FILE ACCESS RULES - READ CAREFULLY:
216
+
217
+ The following files are READ-ONLY and must never be modified:
218
+ ${filesToImport.ignoreFile.map((file) => `- ${file.path}`).join('\n')}
219
+
220
+ Permitted actions:
221
+ ✓ Import these files as dependencies
222
+ ✓ Read from these files
223
+ ✓ Reference these files
224
+
225
+ Strictly forbidden actions:
226
+ ❌ Modify any content within these files
227
+ ❌ Delete these files
228
+ ❌ Rename these files
229
+ ❌ Move these files
230
+ ❌ Create new versions of these files
231
+ ❌ Suggest changes to these files
232
+
233
+ Any attempt to modify these protected files will result in immediate termination of the operation.
234
+
235
+ If you need to make changes to functionality, create new files instead of modifying the protected ones listed above.
236
+ ---
237
+ `;
238
+ }
239
+
240
+ userMessage += `
241
+ ---
242
+ template import is done, and you can now use the imported files,
243
+ edit only the files that need to be changed, and you can create new files as needed.
244
+ NO NOT EDIT/WRITE ANY FILES THAT ALREADY EXIST IN THE PROJECT AND DOES NOT NEED TO BE MODIFIED
245
+ ---
246
+ Now that the Template is imported please continue with my original request
247
+
248
+ IMPORTANT: Dont Forget to install the dependencies before running the app by using \`npm install && npm run dev\`
249
+ `;
250
+
251
+ return {
252
+ assistantMessage,
253
+ userMessage,
254
+ };
255
+ }
@@ -0,0 +1,384 @@
1
+ import type { WebContainer, WebContainerProcess } from '@webcontainer/api';
2
+ import type { ITerminal } from '~/types/terminal';
3
+ import { withResolvers } from './promises';
4
+ import { atom } from 'nanostores';
5
+ import { expoUrlAtom } from '~/lib/stores/qrCodeStore';
6
+
7
+ export async function newShellProcess(webcontainer: WebContainer, terminal: ITerminal) {
8
+ const args: string[] = [];
9
+
10
+ // we spawn a JSH process with a fallback cols and rows in case the process is not attached yet to a visible terminal
11
+ const process = await webcontainer.spawn('/bin/jsh', ['--osc', ...args], {
12
+ terminal: {
13
+ cols: terminal.cols ?? 80,
14
+ rows: terminal.rows ?? 15,
15
+ },
16
+ });
17
+
18
+ const input = process.input.getWriter();
19
+ const output = process.output;
20
+
21
+ const jshReady = withResolvers<void>();
22
+
23
+ let isInteractive = false;
24
+ output.pipeTo(
25
+ new WritableStream({
26
+ write(data) {
27
+ if (!isInteractive) {
28
+ const [, osc] = data.match(/\x1b\]654;([^\x07]+)\x07/) || [];
29
+
30
+ if (osc === 'interactive') {
31
+ // wait until we see the interactive OSC
32
+ isInteractive = true;
33
+
34
+ jshReady.resolve();
35
+ }
36
+ }
37
+
38
+ terminal.write(data);
39
+
40
+ // Capture terminal output for debugging
41
+ try {
42
+ import('~/utils/debugLogger')
43
+ .then(({ captureTerminalLog }) => {
44
+ // Clean the data by removing ANSI escape sequences for logging
45
+ const cleanData = data.replace(/\x1b\[[0-9;]*[mG]/g, '').trim();
46
+
47
+ if (cleanData) {
48
+ captureTerminalLog(cleanData, 'output');
49
+ }
50
+ })
51
+ .catch(() => {
52
+ // Ignore if debug logger is not available
53
+ });
54
+ } catch {
55
+ // Ignore errors in debug logging
56
+ }
57
+ },
58
+ }),
59
+ );
60
+
61
+ terminal.onData((data) => {
62
+ // console.log('terminal onData', { data, isInteractive });
63
+
64
+ if (isInteractive) {
65
+ input.write(data);
66
+
67
+ // Capture terminal input for debugging
68
+ try {
69
+ import('~/utils/debugLogger')
70
+ .then(({ captureTerminalLog }) => {
71
+ // Clean the data and check if it's a command (not just cursor movement)
72
+ const cleanData = data.replace(/\x1b\[[0-9;]*[A-Z]/g, '').trim();
73
+
74
+ if (cleanData && cleanData !== '\r' && cleanData !== '\n') {
75
+ captureTerminalLog(cleanData, 'input');
76
+ }
77
+ })
78
+ .catch(() => {
79
+ // Ignore if debug logger is not available
80
+ });
81
+ } catch {
82
+ // Ignore errors in debug logging
83
+ }
84
+ }
85
+ });
86
+
87
+ await jshReady.promise;
88
+
89
+ return process;
90
+ }
91
+
92
+ export type ExecutionResult = { output: string; exitCode: number } | undefined;
93
+
94
+ export class BoltShell {
95
+ #initialized: (() => void) | undefined;
96
+ #readyPromise: Promise<void>;
97
+ #webcontainer: WebContainer | undefined;
98
+ #terminal: ITerminal | undefined;
99
+ #process: WebContainerProcess | undefined;
100
+ executionState = atom<
101
+ { sessionId: string; active: boolean; executionPrms?: Promise<any>; abort?: () => void } | undefined
102
+ >();
103
+ #outputStream: ReadableStreamDefaultReader<string> | undefined;
104
+ #shellInputStream: WritableStreamDefaultWriter<string> | undefined;
105
+
106
+ constructor() {
107
+ this.#readyPromise = new Promise((resolve) => {
108
+ this.#initialized = resolve;
109
+ });
110
+ }
111
+
112
+ ready() {
113
+ return this.#readyPromise;
114
+ }
115
+
116
+ async init(webcontainer: WebContainer, terminal: ITerminal) {
117
+ this.#webcontainer = webcontainer;
118
+ this.#terminal = terminal;
119
+
120
+ // Use all three streams from tee: one for terminal, one for command execution, one for Expo URL detection
121
+ const { process, commandStream, expoUrlStream } = await this.newBoltShellProcess(webcontainer, terminal);
122
+ this.#process = process;
123
+ this.#outputStream = commandStream.getReader();
124
+
125
+ // Start background Expo URL watcher immediately
126
+ this._watchExpoUrlInBackground(expoUrlStream);
127
+
128
+ await this.waitTillOscCode('interactive');
129
+ this.#initialized?.();
130
+ }
131
+
132
+ async newBoltShellProcess(webcontainer: WebContainer, terminal: ITerminal) {
133
+ const args: string[] = [];
134
+ const process = await webcontainer.spawn('/bin/jsh', ['--osc', ...args], {
135
+ terminal: {
136
+ cols: terminal.cols ?? 80,
137
+ rows: terminal.rows ?? 15,
138
+ },
139
+ });
140
+
141
+ const input = process.input.getWriter();
142
+ this.#shellInputStream = input;
143
+
144
+ // Tee the output so we can have three independent readers
145
+ const [streamA, streamB] = process.output.tee();
146
+ const [streamC, streamD] = streamB.tee();
147
+
148
+ const jshReady = withResolvers<void>();
149
+ let isInteractive = false;
150
+ streamA.pipeTo(
151
+ new WritableStream({
152
+ write(data) {
153
+ if (!isInteractive) {
154
+ const [, osc] = data.match(/\x1b\]654;([^\x07]+)\x07/) || [];
155
+
156
+ if (osc === 'interactive') {
157
+ isInteractive = true;
158
+ jshReady.resolve();
159
+ }
160
+ }
161
+
162
+ terminal.write(data);
163
+ },
164
+ }),
165
+ );
166
+
167
+ terminal.onData((data) => {
168
+ if (isInteractive) {
169
+ input.write(data);
170
+ }
171
+ });
172
+
173
+ await jshReady.promise;
174
+
175
+ // Return all streams for use in init
176
+ return { process, terminalStream: streamA, commandStream: streamC, expoUrlStream: streamD };
177
+ }
178
+
179
+ // Dedicated background watcher for Expo URL
180
+ private async _watchExpoUrlInBackground(stream: ReadableStream<string>) {
181
+ const reader = stream.getReader();
182
+ let buffer = '';
183
+ const expoUrlRegex = /(exp:\/\/[^\s]+)/;
184
+
185
+ while (true) {
186
+ const { value, done } = await reader.read();
187
+
188
+ if (done) {
189
+ break;
190
+ }
191
+
192
+ buffer += value || '';
193
+
194
+ const expoUrlMatch = buffer.match(expoUrlRegex);
195
+
196
+ if (expoUrlMatch) {
197
+ const cleanUrl = expoUrlMatch[1]
198
+ .replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')
199
+ .replace(/[^\x20-\x7E]+$/g, '');
200
+ expoUrlAtom.set(cleanUrl);
201
+ buffer = buffer.slice(buffer.indexOf(expoUrlMatch[1]) + expoUrlMatch[1].length);
202
+ }
203
+
204
+ if (buffer.length > 2048) {
205
+ buffer = buffer.slice(-2048);
206
+ }
207
+ }
208
+ }
209
+
210
+ get terminal() {
211
+ return this.#terminal;
212
+ }
213
+
214
+ get process() {
215
+ return this.#process;
216
+ }
217
+
218
+ async executeCommand(sessionId: string, command: string, abort?: () => void): Promise<ExecutionResult> {
219
+ if (!this.process || !this.terminal) {
220
+ return undefined;
221
+ }
222
+
223
+ const state = this.executionState.get();
224
+
225
+ if (state?.active && state.abort) {
226
+ state.abort();
227
+ }
228
+
229
+ /*
230
+ * interrupt the current execution
231
+ * this.#shellInputStream?.write('\x03');
232
+ */
233
+ this.terminal.input('\x03');
234
+ await this.waitTillOscCode('prompt');
235
+
236
+ if (state && state.executionPrms) {
237
+ await state.executionPrms;
238
+ }
239
+
240
+ //start a new execution
241
+ this.terminal.input(command.trim() + '\n');
242
+
243
+ //wait for the execution to finish
244
+ const executionPromise = this.getCurrentExecutionResult();
245
+ this.executionState.set({ sessionId, active: true, executionPrms: executionPromise, abort });
246
+
247
+ const resp = await executionPromise;
248
+ this.executionState.set({ sessionId, active: false });
249
+
250
+ if (resp) {
251
+ try {
252
+ resp.output = cleanTerminalOutput(resp.output);
253
+ } catch (error) {
254
+ console.log('failed to format terminal output', error);
255
+ }
256
+ }
257
+
258
+ return resp;
259
+ }
260
+
261
+ async getCurrentExecutionResult(): Promise<ExecutionResult> {
262
+ const { output, exitCode } = await this.waitTillOscCode('exit');
263
+ return { output, exitCode };
264
+ }
265
+
266
+ onQRCodeDetected?: (qrCode: string) => void;
267
+
268
+ async waitTillOscCode(waitCode: string) {
269
+ let fullOutput = '';
270
+ let exitCode: number = 0;
271
+ let buffer = ''; // <-- Add a buffer to accumulate output
272
+
273
+ if (!this.#outputStream) {
274
+ return { output: fullOutput, exitCode };
275
+ }
276
+
277
+ const tappedStream = this.#outputStream;
278
+
279
+ // Regex for Expo URL
280
+ const expoUrlRegex = /(exp:\/\/[^\s]+)/;
281
+
282
+ while (true) {
283
+ const { value, done } = await tappedStream.read();
284
+
285
+ if (done) {
286
+ break;
287
+ }
288
+
289
+ const text = value || '';
290
+ fullOutput += text;
291
+ buffer += text; // <-- Accumulate in buffer
292
+
293
+ // Extract Expo URL from buffer and set store
294
+ const expoUrlMatch = buffer.match(expoUrlRegex);
295
+
296
+ if (expoUrlMatch) {
297
+ // Remove any trailing ANSI escape codes or non-printable characters
298
+ const cleanUrl = expoUrlMatch[1]
299
+ .replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')
300
+ .replace(/[^\x20-\x7E]+$/g, '');
301
+ expoUrlAtom.set(cleanUrl);
302
+
303
+ // Remove everything up to and including the URL from the buffer to avoid duplicate matches
304
+ buffer = buffer.slice(buffer.indexOf(expoUrlMatch[1]) + expoUrlMatch[1].length);
305
+ }
306
+
307
+ // Check if command completion signal with exit code
308
+ const [, osc, , , code] = text.match(/\x1b\]654;([^\x07=]+)=?((-?\d+):(\d+))?\x07/) || [];
309
+
310
+ if (osc === 'exit') {
311
+ exitCode = parseInt(code, 10);
312
+ }
313
+
314
+ if (osc === waitCode) {
315
+ break;
316
+ }
317
+ }
318
+
319
+ return { output: fullOutput, exitCode };
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Cleans and formats terminal output while preserving structure and paths
325
+ * Handles ANSI, OSC, and various terminal control sequences
326
+ */
327
+ export function cleanTerminalOutput(input: string): string {
328
+ // Step 1: Remove OSC sequences (including those with parameters)
329
+ const removeOsc = input
330
+ .replace(/\x1b\](\d+;[^\x07\x1b]*|\d+[^\x07\x1b]*)\x07/g, '')
331
+ .replace(/\](\d+;[^\n]*|\d+[^\n]*)/g, '');
332
+
333
+ // Step 2: Remove ANSI escape sequences and color codes more thoroughly
334
+ const removeAnsi = removeOsc
335
+ // Remove all escape sequences with parameters
336
+ .replace(/\u001b\[[\?]?[0-9;]*[a-zA-Z]/g, '')
337
+ .replace(/\x1b\[[\?]?[0-9;]*[a-zA-Z]/g, '')
338
+ // Remove color codes
339
+ .replace(/\u001b\[[0-9;]*m/g, '')
340
+ .replace(/\x1b\[[0-9;]*m/g, '')
341
+ // Clean up any remaining escape characters
342
+ .replace(/\u001b/g, '')
343
+ .replace(/\x1b/g, '');
344
+
345
+ // Step 3: Clean up carriage returns and newlines
346
+ const cleanNewlines = removeAnsi
347
+ .replace(/\r\n/g, '\n')
348
+ .replace(/\r/g, '\n')
349
+ .replace(/\n{3,}/g, '\n\n');
350
+
351
+ // Step 4: Add newlines at key breakpoints while preserving paths
352
+ const formatOutput = cleanNewlines
353
+ // Preserve prompt line
354
+ .replace(/^([~\/][^\n❯]+)❯/m, '$1\n❯')
355
+ // Add newline before command output indicators
356
+ .replace(/(?<!^|\n)>/g, '\n>')
357
+ // Add newline before error keywords without breaking paths
358
+ .replace(/(?<!^|\n|\w)(error|failed|warning|Error|Failed|Warning):/g, '\n$1:')
359
+ // Add newline before 'at' in stack traces without breaking paths
360
+ .replace(/(?<!^|\n|\/)(at\s+(?!async|sync))/g, '\nat ')
361
+ // Ensure 'at async' stays on same line
362
+ .replace(/\bat\s+async/g, 'at async')
363
+ // Add newline before npm error indicators
364
+ .replace(/(?<!^|\n)(npm ERR!)/g, '\n$1');
365
+
366
+ // Step 5: Clean up whitespace while preserving intentional spacing
367
+ const cleanSpaces = formatOutput
368
+ .split('\n')
369
+ .map((line) => line.trim())
370
+ .filter((line) => line.length > 0)
371
+ .join('\n');
372
+
373
+ // Step 6: Final cleanup
374
+ return cleanSpaces
375
+ .replace(/\n{3,}/g, '\n\n') // Replace multiple newlines with double newlines
376
+ .replace(/:\s+/g, ': ') // Normalize spacing after colons
377
+ .replace(/\s{2,}/g, ' ') // Remove multiple spaces
378
+ .replace(/^\s+|\s+$/g, '') // Trim start and end
379
+ .replace(/\u0000/g, ''); // Remove null characters
380
+ }
381
+
382
+ export function newBoltShellProcess() {
383
+ return new BoltShell();
384
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Cleans webcontainer URLs from stack traces to show relative paths instead
3
+ */
4
+ export function cleanStackTrace(stackTrace: string): string {
5
+ // Function to clean a single URL
6
+ const cleanUrl = (url: string): string => {
7
+ const regex = /^https?:\/\/[^\/]+\.webcontainer-api\.io(\/.*)?$/;
8
+
9
+ if (!regex.test(url)) {
10
+ return url;
11
+ }
12
+
13
+ const pathRegex = /^https?:\/\/[^\/]+\.webcontainer-api\.io\/(.*?)$/;
14
+ const match = url.match(pathRegex);
15
+
16
+ return match?.[1] || '';
17
+ };
18
+
19
+ // Split the stack trace into lines and process each line
20
+ return stackTrace
21
+ .split('\n')
22
+ .map((line) => {
23
+ // Match any URL in the line that contains webcontainer-api.io
24
+ return line.replace(/(https?:\/\/[^\/]+\.webcontainer-api\.io\/[^\s\)]+)/g, (match) => cleanUrl(match));
25
+ })
26
+ .join('\n');
27
+ }
@@ -0,0 +1,23 @@
1
+ export function stripIndents(value: string): string;
2
+ export function stripIndents(strings: TemplateStringsArray, ...values: any[]): string;
3
+ export function stripIndents(arg0: string | TemplateStringsArray, ...values: any[]) {
4
+ if (typeof arg0 !== 'string') {
5
+ const processedString = arg0.reduce((acc, curr, i) => {
6
+ acc += curr + (values[i] ?? '');
7
+ return acc;
8
+ }, '');
9
+
10
+ return _stripIndents(processedString);
11
+ }
12
+
13
+ return _stripIndents(arg0);
14
+ }
15
+
16
+ function _stripIndents(value: string) {
17
+ return value
18
+ .split('\n')
19
+ .map((line) => line.trim())
20
+ .join('\n')
21
+ .trimStart()
22
+ .replace(/[\r\n]$/, '');
23
+ }
@@ -0,0 +1,11 @@
1
+ const reset = '\x1b[0m';
2
+
3
+ export const escapeCodes = {
4
+ reset,
5
+ clear: '\x1b[g',
6
+ red: '\x1b[1;31m',
7
+ };
8
+
9
+ export const coloredText = {
10
+ red: (text: string) => `${escapeCodes.red}${text}${reset}`,
11
+ };
@@ -0,0 +1,3 @@
1
+ export function unreachable(message: string): never {
2
+ throw new Error(`Unreachable: ${message}`);
3
+ }