@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,345 @@
1
+ /**
2
+ * AWS RDS Commands
3
+ *
4
+ * RDS database operations with cost warnings before billable actions
5
+ *
6
+ * Usage:
7
+ * nimbus aws rds list
8
+ * nimbus aws rds describe <db-identifier>
9
+ * nimbus aws rds start <db-identifier>
10
+ * nimbus aws rds stop <db-identifier>
11
+ */
12
+ import { logger } from '../../utils';
13
+ import { ui } from '../../wizard/ui';
14
+ import { confirm } from '../../wizard/prompts';
15
+ import { loadSafetyPolicy, evaluateSafety, } from '../../config/safety-policy';
16
+ import { promptForApproval } from '../../wizard/approval';
17
+ import { estimateCloudCost, formatCostWarning } from '../cost/cloud-cost-estimator';
18
+ /**
19
+ * RDS command router
20
+ */
21
+ export async function rdsCommand(action, args, options) {
22
+ logger.info('Running RDS command', { action, args, options });
23
+ switch (action) {
24
+ case 'list':
25
+ case 'ls':
26
+ await listInstances(options);
27
+ break;
28
+ case 'describe':
29
+ if (!args[0]) {
30
+ ui.error('DB instance identifier is required');
31
+ ui.print('Usage: nimbus aws rds describe <db-identifier>');
32
+ return;
33
+ }
34
+ await describeInstance(args[0], options);
35
+ break;
36
+ case 'start':
37
+ if (!args[0]) {
38
+ ui.error('DB instance identifier is required');
39
+ ui.print('Usage: nimbus aws rds start <db-identifier>');
40
+ return;
41
+ }
42
+ await startInstance(args[0], options);
43
+ break;
44
+ case 'stop':
45
+ if (!args[0]) {
46
+ ui.error('DB instance identifier is required');
47
+ ui.print('Usage: nimbus aws rds stop <db-identifier>');
48
+ return;
49
+ }
50
+ await stopInstance(args[0], options);
51
+ break;
52
+ default:
53
+ showRdsHelp();
54
+ break;
55
+ }
56
+ }
57
+ /**
58
+ * Display a cost warning for an RDS instance class using the cloud cost estimator.
59
+ */
60
+ function displayRdsCostWarning(instanceClass, multiAz) {
61
+ const estimate = estimateCloudCost('rds:StartDBInstance', {
62
+ instanceClass,
63
+ multiAz,
64
+ });
65
+ if (estimate) {
66
+ const color = estimate.monthly > 200 ? 'red' : estimate.monthly > 50 ? 'yellow' : 'green';
67
+ ui.newLine();
68
+ ui.print(ui.bold(' Estimated Cost:'));
69
+ ui.print(` Hourly: ${ui.color(`$${estimate.hourly.toFixed(4)}/hr`, color)}`);
70
+ ui.print(` Monthly: ${ui.color(`$${estimate.monthly.toFixed(2)}/mo`, color)} (on-demand${multiAz ? ', Multi-AZ' : ''}, approximate)`);
71
+ ui.newLine();
72
+ }
73
+ }
74
+ /**
75
+ * List all RDS instances
76
+ */
77
+ async function listInstances(options) {
78
+ ui.header('RDS Instances');
79
+ ui.startSpinner({ message: 'Fetching RDS instances...' });
80
+ try {
81
+ const result = await runAwsCommand('rds describe-db-instances', options);
82
+ const instances = result.DBInstances || [];
83
+ ui.stopSpinnerSuccess(`Found ${instances.length} instance(s)`);
84
+ ui.newLine();
85
+ if (instances.length === 0) {
86
+ ui.info('No RDS instances found');
87
+ return;
88
+ }
89
+ // Display table
90
+ displayInstanceTable(instances);
91
+ }
92
+ catch (error) {
93
+ ui.stopSpinnerFail('Failed to list instances');
94
+ ui.error(error.message);
95
+ }
96
+ }
97
+ /**
98
+ * Describe a specific RDS instance
99
+ */
100
+ async function describeInstance(identifier, options) {
101
+ ui.header(`RDS Instance: ${identifier}`);
102
+ ui.startSpinner({ message: 'Fetching instance details...' });
103
+ try {
104
+ const result = await runAwsCommand(`rds describe-db-instances --db-instance-identifier ${identifier}`, options);
105
+ const instances = result.DBInstances || [];
106
+ ui.stopSpinnerSuccess('Instance details retrieved');
107
+ ui.newLine();
108
+ if (instances.length === 0) {
109
+ ui.error(`Instance ${identifier} not found`);
110
+ return;
111
+ }
112
+ const instance = instances[0];
113
+ // Display instance details
114
+ ui.print(ui.bold('Instance Details:'));
115
+ ui.newLine();
116
+ ui.print(` Identifier: ${instance.DBInstanceIdentifier}`);
117
+ ui.print(` Class: ${instance.DBInstanceClass}`);
118
+ ui.print(` Engine: ${instance.Engine} ${instance.EngineVersion}`);
119
+ ui.print(` Status: ${formatStatus(instance.DBInstanceStatus)}`);
120
+ ui.print(` Storage: ${instance.AllocatedStorage} GB`);
121
+ ui.print(` AZ: ${instance.AvailabilityZone}`);
122
+ ui.print(` Multi-AZ: ${instance.MultiAZ ? 'Yes' : 'No'}`);
123
+ if (instance.Endpoint) {
124
+ ui.newLine();
125
+ ui.print(ui.bold('Endpoint:'));
126
+ ui.print(` Address: ${instance.Endpoint.Address}`);
127
+ ui.print(` Port: ${instance.Endpoint.Port}`);
128
+ }
129
+ // Show cost estimate
130
+ displayRdsCostWarning(instance.DBInstanceClass, instance.MultiAZ);
131
+ }
132
+ catch (error) {
133
+ ui.stopSpinnerFail('Failed to describe instance');
134
+ ui.error(error.message);
135
+ }
136
+ }
137
+ /**
138
+ * Start an RDS instance
139
+ */
140
+ async function startInstance(identifier, options) {
141
+ ui.header(`Start RDS Instance: ${identifier}`);
142
+ // Try to get instance class for cost estimate
143
+ try {
144
+ const result = await runAwsCommand(`rds describe-db-instances --db-instance-identifier ${identifier}`, options);
145
+ const instances = result.DBInstances || [];
146
+ if (instances.length > 0) {
147
+ const instance = instances[0];
148
+ const estimate = estimateCloudCost('rds:StartDBInstance', {
149
+ instanceClass: instance.DBInstanceClass,
150
+ multiAz: instance.MultiAZ,
151
+ });
152
+ if (estimate) {
153
+ ui.newLine();
154
+ ui.warning(formatCostWarning(estimate));
155
+ ui.newLine();
156
+ }
157
+ }
158
+ }
159
+ catch {
160
+ // Non-critical, continue without cost estimate
161
+ }
162
+ const proceed = await confirm({
163
+ message: `Start instance ${identifier}?`,
164
+ defaultValue: true,
165
+ });
166
+ if (!proceed) {
167
+ ui.info('Operation cancelled');
168
+ return;
169
+ }
170
+ ui.startSpinner({ message: 'Starting instance...' });
171
+ try {
172
+ await runAwsCommand(`rds start-db-instance --db-instance-identifier ${identifier}`, options);
173
+ ui.stopSpinnerSuccess('Instance starting');
174
+ ui.info(`Instance ${identifier} is now starting`);
175
+ }
176
+ catch (error) {
177
+ ui.stopSpinnerFail('Failed to start instance');
178
+ ui.error(error.message);
179
+ }
180
+ }
181
+ /**
182
+ * Stop an RDS instance
183
+ */
184
+ async function stopInstance(identifier, options) {
185
+ ui.header(`Stop RDS Instance: ${identifier}`);
186
+ // Show cost estimate for the instance being stopped
187
+ try {
188
+ const result = await runAwsCommand(`rds describe-db-instances --db-instance-identifier ${identifier}`, options);
189
+ const instances = result.DBInstances || [];
190
+ if (instances.length > 0) {
191
+ const instance = instances[0];
192
+ displayRdsCostWarning(instance.DBInstanceClass, instance.MultiAZ);
193
+ ui.info('Stopping this instance will stop incurring compute charges.');
194
+ ui.newLine();
195
+ }
196
+ }
197
+ catch {
198
+ // Non-critical, continue without cost estimate
199
+ }
200
+ // Run safety checks
201
+ const safetyResult = await runSafetyCheck('stop', identifier, options);
202
+ if (safetyResult.requiresApproval) {
203
+ const approval = await promptForApproval({
204
+ title: 'Stop RDS Instance',
205
+ operation: `rds stop ${identifier}`,
206
+ risks: safetyResult.risks,
207
+ });
208
+ if (!approval.approved) {
209
+ ui.info('Operation cancelled');
210
+ return;
211
+ }
212
+ }
213
+ else {
214
+ const proceed = await confirm({
215
+ message: `Stop instance ${identifier}?`,
216
+ defaultValue: false,
217
+ });
218
+ if (!proceed) {
219
+ ui.info('Operation cancelled');
220
+ return;
221
+ }
222
+ }
223
+ ui.startSpinner({ message: 'Stopping instance...' });
224
+ try {
225
+ await runAwsCommand(`rds stop-db-instance --db-instance-identifier ${identifier}`, options);
226
+ ui.stopSpinnerSuccess('Instance stopping');
227
+ ui.info(`Instance ${identifier} is now stopping`);
228
+ }
229
+ catch (error) {
230
+ ui.stopSpinnerFail('Failed to stop instance');
231
+ ui.error(error.message);
232
+ }
233
+ }
234
+ /**
235
+ * Run safety check for RDS operation
236
+ */
237
+ async function runSafetyCheck(operation, identifier, options) {
238
+ const policy = loadSafetyPolicy();
239
+ const context = {
240
+ operation,
241
+ type: 'aws',
242
+ resources: [identifier],
243
+ metadata: {
244
+ service: 'rds',
245
+ region: options.region,
246
+ },
247
+ };
248
+ return evaluateSafety(context, policy);
249
+ }
250
+ /**
251
+ * Run AWS CLI command and parse JSON output
252
+ */
253
+ async function runAwsCommand(command, options) {
254
+ const { execFile } = await import('child_process');
255
+ const { promisify } = await import('util');
256
+ const execFileAsync = promisify(execFile);
257
+ const args = command.split(' ');
258
+ const baseCommand = args[0];
259
+ const commandArgs = args.slice(1);
260
+ // Add common options
261
+ if (options.profile) {
262
+ commandArgs.push('--profile', options.profile);
263
+ }
264
+ if (options.region) {
265
+ commandArgs.push('--region', options.region);
266
+ }
267
+ commandArgs.push('--output', 'json');
268
+ const { stdout } = await execFileAsync('aws', [baseCommand, ...commandArgs]);
269
+ return JSON.parse(stdout);
270
+ }
271
+ /**
272
+ * Display instances in a table format
273
+ */
274
+ function displayInstanceTable(instances) {
275
+ const headers = ['Identifier', 'Engine', 'Class', 'Status', 'Storage', 'Multi-AZ'];
276
+ const rows = instances.map(inst => [
277
+ inst.DBInstanceIdentifier,
278
+ `${inst.Engine} ${inst.EngineVersion}`,
279
+ inst.DBInstanceClass,
280
+ inst.DBInstanceStatus,
281
+ `${inst.AllocatedStorage} GB`,
282
+ inst.MultiAZ ? 'Yes' : 'No',
283
+ ]);
284
+ // Print header
285
+ const headerRow = headers
286
+ .map((h, i) => {
287
+ const maxWidth = Math.max(h.length, ...rows.map(r => r[i].length));
288
+ return h.padEnd(maxWidth);
289
+ })
290
+ .join(' ');
291
+ ui.print(ui.bold(headerRow));
292
+ ui.print('-'.repeat(headerRow.length));
293
+ // Print rows
294
+ for (const row of rows) {
295
+ const formattedRow = row
296
+ .map((cell, i) => {
297
+ const maxWidth = Math.max(headers[i].length, ...rows.map(r => r[i].length));
298
+ if (i === 3) {
299
+ // Status column - colorize
300
+ return formatStatus(cell).padEnd(maxWidth + 10);
301
+ }
302
+ return cell.padEnd(maxWidth);
303
+ })
304
+ .join(' ');
305
+ ui.print(formattedRow);
306
+ }
307
+ }
308
+ /**
309
+ * Format instance status with color
310
+ */
311
+ function formatStatus(status) {
312
+ switch (status) {
313
+ case 'available':
314
+ return ui.color(status, 'green');
315
+ case 'stopped':
316
+ return ui.color(status, 'red');
317
+ case 'starting':
318
+ case 'stopping':
319
+ case 'creating':
320
+ case 'modifying':
321
+ return ui.color(status, 'yellow');
322
+ case 'deleting':
323
+ return ui.color(status, 'gray');
324
+ default:
325
+ return status;
326
+ }
327
+ }
328
+ /**
329
+ * Show RDS command help
330
+ */
331
+ function showRdsHelp() {
332
+ ui.print('Usage: nimbus aws rds <action> [args]');
333
+ ui.newLine();
334
+ ui.print(ui.bold('Actions:'));
335
+ ui.print(' list List all RDS instances');
336
+ ui.print(' describe <id> Describe a specific instance');
337
+ ui.print(' start <id> Start an instance');
338
+ ui.print(' stop <id> Stop an instance');
339
+ ui.newLine();
340
+ ui.print(ui.bold('Examples:'));
341
+ ui.print(' nimbus aws rds list');
342
+ ui.print(' nimbus aws rds describe my-database');
343
+ ui.print(' nimbus aws rds stop my-database');
344
+ }
345
+ export default rdsCommand;
@@ -0,0 +1,346 @@
1
+ /**
2
+ * AWS S3 Commands
3
+ *
4
+ * S3 bucket and object operations
5
+ *
6
+ * Usage:
7
+ * nimbus aws s3 ls
8
+ * nimbus aws s3 ls <bucket>
9
+ * nimbus aws s3 cp <src> <dst>
10
+ * nimbus aws s3 rm <path>
11
+ * nimbus aws s3 mb <bucket>
12
+ */
13
+ import { logger } from '../../utils';
14
+ import { ui } from '../../wizard/ui';
15
+ import { confirm } from '../../wizard/prompts';
16
+ import { loadSafetyPolicy, evaluateSafety, } from '../../config/safety-policy';
17
+ import { promptForApproval } from '../../wizard/approval';
18
+ /**
19
+ * S3 command router
20
+ */
21
+ export async function s3Command(action, args, options) {
22
+ logger.info('Running S3 command', { action, args, options });
23
+ switch (action) {
24
+ case 'ls':
25
+ case 'list':
26
+ if (args[0]) {
27
+ await listObjects(args[0], options);
28
+ }
29
+ else {
30
+ await listBuckets(options);
31
+ }
32
+ break;
33
+ case 'cp':
34
+ case 'copy':
35
+ if (args.length < 2) {
36
+ ui.error('Source and destination are required');
37
+ ui.print('Usage: nimbus aws s3 cp <source> <destination>');
38
+ return;
39
+ }
40
+ await copyObject(args[0], args[1], options);
41
+ break;
42
+ case 'rm':
43
+ case 'remove':
44
+ if (!args[0]) {
45
+ ui.error('S3 path is required');
46
+ ui.print('Usage: nimbus aws s3 rm <s3://bucket/key>');
47
+ return;
48
+ }
49
+ await removeObject(args[0], options);
50
+ break;
51
+ case 'mb':
52
+ if (!args[0]) {
53
+ ui.error('Bucket name is required');
54
+ ui.print('Usage: nimbus aws s3 mb <bucket-name>');
55
+ return;
56
+ }
57
+ await makeBucket(args[0], options);
58
+ break;
59
+ case 'rb':
60
+ if (!args[0]) {
61
+ ui.error('Bucket name is required');
62
+ ui.print('Usage: nimbus aws s3 rb <bucket-name>');
63
+ return;
64
+ }
65
+ await removeBucket(args[0], options);
66
+ break;
67
+ default:
68
+ showS3Help();
69
+ break;
70
+ }
71
+ }
72
+ /**
73
+ * List all S3 buckets
74
+ */
75
+ async function listBuckets(options) {
76
+ ui.header('S3 Buckets');
77
+ ui.startSpinner({ message: 'Fetching S3 buckets...' });
78
+ try {
79
+ const result = await runAwsCommand('s3api list-buckets', options);
80
+ const buckets = result.Buckets || [];
81
+ ui.stopSpinnerSuccess(`Found ${buckets.length} bucket(s)`);
82
+ ui.newLine();
83
+ if (buckets.length === 0) {
84
+ ui.info('No S3 buckets found');
85
+ return;
86
+ }
87
+ // Display table
88
+ ui.print(ui.bold(`${'Name'.padEnd(50)}Created`));
89
+ ui.print('-'.repeat(70));
90
+ for (const bucket of buckets) {
91
+ const date = new Date(bucket.CreationDate).toLocaleDateString();
92
+ ui.print(`${bucket.Name.padEnd(50)}${date}`);
93
+ }
94
+ }
95
+ catch (error) {
96
+ ui.stopSpinnerFail('Failed to list buckets');
97
+ ui.error(error.message);
98
+ }
99
+ }
100
+ /**
101
+ * List objects in a bucket
102
+ */
103
+ async function listObjects(bucket, options) {
104
+ // Remove s3:// prefix if present
105
+ const bucketName = bucket.replace(/^s3:\/\//, '').split('/')[0];
106
+ const prefix = bucket
107
+ .replace(/^s3:\/\//, '')
108
+ .split('/')
109
+ .slice(1)
110
+ .join('/');
111
+ ui.header(`S3 Objects: ${bucketName}`);
112
+ ui.startSpinner({ message: 'Fetching objects...' });
113
+ try {
114
+ let command = `s3api list-objects-v2 --bucket ${bucketName}`;
115
+ if (prefix) {
116
+ command += ` --prefix ${prefix}`;
117
+ }
118
+ const result = await runAwsCommand(command, options);
119
+ const objects = result.Contents || [];
120
+ ui.stopSpinnerSuccess(`Found ${objects.length} object(s)`);
121
+ ui.newLine();
122
+ if (objects.length === 0) {
123
+ ui.info('No objects found');
124
+ return;
125
+ }
126
+ // Display table
127
+ ui.print(ui.bold(`${'Key'.padEnd(50) + 'Size'.padEnd(15)}Modified`));
128
+ ui.print('-'.repeat(80));
129
+ for (const obj of objects) {
130
+ const size = formatBytes(obj.Size);
131
+ const date = new Date(obj.LastModified).toLocaleDateString();
132
+ ui.print(`${obj.Key.padEnd(50)}${size.padEnd(15)}${date}`);
133
+ }
134
+ }
135
+ catch (error) {
136
+ ui.stopSpinnerFail('Failed to list objects');
137
+ ui.error(error.message);
138
+ }
139
+ }
140
+ /**
141
+ * Copy object
142
+ */
143
+ async function copyObject(source, destination, options) {
144
+ ui.header('S3 Copy');
145
+ ui.info(`Source: ${source}`);
146
+ ui.info(`Destination: ${destination}`);
147
+ ui.newLine();
148
+ const proceed = await confirm({
149
+ message: 'Proceed with copy?',
150
+ defaultValue: true,
151
+ });
152
+ if (!proceed) {
153
+ ui.info('Operation cancelled');
154
+ return;
155
+ }
156
+ ui.startSpinner({ message: 'Copying...' });
157
+ try {
158
+ await runAwsS3Command(`cp ${source} ${destination}`, options);
159
+ ui.stopSpinnerSuccess('Copy complete');
160
+ }
161
+ catch (error) {
162
+ ui.stopSpinnerFail('Copy failed');
163
+ ui.error(error.message);
164
+ }
165
+ }
166
+ /**
167
+ * Remove object
168
+ */
169
+ async function removeObject(path, options) {
170
+ ui.header('S3 Remove');
171
+ ui.warning(`This will delete: ${path}`);
172
+ ui.newLine();
173
+ // Run safety checks
174
+ const safetyResult = await runSafetyCheck('delete', path, options);
175
+ if (safetyResult.requiresApproval) {
176
+ const approval = await promptForApproval({
177
+ title: 'Delete S3 Object',
178
+ operation: `s3 rm ${path}`,
179
+ risks: safetyResult.risks,
180
+ });
181
+ if (!approval.approved) {
182
+ ui.info('Operation cancelled');
183
+ return;
184
+ }
185
+ }
186
+ else {
187
+ const proceed = await confirm({
188
+ message: 'Delete this object?',
189
+ defaultValue: false,
190
+ });
191
+ if (!proceed) {
192
+ ui.info('Operation cancelled');
193
+ return;
194
+ }
195
+ }
196
+ ui.startSpinner({ message: 'Deleting...' });
197
+ try {
198
+ await runAwsS3Command(`rm ${path}`, options);
199
+ ui.stopSpinnerSuccess('Object deleted');
200
+ }
201
+ catch (error) {
202
+ ui.stopSpinnerFail('Delete failed');
203
+ ui.error(error.message);
204
+ }
205
+ }
206
+ /**
207
+ * Create a bucket
208
+ */
209
+ async function makeBucket(bucketName, options) {
210
+ ui.header('Create S3 Bucket');
211
+ ui.info(`Bucket: ${bucketName}`);
212
+ ui.newLine();
213
+ const proceed = await confirm({
214
+ message: 'Create this bucket?',
215
+ defaultValue: true,
216
+ });
217
+ if (!proceed) {
218
+ ui.info('Operation cancelled');
219
+ return;
220
+ }
221
+ ui.startSpinner({ message: 'Creating bucket...' });
222
+ try {
223
+ await runAwsS3Command(`mb s3://${bucketName}`, options);
224
+ ui.stopSpinnerSuccess('Bucket created');
225
+ }
226
+ catch (error) {
227
+ ui.stopSpinnerFail('Failed to create bucket');
228
+ ui.error(error.message);
229
+ }
230
+ }
231
+ /**
232
+ * Remove a bucket
233
+ */
234
+ async function removeBucket(bucketName, options) {
235
+ ui.header('Remove S3 Bucket');
236
+ ui.warning(`This will delete bucket: ${bucketName}`);
237
+ ui.newLine();
238
+ // Run safety checks
239
+ const safetyResult = await runSafetyCheck('delete', bucketName, options);
240
+ const approval = await promptForApproval({
241
+ title: 'Delete S3 Bucket',
242
+ operation: `s3 rb ${bucketName}`,
243
+ risks: safetyResult.risks,
244
+ requireConfirmation: true,
245
+ confirmationWord: 'delete',
246
+ });
247
+ if (!approval.approved) {
248
+ ui.info('Operation cancelled');
249
+ return;
250
+ }
251
+ ui.startSpinner({ message: 'Removing bucket...' });
252
+ try {
253
+ await runAwsS3Command(`rb s3://${bucketName} --force`, options);
254
+ ui.stopSpinnerSuccess('Bucket removed');
255
+ }
256
+ catch (error) {
257
+ ui.stopSpinnerFail('Failed to remove bucket');
258
+ ui.error(error.message);
259
+ }
260
+ }
261
+ /**
262
+ * Run safety check for S3 operation
263
+ */
264
+ async function runSafetyCheck(operation, resource, options) {
265
+ const policy = loadSafetyPolicy();
266
+ const context = {
267
+ operation,
268
+ type: 'aws',
269
+ resources: [resource],
270
+ metadata: {
271
+ service: 's3',
272
+ region: options.region,
273
+ },
274
+ };
275
+ return evaluateSafety(context, policy);
276
+ }
277
+ /**
278
+ * Run AWS CLI command and parse JSON output
279
+ */
280
+ async function runAwsCommand(command, options) {
281
+ const { execFile } = await import('child_process');
282
+ const { promisify } = await import('util');
283
+ const execFileAsync = promisify(execFile);
284
+ const args = command.split(' ');
285
+ const baseCommand = args[0];
286
+ const commandArgs = args.slice(1);
287
+ // Add common options
288
+ if (options.profile) {
289
+ commandArgs.push('--profile', options.profile);
290
+ }
291
+ if (options.region) {
292
+ commandArgs.push('--region', options.region);
293
+ }
294
+ commandArgs.push('--output', 'json');
295
+ const { stdout } = await execFileAsync('aws', [baseCommand, ...commandArgs]);
296
+ return JSON.parse(stdout);
297
+ }
298
+ /**
299
+ * Run AWS S3 high-level command
300
+ */
301
+ async function runAwsS3Command(command, options) {
302
+ const { execFile } = await import('child_process');
303
+ const { promisify } = await import('util');
304
+ const execFileAsync = promisify(execFile);
305
+ const args = command.split(' ');
306
+ // Add common options
307
+ if (options.profile) {
308
+ args.push('--profile', options.profile);
309
+ }
310
+ if (options.region) {
311
+ args.push('--region', options.region);
312
+ }
313
+ await execFileAsync('aws', ['s3', ...args]);
314
+ }
315
+ /**
316
+ * Format bytes to human readable
317
+ */
318
+ function formatBytes(bytes) {
319
+ if (bytes === 0) {
320
+ return '0 B';
321
+ }
322
+ const k = 1024;
323
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
324
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
325
+ return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
326
+ }
327
+ /**
328
+ * Show S3 command help
329
+ */
330
+ function showS3Help() {
331
+ ui.print('Usage: nimbus aws s3 <action> [args]');
332
+ ui.newLine();
333
+ ui.print(ui.bold('Actions:'));
334
+ ui.print(' ls [bucket] List buckets or objects');
335
+ ui.print(' cp <src> <dst> Copy files/objects');
336
+ ui.print(' rm <path> Remove an object');
337
+ ui.print(' mb <bucket> Create a bucket');
338
+ ui.print(' rb <bucket> Remove a bucket');
339
+ ui.newLine();
340
+ ui.print(ui.bold('Examples:'));
341
+ ui.print(' nimbus aws s3 ls');
342
+ ui.print(' nimbus aws s3 ls s3://my-bucket/prefix/');
343
+ ui.print(' nimbus aws s3 cp file.txt s3://my-bucket/');
344
+ ui.print(' nimbus aws s3 rm s3://my-bucket/file.txt');
345
+ }
346
+ export default s3Command;