@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,515 @@
1
+ /**
2
+ * Upgrade Command
3
+ *
4
+ * Checks for the latest Nimbus version and offers to upgrade.
5
+ * Supports npm registry, GitHub Releases binary download, and Homebrew.
6
+ *
7
+ * Detects the installation method and executes the appropriate upgrade
8
+ * command automatically (with user confirmation unless --force is passed).
9
+ */
10
+ import { VERSION } from '../version';
11
+ /** GitHub repository used for release downloads. */
12
+ const GITHUB_REPO = 'the-ai-project-co/nimbus';
13
+ /** npm package name (may not be published yet). */
14
+ const NPM_PACKAGE = '@build-astron-co/nimbus';
15
+ /** Homebrew tap name for the formula. */
16
+ const HOMEBREW_TAP = 'the-ai-project-co/tap/nimbus';
17
+ // ---------------------------------------------------------------------------
18
+ // ANSI helpers (avoid importing the full wizard/ui for this standalone command)
19
+ // ---------------------------------------------------------------------------
20
+ const c = {
21
+ reset: '\x1b[0m',
22
+ bold: '\x1b[1m',
23
+ dim: '\x1b[2m',
24
+ green: '\x1b[32m',
25
+ yellow: '\x1b[33m',
26
+ red: '\x1b[31m',
27
+ cyan: '\x1b[36m',
28
+ };
29
+ function bold(s) {
30
+ return `${c.bold}${s}${c.reset}`;
31
+ }
32
+ function green(s) {
33
+ return `${c.green}${s}${c.reset}`;
34
+ }
35
+ function yellow(s) {
36
+ return `${c.yellow}${s}${c.reset}`;
37
+ }
38
+ function red(s) {
39
+ return `${c.red}${s}${c.reset}`;
40
+ }
41
+ function dim(s) {
42
+ return `${c.dim}${s}${c.reset}`;
43
+ }
44
+ function cyan(s) {
45
+ return `${c.cyan}${s}${c.reset}`;
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Spinner
49
+ // ---------------------------------------------------------------------------
50
+ const SPINNER_FRAMES = [
51
+ '\u28CB',
52
+ '\u2819',
53
+ '\u2839',
54
+ '\u2838',
55
+ '\u283C',
56
+ '\u2834',
57
+ '\u2826',
58
+ '\u2827',
59
+ '\u2807',
60
+ '\u280F',
61
+ ];
62
+ function startSpinner(message) {
63
+ let frame = 0;
64
+ let currentMsg = message;
65
+ const interval = setInterval(() => {
66
+ const f = cyan(SPINNER_FRAMES[frame % SPINNER_FRAMES.length]);
67
+ process.stderr.write(`\r\x1b[K ${f} ${currentMsg}`);
68
+ frame++;
69
+ }, 80);
70
+ return {
71
+ update(msg) {
72
+ currentMsg = msg;
73
+ },
74
+ success(msg) {
75
+ clearInterval(interval);
76
+ process.stderr.write(`\r\x1b[K ${green('\u2714')} ${msg}\n`);
77
+ },
78
+ fail(msg) {
79
+ clearInterval(interval);
80
+ process.stderr.write(`\r\x1b[K ${red('\u2716')} ${msg}\n`);
81
+ },
82
+ };
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Confirmation prompt
86
+ // ---------------------------------------------------------------------------
87
+ async function confirmPrompt(message, defaultYes = true) {
88
+ const { createInterface } = await import('node:readline');
89
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
90
+ const hint = defaultYes ? '[Y/n]' : '[y/N]';
91
+ return new Promise(resolve => {
92
+ rl.question(` ${message} ${hint} `, answer => {
93
+ rl.close();
94
+ const trimmed = answer.trim().toLowerCase();
95
+ if (!trimmed) {
96
+ resolve(defaultYes);
97
+ }
98
+ else {
99
+ resolve(trimmed === 'y' || trimmed === 'yes');
100
+ }
101
+ });
102
+ });
103
+ }
104
+ // ---------------------------------------------------------------------------
105
+ // Version fetching
106
+ // ---------------------------------------------------------------------------
107
+ /**
108
+ * Try fetching the latest version from the npm registry.
109
+ * Returns the version string on success, or `null` when the package is not
110
+ * published or the registry is unreachable.
111
+ */
112
+ async function fetchNpmVersion() {
113
+ try {
114
+ const response = await fetch(`https://registry.npmjs.org/${NPM_PACKAGE}/latest`, {
115
+ signal: AbortSignal.timeout(5000),
116
+ });
117
+ if (!response.ok) {
118
+ return null;
119
+ }
120
+ const data = (await response.json());
121
+ return data.version ?? null;
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ }
127
+ /**
128
+ * Try fetching the latest release tag from GitHub Releases.
129
+ * Returns the tag name (e.g. `'v0.3.0'`) on success, or `null` when the
130
+ * API is unreachable or there are no releases.
131
+ */
132
+ async function fetchGitHubReleaseVersion() {
133
+ try {
134
+ const response = await fetch(`https://api.github.com/repos/${GITHUB_REPO}/releases/latest`, {
135
+ headers: { Accept: 'application/vnd.github+json' },
136
+ signal: AbortSignal.timeout(5000),
137
+ });
138
+ if (!response.ok) {
139
+ return null;
140
+ }
141
+ const data = (await response.json());
142
+ // Strip leading 'v' from tag name (e.g. 'v0.3.0' -> '0.3.0')
143
+ const tag = data.tag_name ?? null;
144
+ return tag ? tag.replace(/^v/, '') : null;
145
+ }
146
+ catch {
147
+ return null;
148
+ }
149
+ }
150
+ // ---------------------------------------------------------------------------
151
+ // Changelog fetching
152
+ // ---------------------------------------------------------------------------
153
+ /**
154
+ * Fetch the raw CHANGELOG.md from GitHub. Returns the last ~20 lines on success,
155
+ * or null if unavailable.
156
+ */
157
+ async function fetchChangelog() {
158
+ try {
159
+ const urls = [
160
+ `https://raw.githubusercontent.com/${GITHUB_REPO}/main/CHANGELOG.md`,
161
+ `https://raw.githubusercontent.com/${GITHUB_REPO}/main/CHANGELOG`,
162
+ ];
163
+ for (const url of urls) {
164
+ const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
165
+ if (response.ok) {
166
+ const text = await response.text();
167
+ const lines = text.split('\n');
168
+ // Return last 20 lines or the full content if shorter
169
+ return lines.slice(-20).join('\n');
170
+ }
171
+ }
172
+ return null;
173
+ }
174
+ catch {
175
+ return null;
176
+ }
177
+ }
178
+ /**
179
+ * Detect how nimbus was installed by probing Homebrew, npm, bun, and the
180
+ * binary path. Detection commands are given a short timeout so they never
181
+ * block the CLI for too long.
182
+ */
183
+ async function detectInstallMethod() {
184
+ const { execSync } = await import('node:child_process');
185
+ const execOpts = {
186
+ encoding: 'utf-8',
187
+ stdio: ['pipe', 'pipe', 'pipe'],
188
+ timeout: 10_000,
189
+ };
190
+ // 1. Homebrew
191
+ try {
192
+ const brewList = execSync('brew list --formula 2>/dev/null', execOpts);
193
+ if (brewList.includes('nimbus')) {
194
+ return { method: 'homebrew', detail: `Homebrew formula (${HOMEBREW_TAP})` };
195
+ }
196
+ }
197
+ catch {
198
+ /* not homebrew */
199
+ }
200
+ // 2. npm global
201
+ try {
202
+ const npmList = execSync(`npm list -g ${NPM_PACKAGE} 2>/dev/null`, execOpts);
203
+ if (npmList.includes(NPM_PACKAGE)) {
204
+ return { method: 'npm', detail: `npm global package (${NPM_PACKAGE})` };
205
+ }
206
+ }
207
+ catch {
208
+ /* not npm */
209
+ }
210
+ // 3. bun global
211
+ try {
212
+ const bunList = execSync('bun pm ls -g 2>/dev/null', execOpts);
213
+ if (bunList.includes(NPM_PACKAGE)) {
214
+ return { method: 'bun', detail: `bun global package (${NPM_PACKAGE})` };
215
+ }
216
+ }
217
+ catch {
218
+ /* not bun */
219
+ }
220
+ // 4. Compiled binary (not running through bun/node)
221
+ const argv0 = process.argv[0] ?? '';
222
+ const isBinary = !argv0.includes('bun') && !argv0.includes('node');
223
+ if (isBinary) {
224
+ return { method: 'binary', detail: `standalone binary (${argv0 || '/usr/local/bin/nimbus'})` };
225
+ }
226
+ return { method: 'unknown', detail: 'could not determine installation method' };
227
+ }
228
+ // ---------------------------------------------------------------------------
229
+ // Upgrade execution helpers
230
+ // ---------------------------------------------------------------------------
231
+ /**
232
+ * Run a shell command, streaming output to the terminal.
233
+ * Throws on non-zero exit code.
234
+ */
235
+ async function runShellCommand(cmd, timeoutMs = 120_000) {
236
+ const { execSync } = await import('node:child_process');
237
+ execSync(cmd, { stdio: 'inherit', timeout: timeoutMs });
238
+ }
239
+ /**
240
+ * Verify the upgrade by checking the installed version.
241
+ * Returns the new version string, or null if verification failed.
242
+ */
243
+ async function verifyUpgrade() {
244
+ const { execSync } = await import('node:child_process');
245
+ try {
246
+ const output = execSync('nimbus --version 2>/dev/null', {
247
+ encoding: 'utf-8',
248
+ stdio: ['pipe', 'pipe', 'pipe'],
249
+ timeout: 10_000,
250
+ });
251
+ // Output looks like "nimbus 0.3.0" or just "0.3.0"
252
+ const match = output.trim().match(/(\d+\.\d+\.\d+)/);
253
+ return match ? match[1] : null;
254
+ }
255
+ catch {
256
+ return null;
257
+ }
258
+ }
259
+ /**
260
+ * Execute the upgrade via Homebrew.
261
+ */
262
+ async function upgradeViaHomebrew(spinner) {
263
+ spinner.update('Updating Homebrew tap...');
264
+ try {
265
+ await runShellCommand(`brew upgrade ${HOMEBREW_TAP} 2>&1`);
266
+ }
267
+ catch {
268
+ // If the tap formula isn't found, try the short name
269
+ spinner.update('Trying brew upgrade nimbus...');
270
+ await runShellCommand('brew upgrade nimbus 2>&1');
271
+ }
272
+ }
273
+ /**
274
+ * Execute the upgrade via npm.
275
+ */
276
+ async function upgradeViaNpm(spinner) {
277
+ spinner.update(`Installing ${NPM_PACKAGE}@latest via npm...`);
278
+ await runShellCommand(`npm install -g ${NPM_PACKAGE}@latest 2>&1`);
279
+ }
280
+ /**
281
+ * Execute the upgrade via bun.
282
+ */
283
+ async function upgradeViaBun(spinner) {
284
+ spinner.update(`Installing ${NPM_PACKAGE}@latest via bun...`);
285
+ await runShellCommand(`bun install -g ${NPM_PACKAGE}@latest 2>&1`);
286
+ }
287
+ /**
288
+ * Execute the upgrade by downloading a compiled binary from GitHub Releases.
289
+ */
290
+ async function upgradeViaBinaryDownload(latestVersion, spinner) {
291
+ const platform = process.platform === 'darwin' ? 'darwin' : process.platform === 'linux' ? 'linux' : null;
292
+ const arch = process.arch === 'arm64' ? 'arm64' : process.arch === 'x64' ? 'x64' : null;
293
+ if (!platform || !arch) {
294
+ throw new Error(`Unsupported platform/architecture: ${process.platform}/${process.arch}. ` +
295
+ `Please download the binary manually from https://github.com/${GITHUB_REPO}/releases/latest`);
296
+ }
297
+ const assetName = `nimbus-${platform}-${arch}`;
298
+ const downloadUrl = `https://github.com/${GITHUB_REPO}/releases/download/v${latestVersion}/${assetName}`;
299
+ const binaryPath = process.argv[0] || '/usr/local/bin/nimbus';
300
+ const tmpPath = `${binaryPath}.upgrade-tmp`;
301
+ spinner.update(`Downloading ${assetName} v${latestVersion}...`);
302
+ // Download to a temp file, make executable, then atomically replace
303
+ const cmd = [
304
+ `curl -fsSL "${downloadUrl}" -o "${tmpPath}"`,
305
+ `chmod +x "${tmpPath}"`,
306
+ `mv "${tmpPath}" "${binaryPath}"`,
307
+ ].join(' && ');
308
+ try {
309
+ await runShellCommand(cmd, 120_000);
310
+ }
311
+ catch (err) {
312
+ // Clean up temp file on failure
313
+ try {
314
+ const fs = await import('node:fs');
315
+ if (fs.existsSync(tmpPath)) {
316
+ fs.unlinkSync(tmpPath);
317
+ }
318
+ }
319
+ catch {
320
+ /* best effort */
321
+ }
322
+ throw err;
323
+ }
324
+ }
325
+ // ---------------------------------------------------------------------------
326
+ // Main upgrade command
327
+ // ---------------------------------------------------------------------------
328
+ /**
329
+ * Check for and install the latest version of Nimbus.
330
+ */
331
+ export async function upgradeCommand(options = {}) {
332
+ console.log(`Current version: ${bold(VERSION)}`);
333
+ console.log('Checking for updates...\n');
334
+ // Try npm registry first, then fall back to GitHub Releases
335
+ let latestVersion = await fetchNpmVersion();
336
+ let source = latestVersion ? 'npm' : 'none';
337
+ if (!latestVersion) {
338
+ latestVersion = await fetchGitHubReleaseVersion();
339
+ if (latestVersion) {
340
+ source = 'github';
341
+ }
342
+ }
343
+ if (!latestVersion) {
344
+ console.log('No updates available (package not yet published to npm, and no GitHub releases found).');
345
+ console.log(`You are on version ${VERSION}.`);
346
+ return;
347
+ }
348
+ if (latestVersion === VERSION) {
349
+ console.log(green(`You're already on the latest version (${VERSION}).`));
350
+ return;
351
+ }
352
+ // Simple semver comparison to check if remote is actually newer
353
+ const currentParts = VERSION.split('.').map(Number);
354
+ const remoteParts = latestVersion.split('.').map(Number);
355
+ let isNewer = false;
356
+ for (let i = 0; i < 3; i++) {
357
+ if ((remoteParts[i] ?? 0) > (currentParts[i] ?? 0)) {
358
+ isNewer = true;
359
+ break;
360
+ }
361
+ if ((remoteParts[i] ?? 0) < (currentParts[i] ?? 0)) {
362
+ break;
363
+ }
364
+ }
365
+ if (!isNewer) {
366
+ console.log(green(`You're already on the latest version (${VERSION}).`));
367
+ return;
368
+ }
369
+ console.log(`${yellow('New version available:')} ${dim(VERSION)} ${dim('->')} ${bold(green(latestVersion))}`);
370
+ if (source === 'github') {
371
+ console.log(dim(` Source: GitHub Releases (https://github.com/${GITHUB_REPO}/releases)`));
372
+ }
373
+ console.log('');
374
+ // --dry-run: show what would be upgraded without upgrading
375
+ if (options.dryRun) {
376
+ console.log(`${yellow('Dry run:')} Current: ${bold(VERSION)} → Latest: ${bold(green(latestVersion))}`);
377
+ console.log(dim(` Source: ${source === 'github' ? 'GitHub Releases' : 'npm registry'}`));
378
+ console.log('');
379
+ console.log(dim('No changes were made. Remove --dry-run to perform the upgrade.'));
380
+ return;
381
+ }
382
+ // --changelog: fetch and display the changelog
383
+ if (options.changelog) {
384
+ console.log(bold(`Changelog for nimbus ${latestVersion}:`));
385
+ console.log('');
386
+ const cl = await fetchChangelog();
387
+ if (cl) {
388
+ console.log(cl);
389
+ }
390
+ else {
391
+ console.log(dim(`Changelog not available. View releases at: https://github.com/${GITHUB_REPO}/releases`));
392
+ }
393
+ return;
394
+ }
395
+ if (options.check) {
396
+ return;
397
+ }
398
+ // Detect how nimbus was installed
399
+ const detection = await detectInstallMethod();
400
+ console.log(`Detected installation: ${bold(detection.detail)}`);
401
+ console.log('');
402
+ // For unknown install methods, just print manual instructions
403
+ if (detection.method === 'unknown') {
404
+ printManualInstructions(source);
405
+ return;
406
+ }
407
+ // Ask for confirmation unless --force
408
+ if (!options.force) {
409
+ const proceed = await confirmPrompt(`Upgrade nimbus ${VERSION} -> ${latestVersion}?`, true);
410
+ if (!proceed) {
411
+ console.log('\nUpgrade cancelled.');
412
+ return;
413
+ }
414
+ console.log('');
415
+ }
416
+ // Execute the upgrade
417
+ const spinner = startSpinner('Upgrading nimbus...');
418
+ try {
419
+ switch (detection.method) {
420
+ case 'homebrew':
421
+ await upgradeViaHomebrew(spinner);
422
+ break;
423
+ case 'npm':
424
+ await upgradeViaNpm(spinner);
425
+ break;
426
+ case 'bun':
427
+ await upgradeViaBun(spinner);
428
+ break;
429
+ case 'binary':
430
+ if (source !== 'github') {
431
+ spinner.fail('Binary upgrade requires GitHub Releases, but no release was found.');
432
+ printManualInstructions(source);
433
+ return;
434
+ }
435
+ await upgradeViaBinaryDownload(latestVersion, spinner);
436
+ break;
437
+ }
438
+ spinner.success('Upgrade command completed');
439
+ }
440
+ catch (error) {
441
+ const msg = error.message || String(error);
442
+ spinner.fail(`Upgrade failed: ${msg}`);
443
+ console.log('');
444
+ // Provide recovery instructions
445
+ console.log(yellow('You can try upgrading manually:'));
446
+ printUpgradeInstructionForMethod(detection.method, latestVersion, source);
447
+ return;
448
+ }
449
+ // Verify the upgrade succeeded
450
+ console.log('');
451
+ const verifySpinner = startSpinner('Verifying upgrade...');
452
+ const newVersion = await verifyUpgrade();
453
+ if (newVersion && newVersion === latestVersion) {
454
+ verifySpinner.success(`Successfully upgraded to ${bold(green(newVersion))}`);
455
+ }
456
+ else if (newVersion && newVersion !== VERSION) {
457
+ verifySpinner.success(`Upgraded to ${bold(green(newVersion))}`);
458
+ }
459
+ else if (detection.method === 'binary') {
460
+ // For binary upgrades, the current process is the old binary so
461
+ // `nimbus --version` will report the new version only on next launch.
462
+ verifySpinner.success(`Binary replaced. Restart nimbus to use ${bold(green(latestVersion))}.`);
463
+ }
464
+ else {
465
+ verifySpinner.fail('Could not verify the new version. Please run `nimbus --version` to check.');
466
+ }
467
+ }
468
+ // ---------------------------------------------------------------------------
469
+ // Helper: print manual instructions (fallback for unknown install method)
470
+ // ---------------------------------------------------------------------------
471
+ function printManualInstructions(source) {
472
+ console.log('Could not detect installation method. Upgrade manually:');
473
+ console.log('');
474
+ console.log(` ${dim('# npm')}`);
475
+ console.log(` npm install -g ${NPM_PACKAGE}@latest`);
476
+ console.log('');
477
+ console.log(` ${dim('# bun')}`);
478
+ console.log(` bun install -g ${NPM_PACKAGE}@latest`);
479
+ console.log('');
480
+ console.log(` ${dim('# Homebrew')}`);
481
+ console.log(` brew upgrade ${HOMEBREW_TAP}`);
482
+ if (source === 'github') {
483
+ console.log('');
484
+ console.log(` ${dim('# Binary download')}`);
485
+ console.log(` https://github.com/${GITHUB_REPO}/releases/latest`);
486
+ }
487
+ }
488
+ /**
489
+ * Print the specific upgrade instruction for a detected method (used after
490
+ * an automatic upgrade fails).
491
+ */
492
+ function printUpgradeInstructionForMethod(method, latestVersion, source) {
493
+ switch (method) {
494
+ case 'homebrew':
495
+ console.log(` brew upgrade ${HOMEBREW_TAP}`);
496
+ break;
497
+ case 'npm':
498
+ console.log(` npm install -g ${NPM_PACKAGE}@latest`);
499
+ break;
500
+ case 'bun':
501
+ console.log(` bun install -g ${NPM_PACKAGE}@latest`);
502
+ break;
503
+ case 'binary': {
504
+ const platform = process.platform === 'darwin' ? 'darwin' : 'linux';
505
+ const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
506
+ const assetName = `nimbus-${platform}-${arch}`;
507
+ const url = `https://github.com/${GITHUB_REPO}/releases/download/v${latestVersion}/${assetName}`;
508
+ console.log(` curl -fsSL "${url}" -o /usr/local/bin/nimbus && chmod +x /usr/local/bin/nimbus`);
509
+ break;
510
+ }
511
+ default:
512
+ printManualInstructions(source);
513
+ break;
514
+ }
515
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Usage Command
3
+ * Usage dashboard CLI command
4
+ */
5
+ import { ui } from '../../wizard/ui';
6
+ import { billingClient } from '../../clients/enterprise-client';
7
+ /**
8
+ * Get current team ID from config or environment
9
+ */
10
+ function getCurrentTeamId() {
11
+ return process.env.NIMBUS_TEAM_ID || null;
12
+ }
13
+ /**
14
+ * Parse usage options
15
+ */
16
+ export function parseUsageOptions(args) {
17
+ const options = {};
18
+ for (let i = 0; i < args.length; i++) {
19
+ const arg = args[i];
20
+ if (arg === '--period' && args[i + 1]) {
21
+ options.period = args[++i];
22
+ }
23
+ else if (arg === '--team' && args[i + 1]) {
24
+ options.teamId = args[++i];
25
+ }
26
+ else if (arg === '--json') {
27
+ options.json = true;
28
+ }
29
+ else if (arg === '--non-interactive') {
30
+ options.nonInteractive = true;
31
+ }
32
+ }
33
+ return options;
34
+ }
35
+ /**
36
+ * Format number with commas
37
+ */
38
+ function formatNumber(n) {
39
+ return n.toLocaleString();
40
+ }
41
+ /**
42
+ * Format cost in USD
43
+ */
44
+ function formatCost(n) {
45
+ return `$${n.toFixed(2)}`;
46
+ }
47
+ /**
48
+ * Usage command
49
+ */
50
+ export async function usageCommand(options) {
51
+ try {
52
+ const teamId = options.teamId || getCurrentTeamId();
53
+ if (!teamId) {
54
+ ui.error('No team selected. Run `nimbus team switch <team-id>` first.');
55
+ ui.info('Or use: nimbus usage --team <team-id>');
56
+ return;
57
+ }
58
+ const period = options.period || 'month';
59
+ ui.startSpinner({ message: `Fetching ${period} usage...` });
60
+ const usage = await billingClient.getUsage(teamId, period);
61
+ ui.stopSpinnerSuccess('Usage retrieved');
62
+ if (options.json) {
63
+ console.log(JSON.stringify(usage, null, 2));
64
+ return;
65
+ }
66
+ ui.newLine();
67
+ ui.header('Usage Dashboard', `${new Date(usage.period.start).toLocaleDateString()} - ${new Date(usage.period.end).toLocaleDateString()}`);
68
+ // Summary
69
+ ui.section('Summary');
70
+ ui.print(` Total Operations: ${formatNumber(usage.totals.operations)}`);
71
+ ui.print(` Total Tokens: ${formatNumber(usage.totals.tokensUsed)}`);
72
+ ui.print(` Total Cost: ${formatCost(usage.totals.costUsd)}`);
73
+ // By operation type
74
+ const operationTypes = Object.entries(usage.byOperationType);
75
+ if (operationTypes.length > 0) {
76
+ ui.section('By Operation Type');
77
+ ui.table({
78
+ columns: [
79
+ { key: 'type', header: 'Operation' },
80
+ { key: 'count', header: 'Count' },
81
+ { key: 'tokens', header: 'Tokens' },
82
+ { key: 'cost', header: 'Cost' },
83
+ ],
84
+ data: operationTypes.map(([type, data]) => ({
85
+ type,
86
+ count: formatNumber(data.count),
87
+ tokens: formatNumber(data.tokensUsed),
88
+ cost: formatCost(data.costUsd),
89
+ })),
90
+ });
91
+ }
92
+ // By user (if available)
93
+ if (usage.byUser && Object.keys(usage.byUser).length > 0) {
94
+ const userUsage = Object.entries(usage.byUser);
95
+ ui.section('By User');
96
+ ui.table({
97
+ columns: [
98
+ { key: 'user', header: 'User' },
99
+ { key: 'count', header: 'Operations' },
100
+ { key: 'tokens', header: 'Tokens' },
101
+ { key: 'cost', header: 'Cost' },
102
+ ],
103
+ data: userUsage.map(([user, data]) => ({
104
+ user,
105
+ count: formatNumber(data.count),
106
+ tokens: formatNumber(data.tokensUsed),
107
+ cost: formatCost(data.costUsd),
108
+ })),
109
+ });
110
+ }
111
+ ui.newLine();
112
+ ui.dim(`Period: ${period} | Use --period day|week|month to change`);
113
+ }
114
+ catch (error) {
115
+ ui.stopSpinnerFail('Failed to get usage');
116
+ ui.error(error.message);
117
+ }
118
+ }