@build-astron-co/nimbus 0.3.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 (441) hide show
  1. package/bin/nimbus.cmd +41 -0
  2. package/bin/nimbus.mjs +70 -0
  3. package/completions/nimbus.bash +38 -0
  4. package/completions/nimbus.fish +48 -0
  5. package/completions/nimbus.zsh +81 -0
  6. package/dist/src/agent/compaction-agent.js +215 -0
  7. package/dist/src/agent/context-manager.js +385 -0
  8. package/dist/src/agent/context.js +322 -0
  9. package/dist/src/agent/deploy-preview.js +395 -0
  10. package/dist/src/agent/expand-files.js +95 -0
  11. package/dist/src/agent/index.js +18 -0
  12. package/dist/src/agent/loop.js +1535 -0
  13. package/dist/src/agent/modes.js +347 -0
  14. package/dist/src/agent/permissions.js +396 -0
  15. package/dist/src/agent/subagents/base.js +67 -0
  16. package/dist/src/agent/subagents/cost.js +45 -0
  17. package/dist/src/agent/subagents/explore.js +36 -0
  18. package/dist/src/agent/subagents/general.js +41 -0
  19. package/dist/src/agent/subagents/index.js +88 -0
  20. package/dist/src/agent/subagents/infra.js +52 -0
  21. package/dist/src/agent/subagents/security.js +60 -0
  22. package/dist/src/agent/system-prompt.js +860 -0
  23. package/dist/src/app.js +152 -0
  24. package/dist/src/audit/activity-log.js +209 -0
  25. package/dist/src/audit/compliance-checker.js +419 -0
  26. package/dist/src/audit/cost-tracker.js +231 -0
  27. package/dist/src/audit/index.js +10 -0
  28. package/dist/src/audit/security-scanner.js +490 -0
  29. package/dist/src/auth/guard.js +64 -0
  30. package/dist/src/auth/index.js +19 -0
  31. package/dist/src/auth/keychain.js +79 -0
  32. package/dist/src/auth/oauth.js +389 -0
  33. package/dist/src/auth/providers.js +415 -0
  34. package/dist/src/auth/sso.js +87 -0
  35. package/dist/src/auth/store.js +424 -0
  36. package/dist/src/auth/types.js +5 -0
  37. package/dist/src/cli/index.js +8 -0
  38. package/dist/src/cli/init.js +1048 -0
  39. package/dist/src/cli/openapi-spec.js +346 -0
  40. package/dist/src/cli/run.js +505 -0
  41. package/dist/src/cli/serve-auth.js +56 -0
  42. package/dist/src/cli/serve.js +432 -0
  43. package/dist/src/cli/web.js +50 -0
  44. package/dist/src/cli.js +1574 -0
  45. package/dist/src/clients/core-engine-client.js +156 -0
  46. package/dist/src/clients/enterprise-client.js +246 -0
  47. package/dist/src/clients/generator-client.js +219 -0
  48. package/dist/src/clients/git-client.js +367 -0
  49. package/dist/src/clients/github-client.js +229 -0
  50. package/dist/src/clients/helm-client.js +299 -0
  51. package/dist/src/clients/index.js +18 -0
  52. package/dist/src/clients/k8s-client.js +270 -0
  53. package/dist/src/clients/llm-client.js +119 -0
  54. package/dist/src/clients/rest-client.js +104 -0
  55. package/dist/src/clients/service-discovery.js +35 -0
  56. package/dist/src/clients/terraform-client.js +302 -0
  57. package/dist/src/clients/tools-client.js +1227 -0
  58. package/dist/src/clients/ws-client.js +93 -0
  59. package/dist/src/commands/alias.js +91 -0
  60. package/dist/src/commands/analyze/index.js +313 -0
  61. package/dist/src/commands/apply/helm.js +375 -0
  62. package/dist/src/commands/apply/index.js +176 -0
  63. package/dist/src/commands/apply/k8s.js +350 -0
  64. package/dist/src/commands/apply/terraform.js +465 -0
  65. package/dist/src/commands/ask.js +137 -0
  66. package/dist/src/commands/audit/index.js +322 -0
  67. package/dist/src/commands/auth-cloud.js +345 -0
  68. package/dist/src/commands/auth-list.js +112 -0
  69. package/dist/src/commands/auth-profile.js +104 -0
  70. package/dist/src/commands/auth-refresh.js +161 -0
  71. package/dist/src/commands/auth-status.js +122 -0
  72. package/dist/src/commands/aws/ec2.js +402 -0
  73. package/dist/src/commands/aws/iam.js +304 -0
  74. package/dist/src/commands/aws/index.js +108 -0
  75. package/dist/src/commands/aws/lambda.js +317 -0
  76. package/dist/src/commands/aws/rds.js +345 -0
  77. package/dist/src/commands/aws/s3.js +346 -0
  78. package/dist/src/commands/aws/vpc.js +302 -0
  79. package/dist/src/commands/aws-discover.js +413 -0
  80. package/dist/src/commands/aws-terraform.js +618 -0
  81. package/dist/src/commands/azure/aks.js +305 -0
  82. package/dist/src/commands/azure/functions.js +200 -0
  83. package/dist/src/commands/azure/index.js +93 -0
  84. package/dist/src/commands/azure/storage.js +378 -0
  85. package/dist/src/commands/azure/vm.js +291 -0
  86. package/dist/src/commands/billing/index.js +224 -0
  87. package/dist/src/commands/chat.js +259 -0
  88. package/dist/src/commands/completions.js +255 -0
  89. package/dist/src/commands/config.js +291 -0
  90. package/dist/src/commands/cost/cloud-cost-estimator.js +211 -0
  91. package/dist/src/commands/cost/estimator.js +73 -0
  92. package/dist/src/commands/cost/index.js +625 -0
  93. package/dist/src/commands/cost/parsers/terraform.js +234 -0
  94. package/dist/src/commands/cost/parsers/types.js +4 -0
  95. package/dist/src/commands/cost/pricing/aws.js +501 -0
  96. package/dist/src/commands/cost/pricing/azure.js +462 -0
  97. package/dist/src/commands/cost/pricing/gcp.js +359 -0
  98. package/dist/src/commands/cost/pricing/index.js +24 -0
  99. package/dist/src/commands/demo.js +196 -0
  100. package/dist/src/commands/deploy.js +215 -0
  101. package/dist/src/commands/doctor.js +1291 -0
  102. package/dist/src/commands/drift/index.js +674 -0
  103. package/dist/src/commands/explain.js +235 -0
  104. package/dist/src/commands/export.js +120 -0
  105. package/dist/src/commands/feedback.js +319 -0
  106. package/dist/src/commands/fix.js +263 -0
  107. package/dist/src/commands/fs/index.js +338 -0
  108. package/dist/src/commands/gcp/compute.js +266 -0
  109. package/dist/src/commands/gcp/functions.js +221 -0
  110. package/dist/src/commands/gcp/gke.js +357 -0
  111. package/dist/src/commands/gcp/iam.js +295 -0
  112. package/dist/src/commands/gcp/index.js +105 -0
  113. package/dist/src/commands/gcp/storage.js +232 -0
  114. package/dist/src/commands/generate-helm.js +1026 -0
  115. package/dist/src/commands/generate-k8s.js +1263 -0
  116. package/dist/src/commands/generate-terraform.js +1058 -0
  117. package/dist/src/commands/gh/index.js +663 -0
  118. package/dist/src/commands/git/index.js +1208 -0
  119. package/dist/src/commands/helm/index.js +985 -0
  120. package/dist/src/commands/help.js +639 -0
  121. package/dist/src/commands/history.js +120 -0
  122. package/dist/src/commands/import.js +782 -0
  123. package/dist/src/commands/incident.js +144 -0
  124. package/dist/src/commands/index.js +109 -0
  125. package/dist/src/commands/init.js +955 -0
  126. package/dist/src/commands/k8s/index.js +979 -0
  127. package/dist/src/commands/login.js +588 -0
  128. package/dist/src/commands/logout.js +61 -0
  129. package/dist/src/commands/logs.js +160 -0
  130. package/dist/src/commands/onboarding.js +382 -0
  131. package/dist/src/commands/pipeline.js +153 -0
  132. package/dist/src/commands/plan/display.js +216 -0
  133. package/dist/src/commands/plan/index.js +525 -0
  134. package/dist/src/commands/plugin.js +325 -0
  135. package/dist/src/commands/preview.js +356 -0
  136. package/dist/src/commands/profile.js +297 -0
  137. package/dist/src/commands/questionnaire.js +1021 -0
  138. package/dist/src/commands/resume.js +35 -0
  139. package/dist/src/commands/rollback.js +259 -0
  140. package/dist/src/commands/rollout.js +74 -0
  141. package/dist/src/commands/runbook.js +307 -0
  142. package/dist/src/commands/schedule.js +202 -0
  143. package/dist/src/commands/status.js +213 -0
  144. package/dist/src/commands/team/index.js +309 -0
  145. package/dist/src/commands/team-context.js +200 -0
  146. package/dist/src/commands/template.js +204 -0
  147. package/dist/src/commands/tf/index.js +989 -0
  148. package/dist/src/commands/upgrade.js +515 -0
  149. package/dist/src/commands/usage/index.js +118 -0
  150. package/dist/src/commands/version.js +145 -0
  151. package/dist/src/commands/watch.js +127 -0
  152. package/dist/src/compat/index.js +2 -0
  153. package/dist/src/compat/runtime.js +10 -0
  154. package/dist/src/compat/sqlite.js +144 -0
  155. package/dist/src/config/index.js +6 -0
  156. package/dist/src/config/manager.js +469 -0
  157. package/dist/src/config/mode-store.js +57 -0
  158. package/dist/src/config/profiles.js +66 -0
  159. package/dist/src/config/safety-policy.js +251 -0
  160. package/dist/src/config/schema.js +107 -0
  161. package/dist/src/config/types.js +311 -0
  162. package/dist/src/config/workspace-state.js +38 -0
  163. package/dist/src/context/context-db.js +138 -0
  164. package/dist/src/demo/index.js +295 -0
  165. package/dist/src/demo/scenarios/full-journey.js +226 -0
  166. package/dist/src/demo/scenarios/getting-started.js +124 -0
  167. package/dist/src/demo/scenarios/helm-release.js +334 -0
  168. package/dist/src/demo/scenarios/k8s-deployment.js +190 -0
  169. package/dist/src/demo/scenarios/terraform-vpc.js +167 -0
  170. package/dist/src/demo/types.js +6 -0
  171. package/dist/src/engine/cost-estimator.js +334 -0
  172. package/dist/src/engine/diagram-generator.js +192 -0
  173. package/dist/src/engine/drift-detector.js +688 -0
  174. package/dist/src/engine/executor.js +832 -0
  175. package/dist/src/engine/index.js +39 -0
  176. package/dist/src/engine/orchestrator.js +436 -0
  177. package/dist/src/engine/planner.js +616 -0
  178. package/dist/src/engine/safety.js +609 -0
  179. package/dist/src/engine/verifier.js +664 -0
  180. package/dist/src/enterprise/audit.js +241 -0
  181. package/dist/src/enterprise/auth.js +189 -0
  182. package/dist/src/enterprise/billing.js +512 -0
  183. package/dist/src/enterprise/index.js +16 -0
  184. package/dist/src/enterprise/teams.js +315 -0
  185. package/dist/src/generator/best-practices.js +1375 -0
  186. package/dist/src/generator/helm.js +495 -0
  187. package/dist/src/generator/index.js +11 -0
  188. package/dist/src/generator/intent-parser.js +420 -0
  189. package/dist/src/generator/kubernetes.js +773 -0
  190. package/dist/src/generator/terraform.js +1472 -0
  191. package/dist/src/history/index.js +6 -0
  192. package/dist/src/history/manager.js +199 -0
  193. package/dist/src/history/types.js +6 -0
  194. package/dist/src/hooks/config.js +318 -0
  195. package/dist/src/hooks/engine.js +317 -0
  196. package/dist/src/hooks/index.js +2 -0
  197. package/dist/src/llm/auth-bridge.js +157 -0
  198. package/dist/src/llm/circuit-breaker.js +116 -0
  199. package/dist/src/llm/config-loader.js +172 -0
  200. package/dist/src/llm/cost-calculator.js +137 -0
  201. package/dist/src/llm/index.js +7 -0
  202. package/dist/src/llm/model-aliases.js +99 -0
  203. package/dist/src/llm/provider-registry.js +57 -0
  204. package/dist/src/llm/providers/anthropic.js +430 -0
  205. package/dist/src/llm/providers/bedrock.js +409 -0
  206. package/dist/src/llm/providers/google.js +344 -0
  207. package/dist/src/llm/providers/ollama.js +661 -0
  208. package/dist/src/llm/providers/openai-compatible.js +289 -0
  209. package/dist/src/llm/providers/openai.js +284 -0
  210. package/dist/src/llm/providers/openrouter.js +293 -0
  211. package/dist/src/llm/router.js +844 -0
  212. package/dist/src/llm/types.js +69 -0
  213. package/dist/src/lsp/client.js +239 -0
  214. package/dist/src/lsp/languages.js +95 -0
  215. package/dist/src/lsp/manager.js +243 -0
  216. package/dist/src/mcp/client.js +289 -0
  217. package/dist/src/mcp/index.js +5 -0
  218. package/dist/src/mcp/manager.js +113 -0
  219. package/dist/src/nimbus.js +212 -0
  220. package/dist/src/plugins/index.js +13 -0
  221. package/dist/src/plugins/loader.js +280 -0
  222. package/dist/src/plugins/manager.js +282 -0
  223. package/dist/src/plugins/types.js +23 -0
  224. package/dist/src/scanners/cicd-scanner.js +230 -0
  225. package/dist/src/scanners/cloud-scanner.js +415 -0
  226. package/dist/src/scanners/framework-scanner.js +430 -0
  227. package/dist/src/scanners/iac-scanner.js +350 -0
  228. package/dist/src/scanners/index.js +454 -0
  229. package/dist/src/scanners/language-scanner.js +258 -0
  230. package/dist/src/scanners/package-manager-scanner.js +252 -0
  231. package/dist/src/scanners/types.js +6 -0
  232. package/dist/src/sessions/manager.js +395 -0
  233. package/dist/src/sessions/types.js +4 -0
  234. package/dist/src/sharing/sync.js +238 -0
  235. package/dist/src/sharing/viewer.js +131 -0
  236. package/dist/src/snapshots/index.js +1 -0
  237. package/dist/src/snapshots/manager.js +432 -0
  238. package/dist/src/state/artifacts.js +94 -0
  239. package/dist/src/state/audit.js +73 -0
  240. package/dist/src/state/billing.js +126 -0
  241. package/dist/src/state/checkpoints.js +81 -0
  242. package/dist/src/state/config.js +58 -0
  243. package/dist/src/state/conversations.js +7 -0
  244. package/dist/src/state/credentials.js +96 -0
  245. package/dist/src/state/db.js +53 -0
  246. package/dist/src/state/index.js +23 -0
  247. package/dist/src/state/messages.js +76 -0
  248. package/dist/src/state/projects.js +92 -0
  249. package/dist/src/state/schema.js +233 -0
  250. package/dist/src/state/sessions.js +79 -0
  251. package/dist/src/state/teams.js +131 -0
  252. package/dist/src/telemetry.js +91 -0
  253. package/dist/src/tools/aws-ops.js +747 -0
  254. package/dist/src/tools/azure-ops.js +491 -0
  255. package/dist/src/tools/file-ops.js +451 -0
  256. package/dist/src/tools/gcp-ops.js +559 -0
  257. package/dist/src/tools/git-ops.js +557 -0
  258. package/dist/src/tools/github-ops.js +460 -0
  259. package/dist/src/tools/helm-ops.js +634 -0
  260. package/dist/src/tools/index.js +16 -0
  261. package/dist/src/tools/k8s-ops.js +579 -0
  262. package/dist/src/tools/schemas/converter.js +129 -0
  263. package/dist/src/tools/schemas/devops.js +3319 -0
  264. package/dist/src/tools/schemas/index.js +19 -0
  265. package/dist/src/tools/schemas/standard.js +966 -0
  266. package/dist/src/tools/schemas/types.js +409 -0
  267. package/dist/src/tools/spawn-exec.js +109 -0
  268. package/dist/src/tools/terraform-ops.js +627 -0
  269. package/dist/src/types/config.js +1 -0
  270. package/dist/src/types/drift.js +4 -0
  271. package/dist/src/types/enterprise.js +5 -0
  272. package/dist/src/types/index.js +14 -0
  273. package/dist/src/types/plan.js +1 -0
  274. package/dist/src/types/request.js +1 -0
  275. package/dist/src/types/response.js +1 -0
  276. package/dist/src/types/service.js +1 -0
  277. package/dist/src/ui/App.js +1672 -0
  278. package/dist/src/ui/DeployPreview.js +60 -0
  279. package/dist/src/ui/FileDiffModal.js +108 -0
  280. package/dist/src/ui/Header.js +46 -0
  281. package/dist/src/ui/HelpModal.js +9 -0
  282. package/dist/src/ui/InputBox.js +408 -0
  283. package/dist/src/ui/MessageList.js +795 -0
  284. package/dist/src/ui/PermissionPrompt.js +72 -0
  285. package/dist/src/ui/StatusBar.js +109 -0
  286. package/dist/src/ui/TerminalPane.js +31 -0
  287. package/dist/src/ui/ToolCallDisplay.js +303 -0
  288. package/dist/src/ui/TreePane.js +83 -0
  289. package/dist/src/ui/chat-ui.js +721 -0
  290. package/dist/src/ui/index.js +11 -0
  291. package/dist/src/ui/ink/index.js +1325 -0
  292. package/dist/src/ui/streaming.js +137 -0
  293. package/dist/src/ui/theme.js +78 -0
  294. package/dist/src/ui/types.js +7 -0
  295. package/dist/src/utils/analytics.js +61 -0
  296. package/dist/src/utils/cost-warning.js +25 -0
  297. package/dist/src/utils/env.js +42 -0
  298. package/dist/src/utils/errors.js +54 -0
  299. package/dist/src/utils/event-bus.js +22 -0
  300. package/dist/src/utils/index.js +16 -0
  301. package/dist/src/utils/logger.js +150 -0
  302. package/dist/src/utils/rate-limiter.js +90 -0
  303. package/dist/src/utils/service-auth.js +36 -0
  304. package/dist/src/utils/validation.js +39 -0
  305. package/dist/src/version.js +3 -0
  306. package/dist/src/watcher/index.js +192 -0
  307. package/dist/src/wizard/approval.js +275 -0
  308. package/dist/src/wizard/index.js +13 -0
  309. package/dist/src/wizard/prompts.js +273 -0
  310. package/dist/src/wizard/types.js +4 -0
  311. package/dist/src/wizard/ui.js +453 -0
  312. package/dist/src/wizard/wizard.js +227 -0
  313. package/package.json +22 -15
  314. package/src/__tests__/alias.test.ts +133 -0
  315. package/src/__tests__/cli-run.test.ts +237 -1
  316. package/src/__tests__/compat-sqlite.test.ts +68 -0
  317. package/src/__tests__/context-manager.test.ts +130 -0
  318. package/src/__tests__/devops-terminal-gaps.test.ts +718 -0
  319. package/src/__tests__/doctor.test.ts +48 -0
  320. package/src/__tests__/export.test.ts +236 -0
  321. package/src/__tests__/gap-11-18-20.test.ts +958 -0
  322. package/src/__tests__/helm-streaming.test.ts +127 -0
  323. package/src/__tests__/incident.test.ts +179 -0
  324. package/src/__tests__/init.test.ts +54 -3
  325. package/src/__tests__/logs.test.ts +107 -0
  326. package/src/__tests__/loop-errors.test.ts +244 -0
  327. package/src/__tests__/perf-optimizations.test.ts +847 -0
  328. package/src/__tests__/pipeline.test.ts +50 -0
  329. package/src/__tests__/polish-phase3.test.ts +340 -0
  330. package/src/__tests__/profile.test.ts +237 -0
  331. package/src/__tests__/rollback.test.ts +83 -0
  332. package/src/__tests__/runbook.test.ts +219 -0
  333. package/src/__tests__/schedule.test.ts +206 -0
  334. package/src/__tests__/sessions.test.ts +95 -0
  335. package/src/__tests__/standalone-migration.test.ts +199 -0
  336. package/src/__tests__/status.test.ts +158 -0
  337. package/src/__tests__/stream-with-tools.test.ts +49 -1
  338. package/src/__tests__/system-prompt.test.ts +81 -2
  339. package/src/__tests__/terminal-gap-v2.test.ts +395 -0
  340. package/src/__tests__/terminal-parity.test.ts +393 -0
  341. package/src/__tests__/tf-apply.test.ts +187 -0
  342. package/src/__tests__/tool-schemas.test.ts +209 -4
  343. package/src/__tests__/version-json.test.ts +184 -0
  344. package/src/__tests__/watch.test.ts +129 -0
  345. package/src/agent/compaction-agent.ts +40 -1
  346. package/src/agent/context-manager.ts +67 -3
  347. package/src/agent/deploy-preview.ts +62 -1
  348. package/src/agent/expand-files.ts +108 -0
  349. package/src/agent/loop.ts +1312 -31
  350. package/src/agent/permissions.ts +51 -4
  351. package/src/agent/system-prompt.ts +573 -19
  352. package/src/app.ts +58 -0
  353. package/src/audit/security-scanner.ts +45 -0
  354. package/src/auth/keychain.ts +82 -0
  355. package/src/cli/init.ts +378 -5
  356. package/src/cli/run.ts +407 -16
  357. package/src/cli/serve.ts +78 -1
  358. package/src/cli/web.ts +10 -6
  359. package/src/cli.ts +312 -1
  360. package/src/clients/service-discovery.ts +30 -25
  361. package/src/commands/alias.ts +100 -0
  362. package/src/commands/audit/index.ts +121 -2
  363. package/src/commands/auth-cloud.ts +113 -0
  364. package/src/commands/auth-refresh.ts +187 -0
  365. package/src/commands/aws-discover.ts +144 -251
  366. package/src/commands/aws-terraform.ts +68 -118
  367. package/src/commands/chat.ts +9 -3
  368. package/src/commands/completions.ts +268 -0
  369. package/src/commands/config.ts +26 -0
  370. package/src/commands/cost/index.ts +218 -2
  371. package/src/commands/deploy.ts +260 -0
  372. package/src/commands/doctor.ts +744 -152
  373. package/src/commands/drift/index.ts +371 -23
  374. package/src/commands/export.ts +146 -0
  375. package/src/commands/generate-k8s.ts +9 -61
  376. package/src/commands/generate-terraform.ts +191 -449
  377. package/src/commands/help.ts +212 -36
  378. package/src/commands/history.ts +8 -1
  379. package/src/commands/incident.ts +166 -0
  380. package/src/commands/init.ts +5 -0
  381. package/src/commands/login.ts +86 -1
  382. package/src/commands/logs.ts +167 -0
  383. package/src/commands/onboarding.ts +211 -34
  384. package/src/commands/pipeline.ts +186 -0
  385. package/src/commands/plugin.ts +398 -0
  386. package/src/commands/profile.ts +342 -0
  387. package/src/commands/questionnaire.ts +0 -98
  388. package/src/commands/resume.ts +26 -34
  389. package/src/commands/rollback.ts +315 -0
  390. package/src/commands/rollout.ts +88 -0
  391. package/src/commands/runbook.ts +346 -0
  392. package/src/commands/schedule.ts +236 -0
  393. package/src/commands/status.ts +252 -0
  394. package/src/commands/team-context.ts +220 -0
  395. package/src/commands/template.ts +58 -57
  396. package/src/commands/tf/index.ts +70 -11
  397. package/src/commands/upgrade.ts +57 -0
  398. package/src/commands/version.ts +54 -50
  399. package/src/commands/watch.ts +153 -0
  400. package/src/compat/sqlite.ts +75 -5
  401. package/src/config/mode-store.ts +62 -0
  402. package/src/config/profiles.ts +84 -0
  403. package/src/config/types.ts +83 -1
  404. package/src/config/workspace-state.ts +53 -0
  405. package/src/engine/cost-estimator.ts +52 -10
  406. package/src/engine/executor.ts +33 -2
  407. package/src/engine/planner.ts +68 -1
  408. package/src/generator/terraform.ts +8 -0
  409. package/src/history/manager.ts +2 -74
  410. package/src/llm/cost-calculator.ts +2 -2
  411. package/src/llm/providers/anthropic.ts +50 -21
  412. package/src/llm/router.ts +76 -7
  413. package/src/lsp/languages.ts +3 -0
  414. package/src/lsp/manager.ts +20 -4
  415. package/src/nimbus.ts +34 -1
  416. package/src/sessions/manager.ts +108 -1
  417. package/src/sharing/viewer.ts +66 -0
  418. package/src/tools/file-ops.ts +22 -0
  419. package/src/tools/schemas/devops.ts +3007 -117
  420. package/src/tools/schemas/standard.ts +5 -1
  421. package/src/tools/schemas/types.ts +31 -1
  422. package/src/tools/spawn-exec.ts +148 -0
  423. package/src/ui/App.tsx +1183 -66
  424. package/src/ui/DeployPreview.tsx +62 -57
  425. package/src/ui/FileDiffModal.tsx +162 -0
  426. package/src/ui/Header.tsx +87 -24
  427. package/src/ui/HelpModal.tsx +57 -0
  428. package/src/ui/InputBox.tsx +163 -10
  429. package/src/ui/MessageList.tsx +487 -40
  430. package/src/ui/PermissionPrompt.tsx +17 -5
  431. package/src/ui/StatusBar.tsx +122 -3
  432. package/src/ui/TerminalPane.tsx +84 -0
  433. package/src/ui/ToolCallDisplay.tsx +252 -18
  434. package/src/ui/TreePane.tsx +132 -0
  435. package/src/ui/chat-ui.ts +41 -44
  436. package/src/ui/ink/index.ts +771 -38
  437. package/src/ui/theme.ts +104 -0
  438. package/src/ui/types.ts +18 -0
  439. package/src/version.ts +1 -1
  440. package/src/watcher/index.ts +66 -15
  441. package/src/wizard/types.ts +1 -0
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Profile Management Command — H1
3
+ *
4
+ * Per-project credential profiles stored in ~/.nimbus/profiles.json.
5
+ * Format: { "prod": { awsProfile, tfWorkspace, kubectlContext, gcpProject } }
6
+ *
7
+ * Usage:
8
+ * nimbus profile list — show all profiles (current marked with *)
9
+ * nimbus profile create <name> — interactive wizard
10
+ * nimbus profile set <name> — switch all context atomically
11
+ * nimbus profile delete <name> — removes profile
12
+ * nimbus profile show [name] — display profile details
13
+ */
14
+
15
+ import * as fs from 'node:fs';
16
+ import * as path from 'node:path';
17
+ import { homedir } from 'node:os';
18
+ import { ui } from '../wizard/ui';
19
+
20
+ /** A single credential profile. */
21
+ export interface CredentialProfile {
22
+ /** AWS_PROFILE value */
23
+ awsProfile?: string;
24
+ /** Terraform workspace name */
25
+ tfWorkspace?: string;
26
+ /** kubectl context name */
27
+ kubectlContext?: string;
28
+ /** GCP project ID */
29
+ gcpProject?: string;
30
+ /** Azure subscription ID */
31
+ azureSubscription?: string;
32
+ /** K8s namespace */
33
+ k8sNamespace?: string;
34
+ }
35
+
36
+ /** The full profiles store. */
37
+ export type ProfileStore = Record<string, CredentialProfile>;
38
+
39
+ const PROFILES_DIR = path.join(homedir(), '.nimbus');
40
+ const PROFILES_PATH = path.join(PROFILES_DIR, 'profiles.json');
41
+ const CURRENT_PROFILE_PATH = path.join(PROFILES_DIR, 'current-profile');
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // Low-level helpers
45
+ // ---------------------------------------------------------------------------
46
+
47
+ /** Load the profiles.json file. Returns empty object if it doesn't exist. */
48
+ export function loadProfiles(): ProfileStore {
49
+ try {
50
+ if (fs.existsSync(PROFILES_PATH)) {
51
+ const raw = fs.readFileSync(PROFILES_PATH, 'utf-8');
52
+ return JSON.parse(raw) as ProfileStore;
53
+ }
54
+ } catch {
55
+ /* ignore parse errors — treat as empty */
56
+ }
57
+ return {};
58
+ }
59
+
60
+ /** Persist the profiles store to disk. */
61
+ export function saveProfiles(profiles: ProfileStore): void {
62
+ if (!fs.existsSync(PROFILES_DIR)) {
63
+ fs.mkdirSync(PROFILES_DIR, { recursive: true });
64
+ }
65
+ fs.writeFileSync(PROFILES_PATH, JSON.stringify(profiles, null, 2), 'utf-8');
66
+ }
67
+
68
+ /** Get the name of the currently active profile (if any). */
69
+ export function getCurrentProfileName(): string | null {
70
+ // Check env var first
71
+ if (process.env.NIMBUS_PROFILE) return process.env.NIMBUS_PROFILE;
72
+ try {
73
+ if (fs.existsSync(CURRENT_PROFILE_PATH)) {
74
+ return fs.readFileSync(CURRENT_PROFILE_PATH, 'utf-8').trim() || null;
75
+ }
76
+ } catch {
77
+ /* ignore */
78
+ }
79
+ return null;
80
+ }
81
+
82
+ /** Persist the current profile name to disk. */
83
+ function setCurrentProfileName(name: string): void {
84
+ if (!fs.existsSync(PROFILES_DIR)) {
85
+ fs.mkdirSync(PROFILES_DIR, { recursive: true });
86
+ }
87
+ fs.writeFileSync(CURRENT_PROFILE_PATH, name, 'utf-8');
88
+ }
89
+
90
+ // ---------------------------------------------------------------------------
91
+ // Subcommands
92
+ // ---------------------------------------------------------------------------
93
+
94
+ async function listProfiles(): Promise<void> {
95
+ const profiles = loadProfiles();
96
+ const current = getCurrentProfileName();
97
+ const names = Object.keys(profiles);
98
+
99
+ if (names.length === 0) {
100
+ ui.info('No profiles configured. Create one with: nimbus profile create <name>');
101
+ return;
102
+ }
103
+
104
+ ui.header('Credential Profiles');
105
+ for (const name of names) {
106
+ const profile = profiles[name];
107
+ const marker = name === current ? ui.color('* ', 'green') : ' ';
108
+ ui.print(`${marker}${name}`);
109
+ if (profile.awsProfile) ui.print(` AWS profile: ${profile.awsProfile}`);
110
+ if (profile.tfWorkspace) ui.print(` TF workspace: ${profile.tfWorkspace}`);
111
+ if (profile.kubectlContext) ui.print(` kubectl context: ${profile.kubectlContext}`);
112
+ if (profile.gcpProject) ui.print(` GCP project: ${profile.gcpProject}`);
113
+ if (profile.azureSubscription) ui.print(` Azure subscription: ${profile.azureSubscription}`);
114
+ if (profile.k8sNamespace) ui.print(` K8s namespace: ${profile.k8sNamespace}`);
115
+ }
116
+ if (current) {
117
+ ui.newLine();
118
+ ui.dim(`Active profile: ${current}`);
119
+ }
120
+ }
121
+
122
+ async function createProfile(name: string): Promise<void> {
123
+ if (!name) {
124
+ ui.error('Usage: nimbus profile create <name>');
125
+ process.exit(1);
126
+ }
127
+
128
+ const profiles = loadProfiles();
129
+ if (profiles[name]) {
130
+ ui.warning(`Profile "${name}" already exists. Use "nimbus profile set ${name}" to activate it.`);
131
+ return;
132
+ }
133
+
134
+ const { input: inputPrompt } = await import('../wizard/prompts');
135
+
136
+ ui.header(`Create Profile: ${name}`);
137
+ ui.dim('Leave fields empty to skip.');
138
+ ui.newLine();
139
+
140
+ const awsProfile = await inputPrompt({ message: 'AWS_PROFILE value', defaultValue: '' });
141
+ const tfWorkspace = await inputPrompt({ message: 'Terraform workspace', defaultValue: '' });
142
+ const kubectlContext = await inputPrompt({ message: 'kubectl context', defaultValue: '' });
143
+ const gcpProject = await inputPrompt({ message: 'GCP project ID', defaultValue: '' });
144
+ const azureSubscription = await inputPrompt({ message: 'Azure subscription ID', defaultValue: '' });
145
+ const k8sNamespace = await inputPrompt({ message: 'Default K8s namespace', defaultValue: '' });
146
+
147
+ const profile: CredentialProfile = {};
148
+ if (awsProfile) profile.awsProfile = awsProfile;
149
+ if (tfWorkspace) profile.tfWorkspace = tfWorkspace;
150
+ if (kubectlContext) profile.kubectlContext = kubectlContext;
151
+ if (gcpProject) profile.gcpProject = gcpProject;
152
+ if (azureSubscription) profile.azureSubscription = azureSubscription;
153
+ if (k8sNamespace) profile.k8sNamespace = k8sNamespace;
154
+
155
+ profiles[name] = profile;
156
+ saveProfiles(profiles);
157
+
158
+ ui.print(`${ui.color('✓', 'green')} Profile "${name}" created.`);
159
+ ui.dim('Activate it with: nimbus profile set ' + name);
160
+ }
161
+
162
+ async function setProfile(name: string): Promise<void> {
163
+ if (!name) {
164
+ ui.error('Usage: nimbus profile set <name>');
165
+ process.exit(1);
166
+ }
167
+
168
+ const profiles = loadProfiles();
169
+ const profile = profiles[name];
170
+ if (!profile) {
171
+ ui.error(`Profile "${name}" does not exist. Run "nimbus profile list" to see available profiles.`);
172
+ process.exit(1);
173
+ }
174
+
175
+ // Atomically apply all context switches
176
+ const { execFileSync } = await import('node:child_process');
177
+
178
+ const errors: string[] = [];
179
+
180
+ if (profile.awsProfile) {
181
+ process.env.AWS_PROFILE = profile.awsProfile;
182
+ ui.print(`${ui.color('✓', 'green')} AWS_PROFILE=${profile.awsProfile}`);
183
+ }
184
+
185
+ if (profile.gcpProject) {
186
+ process.env.GOOGLE_CLOUD_PROJECT = profile.gcpProject;
187
+ process.env.GCLOUD_PROJECT = profile.gcpProject;
188
+ ui.print(`${ui.color('✓', 'green')} GCP project=${profile.gcpProject}`);
189
+ }
190
+
191
+ if (profile.azureSubscription) {
192
+ process.env.AZURE_SUBSCRIPTION_ID = profile.azureSubscription;
193
+ ui.print(`${ui.color('✓', 'green')} Azure subscription=${profile.azureSubscription}`);
194
+ }
195
+
196
+ if (profile.k8sNamespace) {
197
+ process.env.K8S_NAMESPACE = profile.k8sNamespace;
198
+ ui.print(`${ui.color('✓', 'green')} K8S_NAMESPACE=${profile.k8sNamespace}`);
199
+ }
200
+
201
+ if (profile.kubectlContext) {
202
+ try {
203
+ execFileSync('kubectl', ['config', 'use-context', profile.kubectlContext], {
204
+ encoding: 'utf-8',
205
+ stdio: ['pipe', 'pipe', 'pipe'],
206
+ timeout: 10_000,
207
+ });
208
+ process.env.KUBECTL_CONTEXT = profile.kubectlContext;
209
+ ui.print(`${ui.color('✓', 'green')} kubectl context=${profile.kubectlContext}`);
210
+ } catch (e) {
211
+ const msg = e instanceof Error ? e.message : String(e);
212
+ errors.push(`kubectl context switch failed: ${msg}`);
213
+ }
214
+ }
215
+
216
+ if (profile.tfWorkspace) {
217
+ try {
218
+ execFileSync('terraform', ['workspace', 'select', profile.tfWorkspace], {
219
+ encoding: 'utf-8',
220
+ stdio: ['pipe', 'pipe', 'pipe'],
221
+ timeout: 30_000,
222
+ });
223
+ process.env.TF_WORKSPACE = profile.tfWorkspace;
224
+ ui.print(`${ui.color('✓', 'green')} TF workspace=${profile.tfWorkspace}`);
225
+ } catch (e) {
226
+ const msg = e instanceof Error ? e.message : String(e);
227
+ errors.push(`terraform workspace switch failed: ${msg}`);
228
+ }
229
+ }
230
+
231
+ // Persist the active profile name
232
+ setCurrentProfileName(name);
233
+
234
+ ui.newLine();
235
+ if (errors.length > 0) {
236
+ for (const err of errors) {
237
+ ui.warning(err);
238
+ }
239
+ ui.warning(`Profile "${name}" partially applied. Some tool switches failed.`);
240
+ } else {
241
+ ui.print(`${ui.color('✓', 'green')} Profile "${name}" activated.`);
242
+ }
243
+ }
244
+
245
+ async function deleteProfile(name: string): Promise<void> {
246
+ if (!name) {
247
+ ui.error('Usage: nimbus profile delete <name>');
248
+ process.exit(1);
249
+ }
250
+
251
+ const profiles = loadProfiles();
252
+ if (!profiles[name]) {
253
+ ui.error(`Profile "${name}" does not exist.`);
254
+ process.exit(1);
255
+ }
256
+
257
+ const { confirm } = await import('../wizard');
258
+ const ok = await confirm({
259
+ message: `Delete profile "${name}"?`,
260
+ defaultValue: false,
261
+ });
262
+
263
+ if (!ok) {
264
+ ui.info('Aborted.');
265
+ return;
266
+ }
267
+
268
+ delete profiles[name];
269
+ saveProfiles(profiles);
270
+
271
+ // Clear current profile if it was the deleted one
272
+ const current = getCurrentProfileName();
273
+ if (current === name) {
274
+ try {
275
+ fs.unlinkSync(CURRENT_PROFILE_PATH);
276
+ } catch {
277
+ /* ignore */
278
+ }
279
+ }
280
+
281
+ ui.print(`${ui.color('✓', 'green')} Profile "${name}" deleted.`);
282
+ }
283
+
284
+ function showProfile(name: string | undefined): void {
285
+ const profiles = loadProfiles();
286
+ const current = getCurrentProfileName();
287
+ const targetName = name ?? current;
288
+
289
+ if (!targetName) {
290
+ ui.error('No active profile. Specify a name: nimbus profile show <name>');
291
+ return;
292
+ }
293
+
294
+ const profile = profiles[targetName];
295
+ if (!profile) {
296
+ ui.error(`Profile "${targetName}" does not exist.`);
297
+ return;
298
+ }
299
+
300
+ ui.header(`Profile: ${targetName}${targetName === current ? ' (active)' : ''}`);
301
+ console.log(JSON.stringify(profile, null, 2));
302
+ }
303
+
304
+ // ---------------------------------------------------------------------------
305
+ // Main dispatcher
306
+ // ---------------------------------------------------------------------------
307
+
308
+ export async function profileCommand(subcommand: string, args: string[]): Promise<void> {
309
+ switch (subcommand) {
310
+ case 'list':
311
+ case 'ls':
312
+ await listProfiles();
313
+ break;
314
+ case 'create':
315
+ case 'add':
316
+ await createProfile(args[0] ?? '');
317
+ break;
318
+ case 'set':
319
+ case 'use':
320
+ case 'switch':
321
+ await setProfile(args[0] ?? '');
322
+ break;
323
+ case 'delete':
324
+ case 'remove':
325
+ case 'rm':
326
+ await deleteProfile(args[0] ?? '');
327
+ break;
328
+ case 'show':
329
+ showProfile(args[0]);
330
+ break;
331
+ default:
332
+ ui.print('Usage: nimbus profile <list|create|set|delete|show> [name]');
333
+ ui.newLine();
334
+ ui.print(' list - Show all profiles (current marked with *)');
335
+ ui.print(' create <name> - Create a new profile (interactive wizard)');
336
+ ui.print(' set <name> - Switch to a profile (sets AWS_PROFILE, kubectl context, TF workspace)');
337
+ ui.print(' delete <name> - Delete a profile');
338
+ ui.print(' show [name] - Display profile details');
339
+ }
340
+ }
341
+
342
+ export default profileCommand;
@@ -13,7 +13,6 @@
13
13
  import { logger } from '../utils';
