@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,167 @@
1
+ /**
2
+ * Terraform VPC Demo Scenario
3
+ *
4
+ * Demonstrates creating a VPC with Terraform
5
+ */
6
+ export const terraformVpcScenario = {
7
+ id: 'terraform-vpc',
8
+ name: 'Create AWS VPC with Terraform',
9
+ description: 'Deploy a complete VPC infrastructure using Nimbus and Terraform',
10
+ category: 'terraform',
11
+ duration: 10,
12
+ prerequisites: [
13
+ 'AWS CLI configured with credentials',
14
+ 'Terraform installed (v1.0+)',
15
+ 'Nimbus CLI installed',
16
+ ],
17
+ tags: ['terraform', 'aws', 'vpc', 'networking'],
18
+ steps: [
19
+ {
20
+ id: 'init-project',
21
+ title: 'Initialize Nimbus Project',
22
+ description: 'Scan the current directory and set up Nimbus configuration',
23
+ command: 'nimbus init',
24
+ showOutput: true,
25
+ waitForInput: true,
26
+ mockResponse: `
27
+ Nimbus Initialization
28
+
29
+ Scanning project...
30
+
31
+ Project Summary:
32
+ Type: infrastructure
33
+ Languages: HCL
34
+ IaC Tools: Terraform
35
+ Cloud: AWS
36
+
37
+ Created .nimbus/project.yaml
38
+ Created .nimbus/config.yaml
39
+
40
+ Project initialized successfully!
41
+ `.trim(),
42
+ },
43
+ {
44
+ id: 'start-questionnaire',
45
+ title: 'Start Terraform Questionnaire',
46
+ description: 'Use the interactive wizard to configure VPC settings',
47
+ command: 'nimbus questionnaire terraform',
48
+ showOutput: true,
49
+ waitForInput: true,
50
+ mockResponse: `
51
+ Terraform Configuration Wizard
52
+
53
+ Starting local questionnaire...
54
+
55
+ Step 1/3: Provider Configuration
56
+ Provider: aws
57
+ Region: us-east-1
58
+
59
+ Step 2/3: Component Selection
60
+ Components: vpc
61
+
62
+ Step 3/3: VPC Configuration
63
+ CIDR Block: 10.0.0.0/16
64
+ Availability Zones: 3
65
+
66
+ Questionnaire completed!
67
+ Generating code...
68
+
69
+ Generated files:
70
+ ● main.tf
71
+ ● variables.tf
72
+ ● outputs.tf
73
+
74
+ Output directory: ./terraform
75
+ `.trim(),
76
+ },
77
+ {
78
+ id: 'preview-plan',
79
+ title: 'Preview Terraform Plan',
80
+ description: 'See what changes will be made before applying',
81
+ command: 'nimbus preview terraform ./terraform',
82
+ showOutput: true,
83
+ waitForInput: true,
84
+ mockResponse: `
85
+ Preview Terraform Changes
86
+
87
+ Directory: ./terraform
88
+
89
+ Creating execution plan...
90
+ Plan created
91
+
92
+ Plan Summary:
93
+
94
+ + 6 to add
95
+ ~ 0 to change
96
+ - 0 to destroy
97
+
98
+ Safety Check Summary:
99
+
100
+ 🟡 [MEDIUM] This operation will modify infrastructure
101
+
102
+ All safety checks passed
103
+ `.trim(),
104
+ },
105
+ {
106
+ id: 'apply-terraform',
107
+ title: 'Apply Terraform Configuration',
108
+ description: 'Deploy the VPC infrastructure with safety approval',
109
+ command: 'nimbus apply terraform ./terraform',
110
+ showOutput: true,
111
+ waitForInput: true,
112
+ mockResponse: `
113
+ Terraform Apply
114
+
115
+ Directory: ./terraform
116
+
117
+ Creating execution plan...
118
+ Plan created
119
+
120
+ Plan Summary:
121
+ + 6 to add
122
+
123
+ ╔══════════════════════════════════════════════════════════╗
124
+ ║ APPROVAL REQUIRED ║
125
+ ╠══════════════════════════════════════════════════════════╣
126
+ ║ Operation: terraform apply ║
127
+ ╚══════════════════════════════════════════════════════════╝
128
+
129
+ Identified Risks:
130
+
131
+ 🟡 [MEDIUM] This operation will modify infrastructure
132
+
133
+ Do you want to proceed with this operation? Yes
134
+
135
+ Operation approved
136
+
137
+ Applying changes...
138
+ Apply complete!
139
+
140
+ Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
141
+
142
+ Outputs:
143
+ vpc_id = "vpc-0abc123def456789"
144
+ private_subnets = ["subnet-001", "subnet-002", "subnet-003"]
145
+ public_subnets = ["subnet-101", "subnet-102", "subnet-103"]
146
+ `.trim(),
147
+ },
148
+ {
149
+ id: 'verify-vpc',
150
+ title: 'Verify VPC Creation',
151
+ description: 'List VPCs to confirm our new VPC was created',
152
+ command: 'nimbus aws vpc list',
153
+ showOutput: true,
154
+ waitForInput: false,
155
+ mockResponse: `
156
+ VPCs
157
+
158
+ Found 2 VPC(s)
159
+
160
+ VPC ID Name CIDR State Default
161
+ ─────────────────────────────────────────────────────────────────────
162
+ vpc-default default 172.31.0.0/16 available Yes
163
+ vpc-0abc123def456789 my-project 10.0.0.0/16 available No
164
+ `.trim(),
165
+ },
166
+ ],
167
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Demo Framework Types
3
+ *
4
+ * Type definitions for the demo scenarios framework
5
+ */
6
+ export {};
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Cost Estimator
3
+ *
4
+ * Standalone module for estimating monthly and annual infrastructure costs
5
+ * based on component type, environment, region, and usage patterns.
6
+ *
7
+ * Extracted from the cost estimation logic in verifier.ts and planner.ts,
8
+ * with expanded capabilities for detailed breakdowns and recommendations.
9
+ */
10
+ import { logger } from '../utils';
11
+ // ==========================================
12
+ // Constants
13
+ // ==========================================
14
+ /**
15
+ * Base monthly component costs in USD.
16
+ *
17
+ * These are intentionally conservative estimates for the most common
18
+ * instance sizes and usage patterns. Extracted directly from the
19
+ * original verifier.ts cost table and expanded for additional components.
20
+ *
21
+ * Sources:
22
+ * vpc: NAT Gateway ($0.045/h * 730h) ~= $32
23
+ * eks: Control plane only ($0.10/h * 730h) ~= $73
24
+ * rds: db.t3.micro ($0.017/h) + 20GB storage (~$2.30) ~= $15; rounded to $50 with Multi-AZ
25
+ * s3: Minimal storage estimate (< 100GB) ~= $5
26
+ */
27
+ const BASE_COMPONENT_COSTS = {
28
+ // AWS Compute
29
+ vpc: 32,
30
+ eks: 73,
31
+ ecs: 30,
32
+ lambda: 2,
33
+ // EC2 instance types (monthly on-demand us-east-1)
34
+ 't3.micro': 8,
35
+ 't3.small': 16,
36
+ 't3.medium': 32,
37
+ 't3.large': 65,
38
+ 'm5.large': 70,
39
+ 'm5.xlarge': 140,
40
+ 'm5.2xlarge': 280,
41
+ 'c5.large': 62,
42
+ 'c5.xlarge': 124,
43
+ 'r5.large': 91,
44
+ 'r5.xlarge': 182,
45
+ // RDS instance types (monthly, single-AZ)
46
+ 'db.t3.micro': 14,
47
+ 'db.t3.small': 28,
48
+ 'db.t3.medium': 56,
49
+ 'db.r5.large': 175,
50
+ 'db.r5.xlarge': 350,
51
+ // AWS Data
52
+ rds: 50,
53
+ s3: 5,
54
+ elasticache: 25,
55
+ sqs: 1,
56
+ sns: 1,
57
+ cloudfront: 10,
58
+ // AWS Network/LB
59
+ 'aws_nat_gateway': 32,
60
+ 'aws_lb': 25,
61
+ 'aws_alb': 25,
62
+ 'aws_instance': 30,
63
+ 'aws_db_instance': 50,
64
+ 'aws_s3_bucket': 5,
65
+ 'aws_eks_cluster': 73,
66
+ 'aws_elasticache_cluster': 25,
67
+ 'aws_rds_cluster': 50,
68
+ 'aws_lambda_function': 2,
69
+ 'aws_cloudfront_distribution': 10,
70
+ // GCP
71
+ 'google_compute_instance': 30,
72
+ 'google_container_cluster': 73,
73
+ 'google_sql_database_instance': 50,
74
+ 'google_storage_bucket': 5,
75
+ // Azure
76
+ 'azurerm_virtual_machine': 30,
77
+ 'azurerm_kubernetes_cluster': 73,
78
+ 'azurerm_sql_database': 50,
79
+ 'azurerm_storage_account': 5,
80
+ };
81
+ /**
82
+ * Regional cost multipliers relative to us-east-1 (base = 1.0).
83
+ * Approximate — derived from AWS published pricing differentials.
84
+ */
85
+ const REGIONAL_MULTIPLIERS = {
86
+ 'us-east-1': 1.0,
87
+ 'us-east-2': 1.0,
88
+ 'us-west-1': 1.08,
89
+ 'us-west-2': 1.0,
90
+ 'eu-west-1': 1.06,
91
+ 'eu-west-2': 1.1,
92
+ 'eu-central-1': 1.08,
93
+ 'ap-southeast-1': 1.14,
94
+ 'ap-northeast-1': 1.16,
95
+ 'ap-south-1': 1.05,
96
+ 'sa-east-1': 1.2,
97
+ 'ca-central-1': 1.06,
98
+ // GCP regions (approximate relative costs)
99
+ 'us-central1': 1.0,
100
+ 'us-east1': 1.0,
101
+ 'europe-west1': 1.08,
102
+ 'asia-east1': 1.12,
103
+ // Azure regions
104
+ eastus: 1.0,
105
+ westus: 1.05,
106
+ westeurope: 1.1,
107
+ southeastasia: 1.12,
108
+ };
109
+ /**
110
+ * Environment multipliers.
111
+ * Production typically uses larger, HA-ready instances; dev uses minimal sizes.
112
+ */
113
+ const ENVIRONMENT_MULTIPLIERS = {
114
+ development: 0.5,
115
+ staging: 0.75,
116
+ production: 1.0,
117
+ prod: 1.0,
118
+ dev: 0.5,
119
+ staging_: 0.75,
120
+ };
121
+ /**
122
+ * Human-readable notes per component explaining the cost assumption.
123
+ */
124
+ const COMPONENT_NOTES = {
125
+ vpc: 'NAT Gateway ($0.045/h) — one AZ; add $32/mo per additional AZ',
126
+ eks: 'EKS control plane only ($0.10/h); node group EC2 costs are additive',
127
+ rds: 'db.t3.micro Multi-AZ estimated; scales significantly with instance class',
128
+ s3: 'Minimal estimate (<100GB, <1M requests); review lifecycle policies for long-term savings',
129
+ ecs: 'Fargate minimal workload; scales linearly with vCPU and memory allocation',
130
+ lambda: 'Under 1M invocations/month; free tier may apply',
131
+ cloudfront: 'Under 1TB egress/month; varies heavily with traffic patterns',
132
+ elasticache: 'cache.t3.micro; consider Reserved Nodes for >30% savings in production',
133
+ sqs: 'Under 1M requests/month; near-zero cost at small scale',
134
+ sns: 'Under 1M notifications/month; near-zero cost at small scale',
135
+ };
136
+ // ==========================================
137
+ // CostEstimator
138
+ // ==========================================
139
+ export class CostEstimator {
140
+ /**
141
+ * Estimate the monthly and annual cost for a given set of components.
142
+ */
143
+ estimate(input) {
144
+ const environment = input.environment || 'production';
145
+ const provider = input.provider || 'aws';
146
+ const region = input.region || this.defaultRegion(provider);
147
+ const budgetLimit = input.budgetLimit;
148
+ logger.info(`Estimating cost for ${input.components.length} components ` +
149
+ `(env=${environment}, provider=${provider}, region=${region})`);
150
+ const envMultiplier = this.resolveEnvironmentMultiplier(environment);
151
+ const regionMultiplier = this.resolveRegionalMultiplier(region);
152
+ const breakdown = [];
153
+ for (const component of input.components) {
154
+ const baseCost = this.resolveBaseCost(component, input.customCosts);
155
+ const adjustedCost = Math.round(baseCost * envMultiplier * regionMultiplier * 100) / 100;
156
+ breakdown.push({
157
+ component,
158
+ baseMonthlyCost: baseCost,
159
+ adjustedMonthlyCost: adjustedCost,
160
+ environmentMultiplier: envMultiplier,
161
+ regionalMultiplier: regionMultiplier,
162
+ notes: COMPONENT_NOTES[component] ||
163
+ `Estimate for ${component}; verify against provider pricing`,
164
+ });
165
+ }
166
+ const totalMonthlyCost = Math.round(breakdown.reduce((sum, b) => sum + b.adjustedMonthlyCost, 0) * 100) / 100;
167
+ const totalAnnualCost = Math.round(totalMonthlyCost * 12 * 100) / 100;
168
+ const withinBudget = budgetLimit !== undefined ? totalMonthlyCost <= budgetLimit : true;
169
+ const recommendations = this.generateRecommendations(input, breakdown, totalMonthlyCost);
170
+ logger.info(`Cost estimate: $${totalMonthlyCost}/mo ($${totalAnnualCost}/yr); ` +
171
+ `${withinBudget ? 'within' : 'exceeds'} budget`);
172
+ return {
173
+ totalMonthlyCost,
174
+ totalAnnualCost,
175
+ breakdown,
176
+ withinBudget,
177
+ budgetLimit,
178
+ recommendations,
179
+ environment,
180
+ provider,
181
+ generatedAt: new Date(),
182
+ };
183
+ }
184
+ /**
185
+ * Estimate cost from a flat context object (compatible with verifier/planner usage).
186
+ *
187
+ * This is a convenience wrapper that accepts the same `context` shape used
188
+ * by the Verifier's `runCostChecks` method, allowing the CostEstimator to
189
+ * serve as a drop-in replacement.
190
+ */
191
+ estimateFromContext(context) {
192
+ const components = context.components || [];
193
+ const result = this.estimate({
194
+ components,
195
+ environment: context.environment || 'production',
196
+ provider: context.provider || 'aws',
197
+ region: context.region,
198
+ budgetLimit: context.budget_limit,
199
+ });
200
+ return result.totalMonthlyCost;
201
+ }
202
+ /**
203
+ * Format a CostEstimate as a Markdown report.
204
+ */
205
+ formatAsMarkdown(estimate) {
206
+ const lines = [
207
+ `# Infrastructure Cost Estimate`,
208
+ ``,
209
+ `**Environment:** ${estimate.environment}`,
210
+ `**Provider:** ${estimate.provider}`,
211
+ `**Generated:** ${estimate.generatedAt.toISOString()}`,
212
+ ``,
213
+ `## Summary`,
214
+ ``,
215
+ `| Metric | Value |`,
216
+ `|--------|-------|`,
217
+ `| Monthly Cost | $${estimate.totalMonthlyCost.toFixed(2)} |`,
218
+ `| Annual Cost | $${estimate.totalAnnualCost.toFixed(2)} |`,
219
+ ];
220
+ if (estimate.budgetLimit !== undefined) {
221
+ lines.push(`| Budget Limit | $${estimate.budgetLimit.toFixed(2)} |`, `| Status | ${estimate.withinBudget ? 'Within Budget' : 'Over Budget'} |`);
222
+ }
223
+ lines.push(``, `## Component Breakdown`, ``, `| Component | Base ($/mo) | Adjusted ($/mo) | Notes |`, `|-----------|------------|----------------|-------|`);
224
+ for (const b of estimate.breakdown) {
225
+ lines.push(`| ${b.component} | $${b.baseMonthlyCost.toFixed(2)} | $${b.adjustedMonthlyCost.toFixed(2)} | ${b.notes} |`);
226
+ }
227
+ if (estimate.recommendations.length > 0) {
228
+ lines.push(``, `## Recommendations`, ``);
229
+ for (const rec of estimate.recommendations) {
230
+ lines.push(`- ${rec}`);
231
+ }
232
+ }
233
+ return lines.join('\n');
234
+ }
235
+ /**
236
+ * Generate cost optimisation recommendations based on the estimate inputs and results.
237
+ */
238
+ generateRecommendations(input, breakdown, totalMonthlyCost) {
239
+ const recommendations = [];
240
+ const env = (input.environment || 'production').toLowerCase();
241
+ const components = input.components.map(c => c.toLowerCase());
242
+ // Production: Reserved instances
243
+ if (env === 'production' || env === 'prod') {
244
+ const hasExpensive = components.some(c => ['eks', 'rds', 'elasticache'].includes(c));
245
+ if (hasExpensive) {
246
+ recommendations.push('Consider Reserved Instances or Savings Plans for EKS nodes, RDS, and ElastiCache — ' +
247
+ 'typically 30-40% savings over on-demand pricing with 1-year commitments.');
248
+ }
249
+ }
250
+ // Non-production: Single NAT gateway
251
+ if (env !== 'production' && env !== 'prod' && components.includes('vpc')) {
252
+ recommendations.push('Use a single NAT Gateway in non-production environments to save ~$32/mo per additional AZ.');
253
+ }
254
+ // S3 lifecycle policies
255
+ if (components.includes('s3')) {
256
+ recommendations.push('Configure S3 Lifecycle policies to transition infrequently accessed objects to ' +
257
+ 'S3 Intelligent-Tiering or Glacier; can reduce storage costs by 40-60%.');
258
+ }
259
+ // Development: spot instances
260
+ if (env === 'development' || env === 'dev') {
261
+ if (components.some(c => ['eks', 'ecs'].includes(c))) {
262
+ recommendations.push('Use Spot Instances for development EKS node groups and ECS Fargate Spot — ' +
263
+ 'up to 90% savings with appropriate interruption handling.');
264
+ }
265
+ }
266
+ // High overall cost warning
267
+ if (totalMonthlyCost > 1000) {
268
+ recommendations.push(`Total monthly cost $${totalMonthlyCost.toFixed(2)} is significant. ` +
269
+ 'Review instance types, enable autoscaling, and run AWS Cost Explorer or GCP Cost Management ' +
270
+ 'to identify unexpected spend.');
271
+ }
272
+ // Lambda: evaluate if replacing always-on compute
273
+ if (components.includes('lambda') &&
274
+ !components.includes('ecs') &&
275
+ !components.includes('eks')) {
276
+ recommendations.push('Lambda-only architecture is cost-efficient at low request volumes. ' +
277
+ 'Monitor concurrency limits and cold-start latency as traffic grows.');
278
+ }
279
+ // EKS without VPC
280
+ if (components.includes('eks') && !components.includes('vpc')) {
281
+ recommendations.push('EKS clusters require a VPC. If using an existing VPC, ensure its NAT Gateway costs are ' +
282
+ 'accounted for separately (typically +$32/mo per AZ).');
283
+ }
284
+ return recommendations;
285
+ }
286
+ /**
287
+ * Resolve base cost for a component, respecting custom overrides.
288
+ */
289
+ resolveBaseCost(component, customCosts) {
290
+ if (customCosts && component in customCosts) {
291
+ return customCosts[component];
292
+ }
293
+ return BASE_COMPONENT_COSTS[component.toLowerCase()] ?? 0;
294
+ }
295
+ /**
296
+ * Resolve environment multiplier from an environment string.
297
+ */
298
+ resolveEnvironmentMultiplier(environment) {
299
+ const key = environment.toLowerCase();
300
+ return ENVIRONMENT_MULTIPLIERS[key] ?? 1.0;
301
+ }
302
+ /**
303
+ * Resolve regional multiplier from a region string.
304
+ */
305
+ resolveRegionalMultiplier(region) {
306
+ return REGIONAL_MULTIPLIERS[region] ?? 1.0;
307
+ }
308
+ /**
309
+ * Return the default region for a given provider.
310
+ */
311
+ defaultRegion(provider) {
312
+ switch (provider.toLowerCase()) {
313
+ case 'gcp':
314
+ return 'us-central1';
315
+ case 'azure':
316
+ return 'eastus';
317
+ case 'aws':
318
+ default:
319
+ return 'us-east-1';
320
+ }
321
+ }
322
+ /**
323
+ * Get the base cost table (useful for display or testing).
324
+ */
325
+ getBaseCostTable() {
326
+ return { ...BASE_COMPONENT_COSTS };
327
+ }
328
+ /**
329
+ * Get the regional multiplier table (useful for display or testing).
330
+ */
331
+ getRegionalMultiplierTable() {
332
+ return { ...REGIONAL_MULTIPLIERS };
333
+ }
334
+ }
@@ -0,0 +1,192 @@
1
+ /**
2
+ * ASCII Diagram Generator
3
+ *
4
+ * Generates architecture diagrams using box-drawing characters.
5
+ * No external dependencies — pure string manipulation.
6
+ *
7
+ * Embedded version: identical to services/core-engine-service/src/components/diagram-generator.ts
8
+ */
9
+ /**
10
+ * Generates real ASCII architecture diagrams from component/connection data.
11
+ */
12
+ export class DiagramGenerator {
13
+ boxWidth;
14
+ constructor(options = {}) {
15
+ this.boxWidth = options.boxWidth || 24;
16
+ }
17
+ /**
18
+ * Generate an ASCII architecture diagram.
19
+ */
20
+ generate(components, connections, title) {
21
+ if (components.length === 0) {
22
+ return '(no components)';
23
+ }
24
+ const lines = [];
25
+ // Title
26
+ if (title) {
27
+ lines.push(title);
28
+ lines.push('='.repeat(title.length));
29
+ lines.push('');
30
+ }
31
+ // Build adjacency for topological ordering
32
+ const adj = new Map();
33
+ const inDegree = new Map();
34
+ for (const c of components) {
35
+ adj.set(c.id, []);
36
+ inDegree.set(c.id, 0);
37
+ }
38
+ for (const conn of connections) {
39
+ adj.get(conn.from)?.push(conn.to);
40
+ inDegree.set(conn.to, (inDegree.get(conn.to) || 0) + 1);
41
+ }
42
+ // Topological sort (Kahn's algorithm) to determine row placement
43
+ const rows = [];
44
+ let queue = components.filter(c => (inDegree.get(c.id) || 0) === 0);
45
+ const placed = new Set();
46
+ while (queue.length > 0) {
47
+ rows.push([...queue]);
48
+ const nextQueue = [];
49
+ for (const node of queue) {
50
+ placed.add(node.id);
51
+ for (const neighbor of adj.get(node.id) || []) {
52
+ inDegree.set(neighbor, (inDegree.get(neighbor) || 0) - 1);
53
+ if (inDegree.get(neighbor) === 0 && !placed.has(neighbor)) {
54
+ const comp = components.find(c => c.id === neighbor);
55
+ if (comp) {
56
+ nextQueue.push(comp);
57
+ }
58
+ }
59
+ }
60
+ }
61
+ queue = nextQueue;
62
+ }
63
+ // Add any unplaced components (cycles) to the last row
64
+ for (const c of components) {
65
+ if (!placed.has(c.id)) {
66
+ if (rows.length === 0) {
67
+ rows.push([]);
68
+ }
69
+ rows[rows.length - 1].push(c);
70
+ }
71
+ }
72
+ // Track center positions for drawing connections
73
+ const colWidth = this.boxWidth + 4;
74
+ // Render rows of boxes
75
+ for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
76
+ const row = rows[rowIdx];
77
+ const rowLines = this.renderBoxRow(row, colWidth);
78
+ for (const line of rowLines) {
79
+ lines.push(line);
80
+ }
81
+ // Draw vertical connection arrows between rows
82
+ if (rowIdx < rows.length - 1) {
83
+ const nextRow = rows[rowIdx + 1];
84
+ const arrowLines = this.renderArrows(row, nextRow, connections, colWidth);
85
+ for (const line of arrowLines) {
86
+ lines.push(line);
87
+ }
88
+ }
89
+ }
90
+ // Legend for connections
91
+ if (connections.length > 0) {
92
+ lines.push('');
93
+ lines.push('Connections:');
94
+ for (const conn of connections) {
95
+ const fromComp = components.find(c => c.id === conn.from);
96
+ const toComp = components.find(c => c.id === conn.to);
97
+ if (fromComp && toComp) {
98
+ const label = conn.label ? ` (${conn.label})` : '';
99
+ lines.push(` ${fromComp.label} --> ${toComp.label}${label}`);
100
+ }
101
+ }
102
+ }
103
+ return lines.join('\n');
104
+ }
105
+ /**
106
+ * Render a row of component boxes.
107
+ */
108
+ renderBoxRow(components, colWidth) {
109
+ const w = this.boxWidth;
110
+ const top = `+${'-'.repeat(w)}+`;
111
+ const bot = `+${'-'.repeat(w)}+`;
112
+ const topLine = [];
113
+ const labelLine = [];
114
+ const typeLine = [];
115
+ const botLine = [];
116
+ for (const comp of components) {
117
+ const padding = colWidth - w - 2;
118
+ const pad = ' '.repeat(Math.max(0, padding / 2));
119
+ topLine.push(pad + top + pad);
120
+ const truncLabel = comp.label.length > w - 2 ? `${comp.label.substring(0, w - 5)}...` : comp.label;
121
+ const labelPadded = truncLabel.padStart(Math.floor((w + truncLabel.length) / 2)).padEnd(w);
122
+ labelLine.push(`${pad}|${labelPadded}|${pad}`);
123
+ if (comp.type) {
124
+ const truncType = comp.type.length > w - 2 ? `${comp.type.substring(0, w - 5)}...` : comp.type;
125
+ const typePadded = truncType.padStart(Math.floor((w + truncType.length) / 2)).padEnd(w);
126
+ typeLine.push(`${pad}|${typePadded}|${pad}`);
127
+ }
128
+ else {
129
+ typeLine.push(`${pad}|${' '.repeat(w)}|${pad}`);
130
+ }
131
+ botLine.push(pad + bot + pad);
132
+ }
133
+ return [topLine.join(''), labelLine.join(''), typeLine.join(''), botLine.join('')];
134
+ }
135
+ /**
136
+ * Render vertical arrows between two rows of components.
137
+ */
138
+ renderArrows(fromRow, toRow, connections, colWidth) {
139
+ const totalCols = Math.max(fromRow.length, toRow.length);
140
+ const lineWidth = totalCols * colWidth;
141
+ // Find which connections go between these rows
142
+ const fromIds = new Set(fromRow.map(c => c.id));
143
+ const toIds = new Set(toRow.map(c => c.id));
144
+ const activeConns = connections.filter(c => fromIds.has(c.from) && toIds.has(c.to));
145
+ if (activeConns.length === 0) {
146
+ return [''];
147
+ }
148
+ // Draw simple vertical arrows at the center of each from-component
149
+ const arrowRow1 = new Array(lineWidth).fill(' ');
150
+ const arrowRow2 = new Array(lineWidth).fill(' ');
151
+ const arrowRow3 = new Array(lineWidth).fill(' ');
152
+ for (const conn of activeConns) {
153
+ const fromIdx = fromRow.findIndex(c => c.id === conn.from);
154
+ if (fromIdx >= 0) {
155
+ const center = Math.floor(fromIdx * colWidth + colWidth / 2);
156
+ if (center < lineWidth) {
157
+ arrowRow1[center] = '|';
158
+ arrowRow2[center] = '|';
159
+ arrowRow3[center] = 'V';
160
+ }
161
+ }
162
+ }
163
+ return [
164
+ arrowRow1.join('').trimEnd(),
165
+ arrowRow2.join('').trimEnd(),
166
+ arrowRow3.join('').trimEnd(),
167
+ ];
168
+ }
169
+ /**
170
+ * Generate a diagram for infrastructure components.
171
+ * Convenience method that maps common infra component names to diagram elements.
172
+ */
173
+ generateInfrastructureDiagram(componentNames, provider = 'aws') {
174
+ const components = componentNames.map(name => ({
175
+ id: name,
176
+ label: name.toUpperCase(),
177
+ type: provider.toUpperCase(),
178
+ }));
179
+ // Infer common connections
180
+ const connections = [];
181
+ const hasVpc = componentNames.includes('vpc');
182
+ for (const name of componentNames) {
183
+ if (hasVpc && name !== 'vpc' && ['eks', 'rds', 'ecs', 'lambda'].includes(name)) {
184
+ connections.push({ from: 'vpc', to: name, label: 'network' });
185
+ }
186
+ if (name === 'eks' && componentNames.includes('rds')) {
187
+ connections.push({ from: 'eks', to: 'rds', label: 'database' });
188
+ }
189
+ }
190
+ return this.generate(components, connections, `${provider.toUpperCase()} Infrastructure Architecture`);
191
+ }
192
+ }