@build-astron-co/nimbus 0.2.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 (313) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +628 -0
  3. package/bin/nimbus +38 -0
  4. package/package.json +80 -0
  5. package/src/__tests__/app.test.ts +76 -0
  6. package/src/__tests__/audit.test.ts +877 -0
  7. package/src/__tests__/circuit-breaker.test.ts +116 -0
  8. package/src/__tests__/cli-run.test.ts +115 -0
  9. package/src/__tests__/context-manager.test.ts +502 -0
  10. package/src/__tests__/context.test.ts +242 -0
  11. package/src/__tests__/enterprise.test.ts +401 -0
  12. package/src/__tests__/generator.test.ts +433 -0
  13. package/src/__tests__/hooks.test.ts +582 -0
  14. package/src/__tests__/init.test.ts +436 -0
  15. package/src/__tests__/intent-parser.test.ts +229 -0
  16. package/src/__tests__/llm-router.test.ts +209 -0
  17. package/src/__tests__/lsp.test.ts +293 -0
  18. package/src/__tests__/modes.test.ts +336 -0
  19. package/src/__tests__/permissions.test.ts +338 -0
  20. package/src/__tests__/serve.test.ts +275 -0
  21. package/src/__tests__/sessions.test.ts +227 -0
  22. package/src/__tests__/sharing.test.ts +288 -0
  23. package/src/__tests__/snapshots.test.ts +581 -0
  24. package/src/__tests__/state-db.test.ts +334 -0
  25. package/src/__tests__/stream-with-tools.test.ts +732 -0
  26. package/src/__tests__/subagents.test.ts +176 -0
  27. package/src/__tests__/system-prompt.test.ts +169 -0
  28. package/src/__tests__/tool-converter.test.ts +256 -0
  29. package/src/__tests__/tool-schemas.test.ts +397 -0
  30. package/src/__tests__/tools.test.ts +143 -0
  31. package/src/__tests__/version.test.ts +49 -0
  32. package/src/agent/compaction-agent.ts +227 -0
  33. package/src/agent/context-manager.ts +435 -0
  34. package/src/agent/context.ts +427 -0
  35. package/src/agent/deploy-preview.ts +426 -0
  36. package/src/agent/index.ts +68 -0
  37. package/src/agent/loop.ts +717 -0
  38. package/src/agent/modes.ts +429 -0
  39. package/src/agent/permissions.ts +466 -0
  40. package/src/agent/subagents/base.ts +116 -0
  41. package/src/agent/subagents/cost.ts +51 -0
  42. package/src/agent/subagents/explore.ts +42 -0
  43. package/src/agent/subagents/general.ts +54 -0
  44. package/src/agent/subagents/index.ts +102 -0
  45. package/src/agent/subagents/infra.ts +59 -0
  46. package/src/agent/subagents/security.ts +69 -0
  47. package/src/agent/system-prompt.ts +436 -0
  48. package/src/app.ts +122 -0
  49. package/src/audit/activity-log.ts +290 -0
  50. package/src/audit/compliance-checker.ts +540 -0
  51. package/src/audit/cost-tracker.ts +318 -0
  52. package/src/audit/index.ts +23 -0
  53. package/src/audit/security-scanner.ts +596 -0
  54. package/src/auth/guard.ts +75 -0
  55. package/src/auth/index.ts +56 -0
  56. package/src/auth/oauth.ts +455 -0
  57. package/src/auth/providers.ts +470 -0
  58. package/src/auth/sso.ts +113 -0
  59. package/src/auth/store.ts +505 -0
  60. package/src/auth/types.ts +187 -0
  61. package/src/build.ts +141 -0
  62. package/src/cli/index.ts +16 -0
  63. package/src/cli/init.ts +854 -0
  64. package/src/cli/openapi-spec.ts +356 -0
  65. package/src/cli/run.ts +237 -0
  66. package/src/cli/serve-auth.ts +80 -0
  67. package/src/cli/serve.ts +462 -0
  68. package/src/cli/web.ts +67 -0
  69. package/src/cli.ts +1417 -0
  70. package/src/clients/core-engine-client.ts +227 -0
  71. package/src/clients/enterprise-client.ts +334 -0
  72. package/src/clients/generator-client.ts +351 -0
  73. package/src/clients/git-client.ts +627 -0
  74. package/src/clients/github-client.ts +410 -0
  75. package/src/clients/helm-client.ts +504 -0
  76. package/src/clients/index.ts +80 -0
  77. package/src/clients/k8s-client.ts +497 -0
  78. package/src/clients/llm-client.ts +161 -0
  79. package/src/clients/rest-client.ts +130 -0
  80. package/src/clients/service-discovery.ts +33 -0
  81. package/src/clients/terraform-client.ts +482 -0
  82. package/src/clients/tools-client.ts +1843 -0
  83. package/src/clients/ws-client.ts +115 -0
  84. package/src/commands/analyze/index.ts +352 -0
  85. package/src/commands/apply/helm.ts +473 -0
  86. package/src/commands/apply/index.ts +213 -0
  87. package/src/commands/apply/k8s.ts +454 -0
  88. package/src/commands/apply/terraform.ts +582 -0
  89. package/src/commands/ask.ts +167 -0
  90. package/src/commands/audit/index.ts +238 -0
  91. package/src/commands/auth-cloud.ts +294 -0
  92. package/src/commands/auth-list.ts +134 -0
  93. package/src/commands/auth-profile.ts +121 -0
  94. package/src/commands/auth-status.ts +141 -0
  95. package/src/commands/aws/ec2.ts +501 -0
  96. package/src/commands/aws/iam.ts +397 -0
  97. package/src/commands/aws/index.ts +133 -0
  98. package/src/commands/aws/lambda.ts +396 -0
  99. package/src/commands/aws/rds.ts +439 -0
  100. package/src/commands/aws/s3.ts +439 -0
  101. package/src/commands/aws/vpc.ts +393 -0
  102. package/src/commands/aws-discover.ts +649 -0
  103. package/src/commands/aws-terraform.ts +805 -0
  104. package/src/commands/azure/aks.ts +376 -0
  105. package/src/commands/azure/functions.ts +253 -0
  106. package/src/commands/azure/index.ts +116 -0
  107. package/src/commands/azure/storage.ts +478 -0
  108. package/src/commands/azure/vm.ts +355 -0
  109. package/src/commands/billing/index.ts +256 -0
  110. package/src/commands/chat.ts +314 -0
  111. package/src/commands/config.ts +346 -0
  112. package/src/commands/cost/cloud-cost-estimator.ts +266 -0
  113. package/src/commands/cost/estimator.ts +79 -0
  114. package/src/commands/cost/index.ts +594 -0
  115. package/src/commands/cost/parsers/terraform.ts +273 -0
  116. package/src/commands/cost/parsers/types.ts +25 -0
  117. package/src/commands/cost/pricing/aws.ts +544 -0
  118. package/src/commands/cost/pricing/azure.ts +499 -0
  119. package/src/commands/cost/pricing/gcp.ts +396 -0
  120. package/src/commands/cost/pricing/index.ts +40 -0
  121. package/src/commands/demo.ts +250 -0
  122. package/src/commands/doctor.ts +794 -0
  123. package/src/commands/drift/index.ts +439 -0
  124. package/src/commands/explain.ts +277 -0
  125. package/src/commands/feedback.ts +389 -0
  126. package/src/commands/fix.ts +324 -0
  127. package/src/commands/fs/index.ts +402 -0
  128. package/src/commands/gcp/compute.ts +325 -0
  129. package/src/commands/gcp/functions.ts +271 -0
  130. package/src/commands/gcp/gke.ts +438 -0
  131. package/src/commands/gcp/iam.ts +344 -0
  132. package/src/commands/gcp/index.ts +129 -0
  133. package/src/commands/gcp/storage.ts +284 -0
  134. package/src/commands/generate-helm.ts +1249 -0
  135. package/src/commands/generate-k8s.ts +1560 -0
  136. package/src/commands/generate-terraform.ts +1460 -0
  137. package/src/commands/gh/index.ts +863 -0
  138. package/src/commands/git/index.ts +1343 -0
  139. package/src/commands/helm/index.ts +1126 -0
  140. package/src/commands/help.ts +539 -0
  141. package/src/commands/history.ts +142 -0
  142. package/src/commands/import.ts +868 -0
  143. package/src/commands/index.ts +367 -0
  144. package/src/commands/init.ts +1046 -0
  145. package/src/commands/k8s/index.ts +1137 -0
  146. package/src/commands/login.ts +631 -0
  147. package/src/commands/logout.ts +83 -0
  148. package/src/commands/onboarding.ts +228 -0
  149. package/src/commands/plan/display.ts +279 -0
  150. package/src/commands/plan/index.ts +599 -0
  151. package/src/commands/preview.ts +452 -0
  152. package/src/commands/questionnaire.ts +1270 -0
  153. package/src/commands/resume.ts +55 -0
  154. package/src/commands/team/index.ts +346 -0
  155. package/src/commands/template.ts +232 -0
  156. package/src/commands/tf/index.ts +1034 -0
  157. package/src/commands/upgrade.ts +550 -0
  158. package/src/commands/usage/index.ts +134 -0
  159. package/src/commands/version.ts +170 -0
  160. package/src/compat/index.ts +2 -0
  161. package/src/compat/runtime.ts +12 -0
  162. package/src/compat/sqlite.ts +107 -0
  163. package/src/config/index.ts +17 -0
  164. package/src/config/manager.ts +530 -0
  165. package/src/config/safety-policy.ts +358 -0
  166. package/src/config/schema.ts +125 -0
  167. package/src/config/types.ts +527 -0
  168. package/src/context/context-db.ts +199 -0
  169. package/src/demo/index.ts +349 -0
  170. package/src/demo/scenarios/full-journey.ts +229 -0
  171. package/src/demo/scenarios/getting-started.ts +127 -0
  172. package/src/demo/scenarios/helm-release.ts +341 -0
  173. package/src/demo/scenarios/k8s-deployment.ts +194 -0
  174. package/src/demo/scenarios/terraform-vpc.ts +170 -0
  175. package/src/demo/types.ts +92 -0
  176. package/src/engine/cost-estimator.ts +438 -0
  177. package/src/engine/diagram-generator.ts +256 -0
  178. package/src/engine/drift-detector.ts +902 -0
  179. package/src/engine/executor.ts +1035 -0
  180. package/src/engine/index.ts +76 -0
  181. package/src/engine/orchestrator.ts +636 -0
  182. package/src/engine/planner.ts +720 -0
  183. package/src/engine/safety.ts +743 -0
  184. package/src/engine/verifier.ts +770 -0
  185. package/src/enterprise/audit.ts +348 -0
  186. package/src/enterprise/auth.ts +270 -0
  187. package/src/enterprise/billing.ts +822 -0
  188. package/src/enterprise/index.ts +17 -0
  189. package/src/enterprise/teams.ts +443 -0
  190. package/src/generator/best-practices.ts +1608 -0
  191. package/src/generator/helm.ts +630 -0
  192. package/src/generator/index.ts +37 -0
  193. package/src/generator/intent-parser.ts +514 -0
  194. package/src/generator/kubernetes.ts +976 -0
  195. package/src/generator/terraform.ts +1867 -0
  196. package/src/history/index.ts +8 -0
  197. package/src/history/manager.ts +322 -0
  198. package/src/history/types.ts +34 -0
  199. package/src/hooks/config.ts +432 -0
  200. package/src/hooks/engine.ts +391 -0
  201. package/src/hooks/index.ts +4 -0
  202. package/src/llm/auth-bridge.ts +198 -0
  203. package/src/llm/circuit-breaker.ts +140 -0
  204. package/src/llm/config-loader.ts +201 -0
  205. package/src/llm/cost-calculator.ts +171 -0
  206. package/src/llm/index.ts +8 -0
  207. package/src/llm/model-aliases.ts +115 -0
  208. package/src/llm/provider-registry.ts +63 -0
  209. package/src/llm/providers/anthropic.ts +433 -0
  210. package/src/llm/providers/bedrock.ts +477 -0
  211. package/src/llm/providers/google.ts +405 -0
  212. package/src/llm/providers/ollama.ts +767 -0
  213. package/src/llm/providers/openai-compatible.ts +340 -0
  214. package/src/llm/providers/openai.ts +328 -0
  215. package/src/llm/providers/openrouter.ts +338 -0
  216. package/src/llm/router.ts +1035 -0
  217. package/src/llm/types.ts +232 -0
  218. package/src/lsp/client.ts +298 -0
  219. package/src/lsp/languages.ts +116 -0
  220. package/src/lsp/manager.ts +278 -0
  221. package/src/mcp/client.ts +402 -0
  222. package/src/mcp/index.ts +5 -0
  223. package/src/mcp/manager.ts +133 -0
  224. package/src/nimbus.ts +214 -0
  225. package/src/plugins/index.ts +27 -0
  226. package/src/plugins/loader.ts +334 -0
  227. package/src/plugins/manager.ts +376 -0
  228. package/src/plugins/types.ts +284 -0
  229. package/src/scanners/cicd-scanner.ts +258 -0
  230. package/src/scanners/cloud-scanner.ts +466 -0
  231. package/src/scanners/framework-scanner.ts +469 -0
  232. package/src/scanners/iac-scanner.ts +388 -0
  233. package/src/scanners/index.ts +539 -0
  234. package/src/scanners/language-scanner.ts +276 -0
  235. package/src/scanners/package-manager-scanner.ts +277 -0
  236. package/src/scanners/types.ts +172 -0
  237. package/src/sessions/manager.ts +365 -0
  238. package/src/sessions/types.ts +44 -0
  239. package/src/sharing/sync.ts +296 -0
  240. package/src/sharing/viewer.ts +97 -0
  241. package/src/snapshots/index.ts +2 -0
  242. package/src/snapshots/manager.ts +530 -0
  243. package/src/state/artifacts.ts +147 -0
  244. package/src/state/audit.ts +137 -0
  245. package/src/state/billing.ts +240 -0
  246. package/src/state/checkpoints.ts +117 -0
  247. package/src/state/config.ts +67 -0
  248. package/src/state/conversations.ts +14 -0
  249. package/src/state/credentials.ts +154 -0
  250. package/src/state/db.ts +58 -0
  251. package/src/state/index.ts +26 -0
  252. package/src/state/messages.ts +115 -0
  253. package/src/state/projects.ts +123 -0
  254. package/src/state/schema.ts +236 -0
  255. package/src/state/sessions.ts +147 -0
  256. package/src/state/teams.ts +200 -0
  257. package/src/telemetry.ts +108 -0
  258. package/src/tools/aws-ops.ts +952 -0
  259. package/src/tools/azure-ops.ts +579 -0
  260. package/src/tools/file-ops.ts +593 -0
  261. package/src/tools/gcp-ops.ts +625 -0
  262. package/src/tools/git-ops.ts +773 -0
  263. package/src/tools/github-ops.ts +799 -0
  264. package/src/tools/helm-ops.ts +943 -0
  265. package/src/tools/index.ts +17 -0
  266. package/src/tools/k8s-ops.ts +819 -0
  267. package/src/tools/schemas/converter.ts +184 -0
  268. package/src/tools/schemas/devops.ts +612 -0
  269. package/src/tools/schemas/index.ts +73 -0
  270. package/src/tools/schemas/standard.ts +1144 -0
  271. package/src/tools/schemas/types.ts +705 -0
  272. package/src/tools/terraform-ops.ts +862 -0
  273. package/src/types/ambient.d.ts +193 -0
  274. package/src/types/config.ts +83 -0
  275. package/src/types/drift.ts +116 -0
  276. package/src/types/enterprise.ts +335 -0
  277. package/src/types/index.ts +20 -0
  278. package/src/types/plan.ts +44 -0
  279. package/src/types/request.ts +65 -0
  280. package/src/types/response.ts +54 -0
  281. package/src/types/service.ts +51 -0
  282. package/src/ui/App.tsx +997 -0
  283. package/src/ui/DeployPreview.tsx +169 -0
  284. package/src/ui/Header.tsx +68 -0
  285. package/src/ui/InputBox.tsx +350 -0
  286. package/src/ui/MessageList.tsx +585 -0
  287. package/src/ui/PermissionPrompt.tsx +151 -0
  288. package/src/ui/StatusBar.tsx +158 -0
  289. package/src/ui/ToolCallDisplay.tsx +409 -0
  290. package/src/ui/chat-ui.ts +853 -0
  291. package/src/ui/index.ts +33 -0
  292. package/src/ui/ink/index.ts +711 -0
  293. package/src/ui/streaming.ts +176 -0
  294. package/src/ui/types.ts +57 -0
  295. package/src/utils/analytics.ts +72 -0
  296. package/src/utils/cost-warning.ts +27 -0
  297. package/src/utils/env.ts +46 -0
  298. package/src/utils/errors.ts +69 -0
  299. package/src/utils/event-bus.ts +38 -0
  300. package/src/utils/index.ts +24 -0
  301. package/src/utils/logger.ts +171 -0
  302. package/src/utils/rate-limiter.ts +121 -0
  303. package/src/utils/service-auth.ts +49 -0
  304. package/src/utils/validation.ts +53 -0
  305. package/src/version.ts +4 -0
  306. package/src/watcher/index.ts +163 -0
  307. package/src/wizard/approval.ts +383 -0
  308. package/src/wizard/index.ts +25 -0
  309. package/src/wizard/prompts.ts +338 -0
  310. package/src/wizard/types.ts +171 -0
  311. package/src/wizard/ui.ts +556 -0
  312. package/src/wizard/wizard.ts +304 -0
  313. package/tsconfig.json +24 -0
