@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
package/bin/nimbus CHANGED
@@ -2,28 +2,44 @@
2
2
  # Nimbus CLI launcher — prefers Bun, falls back to Node.js (>=18).
3
3
  set -e
4
4
 
5
+ # Resolve the real script location, following symlinks so this works when npm
6
+ # installs the bin entry as a symlink (e.g. /opt/homebrew/bin/nimbus ->
7
+ # .../node_modules/@build-astron-co/nimbus/bin/nimbus).
5
8
  SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
- ENTRY="$SCRIPT_DIR/../src/nimbus.ts"
9
+ REAL_SCRIPT="$SCRIPT_DIR/nimbus"
10
+ if [ -L "$REAL_SCRIPT" ]; then
11
+ LINK_TARGET="$(readlink "$REAL_SCRIPT")"
12
+ case "$LINK_TARGET" in
13
+ /*) REAL_SCRIPT="$LINK_TARGET" ;;
14
+ *) REAL_SCRIPT="$SCRIPT_DIR/$LINK_TARGET" ;;
15
+ esac
16
+ fi
17
+ PKG_ROOT="$(cd "$(dirname "$REAL_SCRIPT")/.." && pwd)"
18
+ ENTRY="$PKG_ROOT/src/nimbus.ts"
7
19
 
8
20
  # Prefer Bun for best performance (native bun:sqlite, fast startup)
9
21
  if command -v bun >/dev/null 2>&1; then
10
22
  exec bun "$ENTRY" "$@"
11
23
  fi
12
24
 
13
- # Fallback: Node.js with tsx for TypeScript execution
25
+ # Fallback: Node.js with tsx for TypeScript execution.
26
+ # We use `node --loader tsx/esm` rather than `tsx` directly to ensure ESM
27
+ # output mode — required because yoga-layout (Ink dep) uses top-level await
28
+ # which is incompatible with tsx's default CJS output.
14
29
  if command -v node >/dev/null 2>&1; then
15
30
  NODE_VERSION=$(node -e "console.log(process.versions.node.split('.')[0])")
16
31
  if [ "$NODE_VERSION" -ge 18 ] 2>/dev/null; then
17
- # Use tsx (TypeScript eXecute) for Node.js handles TS natively
18
- TSX_BIN="$SCRIPT_DIR/../node_modules/.bin/tsx"
19
- if [ -x "$TSX_BIN" ]; then
20
- exec "$TSX_BIN" "$ENTRY" "$@"
32
+ # Prefer the tsx ESM loader bundled with this package
33
+ TSX_ESM="$PKG_ROOT/node_modules/tsx/dist/esm/index.mjs"
34
+ if [ -f "$TSX_ESM" ]; then
35
+ exec node --loader "$TSX_ESM" "$ENTRY" "$@"
21
36
  fi
22
- # Try global tsx
23
- if command -v tsx >/dev/null 2>&1; then
24
- exec tsx "$ENTRY" "$@"
37
+ # Try global tsx ESM loader (npm global install)
38
+ TSX_GLOBAL_ESM="$(npm root -g 2>/dev/null)/tsx/dist/esm/index.mjs"
39
+ if [ -f "$TSX_GLOBAL_ESM" ]; then
40
+ exec node --loader "$TSX_GLOBAL_ESM" "$ENTRY" "$@"
25
41
  fi
26
- # Last resort: use Node.js --import tsx (Node >= 18.19)
42
+ # Last resort: node --import tsx (Node >= 18.19, tsx must be globally installed)
27
43
  exec node --import tsx "$ENTRY" "$@"
28
44
  fi
29
45
  fi
package/bin/nimbus.cmd ADDED
@@ -0,0 +1,41 @@
1
+ @echo off
2
+ :: Nimbus CLI launcher for Windows (CMD / PowerShell).
3
+ :: Resolves the package root relative to this script's location so it works
4
+ :: when npm installs the bin entry as a junction/shim in node_modules/.bin/.
5
+
6
+ setlocal enabledelayedexpansion
7
+
8
+ :: Locate the package root (one level up from this bin\ directory)
9
+ set "SCRIPT_DIR=%~dp0"
10
+ :: Remove trailing backslash
11
+ if "%SCRIPT_DIR:~-1%"=="\" set "SCRIPT_DIR=%SCRIPT_DIR:~0,-1%"
12
+ set "PKG_ROOT=%SCRIPT_DIR%\.."
13
+ set "ENTRY=%PKG_ROOT%\src\nimbus.ts"
14
+
15
+ :: Primary: Node.js >= 18 with tsx ESM loader (project is Node.js-native)
16
+ where node >nul 2>&1
17
+ if %errorlevel% equ 0 (
18
+ set "TSX_ESM=%PKG_ROOT%\node_modules\tsx\dist\esm\index.mjs"
19
+ if exist "!TSX_ESM!" (
20
+ node --loader "!TSX_ESM!" "%ENTRY%" %*
21
+ exit /b %errorlevel%
22
+ )
23
+ :: Try global tsx loader
24
+ for /f "delims=" %%i in ('npm root -g 2^>nul') do set "NPM_GLOBAL=%%i"
25
+ if defined NPM_GLOBAL (
26
+ set "TSX_GLOBAL=!NPM_GLOBAL!\tsx\dist\esm\index.mjs"
27
+ if exist "!TSX_GLOBAL!" (
28
+ node --loader "!TSX_GLOBAL!" "%ENTRY%" %*
29
+ exit /b %errorlevel%
30
+ )
31
+ )
32
+ :: Last resort: node --import tsx
33
+ node --import tsx "%ENTRY%" %*
34
+ exit /b %errorlevel%
35
+ )
36
+
37
+ echo Error: Nimbus requires Node.js ^>= 18. >&2
38
+ echo. >&2
39
+ echo Install Node.js: >&2
40
+ echo https://nodejs.org/ >&2
41
+ exit /b 1
package/bin/nimbus.mjs ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Nimbus CLI — cross-platform ESM launcher.
4
+ *
5
+ * This is the `bin` entry used by npm on all platforms (including Windows).
6
+ * It locates the package root (following symlinks so npm global installs work),
7
+ * then spawns Node.js with the tsx ESM loader to execute the TypeScript source.
8
+ *
9
+ * Why .mjs instead of a shell script?
10
+ * On Windows, npm's cmd-shim cannot wrap a POSIX sh script. A Node.js ESM
11
+ * bin entry (#!/usr/bin/env node + .mjs) works on all platforms.
12
+ */
13
+
14
+ import { spawnSync, execSync } from 'node:child_process';
15
+ import { existsSync } from 'node:fs';
16
+ import { fileURLToPath } from 'node:url';
17
+ import { dirname, join, resolve } from 'node:path';
18
+
19
+ // L1: Enable ANSI color support on Windows terminals (Windows 10+ supports VT100).
20
+ // FORCE_COLOR=1 is the standard signal for chalk/ink/supports-color to emit ANSI codes.
21
+ // This must run before any child process is spawned so the env var is inherited.
22
+ if (process.platform === 'win32') {
23
+ process.env.FORCE_COLOR ??= '1';
24
+ }
25
+
26
+ // Resolve the true package root, following symlinks (npm global installs symlink on POSIX).
27
+ const __filename = fileURLToPath(import.meta.url);
28
+ const __dirname = dirname(__filename);
29
+ const PKG_ROOT = resolve(__dirname, '..');
30
+ const ENTRY = join(PKG_ROOT, 'src', 'nimbus.ts');
31
+
32
+ const passArgs = process.argv.slice(2);
33
+
34
+ function run(nodeArgs) {
35
+ const result = spawnSync(process.execPath, [...nodeArgs, ENTRY, ...passArgs], {
36
+ stdio: 'inherit',
37
+ env: process.env,
38
+ });
39
+ process.exit(result.status ?? (result.error ? 1 : 0));
40
+ }
41
+
42
+ // 0. Pre-compiled dist (fastest — no tsx overhead)
43
+ const DIST_ENTRY = join(PKG_ROOT, 'dist', 'src', 'nimbus.js');
44
+ if (existsSync(DIST_ENTRY)) {
45
+ const result = spawnSync(process.execPath, [DIST_ENTRY, ...passArgs], {
46
+ stdio: 'inherit',
47
+ env: process.env,
48
+ });
49
+ process.exit(result.status ?? (result.error ? 1 : 0));
50
+ }
51
+
52
+ // 1. tsx ESM loader bundled with this package (most reliable)
53
+ const TSX_BUNDLED = join(PKG_ROOT, 'node_modules', 'tsx', 'dist', 'esm', 'index.mjs');
54
+ if (existsSync(TSX_BUNDLED)) {
55
+ run(['--loader', TSX_BUNDLED]);
56
+ }
57
+
58
+ // 2. tsx ESM loader from global npm
59
+ try {
60
+ const globalRoot = execSync('npm root -g', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
61
+ const TSX_GLOBAL = join(globalRoot, 'tsx', 'dist', 'esm', 'index.mjs');
62
+ if (existsSync(TSX_GLOBAL)) {
63
+ run(['--loader', TSX_GLOBAL]);
64
+ }
65
+ } catch {
66
+ // npm root -g failed — continue
67
+ }
68
+
69
+ // 3. Last resort: node --import tsx (Node >= 18.19, tsx must be available)
70
+ run(['--import', 'tsx']);
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Dynamic completion helpers
4
+ _nimbus_kubectl_contexts() {
5
+ kubectl config get-contexts -o name 2>/dev/null
6
+ }
7
+ _nimbus_namespaces() {
8
+ kubectl get namespaces -o name 2>/dev/null | sed 's|namespace/||'
9
+ }
10
+ _nimbus_tf_workspaces() {
11
+ terraform workspace list 2>/dev/null | sed 's/^[* ]*//'
12
+ }
13
+
14
+ _nimbus_completions() {
15
+ local cur="${COMP_WORDS[COMP_CWORD]}"
16
+ local prev="${COMP_WORDS[COMP_CWORD-1]}"
17
+ local commands="chat run plan build deploy init login logout help version upgrade update doctor logs status alias pipeline rollback incident runbook schedule export"
18
+ # G20: Subcommand completions for terraform/kubectl/helm
19
+ case "${COMP_WORDS[1]}" in
20
+ tf|terraform) COMPREPLY=($(compgen -W "init plan apply destroy validate workspace output" -- "${cur}")); return ;;
21
+ k8s|kubectl) COMPREPLY=($(compgen -W "get apply delete logs scale rollout exec describe diff" -- "${cur}")); return ;;
22
+ helm) COMPREPLY=($(compgen -W "install upgrade rollback uninstall list show diff" -- "${cur}")); return ;;
23
+ runbook) COMPREPLY=($(compgen -W "list run create" -- "${cur}")); return ;;
24
+ schedule) COMPREPLY=($(compgen -W "list add remove run-now" -- "${cur}")); return ;;
25
+ export) COMPREPLY=($(compgen -W "--format --output" -- "${cur}")); return ;;
26
+ esac
27
+ case "$prev" in
28
+ --mode) COMPREPLY=($(compgen -W "plan build deploy" -- "$cur")); return ;;
29
+ --format) COMPREPLY=($(compgen -W "text json table md html" -- "$cur")); return ;;
30
+ --ui) COMPREPLY=($(compgen -W "ink readline" -- "$cur")); return ;;
31
+ --context) COMPREPLY=($(compgen -W "$(_nimbus_kubectl_contexts)" -- "$cur")); return ;;
32
+ --namespace|-n) COMPREPLY=($(compgen -W "$(_nimbus_namespaces)" -- "$cur")); return ;;
33
+ --workspace) COMPREPLY=($(compgen -W "$(_nimbus_tf_workspaces)" -- "$cur")); return ;;
34
+ nimbus) COMPREPLY=($(compgen -W "$commands" -- "$cur")); return ;;
35
+ esac
36
+ COMPREPLY=($(compgen -W "--mode --format --auto-approve --stdin --model --max-turns --help --version --context --namespace --workspace --quiet --budget" -- "$cur"))
37
+ }
38
+ complete -F _nimbus_completions nimbus
@@ -0,0 +1,48 @@
1
+ complete -c nimbus -f
2
+
3
+ # Subcommands
4
+ complete -c nimbus -n '__fish_use_subcommand' -a chat -d 'Interactive DevOps agent TUI'
5
+ complete -c nimbus -n '__fish_use_subcommand' -a run -d 'Run agent non-interactively'
6
+ complete -c nimbus -n '__fish_use_subcommand' -a plan -d 'Preview infrastructure changes'
7
+ complete -c nimbus -n '__fish_use_subcommand' -a init -d 'Generate NIMBUS.md'
8
+ complete -c nimbus -n '__fish_use_subcommand' -a login -d 'Configure LLM provider'
9
+ complete -c nimbus -n '__fish_use_subcommand' -a logout -d 'Remove credentials'
10
+ complete -c nimbus -n '__fish_use_subcommand' -a help -d 'Show help'
11
+ complete -c nimbus -n '__fish_use_subcommand' -a version -d 'Show version'
12
+ complete -c nimbus -n '__fish_use_subcommand' -a upgrade -d 'Upgrade to latest version'
13
+ complete -c nimbus -n '__fish_use_subcommand' -a update -d 'Alias for upgrade'
14
+ complete -c nimbus -n '__fish_use_subcommand' -a doctor -d 'Check environment'
15
+ complete -c nimbus -n '__fish_use_subcommand' -a logs -d 'Stream Kubernetes pod logs'
16
+ complete -c nimbus -n '__fish_use_subcommand' -a status -d 'Show current agent status'
17
+ complete -c nimbus -n '__fish_use_subcommand' -a alias -d 'Manage command aliases'
18
+ complete -c nimbus -n '__fish_use_subcommand' -a pipeline -d 'Run CI/CD pipeline'
19
+ complete -c nimbus -n '__fish_use_subcommand' -a rollback -d 'Rollback infrastructure changes'
20
+ complete -c nimbus -n '__fish_use_subcommand' -a incident -d 'Incident response session'
21
+ complete -c nimbus -n '__fish_use_subcommand' -a runbook -d 'Execute operational runbooks'
22
+ complete -c nimbus -n '__fish_use_subcommand' -a schedule -d 'Manage periodic automation'
23
+ complete -c nimbus -n '__fish_use_subcommand' -a export -d 'Export session to file'
24
+
25
+ # G20: Subcommand completions for tf/kubectl/helm
26
+ complete -c nimbus -n '__fish_seen_subcommand_from tf terraform' -a 'init plan apply destroy validate workspace output' -d 'terraform subcommand'
27
+ complete -c nimbus -n '__fish_seen_subcommand_from k8s kubectl' -a 'get apply delete logs scale rollout exec describe diff' -d 'kubectl subcommand'
28
+ complete -c nimbus -n '__fish_seen_subcommand_from helm' -a 'install upgrade rollback uninstall list show diff' -d 'helm subcommand'
29
+ complete -c nimbus -n '__fish_seen_subcommand_from runbook' -a 'list run create' -d 'runbook subcommand'
30
+ complete -c nimbus -n '__fish_seen_subcommand_from schedule' -a 'list add remove run-now' -d 'schedule subcommand'
31
+
32
+ # Flags
33
+ complete -c nimbus -l mode -a 'plan build deploy' -d 'Agent mode'
34
+ complete -c nimbus -l format -a 'text json table md html' -d 'Output format'
35
+ complete -c nimbus -l auto-approve -d 'Auto-approve permissions'
36
+ complete -c nimbus -l model -d 'LLM model override'
37
+ complete -c nimbus -l max-turns -d 'Maximum agent turns'
38
+ complete -c nimbus -l budget -d 'Cost budget in USD'
39
+ complete -c nimbus -l quiet -s q -d 'Suppress banners and decorative headers'
40
+
41
+ # Dynamic completions for --context (kubectl contexts)
42
+ complete -c nimbus -l context -d 'kubectl context' -a '(kubectl config get-contexts -o name 2>/dev/null)'
43
+
44
+ # Dynamic completions for --namespace (kubernetes namespaces)
45
+ complete -c nimbus -l namespace -s n -d 'Kubernetes namespace' -a '(kubectl get namespaces -o name 2>/dev/null | string replace "namespace/" "")'
46
+
47
+ # Dynamic completions for --workspace (terraform workspaces)
48
+ complete -c nimbus -l workspace -d 'Terraform workspace' -a '(terraform workspace list 2>/dev/null | string replace -r "^[* ]*" "")'
@@ -0,0 +1,81 @@
1
+ #compdef nimbus
2
+
3
+ # Dynamic completion helpers
4
+ _nimbus_kubectl_contexts() {
5
+ local contexts
6
+ contexts=(${(f)"$(kubectl config get-contexts -o name 2>/dev/null)"})
7
+ _describe 'kubectl contexts' contexts
8
+ }
9
+
10
+ _nimbus_namespaces() {
11
+ local namespaces
12
+ namespaces=(${(f)"$(kubectl get namespaces -o name 2>/dev/null | sed 's|namespace/||')"})
13
+ _describe 'kubernetes namespaces' namespaces
14
+ }
15
+
16
+ _nimbus_tf_workspaces() {
17
+ local workspaces
18
+ workspaces=(${(f)"$(terraform workspace list 2>/dev/null | sed 's/^[* ]*//')"})
19
+ _describe 'terraform workspaces' workspaces
20
+ }
21
+
22
+ _nimbus() {
23
+ local -a commands
24
+ commands=(
25
+ 'chat:Interactive DevOps agent TUI'
26
+ 'run:Run agent non-interactively'
27
+ 'plan:Preview infrastructure changes'
28
+ 'init:Generate NIMBUS.md project context'
29
+ 'login:Configure LLM provider'
30
+ 'logout:Remove credentials'
31
+ 'help:Show help'
32
+ 'version:Show version'
33
+ 'upgrade:Upgrade to latest version'
34
+ 'update:Alias for upgrade'
35
+ 'doctor:Check environment'
36
+ 'logs:Stream Kubernetes pod logs'
37
+ 'status:Show current agent status'
38
+ 'alias:Manage command aliases'
39
+ 'pipeline:Run CI/CD pipeline'
40
+ 'rollback:Rollback infrastructure changes'
41
+ 'incident:Incident response session'
42
+ 'runbook:Execute operational runbooks'
43
+ 'schedule:Manage periodic automation'
44
+ 'export:Export session to file'
45
+ )
46
+ _arguments \
47
+ '1: :->command' \
48
+ '--mode[Agent mode]:mode:(plan build deploy)' \
49
+ '--format[Output format]:format:(text json table md html)' \
50
+ '--auto-approve[Auto-approve permissions]' \
51
+ '--model[LLM model]:model:' \
52
+ '--context[kubectl context]:context:_nimbus_kubectl_contexts' \
53
+ '--namespace[Kubernetes namespace]:namespace:_nimbus_namespaces' \
54
+ '--workspace[Terraform workspace]:workspace:_nimbus_tf_workspaces' \
55
+ '--budget[Cost budget in USD]:budget:' \
56
+ '--quiet[Suppress banners/headers]' \
57
+ '--version[Show version]' \
58
+ '--help[Show help]'
59
+ # G20: Subcommand completions
60
+ case ${words[2]} in
61
+ tf|terraform)
62
+ local -a tf_cmds; tf_cmds=('init' 'plan' 'apply' 'destroy' 'validate' 'workspace' 'output')
63
+ _describe 'terraform subcommands' tf_cmds; return ;;
64
+ k8s|kubectl)
65
+ local -a k8s_cmds; k8s_cmds=('get' 'apply' 'delete' 'logs' 'scale' 'rollout' 'exec' 'describe' 'diff')
66
+ _describe 'kubectl subcommands' k8s_cmds; return ;;
67
+ helm)
68
+ local -a helm_cmds; helm_cmds=('install' 'upgrade' 'rollback' 'uninstall' 'list' 'show' 'diff')
69
+ _describe 'helm subcommands' helm_cmds; return ;;
70
+ runbook)
71
+ local -a rb_cmds; rb_cmds=('list' 'run' 'create')
72
+ _describe 'runbook subcommands' rb_cmds; return ;;
73
+ schedule)
74
+ local -a sched_cmds; sched_cmds=('list' 'add' 'remove' 'run-now')
75
+ _describe 'schedule subcommands' sched_cmds; return ;;
76
+ esac
77
+ case $state in
78
+ command) _describe 'nimbus commands' commands ;;
79
+ esac
80
+ }
81
+ _nimbus "$@"
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Compaction Agent
3
+ *
4
+ * Uses a fast LLM model (haiku) to summarize earlier conversation context
5
+ * while preserving key information needed for continuity.
6
+ *
7
+ * The compaction agent is invoked automatically by the context manager
8
+ * when the conversation exceeds the configured threshold, or manually
9
+ * by the user via a `/compact` command in the TUI.
10
+ *
11
+ * Key design decisions:
12
+ * - Uses the cheapest available model (haiku alias) to minimize cost.
13
+ * - Truncates very long tool outputs before sending to the summarizer.
14
+ * - Falls back to a simple extractive summary if the LLM call fails.
15
+ * - Preserves all technical details, file paths, and decisions.
16
+ *
17
+ * @module agent/compaction-agent
18
+ */
19
+ import { getTextContent } from '../llm/types';
20
+ import { ContextManager, estimateTokens } from './context-manager';
21
+ // ---------------------------------------------------------------------------
22
+ // Constants
23
+ // ---------------------------------------------------------------------------
24
+ /** The system prompt given to the compaction model. */
25
+ const COMPACTION_SYSTEM_PROMPT = `You are a conversation summarizer for the Nimbus CLI agent. Your job is to create a concise summary of a conversation between a user and an AI assistant that helps with cloud infrastructure and DevOps tasks.
26
+
27
+ Rules:
28
+ 1. Preserve ALL important technical details: file paths, resource names, configuration values, error messages, decisions made.
29
+ 2. Preserve the user's original intent and any requirements they specified.
30
+ 3. Preserve the current state of any ongoing work (what was done, what remains).
31
+ 4. Remove conversational filler, repeated information, and verbose tool outputs.
32
+ 5. Use bullet points for clarity.
33
+ 6. Keep the summary under 2000 tokens.
34
+ 7. Structure the summary as:
35
+ - **User's Goal**: What the user is trying to accomplish
36
+ - **Key Decisions**: Important choices that were made
37
+ - **Work Completed**: What actions were taken and their results
38
+ - **Current State**: Where things stand now
39
+ - **Pending Items**: What still needs to be done (if any)`;
40
+ // ---------------------------------------------------------------------------
41
+ // Public API
42
+ // ---------------------------------------------------------------------------
43
+ /**
44
+ * Run the compaction agent to summarize a set of messages.
45
+ *
46
+ * Splits the conversation into messages to preserve and messages to
47
+ * summarize (using the context manager's selection logic), sends the
48
+ * latter to a fast LLM for summarization, then reassembles a compacted
49
+ * message array.
50
+ *
51
+ * @param messages - The full conversation message array.
52
+ * @param contextManager - The context manager instance (provides selection logic).
53
+ * @param options - Compaction options (router, model, focus area).
54
+ * @returns The compacted messages and a result summary.
55
+ */
56
+ export async function runCompaction(messages, contextManager, options) {
57
+ const { preserved, toSummarize } = contextManager.selectPreservedMessages(messages);
58
+ // Nothing to summarize -- return early
59
+ if (toSummarize.length === 0) {
60
+ const totalTokens = messages.reduce((sum, m) => sum + estimateTokens(getTextContent(m.content)), 0);
61
+ return {
62
+ messages,
63
+ result: {
64
+ originalTokens: totalTokens,
65
+ compactedTokens: totalTokens,
66
+ savedTokens: 0,
67
+ summaryPreserved: false,
68
+ },
69
+ };
70
+ }
71
+ // Format messages for the summarizer
72
+ const conversationText = formatMessagesForSummary(toSummarize);
73
+ const originalTokens = estimateTokens(conversationText);
74
+ // Build the user prompt for the summarizer
75
+ let userPrompt = `Please summarize the following conversation between a user and the Nimbus AI assistant:\n\n${conversationText}`;
76
+ if (options.focusArea) {
77
+ userPrompt += `\n\nPay special attention to: ${options.focusArea}`;
78
+ }
79
+ // H3: Inject current infraContext into compaction prompt so it's never omitted
80
+ if (options.infraContext) {
81
+ const ic = options.infraContext;
82
+ const infraLines = [];
83
+ if (ic.terraformWorkspace)
84
+ infraLines.push(`- Terraform workspace: ${ic.terraformWorkspace}`);
85
+ if (ic.kubectlContext)
86
+ infraLines.push(`- kubectl context: ${ic.kubectlContext}`);
87
+ if (ic.awsProfile)
88
+ infraLines.push(`- AWS profile: ${ic.awsProfile}`);
89
+ if (ic.awsRegion)
90
+ infraLines.push(`- AWS region: ${ic.awsRegion}`);
91
+ if (ic.gcpProject)
92
+ infraLines.push(`- GCP project: ${ic.gcpProject}`);
93
+ if (ic.azureSubscription)
94
+ infraLines.push(`- Azure subscription: ${ic.azureSubscription}`);
95
+ if (infraLines.length > 0) {
96
+ userPrompt += `\n\n## ALWAYS PRESERVE IN SUMMARY (do not omit):\n${infraLines.join('\n')}`;
97
+ }
98
+ }
99
+ // Call the LLM for summarization using a fast, cheap model
100
+ const model = options.model ?? 'haiku';
101
+ let summary;
102
+ try {
103
+ const response = await options.router.route({
104
+ messages: [
105
+ { role: 'system', content: COMPACTION_SYSTEM_PROMPT },
106
+ { role: 'user', content: userPrompt },
107
+ ],
108
+ model,
109
+ maxTokens: 2048,
110
+ });
111
+ summary = response.content;
112
+ }
113
+ catch {
114
+ // If LLM call fails, fall back to a simple extractive summary
115
+ summary = fallbackSummary(toSummarize);
116
+ }
117
+ // H3: Prepend infraContext block to summary so it survives compaction
118
+ let finalSummary = summary;
119
+ if (options.infraContext) {
120
+ const ic = options.infraContext;
121
+ const infraLines = [];
122
+ if (ic.terraformWorkspace)
123
+ infraLines.push(`- Terraform workspace: ${ic.terraformWorkspace}`);
124
+ if (ic.kubectlContext)
125
+ infraLines.push(`- kubectl context: ${ic.kubectlContext}`);
126
+ if (ic.awsProfile)
127
+ infraLines.push(`- AWS profile: ${ic.awsProfile}`);
128
+ if (ic.awsRegion)
129
+ infraLines.push(`- AWS region: ${ic.awsRegion}`);
130
+ if (ic.gcpProject)
131
+ infraLines.push(`- GCP project: ${ic.gcpProject}`);
132
+ if (ic.azureSubscription)
133
+ infraLines.push(`- Azure subscription: ${ic.azureSubscription}`);
134
+ if (infraLines.length > 0) {
135
+ finalSummary = `## Infrastructure Context\n${infraLines.join('\n')}\n\n${summary}`;
136
+ }
137
+ }
138
+ // Reassemble the compacted message array
139
+ const compactedMessages = contextManager.buildCompactedMessages(preserved, finalSummary);
140
+ const compactedTokens = compactedMessages.reduce((sum, m) => sum + estimateTokens(getTextContent(m.content)), 0);
141
+ return {
142
+ messages: compactedMessages,
143
+ result: {
144
+ originalTokens,
145
+ compactedTokens,
146
+ savedTokens: originalTokens - estimateTokens(summary),
147
+ summaryPreserved: true,
148
+ },
149
+ };
150
+ }
151
+ /**
152
+ * Run manual compaction from a `/compact` command.
153
+ *
154
+ * Creates a temporary context manager with default settings and
155
+ * delegates to {@link runCompaction}.
156
+ *
157
+ * @param messages - The full conversation message array.
158
+ * @param options - Compaction options plus an optional max token override.
159
+ * @returns The compacted messages and a result summary.
160
+ */
161
+ export async function runManualCompaction(messages, options) {
162
+ const contextManager = new ContextManager({
163
+ maxContextTokens: options.maxContextTokens,
164
+ preserveRecentMessages: 5,
165
+ });
166
+ return runCompaction(messages, contextManager, options);
167
+ }
168
+ // ---------------------------------------------------------------------------
169
+ // Internal Helpers
170
+ // ---------------------------------------------------------------------------
171
+ /**
172
+ * Format messages into a readable conversation transcript.
173
+ *
174
+ * Each message is labelled with its role. Very long tool outputs are
175
+ * truncated to avoid overwhelming the summarizer model. Tool call
176
+ * metadata is included inline for context.
177
+ */
178
+ function formatMessagesForSummary(messages) {
179
+ const parts = [];
180
+ for (const msg of messages) {
181
+ const role = msg.role === 'user' ? 'User' : msg.role === 'assistant' ? 'Assistant' : 'Tool';
182
+ const content = getTextContent(msg.content);
183
+ // Truncate very long tool outputs to keep summarizer input manageable
184
+ const truncated = content.length > 2000 ? `${content.slice(0, 2000)}... [truncated]` : content;
185
+ parts.push(`[${role}]: ${truncated}`);
186
+ // Include tool call info if present
187
+ if (msg.toolCalls) {
188
+ for (const tc of msg.toolCalls) {
189
+ parts.push(` [Tool Call: ${tc.function.name}(${tc.function.arguments.slice(0, 200)})]`);
190
+ }
191
+ }
192
+ }
193
+ return parts.join('\n\n');
194
+ }
195
+ /**
196
+ * Fallback summary when the LLM is unavailable.
197
+ *
198
+ * Produces a simple extractive summary by listing message counts
199
+ * and the first few user messages. This is better than nothing when
200
+ * the compaction model cannot be reached.
201
+ */
202
+ function fallbackSummary(messages) {
203
+ const userMessages = messages.filter(m => m.role === 'user');
204
+ const assistantMessages = messages.filter(m => m.role === 'assistant');
205
+ const parts = ['**Conversation Summary (auto-generated)**\n'];
206
+ parts.push(`- ${userMessages.length} user messages and ${assistantMessages.length} assistant responses`);
207
+ // Extract key topics from user messages
208
+ for (const msg of userMessages.slice(0, 5)) {
209
+ const content = getTextContent(msg.content);
210
+ if (content.length > 0) {
211
+ parts.push(`- User asked: "${content.slice(0, 150)}${content.length > 150 ? '...' : ''}"`);
212
+ }
213
+ }
214
+ return parts.join('\n');
215
+ }