@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,235 @@
1
+ /**
2
+ * Explain Command
3
+ *
4
+ * Get AI explanations for code, infrastructure, or errors
5
+ *
6
+ * Usage: nimbus explain <target> [options]
7
+ */
8
+ import { logger } from '../utils';
9
+ import { ui } from '../wizard';
10
+ import { llmClient } from '../clients';
11
+ /**
12
+ * Detect content type from target
13
+ */
14
+ function detectExplainType(target, content) {
15
+ // Check for error patterns
16
+ const errorPatterns = [
17
+ /^error:/i,
18
+ /^exception:/i,
19
+ /failed/i,
20
+ /traceback/i,
21
+ /stack trace/i,
22
+ /undefined variable/i,
23
+ /cannot find/i,
24
+ /not found/i,
25
+ /invalid/i,
26
+ /permission denied/i,
27
+ ];
28
+ const targetLower = target.toLowerCase();
29
+ if (errorPatterns.some(p => p.test(target) || (content && p.test(content)))) {
30
+ return 'error';
31
+ }
32
+ // Check for infrastructure file extensions
33
+ const infraExtensions = ['.tf', '.yaml', '.yml', '.json', '.hcl', '.toml'];
34
+ if (infraExtensions.some(ext => targetLower.endsWith(ext))) {
35
+ return 'infra';
36
+ }
37
+ // Check content for infrastructure patterns
38
+ if (content) {
39
+ if (content.includes('apiVersion:') && content.includes('kind:')) {
40
+ return 'infra'; // Kubernetes
41
+ }
42
+ if (content.includes('resource ') && content.includes('provider ')) {
43
+ return 'infra'; // Terraform
44
+ }
45
+ if (content.includes('AWSTemplateFormatVersion')) {
46
+ return 'infra'; // CloudFormation
47
+ }
48
+ }
49
+ // Check for code file extensions
50
+ const codeExtensions = [
51
+ '.ts',
52
+ '.js',
53
+ '.py',
54
+ '.go',
55
+ '.java',
56
+ '.rs',
57
+ '.rb',
58
+ '.php',
59
+ '.c',
60
+ '.cpp',
61
+ '.cs',
62
+ ];
63
+ if (codeExtensions.some(ext => targetLower.endsWith(ext))) {
64
+ return 'code';
65
+ }
66
+ // Default to code for unknown content
67
+ return 'code';
68
+ }
69
+ /**
70
+ * Build the explanation prompt based on type
71
+ */
72
+ function buildPrompt(type, content, verbose) {
73
+ const detailLevel = verbose ? 'detailed' : 'concise';
74
+ switch (type) {
75
+ case 'error':
76
+ return `Please explain this error and suggest how to fix it. Provide a ${detailLevel} explanation.
77
+
78
+ Error:
79
+ \`\`\`
80
+ ${content}
81
+ \`\`\`
82
+
83
+ Include:
84
+ 1. What the error means
85
+ 2. Why it might have occurred
86
+ 3. How to fix it
87
+ 4. How to prevent it in the future`;
88
+ case 'infra':
89
+ return `Please explain this infrastructure configuration. Provide a ${detailLevel} explanation.
90
+
91
+ Configuration:
92
+ \`\`\`
93
+ ${content}
94
+ \`\`\`
95
+
96
+ Include:
97
+ 1. What this configuration does
98
+ 2. Key components and their purpose
99
+ 3. Any potential issues or improvements
100
+ ${verbose ? '4. Security considerations\n5. Best practices recommendations' : ''}`;
101
+ case 'code':
102
+ default:
103
+ return `Please explain this code. Provide a ${detailLevel} explanation.
104
+
105
+ Code:
106
+ \`\`\`
107
+ ${content}
108
+ \`\`\`
109
+
110
+ Include:
111
+ 1. What the code does
112
+ 2. How it works
113
+ 3. Any potential issues
114
+ ${verbose ? '4. Suggestions for improvement\n5. Related best practices' : ''}`;
115
+ }
116
+ }
117
+ /**
118
+ * Run the explain command
119
+ */
120
+ export async function explainCommand(target, options = {}) {
121
+ logger.info('Running explain command', { target, options });
122
+ let content;
123
+ let filePath;
124
+ // Get content to explain
125
+ if (options.file) {
126
+ // Read from specified file
127
+ filePath = options.file;
128
+ try {
129
+ const fs = await import('fs/promises');
130
+ content = await fs.readFile(filePath, 'utf-8');
131
+ }
132
+ catch (error) {
133
+ ui.error(`Could not read file: ${error.message}`);
134
+ process.exit(1);
135
+ }
136
+ }
137
+ else if (target) {
138
+ // Check if target is a file path
139
+ try {
140
+ const fs = await import('fs/promises');
141
+ const stat = await fs.stat(target);
142
+ if (stat.isFile()) {
143
+ filePath = target;
144
+ content = await fs.readFile(target, 'utf-8');
145
+ }
146
+ else if (stat.isDirectory()) {
147
+ ui.error('Please specify a file, not a directory');
148
+ ui.info('Usage: nimbus explain <file> or nimbus explain "error message"');
149
+ process.exit(1);
150
+ }
151
+ else {
152
+ content = target;
153
+ }
154
+ }
155
+ catch {
156
+ // Not a file, use as content directly
157
+ content = target;
158
+ }
159
+ }
160
+ else {
161
+ ui.error('Please provide something to explain');
162
+ ui.newLine();
163
+ ui.print('Usage: nimbus explain <target> [options]');
164
+ ui.newLine();
165
+ ui.print('Examples:');
166
+ ui.print(' nimbus explain ./main.tf');
167
+ ui.print(' nimbus explain "Error: resource not found" --type error');
168
+ ui.print(' nimbus explain --file ./deployment.yaml');
169
+ process.exit(1);
170
+ }
171
+ // Limit content size
172
+ const maxLength = 10000;
173
+ if (content.length > maxLength) {
174
+ ui.warning(`Content truncated to ${maxLength} characters`);
175
+ content = `${content.slice(0, maxLength)}\n... (content truncated)`;
176
+ }
177
+ // Detect or use specified type
178
+ const type = options.type === 'auto' || !options.type ? detectExplainType(target, content) : options.type;
179
+ // Display header
180
+ ui.header('Nimbus Explain');
181
+ if (filePath) {
182
+ ui.info(`File: ${filePath}`);
183
+ }
184
+ ui.info(`Type: ${type}`);
185
+ ui.newLine();
186
+ // Check if LLM is available
187
+ const llmAvailable = await llmClient.isAvailable();
188
+ if (!llmAvailable) {
189
+ ui.error('LLM service is not available');
190
+ ui.info('Make sure you have configured an LLM provider with "nimbus login"');
191
+ process.exit(1);
192
+ }
193
+ // Build prompt
194
+ const prompt = buildPrompt(type, content, options.verbose ?? false);
195
+ ui.startSpinner({ message: 'Analyzing...' });
196
+ try {
197
+ let response = '';
198
+ let firstChunk = true;
199
+ for await (const chunk of llmClient.chat(prompt, [])) {
200
+ if (chunk.type === 'content' && chunk.content) {
201
+ if (firstChunk) {
202
+ ui.stopSpinnerSuccess('');
203
+ ui.newLine();
204
+ firstChunk = false;
205
+ }
206
+ response += chunk.content;
207
+ process.stdout.write(chunk.content);
208
+ }
209
+ else if (chunk.type === 'error') {
210
+ ui.stopSpinnerFail('Error');
211
+ ui.error(chunk.message || chunk.error || 'Unknown error');
212
+ process.exit(1);
213
+ }
214
+ }
215
+ // Ensure newline at end
216
+ if (!response.endsWith('\n')) {
217
+ ui.newLine();
218
+ }
219
+ // JSON output mode
220
+ if (options.json) {
221
+ console.log(JSON.stringify({
222
+ type,
223
+ file: filePath,
224
+ explanation: response,
225
+ }, null, 2));
226
+ }
227
+ }
228
+ catch (error) {
229
+ ui.stopSpinnerFail('Failed');
230
+ ui.error(error.message);
231
+ process.exit(1);
232
+ }
233
+ }
234
+ // Export as default
235
+ export default explainCommand;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Export Command (G19)
3
+ *
4
+ * Export session conversations to markdown, HTML, or JSON.
5
+ *
6
+ * Usage:
7
+ * nimbus export # most recent session → stdout (md)
8
+ * nimbus export <session-id> # specific session
9
+ * nimbus export --format html # HTML output
10
+ * nimbus export --format json # JSON output
11
+ * nimbus export --output report.md # save to file
12
+ */
13
+ import { writeFileSync } from 'node:fs';
14
+ // ---------------------------------------------------------------------------
15
+ // Helpers
16
+ // ---------------------------------------------------------------------------
17
+ function messageToMarkdown(role, content) {
18
+ const label = role === 'user' ? '**User**' : role === 'assistant' ? '**Agent**' : `*[${role}]*`;
19
+ return `${label}:\n${content}\n`;
20
+ }
21
+ // ---------------------------------------------------------------------------
22
+ // Main export
23
+ // ---------------------------------------------------------------------------
24
+ export async function exportCommand(options = {}) {
25
+ const format = options.format ?? 'md';
26
+ // Load session manager + conversation
27
+ let conversation = [];
28
+ let sessionMeta = { id: 'unknown' };
29
+ try {
30
+ const { SessionManager } = await import('../sessions/manager');
31
+ const sm = SessionManager.getInstance();
32
+ const sessions = sm.list();
33
+ // Find the target session
34
+ let targetSession = sessions.find(s => options.sessionId && (s.id === options.sessionId || s.id.startsWith(options.sessionId))) ?? sessions[0];
35
+ if (!targetSession) {
36
+ console.error('No sessions found. Run "nimbus chat" first to create a session.');
37
+ process.exit(1);
38
+ }
39
+ sessionMeta = {
40
+ id: targetSession.id,
41
+ name: targetSession.name,
42
+ model: targetSession.model,
43
+ mode: targetSession.mode,
44
+ createdAt: targetSession.createdAt,
45
+ };
46
+ const messages = sm.loadConversation(targetSession.id);
47
+ conversation = messages
48
+ .filter(m => m.role === 'user' || m.role === 'assistant')
49
+ .map(m => ({
50
+ role: m.role,
51
+ content: Array.isArray(m.content)
52
+ ? m.content.map((b) => {
53
+ if (typeof b === 'string')
54
+ return b;
55
+ if (b && typeof b === 'object' && 'text' in b)
56
+ return b.text;
57
+ return '';
58
+ }).join('')
59
+ : String(m.content ?? ''),
60
+ }));
61
+ }
62
+ catch (err) {
63
+ console.error(`Failed to load session: ${err instanceof Error ? err.message : String(err)}`);
64
+ process.exit(1);
65
+ }
66
+ // Generate output
67
+ let output = '';
68
+ if (format === 'json') {
69
+ output = JSON.stringify({ session: sessionMeta, messages: conversation }, null, 2);
70
+ }
71
+ else if (format === 'html') {
72
+ output = buildHtml(sessionMeta, conversation);
73
+ }
74
+ else {
75
+ // Default: markdown
76
+ output = buildMarkdown(sessionMeta, conversation);
77
+ }
78
+ // Output to file or stdout
79
+ if (options.output) {
80
+ writeFileSync(options.output, output, 'utf-8');
81
+ console.log(`Exported to: ${options.output}`);
82
+ }
83
+ else {
84
+ process.stdout.write(output);
85
+ }
86
+ }
87
+ function buildMarkdown(meta, conversation) {
88
+ const lines = [
89
+ `# Nimbus Session Export`,
90
+ ``,
91
+ `| Field | Value |`,
92
+ `|-------|-------|`,
93
+ `| Session ID | ${meta.id} |`,
94
+ `| Name | ${meta.name ?? 'N/A'} |`,
95
+ `| Model | ${meta.model ?? 'N/A'} |`,
96
+ `| Mode | ${meta.mode ?? 'N/A'} |`,
97
+ `| Created | ${meta.createdAt ?? new Date().toISOString()} |`,
98
+ ``,
99
+ `---`,
100
+ ``,
101
+ `## Conversation`,
102
+ ``,
103
+ ];
104
+ for (const msg of conversation) {
105
+ lines.push(messageToMarkdown(msg.role, msg.content));
106
+ lines.push('---');
107
+ lines.push('');
108
+ }
109
+ return lines.join('\n');
110
+ }
111
+ function buildHtml(meta, conversation) {
112
+ const escape = (s) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
113
+ const msgs = conversation.map(m => {
114
+ const isUser = m.role === 'user';
115
+ const bg = isUser ? '#3b82f6' : '#1e293b';
116
+ const align = isUser ? 'flex-end' : 'flex-start';
117
+ return `<div style="display:flex;justify-content:${align};margin:8px 0"><div style="max-width:75%;padding:12px 16px;border-radius:16px;background:${bg};color:#e2e8f0;font-size:14px;line-height:1.6;white-space:pre-wrap">${escape(m.content)}</div></div>`;
118
+ }).join('\n');
119
+ return `<!DOCTYPE html><html><head><meta charset="utf-8"><title>Nimbus Session Export — ${escape(meta.id)}</title></head><body style="background:#0f172a;color:#e2e8f0;font-family:monospace;padding:24px"><h2>Nimbus Session: ${escape(meta.name ?? meta.id)}</h2><p>Model: ${escape(meta.model ?? 'N/A')} | Mode: ${escape(meta.mode ?? 'N/A')} | Created: ${escape(meta.createdAt ?? '')}</p><div>${msgs}</div></body></html>`;
120
+ }
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Feedback Command
3
+ *
4
+ * Collect and submit user feedback via GitHub issues or browser
5
+ *
6
+ * Usage: nimbus feedback [options]
7
+ */
8
+ import { logger } from '../utils';
9
+ import { ui } from '../wizard';
10
+ import { input, select } from '../wizard/prompts';
11
+ const FEEDBACK_TYPES = {
12
+ bug: {
13
+ label: 'Bug Report',
14
+ emoji: 'bug',
15
+ template: `## Bug Description
16
+ <!-- A clear and concise description of what the bug is -->
17
+
18
+ ## Steps to Reproduce
19
+ 1.
20
+ 2.
21
+ 3.
22
+
23
+ ## Expected Behavior
24
+ <!-- What you expected to happen -->
25
+
26
+ ## Actual Behavior
27
+ <!-- What actually happened -->
28
+
29
+ ## Environment
30
+ - Nimbus Version:
31
+ - OS:
32
+ - Node Version:
33
+
34
+ ## Additional Context
35
+ <!-- Any other relevant information -->
36
+ `,
37
+ labels: ['bug', 'triage'],
38
+ },
39
+ feature: {
40
+ label: 'Feature Request',
41
+ emoji: 'sparkles',
42
+ template: `## Feature Description
43
+ <!-- A clear and concise description of the feature -->
44
+
45
+ ## Use Case
46
+ <!-- Why do you need this feature? What problem does it solve? -->
47
+
48
+ ## Proposed Solution
49
+ <!-- How do you think this should work? -->
50
+
51
+ ## Alternatives Considered
52
+ <!-- Any alternative solutions or features you've considered -->
53
+
54
+ ## Additional Context
55
+ <!-- Any other relevant information -->
56
+ `,
57
+ labels: ['enhancement', 'feature-request'],
58
+ },
59
+ question: {
60
+ label: 'Question',
61
+ emoji: 'question',
62
+ template: `## Question
63
+ <!-- What would you like to know? -->
64
+
65
+ ## Context
66
+ <!-- What are you trying to accomplish? -->
67
+
68
+ ## What I've Tried
69
+ <!-- What documentation or approaches have you already tried? -->
70
+ `,
71
+ labels: ['question', 'help-wanted'],
72
+ },
73
+ };
74
+ const GITHUB_REPO = 'the-ai-project-co/nimbus';
75
+ const GITHUB_ISSUES_URL = `https://github.com/${GITHUB_REPO}/issues`;
76
+ /**
77
+ * Get system information for bug reports
78
+ */
79
+ async function getSystemInfo() {
80
+ const os = await import('os');
81
+ const { execFileSync } = await import('child_process');
82
+ const info = {
83
+ OS: `${os.platform()} ${os.release()}`,
84
+ Architecture: os.arch(),
85
+ 'Node Version': process.version,
86
+ };
87
+ // Try to get Nimbus version
88
+ try {
89
+ const fs = await import('fs/promises');
90
+ const path = await import('path');
91
+ const packagePath = path.join(__dirname, '../../package.json');
92
+ const packageJson = JSON.parse(await fs.readFile(packagePath, 'utf-8'));
93
+ info['Nimbus Version'] = packageJson.version;
94
+ }
95
+ catch {
96
+ info['Nimbus Version'] = 'unknown';
97
+ }
98
+ // Try to get Bun version
99
+ try {
100
+ const bunVersion = execFileSync('bun', ['--version'], { encoding: 'utf-8' }).trim();
101
+ info['Bun Version'] = bunVersion;
102
+ }
103
+ catch {
104
+ // Bun not installed
105
+ }
106
+ return info;
107
+ }
108
+ /**
109
+ * Open URL in browser
110
+ */
111
+ async function openInBrowser(url) {
112
+ const { exec } = await import('child_process');
113
+ const { promisify } = await import('util');
114
+ const execAsync = promisify(exec);
115
+ try {
116
+ const platform = process.platform;
117
+ let command;
118
+ if (platform === 'darwin') {
119
+ command = `open "${url}"`;
120
+ }
121
+ else if (platform === 'win32') {
122
+ command = `start "" "${url}"`;
123
+ }
124
+ else {
125
+ command = `xdg-open "${url}"`;
126
+ }
127
+ await execAsync(command);
128
+ return true;
129
+ }
130
+ catch {
131
+ return false;
132
+ }
133
+ }
134
+ /**
135
+ * Build GitHub issue URL with pre-filled content
136
+ */
137
+ function buildIssueUrl(type, title, body, labels) {
138
+ const params = new URLSearchParams({
139
+ title,
140
+ body,
141
+ labels: labels.join(','),
142
+ });
143
+ return `${GITHUB_ISSUES_URL}/new?${params.toString()}`;
144
+ }
145
+ /**
146
+ * Interactive feedback collection
147
+ */
148
+ async function collectFeedbackInteractively(options) {
149
+ // Determine feedback type
150
+ let feedbackType;
151
+ if (options.bug) {
152
+ feedbackType = 'bug';
153
+ }
154
+ else if (options.feature) {
155
+ feedbackType = 'feature';
156
+ }
157
+ else if (options.question) {
158
+ feedbackType = 'question';
159
+ }
160
+ else {
161
+ // Ask user to select type
162
+ feedbackType = await select({
163
+ message: 'What type of feedback would you like to provide?',
164
+ options: [
165
+ { label: 'Bug Report', value: 'bug' },
166
+ { label: 'Feature Request', value: 'feature' },
167
+ { label: 'Question', value: 'question' },
168
+ ],
169
+ });
170
+ if (!feedbackType) {
171
+ return null;
172
+ }
173
+ }
174
+ const typeConfig = FEEDBACK_TYPES[feedbackType];
175
+ ui.newLine();
176
+ ui.print(ui.bold(`${typeConfig.label}`));
177
+ ui.newLine();
178
+ // Get title
179
+ let title = options.title;
180
+ if (!title) {
181
+ title = await input({
182
+ message: 'Brief summary (title):',
183
+ placeholder: `Enter a short description of your ${feedbackType === 'bug' ? 'issue' : feedbackType === 'feature' ? 'request' : 'question'}`,
184
+ });
185
+ if (!title || title.trim() === '') {
186
+ ui.warning('Feedback cancelled - no title provided');
187
+ return null;
188
+ }
189
+ }
190
+ // Get body/description
191
+ let body = options.body;
192
+ if (!body) {
193
+ ui.newLine();
194
+ ui.info('Please provide details (press Enter twice to finish):');
195
+ ui.dim('Tip: You can also edit the full template on GitHub');
196
+ ui.newLine();
197
+ body = await input({
198
+ message: 'Details (optional):',
199
+ placeholder: 'Describe the issue, feature, or question in detail...',
200
+ });
201
+ }
202
+ // Build full body with template
203
+ let fullBody = typeConfig.template;
204
+ if (body && body.trim()) {
205
+ // Replace first section placeholder with user's input
206
+ fullBody = fullBody.replace(/<!-- .+? -->/, body.trim());
207
+ }
208
+ // Add system info for bug reports
209
+ if (feedbackType === 'bug') {
210
+ const systemInfo = await getSystemInfo();
211
+ const envSection = Object.entries(systemInfo)
212
+ .map(([key, value]) => `- ${key}: ${value}`)
213
+ .join('\n');
214
+ fullBody = fullBody.replace('## Environment\n- Nimbus Version: \n- OS: \n- Node Version:', `## Environment\n${envSection}`);
215
+ }
216
+ return {
217
+ type: feedbackType,
218
+ title: title.trim(),
219
+ body: fullBody,
220
+ };
221
+ }
222
+ /**
223
+ * Run the feedback command
224
+ */
225
+ export async function feedbackCommand(options = {}) {
226
+ logger.debug('Running feedback command', { options });
227
+ ui.header('Nimbus Feedback');
228
+ ui.info('Help us improve Nimbus by sharing your feedback!');
229
+ ui.newLine();
230
+ // Quick open mode - just open GitHub issues
231
+ if (options.open) {
232
+ ui.info('Opening GitHub issues page...');
233
+ const opened = await openInBrowser(GITHUB_ISSUES_URL);
234
+ if (opened) {
235
+ ui.success('Opened in browser');
236
+ }
237
+ else {
238
+ ui.print(`Visit: ${GITHUB_ISSUES_URL}`);
239
+ }
240
+ return;
241
+ }
242
+ // Collect feedback interactively
243
+ const feedback = await collectFeedbackInteractively(options);
244
+ if (!feedback) {
245
+ return;
246
+ }
247
+ const typeConfig = FEEDBACK_TYPES[feedback.type];
248
+ const issueUrl = buildIssueUrl(feedback.type, feedback.title, feedback.body, typeConfig.labels);
249
+ // JSON output
250
+ if (options.json) {
251
+ console.log(JSON.stringify({
252
+ type: feedback.type,
253
+ title: feedback.title,
254
+ url: issueUrl,
255
+ labels: typeConfig.labels,
256
+ }, null, 2));
257
+ return;
258
+ }
259
+ ui.newLine();
260
+ ui.print(ui.bold('Feedback Summary'));
261
+ ui.print(` Type: ${typeConfig.label}`);
262
+ ui.print(` Title: ${feedback.title}`);
263
+ ui.newLine();
264
+ // Open in browser
265
+ ui.info('Opening GitHub to submit your feedback...');
266
+ const opened = await openInBrowser(issueUrl);
267
+ if (opened) {
268
+ ui.success('Opened in browser - please review and submit the issue');
269
+ }
270
+ else {
271
+ ui.warning('Could not open browser automatically');
272
+ ui.newLine();
273
+ ui.print('Please copy and paste this URL to submit your feedback:');
274
+ ui.print(issueUrl);
275
+ }
276
+ ui.newLine();
277
+ ui.info('Thank you for your feedback!');
278
+ }
279
+ /**
280
+ * Parse feedback command options from CLI args
281
+ */
282
+ export function parseFeedbackOptions(args) {
283
+ const options = {};
284
+ for (let i = 0; i < args.length; i++) {
285
+ const arg = args[i];
286
+ switch (arg) {
287
+ case '--bug':
288
+ case '-b':
289
+ options.bug = true;
290
+ break;
291
+ case '--feature':
292
+ case '-f':
293
+ options.feature = true;
294
+ break;
295
+ case '--question':
296
+ case '-q':
297
+ options.question = true;
298
+ break;
299
+ case '--title':
300
+ case '-t':
301
+ options.title = args[++i];
302
+ break;
303
+ case '--body':
304
+ case '-m':
305
+ options.body = args[++i];
306
+ break;
307
+ case '--open':
308
+ case '-o':
309
+ options.open = true;
310
+ break;
311
+ case '--json':
312
+ options.json = true;
313
+ break;
314
+ }
315
+ }
316
+ return options;
317
+ }
318
+ // Export as default command
319
+ export default feedbackCommand;