@agents-at-scale/ark 0.1.35-rc2 → 0.1.35

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 (215) hide show
  1. package/dist/commands/cluster/index.d.ts +1 -2
  2. package/dist/commands/cluster/index.js +5 -3
  3. package/dist/commands/completion.js +2 -159
  4. package/dist/commands/config.d.ts +3 -0
  5. package/dist/commands/config.js +321 -38
  6. package/dist/commands/generate/config.js +24 -5
  7. package/dist/commands/generate/generators/agent.js +2 -2
  8. package/dist/commands/generate/generators/mcpserver.d.ts +1 -2
  9. package/dist/commands/generate/generators/mcpserver.js +5 -26
  10. package/dist/commands/generate/generators/project.js +41 -22
  11. package/dist/commands/generate/generators/team.js +2 -2
  12. package/dist/commands/generate/index.d.ts +1 -2
  13. package/dist/commands/generate/index.js +1 -1
  14. package/dist/components/statusChecker.d.ts +23 -13
  15. package/dist/components/statusChecker.js +129 -295
  16. package/dist/config.d.ts +22 -3
  17. package/dist/config.js +161 -10
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +42 -44
  20. package/dist/lib/cluster.d.ts +1 -2
  21. package/dist/lib/cluster.js +16 -37
  22. package/dist/lib/config.d.ts +80 -28
  23. package/dist/lib/config.js +205 -70
  24. package/dist/lib/consts.d.ts +1 -0
  25. package/dist/lib/consts.js +2 -0
  26. package/dist/lib/errors.js +1 -1
  27. package/dist/lib/exec.d.ts +4 -0
  28. package/dist/lib/exec.js +11 -0
  29. package/dist/lib/types.d.ts +3 -17
  30. package/dist/ui/MainMenu.d.ts +1 -5
  31. package/dist/ui/MainMenu.js +91 -222
  32. package/dist/ui/statusFormatter.d.ts +7 -22
  33. package/dist/ui/statusFormatter.js +39 -39
  34. package/package.json +5 -17
  35. package/dist/arkServices.d.ts +0 -42
  36. package/dist/arkServices.js +0 -138
  37. package/dist/arkServices.spec.d.ts +0 -1
  38. package/dist/arkServices.spec.js +0 -24
  39. package/dist/charts/charts.d.ts +0 -5
  40. package/dist/charts/charts.js +0 -6
  41. package/dist/charts/dependencies.d.ts +0 -6
  42. package/dist/charts/dependencies.js +0 -50
  43. package/dist/charts/types.d.ts +0 -40
  44. package/dist/charts/types.js +0 -1
  45. package/dist/commands/agents/index.d.ts +0 -3
  46. package/dist/commands/agents/index.js +0 -51
  47. package/dist/commands/agents/index.spec.d.ts +0 -1
  48. package/dist/commands/agents/index.spec.js +0 -67
  49. package/dist/commands/agents/selector.d.ts +0 -8
  50. package/dist/commands/agents/selector.js +0 -53
  51. package/dist/commands/agents.d.ts +0 -2
  52. package/dist/commands/agents.js +0 -53
  53. package/dist/commands/chat/index.d.ts +0 -3
  54. package/dist/commands/chat/index.js +0 -29
  55. package/dist/commands/chat.d.ts +0 -2
  56. package/dist/commands/chat.js +0 -45
  57. package/dist/commands/cluster/get.d.ts +0 -2
  58. package/dist/commands/cluster/get.js +0 -39
  59. package/dist/commands/cluster/get.spec.d.ts +0 -1
  60. package/dist/commands/cluster/get.spec.js +0 -92
  61. package/dist/commands/cluster/index.spec.d.ts +0 -1
  62. package/dist/commands/cluster/index.spec.js +0 -24
  63. package/dist/commands/completion/index.d.ts +0 -3
  64. package/dist/commands/completion/index.js +0 -290
  65. package/dist/commands/completion/index.spec.d.ts +0 -1
  66. package/dist/commands/completion/index.spec.js +0 -34
  67. package/dist/commands/config/index.d.ts +0 -3
  68. package/dist/commands/config/index.js +0 -42
  69. package/dist/commands/config/index.spec.d.ts +0 -1
  70. package/dist/commands/config/index.spec.js +0 -78
  71. package/dist/commands/dashboard/index.d.ts +0 -4
  72. package/dist/commands/dashboard/index.js +0 -39
  73. package/dist/commands/dashboard.d.ts +0 -3
  74. package/dist/commands/dashboard.js +0 -39
  75. package/dist/commands/dev/index.d.ts +0 -3
  76. package/dist/commands/dev/index.js +0 -9
  77. package/dist/commands/dev/tool/check.d.ts +0 -2
  78. package/dist/commands/dev/tool/check.js +0 -142
  79. package/dist/commands/dev/tool/clean.d.ts +0 -2
  80. package/dist/commands/dev/tool/clean.js +0 -153
  81. package/dist/commands/dev/tool/generate.d.ts +0 -2
  82. package/dist/commands/dev/tool/generate.js +0 -28
  83. package/dist/commands/dev/tool/index.d.ts +0 -2
  84. package/dist/commands/dev/tool/index.js +0 -14
  85. package/dist/commands/dev/tool/init.d.ts +0 -2
  86. package/dist/commands/dev/tool/init.js +0 -320
  87. package/dist/commands/dev/tool/shared.d.ts +0 -5
  88. package/dist/commands/dev/tool/shared.js +0 -256
  89. package/dist/commands/dev/tool/status.d.ts +0 -2
  90. package/dist/commands/dev/tool/status.js +0 -136
  91. package/dist/commands/dev/tool-generate.spec.d.ts +0 -1
  92. package/dist/commands/dev/tool-generate.spec.js +0 -163
  93. package/dist/commands/dev/tool.d.ts +0 -2
  94. package/dist/commands/dev/tool.js +0 -559
  95. package/dist/commands/dev/tool.spec.d.ts +0 -1
  96. package/dist/commands/dev/tool.spec.js +0 -48
  97. package/dist/commands/docs/index.d.ts +0 -4
  98. package/dist/commands/docs/index.js +0 -18
  99. package/dist/commands/install/index.d.ts +0 -8
  100. package/dist/commands/install/index.js +0 -300
  101. package/dist/commands/install/index.spec.d.ts +0 -1
  102. package/dist/commands/install/index.spec.js +0 -143
  103. package/dist/commands/install.d.ts +0 -3
  104. package/dist/commands/install.js +0 -147
  105. package/dist/commands/models/create.d.ts +0 -1
  106. package/dist/commands/models/create.js +0 -213
  107. package/dist/commands/models/create.spec.d.ts +0 -1
  108. package/dist/commands/models/create.spec.js +0 -125
  109. package/dist/commands/models/index.d.ts +0 -3
  110. package/dist/commands/models/index.js +0 -60
  111. package/dist/commands/models/index.spec.d.ts +0 -1
  112. package/dist/commands/models/index.spec.js +0 -76
  113. package/dist/commands/models/selector.d.ts +0 -8
  114. package/dist/commands/models/selector.js +0 -53
  115. package/dist/commands/query/index.d.ts +0 -3
  116. package/dist/commands/query/index.js +0 -131
  117. package/dist/commands/routes/index.d.ts +0 -3
  118. package/dist/commands/routes/index.js +0 -93
  119. package/dist/commands/routes.d.ts +0 -2
  120. package/dist/commands/routes.js +0 -101
  121. package/dist/commands/status/index.d.ts +0 -4
  122. package/dist/commands/status/index.js +0 -262
  123. package/dist/commands/status.d.ts +0 -3
  124. package/dist/commands/status.js +0 -33
  125. package/dist/commands/targets/index.d.ts +0 -3
  126. package/dist/commands/targets/index.js +0 -65
  127. package/dist/commands/targets/index.spec.d.ts +0 -1
  128. package/dist/commands/targets/index.spec.js +0 -105
  129. package/dist/commands/targets.d.ts +0 -2
  130. package/dist/commands/targets.js +0 -65
  131. package/dist/commands/teams/index.d.ts +0 -3
  132. package/dist/commands/teams/index.js +0 -49
  133. package/dist/commands/teams/index.spec.d.ts +0 -1
  134. package/dist/commands/teams/index.spec.js +0 -70
  135. package/dist/commands/teams/selector.d.ts +0 -8
  136. package/dist/commands/teams/selector.js +0 -55
  137. package/dist/commands/tools/index.d.ts +0 -3
  138. package/dist/commands/tools/index.js +0 -49
  139. package/dist/commands/tools/index.spec.d.ts +0 -1
  140. package/dist/commands/tools/index.spec.js +0 -70
  141. package/dist/commands/tools/selector.d.ts +0 -8
  142. package/dist/commands/tools/selector.js +0 -53
  143. package/dist/commands/uninstall/index.d.ts +0 -3
  144. package/dist/commands/uninstall/index.js +0 -106
  145. package/dist/commands/uninstall/index.spec.d.ts +0 -1
  146. package/dist/commands/uninstall/index.spec.js +0 -125
  147. package/dist/commands/uninstall.d.ts +0 -2
  148. package/dist/commands/uninstall.js +0 -83
  149. package/dist/components/ChatUI.d.ts +0 -16
  150. package/dist/components/ChatUI.js +0 -801
  151. package/dist/components/StatusView.d.ts +0 -10
  152. package/dist/components/StatusView.js +0 -39
  153. package/dist/lib/arkApiClient.d.ts +0 -53
  154. package/dist/lib/arkApiClient.js +0 -102
  155. package/dist/lib/arkApiProxy.d.ts +0 -9
  156. package/dist/lib/arkApiProxy.js +0 -22
  157. package/dist/lib/arkServiceProxy.d.ts +0 -14
  158. package/dist/lib/arkServiceProxy.js +0 -95
  159. package/dist/lib/arkStatus.d.ts +0 -10
  160. package/dist/lib/arkStatus.js +0 -79
  161. package/dist/lib/arkStatus.spec.d.ts +0 -1
  162. package/dist/lib/arkStatus.spec.js +0 -49
  163. package/dist/lib/chatClient.d.ts +0 -33
  164. package/dist/lib/chatClient.js +0 -99
  165. package/dist/lib/cluster.spec.d.ts +0 -1
  166. package/dist/lib/cluster.spec.js +0 -338
  167. package/dist/lib/commandUtils.d.ts +0 -4
  168. package/dist/lib/commandUtils.js +0 -18
  169. package/dist/lib/commandUtils.test.d.ts +0 -1
  170. package/dist/lib/commandUtils.test.js +0 -44
  171. package/dist/lib/commands.d.ts +0 -16
  172. package/dist/lib/commands.js +0 -29
  173. package/dist/lib/commands.spec.d.ts +0 -1
  174. package/dist/lib/commands.spec.js +0 -146
  175. package/dist/lib/config.spec.d.ts +0 -1
  176. package/dist/lib/config.spec.js +0 -99
  177. package/dist/lib/config.test.d.ts +0 -1
  178. package/dist/lib/config.test.js +0 -93
  179. package/dist/lib/consts.spec.d.ts +0 -1
  180. package/dist/lib/consts.spec.js +0 -15
  181. package/dist/lib/dev/tools/analyzer.d.ts +0 -30
  182. package/dist/lib/dev/tools/analyzer.js +0 -190
  183. package/dist/lib/dev/tools/discover_tools.py +0 -392
  184. package/dist/lib/dev/tools/mcp-types.d.ts +0 -28
  185. package/dist/lib/dev/tools/mcp-types.js +0 -86
  186. package/dist/lib/dev/tools/types.d.ts +0 -50
  187. package/dist/lib/dev/tools/types.js +0 -1
  188. package/dist/lib/errors.spec.d.ts +0 -1
  189. package/dist/lib/errors.spec.js +0 -221
  190. package/dist/lib/nextSteps.d.ts +0 -4
  191. package/dist/lib/nextSteps.js +0 -20
  192. package/dist/lib/nextSteps.spec.d.ts +0 -1
  193. package/dist/lib/nextSteps.spec.js +0 -59
  194. package/dist/lib/output.d.ts +0 -36
  195. package/dist/lib/output.js +0 -89
  196. package/dist/lib/output.spec.d.ts +0 -1
  197. package/dist/lib/output.spec.js +0 -123
  198. package/dist/lib/portUtils.d.ts +0 -8
  199. package/dist/lib/portUtils.js +0 -39
  200. package/dist/lib/startup.d.ts +0 -9
  201. package/dist/lib/startup.js +0 -93
  202. package/dist/lib/startup.spec.d.ts +0 -1
  203. package/dist/lib/startup.spec.js +0 -168
  204. package/dist/types/types.d.ts +0 -40
  205. package/dist/types/types.js +0 -1
  206. package/dist/ui/AgentSelector.d.ts +0 -8
  207. package/dist/ui/AgentSelector.js +0 -53
  208. package/dist/ui/ModelSelector.d.ts +0 -8
  209. package/dist/ui/ModelSelector.js +0 -53
  210. package/dist/ui/TeamSelector.d.ts +0 -8
  211. package/dist/ui/TeamSelector.js +0 -55
  212. package/dist/ui/ToolSelector.d.ts +0 -8
  213. package/dist/ui/ToolSelector.js +0 -53
  214. package/dist/ui/statusFormatter.spec.d.ts +0 -1
  215. package/dist/ui/statusFormatter.spec.js +0 -58
