@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,156 @@
1
+ /**
2
+ * Core Engine Client
3
+ *
4
+ * Client for interacting with the Core Engine Service
5
+ */
6
+ export class CoreEngineClient {
7
+ baseUrl;
8
+ constructor(baseUrl) {
9
+ this.baseUrl = baseUrl || process.env.CORE_ENGINE_URL || 'http://localhost:3010';
10
+ }
11
+ /**
12
+ * Detect drift in infrastructure
13
+ */
14
+ async detectDrift(params) {
15
+ const response = await fetch(`${this.baseUrl}/api/drift/detect`, {
16
+ method: 'POST',
17
+ headers: {
18
+ 'Content-Type': 'application/json',
19
+ },
20
+ body: JSON.stringify(params),
21
+ });
22
+ if (!response.ok) {
23
+ const error = (await response.json().catch(() => ({ message: 'Unknown error' })));
24
+ throw new Error(error.message || `Failed to detect drift: ${response.status}`);
25
+ }
26
+ const data = (await response.json());
27
+ return data.report;
28
+ }
29
+ /**
30
+ * Create a remediation plan for detected drift
31
+ */
32
+ async createRemediationPlan(params) {
33
+ const response = await fetch(`${this.baseUrl}/api/drift/plan`, {
34
+ method: 'POST',
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ },
38
+ body: JSON.stringify(params),
39
+ });
40
+ if (!response.ok) {
41
+ const error = (await response.json().catch(() => ({ message: 'Unknown error' })));
42
+ throw new Error(error.message || `Failed to create remediation plan: ${response.status}`);
43
+ }
44
+ return response.json();
45
+ }
46
+ /**
47
+ * Fix detected drift
48
+ */
49
+ async fixDrift(params) {
50
+ const response = await fetch(`${this.baseUrl}/api/drift/fix`, {
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ },
55
+ body: JSON.stringify(params),
56
+ });
57
+ if (!response.ok) {
58
+ const error = (await response.json().catch(() => ({ message: 'Unknown error' })));
59
+ throw new Error(error.message || `Failed to fix drift: ${response.status}`);
60
+ }
61
+ const data = (await response.json());
62
+ return data.result;
63
+ }
64
+ /**
65
+ * Check if a task can be rolled back
66
+ */
67
+ async canRollback(taskId) {
68
+ const response = await fetch(`${this.baseUrl}/api/tasks/${taskId}/rollback/check`, {
69
+ method: 'GET',
70
+ });
71
+ if (!response.ok) {
72
+ return false;
73
+ }
74
+ const data = (await response.json());
75
+ return data.canRollback;
76
+ }
77
+ /**
78
+ * Rollback a task
79
+ */
80
+ async rollback(params) {
81
+ const response = await fetch(`${this.baseUrl}/api/tasks/${params.taskId}/rollback`, {
82
+ method: 'POST',
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ body: JSON.stringify({ force: params.force }),
87
+ });
88
+ if (!response.ok) {
89
+ const error = (await response.json().catch(() => ({ message: 'Unknown error' })));
90
+ throw new Error(error.message || `Failed to rollback: ${response.status}`);
91
+ }
92
+ return response.json();
93
+ }
94
+ /**
95
+ * Resume a task from its last checkpoint
96
+ */
97
+ async resumeTask(taskId) {
98
+ const response = await fetch(`${this.baseUrl}/api/tasks/${taskId}/resume`, {
99
+ method: 'POST',
100
+ headers: {
101
+ 'Content-Type': 'application/json',
102
+ },
103
+ });
104
+ if (!response.ok) {
105
+ const error = (await response.json().catch(() => ({ message: 'Unknown error' })));
106
+ return {
107
+ success: false,
108
+ error: error.error || error.message || `Failed to resume task: ${response.status}`,
109
+ };
110
+ }
111
+ const data = (await response.json());
112
+ return {
113
+ success: data.success,
114
+ data: data.data,
115
+ error: data.error,
116
+ };
117
+ }
118
+ /**
119
+ * Get compliance report
120
+ */
121
+ async getComplianceReport(params) {
122
+ const response = await fetch(`${this.baseUrl}/api/drift/compliance`, {
123
+ method: 'POST',
124
+ headers: {
125
+ 'Content-Type': 'application/json',
126
+ },
127
+ body: JSON.stringify(params),
128
+ });
129
+ if (!response.ok) {
130
+ const error = (await response.json().catch(() => ({ message: 'Unknown error' })));
131
+ throw new Error(error.message || `Failed to get compliance report: ${response.status}`);
132
+ }
133
+ return response.json();
134
+ }
135
+ /**
136
+ * Check if the Core Engine service is available
137
+ */
138
+ async isAvailable() {
139
+ try {
140
+ const response = await fetch(`${this.baseUrl}/health`, {
141
+ method: 'GET',
142
+ signal: AbortSignal.timeout(5000),
143
+ });
144
+ return response.ok;
145
+ }
146
+ catch {
147
+ return false;
148
+ }
149
+ }
150
+ /**
151
+ * Health check (alias for isAvailable)
152
+ */
153
+ async healthCheck() {
154
+ return this.isAvailable();
155
+ }
156
+ }
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Enterprise API Clients
3
+ * Clients for auth, team, billing, and audit services
4
+ */
5
+ import { RestClient, ServiceURLs } from '.';
6
+ import { logger } from '../utils';
7
+ // ==================== Auth Client ====================
8
+ export class AuthClient {
9
+ client;
10
+ constructor() {
11
+ this.client = new RestClient(ServiceURLs.AUTH);
12
+ }
13
+ async initiateDeviceFlow() {
14
+ const response = await this.client.post('/api/auth/device/initiate');
15
+ if (!response.success || !response.data) {
16
+ throw new Error(response.error?.message || 'Failed to initiate device flow');
17
+ }
18
+ return response.data;
19
+ }
20
+ async pollDeviceCode(deviceCode) {
21
+ const response = await this.client.get(`/api/auth/device/poll/${deviceCode}`);
22
+ if (!response.success || !response.data) {
23
+ throw new Error(response.error?.message || 'Failed to poll device code');
24
+ }
25
+ return response.data;
26
+ }
27
+ async verifyDeviceCode(userCode, userId) {
28
+ const response = await this.client.post('/api/auth/device/verify', {
29
+ userCode,
30
+ userId,
31
+ });
32
+ return response.success && response.data?.verified === true;
33
+ }
34
+ async validateToken(accessToken) {
35
+ const response = await this.client.post('/api/auth/token/validate', {
36
+ accessToken,
37
+ });
38
+ if (!response.success || !response.data) {
39
+ return { valid: false };
40
+ }
41
+ return response.data;
42
+ }
43
+ }
44
+ // ==================== Team Client ====================
45
+ export class TeamClient {
46
+ client;
47
+ constructor() {
48
+ this.client = new RestClient(ServiceURLs.TEAM);
49
+ }
50
+ async createTeam(request) {
51
+ const response = await this.client.post('/api/team/teams', request);
52
+ if (!response.success || !response.data) {
53
+ throw new Error(response.error?.message || 'Failed to create team');
54
+ }
55
+ return response.data;
56
+ }
57
+ async getTeam(teamId) {
58
+ const response = await this.client.get(`/api/team/teams/${teamId}`);
59
+ if (!response.success) {
60
+ return null;
61
+ }
62
+ return response.data || null;
63
+ }
64
+ async listTeams(userId) {
65
+ const response = await this.client.get(`/api/team/teams?userId=${userId}`);
66
+ if (!response.success || !response.data) {
67
+ logger.warn('Failed to list teams; returning empty list', {
68
+ userId,
69
+ error: response.error?.message,
70
+ });
71
+ return [];
72
+ }
73
+ return response.data;
74
+ }
75
+ async deleteTeam(teamId) {
76
+ const response = await this.client.delete(`/api/team/teams/${teamId}`);
77
+ if (!response.success) {
78
+ throw new Error(response.error?.message || 'Failed to delete team');
79
+ }
80
+ }
81
+ async inviteMember(teamId, request) {
82
+ const response = await this.client.post(`/api/team/teams/${teamId}/members`, request);
83
+ if (!response.success || !response.data) {
84
+ throw new Error(response.error?.message || 'Failed to invite member');
85
+ }
86
+ return response.data;
87
+ }
88
+ async listMembers(teamId) {
89
+ const response = await this.client.get(`/api/team/teams/${teamId}/members`);
90
+ if (!response.success || !response.data) {
91
+ logger.warn('Failed to list team members; returning empty list', {
92
+ teamId,
93
+ error: response.error?.message,
94
+ });
95
+ return [];
96
+ }
97
+ return response.data;
98
+ }
99
+ async removeMember(teamId, userId) {
100
+ const response = await this.client.delete(`/api/team/teams/${teamId}/members/${userId}`);
101
+ if (!response.success) {
102
+ throw new Error(response.error?.message || 'Failed to remove member');
103
+ }
104
+ }
105
+ async updateMemberRole(teamId, userId, role) {
106
+ const response = await this.client.put(`/api/team/teams/${teamId}/members/${userId}`, { role });
107
+ if (!response.success || !response.data) {
108
+ throw new Error(response.error?.message || 'Failed to update member role');
109
+ }
110
+ return response.data;
111
+ }
112
+ }
113
+ // ==================== Billing Client ====================
114
+ export class BillingClient {
115
+ client;
116
+ constructor() {
117
+ this.client = new RestClient(ServiceURLs.BILLING);
118
+ }
119
+ async getStatus(teamId) {
120
+ const response = await this.client.get(`/api/billing/status?teamId=${teamId}`);
121
+ if (!response.success || !response.data) {
122
+ throw new Error(response.error?.message || 'Failed to get billing status');
123
+ }
124
+ return response.data;
125
+ }
126
+ async subscribe(teamId, request) {
127
+ const response = await this.client.post('/api/billing/subscribe', {
128
+ ...request,
129
+ teamId,
130
+ });
131
+ if (!response.success || !response.data) {
132
+ throw new Error(response.error?.message || 'Failed to subscribe');
133
+ }
134
+ return response.data;
135
+ }
136
+ async cancel(teamId) {
137
+ const response = await this.client.post('/api/billing/cancel', { teamId });
138
+ if (!response.success || !response.data) {
139
+ throw new Error(response.error?.message || 'Failed to cancel subscription');
140
+ }
141
+ return response.data;
142
+ }
143
+ async getUsage(teamId, period = 'month') {
144
+ const response = await this.client.get(`/api/billing/usage?teamId=${teamId}&period=${period}`);
145
+ if (!response.success || !response.data) {
146
+ throw new Error(response.error?.message || 'Failed to get usage');
147
+ }
148
+ return response.data;
149
+ }
150
+ async getInvoices(teamId, limit = 10) {
151
+ const response = await this.client.get(`/api/billing/invoices?teamId=${teamId}&limit=${limit}`);
152
+ if (!response.success || !response.data) {
153
+ logger.warn('Failed to fetch invoices; returning empty list', {
154
+ teamId,
155
+ error: response.error?.message,
156
+ });
157
+ return [];
158
+ }
159
+ return response.data;
160
+ }
161
+ async recordUsage(teamId, operationType, tokensUsed, costUsd, userId) {
162
+ await this.client.post('/api/billing/usage', {
163
+ teamId,
164
+ userId,
165
+ operationType,
166
+ tokensUsed,
167
+ costUsd,
168
+ });
169
+ }
170
+ }
171
+ // ==================== Audit Client ====================
172
+ export class AuditClient {
173
+ client;
174
+ constructor() {
175
+ this.client = new RestClient(ServiceURLs.AUDIT);
176
+ }
177
+ async createLog(request) {
178
+ const response = await this.client.post('/api/audit/logs', request);
179
+ if (!response.success || !response.data) {
180
+ throw new Error(response.error?.message || 'Failed to create audit log');
181
+ }
182
+ return response.data;
183
+ }
184
+ async queryLogs(query = {}) {
185
+ const params = new URLSearchParams();
186
+ if (query.teamId) {
187
+ params.set('teamId', query.teamId);
188
+ }
189
+ if (query.userId) {
190
+ params.set('userId', query.userId);
191
+ }
192
+ if (query.action) {
193
+ params.set('action', query.action);
194
+ }
195
+ if (query.status) {
196
+ params.set('status', query.status);
197
+ }
198
+ if (query.since) {
199
+ params.set('since', query.since);
200
+ }
201
+ if (query.until) {
202
+ params.set('until', query.until);
203
+ }
204
+ if (query.limit) {
205
+ params.set('limit', query.limit.toString());
206
+ }
207
+ if (query.offset) {
208
+ params.set('offset', query.offset.toString());
209
+ }
210
+ const response = await this.client.get(`/api/audit/logs?${params}`);
211
+ if (!response.success || !response.data) {
212
+ return { logs: [], total: 0, limit: 100, offset: 0 };
213
+ }
214
+ return response.data;
215
+ }
216
+ async exportLogs(format, query = {}) {
217
+ const params = new URLSearchParams();
218
+ params.set('format', format);
219
+ if (query.teamId) {
220
+ params.set('teamId', query.teamId);
221
+ }
222
+ if (query.userId) {
223
+ params.set('userId', query.userId);
224
+ }
225
+ if (query.action) {
226
+ params.set('action', query.action);
227
+ }
228
+ if (query.since) {
229
+ params.set('since', query.since);
230
+ }
231
+ if (query.until) {
232
+ params.set('until', query.until);
233
+ }
234
+ const url = `${ServiceURLs.AUDIT}/api/audit/export?${params}`;
235
+ const response = await fetch(url);
236
+ if (!response.ok) {
237
+ throw new Error('Failed to export audit logs');
238
+ }
239
+ return response.text();
240
+ }
241
+ }
242
+ // ==================== Singleton Instances ====================
243
+ export const authClient = new AuthClient();
244
+ export const teamClient = new TeamClient();
245
+ export const billingClient = new BillingClient();
246
+ export const auditClient = new AuditClient();
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Generator Service Client
3
+ *
4
+ * CLI client for communicating with the Generator Service
5
+ * for conversational IaC generation
6
+ */
7
+ export class GeneratorClient {
8
+ baseUrl;
9
+ constructor(baseUrl) {
10
+ this.baseUrl = baseUrl || process.env.GENERATOR_SERVICE_URL || 'http://localhost:3003';
11
+ }
12
+ /**
13
+ * Check if the generator service is available
14
+ */
15
+ async isAvailable() {
16
+ try {
17
+ const response = await fetch(`${this.baseUrl}/health`, {
18
+ method: 'GET',
19
+ signal: AbortSignal.timeout(5000),
20
+ });
21
+ return response.ok;
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ }
27
+ /**
28
+ * Process a conversational message
29
+ * Sends user message to the generator service and gets response with intent detection
30
+ */
31
+ async processConversation(sessionId, message, userId) {
32
+ const response = await fetch(`${this.baseUrl}/api/conversational/message`, {
33
+ method: 'POST',
34
+ headers: { 'Content-Type': 'application/json' },
35
+ body: JSON.stringify({ sessionId, message, userId }),
36
+ });
37
+ if (!response.ok) {
38
+ throw new Error(`Generator service error: ${response.status}`);
39
+ }
40
+ const data = (await response.json());
41
+ if (!data.success) {
42
+ throw new Error(data.error || 'Failed to process conversation');
43
+ }
44
+ const result = data.data;
45
+ // Determine if we can generate (have enough information)
46
+ const canGenerate = result.intent?.type === 'generate' &&
47
+ (!result.needs_clarification || result.needs_clarification.length === 0) &&
48
+ result.extracted_requirements?.components?.length > 0;
49
+ return {
50
+ message: result.message,
51
+ intent: result.intent,
52
+ canGenerate,
53
+ nextQuestion: result.needs_clarification?.[0],
54
+ extractedRequirements: result.extracted_requirements,
55
+ needsClarification: result.needs_clarification,
56
+ suggestedActions: result.suggested_actions,
57
+ };
58
+ }
59
+ /**
60
+ * Generate infrastructure from a conversation session
61
+ */
62
+ async generateFromConversation(sessionId, options) {
63
+ const response = await fetch(`${this.baseUrl}/api/generate/from-conversation`, {
64
+ method: 'POST',
65
+ headers: { 'Content-Type': 'application/json' },
66
+ body: JSON.stringify({
67
+ sessionId,
68
+ applyBestPractices: options?.applyBestPractices ?? true,
69
+ autofix: options?.autofix ?? true,
70
+ }),
71
+ });
72
+ if (!response.ok) {
73
+ throw new Error(`Generator service error: ${response.status}`);
74
+ }
75
+ const data = (await response.json());
76
+ if (!data.success) {
77
+ throw new Error(data.error || 'Failed to generate infrastructure');
78
+ }
79
+ return {
80
+ success: true,
81
+ files: data.data.generated_files,
82
+ configuration: data.data.configuration,
83
+ stack: data.data.stack,
84
+ bestPracticesReport: data.data.best_practices_report,
85
+ errors: data.data.errors,
86
+ };
87
+ }
88
+ /**
89
+ * Get conversation session state
90
+ */
91
+ async getSession(sessionId) {
92
+ const response = await fetch(`${this.baseUrl}/api/conversational/session/${sessionId}`, {
93
+ method: 'GET',
94
+ });
95
+ if (!response.ok) {
96
+ if (response.status === 404) {
97
+ return null;
98
+ }
99
+ throw new Error(`Generator service error: ${response.status}`);
100
+ }
101
+ const data = (await response.json());
102
+ if (!data.success) {
103
+ return null;
104
+ }
105
+ return {
106
+ sessionId: data.data.session_id,
107
+ infrastructureStack: data.data.infrastructure_stack,
108
+ conversationHistory: data.data.conversation_history || [],
109
+ };
110
+ }
111
+ /**
112
+ * Clear conversation history but keep session
113
+ */
114
+ async clearHistory(sessionId) {
115
+ const response = await fetch(`${this.baseUrl}/api/conversational/clear/${sessionId}`, {
116
+ method: 'POST',
117
+ });
118
+ if (!response.ok) {
119
+ throw new Error(`Generator service error: ${response.status}`);
120
+ }
121
+ }
122
+ /**
123
+ * Delete a conversation session
124
+ */
125
+ async deleteSession(sessionId) {
126
+ const response = await fetch(`${this.baseUrl}/api/conversational/session/${sessionId}`, {
127
+ method: 'DELETE',
128
+ });
129
+ if (!response.ok && response.status !== 404) {
130
+ throw new Error(`Generator service error: ${response.status}`);
131
+ }
132
+ }
133
+ /**
134
+ * Start a questionnaire session
135
+ */
136
+ async startQuestionnaire(type) {
137
+ const response = await fetch(`${this.baseUrl}/api/questionnaire/start`, {
138
+ method: 'POST',
139
+ headers: { 'Content-Type': 'application/json' },
140
+ body: JSON.stringify({ type }),
141
+ });
142
+ if (!response.ok) {
143
+ throw new Error(`Generator service error: ${response.status}`);
144
+ }
145
+ const data = (await response.json());
146
+ if (!data.success) {
147
+ throw new Error(data.error || 'Failed to start questionnaire');
148
+ }
149
+ return data.data;
150
+ }
151
+ /**
152
+ * Submit questionnaire answer
153
+ */
154
+ async submitQuestionnaireAnswer(sessionId, questionId, value) {
155
+ const response = await fetch(`${this.baseUrl}/api/questionnaire/answer`, {
156
+ method: 'POST',
157
+ headers: { 'Content-Type': 'application/json' },
158
+ body: JSON.stringify({ sessionId, questionId, value }),
159
+ });
160
+ if (!response.ok) {
161
+ throw new Error(`Generator service error: ${response.status}`);
162
+ }
163
+ const data = (await response.json());
164
+ if (!data.success) {
165
+ throw new Error(data.error || 'Failed to submit answer');
166
+ }
167
+ return data.data;
168
+ }
169
+ /**
170
+ * Generate from completed questionnaire
171
+ */
172
+ async generateFromQuestionnaire(sessionId, options) {
173
+ const response = await fetch(`${this.baseUrl}/api/generate/from-questionnaire`, {
174
+ method: 'POST',
175
+ headers: { 'Content-Type': 'application/json' },
176
+ body: JSON.stringify({
177
+ sessionId,
178
+ applyBestPractices: options?.applyBestPractices ?? true,
179
+ autofix: options?.autofix ?? true,
180
+ }),
181
+ });
182
+ if (!response.ok) {
183
+ throw new Error(`Generator service error: ${response.status}`);
184
+ }
185
+ const data = (await response.json());
186
+ if (!data.success) {
187
+ throw new Error(data.error || 'Failed to generate from questionnaire');
188
+ }
189
+ return {
190
+ success: true,
191
+ files: data.data.generated_files,
192
+ configuration: data.data.configuration,
193
+ stack: {
194
+ provider: data.data.configuration?.selected_provider || 'aws',
195
+ components: data.data.configuration?.selected_components || [],
196
+ },
197
+ bestPracticesReport: data.data.best_practices_report,
198
+ };
199
+ }
200
+ /**
201
+ * List available templates
202
+ */
203
+ async listTemplates(type) {
204
+ const url = type
205
+ ? `${this.baseUrl}/api/templates/type/${type}`
206
+ : `${this.baseUrl}/api/templates`;
207
+ const response = await fetch(url, { method: 'GET' });
208
+ if (!response.ok) {
209
+ throw new Error(`Generator service error: ${response.status}`);
210
+ }
211
+ const data = (await response.json());
212
+ if (!data.success) {
213
+ throw new Error(data.error || 'Failed to list templates');
214
+ }
215
+ return data.data;
216
+ }
217
+ }
218
+ // Singleton instance
219
+ export const generatorClient = new GeneratorClient();