@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
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { logger } from '../utils';
|
|
10
|
-
import { RestClient } from '../clients';
|
|
11
10
|
import {
|
|
12
11
|
createWizard,
|
|
13
12
|
ui,
|
|
@@ -18,14 +17,11 @@ import {
|
|
|
18
17
|
type StepResult,
|
|
19
18
|
} from '../wizard';
|
|
20
19
|
import { awsDiscoverCommand, type AwsDiscoverOptions } from './aws-discover';
|
|
20
|
+
import { generateTerraformProject } from '../generator/terraform';
|
|
21
21
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
22
22
|
import * as path from 'path';
|
|
23
23
|
import * as fs from 'fs';
|
|
24
24
|
|
|
25
|
-
// AWS Tools Service client
|
|
26
|
-
const awsToolsUrl = process.env.AWS_TOOLS_SERVICE_URL || 'http://localhost:3009';
|
|
27
|
-
const awsClient = new RestClient(awsToolsUrl);
|
|
28
|
-
|
|
29
25
|
/**
|
|
30
26
|
* Terraform generation context
|
|
31
27
|
*/
|
|
@@ -364,85 +360,54 @@ async function outputLocationStep(ctx: AwsTerraformContext): Promise<StepResult>
|
|
|
364
360
|
}
|
|
365
361
|
|
|
366
362
|
/**
|
|
367
|
-
* Step 3: Generate Terraform
|
|
363
|
+
* Step 3: Generate Terraform using local generator
|
|
368
364
|
*/
|
|
369
365
|
async function generateStep(ctx: AwsTerraformContext): Promise<StepResult> {
|
|
370
366
|
ui.startSpinner({ message: 'Generating Terraform configurations...' });
|
|
371
367
|
|
|
372
368
|
try {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
if (
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
response = await awsClient.post<{
|
|
394
|
-
terraformSessionId: string;
|
|
395
|
-
files: Record<string, string>;
|
|
396
|
-
summary: GenerationSummary;
|
|
397
|
-
imports: any[];
|
|
398
|
-
importScript: string;
|
|
399
|
-
}>('/api/aws/terraform/generate-direct', {
|
|
400
|
-
resources: ctx.resources,
|
|
401
|
-
options: {
|
|
402
|
-
organizeByService: ctx.organizeByService,
|
|
403
|
-
generateImportBlocks: ctx.generateImportBlocks,
|
|
404
|
-
terraformVersion: ctx.terraformVersion,
|
|
405
|
-
awsProviderVersion: ctx.awsProviderVersion,
|
|
406
|
-
},
|
|
407
|
-
});
|
|
408
|
-
} else {
|
|
409
|
-
ui.stopSpinnerFail('No resources to generate from');
|
|
410
|
-
return { success: false, error: 'No resources available' };
|
|
369
|
+
// Derive components from discovered resources
|
|
370
|
+
const resourceTypes = (ctx.resources ?? []).map(r => r.type);
|
|
371
|
+
const components: string[] = [];
|
|
372
|
+
if (resourceTypes.some(t => t.includes('VPC') || t.includes('Subnet'))) components.push('vpc');
|
|
373
|
+
if (resourceTypes.some(t => t.includes('EC2') || t.includes('Instance'))) components.push('ec2');
|
|
374
|
+
if (resourceTypes.some(t => t.includes('S3'))) components.push('s3');
|
|
375
|
+
if (resourceTypes.some(t => t.includes('RDS'))) components.push('rds');
|
|
376
|
+
if (resourceTypes.some(t => t.includes('EKS'))) components.push('eks');
|
|
377
|
+
if (components.length === 0) components.push('vpc', 's3');
|
|
378
|
+
|
|
379
|
+
const generatedProject = await generateTerraformProject({
|
|
380
|
+
projectName: 'infrastructure',
|
|
381
|
+
provider: 'aws',
|
|
382
|
+
region: ctx.resources?.[0]?.region || 'us-east-1',
|
|
383
|
+
components,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
const fileMap: Record<string, string> = {};
|
|
387
|
+
for (const file of generatedProject.files) {
|
|
388
|
+
fileMap[file.path] = file.content;
|
|
411
389
|
}
|
|
412
390
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
391
|
+
const summary: GenerationSummary = {
|
|
392
|
+
totalResources: ctx.resources?.length ?? 0,
|
|
393
|
+
mappedResources: ctx.resources?.length ?? 0,
|
|
394
|
+
unmappedResources: 0,
|
|
395
|
+
filesGenerated: generatedProject.files.length,
|
|
396
|
+
servicesIncluded: components,
|
|
397
|
+
regionsIncluded: [...new Set((ctx.resources ?? []).map(r => r.region).filter(Boolean))],
|
|
398
|
+
};
|
|
419
399
|
|
|
420
|
-
ui.stopSpinnerSuccess(`Generated ${Object.keys(
|
|
400
|
+
ui.stopSpinnerSuccess(`Generated ${Object.keys(fileMap).length} file(s)`);
|
|
421
401
|
|
|
422
402
|
// Add starter kit files if requested
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (ctx.
|
|
426
|
-
allFiles['README.md'] = generateReadme(summary);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (ctx.includeGitignore) {
|
|
430
|
-
allFiles['.gitignore'] = generateGitignore();
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if (ctx.includeMakefile) {
|
|
434
|
-
allFiles['Makefile'] = generateMakefile();
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
if (ctx.generateImportScript && importScript) {
|
|
438
|
-
allFiles['import.sh'] = importScript;
|
|
439
|
-
}
|
|
403
|
+
if (ctx.includeReadme) fileMap['README.md'] = generateReadme(summary);
|
|
404
|
+
if (ctx.includeGitignore) fileMap['.gitignore'] = generateGitignore();
|
|
405
|
+
if (ctx.includeMakefile) fileMap['Makefile'] = generateMakefile();
|
|
440
406
|
|
|
441
407
|
return {
|
|
442
408
|
success: true,
|
|
443
409
|
data: {
|
|
444
|
-
|
|
445
|
-
generatedFiles: allFiles,
|
|
410
|
+
generatedFiles: fileMap,
|
|
446
411
|
summary,
|
|
447
412
|
},
|
|
448
413
|
};
|
|
@@ -722,39 +687,41 @@ async function runNonInteractive(options: AwsTerraformOptions): Promise<void> {
|
|
|
722
687
|
resources = inventory.resources;
|
|
723
688
|
}
|
|
724
689
|
|
|
725
|
-
// Generate Terraform
|
|
690
|
+
// Generate Terraform using local generator
|
|
726
691
|
ui.startSpinner({ message: 'Generating Terraform configurations...' });
|
|
727
692
|
|
|
728
693
|
try {
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
if (
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
});
|
|
694
|
+
const resourceTypes = (resources ?? []).map(r => r.type);
|
|
695
|
+
const components: string[] = [];
|
|
696
|
+
if (resourceTypes.some(t => t.includes('VPC') || t.includes('Subnet'))) components.push('vpc');
|
|
697
|
+
if (resourceTypes.some(t => t.includes('EC2') || t.includes('Instance'))) components.push('ec2');
|
|
698
|
+
if (resourceTypes.some(t => t.includes('S3'))) components.push('s3');
|
|
699
|
+
if (resourceTypes.some(t => t.includes('RDS'))) components.push('rds');
|
|
700
|
+
if (resourceTypes.some(t => t.includes('EKS'))) components.push('eks');
|
|
701
|
+
if (components.length === 0) components.push('vpc', 's3');
|
|
702
|
+
|
|
703
|
+
const generatedProject = await generateTerraformProject({
|
|
704
|
+
projectName: 'infrastructure',
|
|
705
|
+
provider: 'aws',
|
|
706
|
+
region: resources?.[0]?.region || 'us-east-1',
|
|
707
|
+
components,
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
const files: Record<string, string> = {};
|
|
711
|
+
for (const file of generatedProject.files) {
|
|
712
|
+
files[file.path] = file.content;
|
|
749
713
|
}
|
|
750
714
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
715
|
+
const summary: GenerationSummary = {
|
|
716
|
+
totalResources: resources?.length ?? 0,
|
|
717
|
+
mappedResources: resources?.length ?? 0,
|
|
718
|
+
unmappedResources: 0,
|
|
719
|
+
filesGenerated: generatedProject.files.length,
|
|
720
|
+
servicesIncluded: components,
|
|
721
|
+
regionsIncluded: [...new Set((resources ?? []).map(r => r.region).filter(Boolean))],
|
|
722
|
+
};
|
|
755
723
|
|
|
756
|
-
|
|
757
|
-
ui.stopSpinnerSuccess(`Generated ${Object.keys(files).length} files`);
|
|
724
|
+
ui.stopSpinnerSuccess(`Generated ${Object.keys(files).length} file(s)`);
|
|
758
725
|
|
|
759
726
|
// Write files
|
|
760
727
|
const outputPath = options.output || './terraform-aws';
|
|
@@ -764,38 +731,21 @@ async function runNonInteractive(options: AwsTerraformOptions): Promise<void> {
|
|
|
764
731
|
fs.mkdirSync(outputPath, { recursive: true });
|
|
765
732
|
}
|
|
766
733
|
|
|
767
|
-
|
|
768
|
-
if (options.includeStarterKit || options.
|
|
769
|
-
|
|
770
|
-
}
|
|
771
|
-
if (options.includeStarterKit || options.includeGitignore) {
|
|
772
|
-
files['.gitignore'] = generateGitignore();
|
|
773
|
-
}
|
|
774
|
-
if (options.includeStarterKit || options.includeMakefile) {
|
|
775
|
-
files['Makefile'] = generateMakefile();
|
|
776
|
-
}
|
|
777
|
-
if (importScript && (options.importScript ?? true)) {
|
|
778
|
-
files['import.sh'] = importScript;
|
|
779
|
-
}
|
|
734
|
+
if (options.includeStarterKit || options.includeReadme) files['README.md'] = generateReadme(summary);
|
|
735
|
+
if (options.includeStarterKit || options.includeGitignore) files['.gitignore'] = generateGitignore();
|
|
736
|
+
if (options.includeStarterKit || options.includeMakefile) files['Makefile'] = generateMakefile();
|
|
780
737
|
|
|
781
738
|
for (const [fileName, content] of Object.entries(files)) {
|
|
782
739
|
const filePath = path.join(outputPath, fileName);
|
|
783
740
|
await writeFile(filePath, content as string, 'utf-8');
|
|
784
741
|
}
|
|
785
742
|
|
|
786
|
-
if (files['import.sh']) {
|
|
787
|
-
fs.chmodSync(path.join(outputPath, 'import.sh'), '755');
|
|
788
|
-
}
|
|
789
|
-
|
|
790
743
|
ui.stopSpinnerSuccess(`Wrote ${Object.keys(files).length} files to ${outputPath}`);
|
|
791
744
|
|
|
792
|
-
// Show summary
|
|
793
745
|
ui.newLine();
|
|
794
746
|
ui.success('Generation complete!');
|
|
795
747
|
ui.print(` Output: ${outputPath}`);
|
|
796
|
-
ui.print(
|
|
797
|
-
` Resources: ${summary.mappedResources} mapped, ${summary.unmappedResources} unmapped`
|
|
798
|
-
);
|
|
748
|
+
ui.print(` Resources: ${summary.mappedResources} mapped`);
|
|
799
749
|
} catch (error: any) {
|
|
800
750
|
ui.stopSpinnerFail(`Generation failed: ${error.message}`);
|
|
801
751
|
process.exit(1);
|
package/src/commands/chat.ts
CHANGED
|
@@ -30,6 +30,10 @@ export interface ChatOptions {
|
|
|
30
30
|
ui?: 'ink' | 'readline';
|
|
31
31
|
/** Resume the most recent chat session */
|
|
32
32
|
continue?: boolean;
|
|
33
|
+
/** Pre-loaded initial prompt sent as the first user message automatically */
|
|
34
|
+
initialPrompt?: string;
|
|
35
|
+
/** Initial agent mode */
|
|
36
|
+
mode?: 'plan' | 'build' | 'deploy';
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
/**
|
|
@@ -108,6 +112,8 @@ export async function chatCommand(options: ChatOptions = {}): Promise<void> {
|
|
|
108
112
|
systemPrompt: options.systemPrompt,
|
|
109
113
|
showTokenCount: options.showTokenCount,
|
|
110
114
|
resumeSessionId,
|
|
115
|
+
initialPrompt: options.initialPrompt,
|
|
116
|
+
mode: options.mode as any,
|
|
111
117
|
});
|
|
112
118
|
return;
|
|
113
119
|
} catch {
|
|
@@ -282,11 +288,11 @@ function getPersonaSystemPrompt(
|
|
|
282
288
|
verbosity: 'minimal' | 'normal' | 'detailed'
|
|
283
289
|
): string {
|
|
284
290
|
// Base identity shared across all personas
|
|
285
|
-
const baseIdentity = `You are Nimbus, an AI-powered
|
|
291
|
+
const baseIdentity = `You are Nimbus, an AI-powered DevOps engineering agent. You help users with:
|
|
286
292
|
|
|
287
|
-
- Infrastructure as Code (Terraform,
|
|
288
|
-
- Kubernetes operations and configurations
|
|
293
|
+
- Infrastructure as Code (Terraform, Kubernetes, Helm)
|
|
289
294
|
- Cloud provider operations (AWS, GCP, Azure)
|
|
295
|
+
- Kubernetes operations and configurations
|
|
290
296
|
- DevOps best practices and CI/CD pipelines
|
|
291
297
|
- Troubleshooting infrastructure issues`;
|
|
292
298
|
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell Completion Auto-Installer (L7)
|
|
3
|
+
*
|
|
4
|
+
* Installs shell completions for bash, zsh, and fish.
|
|
5
|
+
* Completion scripts are generated dynamically from the CLI command list.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import * as os from 'node:os';
|
|
11
|
+
import { ui } from '../wizard/ui';
|
|
12
|
+
|
|
13
|
+
const COMMANDS = [
|
|
14
|
+
'chat', 'run', 'init', 'login', 'logout', 'doctor', 'cost',
|
|
15
|
+
'sessions', 'audit', 'share', 'upgrade', 'serve', 'web',
|
|
16
|
+
'auth-refresh', 'plugin', 'completions', 'team-context',
|
|
17
|
+
'logs', 'pipeline', 'alias',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* L4: Get available kubectl contexts for shell completion.
|
|
22
|
+
*/
|
|
23
|
+
function getKubeContexts(): string[] {
|
|
24
|
+
try {
|
|
25
|
+
const { execFileSync } = require('node:child_process') as typeof import('node:child_process');
|
|
26
|
+
return execFileSync(
|
|
27
|
+
'kubectl',
|
|
28
|
+
['config', 'get-contexts', '--no-headers', '-o', 'name'],
|
|
29
|
+
{ encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] }
|
|
30
|
+
)
|
|
31
|
+
.trim()
|
|
32
|
+
.split('\n')
|
|
33
|
+
.filter(Boolean);
|
|
34
|
+
} catch {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* L2: Get terraform workspaces for dynamic shell completion.
|
|
41
|
+
*/
|
|
42
|
+
function getTerraformWorkspaces(): string[] {
|
|
43
|
+
try {
|
|
44
|
+
const { execFileSync } = require('node:child_process') as typeof import('node:child_process');
|
|
45
|
+
return execFileSync('terraform', ['workspace', 'list'], {
|
|
46
|
+
encoding: 'utf-8',
|
|
47
|
+
timeout: 3000,
|
|
48
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
49
|
+
})
|
|
50
|
+
.split('\n')
|
|
51
|
+
.map((l: string) => l.replace(/^\*?\s*/, '').trim())
|
|
52
|
+
.filter(Boolean);
|
|
53
|
+
} catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* L2: Get helm releases for dynamic shell completion.
|
|
60
|
+
*/
|
|
61
|
+
function getHelmReleases(): string[] {
|
|
62
|
+
try {
|
|
63
|
+
const { execFileSync } = require('node:child_process') as typeof import('node:child_process');
|
|
64
|
+
return execFileSync('helm', ['list', '--short'], {
|
|
65
|
+
encoding: 'utf-8',
|
|
66
|
+
timeout: 3000,
|
|
67
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
68
|
+
})
|
|
69
|
+
.trim()
|
|
70
|
+
.split('\n')
|
|
71
|
+
.filter(Boolean);
|
|
72
|
+
} catch {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* L2: Dynamic completion dispatcher.
|
|
79
|
+
* Called from shell with: nimbus __complete <prev_word> <curr_word>
|
|
80
|
+
*/
|
|
81
|
+
export function dynamicComplete(prevWord: string, _currWord: string): void {
|
|
82
|
+
let suggestions: string[] = [];
|
|
83
|
+
|
|
84
|
+
if (prevWord === 'workspace' || prevWord === 'ws') {
|
|
85
|
+
suggestions = getTerraformWorkspaces();
|
|
86
|
+
} else if (prevWord === 'switch' || prevWord === 'context') {
|
|
87
|
+
suggestions = getKubeContexts();
|
|
88
|
+
} else if (prevWord === 'upgrade' || prevWord === 'rollback') {
|
|
89
|
+
suggestions = getHelmReleases();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (suggestions.length > 0) {
|
|
93
|
+
process.stdout.write(suggestions.join('\n') + '\n');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const FLAGS = [
|
|
98
|
+
'--help', '--version', '--model', '--mode', '--auto-approve',
|
|
99
|
+
'--format', '--verbose', '--json', '--fix',
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
function generateBashCompletion(): string {
|
|
103
|
+
return `# Nimbus bash completion
|
|
104
|
+
_nimbus_completions() {
|
|
105
|
+
local cur prev
|
|
106
|
+
COMPREPLY=()
|
|
107
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
108
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
109
|
+
|
|
110
|
+
local commands="${COMMANDS.join(' ')}"
|
|
111
|
+
local flags="${FLAGS.join(' ')}"
|
|
112
|
+
|
|
113
|
+
if [ \$COMP_CWORD -eq 1 ]; then
|
|
114
|
+
COMPREPLY=( \$(compgen -W "\$commands" -- "\$cur") )
|
|
115
|
+
else
|
|
116
|
+
COMPREPLY=( \$(compgen -W "\$flags" -- "\$cur") )
|
|
117
|
+
fi
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
complete -F _nimbus_completions nimbus
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function generateZshCompletion(): string {
|
|
125
|
+
const commandDefs = COMMANDS.map(c => ` '${c}:${c} command'`).join('\n');
|
|
126
|
+
const kubeContexts = getKubeContexts();
|
|
127
|
+
const contextCompletion = kubeContexts.length > 0
|
|
128
|
+
? `\n '--context[kubectl context]:context:(${kubeContexts.join(' ')})' \\`
|
|
129
|
+
: '';
|
|
130
|
+
return `#compdef nimbus
|
|
131
|
+
# Nimbus zsh completion
|
|
132
|
+
|
|
133
|
+
_nimbus() {
|
|
134
|
+
local state
|
|
135
|
+
|
|
136
|
+
_arguments \\
|
|
137
|
+
'1: :->command' \\${contextCompletion}
|
|
138
|
+
'*: :->args'
|
|
139
|
+
|
|
140
|
+
case \$state in
|
|
141
|
+
command)
|
|
142
|
+
_describe 'nimbus commands' \\
|
|
143
|
+
(
|
|
144
|
+
${commandDefs}
|
|
145
|
+
)
|
|
146
|
+
;;
|
|
147
|
+
args)
|
|
148
|
+
_arguments \\
|
|
149
|
+
'--help[Show help]' \\
|
|
150
|
+
'--version[Show version]' \\
|
|
151
|
+
'--model[Specify LLM model]:model:' \\
|
|
152
|
+
'--mode[Agent mode (plan/build/deploy)]:mode:(plan build deploy)' \\
|
|
153
|
+
'--auto-approve[Auto-approve all actions]' \\
|
|
154
|
+
'--format[Output format]:format:(json text)'
|
|
155
|
+
;;
|
|
156
|
+
esac
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
_nimbus
|
|
160
|
+
`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function generateFishCompletion(): string {
|
|
164
|
+
const cmdCompletions = COMMANDS.map(
|
|
165
|
+
c => `complete -c nimbus -f -n '__fish_use_subcommand' -a '${c}'`
|
|
166
|
+
).join('\n');
|
|
167
|
+
|
|
168
|
+
return `# Nimbus fish completion
|
|
169
|
+
|
|
170
|
+
${cmdCompletions}
|
|
171
|
+
|
|
172
|
+
complete -c nimbus -l help -d 'Show help'
|
|
173
|
+
complete -c nimbus -l version -d 'Show version'
|
|
174
|
+
complete -c nimbus -l model -d 'Specify LLM model' -r
|
|
175
|
+
complete -c nimbus -l mode -d 'Agent mode' -r -a 'plan build deploy'
|
|
176
|
+
complete -c nimbus -l auto-approve -d 'Auto-approve all actions'
|
|
177
|
+
complete -c nimbus -l format -d 'Output format' -r -a 'json text'
|
|
178
|
+
`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export async function completionsCommand(subcommand: string): Promise<void> {
|
|
182
|
+
switch (subcommand) {
|
|
183
|
+
case 'install': {
|
|
184
|
+
const shell = path.basename(process.env.SHELL ?? '/bin/bash');
|
|
185
|
+
ui.info(`Detected shell: ${shell}`);
|
|
186
|
+
|
|
187
|
+
if (shell === 'bash') {
|
|
188
|
+
const dir = path.join(os.homedir(), '.bash_completion.d');
|
|
189
|
+
const file = path.join(dir, 'nimbus.bash');
|
|
190
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
191
|
+
fs.writeFileSync(file, generateBashCompletion(), 'utf-8');
|
|
192
|
+
|
|
193
|
+
// Add source to .bashrc if not already there
|
|
194
|
+
const bashrc = path.join(os.homedir(), '.bashrc');
|
|
195
|
+
const sourceLine = `\n# Nimbus completions\n[ -f "${file}" ] && source "${file}"\n`;
|
|
196
|
+
let alreadyConfigured = false;
|
|
197
|
+
try {
|
|
198
|
+
const existing = fs.readFileSync(bashrc, 'utf-8');
|
|
199
|
+
if (!existing.includes('nimbus.bash')) {
|
|
200
|
+
fs.appendFileSync(bashrc, sourceLine);
|
|
201
|
+
} else {
|
|
202
|
+
alreadyConfigured = true;
|
|
203
|
+
}
|
|
204
|
+
} catch {
|
|
205
|
+
fs.appendFileSync(bashrc, sourceLine);
|
|
206
|
+
}
|
|
207
|
+
ui.print(`${ui.color('✓', 'green')} Installed bash completions to ${file}`);
|
|
208
|
+
if (alreadyConfigured) {
|
|
209
|
+
ui.print(' Already configured, skipping.');
|
|
210
|
+
} else {
|
|
211
|
+
ui.print(' Restart your shell or run: source ~/.bashrc');
|
|
212
|
+
}
|
|
213
|
+
} else if (shell === 'zsh') {
|
|
214
|
+
const dir = path.join(os.homedir(), '.zsh', 'completions');
|
|
215
|
+
const file = path.join(dir, '_nimbus');
|
|
216
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
217
|
+
fs.writeFileSync(file, generateZshCompletion(), 'utf-8');
|
|
218
|
+
ui.print(`${ui.color('✓', 'green')} Installed zsh completions to ${file}`);
|
|
219
|
+
ui.print(' Add to .zshrc: fpath=(~/.zsh/completions $fpath) && autoload -U compinit && compinit');
|
|
220
|
+
ui.print(' Restart your shell or run: source ~/.zshrc');
|
|
221
|
+
} else if (shell === 'fish') {
|
|
222
|
+
const dir = path.join(os.homedir(), '.config', 'fish', 'completions');
|
|
223
|
+
const file = path.join(dir, 'nimbus.fish');
|
|
224
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
225
|
+
fs.writeFileSync(file, generateFishCompletion(), 'utf-8');
|
|
226
|
+
ui.print(`${ui.color('✓', 'green')} Installed fish completions to ${file}`);
|
|
227
|
+
ui.print(' Fish completions are active immediately. Restart your shell to confirm.');
|
|
228
|
+
} else {
|
|
229
|
+
ui.warning(`Shell "${shell}" not supported. Supported: bash, zsh, fish`);
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
case 'uninstall': {
|
|
235
|
+
const shell = path.basename(process.env.SHELL ?? '/bin/bash');
|
|
236
|
+
const files: string[] = [
|
|
237
|
+
path.join(os.homedir(), '.bash_completion.d', 'nimbus.bash'),
|
|
238
|
+
path.join(os.homedir(), '.zsh', 'completions', '_nimbus'),
|
|
239
|
+
path.join(os.homedir(), '.config', 'fish', 'completions', 'nimbus.fish'),
|
|
240
|
+
];
|
|
241
|
+
let removed = 0;
|
|
242
|
+
for (const f of files) {
|
|
243
|
+
if (fs.existsSync(f)) {
|
|
244
|
+
fs.unlinkSync(f);
|
|
245
|
+
ui.print(`${ui.color('✓', 'green')} Removed ${f}`);
|
|
246
|
+
removed++;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (removed === 0) {
|
|
250
|
+
ui.info('No completion files found to remove.');
|
|
251
|
+
} else {
|
|
252
|
+
ui.info(`Removed ${removed} completion file(s). Reload your shell.`);
|
|
253
|
+
}
|
|
254
|
+
void shell; // suppress unused warning
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
case '__complete': {
|
|
259
|
+
// L2: Dynamic completion dispatcher — called from shell completion scripts
|
|
260
|
+
// Usage: nimbus completions __complete <prev_word> <curr_word>
|
|
261
|
+
// (args passed as positional args by the shell)
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
default:
|
|
266
|
+
ui.print('Usage: nimbus completions <install|uninstall>');
|
|
267
|
+
}
|
|
268
|
+
}
|
package/src/commands/config.ts
CHANGED
|
@@ -115,6 +115,32 @@ export async function configSetCommand(options: ConfigSetOptions): Promise<void>
|
|
|
115
115
|
process.exit(1);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// M4: Validate model key against known model IDs
|
|
119
|
+
if (key === 'model' || key === 'llm.defaultModel') {
|
|
120
|
+
const knownModels = [
|
|
121
|
+
'claude-opus-4-6',
|
|
122
|
+
'claude-sonnet-4-6',
|
|
123
|
+
'claude-haiku-4-5-20251001',
|
|
124
|
+
'claude-opus-4-20250514',
|
|
125
|
+
'claude-sonnet-4-20250514',
|
|
126
|
+
'claude-haiku-4-5',
|
|
127
|
+
'anthropic/claude-opus-4-6',
|
|
128
|
+
'anthropic/claude-sonnet-4-6',
|
|
129
|
+
'anthropic/claude-haiku-4-5-20251001',
|
|
130
|
+
'anthropic/claude-opus-4-20250514',
|
|
131
|
+
'anthropic/claude-sonnet-4-20250514',
|
|
132
|
+
];
|
|
133
|
+
if (!knownModels.includes(value)) {
|
|
134
|
+
ui.warning(`"${value}" is not a recognized Nimbus model ID.`);
|
|
135
|
+
ui.info('Known models: ' + knownModels.slice(0, 6).join(', '));
|
|
136
|
+
if (!options.nonInteractive) {
|
|
137
|
+
const { confirm: confirmPrompt } = await import('../wizard/prompts');
|
|
138
|
+
const proceed = await confirmPrompt({ message: 'Set this model anyway?', defaultValue: false });
|
|
139
|
+
if (!proceed) return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
118
144
|
// Parse and set value
|
|
119
145
|
const parsedValue = configManager.parseValue(key, value);
|
|
120
146
|
configManager.set(key, parsedValue);
|