@agents-at-scale/ark 0.1.57 → 0.1.59

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.
@@ -1,8 +1,10 @@
1
1
  import { Command } from 'commander';
2
2
  import type { ArkConfig } from '../../lib/config.js';
3
- export declare function installArk(config: ArkConfig, serviceName?: string, options?: {
3
+ export declare function installArk(config: ArkConfig, serviceNames?: string[], options?: {
4
4
  yes?: boolean;
5
5
  waitForReady?: string;
6
6
  verbose?: boolean;
7
+ arkVersion?: string;
8
+ marketplaceVersion?: string;
7
9
  }): Promise<void>;
8
10
  export declare function createInstallCommand(config: ArkConfig): Command;
@@ -10,6 +10,38 @@ import { printNextSteps } from '../../lib/nextSteps.js';
10
10
  import ora from 'ora';
11
11
  import { waitForServicesReady, } from '../../lib/waitForReady.js';
12
12
  import { parseTimeoutToSeconds } from '../../lib/timeout.js';
13
+ function isValidVersion(version) {
14
+ return /^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(version);
15
+ }
16
+ function isVersionNotFoundError(error, options) {
17
+ let errorMsg = '';
18
+ if (error && typeof error === 'object') {
19
+ const err = error;
20
+ // Check stderr first (execa captures this with pipe), then message
21
+ errorMsg = err.stderr || err.message || String(error);
22
+ }
23
+ else {
24
+ errorMsg = String(error);
25
+ }
26
+ if (options.arkVersion && errorMsg.includes(`:${options.arkVersion}: not found`)) {
27
+ return true;
28
+ }
29
+ if (options.marketplaceVersion && errorMsg.includes(`:${options.marketplaceVersion}: not found`)) {
30
+ return true;
31
+ }
32
+ return false;
33
+ }
34
+ function handleInstallError(error, service, options) {
35
+ if (isVersionNotFoundError(error, options)) {
36
+ const version = options.arkVersion || options.marketplaceVersion;
37
+ output.warning(`${service.name} version ${version} not found, skipping...`);
38
+ return true; // should continue to next service
39
+ }
40
+ // Other errors still fail
41
+ output.error(`failed to install ${service.name}`);
42
+ console.error(error);
43
+ process.exit(1);
44
+ }
13
45
  async function uninstallPrerequisites(service, verbose = false) {
14
46
  if (!service.prerequisiteUninstalls?.length)
15
47
  return;
@@ -43,14 +75,35 @@ async function checkAndCleanFailedRelease(releaseName, namespace, verbose = fals
43
75
  // Ignore errors - prerequisite may not exist
44
76
  }
45
77
  }
46
- async function installService(service, verbose = false) {
78
+ async function installService(service, verbose = false, arkVersionOverride, marketplaceVersionOverride) {
47
79
  await uninstallPrerequisites(service, verbose);
48
80
  await checkAndCleanFailedRelease(service.helmReleaseName, service.namespace, verbose);
81
+ let chartPath = service.chartPath;
82
+ // Override version for ARK core services
83
+ if (arkVersionOverride &&
84
+ chartPath.includes('ghcr.io/mckinsey/agents-at-scale-ark/charts')) {
85
+ chartPath = chartPath.replace(/:[^:]+$/, `:${arkVersionOverride}`);
86
+ }
87
+ // Override version for marketplace items
88
+ if (marketplaceVersionOverride &&
89
+ chartPath.includes('ghcr.io/mckinsey/agents-at-scale-marketplace/charts')) {
90
+ // Check if version tag exists after the last slash
91
+ const lastSlashIndex = chartPath.lastIndexOf('/');
92
+ const afterLastSlash = chartPath.slice(lastSlashIndex + 1);
93
+ if (afterLastSlash.includes(':')) {
94
+ // Replace existing version
95
+ chartPath = chartPath.replace(/:[^:/]+$/, `:${marketplaceVersionOverride}`);
96
+ }
97
+ else {
98
+ // Append version
99
+ chartPath = `${chartPath}:${marketplaceVersionOverride}`;
100
+ }
101
+ }
49
102
  const helmArgs = [
50
103
  'upgrade',
51
104
  '--install',
52
105
  service.helmReleaseName,
53
- service.chartPath,
106
+ chartPath,
54
107
  ];
55
108
  // Only add namespace flag if service has explicit namespace
56
109
  if (service.namespace) {
@@ -58,9 +111,21 @@ async function installService(service, verbose = false) {
58
111
  }
59
112
  // Add any additional install args
60
113
  helmArgs.push(...(service.installArgs || []));
61
- await execute('helm', helmArgs, { stdio: 'inherit' }, { verbose });
114
+ await execute('helm', helmArgs, {
115
+ stdout: 'inherit',
116
+ stderr: 'pipe',
117
+ }, { verbose });
62
118
  }
63
- export async function installArk(config, serviceName, options = {}) {
119
+ export async function installArk(config, serviceNames = [], options = {}) {
120
+ // Validate version strings
121
+ if (options.arkVersion && !isValidVersion(options.arkVersion)) {
122
+ output.error(`Invalid ARK version format: ${options.arkVersion}. Expected semantic versioning (e.g., 0.1.50)`);
123
+ process.exit(1);
124
+ }
125
+ if (options.marketplaceVersion && !isValidVersion(options.marketplaceVersion)) {
126
+ output.error(`Invalid marketplace version format: ${options.marketplaceVersion}. Expected semantic versioning (e.g., 0.1.7)`);
127
+ process.exit(1);
128
+ }
64
129
  // Validate that --wait-for-ready requires -y
65
130
  if (options.waitForReady && !options.yes) {
66
131
  output.error('--wait-for-ready requires -y flag for non-interactive mode');
@@ -75,69 +140,71 @@ export async function installArk(config, serviceName, options = {}) {
75
140
  // Show cluster info
76
141
  output.success(`connected to cluster: ${chalk.bold(clusterInfo.context)}`);
77
142
  console.log(); // Add blank line after cluster info
78
- // If a specific service is requested, install only that service
79
- if (serviceName) {
80
- // Check if it's a marketplace item
81
- if (isMarketplaceService(serviceName)) {
82
- const service = await getMarketplaceItem(serviceName);
83
- if (!service) {
84
- output.error(`marketplace item '${serviceName}' not found`);
85
- output.info('available marketplace items:');
86
- const marketplaceServices = await getAllMarketplaceServices();
87
- if (marketplaceServices) {
88
- for (const name of Object.keys(marketplaceServices)) {
89
- output.info(` marketplace/services/${name}`);
143
+ // If specific services are requested, install only those services
144
+ if (serviceNames.length > 0) {
145
+ for (const serviceName of serviceNames) {
146
+ // Check if it's a marketplace item
147
+ if (isMarketplaceService(serviceName)) {
148
+ const service = await getMarketplaceItem(serviceName);
149
+ if (!service) {
150
+ output.error(`marketplace item '${serviceName}' not found`);
151
+ output.info('available marketplace items:');
152
+ const marketplaceServices = await getAllMarketplaceServices();
153
+ if (marketplaceServices) {
154
+ for (const name of Object.keys(marketplaceServices)) {
155
+ output.info(` marketplace/services/${name}`);
156
+ }
90
157
  }
91
- }
92
- const marketplaceAgents = await getAllMarketplaceAgents();
93
- if (marketplaceAgents) {
94
- for (const name of Object.keys(marketplaceAgents)) {
95
- output.info(` marketplace/agents/${name}`);
158
+ const marketplaceAgents = await getAllMarketplaceAgents();
159
+ if (marketplaceAgents) {
160
+ for (const name of Object.keys(marketplaceAgents)) {
161
+ output.info(` marketplace/agents/${name}`);
162
+ }
163
+ }
164
+ const marketplaceExecutors = await getAllMarketplaceExecutors();
165
+ if (marketplaceExecutors) {
166
+ for (const name of Object.keys(marketplaceExecutors)) {
167
+ output.info(` marketplace/executors/${name}`);
168
+ }
169
+ }
170
+ if (!marketplaceServices && !marketplaceAgents && !marketplaceExecutors) {
171
+ output.warning('Marketplace unavailable');
96
172
  }
173
+ process.exit(1);
174
+ }
175
+ output.info(`installing marketplace item ${service.name}...`);
176
+ try {
177
+ await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
178
+ output.success(`${service.name} installed successfully`);
97
179
  }
98
- const marketplaceExecutors = await getAllMarketplaceExecutors();
99
- if (marketplaceExecutors) {
100
- for (const name of Object.keys(marketplaceExecutors)) {
101
- output.info(` marketplace/executors/${name}`);
180
+ catch (error) {
181
+ if (handleInstallError(error, service, options)) {
182
+ continue;
102
183
  }
103
184
  }
104
- if (!marketplaceServices && !marketplaceAgents && !marketplaceExecutors) {
105
- output.warning('Marketplace unavailable');
185
+ continue;
186
+ }
187
+ // Core ARK service
188
+ const services = getInstallableServices();
189
+ const service = Object.values(services).find((s) => s.name === serviceName);
190
+ if (!service) {
191
+ output.error(`service '${serviceName}' not found`);
192
+ output.info('available services:');
193
+ for (const s of Object.values(services)) {
194
+ output.info(` ${s.name}`);
106
195
  }
107
196
  process.exit(1);
108
197
  }
109
- output.info(`installing marketplace item ${service.name}...`);
198
+ output.info(`installing ${service.name}...`);
110
199
  try {
111
- await installService(service, options.verbose);
200
+ await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
112
201
  output.success(`${service.name} installed successfully`);
113
202
  }
114
203
  catch (error) {
115
- output.error(`failed to install ${service.name}`);
116
- console.error(error);
117
- process.exit(1);
118
- }
119
- return;
120
- }
121
- // Core ARK service
122
- const services = getInstallableServices();
123
- const service = Object.values(services).find((s) => s.name === serviceName);
124
- if (!service) {
125
- output.error(`service '${serviceName}' not found`);
126
- output.info('available services:');
127
- for (const s of Object.values(services)) {
128
- output.info(` ${s.name}`);
204
+ if (handleInstallError(error, service, options)) {
205
+ continue;
206
+ }
129
207
  }
130
- process.exit(1);
131
- }
132
- output.info(`installing ${service.name}...`);
133
- try {
134
- await installService(service, options.verbose);
135
- output.success(`${service.name} installed successfully`);
136
- }
137
- catch (error) {
138
- output.error(`failed to install ${service.name}`);
139
- console.error(error);
140
- process.exit(1);
141
208
  }
142
209
  return;
143
210
  }
@@ -264,12 +331,15 @@ export async function installArk(config, serviceName, options = {}) {
264
331
  }
265
332
  output.info(`installing ${service.name}...`);
266
333
  try {
267
- await installService(service, options.verbose);
334
+ await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
268
335
  console.log(); // Add blank line after command output
269
336
  }
270
- catch {
337
+ catch (error) {
338
+ if (handleInstallError(error, service, options)) {
339
+ console.log(); // Add blank line after warning
340
+ continue;
341
+ }
271
342
  console.log(); // Add blank line after error output
272
- process.exit(1);
273
343
  }
274
344
  }
275
345
  }
@@ -295,17 +365,20 @@ export async function installArk(config, serviceName, options = {}) {
295
365
  for (const service of Object.values(services)) {
296
366
  output.info(`installing ${service.name}...`);
297
367
  try {
298
- await installService(service, options.verbose);
368
+ await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
299
369
  console.log(); // Add blank line after command output
300
370
  }
301
- catch {
371
+ catch (error) {
372
+ if (handleInstallError(error, service, options)) {
373
+ console.log(); // Add blank line after warning
374
+ continue;
375
+ }
302
376
  console.log(); // Add blank line after error output
303
- process.exit(1);
304
377
  }
305
378
  }
306
379
  }
307
380
  // Show next steps after successful installation
308
- if (!serviceName || serviceName === 'all') {
381
+ if (serviceNames.length === 0) {
309
382
  printNextSteps();
310
383
  }
311
384
  // Wait for Ark to be ready if requested
@@ -350,12 +423,14 @@ export function createInstallCommand(config) {
350
423
  const command = new Command('install');
351
424
  command
352
425
  .description('Install ARK components using Helm')
353
- .argument('[service]', 'specific service to install, or all if omitted')
426
+ .argument('[service...]', 'specific services to install, or all if omitted')
354
427
  .option('-y, --yes', 'automatically confirm all installations')
428
+ .option('--ark-version <version>', 'ARK version to install (e.g., 0.1.50, defaults to CLI version)')
429
+ .option('--marketplace-version <version>', 'Marketplace item version to install (e.g., 0.1.5)')
355
430
  .option('--wait-for-ready <timeout>', 'wait for Ark to be ready after installation (e.g., 30s, 2m)')
356
431
  .option('-v, --verbose', 'show commands being executed')
357
- .action(async (service, options) => {
358
- await installArk(config, service, options);
432
+ .action(async (services, options) => {
433
+ await installArk(config, services, options);
359
434
  });
360
435
  return command;
361
436
  }
@@ -14,7 +14,7 @@ async function uninstallService(service, verbose = false) {
14
14
  }
15
15
  await execute('helm', helmArgs, { stdio: 'inherit' }, { verbose });
16
16
  }
17
- async function uninstallArk(config, serviceName, options = {}) {
17
+ async function uninstallArk(config, serviceNames = [], options = {}) {
18
18
  // Check cluster connectivity from config
19
19
  if (!config.clusterInfo) {
20
20
  showNoClusterError();
@@ -24,38 +24,62 @@ async function uninstallArk(config, serviceName, options = {}) {
24
24
  // Show cluster info
25
25
  output.success(`connected to cluster: ${chalk.bold(clusterInfo.context)}`);
26
26
  console.log(); // Add blank line after cluster info
27
- // If a specific service is requested, uninstall only that service
28
- if (serviceName) {
29
- // Check if it's a marketplace item
30
- if (isMarketplaceService(serviceName)) {
31
- const service = await getMarketplaceItem(serviceName);
32
- if (!service) {
33
- output.error(`marketplace item '${serviceName}' not found`);
34
- output.info('available marketplace items:');
35
- const marketplaceServices = await getAllMarketplaceServices();
36
- if (marketplaceServices) {
37
- for (const name of Object.keys(marketplaceServices)) {
38
- output.info(` marketplace/services/${name}`);
27
+ // If specific services are requested, uninstall only those services
28
+ if (serviceNames.length > 0) {
29
+ for (const serviceName of serviceNames) {
30
+ // Check if it's a marketplace item
31
+ if (isMarketplaceService(serviceName)) {
32
+ const service = await getMarketplaceItem(serviceName);
33
+ if (!service) {
34
+ output.error(`marketplace item '${serviceName}' not found`);
35
+ output.info('available marketplace items:');
36
+ const marketplaceServices = await getAllMarketplaceServices();
37
+ if (marketplaceServices) {
38
+ for (const name of Object.keys(marketplaceServices)) {
39
+ output.info(` marketplace/services/${name}`);
40
+ }
39
41
  }
40
- }
41
- const marketplaceAgents = await getAllMarketplaceAgents();
42
- if (marketplaceAgents) {
43
- for (const name of Object.keys(marketplaceAgents)) {
44
- output.info(` marketplace/agents/${name}`);
42
+ const marketplaceAgents = await getAllMarketplaceAgents();
43
+ if (marketplaceAgents) {
44
+ for (const name of Object.keys(marketplaceAgents)) {
45
+ output.info(` marketplace/agents/${name}`);
46
+ }
45
47
  }
46
- }
47
- const marketplaceExecutors = await getAllMarketplaceExecutors();
48
- if (marketplaceExecutors) {
49
- for (const name of Object.keys(marketplaceExecutors)) {
50
- output.info(` marketplace/executors/${name}`);
48
+ const marketplaceExecutors = await getAllMarketplaceExecutors();
49
+ if (marketplaceExecutors) {
50
+ for (const name of Object.keys(marketplaceExecutors)) {
51
+ output.info(` marketplace/executors/${name}`);
52
+ }
53
+ }
54
+ if (!marketplaceServices && !marketplaceAgents && !marketplaceExecutors) {
55
+ output.warning('Marketplace unavailable');
51
56
  }
57
+ process.exit(1);
52
58
  }
53
- if (!marketplaceServices && !marketplaceAgents && !marketplaceExecutors) {
54
- output.warning('Marketplace unavailable');
59
+ output.info(`uninstalling marketplace item ${service.name}...`);
60
+ try {
61
+ await uninstallService(service, options.verbose);
62
+ output.success(`${service.name} uninstalled successfully`);
63
+ }
64
+ catch (error) {
65
+ output.error(`failed to uninstall ${service.name}`);
66
+ console.error(error);
67
+ process.exit(1);
68
+ }
69
+ continue;
70
+ }
71
+ // Core ARK service
72
+ const services = getInstallableServices();
73
+ const service = Object.values(services).find((s) => s.name === serviceName);
74
+ if (!service) {
75
+ output.error(`service '${serviceName}' not found`);
76
+ output.info('available services:');
77
+ for (const s of Object.values(services)) {
78
+ output.info(` ${s.name}`);
55
79
  }
56
80
  process.exit(1);
57
81
  }
58
- output.info(`uninstalling marketplace item ${service.name}...`);
82
+ output.info(`uninstalling ${service.name}...`);
59
83
  try {
60
84
  await uninstallService(service, options.verbose);
61
85
  output.success(`${service.name} uninstalled successfully`);
@@ -65,28 +89,6 @@ async function uninstallArk(config, serviceName, options = {}) {
65
89
  console.error(error);
66
90
  process.exit(1);
67
91
  }
68
- return;
69
- }
70
- // Core ARK service
71
- const services = getInstallableServices();
72
- const service = Object.values(services).find((s) => s.name === serviceName);
73
- if (!service) {
74
- output.error(`service '${serviceName}' not found`);
75
- output.info('available services:');
76
- for (const s of Object.values(services)) {
77
- output.info(` ${s.name}`);
78
- }
79
- process.exit(1);
80
- }
81
- output.info(`uninstalling ${service.name}...`);
82
- try {
83
- await uninstallService(service, options.verbose);
84
- output.success(`${service.name} uninstalled successfully`);
85
- }
86
- catch (error) {
87
- output.error(`failed to uninstall ${service.name}`);
88
- console.error(error);
89
- process.exit(1);
90
92
  }
91
93
  return;
92
94
  }
@@ -134,11 +136,11 @@ export function createUninstallCommand(config) {
134
136
  const command = new Command('uninstall');
135
137
  command
136
138
  .description('Uninstall ARK components using Helm')
137
- .argument('[service]', 'specific service to uninstall, or all if omitted')
139
+ .argument('[service...]', 'specific services to uninstall, or all if omitted')
138
140
  .option('-y, --yes', 'automatically confirm all uninstallations')
139
141
  .option('-v, --verbose', 'show commands being executed')
140
- .action(async (service, options) => {
141
- await uninstallArk(config, service, options);
142
+ .action(async (services, options) => {
143
+ await uninstallArk(config, services, options);
142
144
  });
143
145
  return command;
144
146
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-at-scale/ark",
3
- "version": "0.1.57",
3
+ "version": "0.1.59",
4
4
  "description": "Ark CLI - Interactive terminal interface for ARK agents",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -44,7 +44,7 @@
44
44
  "dependencies": {
45
45
  "@kubernetes/client-node": "^1.3.0",
46
46
  "@modelcontextprotocol/sdk": "^1.27.1",
47
- "axios": "^1.13.5",
47
+ "axios": "^1.15.0",
48
48
  "chalk": "^4.1.2",
49
49
  "commander": "^12.1.0",
50
50
  "debug": "^4.4.1",
@@ -87,8 +87,10 @@
87
87
  "overrides": {
88
88
  "minimatch": "^10.2.3",
89
89
  "rollup": "4.59.0",
90
- "hono": "^4.12.4",
91
- "@hono/node-server": "^1.19.10",
92
- "flatted": "^3.4.2"
90
+ "hono": "^4.12.12",
91
+ "@hono/node-server": "^1.19.13",
92
+ "flatted": "^3.4.2",
93
+ "tar": "^7.5.11",
94
+ "express-rate-limit": "^8.3.0"
93
95
  }
94
96
  }
@@ -95,7 +95,7 @@ ENTRYPOINT [ "/bin/sh", "-c", "mcp-proxy --debug --port 8080 --host 0.0.0.0 --sh
95
95
  {{- end }}
96
96
 
97
97
  {{- else if eq .Values.technology "python" }}
98
- FROM python:3.11-slim
98
+ FROM python:3.11.13-slim
99
99
 
100
100
  WORKDIR /app
101
101
 
@@ -1,4 +1,4 @@
1
- FROM python:3.11-slim
1
+ FROM python:3.11.13-slim
2
2
 
3
3
  # Set working directory
4
4
  WORKDIR /app
@@ -1,4 +1,4 @@
1
- FROM python:3.12-slim
1
+ FROM python:3.12.11-slim
2
2
 
3
3
  WORKDIR /app
4
4