@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,432 @@
1
+ /**
2
+ * nimbus serve -- Headless HTTP API Server
3
+ *
4
+ * Exposes the Nimbus agent loop as a REST + SSE API designed for
5
+ * consumption by the Web UI, IDE extensions, and third-party integrations.
6
+ *
7
+ * Endpoints:
8
+ * POST /api/chat -- Send a message, receive SSE streaming response
9
+ * POST /api/run -- Non-interactive single prompt (JSON response)
10
+ * GET /api/sessions -- List all sessions
11
+ * GET /api/session/:id -- Session details + conversation messages
12
+ * POST /api/session/:id -- Continue an existing session (SSE streaming)
13
+ * GET /api/health -- Health check
14
+ * GET /api/openapi.json -- OpenAPI 3.1 specification
15
+ *
16
+ * Usage:
17
+ * nimbus serve # localhost:4200
18
+ * nimbus serve --port 8080 # custom port
19
+ * nimbus serve --host 0.0.0.0 # bind to all interfaces
20
+ * nimbus serve --auth admin:secret # enable HTTP Basic Auth
21
+ *
22
+ * @module cli/serve
23
+ */
24
+ import { Elysia } from 'elysia';
25
+ import { cors } from '@elysiajs/cors';
26
+ import { initApp } from '../app';
27
+ import { runAgentLoop } from '../agent/loop';
28
+ import { defaultToolRegistry } from '../tools/schemas/types';
29
+ import { standardTools } from '../tools/schemas/standard';
30
+ import { devopsTools } from '../tools/schemas/devops';
31
+ import { SessionManager } from '../sessions/manager';
32
+ import { saveConversation, getConversation } from '../state/conversations';
33
+ import { shareSession, getSharedSession, listShares } from '../sharing/sync';
34
+ import { ContextManager } from '../agent/context-manager';
35
+ import { getOpenAPISpec } from './openapi-spec';
36
+ import { createAuthMiddleware } from './serve-auth';
37
+ // ---------------------------------------------------------------------------
38
+ // Helpers
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * Ensure the default tool registry is populated.
42
+ * Idempotent -- skips tools that are already registered.
43
+ */
44
+ function ensureToolsRegistered() {
45
+ if (defaultToolRegistry.size > 0) {
46
+ return;
47
+ }
48
+ for (const tool of [...standardTools, ...devopsTools]) {
49
+ try {
50
+ defaultToolRegistry.register(tool);
51
+ }
52
+ catch {
53
+ // Already registered -- skip.
54
+ }
55
+ }
56
+ }
57
+ /**
58
+ * Validate and narrow a mode string to the AgentMode union.
59
+ */
60
+ function parseMode(mode) {
61
+ if (mode === 'plan' || mode === 'build' || mode === 'deploy') {
62
+ return mode;
63
+ }
64
+ return 'build';
65
+ }
66
+ /**
67
+ * Create an SSE-formatted ReadableStream that runs the agent loop and
68
+ * emits events for text, tool calls, completion, and errors.
69
+ *
70
+ * SSE event types:
71
+ * session -- { id, mode }
72
+ * text -- { content }
73
+ * tool_start -- { id, name, input? }
74
+ * tool_end -- { id, name, output?, isError }
75
+ * done -- { turns, usage, cost }
76
+ * error -- { message }
77
+ */
78
+ function createAgentSSEStream(userMessage, history, sessionId, mode, model, router, contextManager, sessionManager) {
79
+ return new ReadableStream({
80
+ async start(controller) {
81
+ const encoder = new TextEncoder();
82
+ const send = (event, data) => {
83
+ const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
84
+ controller.enqueue(encoder.encode(payload));
85
+ };
86
+ try {
87
+ send('session', { id: sessionId, mode });
88
+ const result = await runAgentLoop(userMessage, history, {
89
+ router,
90
+ toolRegistry: defaultToolRegistry,
91
+ mode,
92
+ model,
93
+ sessionId,
94
+ onText: (text) => {
95
+ send('text', { content: text });
96
+ },
97
+ onToolCallStart: (toolCall) => {
98
+ send('tool_start', {
99
+ id: toolCall.id,
100
+ name: toolCall.name,
101
+ input: toolCall.input,
102
+ });
103
+ },
104
+ onToolCallEnd: (toolCall, toolResult) => {
105
+ send('tool_end', {
106
+ id: toolCall.id,
107
+ name: toolCall.name,
108
+ output: typeof toolResult.output === 'string'
109
+ ? toolResult.output.slice(0, 5000)
110
+ : toolResult.output,
111
+ isError: toolResult.isError,
112
+ });
113
+ },
114
+ });
115
+ // Persist conversation
116
+ saveConversation(sessionId, userMessage.slice(0, 100), result.messages, model);
117
+ // Update session stats
118
+ sessionManager.updateSession(sessionId, {
119
+ tokenCount: result.usage.totalTokens,
120
+ costUSD: result.totalCost,
121
+ });
122
+ send('done', {
123
+ turns: result.turns,
124
+ usage: result.usage,
125
+ cost: result.totalCost,
126
+ });
127
+ }
128
+ catch (error) {
129
+ const msg = error instanceof Error ? error.message : String(error);
130
+ send('error', { message: msg });
131
+ }
132
+ finally {
133
+ controller.close();
134
+ }
135
+ },
136
+ });
137
+ }
138
+ /**
139
+ * Wrap a ReadableStream as an SSE Response with proper headers.
140
+ */
141
+ function sseResponse(stream) {
142
+ return new Response(stream, {
143
+ headers: {
144
+ 'Content-Type': 'text/event-stream',
145
+ 'Cache-Control': 'no-cache',
146
+ Connection: 'keep-alive',
147
+ 'Access-Control-Allow-Origin': '*',
148
+ },
149
+ });
150
+ }
151
+ // ---------------------------------------------------------------------------
152
+ // Main Command
153
+ // ---------------------------------------------------------------------------
154
+ /**
155
+ * Start the Nimbus headless API server.
156
+ *
157
+ * Initializes the app context (DB + LLM router), registers tools, sets up
158
+ * all API routes via Elysia, and starts listening.
159
+ */
160
+ export async function serveCommand(options) {
161
+ const port = options.port ?? 4200;
162
+ const host = options.host ?? 'localhost';
163
+ // M1: stop a running background server
164
+ if (options.stop) {
165
+ const { join } = await import('node:path');
166
+ const { homedir } = await import('node:os');
167
+ const { readFileSync, unlinkSync, existsSync } = await import('node:fs');
168
+ const pidFile = join(homedir(), '.nimbus', 'serve.pid');
169
+ if (!existsSync(pidFile)) {
170
+ console.log('No background nimbus serve process found.');
171
+ return;
172
+ }
173
+ const pid = parseInt(readFileSync(pidFile, 'utf-8').trim(), 10);
174
+ try {
175
+ process.kill(pid, 'SIGTERM');
176
+ unlinkSync(pidFile);
177
+ console.log(`Stopped nimbus serve (PID: ${pid})`);
178
+ }
179
+ catch (e) {
180
+ console.error(`Failed to stop process ${pid}: ${e.message}`);
181
+ unlinkSync(pidFile);
182
+ }
183
+ return;
184
+ }
185
+ // M1: daemonize — spawn detached child and exit
186
+ if (options.background) {
187
+ const { spawn } = await import('node:child_process');
188
+ const { join } = await import('node:path');
189
+ const { homedir } = await import('node:os');
190
+ const { writeFileSync, mkdirSync } = await import('node:fs');
191
+ const nimbusDir = join(homedir(), '.nimbus');
192
+ mkdirSync(nimbusDir, { recursive: true });
193
+ const childArgs = [process.argv[1], 'serve', '--port', String(port)];
194
+ if (options.host)
195
+ childArgs.push('--host', options.host);
196
+ if (options.auth)
197
+ childArgs.push('--auth', options.auth);
198
+ const child = spawn(process.execPath, childArgs, {
199
+ detached: true,
200
+ stdio: 'ignore',
201
+ env: process.env,
202
+ });
203
+ child.unref();
204
+ writeFileSync(join(nimbusDir, 'serve.pid'), String(child.pid), 'utf-8');
205
+ console.log(`nimbus serve started in background (PID: ${child.pid})`);
206
+ console.log(`Stop with: nimbus serve stop`);
207
+ return;
208
+ }
209
+ // G19: Security guard — non-localhost binding requires explicit auth
210
+ const isLocalhost = !host || host === 'localhost' || host === '127.0.0.1' || host === '::1';
211
+ if (!isLocalhost && !options.auth) {
212
+ throw new Error(`Cannot bind nimbus serve to ${host} without authentication.\n` +
213
+ 'Use --auth user:pass to enable HTTP Basic Auth, or bind to localhost only.');
214
+ }
215
+ // G19: Auto-generate token for localhost when no auth provided
216
+ let autoToken;
217
+ if (isLocalhost && !options.auth) {
218
+ const { randomBytes } = await import('node:crypto');
219
+ autoToken = randomBytes(16).toString('hex');
220
+ process.stderr.write(`\nNimbus API token: ${autoToken}\n`);
221
+ process.stderr.write('Pass as: Authorization: Bearer <token>\n\n');
222
+ }
223
+ // ------------------------------------------------------------------
224
+ // Initialize core systems
225
+ // ------------------------------------------------------------------
226
+ const { router } = await initApp();
227
+ const sessionManager = SessionManager.getInstance();
228
+ const contextManager = new ContextManager();
229
+ ensureToolsRegistered();
230
+ // ------------------------------------------------------------------
231
+ // Build Elysia app
232
+ // ------------------------------------------------------------------
233
+ const app = new Elysia().use(cors({
234
+ origin: true,
235
+ methods: ['GET', 'POST', 'OPTIONS'],
236
+ allowedHeaders: ['Content-Type', 'Authorization'],
237
+ }));
238
+ // HTTP Basic Auth (explicit or auto-generated token)
239
+ if (options.auth) {
240
+ const colonIdx = options.auth.indexOf(':');
241
+ if (colonIdx > 0) {
242
+ const user = options.auth.slice(0, colonIdx);
243
+ const pass = options.auth.slice(colonIdx + 1);
244
+ app.onBeforeHandle(createAuthMiddleware({ username: user, password: pass }));
245
+ }
246
+ }
247
+ else if (autoToken) {
248
+ // G19: Bearer token auth for localhost when no explicit auth provided
249
+ const capturedToken = autoToken;
250
+ app.onBeforeHandle((ctx) => {
251
+ const authHeader = ctx.request.headers.get('Authorization') ?? '';
252
+ if (authHeader !== `Bearer ${capturedToken}`) {
253
+ ctx.set.status = 401;
254
+ return { error: 'Unauthorized. Pass Authorization: Bearer <token>' };
255
+ }
256
+ });
257
+ }
258
+ // ------------------------------------------------------------------
259
+ // GET /api/health
260
+ // ------------------------------------------------------------------
261
+ app.get('/api/health', () => ({
262
+ status: 'ok',
263
+ version: '0.2.0',
264
+ uptime: process.uptime(),
265
+ db: true,
266
+ llm: true,
267
+ }));
268
+ // ------------------------------------------------------------------
269
+ // GET /api/openapi.json
270
+ // ------------------------------------------------------------------
271
+ app.get('/api/openapi.json', () => getOpenAPISpec());
272
+ // ------------------------------------------------------------------
273
+ // GET /api/sessions
274
+ // ------------------------------------------------------------------
275
+ app.get('/api/sessions', () => ({
276
+ sessions: sessionManager.list(),
277
+ }));
278
+ // ------------------------------------------------------------------
279
+ // GET /api/session/:id
280
+ // ------------------------------------------------------------------
281
+ app.get('/api/session/:id', ({ params }) => {
282
+ const session = sessionManager.get(params.id);
283
+ if (!session) {
284
+ return new Response(JSON.stringify({ error: 'Session not found' }), {
285
+ status: 404,
286
+ headers: { 'Content-Type': 'application/json' },
287
+ });
288
+ }
289
+ const conversation = getConversation(params.id);
290
+ return {
291
+ session,
292
+ messages: conversation?.messages ?? [],
293
+ };
294
+ });
295
+ // ------------------------------------------------------------------
296
+ // POST /api/chat -- SSE streaming chat
297
+ // ------------------------------------------------------------------
298
+ app.post('/api/chat', async (ctx) => {
299
+ const body = ctx.body;
300
+ const mode = parseMode(body.mode);
301
+ // Get or create session
302
+ let sessionId = body.sessionId;
303
+ let session = sessionId ? sessionManager.get(sessionId) : null;
304
+ if (!session) {
305
+ session = sessionManager.create({
306
+ name: `API Session ${new Date().toISOString().slice(0, 16)}`,
307
+ mode,
308
+ model: body.model,
309
+ });
310
+ sessionId = session.id;
311
+ }
312
+ // Load existing conversation history
313
+ const existing = getConversation(sessionId);
314
+ const history = existing?.messages ?? [];
315
+ const stream = createAgentSSEStream(body.message, history, sessionId, mode, body.model, router, contextManager, sessionManager);
316
+ return sseResponse(stream);
317
+ });
318
+ // ------------------------------------------------------------------
319
+ // POST /api/run -- Non-interactive single prompt
320
+ // ------------------------------------------------------------------
321
+ app.post('/api/run', async (ctx) => {
322
+ const body = ctx.body;
323
+ const mode = parseMode(body.mode);
324
+ const session = sessionManager.create({
325
+ name: `Run: ${body.prompt.slice(0, 50)}`,
326
+ mode,
327
+ model: body.model,
328
+ });
329
+ try {
330
+ const result = await runAgentLoop(body.prompt, [], {
331
+ router,
332
+ toolRegistry: defaultToolRegistry,
333
+ mode,
334
+ model: body.model,
335
+ });
336
+ // Persist conversation and mark session complete
337
+ saveConversation(session.id, body.prompt.slice(0, 100), result.messages, body.model);
338
+ sessionManager.complete(session.id);
339
+ // Extract final assistant message
340
+ const lastAssistant = [...result.messages].reverse().find(m => m.role === 'assistant');
341
+ return {
342
+ sessionId: session.id,
343
+ response: lastAssistant?.content ?? '',
344
+ turns: result.turns,
345
+ usage: result.usage,
346
+ cost: result.totalCost,
347
+ };
348
+ }
349
+ catch (error) {
350
+ const msg = error instanceof Error ? error.message : String(error);
351
+ sessionManager.complete(session.id);
352
+ return new Response(JSON.stringify({ error: msg }), {
353
+ status: 500,
354
+ headers: { 'Content-Type': 'application/json' },
355
+ });
356
+ }
357
+ });
358
+ // ------------------------------------------------------------------
359
+ // POST /api/session/:id -- Continue existing session (SSE)
360
+ // ------------------------------------------------------------------
361
+ app.post('/api/session/:id', async (ctx) => {
362
+ const params = ctx.params;
363
+ const body = ctx.body;
364
+ const session = sessionManager.get(params.id);
365
+ if (!session) {
366
+ return new Response(JSON.stringify({ error: 'Session not found' }), {
367
+ status: 404,
368
+ headers: { 'Content-Type': 'application/json' },
369
+ });
370
+ }
371
+ const existing = getConversation(params.id);
372
+ const history = existing?.messages ?? [];
373
+ const mode = parseMode(session.mode);
374
+ const stream = createAgentSSEStream(body.message, history, params.id, mode, body.model ?? session.model, router, contextManager, sessionManager);
375
+ return sseResponse(stream);
376
+ });
377
+ // ------------------------------------------------------------------
378
+ // POST /api/share -- Share a session
379
+ // ------------------------------------------------------------------
380
+ app.post('/api/share', ctx => {
381
+ const body = ctx.body;
382
+ const shared = shareSession(body.sessionId, {
383
+ isLive: body.isLive,
384
+ ttlDays: body.ttlDays,
385
+ });
386
+ if (!shared) {
387
+ return new Response(JSON.stringify({ error: 'Session not found' }), {
388
+ status: 404,
389
+ headers: { 'Content-Type': 'application/json' },
390
+ });
391
+ }
392
+ return {
393
+ shareId: shared.id,
394
+ url: `http://${host}:${port}/nimbus/share/${shared.id}`,
395
+ expiresAt: shared.expiresAt,
396
+ isLive: shared.isLive,
397
+ };
398
+ });
399
+ // ------------------------------------------------------------------
400
+ // GET /api/share/:id -- Get shared session
401
+ // ------------------------------------------------------------------
402
+ app.get('/api/share/:id', ({ params }) => {
403
+ const shared = getSharedSession(params.id);
404
+ if (!shared) {
405
+ return new Response(JSON.stringify({ error: 'Shared session not found or expired' }), {
406
+ status: 404,
407
+ headers: { 'Content-Type': 'application/json' },
408
+ });
409
+ }
410
+ return shared;
411
+ });
412
+ // ------------------------------------------------------------------
413
+ // GET /api/shares -- List all shares
414
+ // ------------------------------------------------------------------
415
+ app.get('/api/shares', () => ({
416
+ shares: listShares(),
417
+ }));
418
+ // ------------------------------------------------------------------
419
+ // Start listening
420
+ // ------------------------------------------------------------------
421
+ app.listen({ port, hostname: host });
422
+ console.log(`
423
+ Nimbus API Server
424
+ ─────────────────────────────
425
+ Local: http://${host}:${port}
426
+ Health: http://${host}:${port}/api/health
427
+ OpenAPI: http://${host}:${port}/api/openapi.json
428
+ ${options.auth ? ' Auth: HTTP Basic Auth enabled' : ' Auth: None (use --auth user:pass to enable)'}
429
+
430
+ Press Ctrl+C to stop.
431
+ `);
432
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * nimbus web -- Start the API server and open the Web UI
3
+ *
4
+ * Convenience command that:
5
+ * 1. Starts `nimbus serve` on the configured port
6
+ * 2. Opens the astron-landing Web UI in the default browser
7
+ *
8
+ * Usage:
9
+ * nimbus web # serve on 4200, open http://localhost:6001/nimbus
10
+ * nimbus web --port 8080 # custom serve port
11
+ * nimbus web --ui-url https://app.example.com/nimbus # custom Web UI URL
12
+ */
13
+ import { spawn } from 'node:child_process';
14
+ import { serveCommand } from './serve';
15
+ /**
16
+ * Open a URL in the default browser (cross-platform).
17
+ */
18
+ async function openBrowser(url) {
19
+ const { platform } = process;
20
+ const cmd = platform === 'darwin'
21
+ ? ['open', url]
22
+ : platform === 'win32'
23
+ ? ['cmd', '/c', 'start', url]
24
+ : ['xdg-open', url];
25
+ const proc = spawn(cmd[0], cmd.slice(1), { stdio: 'ignore', detached: true });
26
+ proc.unref();
27
+ }
28
+ /**
29
+ * Run the web command: start serve and open browser.
30
+ */
31
+ export async function webCommand(options) {
32
+ const port = options.port ?? 4200;
33
+ const uiUrl = options.uiUrl ?? 'http://localhost:6001/nimbus';
34
+ console.log(`Starting Nimbus API server on port ${port}...`);
35
+ console.log(`Opening Web UI at ${uiUrl}\n`);
36
+ // Open browser after a short delay to let the server start (skipped with --no-open)
37
+ if (!options.noOpen) {
38
+ setTimeout(() => {
39
+ openBrowser(uiUrl).catch(() => {
40
+ console.log(`Could not open browser. Please visit: ${uiUrl}`);
41
+ });
42
+ }, 1500);
43
+ }
44
+ // Start the server (this blocks)
45
+ await serveCommand({
46
+ port,
47
+ host: options.host,
48
+ auth: options.auth,
49
+ });
50
+ }