@agents-at-scale/ark 0.1.61 → 0.1.63
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.
- package/dist/arkServices.d.ts +3 -2
- package/dist/arkServices.js +8 -5
- package/dist/commands/install/index.d.ts +1 -0
- package/dist/commands/install/index.js +121 -12
- package/dist/lib/config.d.ts +14 -0
- package/dist/lib/config.js +19 -0
- package/package.json +2 -2
- package/templates/tool/uv.lock +3 -3
package/dist/arkServices.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare const arkDependencies: DependencyCollection;
|
|
|
13
13
|
*/
|
|
14
14
|
export declare const arkServices: ServiceCollection;
|
|
15
15
|
/**
|
|
16
|
-
* Get services that can be installed via Helm charts (only enabled services)
|
|
16
|
+
* Get services that can be installed via Helm charts (only enabled services).
|
|
17
|
+
* When a backend is specified, services with a non-matching requiresBackend are excluded.
|
|
17
18
|
*/
|
|
18
|
-
export declare function getInstallableServices(): ServiceCollection;
|
|
19
|
+
export declare function getInstallableServices(backend?: 'etcd' | 'postgresql'): ServiceCollection;
|
package/dist/arkServices.js
CHANGED
|
@@ -221,14 +221,17 @@ function applyConfigOverrides(defaults) {
|
|
|
221
221
|
*/
|
|
222
222
|
export const arkServices = applyConfigOverrides(defaultArkServices);
|
|
223
223
|
/**
|
|
224
|
-
* Get services that can be installed via Helm charts (only enabled services)
|
|
224
|
+
* Get services that can be installed via Helm charts (only enabled services).
|
|
225
|
+
* When a backend is specified, services with a non-matching requiresBackend are excluded.
|
|
225
226
|
*/
|
|
226
|
-
export function getInstallableServices() {
|
|
227
|
+
export function getInstallableServices(backend = 'etcd') {
|
|
227
228
|
const installable = {};
|
|
228
229
|
for (const [key, service] of Object.entries(arkServices)) {
|
|
229
|
-
if (service.enabled
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
if (!service.enabled || !service.chartPath)
|
|
231
|
+
continue;
|
|
232
|
+
if (service.requiresBackend && service.requiresBackend !== backend)
|
|
233
|
+
continue;
|
|
234
|
+
installable[key] = service;
|
|
232
235
|
}
|
|
233
236
|
return installable;
|
|
234
237
|
}
|
|
@@ -6,5 +6,6 @@ export declare function installArk(config: ArkConfig, serviceNames?: string[], o
|
|
|
6
6
|
verbose?: boolean;
|
|
7
7
|
arkVersion?: string;
|
|
8
8
|
marketplaceVersion?: string;
|
|
9
|
+
backend?: string;
|
|
9
10
|
}): Promise<void>;
|
|
10
11
|
export declare function createInstallCommand(config: ArkConfig): Command;
|
|
@@ -10,6 +10,43 @@ 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
|
+
import { runReadinessChecks } from '../../lib/readinessChecks.js';
|
|
14
|
+
function validatePostgresConfig(pg) {
|
|
15
|
+
if (!pg) {
|
|
16
|
+
throw new Error("missing 'storage.postgresql' block in .arkrc.yaml");
|
|
17
|
+
}
|
|
18
|
+
for (const key of ['host', 'user', 'passwordSecretName']) {
|
|
19
|
+
if (!pg[key]) {
|
|
20
|
+
throw new Error(`missing required field storage.postgresql.${key} in .arkrc.yaml`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return pg;
|
|
24
|
+
}
|
|
25
|
+
function backendInstallArgs(service, backend, values) {
|
|
26
|
+
if (backend === 'etcd')
|
|
27
|
+
return [];
|
|
28
|
+
if (!values)
|
|
29
|
+
return [];
|
|
30
|
+
if (service.helmReleaseName === 'ark-controller') {
|
|
31
|
+
return ['--set', 'storage.backend=postgresql'];
|
|
32
|
+
}
|
|
33
|
+
if (service.helmReleaseName === 'ark-apiserver') {
|
|
34
|
+
const args = [];
|
|
35
|
+
args.push('--set', `postgresql.host=${values.host}`);
|
|
36
|
+
if (values.port !== undefined)
|
|
37
|
+
args.push('--set', `postgresql.port=${values.port}`);
|
|
38
|
+
if (values.database)
|
|
39
|
+
args.push('--set', `postgresql.database=${values.database}`);
|
|
40
|
+
args.push('--set', `postgresql.user=${values.user}`);
|
|
41
|
+
args.push('--set', `postgresql.passwordSecretName=${values.passwordSecretName}`);
|
|
42
|
+
if (values.passwordSecretKey)
|
|
43
|
+
args.push('--set', `postgresql.passwordSecretKey=${values.passwordSecretKey}`);
|
|
44
|
+
if (values.sslMode)
|
|
45
|
+
args.push('--set', `postgresql.sslMode=${values.sslMode}`);
|
|
46
|
+
return args;
|
|
47
|
+
}
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
13
50
|
function isValidVersion(version) {
|
|
14
51
|
return /^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(version);
|
|
15
52
|
}
|
|
@@ -75,7 +112,7 @@ async function checkAndCleanFailedRelease(releaseName, namespace, verbose = fals
|
|
|
75
112
|
// Ignore errors - prerequisite may not exist
|
|
76
113
|
}
|
|
77
114
|
}
|
|
78
|
-
async function installService(service, verbose = false, arkVersionOverride, marketplaceVersionOverride) {
|
|
115
|
+
async function installService(service, verbose = false, arkVersionOverride, marketplaceVersionOverride, extraArgs) {
|
|
79
116
|
await uninstallPrerequisites(service, verbose);
|
|
80
117
|
await checkAndCleanFailedRelease(service.helmReleaseName, service.namespace, verbose);
|
|
81
118
|
let chartPath = service.chartPath;
|
|
@@ -111,6 +148,8 @@ async function installService(service, verbose = false, arkVersionOverride, mark
|
|
|
111
148
|
}
|
|
112
149
|
// Add any additional install args
|
|
113
150
|
helmArgs.push(...(service.installArgs || []));
|
|
151
|
+
if (extraArgs)
|
|
152
|
+
helmArgs.push(...extraArgs);
|
|
114
153
|
await execute('helm', helmArgs, {
|
|
115
154
|
stdout: 'inherit',
|
|
116
155
|
stderr: 'pipe',
|
|
@@ -140,6 +179,22 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
140
179
|
// Show cluster info
|
|
141
180
|
output.success(`connected to cluster: ${chalk.bold(clusterInfo.context)}`);
|
|
142
181
|
console.log(); // Add blank line after cluster info
|
|
182
|
+
const requestedBackend = options.backend ?? config.storage?.backend ?? 'etcd';
|
|
183
|
+
if (requestedBackend !== 'etcd' && requestedBackend !== 'postgresql') {
|
|
184
|
+
output.error(`Invalid backend value: ${requestedBackend}. Expected 'etcd' or 'postgresql'.`);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
const backend = requestedBackend;
|
|
188
|
+
let postgresValues;
|
|
189
|
+
if (backend === 'postgresql') {
|
|
190
|
+
try {
|
|
191
|
+
postgresValues = validatePostgresConfig(config.storage?.postgresql);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
output.error(`${err instanceof Error ? err.message : String(err)}`);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
143
198
|
// If specific services are requested, install only those services
|
|
144
199
|
if (serviceNames.length > 0) {
|
|
145
200
|
for (const serviceName of serviceNames) {
|
|
@@ -174,7 +229,7 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
174
229
|
}
|
|
175
230
|
output.info(`installing marketplace item ${service.name}...`);
|
|
176
231
|
try {
|
|
177
|
-
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
|
|
232
|
+
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion, []);
|
|
178
233
|
output.success(`${service.name} installed successfully`);
|
|
179
234
|
}
|
|
180
235
|
catch (error) {
|
|
@@ -185,7 +240,7 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
185
240
|
continue;
|
|
186
241
|
}
|
|
187
242
|
// Core ARK service
|
|
188
|
-
const services = getInstallableServices();
|
|
243
|
+
const services = getInstallableServices(backend);
|
|
189
244
|
const service = Object.values(services).find((s) => s.name === serviceName);
|
|
190
245
|
if (!service) {
|
|
191
246
|
output.error(`service '${serviceName}' not found`);
|
|
@@ -197,8 +252,26 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
197
252
|
}
|
|
198
253
|
output.info(`installing ${service.name}...`);
|
|
199
254
|
try {
|
|
200
|
-
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
|
|
255
|
+
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion, backendInstallArgs(service, backend, postgresValues));
|
|
201
256
|
output.success(`${service.name} installed successfully`);
|
|
257
|
+
// Wait for ark-apiserver to be ready before continuing to other services
|
|
258
|
+
if (service.helmReleaseName === 'ark-apiserver' && backend === 'postgresql') {
|
|
259
|
+
const spinner = ora('Waiting for ark-apiserver to be ready...').start();
|
|
260
|
+
try {
|
|
261
|
+
const results = await runReadinessChecks(120); // 2 minute timeout
|
|
262
|
+
const failed = results.find((r) => !r.passed);
|
|
263
|
+
if (failed) {
|
|
264
|
+
spinner.fail(`ark-apiserver readiness check failed: ${failed.message || 'unknown error'}`);
|
|
265
|
+
output.error('ark-apiserver is not ready. Stopping installation.');
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
spinner.succeed('ark-apiserver is ready');
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
spinner.fail('Failed to check ark-apiserver readiness');
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
202
275
|
}
|
|
203
276
|
catch (error) {
|
|
204
277
|
if (handleInstallError(error, service, options)) {
|
|
@@ -210,11 +283,19 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
210
283
|
}
|
|
211
284
|
// If not using -y flag, show checklist interface
|
|
212
285
|
if (!options.yes) {
|
|
286
|
+
const backendMatch = (s) => !s.requiresBackend || s.requiresBackend === backend;
|
|
213
287
|
const coreServices = Object.values(arkServices)
|
|
214
|
-
.filter((s) => s.category === 'core')
|
|
215
|
-
.sort((a, b) =>
|
|
288
|
+
.filter((s) => s.category === 'core' && backendMatch(s))
|
|
289
|
+
.sort((a, b) => {
|
|
290
|
+
// Ensure ark-controller is always first
|
|
291
|
+
if (a.name === 'ark-controller')
|
|
292
|
+
return -1;
|
|
293
|
+
if (b.name === 'ark-controller')
|
|
294
|
+
return 1;
|
|
295
|
+
return a.name.localeCompare(b.name);
|
|
296
|
+
});
|
|
216
297
|
const otherServices = Object.values(arkServices)
|
|
217
|
-
.filter((s) => s.category === 'service')
|
|
298
|
+
.filter((s) => s.category === 'service' && backendMatch(s))
|
|
218
299
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
219
300
|
const mandatoryServiceNames = [...coreServices, ...otherServices]
|
|
220
301
|
.filter((s) => s.mandatory)
|
|
@@ -331,7 +412,25 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
331
412
|
}
|
|
332
413
|
output.info(`installing ${service.name}...`);
|
|
333
414
|
try {
|
|
334
|
-
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
|
|
415
|
+
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion, backendInstallArgs(service, backend, postgresValues));
|
|
416
|
+
// Wait for ark-apiserver to be ready before continuing to other services
|
|
417
|
+
if (service.helmReleaseName === 'ark-apiserver' && backend === 'postgresql') {
|
|
418
|
+
const spinner = ora('Waiting for ark-apiserver to be ready...').start();
|
|
419
|
+
try {
|
|
420
|
+
const results = await runReadinessChecks(120); // 2 minute timeout
|
|
421
|
+
const failed = results.find((r) => !r.passed);
|
|
422
|
+
if (failed) {
|
|
423
|
+
spinner.fail(`ark-apiserver readiness check failed: ${failed.message || 'unknown error'}`);
|
|
424
|
+
output.error('ark-apiserver is not ready. Stopping installation.');
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
spinner.succeed('ark-apiserver is ready');
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
spinner.fail('Failed to check ark-apiserver readiness');
|
|
431
|
+
throw error;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
335
434
|
console.log(); // Add blank line after command output
|
|
336
435
|
}
|
|
337
436
|
catch (error) {
|
|
@@ -361,11 +460,19 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
361
460
|
}
|
|
362
461
|
}
|
|
363
462
|
// Install all services
|
|
364
|
-
const services = getInstallableServices();
|
|
365
|
-
|
|
463
|
+
const services = getInstallableServices(backend);
|
|
464
|
+
const sortedServices = Object.values(services).sort((a, b) => {
|
|
465
|
+
// Ensure ark-controller is always first
|
|
466
|
+
if (a.name === 'ark-controller')
|
|
467
|
+
return -1;
|
|
468
|
+
if (b.name === 'ark-controller')
|
|
469
|
+
return 1;
|
|
470
|
+
return a.name.localeCompare(b.name);
|
|
471
|
+
});
|
|
472
|
+
for (const service of sortedServices) {
|
|
366
473
|
output.info(`installing ${service.name}...`);
|
|
367
474
|
try {
|
|
368
|
-
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion);
|
|
475
|
+
await installService(service, options.verbose, options.arkVersion, options.marketplaceVersion, backendInstallArgs(service, backend, postgresValues));
|
|
369
476
|
console.log(); // Add blank line after command output
|
|
370
477
|
}
|
|
371
478
|
catch (error) {
|
|
@@ -388,7 +495,8 @@ export async function installArk(config, serviceNames = [], options = {}) {
|
|
|
388
495
|
const servicesToWait = Object.values(arkServices).filter((s) => s.enabled &&
|
|
389
496
|
s.category === 'core' &&
|
|
390
497
|
s.k8sDeploymentName &&
|
|
391
|
-
s.namespace
|
|
498
|
+
s.namespace &&
|
|
499
|
+
(!s.requiresBackend || s.requiresBackend === backend));
|
|
392
500
|
const spinner = ora(`Waiting for Ark to be ready (timeout: ${timeoutSeconds}s)...`).start();
|
|
393
501
|
const statusMap = new Map();
|
|
394
502
|
servicesToWait.forEach((s) => statusMap.set(s.name, false));
|
|
@@ -428,6 +536,7 @@ export function createInstallCommand(config) {
|
|
|
428
536
|
.option('--ark-version <version>', 'ARK version to install (e.g., 0.1.50, defaults to CLI version)')
|
|
429
537
|
.option('--marketplace-version <version>', 'Marketplace item version to install (e.g., 0.1.5)')
|
|
430
538
|
.option('--wait-for-ready <timeout>', 'wait for Ark to be ready after installation (e.g., 30s, 2m)')
|
|
539
|
+
.option('--backend <type>', "storage backend: 'etcd' (default) or 'postgresql' (overrides storage.backend in .arkrc.yaml)")
|
|
431
540
|
.option('-v, --verbose', 'show commands being executed')
|
|
432
541
|
.action(async (services, options) => {
|
|
433
542
|
await installArk(config, services, options);
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -8,6 +8,19 @@ export interface MarketplaceConfig {
|
|
|
8
8
|
repoUrl?: string;
|
|
9
9
|
registry?: string;
|
|
10
10
|
}
|
|
11
|
+
export interface PostgresStorageConfig {
|
|
12
|
+
host: string;
|
|
13
|
+
port?: number | string;
|
|
14
|
+
database?: string;
|
|
15
|
+
user: string;
|
|
16
|
+
passwordSecretName: string;
|
|
17
|
+
passwordSecretKey?: string;
|
|
18
|
+
sslMode?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface StorageConfig {
|
|
21
|
+
backend?: 'etcd' | 'postgresql';
|
|
22
|
+
postgresql?: PostgresStorageConfig;
|
|
23
|
+
}
|
|
11
24
|
export interface ArkConfig {
|
|
12
25
|
chat?: ChatConfig;
|
|
13
26
|
marketplace?: MarketplaceConfig;
|
|
@@ -15,6 +28,7 @@ export interface ArkConfig {
|
|
|
15
28
|
reusePortForwards?: boolean;
|
|
16
29
|
[serviceName: string]: Partial<ArkService> | boolean | undefined;
|
|
17
30
|
};
|
|
31
|
+
storage?: StorageConfig;
|
|
18
32
|
queryTimeout?: string;
|
|
19
33
|
defaultExportTypes?: string[];
|
|
20
34
|
clusterInfo?: ClusterInfo;
|
package/dist/lib/config.js
CHANGED
|
@@ -80,6 +80,13 @@ export function loadConfig() {
|
|
|
80
80
|
config.services.reusePortForwards =
|
|
81
81
|
process.env.ARK_SERVICES_REUSE_PORT_FORWARDS === '1';
|
|
82
82
|
}
|
|
83
|
+
if (process.env.ARK_STORAGE_BACKEND !== undefined) {
|
|
84
|
+
const backend = process.env.ARK_STORAGE_BACKEND;
|
|
85
|
+
if (backend === 'etcd' || backend === 'postgresql') {
|
|
86
|
+
config.storage = config.storage || {};
|
|
87
|
+
config.storage.backend = backend;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
83
90
|
return config;
|
|
84
91
|
}
|
|
85
92
|
/**
|
|
@@ -119,6 +126,18 @@ function mergeConfig(target, source) {
|
|
|
119
126
|
}
|
|
120
127
|
}
|
|
121
128
|
}
|
|
129
|
+
if (source.storage) {
|
|
130
|
+
target.storage = target.storage || {};
|
|
131
|
+
if (source.storage.backend !== undefined) {
|
|
132
|
+
target.storage.backend = source.storage.backend;
|
|
133
|
+
}
|
|
134
|
+
if (source.storage.postgresql) {
|
|
135
|
+
target.storage.postgresql = {
|
|
136
|
+
...target.storage.postgresql,
|
|
137
|
+
...source.storage.postgresql,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
122
141
|
if (source.queryTimeout !== undefined) {
|
|
123
142
|
target.queryTimeout = source.queryTimeout;
|
|
124
143
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agents-at-scale/ark",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.63",
|
|
4
4
|
"description": "Ark CLI - Interactive terminal interface for ARK agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"overrides": {
|
|
88
88
|
"minimatch": "^10.2.3",
|
|
89
89
|
"rollup": "4.59.0",
|
|
90
|
-
"hono": "^4.12.
|
|
90
|
+
"hono": "^4.12.18",
|
|
91
91
|
"@hono/node-server": "^1.19.13",
|
|
92
92
|
"flatted": "^3.4.2",
|
|
93
93
|
"tar": "^7.5.11",
|
package/templates/tool/uv.lock
CHANGED
|
@@ -772,11 +772,11 @@ wheels = [
|
|
|
772
772
|
|
|
773
773
|
[[package]]
|
|
774
774
|
name = "python-multipart"
|
|
775
|
-
version = "0.0.
|
|
775
|
+
version = "0.0.27"
|
|
776
776
|
source = { registry = "https://pypi.org/simple" }
|
|
777
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
777
|
+
sdist = { url = "https://files.pythonhosted.org/packages/69/9b/f23807317a113dc36e74e75eb265a02dd1a4d9082abc3c1064acd22997c4/python_multipart-0.0.27.tar.gz", hash = "sha256:9870a6a8c5a20a5bf4f07c017bd1489006ff8836cff097b6933355ee2b49b602", size = 44043, upload-time = "2026-04-27T10:51:26.649Z" }
|
|
778
778
|
wheels = [
|
|
779
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
779
|
+
{ url = "https://files.pythonhosted.org/packages/99/78/4126abcbdbd3c559d43e0db7f7b9173fc6befe45d39a2856cc0b8ec2a5a6/python_multipart-0.0.27-py3-none-any.whl", hash = "sha256:6fccfad17a27334bd0193681b369f476eda3409f17381a2d65aa7df3f7275645", size = 29254, upload-time = "2026-04-27T10:51:24.997Z" },
|
|
780
780
|
]
|
|
781
781
|
|
|
782
782
|
[[package]]
|