@@ -0,0 +1,943 @@
1
+ /**
2
+ * Helm Operations — Embedded tool (stripped HTTP wrappers)
3
+ *
4
+ * Copied from services/helm-tools-service/src/helm/operations.ts
5
+ * Uses child_process instead of Bun.$ for portability in the embedded binary.
6
+ */
7
+
8
+ import { exec } from 'child_process';
9
+ import { promisify } from 'util';
10
+ import { logger } from '../utils';
11
+
12
+ const execAsync = promisify(exec);
13
+
14
+ export interface HelmConfig {
15
+ kubeconfig?: string;
16
+ kubeContext?: string;
17
+ namespace?: string;
18
+ }
19
+
20
+ export interface InstallOptions {
21
+ name: string;
22
+ chart: string;
23
+ namespace?: string;
24
+ values?: string;
25
+ valuesFiles?: string[];
26
+ set?: Record<string, string>;
27
+ setString?: Record<string, string>;
28
+ version?: string;
29
+ createNamespace?: boolean;
30
+ dryRun?: boolean;
31
+ wait?: boolean;
32
+ timeout?: string;
33
+ atomic?: boolean;
34
+ }
35
+
36
+ export interface UpgradeOptions {
37
+ name: string;
38
+ chart: string;
39
+ namespace?: string;
40
+ values?: string;
41
+ valuesFiles?: string[];
42
+ set?: Record<string, string>;
43
+ setString?: Record<string, string>;
44
+ version?: string;
45
+ install?: boolean;
46
+ createNamespace?: boolean;
47
+ dryRun?: boolean;
48
+ wait?: boolean;
49
+ timeout?: string;
50
+ atomic?: boolean;
51
+ reuseValues?: boolean;
52
+ resetValues?: boolean;
53
+ }
54
+
55
+ export interface UninstallOptions {
56
+ name: string;
57
+ namespace?: string;
58
+ keepHistory?: boolean;
59
+ dryRun?: boolean;
60
+ wait?: boolean;
61
+ timeout?: string;
62
+ }
63
+
64
+ export interface ListOptions {
65
+ namespace?: string;
66
+ allNamespaces?: boolean;
67
+ filter?: string;
68
+ maxResults?: number;
69
+ offset?: number;
70
+ pending?: boolean;
71
+ deployed?: boolean;
72
+ failed?: boolean;
73
+ uninstalling?: boolean;
74
+ superseded?: boolean;
75
+ }
76
+
77
+ export interface RollbackOptions {
78
+ name: string;
79
+ revision: number;
80
+ namespace?: string;
81
+ dryRun?: boolean;
82
+ wait?: boolean;
83
+ timeout?: string;
84
+ force?: boolean;
85
+ }
86
+
87
+ export interface GetValuesOptions {
88
+ name: string;
89
+ namespace?: string;
90
+ allValues?: boolean;
91
+ revision?: number;
92
+ }
93
+
94
+ export interface HistoryOptions {
95
+ name: string;
96
+ namespace?: string;
97
+ maxResults?: number;
98
+ }
99
+
100
+ export interface RepoOptions {
101
+ action: 'add' | 'remove' | 'list' | 'update';
102
+ name?: string;
103
+ url?: string;
104
+ username?: string;
105
+ password?: string;
106
+ }
107
+
108
+ export interface SearchOptions {
109
+ keyword: string;
110
+ repo?: string;
111
+ version?: string;
112
+ versions?: boolean;
113
+ regexp?: boolean;
114
+ maxResults?: number;
115
+ }
116
+
117
+ export interface ShowOptions {
118
+ chart: string;
119
+ subcommand: 'all' | 'chart' | 'readme' | 'values' | 'crds';
120
+ version?: string;
121
+ }
122
+
123
+ export interface TemplateOptions {
124
+ name: string;
125
+ chart: string;
126
+ namespace?: string;
127
+ values?: string;
128
+ valuesFiles?: string[];
129
+ set?: Record<string, string>;
130
+ setString?: Record<string, string>;
131
+ version?: string;
132
+ }
133
+
134
+ export interface CommandResult {
135
+ success: boolean;
136
+ output: string;
137
+ error?: string;
138
+ exitCode: number;
139
+ }
140
+
141
+ export interface TestOptions {
142
+ name: string;
143
+ namespace?: string;
144
+ timeout?: string;
145
+ filter?: string;
146
+ logs?: boolean;
147
+ }
148
+
149
+ export interface PackageOptions {
150
+ destination?: string;
151
+ version?: string;
152
+ appVersion?: string;
153
+ dependencyUpdate?: boolean;
154
+ }
155
+
156
+ /**
157
+ * Helm operations class wrapping helm CLI
158
+ */
159
+ export class HelmOperations {
160
+ private helmPath: string;
161
+ private kubeconfig?: string;
162
+ private kubeContext?: string;
163
+ private defaultNamespace: string;
164
+
165
+ constructor(config: HelmConfig = {}) {
166
+ this.helmPath = 'helm';
167
+ this.kubeconfig = config.kubeconfig;
168
+ this.kubeContext = config.kubeContext;
169
+ this.defaultNamespace = config.namespace || 'default';
170
+ }
171
+
172
+ /**
173
+ * Build base helm command with common flags
174
+ */
175
+ private buildBaseArgs(): string[] {
176
+ const args: string[] = [];
177
+ if (this.kubeconfig) {
178
+ args.push('--kubeconfig', this.kubeconfig);
179
+ }
180
+ if (this.kubeContext) {
181
+ args.push('--kube-context', this.kubeContext);
182
+ }
183
+ return args;
184
+ }
185
+
186
+ /**
187
+ * Execute helm command
188
+ */
189
+ private async execute(args: string[]): Promise<CommandResult> {
190
+ const baseArgs = this.buildBaseArgs();
191
+ const fullArgs = [...baseArgs, ...args];
192
+ const command = `${this.helmPath} ${fullArgs.join(' ')}`;
193
+
194
+ logger.debug(`Executing helm command: ${command}`);
195
+
196
+ try {
197
+ const result = await execAsync(command, {
198
+ maxBuffer: 10 * 1024 * 1024,
199
+ timeout: 300000,
200
+ });
201
+ return {
202
+ success: true,
203
+ output: result.stdout.trim(),
204
+ exitCode: 0,
205
+ };
206
+ } catch (error: any) {
207
+ const exitCode = error.code ?? 1;
208
+ const stderr = error.stderr?.trim() || error.message;
209
+ const stdout = error.stdout?.trim() || '';
210
+
211
+ logger.error(`helm command failed: ${command}`, { exitCode, stderr });
212
+
213
+ return {
214
+ success: false,
215
+ output: stdout,
216
+ error: stderr,
217
+ exitCode,
218
+ };
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Build set arguments from Record
224
+ */
225
+ private buildSetArgs(
226
+ set: Record<string, string> | undefined,
227
+ prefix: string = '--set'
228
+ ): string[] {
229
+ if (!set) {
230
+ return [];
231
+ }
232
+ return Object.entries(set).flatMap(([key, value]) => [prefix, `${key}=${value}`]);
233
+ }
234
+
235
+ /**
236
+ * Install a Helm chart
237
+ */
238
+ async install(options: InstallOptions): Promise<CommandResult> {
239
+ const args = ['install', options.name, options.chart];
240
+
241
+ const namespace = options.namespace || this.defaultNamespace;
242
+ args.push('-n', namespace);
243
+
244
+ if (options.createNamespace) {
245
+ args.push('--create-namespace');
246
+ }
247
+
248
+ if (options.version) {
249
+ args.push('--version', options.version);
250
+ }
251
+
252
+ if (options.values) {
253
+ args.push('-f', '-');
254
+ }
255
+
256
+ if (options.valuesFiles) {
257
+ for (const file of options.valuesFiles) {
258
+ args.push('-f', file);
259
+ }
260
+ }
261
+
262
+ args.push(...this.buildSetArgs(options.set));
263
+ args.push(...this.buildSetArgs(options.setString, '--set-string'));
264
+
265
+ if (options.dryRun) {
266
+ args.push('--dry-run');
267
+ }
268
+
269
+ if (options.wait) {
270
+ args.push('--wait');
271
+ }
272
+
273
+ if (options.timeout) {
274
+ args.push('--timeout', options.timeout);
275
+ }
276
+
277
+ if (options.atomic) {
278
+ args.push('--atomic');
279
+ }
280
+
281
+ args.push('-o', 'json');
282
+
283
+ // If values are provided as string, pipe them
284
+ if (options.values) {
285
+ const baseArgs = this.buildBaseArgs();
286
+ const fullArgs = [...baseArgs, ...args];
287
+ try {
288
+ const result = await execAsync(
289
+ `echo '${options.values.replace(/'/g, "'\\''")}' | ${this.helmPath} ${fullArgs.join(' ')}`,
290
+ { maxBuffer: 10 * 1024 * 1024, timeout: 300000 }
291
+ );
292
+ return {
293
+ success: true,
294
+ output: result.stdout.trim(),
295
+ exitCode: 0,
296
+ };
297
+ } catch (error: any) {
298
+ return {
299
+ success: false,
300
+ output: '',
301
+ error: error.stderr?.trim() || error.message,
302
+ exitCode: error.code ?? 1,
303
+ };
304
+ }
305
+ }
306
+
307
+ return this.execute(args);
308
+ }
309
+
310
+ /**
311
+ * Upgrade a Helm release
312
+ */
313
+ async upgrade(options: UpgradeOptions): Promise<CommandResult> {
314
+ const args = ['upgrade', options.name, options.chart];
315
+
316
+ const namespace = options.namespace || this.defaultNamespace;
317
+ args.push('-n', namespace);
318
+
319
+ if (options.install) {
320
+ args.push('--install');
321
+ }
322
+
323
+ if (options.createNamespace) {
324
+ args.push('--create-namespace');
325
+ }
326
+
327
+ if (options.version) {
328
+ args.push('--version', options.version);
329
+ }
330
+
331
+ if (options.values) {
332
+ args.push('-f', '-');
333
+ }
334
+
335
+ if (options.valuesFiles) {
336
+ for (const file of options.valuesFiles) {
337
+ args.push('-f', file);
338
+ }
339
+ }
340
+
341
+ args.push(...this.buildSetArgs(options.set));
342
+ args.push(...this.buildSetArgs(options.setString, '--set-string'));
343
+
344
+ if (options.reuseValues) {
345
+ args.push('--reuse-values');
346
+ }
347
+
348
+ if (options.resetValues) {
349
+ args.push('--reset-values');
350
+ }
351
+
352
+ if (options.dryRun) {
353
+ args.push('--dry-run');
354
+ }
355
+
356
+ if (options.wait) {
357
+ args.push('--wait');
358
+ }
359
+
360
+ if (options.timeout) {
361
+ args.push('--timeout', options.timeout);
362
+ }
363
+
364
+ if (options.atomic) {
365
+ args.push('--atomic');
366
+ }
367
+
368
+ args.push('-o', 'json');
369
+
370
+ // If values are provided as string, pipe them
371
+ if (options.values) {
372
+ const baseArgs = this.buildBaseArgs();
373
+ const fullArgs = [...baseArgs, ...args];
374
+ try {
375
+ const result = await execAsync(
376
+ `echo '${options.values.replace(/'/g, "'\\''")}' | ${this.helmPath} ${fullArgs.join(' ')}`,
377
+ { maxBuffer: 10 * 1024 * 1024, timeout: 300000 }
378
+ );
379
+ return {
380
+ success: true,
381
+ output: result.stdout.trim(),
382
+ exitCode: 0,
383
+ };
384
+ } catch (error: any) {
385
+ return {
386
+ success: false,
387
+ output: '',
388
+ error: error.stderr?.trim() || error.message,
389
+ exitCode: error.code ?? 1,
390
+ };
391
+ }
392
+ }
393
+
394
+ return this.execute(args);
395
+ }
396
+
397
+ /**
398
+ * Uninstall a Helm release
399
+ */
400
+ async uninstall(options: UninstallOptions): Promise<CommandResult> {
401
+ const args = ['uninstall', options.name];
402
+
403
+ const namespace = options.namespace || this.defaultNamespace;
404
+ args.push('-n', namespace);
405
+
406
+ if (options.keepHistory) {
407
+ args.push('--keep-history');
408
+ }
409
+
410
+ if (options.dryRun) {
411
+ args.push('--dry-run');
412
+ }
413
+
414
+ if (options.wait) {
415
+ args.push('--wait');
416
+ }
417
+
418
+ if (options.timeout) {
419
+ args.push('--timeout', options.timeout);
420
+ }
421
+
422
+ return this.execute(args);
423
+ }
424
+
425
+ /**
426
+ * List Helm releases
427
+ */
428
+ async list(options: ListOptions = {}): Promise<CommandResult> {
429
+ const args = ['list', '-o', 'json'];
430
+
431
+ if (options.allNamespaces) {
432
+ args.push('-A');
433
+ } else if (options.namespace) {
434
+ args.push('-n', options.namespace);
435
+ } else {
436
+ args.push('-n', this.defaultNamespace);
437
+ }
438
+
439
+ if (options.filter) {
440
+ args.push('-f', options.filter);
441
+ }
442
+
443
+ if (options.maxResults) {
444
+ args.push('-m', options.maxResults.toString());
445
+ }
446
+
447
+ if (options.offset) {
448
+ args.push('--offset', options.offset.toString());
449
+ }
450
+
451
+ if (options.pending) {
452
+ args.push('--pending');
453
+ }
454
+
455
+ if (options.deployed) {
456
+ args.push('--deployed');
457
+ }
458
+
459
+ if (options.failed) {
460
+ args.push('--failed');
461
+ }
462
+
463
+ if (options.uninstalling) {
464
+ args.push('--uninstalling');
465
+ }
466
+
467
+ if (options.superseded) {
468
+ args.push('--superseded');
469
+ }
470
+
471
+ return this.execute(args);
472
+ }
473
+
474
+ /**
475
+ * Rollback a Helm release
476
+ */
477
+ async rollback(options: RollbackOptions): Promise<CommandResult> {
478
+ const args = ['rollback', options.name, options.revision.toString()];
479
+
480
+ const namespace = options.namespace || this.defaultNamespace;
481
+ args.push('-n', namespace);
482
+
483
+ if (options.dryRun) {
484
+ args.push('--dry-run');
485
+ }
486
+
487
+ if (options.wait) {
488
+ args.push('--wait');
489
+ }
490
+
491
+ if (options.timeout) {
492
+ args.push('--timeout', options.timeout);
493
+ }
494
+
495
+ if (options.force) {
496
+ args.push('--force');
497
+ }
498
+
499
+ return this.execute(args);
500
+ }
501
+
502
+ /**
503
+ * Get values for a release
504
+ */
505
+ async getValues(options: GetValuesOptions): Promise<CommandResult> {
506
+ const args = ['get', 'values', options.name, '-o', 'yaml'];
507
+
508
+ const namespace = options.namespace || this.defaultNamespace;
509
+ args.push('-n', namespace);
510
+
511
+ if (options.allValues) {
512
+ args.push('-a');
513
+ }
514
+
515
+ if (options.revision) {
516
+ args.push('--revision', options.revision.toString());
517
+ }
518
+
519
+ return this.execute(args);
520
+ }
521
+
522
+ /**
523
+ * Get manifest for a release
524
+ */
525
+ async getManifest(name: string, namespace?: string, revision?: number): Promise<CommandResult> {
526
+ const args = ['get', 'manifest', name];
527
+
528
+ args.push('-n', namespace || this.defaultNamespace);
529
+
530
+ if (revision) {
531
+ args.push('--revision', revision.toString());
532
+ }
533
+
534
+ return this.execute(args);
535
+ }
536
+
537
+ /**
538
+ * Get hooks for a release
539
+ */
540
+ async getHooks(name: string, namespace?: string, revision?: number): Promise<CommandResult> {
541
+ const args = ['get', 'hooks', name];
542
+
543
+ args.push('-n', namespace || this.defaultNamespace);
544
+
545
+ if (revision) {
546
+ args.push('--revision', revision.toString());
547
+ }
548
+
549
+ return this.execute(args);
550
+ }
551
+
552
+ /**
553
+ * Get notes for a release
554
+ */
555
+ async getNotes(name: string, namespace?: string, revision?: number): Promise<CommandResult> {
556
+ const args = ['get', 'notes', name];
557
+
558
+ args.push('-n', namespace || this.defaultNamespace);
559
+
560
+ if (revision) {
561
+ args.push('--revision', revision.toString());
562
+ }
563
+
564
+ return this.execute(args);
565
+ }
566
+
567
+ /**
568
+ * Get release history
569
+ */
570
+ async history(options: HistoryOptions): Promise<CommandResult> {
571
+ const args = ['history', options.name, '-o', 'json'];
572
+
573
+ const namespace = options.namespace || this.defaultNamespace;
574
+ args.push('-n', namespace);
575
+
576
+ if (options.maxResults) {
577
+ args.push('-m', options.maxResults.toString());
578
+ }
579
+
580
+ return this.execute(args);
581
+ }
582
+
583
+ /**
584
+ * Get release status
585
+ */
586
+ async status(name: string, namespace?: string, revision?: number): Promise<CommandResult> {
587
+ const args = ['status', name, '-o', 'json'];
588
+
589
+ args.push('-n', namespace || this.defaultNamespace);
590
+
591
+ if (revision) {
592
+ args.push('--revision', revision.toString());
593
+ }
594
+
595
+ return this.execute(args);
596
+ }
597
+
598
+ /**
599
+ * Manage Helm repositories
600
+ */
601
+ async repo(options: RepoOptions): Promise<CommandResult> {
602
+ const args = ['repo', options.action];
603
+
604
+ switch (options.action) {
605
+ case 'add':
606
+ if (!options.name || !options.url) {
607
+ return {
608
+ success: false,
609
+ output: '',
610
+ error: 'Name and URL are required for repo add',
611
+ exitCode: 1,
612
+ };
613
+ }
614
+ args.push(options.name, options.url);
615
+ if (options.username) {
616
+ args.push('--username', options.username);
617
+ }
618
+ if (options.password) {
619
+ args.push('--password', options.password);
620
+ }
621
+ break;
622
+
623
+ case 'remove':
624
+ if (!options.name) {
625
+ return {
626
+ success: false,
627
+ output: '',
628
+ error: 'Name is required for repo remove',
629
+ exitCode: 1,
630
+ };
631
+ }
632
+ args.push(options.name);
633
+ break;
634
+
635
+ case 'list':
636
+ args.push('-o', 'json');
637
+ break;
638
+
639
+ case 'update':
640
+ // No additional args needed
641
+ break;
642
+ }
643
+
644
+ return this.execute(args);
645
+ }
646
+
647
+ /**
648
+ * Search for charts
649
+ */
650
+ async search(options: SearchOptions): Promise<CommandResult> {
651
+ const args = ['search', 'repo', options.keyword, '-o', 'json'];
652
+
653
+ if (options.version) {
654
+ args.push('--version', options.version);
655
+ }
656
+
657
+ if (options.versions) {
658
+ args.push('--versions');
659
+ }
660
+
661
+ if (options.regexp) {
662
+ args.push('--regexp');
663
+ }
664
+
665
+ if (options.maxResults) {
666
+ args.push('-m', options.maxResults.toString());
667
+ }
668
+
669
+ return this.execute(args);
670
+ }
671
+
672
+ /**
673
+ * Search hub for charts
674
+ */
675
+ async searchHub(keyword: string, maxResults?: number): Promise<CommandResult> {
676
+ const args = ['search', 'hub', keyword, '-o', 'json'];
677
+
678
+ if (maxResults) {
679
+ args.push('-m', maxResults.toString());
680
+ }
681
+
682
+ return this.execute(args);
683
+ }
684
+
685
+ /**
686
+ * Show chart information
687
+ */
688
+ async show(options: ShowOptions): Promise<CommandResult> {
689
+ const args = ['show', options.subcommand, options.chart];
690
+
691
+ if (options.version) {
692
+ args.push('--version', options.version);
693
+ }
694
+
695
+ return this.execute(args);
696
+ }
697
+
698
+ /**
699
+ * Template a chart locally
700
+ */
701
+ async template(options: TemplateOptions): Promise<CommandResult> {
702
+ const args = ['template', options.name, options.chart];
703
+
704
+ if (options.namespace) {
705
+ args.push('-n', options.namespace);
706
+ }
707
+
708
+ if (options.version) {
709
+ args.push('--version', options.version);
710
+ }
711
+
712
+ if (options.values) {
713
+ args.push('-f', '-');
714
+ }
715
+
716
+ if (options.valuesFiles) {
717
+ for (const file of options.valuesFiles) {
718
+ args.push('-f', file);
719
+ }
720
+ }
721
+
722
+ args.push(...this.buildSetArgs(options.set));
723
+ args.push(...this.buildSetArgs(options.setString, '--set-string'));
724
+
725
+ // If values are provided as string, pipe them
726
+ if (options.values) {
727
+ const baseArgs = this.buildBaseArgs();
728
+ const fullArgs = [...baseArgs, ...args];
729
+ try {
730
+ const result = await execAsync(
731
+ `echo '${options.values.replace(/'/g, "'\\''")}' | ${this.helmPath} ${fullArgs.join(' ')}`,
732
+ { maxBuffer: 10 * 1024 * 1024, timeout: 300000 }
733
+ );
734
+ return {
735
+ success: true,
736
+ output: result.stdout.trim(),
737
+ exitCode: 0,
738
+ };
739
+ } catch (error: any) {
740
+ return {
741
+ success: false,
742
+ output: '',
743
+ error: error.stderr?.trim() || error.message,
744
+ exitCode: error.code ?? 1,
745
+ };
746
+ }
747
+ }
748
+
749
+ return this.execute(args);
750
+ }
751
+
752
+ /**
753
+ * Verify Helm is installed and get version
754
+ */
755
+ async version(): Promise<CommandResult> {
756
+ return this.execute(['version', '--short']);
757
+ }
758
+
759
+ /**
760
+ * Pull a chart from a repository
761
+ */
762
+ async pull(
763
+ chart: string,
764
+ version?: string,
765
+ destination?: string,
766
+ untar?: boolean
767
+ ): Promise<CommandResult> {
768
+ const args = ['pull', chart];
769
+
770
+ if (version) {
771
+ args.push('--version', version);
772
+ }
773
+
774
+ if (destination) {
775
+ args.push('-d', destination);
776
+ }
777
+
778
+ if (untar) {
779
+ args.push('--untar');
780
+ }
781
+
782
+ return this.execute(args);
783
+ }
784
+
785
+ /**
786
+ * Lint a chart
787
+ */
788
+ async lint(chartPath: string, strict?: boolean, valuesFiles?: string[]): Promise<CommandResult> {
789
+ const args = ['lint', chartPath];
790
+
791
+ if (strict) {
792
+ args.push('--strict');
793
+ }
794
+
795
+ if (valuesFiles) {
796
+ for (const file of valuesFiles) {
797
+ args.push('-f', file);
798
+ }
799
+ }
800
+
801
+ return this.execute(args);
802
+ }
803
+
804
+ /**
805
+ * Run tests for a release
806
+ */
807
+ async test(options: TestOptions): Promise<CommandResult> {
808
+ const args = ['test', options.name];
809
+
810
+ const namespace = options.namespace || this.defaultNamespace;
811
+ args.push('-n', namespace);
812
+
813
+ if (options.timeout) {
814
+ args.push('--timeout', options.timeout);
815
+ }
816
+
817
+ if (options.filter) {
818
+ args.push('--filter', options.filter);
819
+ }
820
+
821
+ if (options.logs) {
822
+ args.push('--logs');
823
+ }
824
+
825
+ return this.execute(args);
826
+ }
827
+
828
+ /**
829
+ * Package a chart
830
+ */
831
+ async package(chartPath: string, options?: PackageOptions): Promise<CommandResult> {
832
+ const args = ['package', chartPath];
833
+
834
+ if (options?.destination) {
835
+ args.push('-d', options.destination);
836
+ }
837
+
838
+ if (options?.version) {
839
+ args.push('--version', options.version);
840
+ }
841
+
842
+ if (options?.appVersion) {
843
+ args.push('--app-version', options.appVersion);
844
+ }
845
+
846
+ if (options?.dependencyUpdate) {
847
+ args.push('--dependency-update');
848
+ }
849
+
850
+ return this.execute(args);
851
+ }
852
+
853
+ /**
854
+ * Update chart dependencies
855
+ */
856
+ async dependencyUpdate(chartPath: string): Promise<CommandResult> {
857
+ return this.execute(['dependency', 'update', chartPath]);
858
+ }
859
+
860
+ /**
861
+ * Build chart dependencies
862
+ */
863
+ async dependencyBuild(chartPath: string): Promise<CommandResult> {
864
+ return this.execute(['dependency', 'build', chartPath]);
865
+ }
866
+
867
+ /**
868
+ * List chart dependencies
869
+ */
870
+ async dependencyList(chartPath: string): Promise<CommandResult> {
871
+ return this.execute(['dependency', 'list', chartPath]);
872
+ }
873
+
874
+ /**
875
+ * Verify a chart
876
+ */
877
+ async verify(chartPath: string, keyring?: string): Promise<CommandResult> {
878
+ const args = ['verify', chartPath];
879
+
880
+ if (keyring) {
881
+ args.push('--keyring', keyring);
882
+ }
883
+
884
+ return this.execute(args);
885
+ }
886
+
887
+ /**
888
+ * Get all release information
889
+ */
890
+ async getAll(name: string, namespace?: string, revision?: number): Promise<CommandResult> {
891
+ const args = ['get', 'all', name];
892
+
893
+ args.push('-n', namespace || this.defaultNamespace);
894
+
895
+ if (revision) {
896
+ args.push('--revision', revision.toString());
897
+ }
898
+
899
+ return this.execute(args);
900
+ }
901
+
902
+ /**
903
+ * Create a new chart
904
+ */
905
+ async create(name: string, starterChart?: string): Promise<CommandResult> {
906
+ const args = ['create', name];
907
+
908
+ if (starterChart) {
909
+ args.push('--starter', starterChart);
910
+ }
911
+
912
+ return this.execute(args);
913
+ }
914
+
915
+ /**
916
+ * Push a chart to a registry
917
+ */
918
+ async push(chartPath: string, remote: string): Promise<CommandResult> {
919
+ return this.execute(['push', chartPath, remote]);
920
+ }
921
+
922
+ /**
923
+ * Login to a registry
924
+ */
925
+ async registryLogin(host: string, username: string, password: string): Promise<CommandResult> {
926
+ return this.execute([
927
+ 'registry',
928
+ 'login',
929
+ host,
930
+ '--username',
931
+ username,
932
+ '--password',
933
+ password,
934
+ ]);
935
+ }
936
+
937
+ /**
938
+ * Logout from a registry
939
+ */
940
+ async registryLogout(host: string): Promise<CommandResult> {
941
+ return this.execute(['registry', 'logout', host]);
942
+ }
943
+ }