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.
- .github/ISSUE_TEMPLATE/bug_report.md +65 -0
- .github/ISSUE_TEMPLATE/feature_request.md +41 -0
- .github/PULL_REQUEST_TEMPLATE.md +20 -0
- .github/workflows/publish-manual.yml +61 -0
- .github/workflows/publish.yml +64 -0
- .gitignore +214 -0
- CRCA.py +4156 -0
- LICENSE +201 -0
- MANIFEST.in +43 -0
- PKG-INFO +5035 -0
- README.md +4959 -0
- __init__.py +17 -0
- branches/CRCA-Q.py +2728 -0
- branches/crca_cg/corposwarm.py +9065 -0
- branches/crca_cg/fix_rancher_docker_creds.ps1 +155 -0
- branches/crca_cg/package.json +5 -0
- branches/crca_cg/test_bolt_integration.py +446 -0
- branches/crca_cg/test_corposwarm_comprehensive.py +773 -0
- branches/crca_cg/test_new_features.py +163 -0
- branches/crca_sd/__init__.py +149 -0
- branches/crca_sd/crca_sd_core.py +770 -0
- branches/crca_sd/crca_sd_governance.py +1325 -0
- branches/crca_sd/crca_sd_mpc.py +1130 -0
- branches/crca_sd/crca_sd_realtime.py +1844 -0
- branches/crca_sd/crca_sd_tui.py +1133 -0
- crca-1.4.0.dist-info/METADATA +5035 -0
- crca-1.4.0.dist-info/RECORD +501 -0
- crca-1.4.0.dist-info/WHEEL +4 -0
- crca-1.4.0.dist-info/licenses/LICENSE +201 -0
- docs/CRCA-Q.md +2333 -0
- examples/config.yaml.example +25 -0
- examples/crca_sd_example.py +513 -0
- examples/data_broker_example.py +294 -0
- examples/logistics_corporation.py +861 -0
- examples/palantir_example.py +299 -0
- examples/policy_bench.py +934 -0
- examples/pridnestrovia-sd.py +705 -0
- examples/pridnestrovia_realtime.py +1902 -0
- prompts/__init__.py +10 -0
- prompts/default_crca.py +101 -0
- pyproject.toml +151 -0
- requirements.txt +76 -0
- schemas/__init__.py +43 -0
- schemas/mcpSchemas.py +51 -0
- schemas/policy.py +458 -0
- templates/__init__.py +38 -0
- templates/base_specialized_agent.py +195 -0
- templates/drift_detection.py +325 -0
- templates/examples/causal_agent_template.py +309 -0
- templates/examples/drag_drop_example.py +213 -0
- templates/examples/logistics_agent_template.py +207 -0
- templates/examples/trading_agent_template.py +206 -0
- templates/feature_mixins.py +253 -0
- templates/graph_management.py +442 -0
- templates/llm_integration.py +194 -0
- templates/module_registry.py +276 -0
- templates/mpc_planner.py +280 -0
- templates/policy_loop.py +1168 -0
- templates/prediction_framework.py +448 -0
- templates/statistical_methods.py +778 -0
- tests/sanity.yml +31 -0
- tests/sanity_check +406 -0
- tests/test_core.py +47 -0
- tests/test_crca_excel.py +166 -0
- tests/test_crca_sd.py +780 -0
- tests/test_data_broker.py +424 -0
- tests/test_palantir.py +349 -0
- tools/__init__.py +38 -0
- tools/actuators.py +437 -0
- tools/bolt.diy/Dockerfile +103 -0
- tools/bolt.diy/app/components/@settings/core/AvatarDropdown.tsx +175 -0
- tools/bolt.diy/app/components/@settings/core/ControlPanel.tsx +345 -0
- tools/bolt.diy/app/components/@settings/core/constants.tsx +108 -0
- tools/bolt.diy/app/components/@settings/core/types.ts +114 -0
- tools/bolt.diy/app/components/@settings/index.ts +12 -0
- tools/bolt.diy/app/components/@settings/shared/components/TabTile.tsx +151 -0
- tools/bolt.diy/app/components/@settings/shared/service-integration/ConnectionForm.tsx +193 -0
- tools/bolt.diy/app/components/@settings/shared/service-integration/ConnectionTestIndicator.tsx +60 -0
- tools/bolt.diy/app/components/@settings/shared/service-integration/ErrorState.tsx +102 -0
- tools/bolt.diy/app/components/@settings/shared/service-integration/LoadingState.tsx +94 -0
- tools/bolt.diy/app/components/@settings/shared/service-integration/ServiceHeader.tsx +72 -0
- tools/bolt.diy/app/components/@settings/shared/service-integration/index.ts +6 -0
- tools/bolt.diy/app/components/@settings/tabs/data/DataTab.tsx +721 -0
- tools/bolt.diy/app/components/@settings/tabs/data/DataVisualization.tsx +384 -0
- tools/bolt.diy/app/components/@settings/tabs/event-logs/EventLogsTab.tsx +1013 -0
- tools/bolt.diy/app/components/@settings/tabs/features/FeaturesTab.tsx +295 -0
- tools/bolt.diy/app/components/@settings/tabs/github/GitHubTab.tsx +281 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubAuthDialog.tsx +173 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubCacheManager.tsx +367 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubConnection.tsx +233 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubErrorBoundary.tsx +105 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubProgressiveLoader.tsx +266 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubRepositoryCard.tsx +121 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubRepositorySelector.tsx +312 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubStats.tsx +291 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/GitHubUserProfile.tsx +46 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/shared/GitHubStateIndicators.tsx +264 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/shared/RepositoryCard.tsx +361 -0
- tools/bolt.diy/app/components/@settings/tabs/github/components/shared/index.ts +11 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/GitLabTab.tsx +305 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/components/GitLabAuthDialog.tsx +186 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/components/GitLabConnection.tsx +253 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/components/GitLabRepositorySelector.tsx +358 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/components/RepositoryCard.tsx +79 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/components/RepositoryList.tsx +142 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/components/StatsDisplay.tsx +91 -0
- tools/bolt.diy/app/components/@settings/tabs/gitlab/components/index.ts +4 -0
- tools/bolt.diy/app/components/@settings/tabs/mcp/McpServerList.tsx +99 -0
- tools/bolt.diy/app/components/@settings/tabs/mcp/McpServerListItem.tsx +70 -0
- tools/bolt.diy/app/components/@settings/tabs/mcp/McpStatusBadge.tsx +37 -0
- tools/bolt.diy/app/components/@settings/tabs/mcp/McpTab.tsx +239 -0
- tools/bolt.diy/app/components/@settings/tabs/netlify/NetlifyTab.tsx +1393 -0
- tools/bolt.diy/app/components/@settings/tabs/netlify/components/NetlifyConnection.tsx +990 -0
- tools/bolt.diy/app/components/@settings/tabs/netlify/components/index.ts +1 -0
- tools/bolt.diy/app/components/@settings/tabs/notifications/NotificationsTab.tsx +300 -0
- tools/bolt.diy/app/components/@settings/tabs/profile/ProfileTab.tsx +181 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/cloud/CloudProvidersTab.tsx +308 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/ErrorBoundary.tsx +68 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/HealthStatusBadge.tsx +64 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/LoadingSkeleton.tsx +107 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/LocalProvidersTab.tsx +556 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/ModelCard.tsx +106 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/ProviderCard.tsx +120 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/SetupGuide.tsx +671 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/StatusDashboard.tsx +91 -0
- tools/bolt.diy/app/components/@settings/tabs/providers/local/types.ts +44 -0
- tools/bolt.diy/app/components/@settings/tabs/settings/SettingsTab.tsx +215 -0
- tools/bolt.diy/app/components/@settings/tabs/supabase/SupabaseTab.tsx +1089 -0
- tools/bolt.diy/app/components/@settings/tabs/vercel/VercelTab.tsx +909 -0
- tools/bolt.diy/app/components/@settings/tabs/vercel/components/VercelConnection.tsx +368 -0
- tools/bolt.diy/app/components/@settings/tabs/vercel/components/index.ts +1 -0
- tools/bolt.diy/app/components/@settings/utils/tab-helpers.ts +54 -0
- tools/bolt.diy/app/components/chat/APIKeyManager.tsx +169 -0
- tools/bolt.diy/app/components/chat/Artifact.tsx +296 -0
- tools/bolt.diy/app/components/chat/AssistantMessage.tsx +192 -0
- tools/bolt.diy/app/components/chat/BaseChat.module.scss +47 -0
- tools/bolt.diy/app/components/chat/BaseChat.tsx +522 -0
- tools/bolt.diy/app/components/chat/Chat.client.tsx +670 -0
- tools/bolt.diy/app/components/chat/ChatAlert.tsx +108 -0
- tools/bolt.diy/app/components/chat/ChatBox.tsx +334 -0
- tools/bolt.diy/app/components/chat/CodeBlock.module.scss +10 -0
- tools/bolt.diy/app/components/chat/CodeBlock.tsx +85 -0
- tools/bolt.diy/app/components/chat/DicussMode.tsx +17 -0
- tools/bolt.diy/app/components/chat/ExamplePrompts.tsx +37 -0
- tools/bolt.diy/app/components/chat/FilePreview.tsx +38 -0
- tools/bolt.diy/app/components/chat/GitCloneButton.tsx +327 -0
- tools/bolt.diy/app/components/chat/ImportFolderButton.tsx +141 -0
- tools/bolt.diy/app/components/chat/LLMApiAlert.tsx +109 -0
- tools/bolt.diy/app/components/chat/MCPTools.tsx +129 -0
- tools/bolt.diy/app/components/chat/Markdown.module.scss +171 -0
- tools/bolt.diy/app/components/chat/Markdown.spec.ts +48 -0
- tools/bolt.diy/app/components/chat/Markdown.tsx +252 -0
- tools/bolt.diy/app/components/chat/Messages.client.tsx +102 -0
- tools/bolt.diy/app/components/chat/ModelSelector.tsx +797 -0
- tools/bolt.diy/app/components/chat/NetlifyDeploymentLink.client.tsx +51 -0
- tools/bolt.diy/app/components/chat/ProgressCompilation.tsx +110 -0
- tools/bolt.diy/app/components/chat/ScreenshotStateManager.tsx +33 -0
- tools/bolt.diy/app/components/chat/SendButton.client.tsx +39 -0
- tools/bolt.diy/app/components/chat/SpeechRecognition.tsx +28 -0
- tools/bolt.diy/app/components/chat/StarterTemplates.tsx +38 -0
- tools/bolt.diy/app/components/chat/SupabaseAlert.tsx +199 -0
- tools/bolt.diy/app/components/chat/SupabaseConnection.tsx +339 -0
- tools/bolt.diy/app/components/chat/ThoughtBox.tsx +43 -0
- tools/bolt.diy/app/components/chat/ToolInvocations.tsx +409 -0
- tools/bolt.diy/app/components/chat/UserMessage.tsx +101 -0
- tools/bolt.diy/app/components/chat/VercelDeploymentLink.client.tsx +158 -0
- tools/bolt.diy/app/components/chat/chatExportAndImport/ExportChatButton.tsx +49 -0
- tools/bolt.diy/app/components/chat/chatExportAndImport/ImportButtons.tsx +96 -0
- tools/bolt.diy/app/components/deploy/DeployAlert.tsx +197 -0
- tools/bolt.diy/app/components/deploy/DeployButton.tsx +277 -0
- tools/bolt.diy/app/components/deploy/GitHubDeploy.client.tsx +171 -0
- tools/bolt.diy/app/components/deploy/GitHubDeploymentDialog.tsx +1041 -0
- tools/bolt.diy/app/components/deploy/GitLabDeploy.client.tsx +171 -0
- tools/bolt.diy/app/components/deploy/GitLabDeploymentDialog.tsx +764 -0
- tools/bolt.diy/app/components/deploy/NetlifyDeploy.client.tsx +246 -0
- tools/bolt.diy/app/components/deploy/VercelDeploy.client.tsx +235 -0
- tools/bolt.diy/app/components/editor/codemirror/BinaryContent.tsx +7 -0
- tools/bolt.diy/app/components/editor/codemirror/CodeMirrorEditor.tsx +555 -0
- tools/bolt.diy/app/components/editor/codemirror/EnvMasking.ts +80 -0
- tools/bolt.diy/app/components/editor/codemirror/cm-theme.ts +192 -0
- tools/bolt.diy/app/components/editor/codemirror/indent.ts +68 -0
- tools/bolt.diy/app/components/editor/codemirror/languages.ts +112 -0
- tools/bolt.diy/app/components/git/GitUrlImport.client.tsx +147 -0
- tools/bolt.diy/app/components/header/Header.tsx +42 -0
- tools/bolt.diy/app/components/header/HeaderActionButtons.client.tsx +54 -0
- tools/bolt.diy/app/components/mandate/MandateSubmission.tsx +167 -0
- tools/bolt.diy/app/components/observability/DeploymentStatus.tsx +168 -0
- tools/bolt.diy/app/components/observability/EventTimeline.tsx +119 -0
- tools/bolt.diy/app/components/observability/FileDiffViewer.tsx +121 -0
- tools/bolt.diy/app/components/observability/GovernanceStatus.tsx +197 -0
- tools/bolt.diy/app/components/observability/GovernorMetrics.tsx +246 -0
- tools/bolt.diy/app/components/observability/LogStream.tsx +244 -0
- tools/bolt.diy/app/components/observability/MandateDetails.tsx +201 -0
- tools/bolt.diy/app/components/observability/ObservabilityDashboard.tsx +200 -0
- tools/bolt.diy/app/components/sidebar/HistoryItem.tsx +187 -0
- tools/bolt.diy/app/components/sidebar/Menu.client.tsx +536 -0
- tools/bolt.diy/app/components/sidebar/date-binning.ts +59 -0
- tools/bolt.diy/app/components/txt +1 -0
- tools/bolt.diy/app/components/ui/BackgroundRays/index.tsx +18 -0
- tools/bolt.diy/app/components/ui/BackgroundRays/styles.module.scss +246 -0
- tools/bolt.diy/app/components/ui/Badge.tsx +53 -0
- tools/bolt.diy/app/components/ui/BranchSelector.tsx +270 -0
- tools/bolt.diy/app/components/ui/Breadcrumbs.tsx +101 -0
- tools/bolt.diy/app/components/ui/Button.tsx +46 -0
- tools/bolt.diy/app/components/ui/Card.tsx +55 -0
- tools/bolt.diy/app/components/ui/Checkbox.tsx +32 -0
- tools/bolt.diy/app/components/ui/CloseButton.tsx +49 -0
- tools/bolt.diy/app/components/ui/CodeBlock.tsx +103 -0
- tools/bolt.diy/app/components/ui/Collapsible.tsx +9 -0
- tools/bolt.diy/app/components/ui/ColorSchemeDialog.tsx +378 -0
- tools/bolt.diy/app/components/ui/Dialog.tsx +449 -0
- tools/bolt.diy/app/components/ui/Dropdown.tsx +63 -0
- tools/bolt.diy/app/components/ui/EmptyState.tsx +154 -0
- tools/bolt.diy/app/components/ui/FileIcon.tsx +346 -0
- tools/bolt.diy/app/components/ui/FilterChip.tsx +92 -0
- tools/bolt.diy/app/components/ui/GlowingEffect.tsx +192 -0
- tools/bolt.diy/app/components/ui/GradientCard.tsx +100 -0
- tools/bolt.diy/app/components/ui/IconButton.tsx +84 -0
- tools/bolt.diy/app/components/ui/Input.tsx +22 -0
- tools/bolt.diy/app/components/ui/Label.tsx +20 -0
- tools/bolt.diy/app/components/ui/LoadingDots.tsx +27 -0
- tools/bolt.diy/app/components/ui/LoadingOverlay.tsx +32 -0
- tools/bolt.diy/app/components/ui/PanelHeader.tsx +20 -0
- tools/bolt.diy/app/components/ui/PanelHeaderButton.tsx +36 -0
- tools/bolt.diy/app/components/ui/Popover.tsx +29 -0
- tools/bolt.diy/app/components/ui/Progress.tsx +22 -0
- tools/bolt.diy/app/components/ui/RepositoryStats.tsx +87 -0
- tools/bolt.diy/app/components/ui/ScrollArea.tsx +41 -0
- tools/bolt.diy/app/components/ui/SearchInput.tsx +80 -0
- tools/bolt.diy/app/components/ui/SearchResultItem.tsx +134 -0
- tools/bolt.diy/app/components/ui/Separator.tsx +22 -0
- tools/bolt.diy/app/components/ui/SettingsButton.tsx +35 -0
- tools/bolt.diy/app/components/ui/Slider.tsx +73 -0
- tools/bolt.diy/app/components/ui/StatusIndicator.tsx +90 -0
- tools/bolt.diy/app/components/ui/Switch.tsx +37 -0
- tools/bolt.diy/app/components/ui/Tabs.tsx +52 -0
- tools/bolt.diy/app/components/ui/TabsWithSlider.tsx +112 -0
- tools/bolt.diy/app/components/ui/ThemeSwitch.tsx +29 -0
- tools/bolt.diy/app/components/ui/Tooltip.tsx +122 -0
- tools/bolt.diy/app/components/ui/index.ts +38 -0
- tools/bolt.diy/app/components/ui/use-toast.ts +66 -0
- tools/bolt.diy/app/components/workbench/DiffView.tsx +796 -0
- tools/bolt.diy/app/components/workbench/EditorPanel.tsx +174 -0
- tools/bolt.diy/app/components/workbench/ExpoQrModal.tsx +55 -0
- tools/bolt.diy/app/components/workbench/FileBreadcrumb.tsx +150 -0
- tools/bolt.diy/app/components/workbench/FileTree.tsx +565 -0
- tools/bolt.diy/app/components/workbench/Inspector.tsx +126 -0
- tools/bolt.diy/app/components/workbench/InspectorPanel.tsx +146 -0
- tools/bolt.diy/app/components/workbench/LockManager.tsx +262 -0
- tools/bolt.diy/app/components/workbench/PortDropdown.tsx +91 -0
- tools/bolt.diy/app/components/workbench/Preview.tsx +1049 -0
- tools/bolt.diy/app/components/workbench/ScreenshotSelector.tsx +293 -0
- tools/bolt.diy/app/components/workbench/Search.tsx +257 -0
- tools/bolt.diy/app/components/workbench/Workbench.client.tsx +506 -0
- tools/bolt.diy/app/components/workbench/terminal/Terminal.tsx +131 -0
- tools/bolt.diy/app/components/workbench/terminal/TerminalManager.tsx +68 -0
- tools/bolt.diy/app/components/workbench/terminal/TerminalTabs.tsx +277 -0
- tools/bolt.diy/app/components/workbench/terminal/theme.ts +36 -0
- tools/bolt.diy/app/components/workflow/WorkflowPhase.tsx +109 -0
- tools/bolt.diy/app/components/workflow/WorkflowStatus.tsx +60 -0
- tools/bolt.diy/app/components/workflow/WorkflowTimeline.tsx +150 -0
- tools/bolt.diy/app/entry.client.tsx +7 -0
- tools/bolt.diy/app/entry.server.tsx +80 -0
- tools/bolt.diy/app/root.tsx +156 -0
- tools/bolt.diy/app/routes/_index.tsx +175 -0
- tools/bolt.diy/app/routes/api.bug-report.ts +254 -0
- tools/bolt.diy/app/routes/api.chat.ts +463 -0
- tools/bolt.diy/app/routes/api.check-env-key.ts +41 -0
- tools/bolt.diy/app/routes/api.configured-providers.ts +110 -0
- tools/bolt.diy/app/routes/api.corporate-swarm-status.ts +55 -0
- tools/bolt.diy/app/routes/api.enhancer.ts +137 -0
- tools/bolt.diy/app/routes/api.export-api-keys.ts +44 -0
- tools/bolt.diy/app/routes/api.git-info.ts +69 -0
- tools/bolt.diy/app/routes/api.git-proxy.$.ts +178 -0
- tools/bolt.diy/app/routes/api.github-branches.ts +166 -0
- tools/bolt.diy/app/routes/api.github-deploy.ts +67 -0
- tools/bolt.diy/app/routes/api.github-stats.ts +198 -0
- tools/bolt.diy/app/routes/api.github-template.ts +242 -0
- tools/bolt.diy/app/routes/api.github-user.ts +287 -0
- tools/bolt.diy/app/routes/api.gitlab-branches.ts +143 -0
- tools/bolt.diy/app/routes/api.gitlab-deploy.ts +67 -0
- tools/bolt.diy/app/routes/api.gitlab-projects.ts +105 -0
- tools/bolt.diy/app/routes/api.health.ts +8 -0
- tools/bolt.diy/app/routes/api.llmcall.ts +298 -0
- tools/bolt.diy/app/routes/api.mandate.ts +351 -0
- tools/bolt.diy/app/routes/api.mcp-check.ts +16 -0
- tools/bolt.diy/app/routes/api.mcp-update-config.ts +23 -0
- tools/bolt.diy/app/routes/api.models.$provider.ts +2 -0
- tools/bolt.diy/app/routes/api.models.ts +90 -0
- tools/bolt.diy/app/routes/api.netlify-deploy.ts +240 -0
- tools/bolt.diy/app/routes/api.netlify-user.ts +142 -0
- tools/bolt.diy/app/routes/api.supabase-user.ts +199 -0
- tools/bolt.diy/app/routes/api.supabase.query.ts +92 -0
- tools/bolt.diy/app/routes/api.supabase.ts +56 -0
- tools/bolt.diy/app/routes/api.supabase.variables.ts +32 -0
- tools/bolt.diy/app/routes/api.system.diagnostics.ts +142 -0
- tools/bolt.diy/app/routes/api.system.disk-info.ts +311 -0
- tools/bolt.diy/app/routes/api.system.git-info.ts +332 -0
- tools/bolt.diy/app/routes/api.update.ts +21 -0
- tools/bolt.diy/app/routes/api.vercel-deploy.ts +497 -0
- tools/bolt.diy/app/routes/api.vercel-user.ts +161 -0
- tools/bolt.diy/app/routes/api.workflow-status.$proposalId.ts +309 -0
- tools/bolt.diy/app/routes/chat.$id.tsx +8 -0
- tools/bolt.diy/app/routes/execute.$mandateId.tsx +432 -0
- tools/bolt.diy/app/routes/git.tsx +25 -0
- tools/bolt.diy/app/routes/observability.$mandateId.tsx +50 -0
- tools/bolt.diy/app/routes/webcontainer.connect.$id.tsx +32 -0
- tools/bolt.diy/app/routes/webcontainer.preview.$id.tsx +97 -0
- tools/bolt.diy/app/routes/workflow.$proposalId.tsx +170 -0
- tools/bolt.diy/app/styles/animations.scss +49 -0
- tools/bolt.diy/app/styles/components/code.scss +9 -0
- tools/bolt.diy/app/styles/components/editor.scss +135 -0
- tools/bolt.diy/app/styles/components/resize-handle.scss +30 -0
- tools/bolt.diy/app/styles/components/terminal.scss +3 -0
- tools/bolt.diy/app/styles/components/toast.scss +23 -0
- tools/bolt.diy/app/styles/diff-view.css +72 -0
- tools/bolt.diy/app/styles/index.scss +73 -0
- tools/bolt.diy/app/styles/variables.scss +255 -0
- tools/bolt.diy/app/styles/z-index.scss +37 -0
- tools/bolt.diy/app/types/GitHub.ts +182 -0
- tools/bolt.diy/app/types/GitLab.ts +103 -0
- tools/bolt.diy/app/types/actions.ts +85 -0
- tools/bolt.diy/app/types/artifact.ts +5 -0
- tools/bolt.diy/app/types/context.ts +26 -0
- tools/bolt.diy/app/types/design-scheme.ts +93 -0
- tools/bolt.diy/app/types/global.d.ts +13 -0
- tools/bolt.diy/app/types/mandate.ts +333 -0
- tools/bolt.diy/app/types/model.ts +25 -0
- tools/bolt.diy/app/types/netlify.ts +94 -0
- tools/bolt.diy/app/types/supabase.ts +54 -0
- tools/bolt.diy/app/types/template.ts +8 -0
- tools/bolt.diy/app/types/terminal.ts +9 -0
- tools/bolt.diy/app/types/theme.ts +1 -0
- tools/bolt.diy/app/types/vercel.ts +67 -0
- tools/bolt.diy/app/utils/buffer.ts +29 -0
- tools/bolt.diy/app/utils/classNames.ts +65 -0
- tools/bolt.diy/app/utils/constants.ts +147 -0
- tools/bolt.diy/app/utils/debounce.ts +13 -0
- tools/bolt.diy/app/utils/debugLogger.ts +1284 -0
- tools/bolt.diy/app/utils/diff.spec.ts +11 -0
- tools/bolt.diy/app/utils/diff.ts +117 -0
- tools/bolt.diy/app/utils/easings.ts +3 -0
- tools/bolt.diy/app/utils/fileLocks.ts +96 -0
- tools/bolt.diy/app/utils/fileUtils.ts +121 -0
- tools/bolt.diy/app/utils/folderImport.ts +73 -0
- tools/bolt.diy/app/utils/formatSize.ts +12 -0
- tools/bolt.diy/app/utils/getLanguageFromExtension.ts +24 -0
- tools/bolt.diy/app/utils/githubStats.ts +9 -0
- tools/bolt.diy/app/utils/gitlabStats.ts +54 -0
- tools/bolt.diy/app/utils/logger.ts +162 -0
- tools/bolt.diy/app/utils/markdown.ts +155 -0
- tools/bolt.diy/app/utils/mobile.ts +4 -0
- tools/bolt.diy/app/utils/os.ts +4 -0
- tools/bolt.diy/app/utils/path.ts +19 -0
- tools/bolt.diy/app/utils/projectCommands.ts +197 -0
- tools/bolt.diy/app/utils/promises.ts +19 -0
- tools/bolt.diy/app/utils/react.ts +6 -0
- tools/bolt.diy/app/utils/sampler.ts +49 -0
- tools/bolt.diy/app/utils/selectStarterTemplate.ts +255 -0
- tools/bolt.diy/app/utils/shell.ts +384 -0
- tools/bolt.diy/app/utils/stacktrace.ts +27 -0
- tools/bolt.diy/app/utils/stripIndent.ts +23 -0
- tools/bolt.diy/app/utils/terminal.ts +11 -0
- tools/bolt.diy/app/utils/unreachable.ts +3 -0
- tools/bolt.diy/app/vite-env.d.ts +2 -0
- tools/bolt.diy/assets/entitlements.mac.plist +25 -0
- tools/bolt.diy/assets/icons/icon.icns +0 -0
- tools/bolt.diy/assets/icons/icon.ico +0 -0
- tools/bolt.diy/assets/icons/icon.png +0 -0
- tools/bolt.diy/bindings.js +78 -0
- tools/bolt.diy/bindings.sh +33 -0
- tools/bolt.diy/docker-compose.yaml +145 -0
- tools/bolt.diy/electron/main/index.ts +201 -0
- tools/bolt.diy/electron/main/tsconfig.json +30 -0
- tools/bolt.diy/electron/main/ui/menu.ts +29 -0
- tools/bolt.diy/electron/main/ui/window.ts +54 -0
- tools/bolt.diy/electron/main/utils/auto-update.ts +110 -0
- tools/bolt.diy/electron/main/utils/constants.ts +4 -0
- tools/bolt.diy/electron/main/utils/cookie.ts +40 -0
- tools/bolt.diy/electron/main/utils/reload.ts +35 -0
- tools/bolt.diy/electron/main/utils/serve.ts +71 -0
- tools/bolt.diy/electron/main/utils/store.ts +3 -0
- tools/bolt.diy/electron/main/utils/vite-server.ts +44 -0
- tools/bolt.diy/electron/main/vite.config.ts +44 -0
- tools/bolt.diy/electron/preload/index.ts +22 -0
- tools/bolt.diy/electron/preload/tsconfig.json +7 -0
- tools/bolt.diy/electron/preload/vite.config.ts +31 -0
- tools/bolt.diy/electron-builder.yml +64 -0
- tools/bolt.diy/electron-update.yml +4 -0
- tools/bolt.diy/eslint.config.mjs +57 -0
- tools/bolt.diy/functions/[[path]].ts +12 -0
- tools/bolt.diy/icons/angular.svg +1 -0
- tools/bolt.diy/icons/astro.svg +8 -0
- tools/bolt.diy/icons/chat.svg +1 -0
- tools/bolt.diy/icons/expo-brand.svg +1 -0
- tools/bolt.diy/icons/expo.svg +4 -0
- tools/bolt.diy/icons/logo-text.svg +1 -0
- tools/bolt.diy/icons/logo.svg +4 -0
- tools/bolt.diy/icons/mcp.svg +1 -0
- tools/bolt.diy/icons/nativescript.svg +1 -0
- tools/bolt.diy/icons/netlify.svg +10 -0
- tools/bolt.diy/icons/nextjs.svg +1 -0
- tools/bolt.diy/icons/nuxt.svg +1 -0
- tools/bolt.diy/icons/qwik.svg +1 -0
- tools/bolt.diy/icons/react.svg +1 -0
- tools/bolt.diy/icons/remix.svg +24 -0
- tools/bolt.diy/icons/remotion.svg +1 -0
- tools/bolt.diy/icons/shadcn.svg +21 -0
- tools/bolt.diy/icons/slidev.svg +60 -0
- tools/bolt.diy/icons/solidjs.svg +1 -0
- tools/bolt.diy/icons/stars.svg +1 -0
- tools/bolt.diy/icons/svelte.svg +1 -0
- tools/bolt.diy/icons/typescript.svg +1 -0
- tools/bolt.diy/icons/vite.svg +1 -0
- tools/bolt.diy/icons/vue.svg +1 -0
- tools/bolt.diy/load-context.ts +9 -0
- tools/bolt.diy/notarize.cjs +31 -0
- tools/bolt.diy/package.json +218 -0
- tools/bolt.diy/playwright.config.preview.ts +35 -0
- tools/bolt.diy/pre-start.cjs +26 -0
- tools/bolt.diy/public/apple-touch-icon-precomposed.png +0 -0
- tools/bolt.diy/public/apple-touch-icon.png +0 -0
- tools/bolt.diy/public/favicon.ico +0 -0
- tools/bolt.diy/public/favicon.svg +4 -0
- tools/bolt.diy/public/icons/AmazonBedrock.svg +1 -0
- tools/bolt.diy/public/icons/Anthropic.svg +4 -0
- tools/bolt.diy/public/icons/Cohere.svg +4 -0
- tools/bolt.diy/public/icons/Deepseek.svg +5 -0
- tools/bolt.diy/public/icons/Default.svg +4 -0
- tools/bolt.diy/public/icons/Google.svg +4 -0
- tools/bolt.diy/public/icons/Groq.svg +4 -0
- tools/bolt.diy/public/icons/HuggingFace.svg +4 -0
- tools/bolt.diy/public/icons/Hyperbolic.svg +3 -0
- tools/bolt.diy/public/icons/LMStudio.svg +5 -0
- tools/bolt.diy/public/icons/Mistral.svg +4 -0
- tools/bolt.diy/public/icons/Ollama.svg +4 -0
- tools/bolt.diy/public/icons/OpenAI.svg +4 -0
- tools/bolt.diy/public/icons/OpenAILike.svg +4 -0
- tools/bolt.diy/public/icons/OpenRouter.svg +4 -0
- tools/bolt.diy/public/icons/Perplexity.svg +4 -0
- tools/bolt.diy/public/icons/Together.svg +4 -0
- tools/bolt.diy/public/icons/xAI.svg +5 -0
- tools/bolt.diy/public/inspector-script.js +292 -0
- tools/bolt.diy/public/logo-dark-styled.png +0 -0
- tools/bolt.diy/public/logo-dark.png +0 -0
- tools/bolt.diy/public/logo-light-styled.png +0 -0
- tools/bolt.diy/public/logo-light.png +0 -0
- tools/bolt.diy/public/logo.svg +15 -0
- tools/bolt.diy/public/social_preview_index.jpg +0 -0
- tools/bolt.diy/scripts/clean.js +45 -0
- tools/bolt.diy/scripts/electron-dev.mjs +181 -0
- tools/bolt.diy/scripts/setup-env.sh +41 -0
- tools/bolt.diy/scripts/update-imports.sh +7 -0
- tools/bolt.diy/scripts/update.sh +52 -0
- tools/bolt.diy/services/execution-governor/Dockerfile +41 -0
- tools/bolt.diy/services/execution-governor/config.ts +42 -0
- tools/bolt.diy/services/execution-governor/index.ts +683 -0
- tools/bolt.diy/services/execution-governor/metrics.ts +141 -0
- tools/bolt.diy/services/execution-governor/package.json +31 -0
- tools/bolt.diy/services/execution-governor/priority-queue.ts +139 -0
- tools/bolt.diy/services/execution-governor/tsconfig.json +21 -0
- tools/bolt.diy/services/execution-governor/types.ts +145 -0
- tools/bolt.diy/services/headless-executor/Dockerfile +43 -0
- tools/bolt.diy/services/headless-executor/executor.ts +210 -0
- tools/bolt.diy/services/headless-executor/index.ts +323 -0
- tools/bolt.diy/services/headless-executor/package.json +27 -0
- tools/bolt.diy/services/headless-executor/tsconfig.json +21 -0
- tools/bolt.diy/services/headless-executor/types.ts +38 -0
- tools/bolt.diy/test-workflows.sh +240 -0
- tools/bolt.diy/tests/integration/corporate-swarm.test.ts +208 -0
- tools/bolt.diy/tests/mandates/budget-limited.json +34 -0
- tools/bolt.diy/tests/mandates/complex.json +53 -0
- tools/bolt.diy/tests/mandates/constraint-enforced.json +36 -0
- tools/bolt.diy/tests/mandates/simple.json +35 -0
- tools/bolt.diy/tsconfig.json +37 -0
- tools/bolt.diy/types/istextorbinary.d.ts +15 -0
- tools/bolt.diy/uno.config.ts +279 -0
- tools/bolt.diy/vite-electron.config.ts +76 -0
- tools/bolt.diy/vite.config.ts +112 -0
- tools/bolt.diy/worker-configuration.d.ts +22 -0
- tools/bolt.diy/wrangler.toml +6 -0
- tools/code_generator.py +461 -0
- tools/file_operations.py +465 -0
- tools/mandate_generator.py +337 -0
- tools/mcpClientUtils.py +1216 -0
- tools/sensors.py +285 -0
- utils/Agent_types.py +15 -0
- utils/AnyToStr.py +0 -0
- utils/HHCS.py +277 -0
- utils/__init__.py +30 -0
- utils/agent.py +3627 -0
- utils/aop.py +2948 -0
- utils/canonical.py +143 -0
- utils/conversation.py +1195 -0
- utils/doctrine_versioning +230 -0
- utils/formatter.py +474 -0
- utils/ledger.py +311 -0
- utils/out_types.py +16 -0
- utils/rollback.py +339 -0
- utils/router.py +929 -0
- utils/tui.py +1908 -0
utils/ledger.py
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"""Event-sourced ledger for policy engine.
|
|
2
|
+
|
|
3
|
+
This module provides a SQLite-based append-only event store for the policy engine.
|
|
4
|
+
The ledger serves as:
|
|
5
|
+
- Dataset for online learning
|
|
6
|
+
- Audit trail for decisions
|
|
7
|
+
- Replay engine for deterministic execution
|
|
8
|
+
|
|
9
|
+
All events are hashed and stored immutably (append-only).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import sqlite3
|
|
13
|
+
import json
|
|
14
|
+
from typing import Any, Dict, List, Optional
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from loguru import logger
|
|
17
|
+
|
|
18
|
+
from schemas.policy import LedgerEvent
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Ledger:
|
|
22
|
+
"""SQLite-based append-only event ledger.
|
|
23
|
+
|
|
24
|
+
Schema:
|
|
25
|
+
events(
|
|
26
|
+
id INTEGER PRIMARY KEY,
|
|
27
|
+
type TEXT,
|
|
28
|
+
epoch INTEGER,
|
|
29
|
+
hash TEXT UNIQUE,
|
|
30
|
+
payload_json TEXT
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
Indexed on (epoch, type) for fast window queries.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, db_path: str):
|
|
37
|
+
"""
|
|
38
|
+
Initialize ledger with SQLite database.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
db_path: Path to SQLite database file
|
|
42
|
+
"""
|
|
43
|
+
self.db_path = db_path
|
|
44
|
+
self._conn: Optional[sqlite3.Connection] = None
|
|
45
|
+
self._initialize_db()
|
|
46
|
+
|
|
47
|
+
def _initialize_db(self) -> None:
|
|
48
|
+
"""Initialize database schema if it doesn't exist."""
|
|
49
|
+
conn = sqlite3.connect(self.db_path)
|
|
50
|
+
cursor = conn.cursor()
|
|
51
|
+
|
|
52
|
+
# Create events table
|
|
53
|
+
cursor.execute("""
|
|
54
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
55
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
56
|
+
type TEXT NOT NULL,
|
|
57
|
+
epoch INTEGER NOT NULL,
|
|
58
|
+
hash TEXT UNIQUE NOT NULL,
|
|
59
|
+
payload_json TEXT NOT NULL,
|
|
60
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
61
|
+
)
|
|
62
|
+
""")
|
|
63
|
+
|
|
64
|
+
# Create indexes for fast queries
|
|
65
|
+
cursor.execute("""
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_epoch_type
|
|
67
|
+
ON events(epoch, type)
|
|
68
|
+
""")
|
|
69
|
+
|
|
70
|
+
cursor.execute("""
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_epoch
|
|
72
|
+
ON events(epoch)
|
|
73
|
+
""")
|
|
74
|
+
|
|
75
|
+
conn.commit()
|
|
76
|
+
conn.close()
|
|
77
|
+
|
|
78
|
+
def _get_connection(self) -> sqlite3.Connection:
|
|
79
|
+
"""Get or create database connection."""
|
|
80
|
+
if self._conn is None:
|
|
81
|
+
self._conn = sqlite3.connect(self.db_path)
|
|
82
|
+
self._conn.row_factory = sqlite3.Row
|
|
83
|
+
return self._conn
|
|
84
|
+
|
|
85
|
+
def append(self, event: LedgerEvent) -> int:
|
|
86
|
+
"""
|
|
87
|
+
Append an event to the ledger.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
event: LedgerEvent to append
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
int: Event ID
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
sqlite3.IntegrityError: If hash already exists (duplicate event)
|
|
97
|
+
"""
|
|
98
|
+
conn = self._get_connection()
|
|
99
|
+
cursor = conn.cursor()
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
cursor.execute("""
|
|
103
|
+
INSERT INTO events (type, epoch, hash, payload_json)
|
|
104
|
+
VALUES (?, ?, ?, ?)
|
|
105
|
+
""", (
|
|
106
|
+
event.type,
|
|
107
|
+
event.epoch,
|
|
108
|
+
event.hash,
|
|
109
|
+
json.dumps(event.payload)
|
|
110
|
+
))
|
|
111
|
+
conn.commit()
|
|
112
|
+
event_id = cursor.lastrowid
|
|
113
|
+
logger.debug(f"Appended event {event_id} (type={event.type}, epoch={event.epoch})")
|
|
114
|
+
return event_id
|
|
115
|
+
except sqlite3.IntegrityError as e:
|
|
116
|
+
if "UNIQUE constraint failed" in str(e):
|
|
117
|
+
logger.warning(f"Duplicate event hash {event.hash} - skipping")
|
|
118
|
+
# Return existing event ID
|
|
119
|
+
cursor.execute("SELECT id FROM events WHERE hash = ?", (event.hash,))
|
|
120
|
+
row = cursor.fetchone()
|
|
121
|
+
return row["id"] if row else -1
|
|
122
|
+
raise
|
|
123
|
+
|
|
124
|
+
def window(self, epoch: int, k: int, event_type: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
125
|
+
"""
|
|
126
|
+
Get events from the last k epochs ending at epoch.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
epoch: End epoch (inclusive)
|
|
130
|
+
k: Number of epochs to look back
|
|
131
|
+
event_type: Optional event type filter
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
List[Dict[str, Any]]: List of event dictionaries
|
|
135
|
+
"""
|
|
136
|
+
conn = self._get_connection()
|
|
137
|
+
cursor = conn.cursor()
|
|
138
|
+
|
|
139
|
+
start_epoch = max(0, epoch - k + 1)
|
|
140
|
+
|
|
141
|
+
if event_type:
|
|
142
|
+
cursor.execute("""
|
|
143
|
+
SELECT * FROM events
|
|
144
|
+
WHERE epoch >= ? AND epoch <= ? AND type = ?
|
|
145
|
+
ORDER BY epoch ASC, id ASC
|
|
146
|
+
""", (start_epoch, epoch, event_type))
|
|
147
|
+
else:
|
|
148
|
+
cursor.execute("""
|
|
149
|
+
SELECT * FROM events
|
|
150
|
+
WHERE epoch >= ? AND epoch <= ?
|
|
151
|
+
ORDER BY epoch ASC, id ASC
|
|
152
|
+
""", (start_epoch, epoch))
|
|
153
|
+
|
|
154
|
+
rows = cursor.fetchall()
|
|
155
|
+
events = []
|
|
156
|
+
for row in rows:
|
|
157
|
+
events.append({
|
|
158
|
+
"id": row["id"],
|
|
159
|
+
"type": row["type"],
|
|
160
|
+
"epoch": row["epoch"],
|
|
161
|
+
"hash": row["hash"],
|
|
162
|
+
"payload": json.loads(row["payload_json"]),
|
|
163
|
+
"created_at": row["created_at"]
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
return events
|
|
167
|
+
|
|
168
|
+
def latest(self, event_type: Optional[str] = None, epoch: Optional[int] = None) -> Optional[Dict[str, Any]]:
|
|
169
|
+
"""
|
|
170
|
+
Get the latest event (optionally filtered by type and epoch).
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
event_type: Optional event type filter
|
|
174
|
+
epoch: Optional epoch filter
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
Optional[Dict[str, Any]]: Latest event or None
|
|
178
|
+
"""
|
|
179
|
+
conn = self._get_connection()
|
|
180
|
+
cursor = conn.cursor()
|
|
181
|
+
|
|
182
|
+
if event_type and epoch is not None:
|
|
183
|
+
cursor.execute("""
|
|
184
|
+
SELECT * FROM events
|
|
185
|
+
WHERE type = ? AND epoch = ?
|
|
186
|
+
ORDER BY id DESC
|
|
187
|
+
LIMIT 1
|
|
188
|
+
""", (event_type, epoch))
|
|
189
|
+
elif event_type:
|
|
190
|
+
cursor.execute("""
|
|
191
|
+
SELECT * FROM events
|
|
192
|
+
WHERE type = ?
|
|
193
|
+
ORDER BY epoch DESC, id DESC
|
|
194
|
+
LIMIT 1
|
|
195
|
+
""", (event_type,))
|
|
196
|
+
elif epoch is not None:
|
|
197
|
+
cursor.execute("""
|
|
198
|
+
SELECT * FROM events
|
|
199
|
+
WHERE epoch = ?
|
|
200
|
+
ORDER BY id DESC
|
|
201
|
+
LIMIT 1
|
|
202
|
+
""", (epoch,))
|
|
203
|
+
else:
|
|
204
|
+
cursor.execute("""
|
|
205
|
+
SELECT * FROM events
|
|
206
|
+
ORDER BY epoch DESC, id DESC
|
|
207
|
+
LIMIT 1
|
|
208
|
+
""")
|
|
209
|
+
|
|
210
|
+
row = cursor.fetchone()
|
|
211
|
+
if row:
|
|
212
|
+
return {
|
|
213
|
+
"id": row["id"],
|
|
214
|
+
"type": row["type"],
|
|
215
|
+
"epoch": row["epoch"],
|
|
216
|
+
"hash": row["hash"],
|
|
217
|
+
"payload": json.loads(row["payload_json"]),
|
|
218
|
+
"created_at": row["created_at"]
|
|
219
|
+
}
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
def iter_range(
|
|
223
|
+
self,
|
|
224
|
+
t0: int,
|
|
225
|
+
t1: int,
|
|
226
|
+
event_type: Optional[str] = None
|
|
227
|
+
) -> List[Dict[str, Any]]:
|
|
228
|
+
"""
|
|
229
|
+
Iterate over events in epoch range [t0, t1] (inclusive).
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
t0: Start epoch (inclusive)
|
|
233
|
+
t1: End epoch (inclusive)
|
|
234
|
+
event_type: Optional event type filter
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
List[Dict[str, Any]]: List of event dictionaries
|
|
238
|
+
"""
|
|
239
|
+
conn = self._get_connection()
|
|
240
|
+
cursor = conn.cursor()
|
|
241
|
+
|
|
242
|
+
if event_type:
|
|
243
|
+
cursor.execute("""
|
|
244
|
+
SELECT * FROM events
|
|
245
|
+
WHERE epoch >= ? AND epoch <= ? AND type = ?
|
|
246
|
+
ORDER BY epoch ASC, id ASC
|
|
247
|
+
""", (t0, t1, event_type))
|
|
248
|
+
else:
|
|
249
|
+
cursor.execute("""
|
|
250
|
+
SELECT * FROM events
|
|
251
|
+
WHERE epoch >= ? AND epoch <= ?
|
|
252
|
+
ORDER BY epoch ASC, id ASC
|
|
253
|
+
""", (t0, t1))
|
|
254
|
+
|
|
255
|
+
rows = cursor.fetchall()
|
|
256
|
+
events = []
|
|
257
|
+
for row in rows:
|
|
258
|
+
events.append({
|
|
259
|
+
"id": row["id"],
|
|
260
|
+
"type": row["type"],
|
|
261
|
+
"epoch": row["epoch"],
|
|
262
|
+
"hash": row["hash"],
|
|
263
|
+
"payload": json.loads(row["payload_json"]),
|
|
264
|
+
"created_at": row["created_at"]
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
return events
|
|
268
|
+
|
|
269
|
+
def compute_deltas(self, epoch: int) -> Dict[str, float]:
|
|
270
|
+
"""
|
|
271
|
+
Compute feature deltas between observation and outcome at epoch t.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
epoch: Epoch to compute deltas for
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Dict[str, float]: Dictionary mapping metric names to deltas
|
|
278
|
+
"""
|
|
279
|
+
obs = self.latest(event_type="observation", epoch=epoch)
|
|
280
|
+
outcome = self.latest(event_type="outcome", epoch=epoch)
|
|
281
|
+
|
|
282
|
+
if not obs or not outcome:
|
|
283
|
+
return {}
|
|
284
|
+
|
|
285
|
+
obs_metrics = obs["payload"].get("metrics", {})
|
|
286
|
+
outcome_metrics = outcome["payload"].get("metrics", {})
|
|
287
|
+
|
|
288
|
+
deltas = {}
|
|
289
|
+
all_metrics = set(obs_metrics.keys()) | set(outcome_metrics.keys())
|
|
290
|
+
|
|
291
|
+
for metric in all_metrics:
|
|
292
|
+
obs_val = obs_metrics.get(metric, 0.0)
|
|
293
|
+
outcome_val = outcome_metrics.get(metric, 0.0)
|
|
294
|
+
deltas[metric] = outcome_val - obs_val
|
|
295
|
+
|
|
296
|
+
return deltas
|
|
297
|
+
|
|
298
|
+
def close(self) -> None:
|
|
299
|
+
"""Close database connection."""
|
|
300
|
+
if self._conn:
|
|
301
|
+
self._conn.close()
|
|
302
|
+
self._conn = None
|
|
303
|
+
|
|
304
|
+
def __enter__(self):
|
|
305
|
+
"""Context manager entry."""
|
|
306
|
+
return self
|
|
307
|
+
|
|
308
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
309
|
+
"""Context manager exit."""
|
|
310
|
+
self.close()
|
|
311
|
+
|
utils/out_types.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Output type definitions for history and conversation formatting.
|
|
3
|
+
|
|
4
|
+
Defines type literals for specifying output formats when extracting
|
|
5
|
+
conversation history or agent responses.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Literal
|
|
9
|
+
|
|
10
|
+
HistoryOutputType = Literal[
|
|
11
|
+
"list", "dict", "dictionary", "string", "str", "final", "last",
|
|
12
|
+
"json", "all", "yaml", "xml", "dict-all-except-first",
|
|
13
|
+
"str-all-except-first", "basemodel", "dict-final", "list-final"
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
OutputType = HistoryOutputType
|
utils/rollback.py
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"""Rollback system for intervention recovery.
|
|
2
|
+
|
|
3
|
+
Provides checkpoint creation, intervention recording, and rollback
|
|
4
|
+
execution for recovering from failed interventions.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, List, Optional
|
|
8
|
+
from datetime import datetime, timezone
|
|
9
|
+
import sqlite3
|
|
10
|
+
import json
|
|
11
|
+
import uuid
|
|
12
|
+
from loguru import logger
|
|
13
|
+
|
|
14
|
+
from schemas.policy import InterventionSpec
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RollbackManager:
|
|
18
|
+
"""Rollback manager for intervention recovery.
|
|
19
|
+
|
|
20
|
+
Features:
|
|
21
|
+
- State checkpoint creation
|
|
22
|
+
- Intervention recording with results
|
|
23
|
+
- Rollback execution (reverse interventions)
|
|
24
|
+
- Checkpoint restoration
|
|
25
|
+
- Time-based retention
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, db_path: str = ":memory:", retention_days: int = 7):
|
|
29
|
+
"""
|
|
30
|
+
Initialize rollback manager.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
db_path: Path to SQLite database (or ":memory:" for in-memory)
|
|
34
|
+
retention_days: Number of days to retain checkpoints
|
|
35
|
+
"""
|
|
36
|
+
self.db_path = db_path
|
|
37
|
+
self.retention_days = retention_days
|
|
38
|
+
self.conn = sqlite3.connect(db_path)
|
|
39
|
+
self._init_db()
|
|
40
|
+
|
|
41
|
+
def _init_db(self) -> None:
|
|
42
|
+
"""Initialize database schema."""
|
|
43
|
+
cursor = self.conn.cursor()
|
|
44
|
+
|
|
45
|
+
# Checkpoints table
|
|
46
|
+
cursor.execute("""
|
|
47
|
+
CREATE TABLE IF NOT EXISTS checkpoints (
|
|
48
|
+
checkpoint_id TEXT PRIMARY KEY,
|
|
49
|
+
epoch INTEGER NOT NULL,
|
|
50
|
+
state_json TEXT NOT NULL,
|
|
51
|
+
created_at TIMESTAMP NOT NULL
|
|
52
|
+
)
|
|
53
|
+
""")
|
|
54
|
+
|
|
55
|
+
# Interventions table
|
|
56
|
+
cursor.execute("""
|
|
57
|
+
CREATE TABLE IF NOT EXISTS interventions (
|
|
58
|
+
intervention_id TEXT PRIMARY KEY,
|
|
59
|
+
checkpoint_id TEXT,
|
|
60
|
+
epoch INTEGER NOT NULL,
|
|
61
|
+
lever_id TEXT NOT NULL,
|
|
62
|
+
parameters_json TEXT NOT NULL,
|
|
63
|
+
result_json TEXT,
|
|
64
|
+
rollback_descriptor_json TEXT,
|
|
65
|
+
created_at TIMESTAMP NOT NULL,
|
|
66
|
+
FOREIGN KEY (checkpoint_id) REFERENCES checkpoints(checkpoint_id)
|
|
67
|
+
)
|
|
68
|
+
""")
|
|
69
|
+
|
|
70
|
+
# Rollback history table
|
|
71
|
+
cursor.execute("""
|
|
72
|
+
CREATE TABLE IF NOT EXISTS rollback_history (
|
|
73
|
+
rollback_id TEXT PRIMARY KEY,
|
|
74
|
+
epoch INTEGER NOT NULL,
|
|
75
|
+
n_steps INTEGER NOT NULL,
|
|
76
|
+
intervention_ids TEXT NOT NULL,
|
|
77
|
+
created_at TIMESTAMP NOT NULL
|
|
78
|
+
)
|
|
79
|
+
""")
|
|
80
|
+
|
|
81
|
+
self.conn.commit()
|
|
82
|
+
|
|
83
|
+
def create_checkpoint(self, epoch: int, state: Dict[str, Any]) -> str:
|
|
84
|
+
"""
|
|
85
|
+
Create a state checkpoint.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
epoch: Epoch number
|
|
89
|
+
state: State dictionary to checkpoint
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
str: Checkpoint ID
|
|
93
|
+
"""
|
|
94
|
+
checkpoint_id = str(uuid.uuid4())
|
|
95
|
+
state_json = json.dumps(state)
|
|
96
|
+
created_at = datetime.now(timezone.utc).isoformat()
|
|
97
|
+
|
|
98
|
+
cursor = self.conn.cursor()
|
|
99
|
+
cursor.execute("""
|
|
100
|
+
INSERT INTO checkpoints (checkpoint_id, epoch, state_json, created_at)
|
|
101
|
+
VALUES (?, ?, ?, ?)
|
|
102
|
+
""", (checkpoint_id, epoch, state_json, created_at))
|
|
103
|
+
self.conn.commit()
|
|
104
|
+
|
|
105
|
+
logger.info(f"Created checkpoint {checkpoint_id} for epoch {epoch}")
|
|
106
|
+
|
|
107
|
+
# Clean up old checkpoints
|
|
108
|
+
self._cleanup_old_checkpoints()
|
|
109
|
+
|
|
110
|
+
return checkpoint_id
|
|
111
|
+
|
|
112
|
+
def record_intervention(
|
|
113
|
+
self,
|
|
114
|
+
epoch: int,
|
|
115
|
+
intervention: InterventionSpec,
|
|
116
|
+
result: Optional[Dict[str, Any]] = None,
|
|
117
|
+
checkpoint_id: Optional[str] = None
|
|
118
|
+
) -> str:
|
|
119
|
+
"""
|
|
120
|
+
Record an intervention with its result.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
epoch: Epoch number
|
|
124
|
+
intervention: Intervention specification
|
|
125
|
+
result: Optional execution result
|
|
126
|
+
checkpoint_id: Optional checkpoint ID associated with this intervention
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
str: Intervention ID
|
|
130
|
+
"""
|
|
131
|
+
intervention_id = str(uuid.uuid4())
|
|
132
|
+
parameters_json = json.dumps(intervention.parameters)
|
|
133
|
+
result_json = json.dumps(result) if result else None
|
|
134
|
+
rollback_descriptor_json = json.dumps(intervention.rollback_descriptor) if intervention.rollback_descriptor else None
|
|
135
|
+
created_at = datetime.now(timezone.utc).isoformat()
|
|
136
|
+
|
|
137
|
+
cursor = self.conn.cursor()
|
|
138
|
+
cursor.execute("""
|
|
139
|
+
INSERT INTO interventions (
|
|
140
|
+
intervention_id, checkpoint_id, epoch, lever_id,
|
|
141
|
+
parameters_json, result_json, rollback_descriptor_json, created_at
|
|
142
|
+
)
|
|
143
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
144
|
+
""", (
|
|
145
|
+
intervention_id, checkpoint_id, epoch, intervention.lever_id,
|
|
146
|
+
parameters_json, result_json, rollback_descriptor_json, created_at
|
|
147
|
+
))
|
|
148
|
+
self.conn.commit()
|
|
149
|
+
|
|
150
|
+
logger.debug(f"Recorded intervention {intervention_id} for epoch {epoch}")
|
|
151
|
+
|
|
152
|
+
return intervention_id
|
|
153
|
+
|
|
154
|
+
def rollback(
|
|
155
|
+
self,
|
|
156
|
+
epoch: int,
|
|
157
|
+
n_steps: int,
|
|
158
|
+
actuator_registry: Optional[Any] = None
|
|
159
|
+
) -> List[str]:
|
|
160
|
+
"""
|
|
161
|
+
Rollback last N interventions.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
epoch: Current epoch
|
|
165
|
+
n_steps: Number of steps to rollback
|
|
166
|
+
actuator_registry: Optional actuator registry for executing rollbacks
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
List[str]: List of intervention IDs that were rolled back
|
|
170
|
+
"""
|
|
171
|
+
cursor = self.conn.cursor()
|
|
172
|
+
|
|
173
|
+
# Get last N interventions (most recent first)
|
|
174
|
+
cursor.execute("""
|
|
175
|
+
SELECT intervention_id, lever_id, parameters_json, rollback_descriptor_json
|
|
176
|
+
FROM interventions
|
|
177
|
+
WHERE epoch <= ?
|
|
178
|
+
ORDER BY created_at DESC
|
|
179
|
+
LIMIT ?
|
|
180
|
+
""", (epoch, n_steps))
|
|
181
|
+
|
|
182
|
+
interventions = cursor.fetchall()
|
|
183
|
+
|
|
184
|
+
if not interventions:
|
|
185
|
+
logger.warning(f"No interventions found to rollback (epoch {epoch}, n_steps {n_steps})")
|
|
186
|
+
return []
|
|
187
|
+
|
|
188
|
+
rolled_back_ids = []
|
|
189
|
+
|
|
190
|
+
# Execute rollbacks in reverse order (oldest first)
|
|
191
|
+
for intervention_id, lever_id, parameters_json, rollback_descriptor_json in reversed(interventions):
|
|
192
|
+
try:
|
|
193
|
+
if rollback_descriptor_json:
|
|
194
|
+
rollback_descriptor = json.loads(rollback_descriptor_json)
|
|
195
|
+
|
|
196
|
+
# Execute rollback via actuator if available
|
|
197
|
+
if actuator_registry:
|
|
198
|
+
actuator = actuator_registry.get_actuator_for_lever(lever_id)
|
|
199
|
+
if actuator:
|
|
200
|
+
success = actuator.rollback(rollback_descriptor)
|
|
201
|
+
if success:
|
|
202
|
+
logger.info(f"Rolled back intervention {intervention_id}")
|
|
203
|
+
else:
|
|
204
|
+
logger.warning(f"Rollback failed for intervention {intervention_id}")
|
|
205
|
+
else:
|
|
206
|
+
logger.warning(f"No actuator found for lever {lever_id}")
|
|
207
|
+
else:
|
|
208
|
+
logger.info(f"Rollback descriptor for {intervention_id}: {rollback_descriptor}")
|
|
209
|
+
|
|
210
|
+
rolled_back_ids.append(intervention_id)
|
|
211
|
+
except Exception as e:
|
|
212
|
+
logger.error(f"Error rolling back intervention {intervention_id}: {e}")
|
|
213
|
+
|
|
214
|
+
# Record rollback in history
|
|
215
|
+
rollback_id = str(uuid.uuid4())
|
|
216
|
+
intervention_ids_json = json.dumps(rolled_back_ids)
|
|
217
|
+
created_at = datetime.now(timezone.utc).isoformat()
|
|
218
|
+
|
|
219
|
+
cursor.execute("""
|
|
220
|
+
INSERT INTO rollback_history (rollback_id, epoch, n_steps, intervention_ids, created_at)
|
|
221
|
+
VALUES (?, ?, ?, ?, ?)
|
|
222
|
+
""", (rollback_id, epoch, n_steps, intervention_ids_json, created_at))
|
|
223
|
+
self.conn.commit()
|
|
224
|
+
|
|
225
|
+
logger.info(f"Rolled back {len(rolled_back_ids)} interventions")
|
|
226
|
+
|
|
227
|
+
return rolled_back_ids
|
|
228
|
+
|
|
229
|
+
def restore_checkpoint(self, checkpoint_id: str) -> Optional[Dict[str, Any]]:
|
|
230
|
+
"""
|
|
231
|
+
Restore state from checkpoint.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
checkpoint_id: Checkpoint ID to restore
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Dict[str, Any]: Restored state or None if not found
|
|
238
|
+
"""
|
|
239
|
+
cursor = self.conn.cursor()
|
|
240
|
+
cursor.execute("""
|
|
241
|
+
SELECT state_json FROM checkpoints WHERE checkpoint_id = ?
|
|
242
|
+
""", (checkpoint_id,))
|
|
243
|
+
|
|
244
|
+
row = cursor.fetchone()
|
|
245
|
+
if row:
|
|
246
|
+
state = json.loads(row[0])
|
|
247
|
+
logger.info(f"Restored checkpoint {checkpoint_id}")
|
|
248
|
+
return state
|
|
249
|
+
else:
|
|
250
|
+
logger.warning(f"Checkpoint {checkpoint_id} not found")
|
|
251
|
+
return None
|
|
252
|
+
|
|
253
|
+
def get_latest_checkpoint(self, epoch: Optional[int] = None) -> Optional[str]:
|
|
254
|
+
"""
|
|
255
|
+
Get the latest checkpoint ID.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
epoch: Optional epoch to filter by (get latest before or at this epoch)
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
str: Checkpoint ID or None
|
|
262
|
+
"""
|
|
263
|
+
cursor = self.conn.cursor()
|
|
264
|
+
|
|
265
|
+
if epoch is not None:
|
|
266
|
+
cursor.execute("""
|
|
267
|
+
SELECT checkpoint_id FROM checkpoints
|
|
268
|
+
WHERE epoch <= ?
|
|
269
|
+
ORDER BY created_at DESC
|
|
270
|
+
LIMIT 1
|
|
271
|
+
""", (epoch,))
|
|
272
|
+
else:
|
|
273
|
+
cursor.execute("""
|
|
274
|
+
SELECT checkpoint_id FROM checkpoints
|
|
275
|
+
ORDER BY created_at DESC
|
|
276
|
+
LIMIT 1
|
|
277
|
+
""")
|
|
278
|
+
|
|
279
|
+
row = cursor.fetchone()
|
|
280
|
+
return row[0] if row else None
|
|
281
|
+
|
|
282
|
+
def get_rollback_history(self, limit: int = 100) -> List[Dict[str, Any]]:
|
|
283
|
+
"""
|
|
284
|
+
Get rollback history.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
limit: Maximum number of records to return
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
List[Dict[str, Any]]: Rollback history records
|
|
291
|
+
"""
|
|
292
|
+
cursor = self.conn.cursor()
|
|
293
|
+
cursor.execute("""
|
|
294
|
+
SELECT rollback_id, epoch, n_steps, intervention_ids, created_at
|
|
295
|
+
FROM rollback_history
|
|
296
|
+
ORDER BY created_at DESC
|
|
297
|
+
LIMIT ?
|
|
298
|
+
""", (limit,))
|
|
299
|
+
|
|
300
|
+
rows = cursor.fetchall()
|
|
301
|
+
return [
|
|
302
|
+
{
|
|
303
|
+
"rollback_id": row[0],
|
|
304
|
+
"epoch": row[1],
|
|
305
|
+
"n_steps": row[2],
|
|
306
|
+
"intervention_ids": json.loads(row[3]),
|
|
307
|
+
"created_at": row[4]
|
|
308
|
+
}
|
|
309
|
+
for row in rows
|
|
310
|
+
]
|
|
311
|
+
|
|
312
|
+
def _cleanup_old_checkpoints(self) -> None:
|
|
313
|
+
"""Clean up checkpoints older than retention period."""
|
|
314
|
+
cutoff = datetime.now(timezone.utc).timestamp() - (self.retention_days * 86400)
|
|
315
|
+
cutoff_iso = datetime.fromtimestamp(cutoff, tz=timezone.utc).isoformat()
|
|
316
|
+
|
|
317
|
+
cursor = self.conn.cursor()
|
|
318
|
+
cursor.execute("""
|
|
319
|
+
DELETE FROM checkpoints WHERE created_at < ?
|
|
320
|
+
""", (cutoff_iso,))
|
|
321
|
+
|
|
322
|
+
deleted = cursor.rowcount
|
|
323
|
+
if deleted > 0:
|
|
324
|
+
logger.info(f"Cleaned up {deleted} old checkpoints")
|
|
325
|
+
|
|
326
|
+
self.conn.commit()
|
|
327
|
+
|
|
328
|
+
def close(self) -> None:
|
|
329
|
+
"""Close database connection."""
|
|
330
|
+
self.conn.close()
|
|
331
|
+
|
|
332
|
+
def __enter__(self):
|
|
333
|
+
"""Context manager entry."""
|
|
334
|
+
return self
|
|
335
|
+
|
|
336
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
337
|
+
"""Context manager exit."""
|
|
338
|
+
self.close()
|
|
339
|
+
|