@@ -1,300 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import { execute } from '../../lib/commands.js';
4
- import inquirer from 'inquirer';
5
- import { showNoClusterError } from '../../lib/startup.js';
6
- import output from '../../lib/output.js';
7
- import { getInstallableServices, arkDependencies } from '../../arkServices.js';
8
- import { isArkReady } from '../../lib/arkStatus.js';
9
- import { printNextSteps } from '../../lib/nextSteps.js';
10
- import ora from 'ora';
11
- async function installService(service, verbose = false) {
12
- const helmArgs = [
13
- 'upgrade',
14
- '--install',
15
- service.helmReleaseName,
16
- service.chartPath,
17
- ];
18
- // Only add namespace flag if service has explicit namespace
19
- if (service.namespace) {
20
- helmArgs.push('--namespace', service.namespace);
21
- }
22
- // Add any additional install args
23
- helmArgs.push(...(service.installArgs || []));
24
- await execute('helm', helmArgs, { stdio: 'inherit' }, { verbose });
25
- }
26
- export async function installArk(config, serviceName, options = {}) {
27
- // Validate that --wait-for-ready requires -y
28
- if (options.waitForReady && !options.yes) {
29
- output.error('--wait-for-ready requires -y flag for non-interactive mode');
30
- process.exit(1);
31
- }
32
- // Check cluster connectivity from config
33
- if (!config.clusterInfo) {
34
- showNoClusterError();
35
- process.exit(1);
36
- }
37
- const clusterInfo = config.clusterInfo;
38
- // Show cluster info
39
- output.success(`connected to cluster: ${chalk.bold(clusterInfo.context)}`);
40
- output.info(`type: ${clusterInfo.type}`);
41
- output.info(`namespace: ${clusterInfo.namespace}`);
42
- if (clusterInfo.ip) {
43
- output.info(`ip: ${clusterInfo.ip}`);
44
- }
45
- console.log(); // Add blank line after cluster info
46
- // If a specific service is requested, install only that service
47
- if (serviceName) {
48
- const services = getInstallableServices();
49
- const service = Object.values(services).find((s) => s.name === serviceName);
50
- if (!service) {
51
- output.error(`service '${serviceName}' not found`);
52
- output.info('available services:');
53
- for (const s of Object.values(services)) {
54
- output.info(` ${s.name}`);
55
- }
56
- process.exit(1);
57
- }
58
- output.info(`installing ${service.name}...`);
59
- try {
60
- await installService(service, options.verbose);
61
- output.success(`${service.name} installed successfully`);
62
- }
63
- catch (error) {
64
- output.error(`failed to install ${service.name}`);
65
- console.error(error);
66
- process.exit(1);
67
- }
68
- return;
69
- }
70
- // If not using -y flag, show checklist interface
71
- if (!options.yes) {
72
- console.log(chalk.cyan.bold('\nSelect components to install:'));
73
- console.log(chalk.gray('Use arrow keys to navigate, space to toggle, enter to confirm\n'));
74
- // Build choices for the checkbox prompt
75
- const allChoices = [
76
- new inquirer.Separator(chalk.bold('──── Dependencies ────')),
77
- {
78
- name: `cert-manager ${chalk.gray('- Certificate management')}`,
79
- value: 'cert-manager',
80
- checked: true,
81
- },
82
- {
83
- name: `gateway-api ${chalk.gray('- Gateway API CRDs')}`,
84
- value: 'gateway-api',
85
- checked: true,
86
- },
87
- new inquirer.Separator(chalk.bold('──── Ark Core ────')),
88
- {
89
- name: `ark-controller ${chalk.gray('- Core Ark controller')}`,
90
- value: 'ark-controller',
91
- checked: true,
92
- },
93
- new inquirer.Separator(chalk.bold('──── Ark Services ────')),
94
- {
95
- name: `ark-api ${chalk.gray('- API service')}`,
96
- value: 'ark-api',
97
- checked: true,
98
- },
99
- {
100
- name: `ark-dashboard ${chalk.gray('- Web dashboard')}`,
101
- value: 'ark-dashboard',
102
- checked: true,
103
- },
104
- {
105
- name: `ark-mcp ${chalk.gray('- MCP services')}`,
106
- value: 'ark-mcp',
107
- checked: true,
108
- },
109
- {
110
- name: `localhost-gateway ${chalk.gray('- Gateway for local access')}`,
111
- value: 'localhost-gateway',
112
- checked: true,
113
- },
114
- ];
115
- let selectedComponents = [];
116
- try {
117
- const answers = await inquirer.prompt([
118
- {
119
- type: 'checkbox',
120
- name: 'components',
121
- message: 'Components to install:',
122
- choices: allChoices,
123
- pageSize: 15,
124
- },
125
- ]);
126
- selectedComponents = answers.components;
127
- if (selectedComponents.length === 0) {
128
- output.warning('No components selected. Exiting.');
129
- process.exit(0);
130
- }
131
- }
132
- catch (error) {
133
- // Handle Ctrl-C gracefully
134
- if (error && error.name === 'ExitPromptError') {
135
- console.log('\nInstallation cancelled');
136
- process.exit(130);
137
- }
138
- throw error;
139
- }
140
- // Install dependencies if selected
141
- const shouldInstallDeps = selectedComponents.includes('cert-manager') ||
142
- selectedComponents.includes('gateway-api');
143
- // Install selected dependencies
144
- if (shouldInstallDeps) {
145
- // Always install cert-manager repo and update if installing any dependency
146
- if (selectedComponents.includes('cert-manager') ||
147
- selectedComponents.includes('gateway-api')) {
148
- for (const depKey of ['cert-manager-repo', 'helm-repo-update']) {
149
- const dep = arkDependencies[depKey];
150
- output.info(`installing ${dep.description || dep.name}...`);
151
- try {
152
- await execute(dep.command, dep.args, {
153
- stdio: 'inherit',
154
- }, { verbose: options.verbose });
155
- output.success(`${dep.name} completed`);
156
- console.log();
157
- }
158
- catch {
159
- console.log();
160
- process.exit(1);
161
- }
162
- }
163
- }
164
- // Install cert-manager if selected
165
- if (selectedComponents.includes('cert-manager')) {
166
- const dep = arkDependencies['cert-manager'];
167
- output.info(`installing ${dep.description || dep.name}...`);
168
- try {
169
- await execute(dep.command, dep.args, {
170
- stdio: 'inherit',
171
- }, { verbose: options.verbose });
172
- output.success(`${dep.name} completed`);
173
- console.log();
174
- }
175
- catch {
176
- console.log();
177
- process.exit(1);
178
- }
179
- }
180
- // Install gateway-api if selected
181
- if (selectedComponents.includes('gateway-api')) {
182
- const dep = arkDependencies['gateway-api-crds'];
183
- output.info(`installing ${dep.description || dep.name}...`);
184
- try {
185
- await execute(dep.command, dep.args, {
186
- stdio: 'inherit',
187
- }, { verbose: options.verbose });
188
- output.success(`${dep.name} completed`);
189
- console.log();
190
- }
191
- catch {
192
- console.log();
193
- process.exit(1);
194
- }
195
- }
196
- }
197
- // Install selected services
198
- const services = getInstallableServices();
199
- for (const service of Object.values(services)) {
200
- // Check if this service was selected
201
- const serviceKey = service.helmReleaseName;
202
- if (!selectedComponents.includes(serviceKey)) {
203
- continue;
204
- }
205
- output.info(`installing ${service.name}...`);
206
- try {
207
- await installService(service, options.verbose);
208
- console.log(); // Add blank line after command output
209
- }
210
- catch {
211
- // Continue with remaining services on error
212
- console.log(); // Add blank line after error output
213
- }
214
- }
215
- }
216
- else {
217
- // -y flag was used, install everything
218
- // Install all dependencies
219
- for (const dep of Object.values(arkDependencies)) {
220
- output.info(`installing ${dep.description || dep.name}...`);
221
- try {
222
- await execute(dep.command, dep.args, {
223
- stdio: 'inherit',
224
- }, { verbose: options.verbose });
225
- output.success(`${dep.name} completed`);
226
- console.log(); // Add blank line after dependency
227
- }
228
- catch {
229
- console.log(); // Add blank line after error
230
- process.exit(1);
231
- }
232
- }
233
- // Install all services
234
- const services = getInstallableServices();
235
- for (const service of Object.values(services)) {
236
- output.info(`installing ${service.name}...`);
237
- try {
238
- await installService(service, options.verbose);
239
- console.log(); // Add blank line after command output
240
- }
241
- catch {
242
- // Continue with remaining services on error
243
- console.log(); // Add blank line after error output
244
- }
245
- }
246
- }
247
- // Show next steps after successful installation
248
- if (!serviceName || serviceName === 'all') {
249
- printNextSteps();
250
- }
251
- // Wait for Ark to be ready if requested
252
- if (options.waitForReady) {
253
- // Parse timeout value (e.g., '30s', '2m', '60')
254
- const parseTimeout = (value) => {
255
- const match = value.match(/^(\d+)([sm])?$/);
256
- if (!match) {
257
- throw new Error('Invalid timeout format. Use format like 30s or 2m');
258
- }
259
- const num = parseInt(match[1], 10);
260
- const unit = match[2] || 's';
261
- return unit === 'm' ? num * 60 : num;
262
- };
263
- try {
264
- const timeoutSeconds = parseTimeout(options.waitForReady);
265
- const startTime = Date.now();
266
- const endTime = startTime + timeoutSeconds * 1000;
267
- const spinner = ora(`Waiting for Ark to be ready (timeout: ${timeoutSeconds}s)...`).start();
268
- while (Date.now() < endTime) {
269
- if (await isArkReady()) {
270
- spinner.succeed('Ark is ready!');
271
- return;
272
- }
273
- const elapsed = Math.floor((Date.now() - startTime) / 1000);
274
- spinner.text = `Waiting for Ark to be ready (${elapsed}/${timeoutSeconds}s)...`;
275
- // Wait 2 seconds before checking again
276
- await new Promise((resolve) => setTimeout(resolve, 2000));
277
- }
278
- // Timeout reached
279
- spinner.fail(`Ark did not become ready within ${timeoutSeconds} seconds`);
280
- process.exit(1);
281
- }
282
- catch (error) {
283
- output.error(`Failed to wait for ready: ${error instanceof Error ? error.message : 'Unknown error'}`);
284
- process.exit(1);
285
- }
286
- }
287
- }
288
- export function createInstallCommand(config) {
289
- const command = new Command('install');
290
- command
291
- .description('Install ARK components using Helm')
292
- .argument('[service]', 'specific service to install, or all if omitted')
293
- .option('-y, --yes', 'automatically confirm all installations')
294
- .option('--wait-for-ready <timeout>', 'wait for Ark to be ready after installation (e.g., 30s, 2m)')
295
- .option('-v, --verbose', 'show commands being executed')
296
- .action(async (service, options) => {
297
- await installArk(config, service, options);
298
- });
299
- return command;
300
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,143 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { Command } from 'commander';
3
- const mockExeca = jest.fn(() => Promise.resolve());
4
- jest.unstable_mockModule('execa', () => ({
5
- execa: mockExeca,
6
- }));
7
- const mockGetClusterInfo = jest.fn();
8
- jest.unstable_mockModule('../../lib/cluster.js', () => ({
9
- getClusterInfo: mockGetClusterInfo,
10
- }));
11
- const mockGetInstallableServices = jest.fn();
12
- const mockArkServices = {};
13
- const mockArkDependencies = {};
14
- jest.unstable_mockModule('../../arkServices.js', () => ({
15
- getInstallableServices: mockGetInstallableServices,
16
- arkServices: mockArkServices,
17
- arkDependencies: mockArkDependencies,
18
- }));
19
- const mockOutput = {
20
- error: jest.fn(),
21
- info: jest.fn(),
22
- success: jest.fn(),
23
- warning: jest.fn(),
24
- };
25
- jest.unstable_mockModule('../../lib/output.js', () => ({
26
- default: mockOutput,
27
- }));
28
- const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {
29
- throw new Error('process.exit called');
30
- }));
31
- jest.spyOn(console, 'log').mockImplementation(() => { });
32
- jest.spyOn(console, 'error').mockImplementation(() => { });
33
- const { createInstallCommand } = await import('./index.js');
34
- describe('install command', () => {
35
- const mockConfig = {
36
- clusterInfo: {
37
- context: 'test-cluster',
38
- type: 'minikube',
39
- namespace: 'default',
40
- },
41
- };
42
- beforeEach(() => {
43
- jest.clearAllMocks();
44
- mockGetClusterInfo.mockResolvedValue({
45
- context: 'test-cluster',
46
- type: 'minikube',
47
- namespace: 'default',
48
- });
49
- });
50
- it('creates command with correct structure', () => {
51
- const command = createInstallCommand(mockConfig);
52
- expect(command).toBeInstanceOf(Command);
53
- expect(command.name()).toBe('install');
54
- });
55
- it('installs single service with correct helm parameters', async () => {
56
- const mockService = {
57
- name: 'ark-api',
58
- helmReleaseName: 'ark-api',
59
- chartPath: './charts/ark-api',
60
- namespace: 'ark-system',
61
- installArgs: ['--set', 'image.tag=latest'],
62
- };
63
- mockGetInstallableServices.mockReturnValue({
64
- 'ark-api': mockService,
65
- });
66
- const command = createInstallCommand(mockConfig);
67
- await command.parseAsync(['node', 'test', 'ark-api']);
68
- expect(mockExeca).toHaveBeenCalledWith('helm', [
69
- 'upgrade',
70
- '--install',
71
- 'ark-api',
72
- './charts/ark-api',
73
- '--namespace',
74
- 'ark-system',
75
- '--set',
76
- 'image.tag=latest',
77
- ], { stdio: 'inherit' });
78
- expect(mockOutput.success).toHaveBeenCalledWith('ark-api installed successfully');
79
- });
80
- it('shows error when service not found', async () => {
81
- mockGetInstallableServices.mockReturnValue({
82
- 'ark-api': { name: 'ark-api' },
83
- 'ark-controller': { name: 'ark-controller' },
84
- });
85
- const command = createInstallCommand(mockConfig);
86
- await expect(command.parseAsync(['node', 'test', 'invalid-service'])).rejects.toThrow('process.exit called');
87
- expect(mockOutput.error).toHaveBeenCalledWith("service 'invalid-service' not found");
88
- expect(mockOutput.info).toHaveBeenCalledWith('available services:');
89
- expect(mockOutput.info).toHaveBeenCalledWith(' ark-api');
90
- expect(mockOutput.info).toHaveBeenCalledWith(' ark-controller');
91
- expect(mockExit).toHaveBeenCalledWith(1);
92
- });
93
- it('handles service without namespace (uses current context)', async () => {
94
- const mockService = {
95
- name: 'ark-dashboard',
96
- helmReleaseName: 'ark-dashboard',
97
- chartPath: './charts/ark-dashboard',
98
- // namespace is undefined - should use current context
99
- installArgs: ['--set', 'replicas=2'],
100
- };
101
- mockGetInstallableServices.mockReturnValue({
102
- 'ark-dashboard': mockService,
103
- });
104
- const command = createInstallCommand(mockConfig);
105
- await command.parseAsync(['node', 'test', 'ark-dashboard']);
106
- // Should NOT include --namespace flag
107
- expect(mockExeca).toHaveBeenCalledWith('helm', [
108
- 'upgrade',
109
- '--install',
110
- 'ark-dashboard',
111
- './charts/ark-dashboard',
112
- '--set',
113
- 'replicas=2',
114
- ], { stdio: 'inherit' });
115
- });
116
- it('handles service without installArgs', async () => {
117
- const mockService = {
118
- name: 'simple-service',
119
- helmReleaseName: 'simple-service',
120
- chartPath: './charts/simple',
121
- namespace: 'default',
122
- };
123
- mockGetInstallableServices.mockReturnValue({
124
- 'simple-service': mockService,
125
- });
126
- const command = createInstallCommand(mockConfig);
127
- await command.parseAsync(['node', 'test', 'simple-service']);
128
- expect(mockExeca).toHaveBeenCalledWith('helm', [
129
- 'upgrade',
130
- '--install',
131
- 'simple-service',
132
- './charts/simple',
133
- '--namespace',
134
- 'default',
135
- ], { stdio: 'inherit' });
136
- });
137
- it('exits when cluster not connected', async () => {
138
- mockGetClusterInfo.mockResolvedValue({ error: true });
139
- const command = createInstallCommand({});
140
- await expect(command.parseAsync(['node', 'test', 'ark-api'])).rejects.toThrow('process.exit called');
141
- expect(mockExit).toHaveBeenCalledWith(1);
142
- });
143
- });
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function installArk(): Promise<void>;
3
- export declare function createInstallCommand(): Command;
@@ -1,147 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import { execa } from 'execa';
4
- import inquirer from 'inquirer';
5
- import { isCommandAvailable } from '../lib/commandUtils.js';
6
- import { getClusterInfo } from '../lib/cluster.js';
7
- import output from '../lib/output.js';
8
- import { getInstallableServices, arkDependencies } from '../arkServices.js';
9
- import { createModel } from './models/create.js';
10
- export async function installArk() {
11
- // Check if helm is installed
12
- const helmInstalled = await isCommandAvailable('helm');
13
- if (!helmInstalled) {
14
- output.error('helm is not installed. please install helm first:');
15
- output.info('https://helm.sh/docs/intro/install/');
16
- process.exit(1);
17
- }
18
- // Check if kubectl is installed (needed for some dependencies)
19
- const kubectlInstalled = await isCommandAvailable('kubectl');
20
- if (!kubectlInstalled) {
21
- output.error('kubectl is not installed. please install kubectl first:');
22
- output.info('https://kubernetes.io/docs/tasks/tools/');
23
- process.exit(1);
24
- }
25
- // Check cluster connectivity
26
- const clusterInfo = await getClusterInfo();
27
- if (clusterInfo.error) {
28
- output.error('no kubernetes cluster detected');
29
- output.info('please ensure you have a running cluster and kubectl is configured.');
30
- output.info('');
31
- output.info('for local development, we recommend minikube:');
32
- output.info('• install: https://minikube.sigs.k8s.io/docs/start');
33
- output.info('• start cluster: minikube start');
34
- output.info('');
35
- output.info('alternatively, you can use kind or docker desktop.');
36
- process.exit(1);
37
- }
38
- // Show cluster info
39
- output.success(`connected to cluster: ${chalk.bold(clusterInfo.context)}`);
40
- output.info(`type: ${clusterInfo.type}`);
41
- output.info(`namespace: ${clusterInfo.namespace}`);
42
- if (clusterInfo.ip) {
43
- output.info(`ip: ${clusterInfo.ip}`);
44
- }
45
- console.log(); // Add blank line after cluster info
46
- // Ask about installing dependencies
47
- const { shouldInstallDeps } = await inquirer.prompt([
48
- {
49
- type: 'confirm',
50
- name: 'shouldInstallDeps',
51
- message: 'install required dependencies (cert-manager, gateway api)?',
52
- default: true,
53
- },
54
- ]);
55
- if (shouldInstallDeps) {
56
- for (const dep of Object.values(arkDependencies)) {
57
- output.info(`installing ${dep.description || dep.name}...`);
58
- try {
59
- await execa(dep.command, dep.args, {
60
- stdio: 'inherit',
61
- });
62
- output.success(`${dep.name} completed`);
63
- console.log(); // Add blank line after dependency
64
- }
65
- catch {
66
- console.log(); // Add blank line after error
67
- process.exit(1);
68
- }
69
- }
70
- }
71
- // Get installable services and iterate through them
72
- const services = getInstallableServices();
73
- for (const service of Object.values(services)) {
74
- // Ask for confirmation
75
- const { shouldInstall } = await inquirer.prompt([
76
- {
77
- type: 'confirm',
78
- name: 'shouldInstall',
79
- message: `install ${chalk.bold(service.name)}? ${service.description ? chalk.gray(`(${service.description.toLowerCase()})`) : ''}`,
80
- default: true,
81
- },
82
- ]);
83
- if (!shouldInstall) {
84
- output.warning(`skipping ${service.name}`);
85
- continue;
86
- }
87
- try {
88
- // Build helm arguments
89
- const helmArgs = [
90
- 'upgrade',
91
- '--install',
92
- service.helmReleaseName,
93
- service.chartPath,
94
- '--namespace',
95
- service.namespace,
96
- ];
97
- // Add any additional args from the service definition
98
- if (service.installArgs) {
99
- helmArgs.push(...service.installArgs);
100
- }
101
- // Run helm upgrade --install with streaming output
102
- await execa('helm', helmArgs, {
103
- stdio: 'inherit',
104
- });
105
- console.log(); // Add blank line after command output
106
- }
107
- catch {
108
- // Continue with remaining services on error
109
- console.log(); // Add blank line after error output
110
- }
111
- }
112
- // Check for default model after installing services
113
- output.info('checking for default model...');
114
- let modelExists = false;
115
- try {
116
- await execa('kubectl', ['get', 'model', 'default'], { stdio: 'pipe' });
117
- modelExists = true;
118
- output.success('default model already configured');
119
- }
120
- catch {
121
- output.warning('no default model found');
122
- }
123
- if (!modelExists) {
124
- const { shouldCreateModel } = await inquirer.prompt([
125
- {
126
- type: 'confirm',
127
- name: 'shouldCreateModel',
128
- message: 'would you like to create a default model?',
129
- default: true,
130
- },
131
- ]);
132
- if (shouldCreateModel) {
133
- await createModel('default');
134
- }
135
- else {
136
- output.warning('skipping model creation');
137
- output.info('you can create a model later using ark models create or the dashboard');
138
- }
139
- }
140
- }
141
- export function createInstallCommand() {
142
- const command = new Command('install');
143
- command.description('Install ARK components using Helm').action(async () => {
144
- await installArk();
145
- });
146
- return command;
147
- }
@@ -1 +0,0 @@
1
- export declare function createModel(modelName?: string): Promise<boolean>;