14
14
  import { ui } from '../wizard/ui';
15
15
  import { select, input, confirm, multiSelect } from '../wizard/prompts';
16
- import { generatorClient } from '../clients/generator-client';
17
16
 
18
17
  export interface QuestionnaireOptions {
19
18
  /** Questionnaire type */
@@ -69,106 +68,9 @@ export async function questionnaireCommand(options: QuestionnaireOptions): Promi
69
68
  ui.newLine();
70
69
  ui.header(`${capitalize(options.type)} Configuration Wizard`);
71
70
 
72
- // Try to use generator service if available
73
- const serviceAvailable = await generatorClient.isAvailable();
74
-
75
- if (serviceAvailable) {
76
- try {
77
- await runWithGeneratorService(options);
78
- return;
79
- } catch (error: any) {
80
- logger.warn('Generator service failed, falling back to local', { error: error.message });
81
- ui.warning(`Generator service error: ${error.message}. Falling back to local questionnaire.`);
82
- }
83
- }
84
-
85
71
  await runLocal(options);
86
72
  }
87
73
 
88
- /**
89
- * Run questionnaire via generator service
90
- */
91
- async function runWithGeneratorService(options: QuestionnaireOptions): Promise<void> {
92
- ui.info('Connected to Generator Service');
93
- ui.newLine();
94
-
95
- // Start questionnaire session
96
- let session = await generatorClient.startQuestionnaire(
97
- options.type as 'terraform' | 'kubernetes'
98
- );
99
- const sessionId = session.sessionId;
100
-
101
- const answers: Record<string, unknown> = {};
102
-
103
- // Loop through questions until complete
104
- while (!session.completed && session.currentQuestion) {
105
- const question = session.currentQuestion;
106
-
107
- // Build a Question object compatible with askQuestion()
108
- const questionObj: Question = {
109
- id: question.id,
110
- type: (question.type || 'text') as Question['type'],
111
- label: question.text,
112
- options: question.options?.map(opt => ({
113
- value: opt,
114
- label: opt,
115
- })),
116
- };
117
-
118
- const answer = await askQuestion(questionObj, answers);
119
- answers[question.id] = answer;
120
-
121
- // Submit answer to generator service
122
- session = await generatorClient.submitQuestionnaireAnswer(sessionId, question.id, answer);
123
-
124
- // Display progress
125
- if (session.progress !== undefined) {
126
- const percentage = typeof session.progress === 'number' ? session.progress : 0;
127
- ui.print(ui.dim(` Progress: ${percentage}%`));
128
- }
129
- }
130
-
131
- ui.newLine();
132
- ui.success('Questionnaire completed!');
133
-
134
- if (!options.dryRun) {
135
- ui.newLine();
136
- ui.startSpinner({ message: 'Generating code via Generator Service...' });
137
-
138
- const result = await generatorClient.generateFromQuestionnaire(sessionId);
139
-
140
- ui.stopSpinnerSuccess('Code generated successfully');
141
-
142
- // Write generated files to output directory
143
- const outputDir = options.outputDir || `./${options.type}`;
144
- const fs = await import('fs/promises');
145
- const path = await import('path');
146
-
147
- await fs.mkdir(outputDir, { recursive: true });
148
-
149
- const fileNames: string[] = [];
150
- for (const [fileName, content] of Object.entries(result.files)) {
151
- const filePath = path.join(outputDir, fileName);
152
- // Ensure parent directory exists for nested paths
153
- await fs.mkdir(path.dirname(filePath), { recursive: true });
154
- await fs.writeFile(filePath, content);
155
- fileNames.push(fileName);
156
- }
157
-
158
- ui.newLine();
159
- ui.print(ui.bold('Generated files:'));
160
- for (const file of fileNames) {
161
- ui.print(` ${ui.color('●', 'green')} ${file}`);
162
- }
163
- ui.newLine();
164
- ui.print(`Output directory: ${outputDir}`);
165
- } else {
166
- ui.newLine();
167
- ui.print(ui.bold('Collected answers:'));
168
- ui.print(JSON.stringify(answers, null, 2));
169
- }
170
- }
171
-
172
74
  /**
173
75
  * Run questionnaire locally
174
76
  */
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * Resume Command
3
- * Resume a task from its last checkpoint
3
+ * Resume a Nimbus session by ID (or last session if omitted).
4
+ * Looks up sessions from SQLite, then launches chat with that session.
4
5
  */
