@build-astron-co/nimbus 0.2.0 → 0.4.0
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.
- package/bin/nimbus +26 -10
- package/bin/nimbus.cmd +41 -0
- package/bin/nimbus.mjs +70 -0
- package/completions/nimbus.bash +38 -0
- package/completions/nimbus.fish +48 -0
- package/completions/nimbus.zsh +81 -0
- package/dist/src/agent/compaction-agent.js +215 -0
- package/dist/src/agent/context-manager.js +385 -0
- package/dist/src/agent/context.js +322 -0
- package/dist/src/agent/deploy-preview.js +395 -0
- package/dist/src/agent/expand-files.js +95 -0
- package/dist/src/agent/index.js +18 -0
- package/dist/src/agent/loop.js +1535 -0
- package/dist/src/agent/modes.js +347 -0
- package/dist/src/agent/permissions.js +396 -0
- package/dist/src/agent/subagents/base.js +67 -0
- package/dist/src/agent/subagents/cost.js +45 -0
- package/dist/src/agent/subagents/explore.js +36 -0
- package/dist/src/agent/subagents/general.js +41 -0
- package/dist/src/agent/subagents/index.js +88 -0
- package/dist/src/agent/subagents/infra.js +52 -0
- package/dist/src/agent/subagents/security.js +60 -0
- package/dist/src/agent/system-prompt.js +860 -0
- package/dist/src/app.js +152 -0
- package/dist/src/audit/activity-log.js +209 -0
- package/dist/src/audit/compliance-checker.js +419 -0
- package/dist/src/audit/cost-tracker.js +231 -0
- package/dist/src/audit/index.js +10 -0
- package/dist/src/audit/security-scanner.js +490 -0
- package/dist/src/auth/guard.js +64 -0
- package/dist/src/auth/index.js +19 -0
- package/dist/src/auth/keychain.js +79 -0
- package/dist/src/auth/oauth.js +389 -0
- package/dist/src/auth/providers.js +415 -0
- package/dist/src/auth/sso.js +87 -0
- package/dist/src/auth/store.js +424 -0
- package/dist/src/auth/types.js +5 -0
- package/dist/src/cli/index.js +8 -0
- package/dist/src/cli/init.js +1048 -0
- package/dist/src/cli/openapi-spec.js +346 -0
- package/dist/src/cli/run.js +505 -0
- package/dist/src/cli/serve-auth.js +56 -0
- package/dist/src/cli/serve.js +432 -0
- package/dist/src/cli/web.js +50 -0
- package/dist/src/cli.js +1574 -0
- package/dist/src/clients/core-engine-client.js +156 -0
- package/dist/src/clients/enterprise-client.js +246 -0
- package/dist/src/clients/generator-client.js +219 -0
- package/dist/src/clients/git-client.js +367 -0
- package/dist/src/clients/github-client.js +229 -0
- package/dist/src/clients/helm-client.js +299 -0
- package/dist/src/clients/index.js +18 -0
- package/dist/src/clients/k8s-client.js +270 -0
- package/dist/src/clients/llm-client.js +119 -0
- package/dist/src/clients/rest-client.js +104 -0
- package/dist/src/clients/service-discovery.js +35 -0
- package/dist/src/clients/terraform-client.js +302 -0
- package/dist/src/clients/tools-client.js +1227 -0
- package/dist/src/clients/ws-client.js +93 -0
- package/dist/src/commands/alias.js +91 -0
- package/dist/src/commands/analyze/index.js +313 -0
- package/dist/src/commands/apply/helm.js +375 -0
- package/dist/src/commands/apply/index.js +176 -0
- package/dist/src/commands/apply/k8s.js +350 -0
- package/dist/src/commands/apply/terraform.js +465 -0
- package/dist/src/commands/ask.js +137 -0
- package/dist/src/commands/audit/index.js +322 -0
- package/dist/src/commands/auth-cloud.js +345 -0
- package/dist/src/commands/auth-list.js +112 -0
- package/dist/src/commands/auth-profile.js +104 -0
- package/dist/src/commands/auth-refresh.js +161 -0
- package/dist/src/commands/auth-status.js +122 -0
- package/dist/src/commands/aws/ec2.js +402 -0
- package/dist/src/commands/aws/iam.js +304 -0
- package/dist/src/commands/aws/index.js +108 -0
- package/dist/src/commands/aws/lambda.js +317 -0
- package/dist/src/commands/aws/rds.js +345 -0
- package/dist/src/commands/aws/s3.js +346 -0
- package/dist/src/commands/aws/vpc.js +302 -0
- package/dist/src/commands/aws-discover.js +413 -0
- package/dist/src/commands/aws-terraform.js +618 -0
- package/dist/src/commands/azure/aks.js +305 -0
- package/dist/src/commands/azure/functions.js +200 -0
- package/dist/src/commands/azure/index.js +93 -0
- package/dist/src/commands/azure/storage.js +378 -0
- package/dist/src/commands/azure/vm.js +291 -0
- package/dist/src/commands/billing/index.js +224 -0
- package/dist/src/commands/chat.js +259 -0
- package/dist/src/commands/completions.js +255 -0
- package/dist/src/commands/config.js +291 -0
- package/dist/src/commands/cost/cloud-cost-estimator.js +211 -0
- package/dist/src/commands/cost/estimator.js +73 -0
- package/dist/src/commands/cost/index.js +625 -0
- package/dist/src/commands/cost/parsers/terraform.js +234 -0
- package/dist/src/commands/cost/parsers/types.js +4 -0
- package/dist/src/commands/cost/pricing/aws.js +501 -0
- package/dist/src/commands/cost/pricing/azure.js +462 -0
- package/dist/src/commands/cost/pricing/gcp.js +359 -0
- package/dist/src/commands/cost/pricing/index.js +24 -0
- package/dist/src/commands/demo.js +196 -0
- package/dist/src/commands/deploy.js +215 -0
- package/dist/src/commands/doctor.js +1291 -0
- package/dist/src/commands/drift/index.js +674 -0
- package/dist/src/commands/explain.js +235 -0
- package/dist/src/commands/export.js +120 -0
- package/dist/src/commands/feedback.js +319 -0
- package/dist/src/commands/fix.js +263 -0
- package/dist/src/commands/fs/index.js +338 -0
- package/dist/src/commands/gcp/compute.js +266 -0
- package/dist/src/commands/gcp/functions.js +221 -0
- package/dist/src/commands/gcp/gke.js +357 -0
- package/dist/src/commands/gcp/iam.js +295 -0
- package/dist/src/commands/gcp/index.js +105 -0
- package/dist/src/commands/gcp/storage.js +232 -0
- package/dist/src/commands/generate-helm.js +1026 -0
- package/dist/src/commands/generate-k8s.js +1263 -0
- package/dist/src/commands/generate-terraform.js +1058 -0
- package/dist/src/commands/gh/index.js +663 -0
- package/dist/src/commands/git/index.js +1208 -0
- package/dist/src/commands/helm/index.js +985 -0
- package/dist/src/commands/help.js +639 -0
- package/dist/src/commands/history.js +120 -0
- package/dist/src/commands/import.js +782 -0
- package/dist/src/commands/incident.js +144 -0
- package/dist/src/commands/index.js +109 -0
- package/dist/src/commands/init.js +955 -0
- package/dist/src/commands/k8s/index.js +979 -0
- package/dist/src/commands/login.js +588 -0
- package/dist/src/commands/logout.js +61 -0
- package/dist/src/commands/logs.js +160 -0
- package/dist/src/commands/onboarding.js +382 -0
- package/dist/src/commands/pipeline.js +153 -0
- package/dist/src/commands/plan/display.js +216 -0
- package/dist/src/commands/plan/index.js +525 -0
- package/dist/src/commands/plugin.js +325 -0
- package/dist/src/commands/preview.js +356 -0
- package/dist/src/commands/profile.js +297 -0
- package/dist/src/commands/questionnaire.js +1021 -0
- package/dist/src/commands/resume.js +35 -0
- package/dist/src/commands/rollback.js +259 -0
- package/dist/src/commands/rollout.js +74 -0
- package/dist/src/commands/runbook.js +307 -0
- package/dist/src/commands/schedule.js +202 -0
- package/dist/src/commands/status.js +213 -0
- package/dist/src/commands/team/index.js +309 -0
- package/dist/src/commands/team-context.js +200 -0
- package/dist/src/commands/template.js +204 -0
- package/dist/src/commands/tf/index.js +989 -0
- package/dist/src/commands/upgrade.js +515 -0
- package/dist/src/commands/usage/index.js +118 -0
- package/dist/src/commands/version.js +145 -0
- package/dist/src/commands/watch.js +127 -0
- package/dist/src/compat/index.js +2 -0
- package/dist/src/compat/runtime.js +10 -0
- package/dist/src/compat/sqlite.js +144 -0
- package/dist/src/config/index.js +6 -0
- package/dist/src/config/manager.js +469 -0
- package/dist/src/config/mode-store.js +57 -0
- package/dist/src/config/profiles.js +66 -0
- package/dist/src/config/safety-policy.js +251 -0
- package/dist/src/config/schema.js +107 -0
- package/dist/src/config/types.js +311 -0
- package/dist/src/config/workspace-state.js +38 -0
- package/dist/src/context/context-db.js +138 -0
- package/dist/src/demo/index.js +295 -0
- package/dist/src/demo/scenarios/full-journey.js +226 -0
- package/dist/src/demo/scenarios/getting-started.js +124 -0
- package/dist/src/demo/scenarios/helm-release.js +334 -0
- package/dist/src/demo/scenarios/k8s-deployment.js +190 -0
- package/dist/src/demo/scenarios/terraform-vpc.js +167 -0
- package/dist/src/demo/types.js +6 -0
- package/dist/src/engine/cost-estimator.js +334 -0
- package/dist/src/engine/diagram-generator.js +192 -0
- package/dist/src/engine/drift-detector.js +688 -0
- package/dist/src/engine/executor.js +832 -0
- package/dist/src/engine/index.js +39 -0
- package/dist/src/engine/orchestrator.js +436 -0
- package/dist/src/engine/planner.js +616 -0
- package/dist/src/engine/safety.js +609 -0
- package/dist/src/engine/verifier.js +664 -0
- package/dist/src/enterprise/audit.js +241 -0
- package/dist/src/enterprise/auth.js +189 -0
- package/dist/src/enterprise/billing.js +512 -0
- package/dist/src/enterprise/index.js +16 -0
- package/dist/src/enterprise/teams.js +315 -0
- package/dist/src/generator/best-practices.js +1375 -0
- package/dist/src/generator/helm.js +495 -0
- package/dist/src/generator/index.js +11 -0
- package/dist/src/generator/intent-parser.js +420 -0
- package/dist/src/generator/kubernetes.js +773 -0
- package/dist/src/generator/terraform.js +1472 -0
- package/dist/src/history/index.js +6 -0
- package/dist/src/history/manager.js +199 -0
- package/dist/src/history/types.js +6 -0
- package/dist/src/hooks/config.js +318 -0
- package/dist/src/hooks/engine.js +317 -0
- package/dist/src/hooks/index.js +2 -0
- package/dist/src/llm/auth-bridge.js +157 -0
- package/dist/src/llm/circuit-breaker.js +116 -0
- package/dist/src/llm/config-loader.js +172 -0
- package/dist/src/llm/cost-calculator.js +137 -0
- package/dist/src/llm/index.js +7 -0
- package/dist/src/llm/model-aliases.js +99 -0
- package/dist/src/llm/provider-registry.js +57 -0
- package/dist/src/llm/providers/anthropic.js +430 -0
- package/dist/src/llm/providers/bedrock.js +409 -0
- package/dist/src/llm/providers/google.js +344 -0
- package/dist/src/llm/providers/ollama.js +661 -0
- package/dist/src/llm/providers/openai-compatible.js +289 -0
- package/dist/src/llm/providers/openai.js +284 -0
- package/dist/src/llm/providers/openrouter.js +293 -0
- package/dist/src/llm/router.js +844 -0
- package/dist/src/llm/types.js +69 -0
- package/dist/src/lsp/client.js +239 -0
- package/dist/src/lsp/languages.js +95 -0
- package/dist/src/lsp/manager.js +243 -0
- package/dist/src/mcp/client.js +289 -0
- package/dist/src/mcp/index.js +5 -0
- package/dist/src/mcp/manager.js +113 -0
- package/dist/src/nimbus.js +212 -0
- package/dist/src/plugins/index.js +13 -0
- package/dist/src/plugins/loader.js +280 -0
- package/dist/src/plugins/manager.js +282 -0
- package/dist/src/plugins/types.js +23 -0
- package/dist/src/scanners/cicd-scanner.js +230 -0
- package/dist/src/scanners/cloud-scanner.js +415 -0
- package/dist/src/scanners/framework-scanner.js +430 -0
- package/dist/src/scanners/iac-scanner.js +350 -0
- package/dist/src/scanners/index.js +454 -0
- package/dist/src/scanners/language-scanner.js +258 -0
- package/dist/src/scanners/package-manager-scanner.js +252 -0
- package/dist/src/scanners/types.js +6 -0
- package/dist/src/sessions/manager.js +395 -0
- package/dist/src/sessions/types.js +4 -0
- package/dist/src/sharing/sync.js +238 -0
- package/dist/src/sharing/viewer.js +131 -0
- package/dist/src/snapshots/index.js +1 -0
- package/dist/src/snapshots/manager.js +432 -0
- package/dist/src/state/artifacts.js +94 -0
- package/dist/src/state/audit.js +73 -0
- package/dist/src/state/billing.js +126 -0
- package/dist/src/state/checkpoints.js +81 -0
- package/dist/src/state/config.js +58 -0
- package/dist/src/state/conversations.js +7 -0
- package/dist/src/state/credentials.js +96 -0
- package/dist/src/state/db.js +53 -0
- package/dist/src/state/index.js +23 -0
- package/dist/src/state/messages.js +76 -0
- package/dist/src/state/projects.js +92 -0
- package/dist/src/state/schema.js +233 -0
- package/dist/src/state/sessions.js +79 -0
- package/dist/src/state/teams.js +131 -0
- package/dist/src/telemetry.js +91 -0
- package/dist/src/tools/aws-ops.js +747 -0
- package/dist/src/tools/azure-ops.js +491 -0
- package/dist/src/tools/file-ops.js +451 -0
- package/dist/src/tools/gcp-ops.js +559 -0
- package/dist/src/tools/git-ops.js +557 -0
- package/dist/src/tools/github-ops.js +460 -0
- package/dist/src/tools/helm-ops.js +634 -0
- package/dist/src/tools/index.js +16 -0
- package/dist/src/tools/k8s-ops.js +579 -0
- package/dist/src/tools/schemas/converter.js +129 -0
- package/dist/src/tools/schemas/devops.js +3319 -0
- package/dist/src/tools/schemas/index.js +19 -0
- package/dist/src/tools/schemas/standard.js +966 -0
- package/dist/src/tools/schemas/types.js +409 -0
- package/dist/src/tools/spawn-exec.js +109 -0
- package/dist/src/tools/terraform-ops.js +627 -0
- package/dist/src/types/config.js +1 -0
- package/dist/src/types/drift.js +4 -0
- package/dist/src/types/enterprise.js +5 -0
- package/dist/src/types/index.js +14 -0
- package/dist/src/types/plan.js +1 -0
- package/dist/src/types/request.js +1 -0
- package/dist/src/types/response.js +1 -0
- package/dist/src/types/service.js +1 -0
- package/dist/src/ui/App.js +1672 -0
- package/dist/src/ui/DeployPreview.js +60 -0
- package/dist/src/ui/FileDiffModal.js +108 -0
- package/dist/src/ui/Header.js +46 -0
- package/dist/src/ui/HelpModal.js +9 -0
- package/dist/src/ui/InputBox.js +408 -0
- package/dist/src/ui/MessageList.js +795 -0
- package/dist/src/ui/PermissionPrompt.js +72 -0
- package/dist/src/ui/StatusBar.js +109 -0
- package/dist/src/ui/TerminalPane.js +31 -0
- package/dist/src/ui/ToolCallDisplay.js +303 -0
- package/dist/src/ui/TreePane.js +83 -0
- package/dist/src/ui/chat-ui.js +721 -0
- package/dist/src/ui/index.js +11 -0
- package/dist/src/ui/ink/index.js +1325 -0
- package/dist/src/ui/streaming.js +137 -0
- package/dist/src/ui/theme.js +78 -0
- package/dist/src/ui/types.js +7 -0
- package/dist/src/utils/analytics.js +61 -0
- package/dist/src/utils/cost-warning.js +25 -0
- package/dist/src/utils/env.js +42 -0
- package/dist/src/utils/errors.js +54 -0
- package/dist/src/utils/event-bus.js +22 -0
- package/dist/src/utils/index.js +16 -0
- package/dist/src/utils/logger.js +150 -0
- package/dist/src/utils/rate-limiter.js +90 -0
- package/dist/src/utils/service-auth.js +36 -0
- package/dist/src/utils/validation.js +39 -0
- package/dist/src/version.js +3 -0
- package/dist/src/watcher/index.js +192 -0
- package/dist/src/wizard/approval.js +275 -0
- package/dist/src/wizard/index.js +13 -0
- package/dist/src/wizard/prompts.js +273 -0
- package/dist/src/wizard/types.js +4 -0
- package/dist/src/wizard/ui.js +453 -0
- package/dist/src/wizard/wizard.js +227 -0
- package/package.json +31 -23
- package/src/__tests__/alias.test.ts +133 -0
- package/src/__tests__/app.test.ts +1 -1
- package/src/__tests__/audit.test.ts +1 -1
- package/src/__tests__/circuit-breaker.test.ts +1 -1
- package/src/__tests__/cli-run.test.ts +237 -1
- package/src/__tests__/compat-sqlite.test.ts +68 -0
- package/src/__tests__/context-manager.test.ts +131 -1
- package/src/__tests__/context.test.ts +1 -1
- package/src/__tests__/devops-terminal-gaps.test.ts +718 -0
- package/src/__tests__/doctor.test.ts +48 -0
- package/src/__tests__/enterprise.test.ts +1 -1
- package/src/__tests__/export.test.ts +236 -0
- package/src/__tests__/gap-11-18-20.test.ts +958 -0
- package/src/__tests__/generator.test.ts +1 -1
- package/src/__tests__/helm-streaming.test.ts +127 -0
- package/src/__tests__/hooks.test.ts +1 -1
- package/src/__tests__/incident.test.ts +179 -0
- package/src/__tests__/init.test.ts +55 -4
- package/src/__tests__/intent-parser.test.ts +1 -1
- package/src/__tests__/llm-router.test.ts +1 -1
- package/src/__tests__/logs.test.ts +107 -0
- package/src/__tests__/loop-errors.test.ts +244 -0
- package/src/__tests__/lsp.test.ts +1 -1
- package/src/__tests__/modes.test.ts +1 -1
- package/src/__tests__/perf-optimizations.test.ts +847 -0
- package/src/__tests__/permissions.test.ts +1 -1
- package/src/__tests__/pipeline.test.ts +50 -0
- package/src/__tests__/polish-phase3.test.ts +340 -0
- package/src/__tests__/profile.test.ts +237 -0
- package/src/__tests__/rollback.test.ts +83 -0
- package/src/__tests__/runbook.test.ts +219 -0
- package/src/__tests__/schedule.test.ts +206 -0
- package/src/__tests__/serve.test.ts +1 -1
- package/src/__tests__/sessions.test.ts +96 -1
- package/src/__tests__/sharing.test.ts +53 -1
- package/src/__tests__/snapshots.test.ts +1 -1
- package/src/__tests__/standalone-migration.test.ts +199 -0
- package/src/__tests__/state-db.test.ts +1 -1
- package/src/__tests__/status.test.ts +158 -0
- package/src/__tests__/stream-with-tools.test.ts +71 -25
- package/src/__tests__/subagents.test.ts +1 -1
- package/src/__tests__/system-prompt.test.ts +82 -3
- package/src/__tests__/terminal-gap-v2.test.ts +395 -0
- package/src/__tests__/terminal-parity.test.ts +393 -0
- package/src/__tests__/tf-apply.test.ts +187 -0
- package/src/__tests__/tool-converter.test.ts +1 -1
- package/src/__tests__/tool-schemas.test.ts +209 -4
- package/src/__tests__/tools.test.ts +4 -3
- package/src/__tests__/version-json.test.ts +184 -0
- package/src/__tests__/version.test.ts +1 -1
- package/src/__tests__/watch.test.ts +129 -0
- package/src/agent/compaction-agent.ts +40 -1
- package/src/agent/context-manager.ts +67 -3
- package/src/agent/deploy-preview.ts +62 -1
- package/src/agent/expand-files.ts +108 -0
- package/src/agent/loop.ts +1312 -31
- package/src/agent/permissions.ts +51 -4
- package/src/agent/system-prompt.ts +573 -19
- package/src/app.ts +58 -0
- package/src/audit/security-scanner.ts +45 -0
- package/src/auth/keychain.ts +82 -0
- package/src/auth/oauth.ts +15 -5
- package/src/cli/init.ts +378 -5
- package/src/cli/run.ts +407 -16
- package/src/cli/serve.ts +78 -1
- package/src/cli/web.ts +10 -6
- package/src/cli.ts +312 -1
- package/src/clients/service-discovery.ts +30 -25
- package/src/commands/alias.ts +100 -0
- package/src/commands/audit/index.ts +121 -2
- package/src/commands/auth-cloud.ts +113 -0
- package/src/commands/auth-refresh.ts +187 -0
- package/src/commands/aws-discover.ts +144 -251
- package/src/commands/aws-terraform.ts +68 -118
- package/src/commands/chat.ts +9 -3
- package/src/commands/completions.ts +268 -0
- package/src/commands/config.ts +26 -0
- package/src/commands/cost/index.ts +218 -2
- package/src/commands/deploy.ts +260 -0
- package/src/commands/doctor.ts +744 -152
- package/src/commands/drift/index.ts +371 -23
- package/src/commands/export.ts +146 -0
- package/src/commands/generate-k8s.ts +9 -61
- package/src/commands/generate-terraform.ts +191 -449
- package/src/commands/help.ts +212 -36
- package/src/commands/history.ts +8 -1
- package/src/commands/incident.ts +166 -0
- package/src/commands/init.ts +5 -0
- package/src/commands/login.ts +86 -1
- package/src/commands/logs.ts +167 -0
- package/src/commands/onboarding.ts +211 -34
- package/src/commands/pipeline.ts +186 -0
- package/src/commands/plugin.ts +398 -0
- package/src/commands/profile.ts +342 -0
- package/src/commands/questionnaire.ts +0 -98
- package/src/commands/resume.ts +26 -34
- package/src/commands/rollback.ts +315 -0
- package/src/commands/rollout.ts +88 -0
- package/src/commands/runbook.ts +346 -0
- package/src/commands/schedule.ts +236 -0
- package/src/commands/status.ts +252 -0
- package/src/commands/team-context.ts +220 -0
- package/src/commands/template.ts +58 -57
- package/src/commands/tf/index.ts +70 -11
- package/src/commands/upgrade.ts +57 -0
- package/src/commands/version.ts +54 -50
- package/src/commands/watch.ts +153 -0
- package/src/compat/runtime.ts +1 -1
- package/src/compat/sqlite.ts +75 -5
- package/src/config/mode-store.ts +62 -0
- package/src/config/profiles.ts +84 -0
- package/src/config/types.ts +83 -1
- package/src/config/workspace-state.ts +53 -0
- package/src/engine/cost-estimator.ts +52 -10
- package/src/engine/executor.ts +33 -2
- package/src/engine/planner.ts +68 -1
- package/src/generator/terraform.ts +8 -0
- package/src/history/manager.ts +2 -74
- package/src/hooks/engine.ts +5 -4
- package/src/llm/cost-calculator.ts +2 -2
- package/src/llm/providers/anthropic.ts +50 -21
- package/src/llm/router.ts +76 -7
- package/src/lsp/languages.ts +3 -0
- package/src/lsp/manager.ts +21 -5
- package/src/nimbus.ts +37 -18
- package/src/sessions/manager.ts +108 -1
- package/src/sharing/sync.ts +4 -0
- package/src/sharing/viewer.ts +66 -0
- package/src/tools/file-ops.ts +22 -0
- package/src/tools/schemas/devops.ts +3007 -117
- package/src/tools/schemas/standard.ts +5 -1
- package/src/tools/schemas/types.ts +31 -1
- package/src/tools/spawn-exec.ts +148 -0
- package/src/ui/App.tsx +1183 -66
- package/src/ui/DeployPreview.tsx +62 -57
- package/src/ui/FileDiffModal.tsx +162 -0
- package/src/ui/Header.tsx +87 -24
- package/src/ui/HelpModal.tsx +57 -0
- package/src/ui/InputBox.tsx +163 -10
- package/src/ui/MessageList.tsx +487 -40
- package/src/ui/PermissionPrompt.tsx +17 -5
- package/src/ui/StatusBar.tsx +122 -3
- package/src/ui/TerminalPane.tsx +84 -0
- package/src/ui/ToolCallDisplay.tsx +252 -18
- package/src/ui/TreePane.tsx +132 -0
- package/src/ui/chat-ui.ts +41 -44
- package/src/ui/ink/index.ts +771 -38
- package/src/ui/streaming.ts +1 -1
- package/src/ui/theme.ts +104 -0
- package/src/ui/types.ts +18 -0
- package/src/version.ts +1 -1
- package/src/watcher/index.ts +66 -15
- package/src/wizard/types.ts +1 -0
- package/src/wizard/ui.ts +1 -1
- package/tsconfig.json +2 -2
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safety Policy Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines safety policies for infrastructure operations
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
/**
|
|
9
|
+
* Default safety policy
|
|
10
|
+
*/
|
|
11
|
+
export const defaultSafetyPolicy = {
|
|
12
|
+
alwaysRequireApproval: ['destroy', 'delete', 'terminate', 'update', 'apply', 'create'],
|
|
13
|
+
protectedEnvironments: ['production', 'prod', 'prd', 'live', 'main', 'master'],
|
|
14
|
+
costThreshold: 500,
|
|
15
|
+
skipSafetyFor: ['plan', 'validate', 'show', 'list', 'get', 'describe', 'logs', 'status'],
|
|
16
|
+
customRules: [],
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Load safety policy from config file or use defaults
|
|
20
|
+
*/
|
|
21
|
+
export function loadSafetyPolicy(configPath) {
|
|
22
|
+
// Try to load from workspace config
|
|
23
|
+
const nimbusDir = path.join(process.cwd(), '.nimbus');
|
|
24
|
+
const configFile = configPath || path.join(nimbusDir, 'config.yaml');
|
|
25
|
+
if (fs.existsSync(configFile)) {
|
|
26
|
+
try {
|
|
27
|
+
const content = fs.readFileSync(configFile, 'utf-8');
|
|
28
|
+
const policy = parseSafetyConfig(content);
|
|
29
|
+
if (policy) {
|
|
30
|
+
return { ...defaultSafetyPolicy, ...policy };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Use defaults
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return defaultSafetyPolicy;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parse safety config from YAML content
|
|
41
|
+
*/
|
|
42
|
+
function parseSafetyConfig(content) {
|
|
43
|
+
// Simple YAML parsing for safety section
|
|
44
|
+
const safetyMatch = content.match(/safety:\s*\n((?:[ \t]+.+\n?)*)/);
|
|
45
|
+
if (!safetyMatch) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const safetySection = safetyMatch[1];
|
|
49
|
+
const policy = {};
|
|
50
|
+
// Parse requireApproval
|
|
51
|
+
const approvalMatch = safetySection.match(/requireApproval:\s*(true|false)/);
|
|
52
|
+
if (approvalMatch) {
|
|
53
|
+
if (approvalMatch[1] === 'false') {
|
|
54
|
+
policy.alwaysRequireApproval = [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Parse protectedEnvironments
|
|
58
|
+
const envMatch = safetySection.match(/protectedEnvironments:\s*\[([^\]]+)\]/);
|
|
59
|
+
if (envMatch) {
|
|
60
|
+
policy.protectedEnvironments = envMatch[1].split(',').map(s => s.trim().replace(/['"]/g, ''));
|
|
61
|
+
}
|
|
62
|
+
// Parse costThreshold
|
|
63
|
+
const costMatch = safetySection.match(/costThreshold:\s*(\d+)/);
|
|
64
|
+
if (costMatch) {
|
|
65
|
+
policy.costThreshold = parseInt(costMatch[1], 10);
|
|
66
|
+
}
|
|
67
|
+
return policy;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check if an operation requires safety checks
|
|
71
|
+
*/
|
|
72
|
+
export function requiresSafetyCheck(operation, policy = defaultSafetyPolicy) {
|
|
73
|
+
const normalizedOp = operation.toLowerCase();
|
|
74
|
+
return !policy.skipSafetyFor.some(skip => normalizedOp.includes(skip.toLowerCase()));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if an operation requires approval
|
|
78
|
+
*/
|
|
79
|
+
export function requiresApproval(operation, context, policy = defaultSafetyPolicy) {
|
|
80
|
+
const normalizedOp = operation.toLowerCase();
|
|
81
|
+
// Check if operation is in always require list
|
|
82
|
+
if (policy.alwaysRequireApproval.some(op => normalizedOp.includes(op.toLowerCase()))) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
// Check if environment is protected
|
|
86
|
+
if (context.environment) {
|
|
87
|
+
const normalizedEnv = context.environment.toLowerCase();
|
|
88
|
+
if (policy.protectedEnvironments.some(env => normalizedEnv.includes(env.toLowerCase()))) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Check cost threshold
|
|
93
|
+
if (context.estimatedCost && context.estimatedCost > policy.costThreshold) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Evaluate safety for an operation
|
|
100
|
+
*/
|
|
101
|
+
export function evaluateSafety(context, policy = defaultSafetyPolicy) {
|
|
102
|
+
const risks = [];
|
|
103
|
+
const blockers = [];
|
|
104
|
+
let requiresApprovalFlag = false;
|
|
105
|
+
// Check for destroy/delete operations
|
|
106
|
+
if (['destroy', 'delete', 'terminate'].some(op => context.operation.toLowerCase().includes(op))) {
|
|
107
|
+
const risk = {
|
|
108
|
+
id: 'destructive-operation',
|
|
109
|
+
severity: 'critical',
|
|
110
|
+
message: `Destructive operation: ${context.operation}`,
|
|
111
|
+
canProceed: true,
|
|
112
|
+
requiresApproval: true,
|
|
113
|
+
};
|
|
114
|
+
risks.push(risk);
|
|
115
|
+
requiresApprovalFlag = true;
|
|
116
|
+
}
|
|
117
|
+
// Check for protected environment
|
|
118
|
+
if (context.environment) {
|
|
119
|
+
const normalizedEnv = context.environment.toLowerCase();
|
|
120
|
+
if (policy.protectedEnvironments.some(env => normalizedEnv.includes(env.toLowerCase()))) {
|
|
121
|
+
const risk = {
|
|
122
|
+
id: 'protected-environment',
|
|
123
|
+
severity: 'high',
|
|
124
|
+
message: `Operating on protected environment: ${context.environment}`,
|
|
125
|
+
canProceed: true,
|
|
126
|
+
requiresApproval: true,
|
|
127
|
+
};
|
|
128
|
+
risks.push(risk);
|
|
129
|
+
requiresApprovalFlag = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Check cost threshold
|
|
133
|
+
if (context.estimatedCost && context.estimatedCost > policy.costThreshold) {
|
|
134
|
+
const risk = {
|
|
135
|
+
id: 'high-cost',
|
|
136
|
+
severity: 'high',
|
|
137
|
+
message: `Estimated cost $${context.estimatedCost} exceeds threshold $${policy.costThreshold}`,
|
|
138
|
+
details: {
|
|
139
|
+
estimatedCost: context.estimatedCost,
|
|
140
|
+
threshold: policy.costThreshold,
|
|
141
|
+
},
|
|
142
|
+
canProceed: true,
|
|
143
|
+
requiresApproval: true,
|
|
144
|
+
};
|
|
145
|
+
risks.push(risk);
|
|
146
|
+
requiresApprovalFlag = true;
|
|
147
|
+
}
|
|
148
|
+
// Check for mutations in apply
|
|
149
|
+
if (context.operation.toLowerCase().includes('apply')) {
|
|
150
|
+
const risk = {
|
|
151
|
+
id: 'mutation-operation',
|
|
152
|
+
severity: 'medium',
|
|
153
|
+
message: 'This operation will modify infrastructure',
|
|
154
|
+
canProceed: true,
|
|
155
|
+
requiresApproval: true,
|
|
156
|
+
};
|
|
157
|
+
risks.push(risk);
|
|
158
|
+
requiresApprovalFlag = true;
|
|
159
|
+
}
|
|
160
|
+
// Check custom rules
|
|
161
|
+
if (policy.customRules) {
|
|
162
|
+
for (const rule of policy.customRules) {
|
|
163
|
+
try {
|
|
164
|
+
if (rule.check(context)) {
|
|
165
|
+
const risk = {
|
|
166
|
+
id: rule.id,
|
|
167
|
+
severity: rule.severity,
|
|
168
|
+
message: rule.message,
|
|
169
|
+
canProceed: rule.severity !== 'critical',
|
|
170
|
+
requiresApproval: rule.severity === 'critical' || rule.severity === 'high',
|
|
171
|
+
};
|
|
172
|
+
if (!risk.canProceed) {
|
|
173
|
+
blockers.push(risk);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
risks.push(risk);
|
|
177
|
+
if (risk.requiresApproval) {
|
|
178
|
+
requiresApprovalFlag = true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// Skip rule on error
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Analyze plan output for resource changes
|
|
189
|
+
if (context.planOutput) {
|
|
190
|
+
const changes = analyzePlanOutput(context.planOutput);
|
|
191
|
+
if (changes.destroy > 0) {
|
|
192
|
+
const risk = {
|
|
193
|
+
id: 'resource-destruction',
|
|
194
|
+
severity: 'high',
|
|
195
|
+
message: `${changes.destroy} resources will be destroyed`,
|
|
196
|
+
details: { count: changes.destroy },
|
|
197
|
+
canProceed: true,
|
|
198
|
+
requiresApproval: true,
|
|
199
|
+
};
|
|
200
|
+
risks.push(risk);
|
|
201
|
+
requiresApprovalFlag = true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
passed: blockers.length === 0,
|
|
206
|
+
risks,
|
|
207
|
+
blockers,
|
|
208
|
+
requiresApproval: requiresApprovalFlag,
|
|
209
|
+
estimatedCost: context.estimatedCost,
|
|
210
|
+
affectedResources: context.resources,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Analyze Terraform plan output for changes
|
|
215
|
+
*/
|
|
216
|
+
function analyzePlanOutput(output) {
|
|
217
|
+
const addMatch = output.match(/(\d+) to add/);
|
|
218
|
+
const changeMatch = output.match(/(\d+) to change/);
|
|
219
|
+
const destroyMatch = output.match(/(\d+) to destroy/);
|
|
220
|
+
return {
|
|
221
|
+
add: addMatch ? parseInt(addMatch[1], 10) : 0,
|
|
222
|
+
change: changeMatch ? parseInt(changeMatch[1], 10) : 0,
|
|
223
|
+
destroy: destroyMatch ? parseInt(destroyMatch[1], 10) : 0,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Format risks for display
|
|
228
|
+
*/
|
|
229
|
+
export function formatRisks(risks) {
|
|
230
|
+
return risks.map(risk => {
|
|
231
|
+
const icon = getSeverityIcon(risk.severity);
|
|
232
|
+
return `${icon} [${risk.severity.toUpperCase()}] ${risk.message}`;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Get icon for severity level
|
|
237
|
+
*/
|
|
238
|
+
function getSeverityIcon(severity) {
|
|
239
|
+
switch (severity) {
|
|
240
|
+
case 'critical':
|
|
241
|
+
return '🔴';
|
|
242
|
+
case 'high':
|
|
243
|
+
return '🟠';
|
|
244
|
+
case 'medium':
|
|
245
|
+
return '🟡';
|
|
246
|
+
case 'low':
|
|
247
|
+
return '🔵';
|
|
248
|
+
default:
|
|
249
|
+
return '⚪';
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod Config Schema
|
|
3
|
+
*
|
|
4
|
+
* Validates NimbusConfig at load time and on set() operations.
|
|
5
|
+
* Uses safeParse to gracefully handle invalid configs without crashing.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
export const WorkspaceConfigSchema = z.object({
|
|
9
|
+
defaultProvider: z.string().optional(),
|
|
10
|
+
outputDirectory: z.string().optional(),
|
|
11
|
+
name: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
export const CostOptimizationConfigSchema = z.object({
|
|
14
|
+
enabled: z.boolean().optional(),
|
|
15
|
+
cheap_model: z.string().optional(),
|
|
16
|
+
expensive_model: z.string().optional(),
|
|
17
|
+
// A5/A6: task-category routing arrays
|
|
18
|
+
use_cheap_model_for: z.array(z.string()).optional(),
|
|
19
|
+
use_expensive_model_for: z.array(z.string()).optional(),
|
|
20
|
+
});
|
|
21
|
+
// A3/A4: per-provider configuration map entry
|
|
22
|
+
export const ProviderConfigSchema = z.object({
|
|
23
|
+
api_key: z.string().optional(),
|
|
24
|
+
base_url: z.string().url().optional(),
|
|
25
|
+
models: z.array(z.string()).optional(),
|
|
26
|
+
});
|
|
27
|
+
// A7/A8: provider fallback configuration
|
|
28
|
+
export const FallbackConfigSchema = z.object({
|
|
29
|
+
enabled: z.boolean().optional(),
|
|
30
|
+
providers: z.array(z.string()).optional(),
|
|
31
|
+
});
|
|
32
|
+
export const LLMConfigSchema = z.object({
|
|
33
|
+
defaultModel: z.string().optional(),
|
|
34
|
+
// A2: explicit default provider name
|
|
35
|
+
default_provider: z.string().optional(),
|
|
36
|
+
temperature: z.number().min(0).max(1).optional(),
|
|
37
|
+
maxTokens: z.number().positive().optional(),
|
|
38
|
+
cost_optimization: CostOptimizationConfigSchema.optional(),
|
|
39
|
+
// A3/A4: per-provider configuration keyed by provider name
|
|
40
|
+
providers: z.record(z.string(), ProviderConfigSchema).optional(),
|
|
41
|
+
// A7/A8: fallback provider chain
|
|
42
|
+
fallback: FallbackConfigSchema.optional(),
|
|
43
|
+
});
|
|
44
|
+
export const HistoryConfigSchema = z.object({
|
|
45
|
+
maxEntries: z.number().positive().optional(),
|
|
46
|
+
enabled: z.boolean().optional(),
|
|
47
|
+
});
|
|
48
|
+
export const AutoApproveConfigSchema = z.object({
|
|
49
|
+
read: z.boolean().optional(),
|
|
50
|
+
generate: z.boolean().optional(),
|
|
51
|
+
create: z.boolean().optional(),
|
|
52
|
+
update: z.boolean().optional(),
|
|
53
|
+
delete: z.boolean().optional(),
|
|
54
|
+
});
|
|
55
|
+
export const SafetyConfigSchema = z.object({
|
|
56
|
+
requireConfirmation: z.boolean().optional(),
|
|
57
|
+
dryRunByDefault: z.boolean().optional(),
|
|
58
|
+
auto_approve: AutoApproveConfigSchema.optional(),
|
|
59
|
+
});
|
|
60
|
+
export const UIConfigSchema = z.object({
|
|
61
|
+
theme: z.enum(['dark', 'light', 'auto']).optional(),
|
|
62
|
+
colors: z.boolean().optional(),
|
|
63
|
+
spinner: z.enum(['dots', 'line', 'simple']).optional(),
|
|
64
|
+
});
|
|
65
|
+
export const PersonaConfigSchema = z.object({
|
|
66
|
+
// A9: added 'custom' to the mode enum
|
|
67
|
+
mode: z
|
|
68
|
+
.enum(['professional', 'assistant', 'expert', 'standard', 'concise', 'detailed', 'custom'])
|
|
69
|
+
.optional(),
|
|
70
|
+
verbosity: z.enum(['minimal', 'normal', 'detailed', 'verbose']).optional(),
|
|
71
|
+
custom: z.string().optional(),
|
|
72
|
+
});
|
|
73
|
+
export const CloudProviderConfigSchema = z.object({
|
|
74
|
+
default_region: z.string().optional(),
|
|
75
|
+
default_profile: z.string().optional(),
|
|
76
|
+
default_project: z.string().optional(),
|
|
77
|
+
default_subscription: z.string().optional(),
|
|
78
|
+
});
|
|
79
|
+
export const CloudConfigSchema = z.object({
|
|
80
|
+
default_provider: z.enum(['aws', 'gcp', 'azure']).optional(),
|
|
81
|
+
aws: CloudProviderConfigSchema.optional(),
|
|
82
|
+
gcp: CloudProviderConfigSchema.optional(),
|
|
83
|
+
azure: CloudProviderConfigSchema.optional(),
|
|
84
|
+
});
|
|
85
|
+
export const TerraformDefaultsSchema = z.object({
|
|
86
|
+
default_backend: z.enum(['s3', 'gcs', 'azurerm', 'local']).optional(),
|
|
87
|
+
state_bucket: z.string().optional(),
|
|
88
|
+
lock_table: z.string().optional(),
|
|
89
|
+
});
|
|
90
|
+
export const KubernetesDefaultsSchema = z.object({
|
|
91
|
+
default_context: z.string().optional(),
|
|
92
|
+
default_namespace: z.string().optional(),
|
|
93
|
+
});
|
|
94
|
+
export const NimbusConfigSchema = z.object({
|
|
95
|
+
version: z.number().optional(),
|
|
96
|
+
// A1: opt-in/out of anonymous telemetry
|
|
97
|
+
telemetry: z.boolean().optional(),
|
|
98
|
+
workspace: WorkspaceConfigSchema.optional(),
|
|
99
|
+
llm: LLMConfigSchema.optional(),
|
|
100
|
+
history: HistoryConfigSchema.optional(),
|
|
101
|
+
safety: SafetyConfigSchema.optional(),
|
|
102
|
+
ui: UIConfigSchema.optional(),
|
|
103
|
+
persona: PersonaConfigSchema.optional(),
|
|
104
|
+
cloud: CloudConfigSchema.optional(),
|
|
105
|
+
terraform: TerraformDefaultsSchema.optional(),
|
|
106
|
+
kubernetes: KubernetesDefaultsSchema.optional(),
|
|
107
|
+
});
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for Nimbus CLI configuration
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Registry of all config keys
|
|
8
|
+
*/
|
|
9
|
+
export const CONFIG_KEYS = [
|
|
10
|
+
{
|
|
11
|
+
key: 'workspace.defaultProvider',
|
|
12
|
+
description: 'Default cloud provider (aws, gcp, azure)',
|
|
13
|
+
type: 'string',
|
|
14
|
+
defaultValue: 'aws',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: 'workspace.outputDirectory',
|
|
18
|
+
description: 'Output directory for generated code',
|
|
19
|
+
type: 'string',
|
|
20
|
+
defaultValue: './infrastructure',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'workspace.name',
|
|
24
|
+
description: 'Project name',
|
|
25
|
+
type: 'string',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: 'llm.defaultModel',
|
|
29
|
+
description: 'Default LLM model to use',
|
|
30
|
+
type: 'string',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: 'llm.temperature',
|
|
34
|
+
description: 'Temperature for LLM generation (0-1)',
|
|
35
|
+
type: 'number',
|
|
36
|
+
defaultValue: 0.7,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: 'llm.maxTokens',
|
|
40
|
+
description: 'Maximum tokens for LLM response',
|
|
41
|
+
type: 'number',
|
|
42
|
+
defaultValue: 4096,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
key: 'history.maxEntries',
|
|
46
|
+
description: 'Maximum history entries to keep',
|
|
47
|
+
type: 'number',
|
|
48
|
+
defaultValue: 100,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
key: 'history.enabled',
|
|
52
|
+
description: 'Enable command history',
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
defaultValue: true,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: 'safety.requireConfirmation',
|
|
58
|
+
description: 'Require confirmation for destructive operations',
|
|
59
|
+
type: 'boolean',
|
|
60
|
+
defaultValue: true,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
key: 'safety.dryRunByDefault',
|
|
64
|
+
description: 'Enable dry-run mode by default',
|
|
65
|
+
type: 'boolean',
|
|
66
|
+
defaultValue: false,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
key: 'safety.auto_approve.read',
|
|
70
|
+
description: 'Auto-approve read operations (list, get, describe)',
|
|
71
|
+
type: 'boolean',
|
|
72
|
+
defaultValue: true,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
key: 'safety.auto_approve.generate',
|
|
76
|
+
description: 'Auto-approve generate operations (IaC generation)',
|
|
77
|
+
type: 'boolean',
|
|
78
|
+
defaultValue: true,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: 'safety.auto_approve.create',
|
|
82
|
+
description: 'Auto-approve create operations (apply, install)',
|
|
83
|
+
type: 'boolean',
|
|
84
|
+
defaultValue: false,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
key: 'safety.auto_approve.update',
|
|
88
|
+
description: 'Auto-approve update operations (upgrade, scale)',
|
|
89
|
+
type: 'boolean',
|
|
90
|
+
defaultValue: false,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
key: 'safety.auto_approve.delete',
|
|
94
|
+
description: 'Auto-approve delete operations (delete, destroy, uninstall)',
|
|
95
|
+
type: 'boolean',
|
|
96
|
+
defaultValue: false,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
key: 'ui.theme',
|
|
100
|
+
description: 'Color theme (dark, light, auto)',
|
|
101
|
+
type: 'string',
|
|
102
|
+
defaultValue: 'auto',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: 'ui.colors',
|
|
106
|
+
description: 'Enable colors in output',
|
|
107
|
+
type: 'boolean',
|
|
108
|
+
defaultValue: true,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
key: 'ui.spinner',
|
|
112
|
+
description: 'Spinner style (dots, line, simple)',
|
|
113
|
+
type: 'string',
|
|
114
|
+
defaultValue: 'dots',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
key: 'persona.mode',
|
|
118
|
+
description: 'AI persona mode (standard, concise, detailed, expert)',
|
|
119
|
+
type: 'string',
|
|
120
|
+
defaultValue: 'standard',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
key: 'persona.verbosity',
|
|
124
|
+
description: 'Response verbosity level (minimal, normal, verbose)',
|
|
125
|
+
type: 'string',
|
|
126
|
+
defaultValue: 'normal',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
key: 'persona.custom',
|
|
130
|
+
description: 'Custom persona prompt override',
|
|
131
|
+
type: 'string',
|
|
132
|
+
defaultValue: '',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: 'cloud.default_provider',
|
|
136
|
+
description: 'Default cloud provider (aws, gcp, azure)',
|
|
137
|
+
type: 'string',
|
|
138
|
+
defaultValue: 'aws',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
key: 'cloud.aws.default_region',
|
|
142
|
+
description: 'Default AWS region',
|
|
143
|
+
type: 'string',
|
|
144
|
+
defaultValue: 'us-east-1',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: 'cloud.aws.default_profile',
|
|
148
|
+
description: 'Default AWS CLI profile',
|
|
149
|
+
type: 'string',
|
|
150
|
+
defaultValue: 'default',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
key: 'cloud.gcp.default_region',
|
|
154
|
+
description: 'Default GCP region',
|
|
155
|
+
type: 'string',
|
|
156
|
+
defaultValue: 'us-central1',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
key: 'cloud.gcp.default_project',
|
|
160
|
+
description: 'Default GCP project ID',
|
|
161
|
+
type: 'string',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
key: 'cloud.azure.default_region',
|
|
165
|
+
description: 'Default Azure region',
|
|
166
|
+
type: 'string',
|
|
167
|
+
defaultValue: 'eastus',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
key: 'cloud.azure.default_subscription',
|
|
171
|
+
description: 'Default Azure subscription ID',
|
|
172
|
+
type: 'string',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
key: 'terraform.default_backend',
|
|
176
|
+
description: 'Default Terraform backend (s3, gcs, azurerm, local)',
|
|
177
|
+
type: 'string',
|
|
178
|
+
defaultValue: 's3',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
key: 'terraform.state_bucket',
|
|
182
|
+
description: 'Terraform state bucket name',
|
|
183
|
+
type: 'string',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
key: 'terraform.lock_table',
|
|
187
|
+
description: 'Terraform DynamoDB lock table name',
|
|
188
|
+
type: 'string',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
key: 'kubernetes.default_context',
|
|
192
|
+
description: 'Default kubectl context',
|
|
193
|
+
type: 'string',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
key: 'kubernetes.default_namespace',
|
|
197
|
+
description: 'Default Kubernetes namespace',
|
|
198
|
+
type: 'string',
|
|
199
|
+
defaultValue: 'default',
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
key: 'llm.cost_optimization.enabled',
|
|
203
|
+
description: 'Enable LLM cost optimization routing',
|
|
204
|
+
type: 'boolean',
|
|
205
|
+
defaultValue: false,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
key: 'llm.cost_optimization.cheap_model',
|
|
209
|
+
description: 'Model for simple tasks (summaries, classification)',
|
|
210
|
+
type: 'string',
|
|
211
|
+
defaultValue: 'claude-haiku-4-20250514',
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
key: 'llm.cost_optimization.expensive_model',
|
|
215
|
+
description: 'Model for complex tasks (code generation, reasoning)',
|
|
216
|
+
type: 'string',
|
|
217
|
+
defaultValue: 'claude-sonnet-4-20250514',
|
|
218
|
+
},
|
|
219
|
+
// A1: Telemetry
|
|
220
|
+
{
|
|
221
|
+
key: 'telemetry',
|
|
222
|
+
description: 'Enable anonymous usage statistics and error reporting',
|
|
223
|
+
type: 'boolean',
|
|
224
|
+
defaultValue: true,
|
|
225
|
+
},
|
|
226
|
+
// A2: LLM default provider
|
|
227
|
+
{
|
|
228
|
+
key: 'llm.default_provider',
|
|
229
|
+
description: 'Default LLM provider to use (e.g. anthropic, openai, google)',
|
|
230
|
+
type: 'string',
|
|
231
|
+
},
|
|
232
|
+
// A5: Cost optimization — cheap model task routing
|
|
233
|
+
{
|
|
234
|
+
key: 'llm.cost_optimization.use_cheap_model_for',
|
|
235
|
+
description: 'Task categories that should be routed to the cheap model (JSON array)',
|
|
236
|
+
type: 'string',
|
|
237
|
+
},
|
|
238
|
+
// A6: Cost optimization — expensive model task routing
|
|
239
|
+
{
|
|
240
|
+
key: 'llm.cost_optimization.use_expensive_model_for',
|
|
241
|
+
description: 'Task categories that should be routed to the expensive model (JSON array)',
|
|
242
|
+
type: 'string',
|
|
243
|
+
},
|
|
244
|
+
// A7: Fallback enabled
|
|
245
|
+
{
|
|
246
|
+
key: 'llm.fallback.enabled',
|
|
247
|
+
description: 'Enable automatic fallback to alternative LLM providers on failure',
|
|
248
|
+
type: 'boolean',
|
|
249
|
+
defaultValue: false,
|
|
250
|
+
},
|
|
251
|
+
// A8: Fallback provider list
|
|
252
|
+
{
|
|
253
|
+
key: 'llm.fallback.providers',
|
|
254
|
+
description: 'Ordered list of fallback LLM providers to try on failure (JSON array)',
|
|
255
|
+
type: 'string',
|
|
256
|
+
},
|
|
257
|
+
// M4: Primary cloud providers
|
|
258
|
+
{
|
|
259
|
+
key: 'primaryClouds',
|
|
260
|
+
description: 'Primary cloud providers (comma-separated: aws,gcp,azure)',
|
|
261
|
+
type: 'string',
|
|
262
|
+
},
|
|
263
|
+
// M4: Model override (validated against known model IDs)
|
|
264
|
+
{
|
|
265
|
+
key: 'model',
|
|
266
|
+
description: 'Default model ID (e.g. claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5-20251001)',
|
|
267
|
+
type: 'string',
|
|
268
|
+
},
|
|
269
|
+
// G16: Default cost budget per session
|
|
270
|
+
{
|
|
271
|
+
key: 'defaultCostBudget',
|
|
272
|
+
description: 'Default cost budget in USD per session (e.g. 1.00). 0 means unlimited.',
|
|
273
|
+
type: 'number',
|
|
274
|
+
defaultValue: 0,
|
|
275
|
+
},
|
|
276
|
+
// G21: Configurable agent turn silence timeout
|
|
277
|
+
{
|
|
278
|
+
key: 'agentTurnTimeoutSeconds',
|
|
279
|
+
description: 'Seconds to wait for LLM response before aborting (default: 60)',
|
|
280
|
+
type: 'number',
|
|
281
|
+
defaultValue: 60,
|
|
282
|
+
},
|
|
283
|
+
];
|
|
284
|
+
/**
|
|
285
|
+
* Load per-project configuration from:
|
|
286
|
+
* 1. <cwd>/nimbus.yaml (JSON-parsed, no YAML dep)
|
|
287
|
+
* 2. <cwd>/.nimbus/config.json
|
|
288
|
+
*
|
|
289
|
+
* Returns null if neither file exists or both fail to parse.
|
|
290
|
+
*/
|
|
291
|
+
export function loadProjectConfig(cwd) {
|
|
292
|
+
const { existsSync, readFileSync } = require('node:fs');
|
|
293
|
+
const { join } = require('node:path');
|
|
294
|
+
const candidates = [
|
|
295
|
+
join(cwd, 'nimbus.yaml'),
|
|
296
|
+
join(cwd, '.nimbus', 'config.json'),
|
|
297
|
+
];
|
|
298
|
+
for (const file of candidates) {
|
|
299
|
+
try {
|
|
300
|
+
if (!existsSync(file))
|
|
301
|
+
continue;
|
|
302
|
+
const raw = readFileSync(file, 'utf-8');
|
|
303
|
+
const parsed = JSON.parse(raw);
|
|
304
|
+
return parsed;
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
// Try next candidate
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace state persistence — saves terraform workspace + kubectl context
|
|
3
|
+
* per working directory to ~/.nimbus/workspace-state.json
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
const STATE_PATH = join(homedir(), '.nimbus', 'workspace-state.json');
|
|
9
|
+
function loadStateFile() {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(readFileSync(STATE_PATH, 'utf-8'));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function saveStateFile(state) {
|
|
18
|
+
try {
|
|
19
|
+
mkdirSync(join(homedir(), '.nimbus'), { recursive: true });
|
|
20
|
+
writeFileSync(STATE_PATH, JSON.stringify(state, null, 2), 'utf-8');
|
|
21
|
+
}
|
|
22
|
+
catch { /* non-critical */ }
|
|
23
|
+
}
|
|
24
|
+
export function loadWorkspaceState(cwd) {
|
|
25
|
+
const all = loadStateFile();
|
|
26
|
+
return all[cwd] ?? {};
|
|
27
|
+
}
|
|
28
|
+
export function saveWorkspaceState(cwd, state) {
|
|
29
|
+
const all = loadStateFile();
|
|
30
|
+
all[cwd] = { ...all[cwd], ...state, lastSeen: new Date().toISOString() };
|
|
31
|
+
saveStateFile(all);
|
|
32
|
+
}
|
|
33
|
+
export function mergeWorkspaceState(cwd, infra) {
|
|
34
|
+
const existing = loadWorkspaceState(cwd);
|
|
35
|
+
const merged = { ...existing, ...infra };
|
|
36
|
+
saveWorkspaceState(cwd, merged);
|
|
37
|
+
return merged;
|
|
38
|
+
}
|