@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
|
@@ -75,6 +75,26 @@ export interface SystemPromptOptions {
|
|
|
75
75
|
* focused, scoped execution.
|
|
76
76
|
*/
|
|
77
77
|
readonly activeSubagent?: string;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Live infrastructure context discovered at startup or session resume (Gaps 7 & 10).
|
|
81
|
+
* When provided, a "Current Infrastructure Context" section is appended to the prompt.
|
|
82
|
+
*/
|
|
83
|
+
readonly infraContext?: {
|
|
84
|
+
terraformWorkspace?: string;
|
|
85
|
+
kubectlContext?: string;
|
|
86
|
+
helmReleases?: string[];
|
|
87
|
+
awsAccount?: string;
|
|
88
|
+
awsRegion?: string;
|
|
89
|
+
gcpProject?: string;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* M1: Dry-run mode flag. When true, appends a hard constraint at the end
|
|
94
|
+
* of the system prompt instructing the agent not to execute any mutating
|
|
95
|
+
* operations and to only list what it would do.
|
|
96
|
+
*/
|
|
97
|
+
readonly dryRun?: boolean;
|
|
78
98
|
}
|
|
79
99
|
|
|
80
100
|
// ---------------------------------------------------------------------------
|
|
@@ -114,6 +134,17 @@ export function buildSystemPrompt(options: SystemPromptOptions): string {
|
|
|
114
134
|
// 3. Tool-use guidelines
|
|
115
135
|
parts.push(TOOL_USE_GUIDELINES);
|
|
116
136
|
|
|
137
|
+
// 3b. H4: Task-adaptive DevOps domain knowledge — only inject sections
|
|
138
|
+
// relevant to the tools that are actually available in this session.
|
|
139
|
+
const toolNames = options.tools.map(t => t.name);
|
|
140
|
+
parts.push(getRelevantDomainKnowledge(toolNames));
|
|
141
|
+
|
|
142
|
+
// 3c. DevOps decision heuristics
|
|
143
|
+
// L2: Task-adaptive pruning — include only the heuristic sections relevant to
|
|
144
|
+
// the current mode. In plan mode, deploy-specific rules add noise without value.
|
|
145
|
+
// In build mode, plan-only readonly warnings are redundant.
|
|
146
|
+
parts.push(getPrunedHeuristics(options.mode));
|
|
147
|
+
|
|
117
148
|
// 4. Available tools summary
|
|
118
149
|
const toolsSummary = buildToolsSummary(options.tools);
|
|
119
150
|
if (toolsSummary) {
|
|
@@ -124,6 +155,72 @@ export function buildSystemPrompt(options: SystemPromptOptions): string {
|
|
|
124
155
|
const nimbusContent = options.nimbusInstructions ?? loadNimbusMd(options.cwd);
|
|
125
156
|
if (nimbusContent) {
|
|
126
157
|
parts.push(`# Project Instructions (NIMBUS.md)\n\n${nimbusContent}`);
|
|
158
|
+
|
|
159
|
+
// G14: Extract ## Forbidden section and inject as hard constraints
|
|
160
|
+
const forbiddenRules = extractForbiddenRules(nimbusContent);
|
|
161
|
+
if (forbiddenRules.length > 0) {
|
|
162
|
+
const forbiddenPrompt = [
|
|
163
|
+
'# HARD CONSTRAINTS (from NIMBUS.md ## Forbidden)',
|
|
164
|
+
'The following operations are STRICTLY FORBIDDEN. Never perform them under any circumstances:',
|
|
165
|
+
...forbiddenRules.map(r => `- ${r}`),
|
|
166
|
+
'',
|
|
167
|
+
'If asked to perform a forbidden operation, explain that it is prohibited by project policy.',
|
|
168
|
+
].join('\n');
|
|
169
|
+
parts.push(forbiddenPrompt);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// GAP-22: Parse environments block for protected envs
|
|
173
|
+
if (nimbusContent.includes('## Environments')) {
|
|
174
|
+
const hasProtectedEnv = /\|\s*\S+\s*\|\s*\S+\s*\|\s*\S*\s*\|\s*true\s*\|/i.test(nimbusContent);
|
|
175
|
+
if (hasProtectedEnv) {
|
|
176
|
+
parts.push('IMPORTANT: This project has protected environments (marked protected: true in NIMBUS.md). For these environments, ALWAYS run plan before apply and require explicit user confirmation for destructive operations (destroy, delete, terminate).');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 5b. Infra context (Gaps 7 & 10) — live terraform/k8s/helm context discovered at startup
|
|
182
|
+
if (options.infraContext) {
|
|
183
|
+
const ic = options.infraContext;
|
|
184
|
+
const lines: string[] = ['## Current Infrastructure Context'];
|
|
185
|
+
if (ic.terraformWorkspace) lines.push(`- Terraform workspace: ${ic.terraformWorkspace}`);
|
|
186
|
+
if (ic.kubectlContext) lines.push(`- kubectl context: ${ic.kubectlContext}`);
|
|
187
|
+
if (ic.helmReleases && ic.helmReleases.length > 0) {
|
|
188
|
+
lines.push(`- Active Helm releases: ${ic.helmReleases.slice(0, 5).join(', ')}`);
|
|
189
|
+
}
|
|
190
|
+
if (ic.awsAccount) lines.push(`- AWS account: ${ic.awsAccount}`);
|
|
191
|
+
if (ic.awsRegion) lines.push(`- AWS region: ${ic.awsRegion}`);
|
|
192
|
+
if (ic.gcpProject) lines.push(`- GCP project: ${ic.gcpProject}`);
|
|
193
|
+
parts.push(lines.join('\n'));
|
|
194
|
+
|
|
195
|
+
// H3: Inject known resource inventory for better tool call accuracy.
|
|
196
|
+
// Lists exact names for contexts, releases, workspaces, and cloud accounts
|
|
197
|
+
// so the agent uses them verbatim instead of guessing.
|
|
198
|
+
const resourceInventory: string[] = [];
|
|
199
|
+
if (ic.kubectlContext) {
|
|
200
|
+
resourceInventory.push(`kubectl context: ${ic.kubectlContext}`);
|
|
201
|
+
}
|
|
202
|
+
if (ic.helmReleases && ic.helmReleases.length > 0) {
|
|
203
|
+
resourceInventory.push(`Helm releases: ${ic.helmReleases.join(', ')}`);
|
|
204
|
+
}
|
|
205
|
+
if (ic.terraformWorkspace) {
|
|
206
|
+
resourceInventory.push(`Terraform workspace: ${ic.terraformWorkspace}`);
|
|
207
|
+
}
|
|
208
|
+
if (ic.awsAccount) {
|
|
209
|
+
resourceInventory.push(`AWS account: ${ic.awsAccount} (${ic.awsRegion ?? 'unknown region'})`);
|
|
210
|
+
}
|
|
211
|
+
// C6: Inject awsRegion standalone so LLM passes correct region to tool calls
|
|
212
|
+
if (ic.awsRegion) {
|
|
213
|
+
resourceInventory.push(`AWS default region: ${ic.awsRegion} (pass region param to target others)`);
|
|
214
|
+
}
|
|
215
|
+
if (ic.gcpProject) {
|
|
216
|
+
resourceInventory.push(`GCP project: ${ic.gcpProject}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (resourceInventory.length > 0) {
|
|
220
|
+
parts.push(
|
|
221
|
+
`## Known Infrastructure Resources\nUse these exact names when calling tools:\n${resourceInventory.map(r => `- ${r}`).join('\n')}`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
127
224
|
}
|
|
128
225
|
|
|
129
226
|
// 6. Subagent instructions (if applicable)
|
|
@@ -134,6 +231,27 @@ export function buildSystemPrompt(options: SystemPromptOptions): string {
|
|
|
134
231
|
// 7. Environment context
|
|
135
232
|
parts.push(buildEnvironmentContext(options.cwd));
|
|
136
233
|
|
|
234
|
+
// C5: Primary cloud providers section (from ~/.nimbus/config.json)
|
|
235
|
+
const primaryCloudsSection = buildPrimaryCloudSection();
|
|
236
|
+
if (primaryCloudsSection) {
|
|
237
|
+
parts.push(primaryCloudsSection);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// M1: Dry-run mode — append hard constraint at the end so it takes priority
|
|
241
|
+
if (options.dryRun) {
|
|
242
|
+
parts.push(
|
|
243
|
+
'# DRY-RUN MODE — ACTIVE\n\n' +
|
|
244
|
+
'DRY-RUN MODE: Do not execute any mutating operations. ' +
|
|
245
|
+
'List exactly what you would do step by step.\n\n' +
|
|
246
|
+
'You MUST NOT:\n' +
|
|
247
|
+
'- Apply, create, update, or delete any infrastructure\n' +
|
|
248
|
+
'- Run terraform apply, kubectl apply, helm install/upgrade/uninstall\n' +
|
|
249
|
+
'- Write or modify files\n' +
|
|
250
|
+
'- Execute any destructive bash commands\n\n' +
|
|
251
|
+
'Instead, describe precisely what each step would do and why.'
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
137
255
|
return parts.join('\n\n---\n\n');
|
|
138
256
|
}
|
|
139
257
|
|
|
@@ -145,19 +263,27 @@ export function buildSystemPrompt(options: SystemPromptOptions): string {
|
|
|
145
263
|
* Core identity and behavioral rules that apply regardless of mode.
|
|
146
264
|
* @internal
|
|
147
265
|
*/
|
|
148
|
-
const BASE_PROMPT = `You are Nimbus, an
|
|
266
|
+
const BASE_PROMPT = `You are Nimbus, an autonomous DevOps operator. Your job is to keep
|
|
267
|
+
infrastructure healthy, deployments flowing, and production stable — through direct action.
|
|
268
|
+
|
|
269
|
+
Your PRIMARY instinct is to RUN commands and query live state first:
|
|
270
|
+
- When something is broken: run \`kubectl describe\`, \`terraform plan\`, \`aws logs\` BEFORE reading files
|
|
271
|
+
- When asked about infrastructure state: query it (\`kubectl get pods -A\`, \`terraform state list\`)
|
|
272
|
+
- When asked to deploy: validate → plan → show plan → confirm → apply
|
|
273
|
+
- Edit IaC files only as a follow-up once diagnostics reveal what must change
|
|
149
274
|
|
|
150
|
-
|
|
275
|
+
Your domain is DevOps: Terraform, Kubernetes, Helm, AWS, GCP, Azure, CI/CD, Docker, secrets management.
|
|
151
276
|
|
|
152
|
-
|
|
277
|
+
Key operational rules:
|
|
278
|
+
- Run diagnostics and infrastructure commands FIRST — do not start by reading files
|
|
279
|
+
- Always show a plan/preview and get confirmation before destructive operations
|
|
280
|
+
- Always run validation (terraform validate, kubectl --dry-run) before apply
|
|
281
|
+
- Be namespace-aware for Kubernetes; always pass \`-n <namespace>\` explicitly
|
|
282
|
+
- Explain what you are doing and why at each step
|
|
283
|
+
- If a tool call fails, classify the error and try a corrective approach before giving up
|
|
284
|
+
- Make precise, targeted edits to IaC files — never rewrite entire configurations
|
|
153
285
|
|
|
154
|
-
|
|
155
|
-
- Read files before editing them to understand the current state
|
|
156
|
-
- Make precise, targeted edits rather than rewriting entire files
|
|
157
|
-
- Run tests after making changes to verify correctness
|
|
158
|
-
- Show deployment previews before executing destructive infrastructure changes
|
|
159
|
-
- Explain what you're doing and why at each step
|
|
160
|
-
- If a tool call fails, analyze the error and try a different approach`;
|
|
286
|
+
You are specialized exclusively for DevOps, infrastructure, and cloud operations. If asked to help with tasks unrelated to DevOps (e.g., building a UI, writing business logic, general algorithms unrelated to infrastructure), respond: "I'm specialized for DevOps and infrastructure. For general software development, try a general-purpose coding agent. Is there an infrastructure or deployment aspect I can help with?"`;
|
|
161
287
|
|
|
162
288
|
/**
|
|
163
289
|
* General best-practice guidelines for tool invocation that are included in
|
|
@@ -174,7 +300,317 @@ const TOOL_USE_GUIDELINES = `# Tool-Use Guidelines
|
|
|
174
300
|
- Use \`deploy_preview\` before any destructive infrastructure change.
|
|
175
301
|
- Use the \`task\` tool to spawn subagents for parallel or specialized work.
|
|
176
302
|
- When using \`terraform\`, always run \`terraform init\` before \`plan\` or \`apply\` if not already initialized.
|
|
177
|
-
- For Kubernetes operations, be namespace-aware. Default to the current namespace context
|
|
303
|
+
- For Kubernetes operations, be namespace-aware. Default to the current namespace context.
|
|
304
|
+
- Never read or search inside generated/dependency directories: \`node_modules/\`, \`dist/\`, \`build/\`, \`__pycache__/\`, \`.terraform/\`, \`.git/\`, \`coverage/\`, \`.next/\`, \`vendor/\`. These are never relevant to editing source code and will waste context window.
|
|
305
|
+
- Respect \`.gitignore\` patterns — do not read files that would be gitignored unless the user explicitly asks for them.`;
|
|
306
|
+
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
// H4: Task-Adaptive DevOps Domain Knowledge
|
|
309
|
+
//
|
|
310
|
+
// The domain knowledge is split into named sections. buildSystemPrompt uses
|
|
311
|
+
// getRelevantDomainKnowledge() to include only the sections that are relevant
|
|
312
|
+
// to the tools available in the current session, keeping the prompt concise.
|
|
313
|
+
// ---------------------------------------------------------------------------
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Per-domain knowledge sections keyed by domain name.
|
|
317
|
+
* @internal
|
|
318
|
+
*/
|
|
319
|
+
const DOMAIN_SECTIONS: Record<string, string> = {
|
|
320
|
+
general: `## General DevOps Principles
|
|
321
|
+
- Infrastructure drift: plan outputs starting with \`~\` = modify, \`-\` = destroy, \`+\` = create
|
|
322
|
+
- Zero-downtime deploys: rolling updates, blue/green, canary with traffic splitting
|
|
323
|
+
- Secret management: never hardcode secrets; use SSM Parameter Store, Secrets Manager, Vault, or sealed-secrets
|
|
324
|
+
- Observability: logs → \`kubectl logs\`, metrics → \`kubectl top\`, traces → service mesh
|
|
325
|
+
- Cost optimization: right-size instances, use spot/preemptible for stateless workloads
|
|
326
|
+
|
|
327
|
+
## Docker Best Practices
|
|
328
|
+
- Always use multi-stage builds to minimize image size; pin base image tags (avoid \`latest\`)
|
|
329
|
+
- Build: \`docker build -t myapp:v1.0 -f Dockerfile .\`
|
|
330
|
+
- Compose: \`docker compose up -d\` starts detached; \`docker compose down\` removes containers
|
|
331
|
+
- Check daemon: \`docker info\`; if not running → \`colima start\` (macOS) or \`sudo systemctl start docker\`
|
|
332
|
+
- Common errors:
|
|
333
|
+
- \`cannot connect to the Docker daemon\` → start Docker Desktop or run \`colima start\`
|
|
334
|
+
- \`manifest not found\` → verify image name/tag; check registry login (\`docker login\`)
|
|
335
|
+
- \`no space left on device\` → run \`docker system prune -f\` to reclaim space
|
|
336
|
+
- \`permission denied\` on socket → add user to docker group or use \`sudo\`
|
|
337
|
+
|
|
338
|
+
## Incident Management (PagerDuty & Opsgenie)
|
|
339
|
+
- PagerDuty: requires \`PD_API_KEY\` env var; list incidents with action=incidents, acknowledge with action=ack, resolve with action=resolve
|
|
340
|
+
- Opsgenie: requires \`OPSGENIE_API_KEY\` env var; list alerts with action=alerts, acknowledge with action=ack, close with action=resolve
|
|
341
|
+
- On-call schedule: use action=on-call with provider=pagerduty or provider=opsgenie to see who is currently on call
|
|
342
|
+
- Incident response workflow: acknowledge first (stops escalation) → investigate → resolve
|
|
343
|
+
- Common errors:
|
|
344
|
+
- \`401 Unauthorized\` → verify API key is correct and not expired
|
|
345
|
+
- \`403 Forbidden\` → check API key permissions (needs read+write for ack/resolve)
|
|
346
|
+
- \`404 Not Found\` → verify incident/alert ID is correct (use list first)
|
|
347
|
+
|
|
348
|
+
## Web Search for DevOps
|
|
349
|
+
- Use \`web_search\` to look up error codes, provider limits, API endpoints, pricing
|
|
350
|
+
- Set \`BRAVE_API_KEY\` env var for higher-quality search results via Brave Search API`,
|
|
351
|
+
|
|
352
|
+
terraform: `## Terraform Best Practices
|
|
353
|
+
- Always run \`terraform validate\` → \`terraform plan\` → \`terraform apply\` in sequence
|
|
354
|
+
- Use \`terraform plan -out=tfplan\` to save plan files; apply with \`terraform apply tfplan\`
|
|
355
|
+
- For state inspection: \`terraform state list\`, \`terraform state show <resource>\`
|
|
356
|
+
- Remote state: prefer S3+DynamoDB (AWS), GCS (GCP), Azure Blob. Never commit \`.tfstate\` files
|
|
357
|
+
- Workspaces: \`terraform workspace new <env>\`, \`terraform workspace select <env>\`
|
|
358
|
+
- Module structure: \`main.tf\`, \`variables.tf\`, \`outputs.tf\`, \`versions.tf\`
|
|
359
|
+
- Lock files (\`.terraform.lock.hcl\`) MUST be committed to version control
|
|
360
|
+
- Use \`count\` or \`for_each\` for resource iteration; avoid \`count\` for ordered resources
|
|
361
|
+
- \`depends_on\` is a last resort — prefer implicit dependencies via references
|
|
362
|
+
|
|
363
|
+
## Error Diagnosis — Terraform
|
|
364
|
+
- \`Error: The provider "hashicorp/aws" requires Terraform >= X\` → run \`terraform init -upgrade\`
|
|
365
|
+
- \`Error: configuring Terraform AWS Provider: no valid credentials\` → check AWS credentials, run \`aws configure\`
|
|
366
|
+
- \`Error: creating EC2 Instance: VcpuLimitExceeded\` → request quota increase in AWS Console`,
|
|
367
|
+
|
|
368
|
+
kubernetes: `## Kubernetes Operations
|
|
369
|
+
- Check cluster health first: \`kubectl get nodes\`, \`kubectl get pods -A\`
|
|
370
|
+
- Namespace-aware commands: always pass \`-n <namespace>\` or use \`--all-namespaces\`
|
|
371
|
+
- Deployment rollouts: \`kubectl rollout status deploy/<name>\`, \`kubectl rollout history deploy/<name>\`
|
|
372
|
+
- Rollback: \`kubectl rollout undo deploy/<name>\`, or \`kubectl rollout undo deploy/<name> --to-revision=N\`
|
|
373
|
+
- Resource sizing: check \`kubectl top pods\`, \`kubectl top nodes\` before scaling
|
|
374
|
+
- Debug pods: \`kubectl exec -it <pod> -- /bin/sh\`, \`kubectl logs <pod> --previous\` for crashloops
|
|
375
|
+
- Dry-run before apply: \`kubectl apply --dry-run=client -f manifest.yaml\`
|
|
376
|
+
- Labels and selectors: always verify selectors match pod templates in Deployments
|
|
377
|
+
|
|
378
|
+
## Error Diagnosis — Kubernetes
|
|
379
|
+
- \`OOMKilled\` → increase memory limit in pod spec; check \`kubectl describe pod\`
|
|
380
|
+
- \`CrashLoopBackOff\` → \`kubectl logs <pod> --previous\`; check readiness/liveness probes
|
|
381
|
+
- \`ImagePullBackOff\` → verify image name/tag, check registry credentials (imagePullSecret)
|
|
382
|
+
- \`Pending\` pods → \`kubectl describe pod\` for events; common: insufficient resources, no matching node`,
|
|
383
|
+
|
|
384
|
+
helm: `## Helm Operations
|
|
385
|
+
- Repo management: \`helm repo add <name> <url>\`, \`helm repo update\` before install/upgrade
|
|
386
|
+
- Template debugging: \`helm template <release> <chart> -f values.yaml\` before install
|
|
387
|
+
- Diff before upgrade: \`helm diff upgrade <release> <chart>\` (requires helm-diff plugin)
|
|
388
|
+
- Override values: \`-f values.yaml\` for files, \`--set key=value\` for single values
|
|
389
|
+
- Release history: \`helm history <release> -n <namespace>\`
|
|
390
|
+
- Rollback: \`helm rollback <release> <revision> -n <namespace>\`
|
|
391
|
+
|
|
392
|
+
## Helm Secrets (SOPS) Best Practices
|
|
393
|
+
- Install: \`helm plugin install https://github.com/jkroepke/helm-secrets\`
|
|
394
|
+
- Encrypt: \`helm secrets enc values.yaml\` (requires SOPS config \`.sops.yaml\`)
|
|
395
|
+
- Decrypt: \`helm secrets dec values.yaml.enc\`
|
|
396
|
+
- View without decrypt: \`helm secrets view values.yaml.enc\`
|
|
397
|
+
- Install with secrets: \`helm secrets install release chart -f values.yaml.enc\`
|
|
398
|
+
- Common errors:
|
|
399
|
+
- \`plugin not found\` → run \`helm plugin list | grep secrets\` to verify install
|
|
400
|
+
- \`sops: not found\` → install sops: \`brew install sops\``,
|
|
401
|
+
|
|
402
|
+
aws: `## AWS Patterns
|
|
403
|
+
- IAM: prefer roles over long-lived credentials; use instance profiles, IRSA, workload identity
|
|
404
|
+
- Networking: VPC → subnets → security groups → route tables; know public vs private subnets
|
|
405
|
+
- EKS: use IRSA for pod-level AWS API access; node groups vs Fargate tradeoffs
|
|
406
|
+
- S3 versioning + lifecycle policies for state files; enable MFA delete for sensitive buckets
|
|
407
|
+
- Common debug: \`aws sts get-caller-identity\`, \`aws configure list\`, \`aws --debug <cmd>\``,
|
|
408
|
+
|
|
409
|
+
secrets: `## Secrets Management Best Practices
|
|
410
|
+
- Never log or display raw secret values — always redact in output
|
|
411
|
+
- Rotation patterns: automate rotation with Lambda (AWS) or Cloud Functions (GCP)
|
|
412
|
+
- Kubernetes secrets: prefer external-secrets-operator or Vault Agent Injector over native k8s secrets
|
|
413
|
+
- SOPS (Secrets OPerationS): encrypt secrets files committed to Git using \`sops --encrypt file.yaml\`
|
|
414
|
+
- External Secrets Operator: syncs secrets from Vault/AWS/GCP into k8s Secrets automatically
|
|
415
|
+
- Vault: use \`vault kv get -format=json <path>\` and never expose SecretString in logs
|
|
416
|
+
- Common errors:
|
|
417
|
+
- \`permission denied\` on Vault → check policy: \`vault policy read <policy-name>\`
|
|
418
|
+
- \`secret not found\` → verify path and namespace: \`vault kv list <mount>\``,
|
|
419
|
+
|
|
420
|
+
cicd: `## CI/CD Pipeline Best Practices
|
|
421
|
+
- GitHub Actions: workflow files live in \`.github/workflows/\`; use \`gh workflow run\` to trigger
|
|
422
|
+
- GitLab CI: \`.gitlab-ci.yml\` at repo root; \`glab ci run\` triggers pipelines
|
|
423
|
+
- CircleCI: \`.circleci/config.yml\`; use project slugs (gh/org/repo)
|
|
424
|
+
- Always check branch protection rules before triggering on main/production
|
|
425
|
+
- Common errors:
|
|
426
|
+
- \`workflow not found\` → check filename in \`.github/workflows/\` and branch name
|
|
427
|
+
- \`rate limited\` → wait 60s and retry; check API rate limit headers
|
|
428
|
+
- \`token expired\` → refresh token or check service account permissions`,
|
|
429
|
+
|
|
430
|
+
monitoring: `## Monitoring & Observability Best Practices
|
|
431
|
+
- Prometheus: use \`rate()\` for counters, \`histogram_quantile()\` for latencies; query via HTTP API
|
|
432
|
+
- CloudWatch: structured queries with CloudWatch Insights for efficient log searching
|
|
433
|
+
- Grafana: use \`$GRAFANA_URL\` env var + Bearer token for API access
|
|
434
|
+
- Datadog: requires both \`DD_API_KEY\` and \`DD_APP_KEY\` for query API
|
|
435
|
+
- Alert on: error rate, latency p99, saturation (CPU/memory), traffic (requests/sec)
|
|
436
|
+
- SLO pattern: \`1 - (error_rate / total_rate)\` over 30-day rolling window`,
|
|
437
|
+
|
|
438
|
+
gitops: `## GitOps Best Practices (ArgoCD & Flux)
|
|
439
|
+
- ArgoCD: \`argocd app sync\` triggers reconciliation; \`argocd app diff\` shows pending changes
|
|
440
|
+
- Flux: \`flux reconcile kustomization flux-system\` forces immediate reconciliation
|
|
441
|
+
- Always check health before sync: \`argocd app get <app>\` shows health.status
|
|
442
|
+
- Rollback strategy: ArgoCD → \`argocd app rollback <app> <revision>\`; Flux → revert Git commit
|
|
443
|
+
- Common errors:
|
|
444
|
+
- \`app not found\` → check \`ARGOCD_SERVER\` env var and login token
|
|
445
|
+
- \`ComparisonError\` → validate manifests with \`kubectl apply --dry-run=client\``,
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Return the DevOps domain knowledge sections that are relevant to the given
|
|
450
|
+
* set of tool names.
|
|
451
|
+
*
|
|
452
|
+
* The general section is always included. Domain-specific sections (terraform,
|
|
453
|
+
* kubernetes, helm, aws, secrets, cicd, monitoring, gitops) are only added when
|
|
454
|
+
* at least one tool in `toolNames` maps to that domain.
|
|
455
|
+
*
|
|
456
|
+
* This keeps the system prompt lean for sessions that only use a small subset
|
|
457
|
+
* of the DevOps toolchain.
|
|
458
|
+
*
|
|
459
|
+
* @param toolNames - The names of the tools available in the current session.
|
|
460
|
+
* @returns A markdown string containing only the relevant knowledge sections.
|
|
461
|
+
*/
|
|
462
|
+
export function getRelevantDomainKnowledge(toolNames: string[]): string {
|
|
463
|
+
const sections: string[] = [`# DevOps Domain Knowledge\n\n${DOMAIN_SECTIONS.general}`];
|
|
464
|
+
|
|
465
|
+
if (toolNames.some(t => t.includes('terraform') || t === 'drift_detect')) {
|
|
466
|
+
sections.push(DOMAIN_SECTIONS.terraform);
|
|
467
|
+
}
|
|
468
|
+
if (toolNames.some(t => t.includes('kubectl') || t === 'k8s_rbac' || t === 'k8s')) {
|
|
469
|
+
sections.push(DOMAIN_SECTIONS.kubernetes);
|
|
470
|
+
}
|
|
471
|
+
if (toolNames.some(t => t.includes('helm'))) {
|
|
472
|
+
sections.push(DOMAIN_SECTIONS.helm);
|
|
473
|
+
}
|
|
474
|
+
if (toolNames.some(t => t.includes('aws') || t.includes('cloud'))) {
|
|
475
|
+
sections.push(DOMAIN_SECTIONS.aws);
|
|
476
|
+
}
|
|
477
|
+
if (toolNames.some(t => t.includes('secret') || t.includes('vault'))) {
|
|
478
|
+
sections.push(DOMAIN_SECTIONS.secrets);
|
|
479
|
+
}
|
|
480
|
+
if (toolNames.some(t => t.includes('cicd') || t.includes('pipeline') || t.includes('github'))) {
|
|
481
|
+
sections.push(DOMAIN_SECTIONS.cicd);
|
|
482
|
+
}
|
|
483
|
+
if (toolNames.some(t => t.includes('monitor') || t.includes('logs') || t.includes('metric'))) {
|
|
484
|
+
sections.push(DOMAIN_SECTIONS.monitoring);
|
|
485
|
+
}
|
|
486
|
+
if (toolNames.some(t => t.includes('gitops') || t.includes('argocd') || t.includes('flux'))) {
|
|
487
|
+
sections.push(DOMAIN_SECTIONS.gitops);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return sections.join('\n\n');
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* The full concatenated DevOps domain knowledge (all sections).
|
|
495
|
+
*
|
|
496
|
+
* Kept for backward-compatibility. New call sites should prefer
|
|
497
|
+
* {@link getRelevantDomainKnowledge} with a tool list so only the relevant
|
|
498
|
+
* sections are included in the prompt.
|
|
499
|
+
*
|
|
500
|
+
* @deprecated Use {@link getRelevantDomainKnowledge} instead.
|
|
501
|
+
* @internal
|
|
502
|
+
*/
|
|
503
|
+
export const DEVOPS_DOMAIN_KNOWLEDGE = [
|
|
504
|
+
`# DevOps Domain Knowledge\n\n${DOMAIN_SECTIONS.general}`,
|
|
505
|
+
DOMAIN_SECTIONS.terraform,
|
|
506
|
+
DOMAIN_SECTIONS.kubernetes,
|
|
507
|
+
DOMAIN_SECTIONS.helm,
|
|
508
|
+
DOMAIN_SECTIONS.aws,
|
|
509
|
+
DOMAIN_SECTIONS.secrets,
|
|
510
|
+
DOMAIN_SECTIONS.cicd,
|
|
511
|
+
DOMAIN_SECTIONS.monitoring,
|
|
512
|
+
DOMAIN_SECTIONS.gitops,
|
|
513
|
+
].join('\n\n');
|
|
514
|
+
|
|
515
|
+
// ---------------------------------------------------------------------------
|
|
516
|
+
// DevOps Decision Heuristics
|
|
517
|
+
// ---------------------------------------------------------------------------
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Explicit decision rules injected into every prompt to prevent common mistakes.
|
|
521
|
+
* @internal
|
|
522
|
+
*/
|
|
523
|
+
const DEVOPS_HEURISTICS = `# DevOps Decision Heuristics
|
|
524
|
+
|
|
525
|
+
## Terraform Workflow Rules
|
|
526
|
+
- ALWAYS follow: init → validate → plan → review → apply. NEVER apply without a prior plan.
|
|
527
|
+
- NEVER use terraform apply if you haven't seen the plan output in this session.
|
|
528
|
+
- state-rm and force-unlock require EXPLICIT user confirmation — always ask before running.
|
|
529
|
+
- For multi-environment: check active workspace (\`terraform workspace show\`) before any operation.
|
|
530
|
+
- Tag every resource you create with \`managed_by = "nimbus"\` in Terraform resources.
|
|
531
|
+
- Prefer \`terraform output -json\` over parsing state files directly.
|
|
532
|
+
|
|
533
|
+
## Kubernetes Rules
|
|
534
|
+
- ALWAYS include \`-n <namespace>\` or \`--all-namespaces\`. Never assume default namespace.
|
|
535
|
+
- When debugging: check LOGS first, then events (\`kubectl describe\`), then resource state.
|
|
536
|
+
- NEVER delete a pod directly unless debugging — prefer \`kubectl rollout restart deploy/<name>\`.
|
|
537
|
+
- Cordon/drain before node maintenance: \`kubectl cordon\` then \`kubectl drain --ignore-daemonsets\`.
|
|
538
|
+
- Add label \`app.kubernetes.io/managed-by: nimbus\` to K8s resources you create.
|
|
539
|
+
|
|
540
|
+
## Helm Rules
|
|
541
|
+
- ALWAYS run \`helm lint\` before install or upgrade.
|
|
542
|
+
- ALWAYS get current values before upgrading: \`helm get values <release> -n <ns>\`.
|
|
543
|
+
- Use \`--atomic\` on upgrades to auto-rollback on failure.
|
|
544
|
+
- Check \`helm history\` before rollback to pick the correct revision.
|
|
545
|
+
|
|
546
|
+
## General DevOps Rules
|
|
547
|
+
- Prefer read/inspect operations before any write/mutate operations.
|
|
548
|
+
- In PLAN mode: NEVER apply, apply, delete, or mutate any resource.
|
|
549
|
+
- In DEPLOY mode: ALWAYS show deploy_preview before destructive operations (destroy/delete/state-rm).
|
|
550
|
+
- Use \`env\` field on terraform/kubectl/helm tools to pass \`AWS_PROFILE\`, \`KUBECONFIG\`, \`TF_WORKSPACE\`.
|
|
551
|
+
- Prefer dedicated cloud tools (\`aws\`, \`gcloud\`, \`az\`) over \`bash\` for cloud operations.
|
|
552
|
+
|
|
553
|
+
## Tool Selection Priority
|
|
554
|
+
1. Use terraform/kubectl/helm tools for IaC operations (not bash).
|
|
555
|
+
2. Use cloud_discover to find resources before operating on them.
|
|
556
|
+
3. Use drift_detect to check actual vs desired state.
|
|
557
|
+
4. Use cost_estimate to understand financial impact before applying.
|
|
558
|
+
5. Fall back to bash only when no dedicated tool covers the operation.`;
|
|
559
|
+
|
|
560
|
+
// ---------------------------------------------------------------------------
|
|
561
|
+
// L2: Mode-Pruned Heuristics
|
|
562
|
+
// ---------------------------------------------------------------------------
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Return the DevOps decision heuristics pruned to only include sections
|
|
566
|
+
* relevant to the current mode. This prevents prompt bloat in restricted
|
|
567
|
+
* modes where deploy-specific or plan-specific rules are irrelevant.
|
|
568
|
+
*
|
|
569
|
+
* - plan mode: omit deploy-related execution rules (they cannot be triggered)
|
|
570
|
+
* - build mode: omit plan-only readonly reminders (build mode can write files)
|
|
571
|
+
* - deploy mode: include everything
|
|
572
|
+
*
|
|
573
|
+
* @param mode - The current agent mode.
|
|
574
|
+
* @returns A pruned markdown heuristics string.
|
|
575
|
+
*/
|
|
576
|
+
export function getPrunedHeuristics(mode: AgentMode): string {
|
|
577
|
+
if (mode === 'deploy') {
|
|
578
|
+
// Deploy mode: include the complete heuristics — no pruning needed.
|
|
579
|
+
return DEVOPS_HEURISTICS;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Split into lines and filter based on mode.
|
|
583
|
+
const lines = DEVOPS_HEURISTICS.split('\n');
|
|
584
|
+
|
|
585
|
+
if (mode === 'plan') {
|
|
586
|
+
// Plan mode: skip lines that reference apply/deploy operations that are
|
|
587
|
+
// blocked anyway. This saves ~10-15 tokens without losing useful context.
|
|
588
|
+
return lines
|
|
589
|
+
.filter(line => {
|
|
590
|
+
const l = line.toLowerCase();
|
|
591
|
+
// Remove deploy-specific execution requirements (plan mode cannot apply)
|
|
592
|
+
if (l.includes('in deploy mode:') || l.includes('deploy_preview before')) return false;
|
|
593
|
+
// Remove tool selection items for deploy-only tools
|
|
594
|
+
if (l.includes('use drift_detect') || l.includes('use cost_estimate')) return false;
|
|
595
|
+
return true;
|
|
596
|
+
})
|
|
597
|
+
.join('\n');
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (mode === 'build') {
|
|
601
|
+
// Build mode: skip plan-only readonly reminders that contradict build mode.
|
|
602
|
+
return lines
|
|
603
|
+
.filter(line => {
|
|
604
|
+
const l = line.toLowerCase();
|
|
605
|
+
// Remove plan-mode-only readonly enforcement lines
|
|
606
|
+
if (l.includes('in plan mode:') || l.includes('never apply, apply')) return false;
|
|
607
|
+
return true;
|
|
608
|
+
})
|
|
609
|
+
.join('\n');
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
return DEVOPS_HEURISTICS;
|
|
613
|
+
}
|
|
178
614
|
|
|
179
615
|
// ---------------------------------------------------------------------------
|
|
180
616
|
// Mode Instructions
|
|
@@ -198,19 +634,23 @@ function getModeInstructions(mode: AgentMode): string {
|
|
|
198
634
|
You are in Plan mode. Your role is to analyze, explore, and propose — NOT to modify.
|
|
199
635
|
|
|
200
636
|
Allowed actions:
|
|
201
|
-
- Read files, search
|
|
202
|
-
- Analyze infrastructure configurations
|
|
637
|
+
- Read files, search configurations, list directories
|
|
638
|
+
- Analyze infrastructure configurations (Terraform, Kubernetes, Helm, CI/CD)
|
|
203
639
|
- Estimate costs and detect drift
|
|
640
|
+
- Use terraform_plan_analyze to inspect plan files
|
|
641
|
+
- Use kubectl_context to list cluster contexts (read-only)
|
|
204
642
|
- Propose changes and create task lists
|
|
205
643
|
- Fetch web content for research
|
|
206
644
|
|
|
207
645
|
NOT allowed:
|
|
208
646
|
- Editing or creating files
|
|
209
|
-
- Running
|
|
647
|
+
- Running bash commands that modify state
|
|
210
648
|
- Executing terraform apply, kubectl apply, helm install
|
|
211
649
|
- Making any state-changing operations
|
|
212
650
|
|
|
213
|
-
|
|
651
|
+
WORKSPACE AWARENESS: Start by checking the active Terraform workspace and kubectl context. Report the current workspace/context before making any proposals so the user knows what environment you're analyzing.
|
|
652
|
+
|
|
653
|
+
Focus on understanding the infrastructure and environment, then propose a clear, specific action plan.`;
|
|
214
654
|
|
|
215
655
|
case 'build':
|
|
216
656
|
return `# Mode: BUILD
|
|
@@ -219,11 +659,11 @@ You are in Build mode. You can read, edit, create files, and run non-destructive
|
|
|
219
659
|
|
|
220
660
|
Allowed actions:
|
|
221
661
|
- All Plan mode actions
|
|
222
|
-
- Edit and
|
|
223
|
-
-
|
|
224
|
-
- Generate Terraform/K8s/Helm configurations
|
|
662
|
+
- Edit infrastructure configurations, generate IaC, fix scripts and automation code
|
|
663
|
+
- Edit and create files (Terraform, Kubernetes manifests, Helm charts, CI/CD configs)
|
|
225
664
|
- Run terraform validate, terraform fmt, terraform plan
|
|
226
665
|
- Run kubectl get, kubectl describe, kubectl diff
|
|
666
|
+
- Run linters, formatters, and validation commands
|
|
227
667
|
|
|
228
668
|
NOT allowed:
|
|
229
669
|
- terraform apply, terraform destroy
|
|
@@ -231,7 +671,7 @@ NOT allowed:
|
|
|
231
671
|
- helm install, helm upgrade, helm uninstall
|
|
232
672
|
- Any infrastructure-mutating operations
|
|
233
673
|
|
|
234
|
-
Focus on
|
|
674
|
+
Focus on generating, editing, and validating infrastructure configurations before deploying.`;
|
|
235
675
|
|
|
236
676
|
case 'deploy':
|
|
237
677
|
return `# Mode: DEPLOY
|
|
@@ -249,6 +689,8 @@ REQUIRED:
|
|
|
249
689
|
- Always run deploy_preview before any destructive operation
|
|
250
690
|
- Show the user what will change before executing
|
|
251
691
|
- Wait for explicit approval on destructive changes
|
|
692
|
+
- Be WORKSPACE-AWARE: before applying, confirm the active Terraform workspace and kubectl context match the intended environment. State this explicitly: "Applying to workspace: X in cluster: Y"
|
|
693
|
+
- For multi-environment setups, use terraform_plan_analyze to confirm the scope before terraform apply
|
|
252
694
|
|
|
253
695
|
Focus on safe, verified deployments with minimal blast radius.`;
|
|
254
696
|
}
|
|
@@ -323,6 +765,47 @@ export function loadNimbusMd(cwd?: string): string | null {
|
|
|
323
765
|
return null;
|
|
324
766
|
}
|
|
325
767
|
|
|
768
|
+
// ---------------------------------------------------------------------------
|
|
769
|
+
// G14: Forbidden rules extraction
|
|
770
|
+
// ---------------------------------------------------------------------------
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Extract bullet items from the `## Forbidden` section of a NIMBUS.md string.
|
|
774
|
+
* Returns an array of rule strings (without the leading `-` or `*`).
|
|
775
|
+
*
|
|
776
|
+
* @param nimbusContent - The full content of a NIMBUS.md file.
|
|
777
|
+
* @returns Array of forbidden rule strings, empty if section not found or empty.
|
|
778
|
+
*/
|
|
779
|
+
export function extractForbiddenRules(nimbusContent: string): string[] {
|
|
780
|
+
// Find the ## Forbidden section and extract lines until the next ## heading or end of string
|
|
781
|
+
const lines = nimbusContent.split('\n');
|
|
782
|
+
let inForbidden = false;
|
|
783
|
+
const rules: string[] = [];
|
|
784
|
+
|
|
785
|
+
for (const line of lines) {
|
|
786
|
+
const trimmed = line.trim();
|
|
787
|
+
if (/^##\s+Forbidden\s*$/.test(trimmed)) {
|
|
788
|
+
inForbidden = true;
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
if (inForbidden) {
|
|
792
|
+
// Stop at any new ## section
|
|
793
|
+
if (/^##\s/.test(trimmed)) break;
|
|
794
|
+
// Skip blank lines and HTML comments
|
|
795
|
+
if (!trimmed || trimmed.startsWith('<!--')) continue;
|
|
796
|
+
// Collect bullet items
|
|
797
|
+
if (trimmed.startsWith('-') || trimmed.startsWith('*')) {
|
|
798
|
+
const rule = trimmed.replace(/^[-*]\s*/, '').trim();
|
|
799
|
+
if (rule && !rule.startsWith('<!--')) {
|
|
800
|
+
rules.push(rule);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
return rules;
|
|
807
|
+
}
|
|
808
|
+
|
|
326
809
|
// ---------------------------------------------------------------------------
|
|
327
810
|
// Subagent Instructions
|
|
328
811
|
// ---------------------------------------------------------------------------
|
|
@@ -432,5 +915,76 @@ function buildEnvironmentContext(cwd?: string): string {
|
|
|
432
915
|
}
|
|
433
916
|
}
|
|
434
917
|
|
|
918
|
+
// Kubernetes context
|
|
919
|
+
try {
|
|
920
|
+
const ctx = execSync('kubectl config current-context', { timeout: 2000, encoding: 'utf-8' }).trim();
|
|
921
|
+
if (ctx) parts.push(`- Kubernetes context: ${ctx}`);
|
|
922
|
+
} catch { /* ignore */ }
|
|
923
|
+
|
|
924
|
+
// Terraform workspace (only if .terraform dir exists)
|
|
925
|
+
if (fs.existsSync(path.join(effectiveCwd, '.terraform'))) {
|
|
926
|
+
try {
|
|
927
|
+
const ws = execSync('terraform workspace show', {
|
|
928
|
+
cwd: effectiveCwd, timeout: 5000, encoding: 'utf-8',
|
|
929
|
+
}).trim();
|
|
930
|
+
if (ws) parts.push(`- Terraform workspace: ${ws}`);
|
|
931
|
+
} catch { /* ignore */ }
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// AWS identity (only if credentials are configured)
|
|
935
|
+
if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_PROFILE || fs.existsSync(path.join(homedir(), '.aws', 'credentials'))) {
|
|
936
|
+
try {
|
|
937
|
+
const identity = execSync('aws sts get-caller-identity --output json', {
|
|
938
|
+
timeout: 5000, encoding: 'utf-8',
|
|
939
|
+
}).trim();
|
|
940
|
+
const parsed = JSON.parse(identity);
|
|
941
|
+
parts.push(`- AWS account: ${parsed.Account}`);
|
|
942
|
+
} catch { /* ignore */ }
|
|
943
|
+
try {
|
|
944
|
+
const region = execSync('aws configure get region', { timeout: 2000, encoding: 'utf-8' }).trim();
|
|
945
|
+
if (region) parts.push(`- AWS region: ${region}`);
|
|
946
|
+
} catch {
|
|
947
|
+
if (process.env.AWS_DEFAULT_REGION) parts.push(`- AWS region: ${process.env.AWS_DEFAULT_REGION}`);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// GCP project (only if gcloud available)
|
|
952
|
+
try {
|
|
953
|
+
const proj = execSync('gcloud config get-value project 2>/dev/null', {
|
|
954
|
+
timeout: 3000, encoding: 'utf-8',
|
|
955
|
+
}).trim();
|
|
956
|
+
if (proj && proj !== '(unset)') parts.push(`- GCP project: ${proj}`);
|
|
957
|
+
} catch { /* ignore */ }
|
|
958
|
+
|
|
435
959
|
return parts.join('\n');
|
|
436
960
|
}
|
|
961
|
+
|
|
962
|
+
// ---------------------------------------------------------------------------
|
|
963
|
+
// C5: Primary Cloud Section
|
|
964
|
+
// ---------------------------------------------------------------------------
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Read the primaryClouds field from ~/.nimbus/config.json and build a section
|
|
968
|
+
* that focuses the agent on those cloud providers.
|
|
969
|
+
*
|
|
970
|
+
* @returns A markdown section string, or `null` if not configured.
|
|
971
|
+
* @internal
|
|
972
|
+
*/
|
|
973
|
+
function buildPrimaryCloudSection(): string | null {
|
|
974
|
+
try {
|
|
975
|
+
const configPath = path.join(homedir(), '.nimbus', 'config.json');
|
|
976
|
+
if (!fs.existsSync(configPath)) return null;
|
|
977
|
+
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
978
|
+
const config = JSON.parse(raw) as Record<string, unknown>;
|
|
979
|
+
const clouds = config.primaryClouds;
|
|
980
|
+
if (!Array.isArray(clouds) || clouds.length === 0) return null;
|
|
981
|
+
const cloudNames = (clouds as string[]).map(c => c.toUpperCase()).join(', ');
|
|
982
|
+
return [
|
|
983
|
+
'# Primary Cloud Providers',
|
|
984
|
+
`Primary cloud providers: ${cloudNames}`,
|
|
985
|
+
`Focus on ${cloudNames} patterns and best practices in your responses.`,
|
|
986
|
+
].join('\n');
|
|
987
|
+
} catch {
|
|
988
|
+
return null;
|
|
989
|
+
}
|
|
990
|
+
}
|