@build-astron-co/nimbus 0.4.2 → 0.4.3
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/dist/src/agent/compaction-agent.js +24 -12
- package/dist/src/agent/context-manager.js +2 -1
- package/dist/src/agent/expand-files.js +2 -1
- package/dist/src/agent/loop.js +71 -33
- package/dist/src/agent/permissions.js +4 -2
- package/dist/src/agent/system-prompt.js +34 -17
- package/dist/src/app.js +1 -1
- package/dist/src/auth/keychain.js +8 -4
- package/dist/src/auth/store.js +70 -107
- package/dist/src/cli/init.js +35 -19
- package/dist/src/cli/run.js +18 -10
- package/dist/src/cli/serve.js +4 -2
- package/dist/src/cli.js +52 -11
- package/dist/src/commands/alias.js +5 -3
- package/dist/src/commands/audit/index.js +2 -1
- package/dist/src/commands/aws-terraform.js +36 -18
- package/dist/src/commands/completions.js +1 -1
- package/dist/src/commands/config.js +3 -2
- package/dist/src/commands/connect-github.js +92 -0
- package/dist/src/commands/cost/index.js +3 -2
- package/dist/src/commands/deploy.js +15 -10
- package/dist/src/commands/doctor.js +6 -3
- package/dist/src/commands/drift/index.js +2 -1
- package/dist/src/commands/export.js +5 -3
- package/dist/src/commands/generate-terraform.js +110 -2
- package/dist/src/commands/import.js +3 -3
- package/dist/src/commands/incident.js +10 -5
- package/dist/src/commands/login.js +8 -93
- package/dist/src/commands/logs.js +16 -8
- package/dist/src/commands/onboarding.js +6 -4
- package/dist/src/commands/pipeline.js +6 -3
- package/dist/src/commands/plugin.js +3 -2
- package/dist/src/commands/profile.js +27 -14
- package/dist/src/commands/questionnaire.js +1 -1
- package/dist/src/commands/rollback.js +3 -2
- package/dist/src/commands/rollout.js +5 -3
- package/dist/src/commands/runbook.js +17 -10
- package/dist/src/commands/schedule.js +10 -5
- package/dist/src/commands/status.js +2 -1
- package/dist/src/commands/team-context.js +12 -7
- package/dist/src/commands/template.js +1 -1
- package/dist/src/commands/tf/index.js +6 -3
- package/dist/src/commands/version.js +6 -3
- package/dist/src/commands/watch.js +6 -3
- package/dist/src/compat/sqlite.js +5 -3
- package/dist/src/config/mode-store.js +2 -1
- package/dist/src/config/profiles.js +4 -2
- package/dist/src/config/types.js +2 -1
- package/dist/src/engine/executor.js +8 -4
- package/dist/src/engine/planner.js +9 -5
- package/dist/src/llm/providers/anthropic.js +6 -3
- package/dist/src/llm/providers/ollama.js +1 -1
- package/dist/src/llm/router.js +22 -7
- package/dist/src/sessions/manager.js +6 -3
- package/dist/src/sharing/viewer.js +2 -1
- package/dist/src/tools/file-ops.js +1 -2
- package/dist/src/tools/schemas/devops.js +197 -108
- package/dist/src/tools/schemas/standard.js +1 -1
- package/dist/src/ui/App.js +25 -13
- package/dist/src/ui/FileDiffModal.js +22 -11
- package/dist/src/ui/HelpModal.js +2 -1
- package/dist/src/ui/InputBox.js +6 -3
- package/dist/src/ui/MessageList.js +40 -20
- package/dist/src/ui/TerminalPane.js +2 -1
- package/dist/src/ui/ToolCallDisplay.js +12 -6
- package/dist/src/ui/TreePane.js +2 -1
- package/dist/src/ui/ink/index.js +37 -21
- package/dist/src/watcher/index.js +8 -4
- package/package.json +3 -5
- package/src/__tests__/alias.test.ts +0 -133
- package/src/__tests__/app.test.ts +0 -76
- package/src/__tests__/audit.test.ts +0 -877
- package/src/__tests__/circuit-breaker.test.ts +0 -116
- package/src/__tests__/cli-run.test.ts +0 -351
- package/src/__tests__/compat-sqlite.test.ts +0 -68
- package/src/__tests__/context-manager.test.ts +0 -632
- package/src/__tests__/context.test.ts +0 -242
- package/src/__tests__/devops-terminal-gaps.test.ts +0 -718
- package/src/__tests__/doctor.test.ts +0 -48
- package/src/__tests__/enterprise.test.ts +0 -401
- package/src/__tests__/export.test.ts +0 -236
- package/src/__tests__/gap-11-18-20.test.ts +0 -958
- package/src/__tests__/generator.test.ts +0 -433
- package/src/__tests__/helm-streaming.test.ts +0 -127
- package/src/__tests__/hooks.test.ts +0 -582
- package/src/__tests__/incident.test.ts +0 -179
- package/src/__tests__/init.test.ts +0 -487
- package/src/__tests__/intent-parser.test.ts +0 -229
- package/src/__tests__/llm-router.test.ts +0 -209
- package/src/__tests__/logs.test.ts +0 -107
- package/src/__tests__/loop-errors.test.ts +0 -244
- package/src/__tests__/lsp.test.ts +0 -293
- package/src/__tests__/modes.test.ts +0 -336
- package/src/__tests__/perf-optimizations.test.ts +0 -847
- package/src/__tests__/permissions.test.ts +0 -338
- package/src/__tests__/pipeline.test.ts +0 -50
- package/src/__tests__/polish-phase3.test.ts +0 -340
- package/src/__tests__/profile.test.ts +0 -237
- package/src/__tests__/rollback.test.ts +0 -83
- package/src/__tests__/runbook.test.ts +0 -219
- package/src/__tests__/schedule.test.ts +0 -206
- package/src/__tests__/serve.test.ts +0 -275
- package/src/__tests__/sessions.test.ts +0 -322
- package/src/__tests__/sharing.test.ts +0 -340
- package/src/__tests__/snapshots.test.ts +0 -581
- package/src/__tests__/standalone-migration.test.ts +0 -199
- package/src/__tests__/state-db.test.ts +0 -334
- package/src/__tests__/status.test.ts +0 -158
- package/src/__tests__/stream-with-tools.test.ts +0 -778
- package/src/__tests__/subagents.test.ts +0 -176
- package/src/__tests__/system-prompt.test.ts +0 -248
- package/src/__tests__/terminal-gap-v2.test.ts +0 -395
- package/src/__tests__/terminal-parity.test.ts +0 -393
- package/src/__tests__/tf-apply.test.ts +0 -187
- package/src/__tests__/tool-converter.test.ts +0 -256
- package/src/__tests__/tool-schemas.test.ts +0 -602
- package/src/__tests__/tools.test.ts +0 -144
- package/src/__tests__/version-json.test.ts +0 -184
- package/src/__tests__/version.test.ts +0 -49
- package/src/__tests__/watch.test.ts +0 -129
- package/src/agent/compaction-agent.ts +0 -266
- package/src/agent/context-manager.ts +0 -499
- package/src/agent/context.ts +0 -427
- package/src/agent/deploy-preview.ts +0 -487
- package/src/agent/expand-files.ts +0 -108
- package/src/agent/index.ts +0 -68
- package/src/agent/loop.ts +0 -1998
- package/src/agent/modes.ts +0 -429
- package/src/agent/permissions.ts +0 -513
- package/src/agent/subagents/base.ts +0 -116
- package/src/agent/subagents/cost.ts +0 -51
- package/src/agent/subagents/explore.ts +0 -42
- package/src/agent/subagents/general.ts +0 -54
- package/src/agent/subagents/index.ts +0 -102
- package/src/agent/subagents/infra.ts +0 -59
- package/src/agent/subagents/security.ts +0 -69
- package/src/agent/system-prompt.ts +0 -990
- package/src/app.ts +0 -180
- package/src/audit/activity-log.ts +0 -290
- package/src/audit/compliance-checker.ts +0 -540
- package/src/audit/cost-tracker.ts +0 -318
- package/src/audit/index.ts +0 -23
- package/src/audit/security-scanner.ts +0 -641
- package/src/auth/guard.ts +0 -75
- package/src/auth/index.ts +0 -56
- package/src/auth/keychain.ts +0 -82
- package/src/auth/oauth.ts +0 -465
- package/src/auth/providers.ts +0 -470
- package/src/auth/sso.ts +0 -113
- package/src/auth/store.ts +0 -505
- package/src/auth/types.ts +0 -187
- package/src/build.ts +0 -141
- package/src/cli/index.ts +0 -16
- package/src/cli/init.ts +0 -1227
- package/src/cli/openapi-spec.ts +0 -356
- package/src/cli/run.ts +0 -628
- package/src/cli/serve-auth.ts +0 -80
- package/src/cli/serve.ts +0 -539
- package/src/cli/web.ts +0 -71
- package/src/cli.ts +0 -1728
- package/src/clients/core-engine-client.ts +0 -227
- package/src/clients/enterprise-client.ts +0 -334
- package/src/clients/generator-client.ts +0 -351
- package/src/clients/git-client.ts +0 -627
- package/src/clients/github-client.ts +0 -410
- package/src/clients/helm-client.ts +0 -504
- package/src/clients/index.ts +0 -80
- package/src/clients/k8s-client.ts +0 -497
- package/src/clients/llm-client.ts +0 -161
- package/src/clients/rest-client.ts +0 -130
- package/src/clients/service-discovery.ts +0 -38
- package/src/clients/terraform-client.ts +0 -482
- package/src/clients/tools-client.ts +0 -1843
- package/src/clients/ws-client.ts +0 -115
- package/src/commands/alias.ts +0 -100
- package/src/commands/analyze/index.ts +0 -352
- package/src/commands/apply/helm.ts +0 -473
- package/src/commands/apply/index.ts +0 -213
- package/src/commands/apply/k8s.ts +0 -454
- package/src/commands/apply/terraform.ts +0 -582
- package/src/commands/ask.ts +0 -167
- package/src/commands/audit/index.ts +0 -357
- package/src/commands/auth-cloud.ts +0 -407
- package/src/commands/auth-list.ts +0 -134
- package/src/commands/auth-profile.ts +0 -121
- package/src/commands/auth-refresh.ts +0 -187
- package/src/commands/auth-status.ts +0 -141
- package/src/commands/aws/ec2.ts +0 -501
- package/src/commands/aws/iam.ts +0 -397
- package/src/commands/aws/index.ts +0 -133
- package/src/commands/aws/lambda.ts +0 -396
- package/src/commands/aws/rds.ts +0 -439
- package/src/commands/aws/s3.ts +0 -439
- package/src/commands/aws/vpc.ts +0 -393
- package/src/commands/aws-discover.ts +0 -542
- package/src/commands/aws-terraform.ts +0 -755
- package/src/commands/azure/aks.ts +0 -376
- package/src/commands/azure/functions.ts +0 -253
- package/src/commands/azure/index.ts +0 -116
- package/src/commands/azure/storage.ts +0 -478
- package/src/commands/azure/vm.ts +0 -355
- package/src/commands/billing/index.ts +0 -256
- package/src/commands/chat.ts +0 -320
- package/src/commands/completions.ts +0 -268
- package/src/commands/config.ts +0 -372
- package/src/commands/cost/cloud-cost-estimator.ts +0 -266
- package/src/commands/cost/estimator.ts +0 -79
- package/src/commands/cost/index.ts +0 -810
- package/src/commands/cost/parsers/terraform.ts +0 -273
- package/src/commands/cost/parsers/types.ts +0 -25
- package/src/commands/cost/pricing/aws.ts +0 -544
- package/src/commands/cost/pricing/azure.ts +0 -499
- package/src/commands/cost/pricing/gcp.ts +0 -396
- package/src/commands/cost/pricing/index.ts +0 -40
- package/src/commands/demo.ts +0 -250
- package/src/commands/deploy.ts +0 -260
- package/src/commands/doctor.ts +0 -1386
- package/src/commands/drift/index.ts +0 -787
- package/src/commands/explain.ts +0 -277
- package/src/commands/export.ts +0 -146
- package/src/commands/feedback.ts +0 -389
- package/src/commands/fix.ts +0 -324
- package/src/commands/fs/index.ts +0 -402
- package/src/commands/gcp/compute.ts +0 -325
- package/src/commands/gcp/functions.ts +0 -271
- package/src/commands/gcp/gke.ts +0 -438
- package/src/commands/gcp/iam.ts +0 -344
- package/src/commands/gcp/index.ts +0 -129
- package/src/commands/gcp/storage.ts +0 -284
- package/src/commands/generate-helm.ts +0 -1249
- package/src/commands/generate-k8s.ts +0 -1508
- package/src/commands/generate-terraform.ts +0 -1202
- package/src/commands/gh/index.ts +0 -863
- package/src/commands/git/index.ts +0 -1343
- package/src/commands/helm/index.ts +0 -1126
- package/src/commands/help.ts +0 -715
- package/src/commands/history.ts +0 -149
- package/src/commands/import.ts +0 -868
- package/src/commands/incident.ts +0 -166
- package/src/commands/index.ts +0 -367
- package/src/commands/init.ts +0 -1051
- package/src/commands/k8s/index.ts +0 -1137
- package/src/commands/login.ts +0 -716
- package/src/commands/logout.ts +0 -83
- package/src/commands/logs.ts +0 -167
- package/src/commands/onboarding.ts +0 -405
- package/src/commands/pipeline.ts +0 -186
- package/src/commands/plan/display.ts +0 -279
- package/src/commands/plan/index.ts +0 -599
- package/src/commands/plugin.ts +0 -398
- package/src/commands/preview.ts +0 -452
- package/src/commands/profile.ts +0 -342
- package/src/commands/questionnaire.ts +0 -1172
- package/src/commands/resume.ts +0 -47
- package/src/commands/rollback.ts +0 -315
- package/src/commands/rollout.ts +0 -88
- package/src/commands/runbook.ts +0 -346
- package/src/commands/schedule.ts +0 -236
- package/src/commands/status.ts +0 -252
- package/src/commands/team/index.ts +0 -346
- package/src/commands/team-context.ts +0 -220
- package/src/commands/template.ts +0 -233
- package/src/commands/tf/index.ts +0 -1093
- package/src/commands/upgrade.ts +0 -609
- package/src/commands/usage/index.ts +0 -134
- package/src/commands/version.ts +0 -174
- package/src/commands/watch.ts +0 -153
- package/src/compat/index.ts +0 -2
- package/src/compat/runtime.ts +0 -12
- package/src/compat/sqlite.ts +0 -177
- package/src/config/index.ts +0 -17
- package/src/config/manager.ts +0 -530
- package/src/config/mode-store.ts +0 -62
- package/src/config/profiles.ts +0 -84
- package/src/config/safety-policy.ts +0 -358
- package/src/config/schema.ts +0 -125
- package/src/config/types.ts +0 -609
- package/src/config/workspace-state.ts +0 -53
- package/src/context/context-db.ts +0 -199
- package/src/demo/index.ts +0 -349
- package/src/demo/scenarios/full-journey.ts +0 -229
- package/src/demo/scenarios/getting-started.ts +0 -127
- package/src/demo/scenarios/helm-release.ts +0 -341
- package/src/demo/scenarios/k8s-deployment.ts +0 -194
- package/src/demo/scenarios/terraform-vpc.ts +0 -170
- package/src/demo/types.ts +0 -92
- package/src/engine/cost-estimator.ts +0 -480
- package/src/engine/diagram-generator.ts +0 -256
- package/src/engine/drift-detector.ts +0 -902
- package/src/engine/executor.ts +0 -1066
- package/src/engine/index.ts +0 -76
- package/src/engine/orchestrator.ts +0 -636
- package/src/engine/planner.ts +0 -787
- package/src/engine/safety.ts +0 -743
- package/src/engine/verifier.ts +0 -770
- package/src/enterprise/audit.ts +0 -348
- package/src/enterprise/auth.ts +0 -270
- package/src/enterprise/billing.ts +0 -822
- package/src/enterprise/index.ts +0 -17
- package/src/enterprise/teams.ts +0 -443
- package/src/generator/best-practices.ts +0 -1608
- package/src/generator/helm.ts +0 -630
- package/src/generator/index.ts +0 -37
- package/src/generator/intent-parser.ts +0 -514
- package/src/generator/kubernetes.ts +0 -976
- package/src/generator/terraform.ts +0 -1875
- package/src/history/index.ts +0 -8
- package/src/history/manager.ts +0 -250
- package/src/history/types.ts +0 -34
- package/src/hooks/config.ts +0 -432
- package/src/hooks/engine.ts +0 -392
- package/src/hooks/index.ts +0 -4
- package/src/llm/auth-bridge.ts +0 -198
- package/src/llm/circuit-breaker.ts +0 -140
- package/src/llm/config-loader.ts +0 -201
- package/src/llm/cost-calculator.ts +0 -171
- package/src/llm/index.ts +0 -8
- package/src/llm/model-aliases.ts +0 -115
- package/src/llm/provider-registry.ts +0 -63
- package/src/llm/providers/anthropic.ts +0 -462
- package/src/llm/providers/bedrock.ts +0 -477
- package/src/llm/providers/google.ts +0 -405
- package/src/llm/providers/ollama.ts +0 -767
- package/src/llm/providers/openai-compatible.ts +0 -340
- package/src/llm/providers/openai.ts +0 -328
- package/src/llm/providers/openrouter.ts +0 -338
- package/src/llm/router.ts +0 -1104
- package/src/llm/types.ts +0 -232
- package/src/lsp/client.ts +0 -298
- package/src/lsp/languages.ts +0 -119
- package/src/lsp/manager.ts +0 -294
- package/src/mcp/client.ts +0 -402
- package/src/mcp/index.ts +0 -5
- package/src/mcp/manager.ts +0 -133
- package/src/nimbus.ts +0 -234
- package/src/plugins/index.ts +0 -27
- package/src/plugins/loader.ts +0 -334
- package/src/plugins/manager.ts +0 -376
- package/src/plugins/types.ts +0 -284
- package/src/scanners/cicd-scanner.ts +0 -258
- package/src/scanners/cloud-scanner.ts +0 -466
- package/src/scanners/framework-scanner.ts +0 -469
- package/src/scanners/iac-scanner.ts +0 -388
- package/src/scanners/index.ts +0 -539
- package/src/scanners/language-scanner.ts +0 -276
- package/src/scanners/package-manager-scanner.ts +0 -277
- package/src/scanners/types.ts +0 -172
- package/src/sessions/manager.ts +0 -472
- package/src/sessions/types.ts +0 -44
- package/src/sharing/sync.ts +0 -300
- package/src/sharing/viewer.ts +0 -163
- package/src/snapshots/index.ts +0 -2
- package/src/snapshots/manager.ts +0 -530
- package/src/state/artifacts.ts +0 -147
- package/src/state/audit.ts +0 -137
- package/src/state/billing.ts +0 -240
- package/src/state/checkpoints.ts +0 -117
- package/src/state/config.ts +0 -67
- package/src/state/conversations.ts +0 -14
- package/src/state/credentials.ts +0 -154
- package/src/state/db.ts +0 -58
- package/src/state/index.ts +0 -26
- package/src/state/messages.ts +0 -115
- package/src/state/projects.ts +0 -123
- package/src/state/schema.ts +0 -236
- package/src/state/sessions.ts +0 -147
- package/src/state/teams.ts +0 -200
- package/src/telemetry.ts +0 -108
- package/src/tools/aws-ops.ts +0 -952
- package/src/tools/azure-ops.ts +0 -579
- package/src/tools/file-ops.ts +0 -615
- package/src/tools/gcp-ops.ts +0 -625
- package/src/tools/git-ops.ts +0 -773
- package/src/tools/github-ops.ts +0 -799
- package/src/tools/helm-ops.ts +0 -943
- package/src/tools/index.ts +0 -17
- package/src/tools/k8s-ops.ts +0 -819
- package/src/tools/schemas/converter.ts +0 -184
- package/src/tools/schemas/devops.ts +0 -3502
- package/src/tools/schemas/index.ts +0 -73
- package/src/tools/schemas/standard.ts +0 -1148
- package/src/tools/schemas/types.ts +0 -735
- package/src/tools/spawn-exec.ts +0 -148
- package/src/tools/terraform-ops.ts +0 -862
- package/src/types/ambient.d.ts +0 -193
- package/src/types/config.ts +0 -83
- package/src/types/drift.ts +0 -116
- package/src/types/enterprise.ts +0 -335
- package/src/types/index.ts +0 -20
- package/src/types/plan.ts +0 -44
- package/src/types/request.ts +0 -65
- package/src/types/response.ts +0 -54
- package/src/types/service.ts +0 -51
- package/src/ui/App.tsx +0 -2114
- package/src/ui/DeployPreview.tsx +0 -174
- package/src/ui/FileDiffModal.tsx +0 -162
- package/src/ui/Header.tsx +0 -131
- package/src/ui/HelpModal.tsx +0 -57
- package/src/ui/InputBox.tsx +0 -503
- package/src/ui/MessageList.tsx +0 -1032
- package/src/ui/PermissionPrompt.tsx +0 -163
- package/src/ui/StatusBar.tsx +0 -277
- package/src/ui/TerminalPane.tsx +0 -84
- package/src/ui/ToolCallDisplay.tsx +0 -643
- package/src/ui/TreePane.tsx +0 -132
- package/src/ui/chat-ui.ts +0 -850
- package/src/ui/index.ts +0 -33
- package/src/ui/ink/index.ts +0 -1444
- package/src/ui/streaming.ts +0 -176
- package/src/ui/theme.ts +0 -104
- package/src/ui/types.ts +0 -75
- package/src/utils/analytics.ts +0 -72
- package/src/utils/cost-warning.ts +0 -27
- package/src/utils/env.ts +0 -46
- package/src/utils/errors.ts +0 -69
- package/src/utils/event-bus.ts +0 -38
- package/src/utils/index.ts +0 -24
- package/src/utils/logger.ts +0 -171
- package/src/utils/rate-limiter.ts +0 -121
- package/src/utils/service-auth.ts +0 -49
- package/src/utils/validation.ts +0 -53
- package/src/version.ts +0 -4
- package/src/watcher/index.ts +0 -214
- package/src/wizard/approval.ts +0 -383
- package/src/wizard/index.ts +0 -25
- package/src/wizard/prompts.ts +0 -338
- package/src/wizard/types.ts +0 -172
- package/src/wizard/ui.ts +0 -556
- package/src/wizard/wizard.ts +0 -304
- package/tsconfig.json +0 -24
|
@@ -80,18 +80,24 @@ export async function runCompaction(messages, contextManager, options) {
|
|
|
80
80
|
if (options.infraContext) {
|
|
81
81
|
const ic = options.infraContext;
|
|
82
82
|
const infraLines = [];
|
|
83
|
-
if (ic.terraformWorkspace)
|
|
83
|
+
if (ic.terraformWorkspace) {
|
|
84
84
|
infraLines.push(`- Terraform workspace: ${ic.terraformWorkspace}`);
|
|
85
|
-
|
|
85
|
+
}
|
|
86
|
+
if (ic.kubectlContext) {
|
|
86
87
|
infraLines.push(`- kubectl context: ${ic.kubectlContext}`);
|
|
87
|
-
|
|
88
|
+
}
|
|
89
|
+
if (ic.awsProfile) {
|
|
88
90
|
infraLines.push(`- AWS profile: ${ic.awsProfile}`);
|
|
89
|
-
|
|
91
|
+
}
|
|
92
|
+
if (ic.awsRegion) {
|
|
90
93
|
infraLines.push(`- AWS region: ${ic.awsRegion}`);
|
|
91
|
-
|
|
94
|
+
}
|
|
95
|
+
if (ic.gcpProject) {
|
|
92
96
|
infraLines.push(`- GCP project: ${ic.gcpProject}`);
|
|
93
|
-
|
|
97
|
+
}
|
|
98
|
+
if (ic.azureSubscription) {
|
|
94
99
|
infraLines.push(`- Azure subscription: ${ic.azureSubscription}`);
|
|
100
|
+
}
|
|
95
101
|
if (infraLines.length > 0) {
|
|
96
102
|
userPrompt += `\n\n## ALWAYS PRESERVE IN SUMMARY (do not omit):\n${infraLines.join('\n')}`;
|
|
97
103
|
}
|
|
@@ -119,18 +125,24 @@ export async function runCompaction(messages, contextManager, options) {
|
|
|
119
125
|
if (options.infraContext) {
|
|
120
126
|
const ic = options.infraContext;
|
|
121
127
|
const infraLines = [];
|
|
122
|
-
if (ic.terraformWorkspace)
|
|
128
|
+
if (ic.terraformWorkspace) {
|
|
123
129
|
infraLines.push(`- Terraform workspace: ${ic.terraformWorkspace}`);
|
|
124
|
-
|
|
130
|
+
}
|
|
131
|
+
if (ic.kubectlContext) {
|
|
125
132
|
infraLines.push(`- kubectl context: ${ic.kubectlContext}`);
|
|
126
|
-
|
|
133
|
+
}
|
|
134
|
+
if (ic.awsProfile) {
|
|
127
135
|
infraLines.push(`- AWS profile: ${ic.awsProfile}`);
|
|
128
|
-
|
|
136
|
+
}
|
|
137
|
+
if (ic.awsRegion) {
|
|
129
138
|
infraLines.push(`- AWS region: ${ic.awsRegion}`);
|
|
130
|
-
|
|
139
|
+
}
|
|
140
|
+
if (ic.gcpProject) {
|
|
131
141
|
infraLines.push(`- GCP project: ${ic.gcpProject}`);
|
|
132
|
-
|
|
142
|
+
}
|
|
143
|
+
if (ic.azureSubscription) {
|
|
133
144
|
infraLines.push(`- Azure subscription: ${ic.azureSubscription}`);
|
|
145
|
+
}
|
|
134
146
|
if (infraLines.length > 0) {
|
|
135
147
|
finalSummary = `## Infrastructure Context\n${infraLines.join('\n')}\n\n${summary}`;
|
|
136
148
|
}
|
|
@@ -188,8 +188,9 @@ export class ContextManager {
|
|
|
188
188
|
const tcIds = msg.toolCalls?.map(tc => tc.id).join(',') ?? '';
|
|
189
189
|
const key = `${msg.role}:${contentLen}:${tcCount}:${tcIds}`;
|
|
190
190
|
const cached = this._tokenCache.get(key);
|
|
191
|
-
if (cached !== undefined)
|
|
191
|
+
if (cached !== undefined) {
|
|
192
192
|
return cached;
|
|
193
|
+
}
|
|
193
194
|
const val = estimateMessageTokens(msg);
|
|
194
195
|
this._tokenCache.set(key, val);
|
|
195
196
|
return val;
|
|
@@ -24,8 +24,9 @@ const SENSITIVE_FILE_RE = /(\.env|\.pem|\.key|\.p12|\.pfx|id_rsa|id_ed25519|cred
|
|
|
24
24
|
*/
|
|
25
25
|
export function expandFileReferences(text, cwd = process.cwd()) {
|
|
26
26
|
const fileRefs = text.match(/@([\w./_-]+)/g);
|
|
27
|
-
if (!fileRefs)
|
|
27
|
+
if (!fileRefs) {
|
|
28
28
|
return text;
|
|
29
|
+
}
|
|
29
30
|
let expanded = text;
|
|
30
31
|
// G22: Handle @workspace special token — concatenate all .tf files
|
|
31
32
|
if (expanded.includes('@workspace')) {
|
package/dist/src/agent/loop.js
CHANGED
|
@@ -27,6 +27,7 @@ import { maskSecrets } from '../audit/security-scanner';
|
|
|
27
27
|
import { classifyTaskComplexity, routeModel } from '../llm/router';
|
|
28
28
|
import { mkdirSync as _cpMkdirSync, writeFileSync as _cpWriteFileSync } from 'node:fs';
|
|
29
29
|
import { homedir as _cpHomedir } from 'node:os';
|
|
30
|
+
import { authStore } from '../auth/store';
|
|
30
31
|
// ---------------------------------------------------------------------------
|
|
31
32
|
// C2: Infra state checkpoint helper
|
|
32
33
|
// ---------------------------------------------------------------------------
|
|
@@ -58,7 +59,7 @@ function writeInfraCheckpoint(tool, action, input) {
|
|
|
58
59
|
cwd: process.cwd(),
|
|
59
60
|
workdir: input.workdir ?? undefined,
|
|
60
61
|
};
|
|
61
|
-
const fileName = timestamp.replace(/[:.]/g, '-')
|
|
62
|
+
const fileName = `${timestamp.replace(/[:.]/g, '-')}.json`;
|
|
62
63
|
_cpWriteFileSync(join(checkpointsDir, fileName), JSON.stringify(checkpoint, null, 2), 'utf-8');
|
|
63
64
|
}
|
|
64
65
|
catch { /* non-critical */ }
|
|
@@ -274,11 +275,13 @@ function isRetryableStreamError(err) {
|
|
|
274
275
|
const e = err;
|
|
275
276
|
const status = (typeof e.status === 'number' ? e.status : undefined) ??
|
|
276
277
|
(typeof e.statusCode === 'number' ? e.statusCode : undefined);
|
|
277
|
-
if (status === 429 || (status !== undefined && status >= 500 && status < 600))
|
|
278
|
+
if (status === 429 || (status !== undefined && status >= 500 && status < 600)) {
|
|
278
279
|
return true;
|
|
280
|
+
}
|
|
279
281
|
const msg = typeof e.message === 'string' ? e.message : '';
|
|
280
|
-
if (/rate.?limit|429|too many requests|overloaded|503/i.test(msg))
|
|
282
|
+
if (/rate.?limit|429|too many requests|overloaded|503/i.test(msg)) {
|
|
281
283
|
return true;
|
|
284
|
+
}
|
|
282
285
|
}
|
|
283
286
|
return false;
|
|
284
287
|
}
|
|
@@ -319,12 +322,15 @@ function extractCostHintFromToolOutput(toolName, input, output) {
|
|
|
319
322
|
const changed = Number(m[2]);
|
|
320
323
|
const destroyed = Number(m[3]);
|
|
321
324
|
const parts = [];
|
|
322
|
-
if (added > 0)
|
|
325
|
+
if (added > 0) {
|
|
323
326
|
parts.push(`+${added} resources created`);
|
|
324
|
-
|
|
327
|
+
}
|
|
328
|
+
if (changed > 0) {
|
|
325
329
|
parts.push(`${changed} updated`);
|
|
326
|
-
|
|
330
|
+
}
|
|
331
|
+
if (destroyed > 0) {
|
|
327
332
|
parts.push(`${destroyed} destroyed`);
|
|
333
|
+
}
|
|
328
334
|
return parts.length > 0
|
|
329
335
|
? `${parts.join(', ')} — run "nimbus cost" for monthly cost estimate`
|
|
330
336
|
: null;
|
|
@@ -352,11 +358,13 @@ function trackAndPersistError(toolName, errorHint, cwd) {
|
|
|
352
358
|
const { existsSync, readFileSync, writeFileSync, appendFileSync } = require('node:fs');
|
|
353
359
|
const { join } = require('node:path');
|
|
354
360
|
const nimbusPath = join(cwd, 'NIMBUS.md');
|
|
355
|
-
if (!existsSync(nimbusPath))
|
|
361
|
+
if (!existsSync(nimbusPath)) {
|
|
356
362
|
return;
|
|
363
|
+
}
|
|
357
364
|
const existing = readFileSync(nimbusPath, 'utf-8');
|
|
358
|
-
if (existing.includes(errorHint.slice(0, 40)))
|
|
359
|
-
return;
|
|
365
|
+
if (existing.includes(errorHint.slice(0, 40))) {
|
|
366
|
+
return;
|
|
367
|
+
} // already recorded
|
|
360
368
|
const entry = `- ${toolName}: ${errorHint}\n`;
|
|
361
369
|
if (existing.includes('## Observed Issues')) {
|
|
362
370
|
writeFileSync(nimbusPath, existing.replace('## Observed Issues\n', `## Observed Issues\n${entry}`));
|
|
@@ -394,8 +402,9 @@ function cacheTerraformPlan(workdir, output) {
|
|
|
394
402
|
/** Retrieve a cached terraform plan for a workdir, or null if expired/missing. */
|
|
395
403
|
function getCachedTerraformPlan(workdir) {
|
|
396
404
|
const entry = terraformPlanCache.get(workdir);
|
|
397
|
-
if (!entry)
|
|
405
|
+
if (!entry) {
|
|
398
406
|
return null;
|
|
407
|
+
}
|
|
399
408
|
if (Date.now() - entry.timestamp > PLAN_CACHE_TTL_MS) {
|
|
400
409
|
terraformPlanCache.delete(workdir);
|
|
401
410
|
return null;
|
|
@@ -561,6 +570,8 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
561
570
|
// A1: Retry on transient errors (rate-limit / 5xx) with exponential backoff
|
|
562
571
|
const MAX_STREAM_RETRIES = 2;
|
|
563
572
|
let streamAttempt = 0;
|
|
573
|
+
// Flag to prevent infinite 401-retry loops (attempt re-init only once per turn)
|
|
574
|
+
let _401RecoveryAttempted = false;
|
|
564
575
|
while (true) {
|
|
565
576
|
// A2: Silence timeout — abort if no chunk arrives (G21: configurable)
|
|
566
577
|
const STREAM_SILENCE_MS = options.streamSilenceTimeoutMs ?? 60_000;
|
|
@@ -611,13 +622,30 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
611
622
|
responseUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
612
623
|
continue;
|
|
613
624
|
}
|
|
614
|
-
//
|
|
625
|
+
// 401 auto-recovery: reinitialize providers in case credentials were just updated
|
|
615
626
|
const streamErrObj = streamErr;
|
|
627
|
+
const is401 = streamErrObj?.status === 401 || streamErrObj?.statusCode === 401
|
|
628
|
+
|| /401|Invalid API Key|Unauthorized|authentication_error/i.test(streamErrObj?.message ?? '');
|
|
629
|
+
if (is401 && !_401RecoveryAttempted) {
|
|
630
|
+
_401RecoveryAttempted = true;
|
|
631
|
+
try {
|
|
632
|
+
authStore.reload();
|
|
633
|
+
router.reinitializeProviders();
|
|
634
|
+
}
|
|
635
|
+
catch { /* non-critical */ }
|
|
636
|
+
// Reset partial accumulation and retry once
|
|
637
|
+
responseContent = '';
|
|
638
|
+
responseToolCalls = undefined;
|
|
639
|
+
responseUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
// G24: Graceful network error message instead of raw Node.js error
|
|
616
643
|
const isNetworkError = /ECONNREFUSED|ETIMEDOUT|ENOTFOUND|fetch failed|network/i.test(streamErrObj?.message ?? '');
|
|
617
644
|
if (isNetworkError) {
|
|
618
645
|
const netMsg = '\n[!!] Network unreachable — cannot reach the LLM API.\nCheck your internet connection and API key validity, then try again.\n';
|
|
619
|
-
if (onText)
|
|
646
|
+
if (onText) {
|
|
620
647
|
onText(netMsg);
|
|
648
|
+
}
|
|
621
649
|
// Re-throw a specially-marked error so the outer turn catch block can handle it
|
|
622
650
|
const netErr = new Error(netMsg);
|
|
623
651
|
netErr._nimbusNetworkError = true;
|
|
@@ -651,8 +679,9 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
651
679
|
// G16: Cost budget enforcement — stop if cumulative cost exceeds the limit
|
|
652
680
|
if (options.costBudgetUSD !== undefined && totalCost >= options.costBudgetUSD) {
|
|
653
681
|
const budgetMsg = `\n\n[!!] Cost budget of $${options.costBudgetUSD.toFixed(2)} reached (used: $${totalCost.toFixed(3)}). Stopping to prevent overspend.\n`;
|
|
654
|
-
if (onText)
|
|
682
|
+
if (onText) {
|
|
655
683
|
onText(budgetMsg);
|
|
684
|
+
}
|
|
656
685
|
messages.push({ role: 'assistant', content: budgetMsg });
|
|
657
686
|
break;
|
|
658
687
|
}
|
|
@@ -747,7 +776,7 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
747
776
|
if (destructiveWarning) {
|
|
748
777
|
messages.push({
|
|
749
778
|
role: 'tool',
|
|
750
|
-
toolCallId: toolCall.id
|
|
779
|
+
toolCallId: `${toolCall.id}-guard`,
|
|
751
780
|
name: toolCall.function.name,
|
|
752
781
|
content: `[SAFETY] ${destructiveWarning}`,
|
|
753
782
|
});
|
|
@@ -798,11 +827,11 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
798
827
|
}
|
|
799
828
|
const refreshMsg = [
|
|
800
829
|
'[!!] Credential expired. Run: nimbus auth-refresh',
|
|
801
|
-
|
|
830
|
+
`[Nimbus] Credential error detected on tool: ${toolCall.function.name}`,
|
|
802
831
|
'Run "nimbus auth-refresh" to refresh cloud credentials, then retry.',
|
|
803
832
|
].join('\n');
|
|
804
|
-
toolContent +=
|
|
805
|
-
result.output +=
|
|
833
|
+
toolContent += `\n\n${refreshMsg}`;
|
|
834
|
+
result.output += `\n\n${refreshMsg}`;
|
|
806
835
|
}
|
|
807
836
|
}
|
|
808
837
|
else if (DEVOPS_TOOL_NAMES.has(toolCall.function.name)) {
|
|
@@ -884,7 +913,7 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
884
913
|
cwd: options.cwd ?? process.cwd(),
|
|
885
914
|
timestamp: new Date().toISOString(),
|
|
886
915
|
});
|
|
887
|
-
appendFileSync(join(auditDir, 'audit.jsonl'), event
|
|
916
|
+
appendFileSync(join(auditDir, 'audit.jsonl'), `${event}\n`, 'utf-8');
|
|
888
917
|
}
|
|
889
918
|
catch { /* audit logging is non-critical */ }
|
|
890
919
|
}
|
|
@@ -927,8 +956,9 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
927
956
|
const batchFiles = buildFileDiffBatchFromPlan({ changes });
|
|
928
957
|
for (const file of batchFiles) {
|
|
929
958
|
const decision = await options.requestFileDiff(file.filePath, file.toolName ?? 'terraform', file.diff ?? '');
|
|
930
|
-
if (decision === 'reject-all')
|
|
959
|
+
if (decision === 'reject-all') {
|
|
931
960
|
break;
|
|
961
|
+
}
|
|
932
962
|
}
|
|
933
963
|
}
|
|
934
964
|
}
|
|
@@ -1016,13 +1046,13 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
1016
1046
|
const outFile = join(outDir, `${Date.now()}-${toolCall.function.name}.log`);
|
|
1017
1047
|
_writeFileSync(outFile, toolContent, 'utf-8');
|
|
1018
1048
|
toolContent = omitted > 0
|
|
1019
|
-
? `${head}${tail ?
|
|
1020
|
-
: `${head}${tail ?
|
|
1049
|
+
? `${head}${tail ? `\n\n... [${omitted} lines omitted — full output saved to ${outFile}] ...\n\n${tail}` : `\n\n... [full output saved to ${outFile}]`}`
|
|
1050
|
+
: `${head}${tail ? `\n\n${tail}` : ''}`;
|
|
1021
1051
|
}
|
|
1022
1052
|
catch {
|
|
1023
1053
|
toolContent = omitted > 0
|
|
1024
|
-
? `${head}${tail ?
|
|
1025
|
-
: `${head}${tail ?
|
|
1054
|
+
? `${head}${tail ? `\n\n... [${omitted} lines omitted — output too large for context] ...\n\n${tail}` : `\n\n... [${omitted} lines omitted]`}`
|
|
1055
|
+
: `${head}${tail ? `\n\n${tail}` : ''}`;
|
|
1026
1056
|
}
|
|
1027
1057
|
}
|
|
1028
1058
|
messages.push({
|
|
@@ -1112,14 +1142,17 @@ export async function runAgentLoop(userMessage, history, options) {
|
|
|
1112
1142
|
const kubectl = allToolCalls.filter(c => c.name === 'kubectl');
|
|
1113
1143
|
const helm = allToolCalls.filter(c => c.name === 'helm');
|
|
1114
1144
|
const summaryLines = ['---', '**Session Summary**'];
|
|
1115
|
-
if (terraform.length)
|
|
1145
|
+
if (terraform.length) {
|
|
1116
1146
|
summaryLines.push(`• Terraform: ${terraform.map(c => String(c.input.action ?? '')).join(', ')}`);
|
|
1117
|
-
|
|
1147
|
+
}
|
|
1148
|
+
if (kubectl.length) {
|
|
1118
1149
|
summaryLines.push(`• Kubectl: ${kubectl.map(c => String(c.input.action ?? '')).join(', ')}`);
|
|
1119
|
-
|
|
1150
|
+
}
|
|
1151
|
+
if (helm.length) {
|
|
1120
1152
|
summaryLines.push(`• Helm: ${helm.map(c => String(c.input.action ?? '')).join(', ')}`);
|
|
1153
|
+
}
|
|
1121
1154
|
if (summaryLines.length > 2) {
|
|
1122
|
-
options.onText(
|
|
1155
|
+
options.onText(`\n\n${summaryLines.join('\n')}`);
|
|
1123
1156
|
}
|
|
1124
1157
|
}
|
|
1125
1158
|
}
|
|
@@ -1178,8 +1211,9 @@ async function computeProposedDiff(toolName, args) {
|
|
|
1178
1211
|
try {
|
|
1179
1212
|
const { readFile } = await import('node:fs/promises');
|
|
1180
1213
|
const path = args.path;
|
|
1181
|
-
if (!path)
|
|
1214
|
+
if (!path) {
|
|
1182
1215
|
return null;
|
|
1216
|
+
}
|
|
1183
1217
|
const currentContent = await readFile(path, 'utf-8').catch(() => '');
|
|
1184
1218
|
let proposed = currentContent;
|
|
1185
1219
|
if (toolName === 'edit_file') {
|
|
@@ -1196,8 +1230,9 @@ async function computeProposedDiff(toolName, args) {
|
|
|
1196
1230
|
else if (toolName === 'write_file') {
|
|
1197
1231
|
proposed = args.content;
|
|
1198
1232
|
}
|
|
1199
|
-
if (proposed === currentContent)
|
|
1200
|
-
return null;
|
|
1233
|
+
if (proposed === currentContent) {
|
|
1234
|
+
return null;
|
|
1235
|
+
} // no change
|
|
1201
1236
|
return generateUnifiedDiff(path, currentContent, proposed);
|
|
1202
1237
|
}
|
|
1203
1238
|
catch {
|
|
@@ -1328,8 +1363,9 @@ async function executeToolCall(toolCall, registry, onStart, onEnd, checkPermissi
|
|
|
1328
1363
|
error: undefined,
|
|
1329
1364
|
isError: false,
|
|
1330
1365
|
};
|
|
1331
|
-
if (onEnd)
|
|
1366
|
+
if (onEnd) {
|
|
1332
1367
|
onEnd(callInfo, rejResult);
|
|
1368
|
+
}
|
|
1333
1369
|
return rejResult;
|
|
1334
1370
|
}
|
|
1335
1371
|
const diff = await computeProposedDiff(toolName, parsedArgs);
|
|
@@ -1342,8 +1378,9 @@ async function executeToolCall(toolCall, registry, onStart, onEnd, checkPermissi
|
|
|
1342
1378
|
error: undefined,
|
|
1343
1379
|
isError: false,
|
|
1344
1380
|
};
|
|
1345
|
-
if (onEnd)
|
|
1381
|
+
if (onEnd) {
|
|
1346
1382
|
onEnd(callInfo, rejResult);
|
|
1383
|
+
}
|
|
1347
1384
|
return rejResult;
|
|
1348
1385
|
}
|
|
1349
1386
|
if (decision === 'reject-all') {
|
|
@@ -1355,8 +1392,9 @@ async function executeToolCall(toolCall, registry, onStart, onEnd, checkPermissi
|
|
|
1355
1392
|
error: undefined,
|
|
1356
1393
|
isError: false,
|
|
1357
1394
|
};
|
|
1358
|
-
if (onEnd)
|
|
1395
|
+
if (onEnd) {
|
|
1359
1396
|
onEnd(callInfo, rejResult);
|
|
1397
|
+
}
|
|
1360
1398
|
return rejResult;
|
|
1361
1399
|
}
|
|
1362
1400
|
if (decision === 'apply-all' && skipRemainingDiffPrompts) {
|
|
@@ -131,8 +131,9 @@ export function checkPermission(tool, input, sessionState, config, autoApprove /
|
|
|
131
131
|
) {
|
|
132
132
|
// H2: When running in CI / --auto-approve / --non-interactive mode,
|
|
133
133
|
// bypass all tier logic and immediately allow the tool call.
|
|
134
|
-
if (autoApprove)
|
|
134
|
+
if (autoApprove) {
|
|
135
135
|
return 'allow';
|
|
136
|
+
}
|
|
136
137
|
// 1. Check user overrides first
|
|
137
138
|
if (config?.toolOverrides?.[tool.name]) {
|
|
138
139
|
const overrideTier = config.toolOverrides[tool.name];
|
|
@@ -362,8 +363,9 @@ function checkHelmPermission(input, _sessionState) {
|
|
|
362
363
|
* @returns `'block'` if forbidden, `null` otherwise.
|
|
363
364
|
*/
|
|
364
365
|
export function checkForbiddenPatterns(toolName, input, forbiddenRules) {
|
|
365
|
-
if (forbiddenRules.length === 0)
|
|
366
|
+
if (forbiddenRules.length === 0) {
|
|
366
367
|
return null;
|
|
368
|
+
}
|
|
367
369
|
const inputStr = JSON.stringify(input ?? {}).toLowerCase();
|
|
368
370
|
const toolLower = toolName.toLowerCase();
|
|
369
371
|
for (const rule of forbiddenRules) {
|
|
@@ -100,19 +100,24 @@ export function buildSystemPrompt(options) {
|
|
|
100
100
|
if (options.infraContext) {
|
|
101
101
|
const ic = options.infraContext;
|
|
102
102
|
const lines = ['## Current Infrastructure Context'];
|
|
103
|
-
if (ic.terraformWorkspace)
|
|
103
|
+
if (ic.terraformWorkspace) {
|
|
104
104
|
lines.push(`- Terraform workspace: ${ic.terraformWorkspace}`);
|
|
105
|
-
|
|
105
|
+
}
|
|
106
|
+
if (ic.kubectlContext) {
|
|
106
107
|
lines.push(`- kubectl context: ${ic.kubectlContext}`);
|
|
108
|
+
}
|
|
107
109
|
if (ic.helmReleases && ic.helmReleases.length > 0) {
|
|
108
110
|
lines.push(`- Active Helm releases: ${ic.helmReleases.slice(0, 5).join(', ')}`);
|
|
109
111
|
}
|
|
110
|
-
if (ic.awsAccount)
|
|
112
|
+
if (ic.awsAccount) {
|
|
111
113
|
lines.push(`- AWS account: ${ic.awsAccount}`);
|
|
112
|
-
|
|
114
|
+
}
|
|
115
|
+
if (ic.awsRegion) {
|
|
113
116
|
lines.push(`- AWS region: ${ic.awsRegion}`);
|
|
114
|
-
|
|
117
|
+
}
|
|
118
|
+
if (ic.gcpProject) {
|
|
115
119
|
lines.push(`- GCP project: ${ic.gcpProject}`);
|
|
120
|
+
}
|
|
116
121
|
parts.push(lines.join('\n'));
|
|
117
122
|
// H3: Inject known resource inventory for better tool call accuracy.
|
|
118
123
|
// Lists exact names for contexts, releases, workspaces, and cloud accounts
|
|
@@ -478,11 +483,13 @@ export function getPrunedHeuristics(mode) {
|
|
|
478
483
|
.filter(line => {
|
|
479
484
|
const l = line.toLowerCase();
|
|
480
485
|
// Remove deploy-specific execution requirements (plan mode cannot apply)
|
|
481
|
-
if (l.includes('in deploy mode:') || l.includes('deploy_preview before'))
|
|
486
|
+
if (l.includes('in deploy mode:') || l.includes('deploy_preview before')) {
|
|
482
487
|
return false;
|
|
488
|
+
}
|
|
483
489
|
// Remove tool selection items for deploy-only tools
|
|
484
|
-
if (l.includes('use drift_detect') || l.includes('use cost_estimate'))
|
|
490
|
+
if (l.includes('use drift_detect') || l.includes('use cost_estimate')) {
|
|
485
491
|
return false;
|
|
492
|
+
}
|
|
486
493
|
return true;
|
|
487
494
|
})
|
|
488
495
|
.join('\n');
|
|
@@ -493,8 +500,9 @@ export function getPrunedHeuristics(mode) {
|
|
|
493
500
|
.filter(line => {
|
|
494
501
|
const l = line.toLowerCase();
|
|
495
502
|
// Remove plan-mode-only readonly enforcement lines
|
|
496
|
-
if (l.includes('in plan mode:') || l.includes('never apply, apply'))
|
|
503
|
+
if (l.includes('in plan mode:') || l.includes('never apply, apply')) {
|
|
497
504
|
return false;
|
|
505
|
+
}
|
|
498
506
|
return true;
|
|
499
507
|
})
|
|
500
508
|
.join('\n');
|
|
@@ -666,11 +674,13 @@ export function extractForbiddenRules(nimbusContent) {
|
|
|
666
674
|
}
|
|
667
675
|
if (inForbidden) {
|
|
668
676
|
// Stop at any new ## section
|
|
669
|
-
if (/^##\s/.test(trimmed))
|
|
677
|
+
if (/^##\s/.test(trimmed)) {
|
|
670
678
|
break;
|
|
679
|
+
}
|
|
671
680
|
// Skip blank lines and HTML comments
|
|
672
|
-
if (!trimmed || trimmed.startsWith('<!--'))
|
|
681
|
+
if (!trimmed || trimmed.startsWith('<!--')) {
|
|
673
682
|
continue;
|
|
683
|
+
}
|
|
674
684
|
// Collect bullet items
|
|
675
685
|
if (trimmed.startsWith('-') || trimmed.startsWith('*')) {
|
|
676
686
|
const rule = trimmed.replace(/^[-*]\s*/, '').trim();
|
|
@@ -781,8 +791,9 @@ function buildEnvironmentContext(cwd) {
|
|
|
781
791
|
// Kubernetes context
|
|
782
792
|
try {
|
|
783
793
|
const ctx = execSync('kubectl config current-context', { timeout: 2000, encoding: 'utf-8' }).trim();
|
|
784
|
-
if (ctx)
|
|
794
|
+
if (ctx) {
|
|
785
795
|
parts.push(`- Kubernetes context: ${ctx}`);
|
|
796
|
+
}
|
|
786
797
|
}
|
|
787
798
|
catch { /* ignore */ }
|
|
788
799
|
// Terraform workspace (only if .terraform dir exists)
|
|
@@ -791,8 +802,9 @@ function buildEnvironmentContext(cwd) {
|
|
|
791
802
|
const ws = execSync('terraform workspace show', {
|
|
792
803
|
cwd: effectiveCwd, timeout: 5000, encoding: 'utf-8',
|
|
793
804
|
}).trim();
|
|
794
|
-
if (ws)
|
|
805
|
+
if (ws) {
|
|
795
806
|
parts.push(`- Terraform workspace: ${ws}`);
|
|
807
|
+
}
|
|
796
808
|
}
|
|
797
809
|
catch { /* ignore */ }
|
|
798
810
|
}
|
|
@@ -808,12 +820,14 @@ function buildEnvironmentContext(cwd) {
|
|
|
808
820
|
catch { /* ignore */ }
|
|
809
821
|
try {
|
|
810
822
|
const region = execSync('aws configure get region', { timeout: 2000, encoding: 'utf-8' }).trim();
|
|
811
|
-
if (region)
|
|
823
|
+
if (region) {
|
|
812
824
|
parts.push(`- AWS region: ${region}`);
|
|
825
|
+
}
|
|
813
826
|
}
|
|
814
827
|
catch {
|
|
815
|
-
if (process.env.AWS_DEFAULT_REGION)
|
|
828
|
+
if (process.env.AWS_DEFAULT_REGION) {
|
|
816
829
|
parts.push(`- AWS region: ${process.env.AWS_DEFAULT_REGION}`);
|
|
830
|
+
}
|
|
817
831
|
}
|
|
818
832
|
}
|
|
819
833
|
// GCP project (only if gcloud available)
|
|
@@ -821,8 +835,9 @@ function buildEnvironmentContext(cwd) {
|
|
|
821
835
|
const proj = execSync('gcloud config get-value project 2>/dev/null', {
|
|
822
836
|
timeout: 3000, encoding: 'utf-8',
|
|
823
837
|
}).trim();
|
|
824
|
-
if (proj && proj !== '(unset)')
|
|
838
|
+
if (proj && proj !== '(unset)') {
|
|
825
839
|
parts.push(`- GCP project: ${proj}`);
|
|
840
|
+
}
|
|
826
841
|
}
|
|
827
842
|
catch { /* ignore */ }
|
|
828
843
|
return parts.join('\n');
|
|
@@ -840,13 +855,15 @@ function buildEnvironmentContext(cwd) {
|
|
|
840
855
|
function buildPrimaryCloudSection() {
|
|
841
856
|
try {
|
|
842
857
|
const configPath = path.join(homedir(), '.nimbus', 'config.json');
|
|
843
|
-
if (!fs.existsSync(configPath))
|
|
858
|
+
if (!fs.existsSync(configPath)) {
|
|
844
859
|
return null;
|
|
860
|
+
}
|
|
845
861
|
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
846
862
|
const config = JSON.parse(raw);
|
|
847
863
|
const clouds = config.primaryClouds;
|
|
848
|
-
if (!Array.isArray(clouds) || clouds.length === 0)
|
|
864
|
+
if (!Array.isArray(clouds) || clouds.length === 0) {
|
|
849
865
|
return null;
|
|
866
|
+
}
|
|
850
867
|
const cloudNames = clouds.map(c => c.toUpperCase()).join(', ');
|
|
851
868
|
return [
|
|
852
869
|
'# Primary Cloud Providers',
|
package/dist/src/app.js
CHANGED
|
@@ -41,7 +41,7 @@ export async function initApp() {
|
|
|
41
41
|
'',
|
|
42
42
|
'\x1b[2mRun `nimbus doctor` for detailed diagnosis.\x1b[0m',
|
|
43
43
|
];
|
|
44
|
-
process.stderr.write(lines.join('\n')
|
|
44
|
+
process.stderr.write(`${lines.join('\n')}\n`);
|
|
45
45
|
process.exit(1);
|
|
46
46
|
}
|
|
47
47
|
startupWarnings = issues.warnings;
|
|
@@ -13,8 +13,9 @@ const SERVICE = 'nimbus-ai';
|
|
|
13
13
|
/** Lazy-loaded keytar module. null = checked and unavailable. */
|
|
14
14
|
let keytarModule = undefined; // undefined = not yet checked
|
|
15
15
|
async function loadKeytar() {
|
|
16
|
-
if (keytarModule !== undefined)
|
|
16
|
+
if (keytarModule !== undefined) {
|
|
17
17
|
return keytarModule;
|
|
18
|
+
}
|
|
18
19
|
try {
|
|
19
20
|
// Dynamic import — keytar is an optional peer dependency
|
|
20
21
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
@@ -38,8 +39,9 @@ export async function isKeychainAvailable() {
|
|
|
38
39
|
*/
|
|
39
40
|
export async function keychainGet(account) {
|
|
40
41
|
const kt = await loadKeytar();
|
|
41
|
-
if (!kt)
|
|
42
|
+
if (!kt) {
|
|
42
43
|
return null;
|
|
44
|
+
}
|
|
43
45
|
try {
|
|
44
46
|
return await kt.getPassword(SERVICE, account);
|
|
45
47
|
}
|
|
@@ -53,8 +55,9 @@ export async function keychainGet(account) {
|
|
|
53
55
|
*/
|
|
54
56
|
export async function keychainSet(account, secret) {
|
|
55
57
|
const kt = await loadKeytar();
|
|
56
|
-
if (!kt)
|
|
58
|
+
if (!kt) {
|
|
57
59
|
return;
|
|
60
|
+
}
|
|
58
61
|
try {
|
|
59
62
|
await kt.setPassword(SERVICE, account, secret);
|
|
60
63
|
}
|
|
@@ -68,8 +71,9 @@ export async function keychainSet(account, secret) {
|
|
|
68
71
|
*/
|
|
69
72
|
export async function keychainDelete(account) {
|
|
70
73
|
const kt = await loadKeytar();
|
|
71
|
-
if (!kt)
|
|
74
|
+
if (!kt) {
|
|
72
75
|
return;
|
|
76
|
+
}
|
|
73
77
|
try {
|
|
74
78
|
await kt.deletePassword(SERVICE, account);
|
|
75
79
|
}
|