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,683 @@
1
+ /**
2
+ * Execution Governor Service
3
+ *
4
+ * Manages mandate execution with concurrency control, priority queuing,
5
+ * rate limiting, and resource management.
6
+ */
7
+
8
+ import express from 'express';
9
+ import { WebSocketServer, WebSocket } from 'ws';
10
+ import cors from 'cors';
11
+ import { loadConfig, type GovernorConfig } from './config.js';
12
+ import { MandatePriorityQueue } from './priority-queue.js';
13
+ import { MetricsCollector } from './metrics.js';
14
+ import type {
15
+ Mandate,
16
+ QueuedMandate,
17
+ ActiveExecution,
18
+ Worker,
19
+ ExecutionStatus,
20
+ ExecutionEvent,
21
+ GovernorState,
22
+ } from './types.js';
23
+
24
+ const config = loadConfig();
25
+ const app = express();
26
+ app.use(cors());
27
+ app.use(express.json());
28
+
29
+ // State management
30
+ const mandateQueue = new MandatePriorityQueue();
31
+ const activeExecutions = new Map<string, ActiveExecution>();
32
+ const workers = new Map<string, Worker>();
33
+ const executionStatuses = new Map<string, ExecutionStatus>();
34
+ const metrics = new MetricsCollector();
35
+ const eventListeners = new Map<string, Set<WebSocket>>(); // mandate_id -> WebSocket clients
36
+ let globalBudgetUsed = 0;
37
+ let rateLimitWindow: { start: number; count: number } = { start: Date.now(), count: 0 };
38
+
39
+ // WebSocket server
40
+ const server = app.listen(config.port, () => {
41
+ console.log(`Execution Governor listening on port ${config.port}`);
42
+ });
43
+
44
+ const wss = new WebSocketServer({ server });
45
+
46
+ /**
47
+ * Calculate priority for a mandate.
48
+ */
49
+ function calculatePriority(mandate: Mandate): number {
50
+ let priority = config.defaultPriority;
51
+
52
+ // Higher priority for governance-required mandates
53
+ if (mandate.governance?.proposal_id) {
54
+ priority += 10;
55
+ }
56
+
57
+ // Higher priority for critical proposals
58
+ if (mandate.metadata?.priority === 'critical') {
59
+ priority += 30;
60
+ } else if (mandate.metadata?.priority === 'high') {
61
+ priority += 20;
62
+ } else if (mandate.metadata?.priority === 'medium') {
63
+ priority += 10;
64
+ }
65
+
66
+ // Lower priority for larger budgets (more expensive)
67
+ priority -= Math.min(20, mandate.budget.cost / 10);
68
+
69
+ // Higher priority for earlier mandates (FIFO within same priority)
70
+ // This is handled by queue ordering, not priority value
71
+
72
+ return Math.max(0, Math.min(100, priority));
73
+ }
74
+
75
+ /**
76
+ * Check if we can accept a new mandate (rate limiting).
77
+ */
78
+ function canAcceptMandate(): boolean {
79
+ const now = Date.now();
80
+ const windowMs = 60 * 1000; // 1 minute
81
+
82
+ // Reset window if expired
83
+ if (now - rateLimitWindow.start > windowMs) {
84
+ rateLimitWindow = { start: now, count: 0 };
85
+ }
86
+
87
+ // Check rate limit
88
+ if (rateLimitWindow.count >= config.maxMandatesPerMinute) {
89
+ return false;
90
+ }
91
+
92
+ // Check global budget
93
+ if (globalBudgetUsed >= config.globalBudgetLimit) {
94
+ return false;
95
+ }
96
+
97
+ return true;
98
+ }
99
+
100
+ /**
101
+ * Check if we have available execution slots.
102
+ */
103
+ function hasAvailableSlot(): boolean {
104
+ return activeExecutions.size < config.maxConcurrentExecutions;
105
+ }
106
+
107
+ /**
108
+ * Find available worker.
109
+ */
110
+ function findAvailableWorker(): Worker | undefined {
111
+ for (const worker of workers.values()) {
112
+ if (
113
+ worker.status === 'idle' &&
114
+ worker.capabilities.currentExecutions < worker.capabilities.maxConcurrent
115
+ ) {
116
+ return worker;
117
+ }
118
+ }
119
+ return undefined;
120
+ }
121
+
122
+ /**
123
+ * Process queue and dispatch mandates to available workers.
124
+ */
125
+ function processQueue(): void {
126
+ while (!mandateQueue.isEmpty() && hasAvailableSlot()) {
127
+ const queuedMandate = mandateQueue.peek();
128
+ if (!queuedMandate) {
129
+ break;
130
+ }
131
+
132
+ const worker = findAvailableWorker();
133
+ if (!worker) {
134
+ break;
135
+ }
136
+
137
+ // Dequeue mandate
138
+ const mandate = mandateQueue.dequeue();
139
+ if (!mandate) {
140
+ break;
141
+ }
142
+
143
+ // Mark worker as busy
144
+ worker.status = 'busy';
145
+ worker.currentMandateId = mandate.mandate.mandate_id;
146
+ worker.capabilities.currentExecutions++;
147
+
148
+ // Create active execution
149
+ const execution: ActiveExecution = {
150
+ mandateId: mandate.mandate.mandate_id,
151
+ workerId: worker.workerId,
152
+ startedAt: Date.now(),
153
+ estimatedCompletion: Date.now() + mandate.mandate.budget.time * 1000,
154
+ resourceUsage: {
155
+ cpu: config.resourceLimits.cpu / config.maxConcurrentExecutions,
156
+ memory: config.resourceLimits.memory / config.maxConcurrentExecutions,
157
+ },
158
+ };
159
+ activeExecutions.set(mandate.mandate.mandate_id, execution);
160
+
161
+ // Update status
162
+ const status: ExecutionStatus = {
163
+ mandateId: mandate.mandate.mandate_id,
164
+ status: 'executing',
165
+ workerId: worker.workerId,
166
+ progress: 0,
167
+ startedAt: execution.startedAt,
168
+ };
169
+ executionStatuses.set(mandate.mandate.mandate_id, status);
170
+
171
+ // Record metrics
172
+ metrics.recordStart(mandate.mandate.mandate_id, worker.workerId);
173
+
174
+ // Notify worker (via WebSocket or HTTP)
175
+ broadcastToWorker(worker.workerId, {
176
+ type: 'mandate_assigned',
177
+ mandate: mandate.mandate,
178
+ executionId: mandate.mandate.mandate_id,
179
+ });
180
+
181
+ console.log(
182
+ `Dispatched mandate ${mandate.mandate.mandate_id} to worker ${worker.workerId}`
183
+ );
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Broadcast message to a specific worker.
189
+ */
190
+ function broadcastToWorker(workerId: string, message: any): void {
191
+ // In a real implementation, this would use WebSocket or HTTP
192
+ // For now, workers will poll for mandates
193
+ console.log(`Broadcasting to worker ${workerId}:`, message);
194
+ }
195
+
196
+ /**
197
+ * Broadcast event to all listeners for a mandate.
198
+ */
199
+ function broadcastEvent(mandateId: string, event: ExecutionEvent): void {
200
+ const listeners = eventListeners.get(mandateId);
201
+ if (listeners) {
202
+ const message = JSON.stringify(event);
203
+ for (const ws of listeners) {
204
+ if (ws.readyState === WebSocket.OPEN) {
205
+ ws.send(message);
206
+ }
207
+ }
208
+ }
209
+ }
210
+
211
+ // ============================================================================
212
+ // HTTP API Endpoints
213
+ // ============================================================================
214
+
215
+ /**
216
+ * POST /mandates - Accept mandate from bolt.diy API
217
+ */
218
+ app.post('/mandates', (req: express.Request, res: express.Response) => {
219
+ try {
220
+ const mandate: Mandate = req.body;
221
+
222
+ // Validate mandate
223
+ if (!mandate.mandate_id || !mandate.objectives || !mandate.budget) {
224
+ return res.status(400).json({ error: 'Invalid mandate structure' });
225
+ }
226
+
227
+ // Check rate limiting
228
+ if (!canAcceptMandate()) {
229
+ return res.status(429).json({
230
+ error: 'Rate limit exceeded',
231
+ retryAfter: 60,
232
+ });
233
+ }
234
+
235
+ // Calculate priority
236
+ const priority = calculatePriority(mandate);
237
+
238
+ // Create queued mandate
239
+ const queuedMandate: QueuedMandate = {
240
+ mandate,
241
+ priority,
242
+ queuedAt: Date.now(),
243
+ retryCount: 0,
244
+ };
245
+
246
+ // Enqueue
247
+ mandateQueue.enqueue(queuedMandate);
248
+ rateLimitWindow.count++;
249
+
250
+ // Initialize status
251
+ const status: ExecutionStatus = {
252
+ mandateId: mandate.mandate_id,
253
+ status: 'queued',
254
+ queuePosition: mandateQueue.getPosition(mandate.mandate_id),
255
+ };
256
+ executionStatuses.set(mandate.mandate_id, status);
257
+
258
+ // Try to process queue
259
+ processQueue();
260
+
261
+ res.status(202).json({
262
+ success: true,
263
+ mandate_id: mandate.mandate_id,
264
+ status: 'queued',
265
+ queue_position: status.queuePosition,
266
+ estimated_wait_time: estimateWaitTime(),
267
+ });
268
+ } catch (error) {
269
+ console.error('Error accepting mandate:', error);
270
+ res.status(500).json({ error: 'Failed to accept mandate' });
271
+ }
272
+ });
273
+
274
+ /**
275
+ * GET /mandates/:id/status - Get mandate execution status
276
+ */
277
+ app.get('/mandates/:id/status', (req, res) => {
278
+ const status = executionStatuses.get(req.params.id);
279
+ if (!status) {
280
+ return res.status(404).json({ error: 'Mandate not found' });
281
+ }
282
+
283
+ // Update queue position if queued
284
+ if (status.status === 'queued') {
285
+ status.queuePosition = mandateQueue.getPosition(req.params.id);
286
+ }
287
+
288
+ res.json(status);
289
+ });
290
+
291
+ /**
292
+ * POST /workers/register - Register headless worker
293
+ */
294
+ app.post('/workers/register', (req, res) => {
295
+ try {
296
+ const { workerId, capabilities } = req.body;
297
+
298
+ if (!workerId) {
299
+ return res.status(400).json({ error: 'workerId is required' });
300
+ }
301
+
302
+ const worker: Worker = {
303
+ workerId,
304
+ registeredAt: Date.now(),
305
+ lastHeartbeat: Date.now(),
306
+ status: 'idle',
307
+ capabilities: {
308
+ maxConcurrent: capabilities?.maxConcurrent || 1,
309
+ currentExecutions: 0,
310
+ },
311
+ };
312
+
313
+ workers.set(workerId, worker);
314
+
315
+ console.log(`Worker ${workerId} registered`);
316
+
317
+ res.json({
318
+ success: true,
319
+ workerId,
320
+ message: 'Worker registered successfully',
321
+ });
322
+ } catch (error) {
323
+ console.error('Error registering worker:', error);
324
+ res.status(500).json({ error: 'Failed to register worker' });
325
+ }
326
+ });
327
+
328
+ /**
329
+ * POST /workers/:id/heartbeat - Worker heartbeat
330
+ */
331
+ app.post('/workers/:id/heartbeat', (req, res) => {
332
+ const worker = workers.get(req.params.id);
333
+ if (!worker) {
334
+ return res.status(404).json({ error: 'Worker not found' });
335
+ }
336
+
337
+ worker.lastHeartbeat = Date.now();
338
+ worker.status = req.body.status || worker.status;
339
+
340
+ res.json({ success: true });
341
+ });
342
+
343
+ /**
344
+ * POST /workers/:id/request-mandate - Worker requests next mandate
345
+ */
346
+ app.post('/workers/:id/request-mandate', (req, res) => {
347
+ const worker = workers.get(req.params.id);
348
+ if (!worker) {
349
+ return res.status(404).json({ error: 'Worker not found' });
350
+ }
351
+
352
+ // Check if worker is available
353
+ if (
354
+ worker.status !== 'idle' ||
355
+ worker.capabilities.currentExecutions >= worker.capabilities.maxConcurrent
356
+ ) {
357
+ return res.json({ mandate: null, message: 'Worker not available' });
358
+ }
359
+
360
+ // Process queue to dispatch mandates
361
+ processQueue();
362
+
363
+ // Check if this worker was assigned a mandate
364
+ if (worker.currentMandateId) {
365
+ const execution = activeExecutions.get(worker.currentMandateId);
366
+ if (execution) {
367
+ const status = executionStatuses.get(execution.mandateId);
368
+ // Get mandate from queue or active execution
369
+ // For now, return the mandate ID - worker should fetch full mandate
370
+ return res.json({
371
+ mandate_id: execution.mandateId,
372
+ execution_id: execution.mandateId,
373
+ });
374
+ }
375
+ }
376
+
377
+ res.json({ mandate: null, message: 'No mandate available' });
378
+ });
379
+
380
+ /**
381
+ * GET /mandates/:id - Get full mandate details
382
+ */
383
+ app.get('/mandates/:id', (req, res) => {
384
+ const status = executionStatuses.get(req.params.id);
385
+ if (!status) {
386
+ return res.status(404).json({ error: 'Mandate not found' });
387
+ }
388
+
389
+ // Find mandate in queue or active execution
390
+ const queued = mandateQueue.get(req.params.id);
391
+ if (queued) {
392
+ return res.json({ mandate: queued.mandate });
393
+ }
394
+
395
+ const execution = activeExecutions.get(req.params.id);
396
+ if (execution) {
397
+ // Mandate is being executed - we'd need to store it
398
+ // For now, return error
399
+ return res.status(404).json({ error: 'Mandate not available (in execution)' });
400
+ }
401
+
402
+ res.status(404).json({ error: 'Mandate not found' });
403
+ });
404
+
405
+ /**
406
+ * POST /workers/:id/report-progress - Worker reports execution progress
407
+ */
408
+ app.post('/workers/:id/report-progress', (req, res) => {
409
+ const worker = workers.get(req.params.id);
410
+ if (!worker) {
411
+ return res.status(404).json({ error: 'Worker not found' });
412
+ }
413
+
414
+ const { mandateId, event, progress, status: execStatus } = req.body;
415
+
416
+ if (!mandateId) {
417
+ return res.status(400).json({ error: 'mandateId is required' });
418
+ }
419
+
420
+ const execution = activeExecutions.get(mandateId);
421
+ if (!execution || execution.workerId !== req.params.id) {
422
+ return res.status(404).json({ error: 'Execution not found' });
423
+ }
424
+
425
+ // Update execution status
426
+ const status = executionStatuses.get(mandateId);
427
+ if (status) {
428
+ if (progress !== undefined) {
429
+ status.progress = progress;
430
+ }
431
+ if (execStatus) {
432
+ status.status = execStatus;
433
+ }
434
+ }
435
+
436
+ // Broadcast event if provided
437
+ if (event) {
438
+ const executionEvent: ExecutionEvent = {
439
+ mandate_id: mandateId,
440
+ iteration: event.iteration || 0,
441
+ type: event.type,
442
+ timestamp: event.timestamp || Date.now(),
443
+ data: event.data || {},
444
+ metadata: event.metadata || {},
445
+ };
446
+ broadcastEvent(mandateId, executionEvent);
447
+ }
448
+
449
+ res.json({ success: true });
450
+ });
451
+
452
+ /**
453
+ * POST /workers/:id/complete - Worker reports mandate completion
454
+ */
455
+ app.post('/workers/:id/complete', (req, res) => {
456
+ const worker = workers.get(req.params.id);
457
+ if (!worker) {
458
+ return res.status(404).json({ error: 'Worker not found' });
459
+ }
460
+
461
+ const { mandateId, success, result, error } = req.body;
462
+
463
+ if (!mandateId) {
464
+ return res.status(400).json({ error: 'mandateId is required' });
465
+ }
466
+
467
+ const execution = activeExecutions.get(mandateId);
468
+ if (!execution || execution.workerId !== req.params.id) {
469
+ return res.status(404).json({ error: 'Execution not found' });
470
+ }
471
+
472
+ // Calculate duration
473
+ const duration = Date.now() - execution.startedAt;
474
+
475
+ // Update status
476
+ const status = executionStatuses.get(mandateId);
477
+ if (status) {
478
+ status.status = success ? 'completed' : 'failed';
479
+ status.completedAt = Date.now();
480
+ status.result = result;
481
+ status.error = error;
482
+ }
483
+
484
+ // Record metrics
485
+ metrics.recordCompletion(mandateId, worker.workerId, duration, success);
486
+
487
+ // Update budget
488
+ if (result?.budget_summary?.cost_incurred) {
489
+ globalBudgetUsed += result.budget_summary.cost_incurred;
490
+ }
491
+
492
+ // Clean up
493
+ activeExecutions.delete(mandateId);
494
+ worker.status = 'idle';
495
+ worker.currentMandateId = undefined;
496
+ worker.capabilities.currentExecutions--;
497
+
498
+ // Broadcast completion event
499
+ const completionEvent: ExecutionEvent = {
500
+ mandate_id: mandateId,
501
+ iteration: 0,
502
+ type: success ? 'iteration_end' : 'error',
503
+ timestamp: Date.now(),
504
+ data: {
505
+ status: success ? 'success' : 'failed',
506
+ ...(error && { message: error }),
507
+ },
508
+ metadata: {},
509
+ };
510
+ broadcastEvent(mandateId, completionEvent);
511
+
512
+ // Process queue for next mandate
513
+ processQueue();
514
+
515
+ res.json({ success: true });
516
+
517
+ console.log(
518
+ `Mandate ${mandateId} ${success ? 'completed' : 'failed'} by worker ${worker.workerId} in ${duration}ms`
519
+ );
520
+ });
521
+
522
+ /**
523
+ * GET /governor/state - Get governor state
524
+ */
525
+ app.get('/governor/state', (req, res) => {
526
+ const healthyWorkers = Array.from(workers.values()).filter(
527
+ (w) => Date.now() - w.lastHeartbeat < config.workerHealthCheckInterval * 2
528
+ ).length;
529
+
530
+ const state: GovernorState = {
531
+ queueDepth: mandateQueue.size(),
532
+ activeExecutions: activeExecutions.size,
533
+ maxConcurrentExecutions: config.maxConcurrentExecutions,
534
+ registeredWorkers: workers.size,
535
+ healthyWorkers,
536
+ totalMandatesProcessed: metrics.getMetrics().totalMandatesProcessed,
537
+ totalMandatesFailed: metrics.getMetrics().totalMandatesFailed,
538
+ averageExecutionTime: metrics.getMetrics().averageExecutionTime,
539
+ currentBudgetUsage: globalBudgetUsed,
540
+ globalBudgetLimit: config.globalBudgetLimit,
541
+ };
542
+
543
+ res.json(state);
544
+ });
545
+
546
+ /**
547
+ * GET /governor/metrics - Get execution metrics
548
+ */
549
+ app.get('/governor/metrics', (req, res) => {
550
+ res.json(metrics.getMetrics());
551
+ });
552
+
553
+ /**
554
+ * Estimate wait time for a mandate in queue.
555
+ */
556
+ function estimateWaitTime(): number {
557
+ // Simple estimation: average execution time * queue position
558
+ const avgTime = metrics.getMetrics().averageExecutionTime || 60000; // 1 minute default
559
+ const queueDepth = mandateQueue.size();
560
+ const activeCount = activeExecutions.size;
561
+ const availableSlots = config.maxConcurrentExecutions - activeCount;
562
+
563
+ if (availableSlots > 0) {
564
+ return 0; // Can start immediately
565
+ }
566
+
567
+ // Estimate based on current executions completing
568
+ return Math.ceil((queueDepth / config.maxConcurrentExecutions) * avgTime);
569
+ }
570
+
571
+ // ============================================================================
572
+ // WebSocket Server
573
+ // ============================================================================
574
+
575
+ wss.on('connection', (ws: WebSocket, req) => {
576
+ console.log('WebSocket client connected');
577
+
578
+ ws.on('message', (message: string) => {
579
+ try {
580
+ const data = JSON.parse(message.toString());
581
+
582
+ if (data.type === 'subscribe') {
583
+ // Subscribe to events for a mandate
584
+ const mandateId = data.mandate_id;
585
+ if (mandateId) {
586
+ if (!eventListeners.has(mandateId)) {
587
+ eventListeners.set(mandateId, new Set());
588
+ }
589
+ eventListeners.get(mandateId)!.add(ws);
590
+ ws.send(JSON.stringify({ type: 'subscribed', mandate_id: mandateId }));
591
+ }
592
+ } else if (data.type === 'unsubscribe') {
593
+ // Unsubscribe from mandate events
594
+ const mandateId = data.mandate_id;
595
+ if (mandateId && eventListeners.has(mandateId)) {
596
+ eventListeners.get(mandateId)!.delete(ws);
597
+ }
598
+ }
599
+ } catch (error) {
600
+ console.error('Error handling WebSocket message:', error);
601
+ }
602
+ });
603
+
604
+ ws.on('close', () => {
605
+ // Remove from all event listeners
606
+ for (const listeners of eventListeners.values()) {
607
+ listeners.delete(ws);
608
+ }
609
+ console.log('WebSocket client disconnected');
610
+ });
611
+ });
612
+
613
+ // ============================================================================
614
+ // Worker Health Monitoring
615
+ // ============================================================================
616
+
617
+ setInterval(() => {
618
+ const now = Date.now();
619
+ for (const [workerId, worker] of workers.entries()) {
620
+ const timeSinceHeartbeat = now - worker.lastHeartbeat;
621
+ if (timeSinceHeartbeat > config.workerHealthCheckInterval * 2) {
622
+ console.warn(`Worker ${workerId} appears unhealthy (no heartbeat for ${timeSinceHeartbeat}ms)`);
623
+ worker.status = 'unhealthy';
624
+
625
+ // If worker has active execution, mark it for retry
626
+ if (worker.currentMandateId) {
627
+ const execution = activeExecutions.get(worker.currentMandateId);
628
+ if (execution) {
629
+ // Re-queue mandate for retry
630
+ const status = executionStatuses.get(execution.mandateId);
631
+ if (status && status.status === 'executing') {
632
+ // Find original mandate (would need to store it)
633
+ // For now, just mark execution as failed
634
+ status.status = 'failed';
635
+ status.error = 'Worker became unhealthy';
636
+ activeExecutions.delete(execution.mandateId);
637
+ worker.status = 'idle';
638
+ worker.currentMandateId = undefined;
639
+ worker.capabilities.currentExecutions--;
640
+ processQueue();
641
+ }
642
+ }
643
+ }
644
+ } else if (worker.status === 'unhealthy' && timeSinceHeartbeat < config.workerHealthCheckInterval) {
645
+ // Worker recovered
646
+ worker.status = 'idle';
647
+ console.log(`Worker ${workerId} recovered`);
648
+ }
649
+ }
650
+ }, config.workerHealthCheckInterval);
651
+
652
+ // ============================================================================
653
+ // Queue Processing
654
+ // ============================================================================
655
+
656
+ setInterval(() => {
657
+ processQueue();
658
+ }, config.queueCheckInterval);
659
+
660
+ // ============================================================================
661
+ // Graceful Shutdown
662
+ // ============================================================================
663
+
664
+ process.on('SIGTERM', () => {
665
+ console.log('SIGTERM received, shutting down gracefully');
666
+ wss.close(() => {
667
+ server.close(() => {
668
+ console.log('Execution Governor shut down');
669
+ process.exit(0);
670
+ });
671
+ });
672
+ });
673
+
674
+ process.on('SIGINT', () => {
675
+ console.log('SIGINT received, shutting down gracefully');
676
+ wss.close(() => {
677
+ server.close(() => {
678
+ console.log('Execution Governor shut down');
679
+ process.exit(0);
680
+ });
681
+ });
682
+ });
683
+