@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.
Files changed (469) hide show
  1. package/bin/nimbus +26 -10
  2. package/bin/nimbus.cmd +41 -0
  3. package/bin/nimbus.mjs +70 -0
  4. package/completions/nimbus.bash +38 -0
  5. package/completions/nimbus.fish +48 -0
  6. package/completions/nimbus.zsh +81 -0
  7. package/dist/src/agent/compaction-agent.js +215 -0
  8. package/dist/src/agent/context-manager.js +385 -0
  9. package/dist/src/agent/context.js +322 -0
  10. package/dist/src/agent/deploy-preview.js +395 -0
  11. package/dist/src/agent/expand-files.js +95 -0
  12. package/dist/src/agent/index.js +18 -0
  13. package/dist/src/agent/loop.js +1535 -0
  14. package/dist/src/agent/modes.js +347 -0
  15. package/dist/src/agent/permissions.js +396 -0
  16. package/dist/src/agent/subagents/base.js +67 -0
  17. package/dist/src/agent/subagents/cost.js +45 -0
  18. package/dist/src/agent/subagents/explore.js +36 -0
  19. package/dist/src/agent/subagents/general.js +41 -0
  20. package/dist/src/agent/subagents/index.js +88 -0
  21. package/dist/src/agent/subagents/infra.js +52 -0
  22. package/dist/src/agent/subagents/security.js +60 -0
  23. package/dist/src/agent/system-prompt.js +860 -0
  24. package/dist/src/app.js +152 -0
  25. package/dist/src/audit/activity-log.js +209 -0
  26. package/dist/src/audit/compliance-checker.js +419 -0
  27. package/dist/src/audit/cost-tracker.js +231 -0
  28. package/dist/src/audit/index.js +10 -0
  29. package/dist/src/audit/security-scanner.js +490 -0
  30. package/dist/src/auth/guard.js +64 -0
  31. package/dist/src/auth/index.js +19 -0
  32. package/dist/src/auth/keychain.js +79 -0
  33. package/dist/src/auth/oauth.js +389 -0
  34. package/dist/src/auth/providers.js +415 -0
  35. package/dist/src/auth/sso.js +87 -0
  36. package/dist/src/auth/store.js +424 -0
  37. package/dist/src/auth/types.js +5 -0
  38. package/dist/src/cli/index.js +8 -0
  39. package/dist/src/cli/init.js +1048 -0
  40. package/dist/src/cli/openapi-spec.js +346 -0
  41. package/dist/src/cli/run.js +505 -0
  42. package/dist/src/cli/serve-auth.js +56 -0
  43. package/dist/src/cli/serve.js +432 -0
  44. package/dist/src/cli/web.js +50 -0
  45. package/dist/src/cli.js +1574 -0
  46. package/dist/src/clients/core-engine-client.js +156 -0
  47. package/dist/src/clients/enterprise-client.js +246 -0
  48. package/dist/src/clients/generator-client.js +219 -0
  49. package/dist/src/clients/git-client.js +367 -0
  50. package/dist/src/clients/github-client.js +229 -0
  51. package/dist/src/clients/helm-client.js +299 -0
  52. package/dist/src/clients/index.js +18 -0
  53. package/dist/src/clients/k8s-client.js +270 -0
  54. package/dist/src/clients/llm-client.js +119 -0
  55. package/dist/src/clients/rest-client.js +104 -0
  56. package/dist/src/clients/service-discovery.js +35 -0
  57. package/dist/src/clients/terraform-client.js +302 -0
  58. package/dist/src/clients/tools-client.js +1227 -0
  59. package/dist/src/clients/ws-client.js +93 -0
  60. package/dist/src/commands/alias.js +91 -0
  61. package/dist/src/commands/analyze/index.js +313 -0
  62. package/dist/src/commands/apply/helm.js +375 -0
  63. package/dist/src/commands/apply/index.js +176 -0
  64. package/dist/src/commands/apply/k8s.js +350 -0
  65. package/dist/src/commands/apply/terraform.js +465 -0
  66. package/dist/src/commands/ask.js +137 -0
  67. package/dist/src/commands/audit/index.js +322 -0
  68. package/dist/src/commands/auth-cloud.js +345 -0
  69. package/dist/src/commands/auth-list.js +112 -0
  70. package/dist/src/commands/auth-profile.js +104 -0
  71. package/dist/src/commands/auth-refresh.js +161 -0
  72. package/dist/src/commands/auth-status.js +122 -0
  73. package/dist/src/commands/aws/ec2.js +402 -0
  74. package/dist/src/commands/aws/iam.js +304 -0
  75. package/dist/src/commands/aws/index.js +108 -0
  76. package/dist/src/commands/aws/lambda.js +317 -0
  77. package/dist/src/commands/aws/rds.js +345 -0
  78. package/dist/src/commands/aws/s3.js +346 -0
  79. package/dist/src/commands/aws/vpc.js +302 -0
  80. package/dist/src/commands/aws-discover.js +413 -0
  81. package/dist/src/commands/aws-terraform.js +618 -0
  82. package/dist/src/commands/azure/aks.js +305 -0
  83. package/dist/src/commands/azure/functions.js +200 -0
  84. package/dist/src/commands/azure/index.js +93 -0
  85. package/dist/src/commands/azure/storage.js +378 -0
  86. package/dist/src/commands/azure/vm.js +291 -0
  87. package/dist/src/commands/billing/index.js +224 -0
  88. package/dist/src/commands/chat.js +259 -0
  89. package/dist/src/commands/completions.js +255 -0
  90. package/dist/src/commands/config.js +291 -0
  91. package/dist/src/commands/cost/cloud-cost-estimator.js +211 -0
  92. package/dist/src/commands/cost/estimator.js +73 -0
  93. package/dist/src/commands/cost/index.js +625 -0
  94. package/dist/src/commands/cost/parsers/terraform.js +234 -0
  95. package/dist/src/commands/cost/parsers/types.js +4 -0
  96. package/dist/src/commands/cost/pricing/aws.js +501 -0
  97. package/dist/src/commands/cost/pricing/azure.js +462 -0
  98. package/dist/src/commands/cost/pricing/gcp.js +359 -0
  99. package/dist/src/commands/cost/pricing/index.js +24 -0
  100. package/dist/src/commands/demo.js +196 -0
  101. package/dist/src/commands/deploy.js +215 -0
  102. package/dist/src/commands/doctor.js +1291 -0
  103. package/dist/src/commands/drift/index.js +674 -0
  104. package/dist/src/commands/explain.js +235 -0
  105. package/dist/src/commands/export.js +120 -0
  106. package/dist/src/commands/feedback.js +319 -0
  107. package/dist/src/commands/fix.js +263 -0
  108. package/dist/src/commands/fs/index.js +338 -0
  109. package/dist/src/commands/gcp/compute.js +266 -0
  110. package/dist/src/commands/gcp/functions.js +221 -0
  111. package/dist/src/commands/gcp/gke.js +357 -0
  112. package/dist/src/commands/gcp/iam.js +295 -0
  113. package/dist/src/commands/gcp/index.js +105 -0
  114. package/dist/src/commands/gcp/storage.js +232 -0
  115. package/dist/src/commands/generate-helm.js +1026 -0
  116. package/dist/src/commands/generate-k8s.js +1263 -0
  117. package/dist/src/commands/generate-terraform.js +1058 -0
  118. package/dist/src/commands/gh/index.js +663 -0
  119. package/dist/src/commands/git/index.js +1208 -0
  120. package/dist/src/commands/helm/index.js +985 -0
  121. package/dist/src/commands/help.js +639 -0
  122. package/dist/src/commands/history.js +120 -0
  123. package/dist/src/commands/import.js +782 -0
  124. package/dist/src/commands/incident.js +144 -0
  125. package/dist/src/commands/index.js +109 -0
  126. package/dist/src/commands/init.js +955 -0
  127. package/dist/src/commands/k8s/index.js +979 -0
  128. package/dist/src/commands/login.js +588 -0
  129. package/dist/src/commands/logout.js +61 -0
  130. package/dist/src/commands/logs.js +160 -0
  131. package/dist/src/commands/onboarding.js +382 -0
  132. package/dist/src/commands/pipeline.js +153 -0
  133. package/dist/src/commands/plan/display.js +216 -0
  134. package/dist/src/commands/plan/index.js +525 -0
  135. package/dist/src/commands/plugin.js +325 -0
  136. package/dist/src/commands/preview.js +356 -0
  137. package/dist/src/commands/profile.js +297 -0
  138. package/dist/src/commands/questionnaire.js +1021 -0
  139. package/dist/src/commands/resume.js +35 -0
  140. package/dist/src/commands/rollback.js +259 -0
  141. package/dist/src/commands/rollout.js +74 -0
  142. package/dist/src/commands/runbook.js +307 -0
  143. package/dist/src/commands/schedule.js +202 -0
  144. package/dist/src/commands/status.js +213 -0
  145. package/dist/src/commands/team/index.js +309 -0
  146. package/dist/src/commands/team-context.js +200 -0
  147. package/dist/src/commands/template.js +204 -0
  148. package/dist/src/commands/tf/index.js +989 -0
  149. package/dist/src/commands/upgrade.js +515 -0
  150. package/dist/src/commands/usage/index.js +118 -0
  151. package/dist/src/commands/version.js +145 -0
  152. package/dist/src/commands/watch.js +127 -0
  153. package/dist/src/compat/index.js +2 -0
  154. package/dist/src/compat/runtime.js +10 -0
  155. package/dist/src/compat/sqlite.js +144 -0
  156. package/dist/src/config/index.js +6 -0
  157. package/dist/src/config/manager.js +469 -0
  158. package/dist/src/config/mode-store.js +57 -0
  159. package/dist/src/config/profiles.js +66 -0
  160. package/dist/src/config/safety-policy.js +251 -0
  161. package/dist/src/config/schema.js +107 -0
  162. package/dist/src/config/types.js +311 -0
  163. package/dist/src/config/workspace-state.js +38 -0
  164. package/dist/src/context/context-db.js +138 -0
  165. package/dist/src/demo/index.js +295 -0
  166. package/dist/src/demo/scenarios/full-journey.js +226 -0
  167. package/dist/src/demo/scenarios/getting-started.js +124 -0
  168. package/dist/src/demo/scenarios/helm-release.js +334 -0
  169. package/dist/src/demo/scenarios/k8s-deployment.js +190 -0
  170. package/dist/src/demo/scenarios/terraform-vpc.js +167 -0
  171. package/dist/src/demo/types.js +6 -0
  172. package/dist/src/engine/cost-estimator.js +334 -0
  173. package/dist/src/engine/diagram-generator.js +192 -0
  174. package/dist/src/engine/drift-detector.js +688 -0
  175. package/dist/src/engine/executor.js +832 -0
  176. package/dist/src/engine/index.js +39 -0
  177. package/dist/src/engine/orchestrator.js +436 -0
  178. package/dist/src/engine/planner.js +616 -0
  179. package/dist/src/engine/safety.js +609 -0
  180. package/dist/src/engine/verifier.js +664 -0
  181. package/dist/src/enterprise/audit.js +241 -0
  182. package/dist/src/enterprise/auth.js +189 -0
  183. package/dist/src/enterprise/billing.js +512 -0
  184. package/dist/src/enterprise/index.js +16 -0
  185. package/dist/src/enterprise/teams.js +315 -0
  186. package/dist/src/generator/best-practices.js +1375 -0
  187. package/dist/src/generator/helm.js +495 -0
  188. package/dist/src/generator/index.js +11 -0
  189. package/dist/src/generator/intent-parser.js +420 -0
  190. package/dist/src/generator/kubernetes.js +773 -0
  191. package/dist/src/generator/terraform.js +1472 -0
  192. package/dist/src/history/index.js +6 -0
  193. package/dist/src/history/manager.js +199 -0
  194. package/dist/src/history/types.js +6 -0
  195. package/dist/src/hooks/config.js +318 -0
  196. package/dist/src/hooks/engine.js +317 -0
  197. package/dist/src/hooks/index.js +2 -0
  198. package/dist/src/llm/auth-bridge.js +157 -0
  199. package/dist/src/llm/circuit-breaker.js +116 -0
  200. package/dist/src/llm/config-loader.js +172 -0
  201. package/dist/src/llm/cost-calculator.js +137 -0
  202. package/dist/src/llm/index.js +7 -0
  203. package/dist/src/llm/model-aliases.js +99 -0
  204. package/dist/src/llm/provider-registry.js +57 -0
  205. package/dist/src/llm/providers/anthropic.js +430 -0
  206. package/dist/src/llm/providers/bedrock.js +409 -0
  207. package/dist/src/llm/providers/google.js +344 -0
  208. package/dist/src/llm/providers/ollama.js +661 -0
  209. package/dist/src/llm/providers/openai-compatible.js +289 -0
  210. package/dist/src/llm/providers/openai.js +284 -0
  211. package/dist/src/llm/providers/openrouter.js +293 -0
  212. package/dist/src/llm/router.js +844 -0
  213. package/dist/src/llm/types.js +69 -0
  214. package/dist/src/lsp/client.js +239 -0
  215. package/dist/src/lsp/languages.js +95 -0
  216. package/dist/src/lsp/manager.js +243 -0
  217. package/dist/src/mcp/client.js +289 -0
  218. package/dist/src/mcp/index.js +5 -0
  219. package/dist/src/mcp/manager.js +113 -0
  220. package/dist/src/nimbus.js +212 -0
  221. package/dist/src/plugins/index.js +13 -0
  222. package/dist/src/plugins/loader.js +280 -0
  223. package/dist/src/plugins/manager.js +282 -0
  224. package/dist/src/plugins/types.js +23 -0
  225. package/dist/src/scanners/cicd-scanner.js +230 -0
  226. package/dist/src/scanners/cloud-scanner.js +415 -0
  227. package/dist/src/scanners/framework-scanner.js +430 -0
  228. package/dist/src/scanners/iac-scanner.js +350 -0
  229. package/dist/src/scanners/index.js +454 -0
  230. package/dist/src/scanners/language-scanner.js +258 -0
  231. package/dist/src/scanners/package-manager-scanner.js +252 -0
  232. package/dist/src/scanners/types.js +6 -0
  233. package/dist/src/sessions/manager.js +395 -0
  234. package/dist/src/sessions/types.js +4 -0
  235. package/dist/src/sharing/sync.js +238 -0
  236. package/dist/src/sharing/viewer.js +131 -0
  237. package/dist/src/snapshots/index.js +1 -0
  238. package/dist/src/snapshots/manager.js +432 -0
  239. package/dist/src/state/artifacts.js +94 -0
  240. package/dist/src/state/audit.js +73 -0
  241. package/dist/src/state/billing.js +126 -0
  242. package/dist/src/state/checkpoints.js +81 -0
  243. package/dist/src/state/config.js +58 -0
  244. package/dist/src/state/conversations.js +7 -0
  245. package/dist/src/state/credentials.js +96 -0
  246. package/dist/src/state/db.js +53 -0
  247. package/dist/src/state/index.js +23 -0
  248. package/dist/src/state/messages.js +76 -0
  249. package/dist/src/state/projects.js +92 -0
  250. package/dist/src/state/schema.js +233 -0
  251. package/dist/src/state/sessions.js +79 -0
  252. package/dist/src/state/teams.js +131 -0
  253. package/dist/src/telemetry.js +91 -0
  254. package/dist/src/tools/aws-ops.js +747 -0
  255. package/dist/src/tools/azure-ops.js +491 -0
  256. package/dist/src/tools/file-ops.js +451 -0
  257. package/dist/src/tools/gcp-ops.js +559 -0
  258. package/dist/src/tools/git-ops.js +557 -0
  259. package/dist/src/tools/github-ops.js +460 -0
  260. package/dist/src/tools/helm-ops.js +634 -0
  261. package/dist/src/tools/index.js +16 -0
  262. package/dist/src/tools/k8s-ops.js +579 -0
  263. package/dist/src/tools/schemas/converter.js +129 -0
  264. package/dist/src/tools/schemas/devops.js +3319 -0
  265. package/dist/src/tools/schemas/index.js +19 -0
  266. package/dist/src/tools/schemas/standard.js +966 -0
  267. package/dist/src/tools/schemas/types.js +409 -0
  268. package/dist/src/tools/spawn-exec.js +109 -0
  269. package/dist/src/tools/terraform-ops.js +627 -0
  270. package/dist/src/types/config.js +1 -0
  271. package/dist/src/types/drift.js +4 -0
  272. package/dist/src/types/enterprise.js +5 -0
  273. package/dist/src/types/index.js +14 -0
  274. package/dist/src/types/plan.js +1 -0
  275. package/dist/src/types/request.js +1 -0
  276. package/dist/src/types/response.js +1 -0
  277. package/dist/src/types/service.js +1 -0
  278. package/dist/src/ui/App.js +1672 -0
  279. package/dist/src/ui/DeployPreview.js +60 -0
  280. package/dist/src/ui/FileDiffModal.js +108 -0
  281. package/dist/src/ui/Header.js +46 -0
  282. package/dist/src/ui/HelpModal.js +9 -0
  283. package/dist/src/ui/InputBox.js +408 -0
  284. package/dist/src/ui/MessageList.js +795 -0
  285. package/dist/src/ui/PermissionPrompt.js +72 -0
  286. package/dist/src/ui/StatusBar.js +109 -0
  287. package/dist/src/ui/TerminalPane.js +31 -0
  288. package/dist/src/ui/ToolCallDisplay.js +303 -0
  289. package/dist/src/ui/TreePane.js +83 -0
  290. package/dist/src/ui/chat-ui.js +721 -0
  291. package/dist/src/ui/index.js +11 -0
  292. package/dist/src/ui/ink/index.js +1325 -0
  293. package/dist/src/ui/streaming.js +137 -0
  294. package/dist/src/ui/theme.js +78 -0
  295. package/dist/src/ui/types.js +7 -0
  296. package/dist/src/utils/analytics.js +61 -0
  297. package/dist/src/utils/cost-warning.js +25 -0
  298. package/dist/src/utils/env.js +42 -0
  299. package/dist/src/utils/errors.js +54 -0
  300. package/dist/src/utils/event-bus.js +22 -0
  301. package/dist/src/utils/index.js +16 -0
  302. package/dist/src/utils/logger.js +150 -0
  303. package/dist/src/utils/rate-limiter.js +90 -0
  304. package/dist/src/utils/service-auth.js +36 -0
  305. package/dist/src/utils/validation.js +39 -0
  306. package/dist/src/version.js +3 -0
  307. package/dist/src/watcher/index.js +192 -0
  308. package/dist/src/wizard/approval.js +275 -0
  309. package/dist/src/wizard/index.js +13 -0
  310. package/dist/src/wizard/prompts.js +273 -0
  311. package/dist/src/wizard/types.js +4 -0
  312. package/dist/src/wizard/ui.js +453 -0
  313. package/dist/src/wizard/wizard.js +227 -0
  314. package/package.json +31 -23
  315. package/src/__tests__/alias.test.ts +133 -0
  316. package/src/__tests__/app.test.ts +1 -1
  317. package/src/__tests__/audit.test.ts +1 -1
  318. package/src/__tests__/circuit-breaker.test.ts +1 -1
  319. package/src/__tests__/cli-run.test.ts +237 -1
  320. package/src/__tests__/compat-sqlite.test.ts +68 -0
  321. package/src/__tests__/context-manager.test.ts +131 -1
  322. package/src/__tests__/context.test.ts +1 -1
  323. package/src/__tests__/devops-terminal-gaps.test.ts +718 -0
  324. package/src/__tests__/doctor.test.ts +48 -0
  325. package/src/__tests__/enterprise.test.ts +1 -1
  326. package/src/__tests__/export.test.ts +236 -0
  327. package/src/__tests__/gap-11-18-20.test.ts +958 -0
  328. package/src/__tests__/generator.test.ts +1 -1
  329. package/src/__tests__/helm-streaming.test.ts +127 -0
  330. package/src/__tests__/hooks.test.ts +1 -1
  331. package/src/__tests__/incident.test.ts +179 -0
  332. package/src/__tests__/init.test.ts +55 -4
  333. package/src/__tests__/intent-parser.test.ts +1 -1
  334. package/src/__tests__/llm-router.test.ts +1 -1
  335. package/src/__tests__/logs.test.ts +107 -0
  336. package/src/__tests__/loop-errors.test.ts +244 -0
  337. package/src/__tests__/lsp.test.ts +1 -1
  338. package/src/__tests__/modes.test.ts +1 -1
  339. package/src/__tests__/perf-optimizations.test.ts +847 -0
  340. package/src/__tests__/permissions.test.ts +1 -1
  341. package/src/__tests__/pipeline.test.ts +50 -0
  342. package/src/__tests__/polish-phase3.test.ts +340 -0
  343. package/src/__tests__/profile.test.ts +237 -0
  344. package/src/__tests__/rollback.test.ts +83 -0
  345. package/src/__tests__/runbook.test.ts +219 -0
  346. package/src/__tests__/schedule.test.ts +206 -0
  347. package/src/__tests__/serve.test.ts +1 -1
  348. package/src/__tests__/sessions.test.ts +96 -1
  349. package/src/__tests__/sharing.test.ts +53 -1
  350. package/src/__tests__/snapshots.test.ts +1 -1
  351. package/src/__tests__/standalone-migration.test.ts +199 -0
  352. package/src/__tests__/state-db.test.ts +1 -1
  353. package/src/__tests__/status.test.ts +158 -0
  354. package/src/__tests__/stream-with-tools.test.ts +71 -25
  355. package/src/__tests__/subagents.test.ts +1 -1
  356. package/src/__tests__/system-prompt.test.ts +82 -3
  357. package/src/__tests__/terminal-gap-v2.test.ts +395 -0
  358. package/src/__tests__/terminal-parity.test.ts +393 -0
  359. package/src/__tests__/tf-apply.test.ts +187 -0
  360. package/src/__tests__/tool-converter.test.ts +1 -1
  361. package/src/__tests__/tool-schemas.test.ts +209 -4
  362. package/src/__tests__/tools.test.ts +4 -3
  363. package/src/__tests__/version-json.test.ts +184 -0
  364. package/src/__tests__/version.test.ts +1 -1
  365. package/src/__tests__/watch.test.ts +129 -0
  366. package/src/agent/compaction-agent.ts +40 -1
  367. package/src/agent/context-manager.ts +67 -3
  368. package/src/agent/deploy-preview.ts +62 -1
  369. package/src/agent/expand-files.ts +108 -0
  370. package/src/agent/loop.ts +1312 -31
  371. package/src/agent/permissions.ts +51 -4
  372. package/src/agent/system-prompt.ts +573 -19
  373. package/src/app.ts +58 -0
  374. package/src/audit/security-scanner.ts +45 -0
  375. package/src/auth/keychain.ts +82 -0
  376. package/src/auth/oauth.ts +15 -5
  377. package/src/cli/init.ts +378 -5
  378. package/src/cli/run.ts +407 -16
  379. package/src/cli/serve.ts +78 -1
  380. package/src/cli/web.ts +10 -6
  381. package/src/cli.ts +312 -1
  382. package/src/clients/service-discovery.ts +30 -25
  383. package/src/commands/alias.ts +100 -0
  384. package/src/commands/audit/index.ts +121 -2
  385. package/src/commands/auth-cloud.ts +113 -0
  386. package/src/commands/auth-refresh.ts +187 -0
  387. package/src/commands/aws-discover.ts +144 -251
  388. package/src/commands/aws-terraform.ts +68 -118
  389. package/src/commands/chat.ts +9 -3
  390. package/src/commands/completions.ts +268 -0
  391. package/src/commands/config.ts +26 -0
  392. package/src/commands/cost/index.ts +218 -2
  393. package/src/commands/deploy.ts +260 -0
  394. package/src/commands/doctor.ts +744 -152
  395. package/src/commands/drift/index.ts +371 -23
  396. package/src/commands/export.ts +146 -0
  397. package/src/commands/generate-k8s.ts +9 -61
  398. package/src/commands/generate-terraform.ts +191 -449
  399. package/src/commands/help.ts +212 -36
  400. package/src/commands/history.ts +8 -1
  401. package/src/commands/incident.ts +166 -0
  402. package/src/commands/init.ts +5 -0
  403. package/src/commands/login.ts +86 -1
  404. package/src/commands/logs.ts +167 -0
  405. package/src/commands/onboarding.ts +211 -34
  406. package/src/commands/pipeline.ts +186 -0
  407. package/src/commands/plugin.ts +398 -0
  408. package/src/commands/profile.ts +342 -0
  409. package/src/commands/questionnaire.ts +0 -98
  410. package/src/commands/resume.ts +26 -34
  411. package/src/commands/rollback.ts +315 -0
  412. package/src/commands/rollout.ts +88 -0
  413. package/src/commands/runbook.ts +346 -0
  414. package/src/commands/schedule.ts +236 -0
  415. package/src/commands/status.ts +252 -0
  416. package/src/commands/team-context.ts +220 -0
  417. package/src/commands/template.ts +58 -57
  418. package/src/commands/tf/index.ts +70 -11
  419. package/src/commands/upgrade.ts +57 -0
  420. package/src/commands/version.ts +54 -50
  421. package/src/commands/watch.ts +153 -0
  422. package/src/compat/runtime.ts +1 -1
  423. package/src/compat/sqlite.ts +75 -5
  424. package/src/config/mode-store.ts +62 -0
  425. package/src/config/profiles.ts +84 -0
  426. package/src/config/types.ts +83 -1
  427. package/src/config/workspace-state.ts +53 -0
  428. package/src/engine/cost-estimator.ts +52 -10
  429. package/src/engine/executor.ts +33 -2
  430. package/src/engine/planner.ts +68 -1
  431. package/src/generator/terraform.ts +8 -0
  432. package/src/history/manager.ts +2 -74
  433. package/src/hooks/engine.ts +5 -4
  434. package/src/llm/cost-calculator.ts +2 -2
  435. package/src/llm/providers/anthropic.ts +50 -21
  436. package/src/llm/router.ts +76 -7
  437. package/src/lsp/languages.ts +3 -0
  438. package/src/lsp/manager.ts +21 -5
  439. package/src/nimbus.ts +37 -18
  440. package/src/sessions/manager.ts +108 -1
  441. package/src/sharing/sync.ts +4 -0
  442. package/src/sharing/viewer.ts +66 -0
  443. package/src/tools/file-ops.ts +22 -0
  444. package/src/tools/schemas/devops.ts +3007 -117
  445. package/src/tools/schemas/standard.ts +5 -1
  446. package/src/tools/schemas/types.ts +31 -1
  447. package/src/tools/spawn-exec.ts +148 -0
  448. package/src/ui/App.tsx +1183 -66
  449. package/src/ui/DeployPreview.tsx +62 -57
  450. package/src/ui/FileDiffModal.tsx +162 -0
  451. package/src/ui/Header.tsx +87 -24
  452. package/src/ui/HelpModal.tsx +57 -0
  453. package/src/ui/InputBox.tsx +163 -10
  454. package/src/ui/MessageList.tsx +487 -40
  455. package/src/ui/PermissionPrompt.tsx +17 -5
  456. package/src/ui/StatusBar.tsx +122 -3
  457. package/src/ui/TerminalPane.tsx +84 -0
  458. package/src/ui/ToolCallDisplay.tsx +252 -18
  459. package/src/ui/TreePane.tsx +132 -0
  460. package/src/ui/chat-ui.ts +41 -44
  461. package/src/ui/ink/index.ts +771 -38
  462. package/src/ui/streaming.ts +1 -1
  463. package/src/ui/theme.ts +104 -0
  464. package/src/ui/types.ts +18 -0
  465. package/src/version.ts +1 -1
  466. package/src/watcher/index.ts +66 -15
  467. package/src/wizard/types.ts +1 -0
  468. package/src/wizard/ui.ts +1 -1
  469. package/tsconfig.json +2 -2