5
6
 
6
7
  import { ui } from '../wizard/ui';
7
- import { CoreEngineClient } from '../clients/core-engine-client';
8
+ import { SessionManager } from '../sessions/manager';
8
9
 
9
10
  export interface ResumeOptions {
10
11
  taskId?: string;
@@ -13,43 +14,34 @@ export interface ResumeOptions {
13
14
  export async function resumeCommand(taskIdOrOptions: string | ResumeOptions = {}): Promise<void> {
14
15
  const taskId = typeof taskIdOrOptions === 'string' ? taskIdOrOptions : taskIdOrOptions.taskId;
15
16
 
17
+ ui.header('Resume Session');
18
+
19
+ const sessionManager = SessionManager.getInstance();
20
+
21
+ // If no taskId given, try to resume the most recent session
16
22
  if (!taskId) {
17
- ui.error('Task ID is required. Usage: nimbus resume <task-id>');
18
- process.exit(1);
23
+ const sessions = sessionManager.list();
24
+ if (sessions.length === 0) {
25
+ ui.error('No sessions found. Start a new session with "nimbus chat".');
26
+ process.exit(1);
27
+ }
28
+ const lastSession = sessions[0];
29
+ ui.info(`Resuming last session: ${lastSession.id.slice(0, 8)}`);
30
+ const { chatCommand } = await import('./chat');
31
+ await chatCommand({ continue: true });
32
+ return;
19
33
  }
20
34
 
21
- ui.header('Resume Task');
22
- ui.info(`Task ID: ${taskId}`);
23
- ui.newLine();
35
+ // Look up specific session by ID (or prefix)
36
+ const sessions = sessionManager.list();
37
+ const found = sessions.find((s: { id: string }) => s.id === taskId || s.id.startsWith(taskId));
24
38
 
25
- const client = new CoreEngineClient();
26
-
27
- const available = await client.isAvailable();
28
- if (!available) {
29
- ui.error('Core Engine service is not available.');
39
+ if (!found) {
40
+ ui.error(`Session not found. Use "nimbus sessions" to list available sessions.`);
30
41
  process.exit(1);
31
42
  }
32
43
 
33
- ui.startSpinner({ message: 'Resuming task from checkpoint...' });
34
-
35
- try {
36
- const result = await client.resumeTask(taskId);
37
-
38
- if (result.success) {
39
- ui.stopSpinnerSuccess('Task resumed and completed successfully');
40
- ui.newLine();
41
- if (result.data) {
42
- const executionResults = result.data.executionResults || [];
43
- ui.print(`Steps completed: ${executionResults.length}`);
44
- }
45
- } else {
46
- ui.stopSpinnerFail('Resume failed');
47
- ui.error(result.error || 'Unknown error');
48
- process.exit(1);
49
- }
50
- } catch (error: any) {
51
- ui.stopSpinnerFail('Resume failed');
52
- ui.error(error.message || 'Failed to resume task');
53
- process.exit(1);
54
- }
44
+ ui.info(`Resuming session: ${found.id.slice(0, 8)}`);
45
+ const { chatCommand } = await import('./chat');
46
+ await chatCommand({ continue: true });
55
47
  }