@@ -0,0 +1,618 @@
1
+ /**
2
+ * AWS Terraform Command
3
+ *
4
+ * Generate Terraform configurations from AWS infrastructure
5
+ *
6
+ * Usage: nimbus aws terraform [options]
7
+ */
8
+ import { logger } from '../utils';
9
+ import { createWizard, ui, select, confirm, pathInput, } from '../wizard';
10
+ import { awsDiscoverCommand } from './aws-discover';
11
+ import { generateTerraformProject } from '../generator/terraform';
12
+ import { readFile, writeFile } from 'node:fs/promises';
13
+ import * as path from 'path';
14
+ import * as fs from 'fs';
15
+ /**
16
+ * Run the AWS terraform command
17
+ */
18
+ export async function awsTerraformCommand(options = {}) {
19
+ logger.info('Starting AWS Terraform generation');
20
+ // Non-interactive mode
21
+ if (options.nonInteractive) {
22
+ await runNonInteractive(options);
23
+ return;
24
+ }
25
+ // Check if we have resources to generate from
26
+ let resources;
27
+ let discoverySessionId;
28
+ // Option 1: Use existing discovery session
29
+ if (options.sessionId) {
30
+ discoverySessionId = options.sessionId;
31
+ ui.info(`Using existing discovery session: ${options.sessionId}`);
32
+ }
33
+ // Option 2: Load resources from file
34
+ else if (options.resourcesFile) {
35
+ ui.startSpinner({ message: 'Loading resources from file...' });
36
+ try {
37
+ const fileContent = await readFile(options.resourcesFile, 'utf-8');
38
+ const data = JSON.parse(fileContent);
39
+ resources = data.resources || data;
40
+ ui.stopSpinnerSuccess(`Loaded ${resources.length} resources from file`);
41
+ }
42
+ catch (error) {
43
+ ui.stopSpinnerFail(`Failed to load resources: ${error.message}`);
44
+ return;
45
+ }
46
+ }
47
+ // Option 3: Run discovery first
48
+ else if (!options.skipDiscovery) {
49
+ const discoveryOptions = {
50
+ profile: options.profile,
51
+ regions: options.regions,
52
+ services: options.services,
53
+ nonInteractive: false,
54
+ };
55
+ ui.header('nimbus aws terraform', 'Step 1: Infrastructure Discovery');
56
+ ui.newLine();
57
+ const inventory = await awsDiscoverCommand(discoveryOptions);
58
+ if (!inventory) {
59
+ ui.error('Discovery failed, cannot generate Terraform');
60
+ return;
61
+ }
62
+ resources = inventory.resources;
63
+ ui.newLine();
64
+ ui.header('nimbus aws terraform', 'Step 2: Terraform Generation');
65
+ ui.newLine();
66
+ }
67
+ // Interactive wizard for generation options
68
+ const wizard = createWizard({
69
+ title: 'Terraform Generation',
70
+ description: 'Configure Terraform generation options',
71
+ initialContext: {
72
+ discoverySessionId,
73
+ resources,
74
+ outputPath: options.output,
75
+ organizeByService: options.organizeByService ?? true,
76
+ generateImportBlocks: options.importBlocks ?? true,
77
+ generateImportScript: options.importScript ?? true,
78
+ terraformVersion: options.terraformVersion,
79
+ awsProviderVersion: options.awsProviderVersion,
80
+ includeReadme: options.includeReadme ?? options.includeStarterKit,
81
+ includeGitignore: options.includeGitignore ?? options.includeStarterKit,
82
+ includeMakefile: options.includeMakefile ?? options.includeStarterKit,
83
+ },
84
+ steps: createWizardSteps(!!discoverySessionId || !!resources),
85
+ onEvent: event => {
86
+ logger.debug('Wizard event', { type: event.type });
87
+ },
88
+ });
89
+ const result = await wizard.run();
90
+ if (result.success) {
91
+ displayCompletionMessage(result.context);
92
+ }
93
+ else {
94
+ ui.error(`Generation failed: ${result.error?.message || 'Unknown error'}`);
95
+ process.exit(1);
96
+ }
97
+ }
98
+ /**
99
+ * Create wizard steps
100
+ */
101
+ function createWizardSteps(_hasResources) {
102
+ const steps = [];
103
+ // Step 1: Generation Options
104
+ steps.push({
105
+ id: 'generation-options',
106
+ title: 'Generation Options',
107
+ description: 'Configure how Terraform files should be generated',
108
+ execute: generationOptionsStep,
109
+ });
110
+ // Step 2: Output Location
111
+ steps.push({
112
+ id: 'output-location',
113
+ title: 'Output Location',
114
+ description: 'Where should the Terraform files be saved?',
115
+ execute: outputLocationStep,
116
+ });
117
+ // Step 3: Generate
118
+ steps.push({
119
+ id: 'generate',
120
+ title: 'Generate Terraform',
121
+ description: 'Generating Terraform configurations...',
122
+ execute: generateStep,
123
+ });
124
+ // Step 4: Write Files
125
+ steps.push({
126
+ id: 'write-files',
127
+ title: 'Write Files',
128
+ description: 'Writing files to disk...',
129
+ execute: writeFilesStep,
130
+ });
131
+ return steps;
132
+ }
133
+ /**
134
+ * Step 1: Generation Options
135
+ */
136
+ async function generationOptionsStep(ctx) {
137
+ // Organization style
138
+ const organizeChoice = await select({
139
+ message: 'How should Terraform files be organized?',
140
+ options: [
141
+ {
142
+ value: 'service',
143
+ label: 'By service (Recommended)',
144
+ description: 'Separate files for each AWS service (ec2.tf, s3.tf, etc.)',
145
+ },
146
+ {
147
+ value: 'single',
148
+ label: 'Single file',
149
+ description: 'All resources in main.tf',
150
+ },
151
+ ],
152
+ defaultValue: ctx.organizeByService !== false ? 'service' : 'single',
153
+ });
154
+ // Import method
155
+ ui.newLine();
156
+ const importMethod = await select({
157
+ message: 'How should imports be generated?',
158
+ options: [
159
+ {
160
+ value: 'both',
161
+ label: 'Both import blocks and shell script (Recommended)',
162
+ description: 'Maximum compatibility with all Terraform versions',
163
+ },
164
+ {
165
+ value: 'blocks',
166
+ label: 'Import blocks only (Terraform 1.5+)',
167
+ description: 'Modern declarative imports in .tf files',
168
+ },
169
+ {
170
+ value: 'script',
171
+ label: 'Shell script only',
172
+ description: 'Traditional terraform import commands',
173
+ },
174
+ {
175
+ value: 'none',
176
+ label: 'No imports',
177
+ description: 'Generate resource definitions only',
178
+ },
179
+ ],
180
+ defaultValue: 'both',
181
+ });
182
+ // Terraform version
183
+ ui.newLine();
184
+ const terraformVersion = await select({
185
+ message: 'Target Terraform version:',
186
+ options: [
187
+ { value: '1.5.0', label: '1.5.0+', description: 'Supports import blocks' },
188
+ { value: '1.4.0', label: '1.4.0', description: 'Latest stable without import blocks' },
189
+ { value: '1.3.0', label: '1.3.0', description: 'Older version' },
190
+ ],
191
+ defaultValue: ctx.terraformVersion || '1.5.0',
192
+ });
193
+ // Starter kit
194
+ ui.newLine();
195
+ const includeStarterKit = await confirm({
196
+ message: 'Include starter kit (README, .gitignore, Makefile)?',
197
+ defaultValue: true,
198
+ });
199
+ return {
200
+ success: true,
201
+ data: {
202
+ organizeByService: organizeChoice === 'service',
203
+ generateImportBlocks: importMethod === 'both' || importMethod === 'blocks',
204
+ generateImportScript: importMethod === 'both' || importMethod === 'script',
205
+ terraformVersion,
206
+ includeReadme: includeStarterKit,
207
+ includeGitignore: includeStarterKit,
208
+ includeMakefile: includeStarterKit,
209
+ },
210
+ };
211
+ }
212
+ /**
213
+ * Step 2: Output Location
214
+ */
215
+ async function outputLocationStep(ctx) {
216
+ const outputPath = await pathInput('Where should the Terraform files be saved?', ctx.outputPath || './terraform-aws');
217
+ if (!outputPath) {
218
+ return { success: false, error: 'Output path is required' };
219
+ }
220
+ // Check if directory exists
221
+ const exists = fs.existsSync(outputPath);
222
+ if (exists) {
223
+ const files = fs.readdirSync(outputPath);
224
+ if (files.length > 0) {
225
+ ui.newLine();
226
+ ui.warning(`Directory ${outputPath} is not empty (${files.length} files)`);
227
+ const overwrite = await confirm({
228
+ message: 'Overwrite existing files?',
229
+ defaultValue: false,
230
+ });
231
+ if (!overwrite) {
232
+ return { success: false, error: 'User cancelled - directory not empty' };
233
+ }
234
+ }
235
+ }
236
+ return {
237
+ success: true,
238
+ data: { outputPath },
239
+ };
240
+ }
241
+ /**
242
+ * Step 3: Generate Terraform using local generator
243
+ */
244
+ async function generateStep(ctx) {
245
+ ui.startSpinner({ message: 'Generating Terraform configurations...' });
246
+ try {
247
+ // Derive components from discovered resources
248
+ const resourceTypes = (ctx.resources ?? []).map(r => r.type);
249
+ const components = [];
250
+ if (resourceTypes.some(t => t.includes('VPC') || t.includes('Subnet')))
251
+ components.push('vpc');
252
+ if (resourceTypes.some(t => t.includes('EC2') || t.includes('Instance')))
253
+ components.push('ec2');
254
+ if (resourceTypes.some(t => t.includes('S3')))
255
+ components.push('s3');
256
+ if (resourceTypes.some(t => t.includes('RDS')))
257
+ components.push('rds');
258
+ if (resourceTypes.some(t => t.includes('EKS')))
259
+ components.push('eks');
260
+ if (components.length === 0)
261
+ components.push('vpc', 's3');
262
+ const generatedProject = await generateTerraformProject({
263
+ projectName: 'infrastructure',
264
+ provider: 'aws',
265
+ region: ctx.resources?.[0]?.region || 'us-east-1',
266
+ components,
267
+ });
268
+ const fileMap = {};
269
+ for (const file of generatedProject.files) {
270
+ fileMap[file.path] = file.content;
271
+ }
272
+ const summary = {
273
+ totalResources: ctx.resources?.length ?? 0,
274
+ mappedResources: ctx.resources?.length ?? 0,
275
+ unmappedResources: 0,
276
+ filesGenerated: generatedProject.files.length,
277
+ servicesIncluded: components,
278
+ regionsIncluded: [...new Set((ctx.resources ?? []).map(r => r.region).filter(Boolean))],
279
+ };
280
+ ui.stopSpinnerSuccess(`Generated ${Object.keys(fileMap).length} file(s)`);
281
+ // Add starter kit files if requested
282
+ if (ctx.includeReadme)
283
+ fileMap['README.md'] = generateReadme(summary);
284
+ if (ctx.includeGitignore)
285
+ fileMap['.gitignore'] = generateGitignore();
286
+ if (ctx.includeMakefile)
287
+ fileMap['Makefile'] = generateMakefile();
288
+ return {
289
+ success: true,
290
+ data: {
291
+ generatedFiles: fileMap,
292
+ summary,
293
+ },
294
+ };
295
+ }
296
+ catch (error) {
297
+ ui.stopSpinnerFail(`Generation failed: ${error.message}`);
298
+ return { success: false, error: error.message };
299
+ }
300
+ }
301
+ /**
302
+ * Step 4: Write Files
303
+ */
304
+ async function writeFilesStep(ctx) {
305
+ if (!ctx.generatedFiles || !ctx.outputPath) {
306
+ return { success: false, error: 'No files to write' };
307
+ }
308
+ ui.startSpinner({ message: 'Writing files to disk...' });
309
+ try {
310
+ // Create output directory
311
+ if (!fs.existsSync(ctx.outputPath)) {
312
+ fs.mkdirSync(ctx.outputPath, { recursive: true });
313
+ }
314
+ // Write each file
315
+ const fileNames = Object.keys(ctx.generatedFiles);
316
+ for (const fileName of fileNames) {
317
+ const filePath = path.join(ctx.outputPath, fileName);
318
+ const content = ctx.generatedFiles[fileName];
319
+ // Create subdirectories if needed
320
+ const dir = path.dirname(filePath);
321
+ if (!fs.existsSync(dir)) {
322
+ fs.mkdirSync(dir, { recursive: true });
323
+ }
324
+ await writeFile(filePath, content, 'utf-8');
325
+ }
326
+ // Make import script executable
327
+ if (ctx.generatedFiles['import.sh']) {
328
+ const scriptPath = path.join(ctx.outputPath, 'import.sh');
329
+ fs.chmodSync(scriptPath, '755');
330
+ }
331
+ ui.stopSpinnerSuccess(`Wrote ${fileNames.length} files to ${ctx.outputPath}`);
332
+ return {
333
+ success: true,
334
+ data: { filesWritten: fileNames.length },
335
+ };
336
+ }
337
+ catch (error) {
338
+ ui.stopSpinnerFail(`Failed to write files: ${error.message}`);
339
+ return { success: false, error: error.message };
340
+ }
341
+ }
342
+ /**
343
+ * Generate README.md content
344
+ */
345
+ function generateReadme(summary) {
346
+ return `# Terraform AWS Infrastructure
347
+
348
+ Generated by Nimbus CLI
349
+
350
+ ## Summary
351
+
352
+ - **Total Resources**: ${summary.totalResources}
353
+ - **Mapped Resources**: ${summary.mappedResources}
354
+ - **Unmapped Resources**: ${summary.unmappedResources}
355
+ - **Files Generated**: ${summary.filesGenerated}
356
+
357
+ ### Services
358
+
359
+ ${summary.servicesIncluded.map(s => `- ${s}`).join('\n')}
360
+
361
+ ### Regions
362
+
363
+ ${summary.regionsIncluded.map(r => `- ${r}`).join('\n')}
364
+
365
+ ## Getting Started
366
+
367
+ 1. **Initialize Terraform**:
368
+ \`\`\`bash
369
+ terraform init
370
+ \`\`\`
371
+
372
+ 2. **Import existing resources** (choose one):
373
+
374
+ Using import blocks (Terraform 1.5+):
375
+ \`\`\`bash
376
+ terraform plan -generate-config-out=generated.tf
377
+ \`\`\`
378
+
379
+ Using import script:
380
+ \`\`\`bash
381
+ ./import.sh
382
+ \`\`\`
383
+
384
+ 3. **Review the plan**:
385
+ \`\`\`bash
386
+ terraform plan
387
+ \`\`\`
388
+
389
+ 4. **Apply changes** (should show no changes if imports were successful):
390
+ \`\`\`bash
391
+ terraform apply
392
+ \`\`\`
393
+
394
+ ## File Structure
395
+
396
+ - \`providers.tf\` - AWS provider configuration
397
+ - \`variables.tf\` - Input variables
398
+ - \`outputs.tf\` - Output values
399
+ - \`*.tf\` - Resource definitions by service
400
+ - \`import.sh\` - Import script for existing resources
401
+
402
+ ## Notes
403
+
404
+ - Review all generated configurations before applying
405
+ - Some sensitive values may need to be filled in manually
406
+ - Consider using Terraform workspaces for different environments
407
+ `;
408
+ }
409
+ /**
410
+ * Generate .gitignore content
411
+ */
412
+ function generateGitignore() {
413
+ return `# Terraform
414
+ *.tfstate
415
+ *.tfstate.*
416
+ .terraform/
417
+ .terraform.lock.hcl
418
+ crash.log
419
+ crash.*.log
420
+ *.tfvars
421
+ *.tfvars.json
422
+ override.tf
423
+ override.tf.json
424
+ *_override.tf
425
+ *_override.tf.json
426
+
427
+ # Sensitive files
428
+ *.pem
429
+ *.key
430
+ .env
431
+ .env.*
432
+
433
+ # IDE
434
+ .idea/
435
+ .vscode/
436
+ *.swp
437
+ *.swo
438
+
439
+ # OS
440
+ .DS_Store
441
+ Thumbs.db
442
+ `;
443
+ }
444
+ /**
445
+ * Generate Makefile content
446
+ */
447
+ function generateMakefile() {
448
+ return `# Terraform Makefile
449
+
450
+ .PHONY: init plan apply destroy fmt validate import clean
451
+
452
+ # Initialize Terraform
453
+ init:
454
+ terraform init
455
+
456
+ # Plan changes
457
+ plan:
458
+ terraform plan
459
+
460
+ # Apply changes
461
+ apply:
462
+ terraform apply
463
+
464
+ # Destroy infrastructure
465
+ destroy:
466
+ terraform destroy
467
+
468
+ # Format code
469
+ fmt:
470
+ terraform fmt -recursive
471
+
472
+ # Validate configuration
473
+ validate:
474
+ terraform validate
475
+
476
+ # Import existing resources
477
+ import:
478
+ ./import.sh
479
+
480
+ # Clean up
481
+ clean:
482
+ rm -rf .terraform
483
+ rm -f .terraform.lock.hcl
484
+
485
+ # Full workflow
486
+ all: init fmt validate plan
487
+ `;
488
+ }
489
+ /**
490
+ * Display completion message
491
+ */
492
+ function displayCompletionMessage(ctx) {
493
+ ui.newLine();
494
+ ui.box({
495
+ title: 'Terraform Generation Complete!',
496
+ content: [
497
+ `Output: ${ctx.outputPath}`,
498
+ `Files: ${Object.keys(ctx.generatedFiles || {}).length}`,
499
+ '',
500
+ 'Summary:',
501
+ ` Resources: ${ctx.summary?.mappedResources || 0} mapped, ${ctx.summary?.unmappedResources || 0} unmapped`,
502
+ ` Services: ${ctx.summary?.servicesIncluded?.join(', ') || 'N/A'}`,
503
+ '',
504
+ 'Next steps:',
505
+ ` 1. cd ${ctx.outputPath}`,
506
+ ' 2. terraform init',
507
+ ' 3. ./import.sh # Import existing resources',
508
+ ' 4. terraform plan',
509
+ ],
510
+ style: 'rounded',
511
+ borderColor: 'green',
512
+ padding: 1,
513
+ });
514
+ }
515
+ /**
516
+ * Run in non-interactive mode
517
+ */
518
+ async function runNonInteractive(options) {
519
+ ui.header('nimbus aws terraform', 'Non-interactive mode');
520
+ // Must have either session ID, resources file, or profile for discovery
521
+ if (!options.sessionId && !options.resourcesFile && !options.profile) {
522
+ ui.error('One of --session-id, --resources-file, or --profile is required');
523
+ process.exit(1);
524
+ }
525
+ let resources;
526
+ // Load from file if specified
527
+ if (options.resourcesFile) {
528
+ ui.startSpinner({ message: 'Loading resources from file...' });
529
+ try {
530
+ const fileContent = await readFile(options.resourcesFile, 'utf-8');
531
+ const data = JSON.parse(fileContent);
532
+ resources = data.resources || data;
533
+ ui.stopSpinnerSuccess(`Loaded ${resources.length} resources`);
534
+ }
535
+ catch (error) {
536
+ ui.stopSpinnerFail(`Failed to load resources: ${error.message}`);
537
+ process.exit(1);
538
+ }
539
+ }
540
+ // Run discovery if profile specified
541
+ else if (options.profile && !options.sessionId) {
542
+ const discoveryOptions = {
543
+ profile: options.profile,
544
+ regions: options.regions,
545
+ services: options.services,
546
+ nonInteractive: true,
547
+ };
548
+ const inventory = await awsDiscoverCommand(discoveryOptions);
549
+ if (!inventory) {
550
+ ui.error('Discovery failed');
551
+ process.exit(1);
552
+ }
553
+ resources = inventory.resources;
554
+ }
555
+ // Generate Terraform using local generator
556
+ ui.startSpinner({ message: 'Generating Terraform configurations...' });
557
+ try {
558
+ const resourceTypes = (resources ?? []).map(r => r.type);
559
+ const components = [];
560
+ if (resourceTypes.some(t => t.includes('VPC') || t.includes('Subnet')))
561
+ components.push('vpc');
562
+ if (resourceTypes.some(t => t.includes('EC2') || t.includes('Instance')))
563
+ components.push('ec2');
564
+ if (resourceTypes.some(t => t.includes('S3')))
565
+ components.push('s3');
566
+ if (resourceTypes.some(t => t.includes('RDS')))
567
+ components.push('rds');
568
+ if (resourceTypes.some(t => t.includes('EKS')))
569
+ components.push('eks');
570
+ if (components.length === 0)
571
+ components.push('vpc', 's3');
572
+ const generatedProject = await generateTerraformProject({
573
+ projectName: 'infrastructure',
574
+ provider: 'aws',
575
+ region: resources?.[0]?.region || 'us-east-1',
576
+ components,
577
+ });
578
+ const files = {};
579
+ for (const file of generatedProject.files) {
580
+ files[file.path] = file.content;
581
+ }
582
+ const summary = {
583
+ totalResources: resources?.length ?? 0,
584
+ mappedResources: resources?.length ?? 0,
585
+ unmappedResources: 0,
586
+ filesGenerated: generatedProject.files.length,
587
+ servicesIncluded: components,
588
+ regionsIncluded: [...new Set((resources ?? []).map(r => r.region).filter(Boolean))],
589
+ };
590
+ ui.stopSpinnerSuccess(`Generated ${Object.keys(files).length} file(s)`);
591
+ // Write files
592
+ const outputPath = options.output || './terraform-aws';
593
+ ui.startSpinner({ message: 'Writing files...' });
594
+ if (!fs.existsSync(outputPath)) {
595
+ fs.mkdirSync(outputPath, { recursive: true });
596
+ }
597
+ if (options.includeStarterKit || options.includeReadme)
598
+ files['README.md'] = generateReadme(summary);
599
+ if (options.includeStarterKit || options.includeGitignore)
600
+ files['.gitignore'] = generateGitignore();
601
+ if (options.includeStarterKit || options.includeMakefile)
602
+ files['Makefile'] = generateMakefile();
603
+ for (const [fileName, content] of Object.entries(files)) {
604
+ const filePath = path.join(outputPath, fileName);
605
+ await writeFile(filePath, content, 'utf-8');
606
+ }
607
+ ui.stopSpinnerSuccess(`Wrote ${Object.keys(files).length} files to ${outputPath}`);
608
+ ui.newLine();
609
+ ui.success('Generation complete!');
610
+ ui.print(` Output: ${outputPath}`);
611
+ ui.print(` Resources: ${summary.mappedResources} mapped`);
612
+ }
613
+ catch (error) {
614
+ ui.stopSpinnerFail(`Generation failed: ${error.message}`);
615
+ process.exit(1);
616
+ }
617
+ }
618
+ export default awsTerraformCommand;