@vm0/cli 4.35.3 → 4.36.1
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/index.js +252 -671
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -6,8 +6,8 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
|
-
import { Command as
|
|
10
|
-
import
|
|
9
|
+
import { Command as Command24 } from "commander";
|
|
10
|
+
import chalk27 from "chalk";
|
|
11
11
|
|
|
12
12
|
// src/lib/auth.ts
|
|
13
13
|
import chalk from "chalk";
|
|
@@ -2760,7 +2760,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
|
2760
2760
|
function isValidBase64URL(data) {
|
|
2761
2761
|
if (!base64url.test(data))
|
|
2762
2762
|
return false;
|
|
2763
|
-
const base643 = data.replace(/[-_]/g, (
|
|
2763
|
+
const base643 = data.replace(/[-_]/g, (c11) => c11 === "-" ? "+" : "/");
|
|
2764
2764
|
const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
|
|
2765
2765
|
return isValidBase64(padded);
|
|
2766
2766
|
}
|
|
@@ -11672,9 +11672,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
|
|
|
11672
11672
|
ZodType.init(inst, def);
|
|
11673
11673
|
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
11674
11674
|
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
11675
|
-
const
|
|
11676
|
-
inst.minDate =
|
|
11677
|
-
inst.maxDate =
|
|
11675
|
+
const c11 = inst._zod.bag;
|
|
11676
|
+
inst.minDate = c11.minimum ? new Date(c11.minimum) : null;
|
|
11677
|
+
inst.maxDate = c11.maximum ? new Date(c11.maximum) : null;
|
|
11678
11678
|
});
|
|
11679
11679
|
function date3(params) {
|
|
11680
11680
|
return _date(ZodDate, params);
|
|
@@ -12284,11 +12284,33 @@ var volumeConfigSchema = external_exports.object({
|
|
|
12284
12284
|
name: external_exports.string().min(1, "Volume name is required"),
|
|
12285
12285
|
version: external_exports.string().min(1, "Volume version is required")
|
|
12286
12286
|
});
|
|
12287
|
+
var SUPPORTED_APPS = ["github"];
|
|
12288
|
+
var SUPPORTED_APP_TAGS = ["latest", "dev"];
|
|
12289
|
+
var appStringSchema = external_exports.string().regex(
|
|
12290
|
+
/^[a-z]+(:(?:latest|dev))?$/,
|
|
12291
|
+
"App must be in format 'app' or 'app:tag' (e.g., 'github', 'github:dev')"
|
|
12292
|
+
).refine(
|
|
12293
|
+
(val) => {
|
|
12294
|
+
const [app] = val.split(":");
|
|
12295
|
+
return SUPPORTED_APPS.includes(app);
|
|
12296
|
+
},
|
|
12297
|
+
`Unsupported app. Supported apps: ${SUPPORTED_APPS.join(", ")}`
|
|
12298
|
+
);
|
|
12287
12299
|
var agentDefinitionSchema = external_exports.object({
|
|
12288
12300
|
description: external_exports.string().optional(),
|
|
12301
|
+
/**
|
|
12302
|
+
* @deprecated Use `apps` field instead for pre-installed tools.
|
|
12303
|
+
* This field will be removed in a future version.
|
|
12304
|
+
*/
|
|
12289
12305
|
image: external_exports.string().optional(),
|
|
12290
|
-
// Optional when provider supports auto-config
|
|
12291
12306
|
provider: external_exports.string().min(1, "Provider is required"),
|
|
12307
|
+
/**
|
|
12308
|
+
* Array of pre-installed apps/tools for the agent environment.
|
|
12309
|
+
* Format: "app" or "app:tag" (e.g., "github", "github:dev", "github:latest")
|
|
12310
|
+
* Default tag is "latest" if not specified.
|
|
12311
|
+
* Currently supported apps: "github" (includes GitHub CLI)
|
|
12312
|
+
*/
|
|
12313
|
+
apps: external_exports.array(appStringSchema).optional(),
|
|
12292
12314
|
volumes: external_exports.array(external_exports.string()).optional(),
|
|
12293
12315
|
working_dir: external_exports.string().optional(),
|
|
12294
12316
|
// Optional when provider supports auto-config
|
|
@@ -13302,129 +13324,8 @@ var authContract = c6.router({
|
|
|
13302
13324
|
}
|
|
13303
13325
|
});
|
|
13304
13326
|
|
|
13305
|
-
// ../../packages/core/src/contracts/images.ts
|
|
13306
|
-
var c7 = initContract();
|
|
13307
|
-
var buildStatusSchema = external_exports.enum(["building", "ready", "error"]);
|
|
13308
|
-
var imageInfoSchema = external_exports.object({
|
|
13309
|
-
id: external_exports.string(),
|
|
13310
|
-
alias: external_exports.string(),
|
|
13311
|
-
versionId: external_exports.string().nullable(),
|
|
13312
|
-
// null for legacy images without versioning
|
|
13313
|
-
status: external_exports.string(),
|
|
13314
|
-
errorMessage: external_exports.string().nullable(),
|
|
13315
|
-
createdAt: external_exports.coerce.date(),
|
|
13316
|
-
updatedAt: external_exports.coerce.date()
|
|
13317
|
-
});
|
|
13318
|
-
var createImageRequestSchema = external_exports.object({
|
|
13319
|
-
dockerfile: external_exports.string().min(1, "dockerfile is required"),
|
|
13320
|
-
alias: external_exports.string().min(3, "alias must be at least 3 characters").max(64, "alias must be at most 64 characters").regex(
|
|
13321
|
-
/^[a-zA-Z0-9][a-zA-Z0-9-]{1,62}[a-zA-Z0-9]$/,
|
|
13322
|
-
"alias must be 3-64 characters, alphanumeric and hyphens, start/end with alphanumeric"
|
|
13323
|
-
).refine(
|
|
13324
|
-
(val) => !val.toLowerCase().startsWith("vm0-"),
|
|
13325
|
-
'alias cannot start with "vm0-" (reserved for system templates)'
|
|
13326
|
-
).transform((s) => s.toLowerCase()),
|
|
13327
|
-
deleteExisting: external_exports.boolean().optional()
|
|
13328
|
-
});
|
|
13329
|
-
var createImageResponseSchema = external_exports.object({
|
|
13330
|
-
buildId: external_exports.string(),
|
|
13331
|
-
imageId: external_exports.string(),
|
|
13332
|
-
alias: external_exports.string(),
|
|
13333
|
-
versionId: external_exports.string()
|
|
13334
|
-
// nanoid(8), unique per build
|
|
13335
|
-
});
|
|
13336
|
-
var buildStatusResponseSchema = external_exports.object({
|
|
13337
|
-
status: buildStatusSchema,
|
|
13338
|
-
logs: external_exports.array(external_exports.string()),
|
|
13339
|
-
logsOffset: external_exports.number(),
|
|
13340
|
-
error: external_exports.string().optional()
|
|
13341
|
-
});
|
|
13342
|
-
var imagesMainContract = c7.router({
|
|
13343
|
-
/**
|
|
13344
|
-
* GET /api/images
|
|
13345
|
-
* List all images for authenticated user
|
|
13346
|
-
*/
|
|
13347
|
-
list: {
|
|
13348
|
-
method: "GET",
|
|
13349
|
-
path: "/api/images",
|
|
13350
|
-
responses: {
|
|
13351
|
-
200: external_exports.object({
|
|
13352
|
-
images: external_exports.array(imageInfoSchema)
|
|
13353
|
-
}),
|
|
13354
|
-
401: apiErrorSchema,
|
|
13355
|
-
500: apiErrorSchema
|
|
13356
|
-
},
|
|
13357
|
-
summary: "List user images"
|
|
13358
|
-
},
|
|
13359
|
-
/**
|
|
13360
|
-
* POST /api/images
|
|
13361
|
-
* Create an image build task from a Dockerfile
|
|
13362
|
-
*/
|
|
13363
|
-
create: {
|
|
13364
|
-
method: "POST",
|
|
13365
|
-
path: "/api/images",
|
|
13366
|
-
body: createImageRequestSchema,
|
|
13367
|
-
responses: {
|
|
13368
|
-
202: createImageResponseSchema,
|
|
13369
|
-
400: apiErrorSchema,
|
|
13370
|
-
401: apiErrorSchema,
|
|
13371
|
-
500: apiErrorSchema
|
|
13372
|
-
},
|
|
13373
|
-
summary: "Create image build"
|
|
13374
|
-
}
|
|
13375
|
-
});
|
|
13376
|
-
var imagesByIdContract = c7.router({
|
|
13377
|
-
/**
|
|
13378
|
-
* DELETE /api/images/:imageId
|
|
13379
|
-
* Delete an image by ID
|
|
13380
|
-
*/
|
|
13381
|
-
delete: {
|
|
13382
|
-
method: "DELETE",
|
|
13383
|
-
path: "/api/images/:imageId",
|
|
13384
|
-
pathParams: external_exports.object({
|
|
13385
|
-
imageId: external_exports.string().min(1, "imageId is required")
|
|
13386
|
-
}),
|
|
13387
|
-
responses: {
|
|
13388
|
-
200: external_exports.object({
|
|
13389
|
-
deleted: external_exports.boolean()
|
|
13390
|
-
}),
|
|
13391
|
-
400: apiErrorSchema,
|
|
13392
|
-
401: apiErrorSchema,
|
|
13393
|
-
403: apiErrorSchema,
|
|
13394
|
-
404: apiErrorSchema,
|
|
13395
|
-
500: apiErrorSchema
|
|
13396
|
-
},
|
|
13397
|
-
summary: "Delete image"
|
|
13398
|
-
}
|
|
13399
|
-
});
|
|
13400
|
-
var imageBuildsContract = c7.router({
|
|
13401
|
-
/**
|
|
13402
|
-
* GET /api/images/:imageId/builds/:buildId
|
|
13403
|
-
* Query build status with incremental logs
|
|
13404
|
-
*/
|
|
13405
|
-
getStatus: {
|
|
13406
|
-
method: "GET",
|
|
13407
|
-
path: "/api/images/:imageId/builds/:buildId",
|
|
13408
|
-
pathParams: external_exports.object({
|
|
13409
|
-
imageId: external_exports.string().min(1, "imageId is required"),
|
|
13410
|
-
buildId: external_exports.string().min(1, "buildId is required")
|
|
13411
|
-
}),
|
|
13412
|
-
query: external_exports.object({
|
|
13413
|
-
logsOffset: external_exports.coerce.number().int().min(0).optional().default(0)
|
|
13414
|
-
}),
|
|
13415
|
-
responses: {
|
|
13416
|
-
200: buildStatusResponseSchema,
|
|
13417
|
-
400: apiErrorSchema,
|
|
13418
|
-
401: apiErrorSchema,
|
|
13419
|
-
404: apiErrorSchema,
|
|
13420
|
-
500: apiErrorSchema
|
|
13421
|
-
},
|
|
13422
|
-
summary: "Get build status"
|
|
13423
|
-
}
|
|
13424
|
-
});
|
|
13425
|
-
|
|
13426
13327
|
// ../../packages/core/src/contracts/cron.ts
|
|
13427
|
-
var
|
|
13328
|
+
var c7 = initContract();
|
|
13428
13329
|
var cleanupResultSchema = external_exports.object({
|
|
13429
13330
|
runId: external_exports.string(),
|
|
13430
13331
|
sandboxId: external_exports.string().nullable(),
|
|
@@ -13436,7 +13337,7 @@ var cleanupResponseSchema = external_exports.object({
|
|
|
13436
13337
|
errors: external_exports.number(),
|
|
13437
13338
|
results: external_exports.array(cleanupResultSchema)
|
|
13438
13339
|
});
|
|
13439
|
-
var cronCleanupSandboxesContract =
|
|
13340
|
+
var cronCleanupSandboxesContract = c7.router({
|
|
13440
13341
|
/**
|
|
13441
13342
|
* GET /api/cron/cleanup-sandboxes
|
|
13442
13343
|
* Cron job to cleanup sandboxes that have stopped sending heartbeats
|
|
@@ -13468,7 +13369,7 @@ var proxyErrorSchema = external_exports.object({
|
|
|
13468
13369
|
});
|
|
13469
13370
|
|
|
13470
13371
|
// ../../packages/core/src/contracts/scopes.ts
|
|
13471
|
-
var
|
|
13372
|
+
var c8 = initContract();
|
|
13472
13373
|
var scopeTypeSchema = external_exports.enum(["personal", "organization", "system"]);
|
|
13473
13374
|
var scopeSlugSchema = external_exports.string().min(3, "Scope slug must be at least 3 characters").max(64, "Scope slug must be at most 64 characters").regex(
|
|
13474
13375
|
/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]{1,2}$/,
|
|
@@ -13493,7 +13394,7 @@ var updateScopeRequestSchema = external_exports.object({
|
|
|
13493
13394
|
slug: scopeSlugSchema,
|
|
13494
13395
|
force: external_exports.boolean().optional().default(false)
|
|
13495
13396
|
});
|
|
13496
|
-
var scopeContract =
|
|
13397
|
+
var scopeContract = c8.router({
|
|
13497
13398
|
/**
|
|
13498
13399
|
* GET /api/scope
|
|
13499
13400
|
* Get current user's scope
|
|
@@ -13548,7 +13449,7 @@ var scopeContract = c9.router({
|
|
|
13548
13449
|
});
|
|
13549
13450
|
|
|
13550
13451
|
// ../../packages/core/src/contracts/sessions.ts
|
|
13551
|
-
var
|
|
13452
|
+
var c9 = initContract();
|
|
13552
13453
|
var sessionResponseSchema = external_exports.object({
|
|
13553
13454
|
id: external_exports.string(),
|
|
13554
13455
|
agentComposeId: external_exports.string(),
|
|
@@ -13582,7 +13483,7 @@ var checkpointResponseSchema = external_exports.object({
|
|
|
13582
13483
|
volumeVersionsSnapshot: volumeVersionsSnapshotSchema2.nullable(),
|
|
13583
13484
|
createdAt: external_exports.string()
|
|
13584
13485
|
});
|
|
13585
|
-
var sessionsByIdContract =
|
|
13486
|
+
var sessionsByIdContract = c9.router({
|
|
13586
13487
|
/**
|
|
13587
13488
|
* GET /api/agent/sessions/:id
|
|
13588
13489
|
* Get session by ID
|
|
@@ -13602,7 +13503,7 @@ var sessionsByIdContract = c10.router({
|
|
|
13602
13503
|
summary: "Get session by ID"
|
|
13603
13504
|
}
|
|
13604
13505
|
});
|
|
13605
|
-
var checkpointsByIdContract =
|
|
13506
|
+
var checkpointsByIdContract = c9.router({
|
|
13606
13507
|
/**
|
|
13607
13508
|
* GET /api/agent/checkpoints/:id
|
|
13608
13509
|
* Get checkpoint by ID
|
|
@@ -13624,7 +13525,7 @@ var checkpointsByIdContract = c10.router({
|
|
|
13624
13525
|
});
|
|
13625
13526
|
|
|
13626
13527
|
// ../../packages/core/src/contracts/runners.ts
|
|
13627
|
-
var
|
|
13528
|
+
var c10 = initContract();
|
|
13628
13529
|
var runnerGroupSchema = external_exports.string().regex(
|
|
13629
13530
|
/^[a-z0-9-]+\/[a-z0-9-]+$/,
|
|
13630
13531
|
"Runner group must be in scope/name format (e.g., acme/production)"
|
|
@@ -13637,7 +13538,7 @@ var jobSchema = external_exports.object({
|
|
|
13637
13538
|
secretNames: external_exports.array(external_exports.string()).nullable(),
|
|
13638
13539
|
checkpointId: external_exports.string().uuid().nullable()
|
|
13639
13540
|
});
|
|
13640
|
-
var runnersPollContract =
|
|
13541
|
+
var runnersPollContract = c10.router({
|
|
13641
13542
|
poll: {
|
|
13642
13543
|
method: "POST",
|
|
13643
13544
|
path: "/api/runners/poll",
|
|
@@ -13699,7 +13600,7 @@ var executionContextSchema = external_exports.object({
|
|
|
13699
13600
|
secretValues: external_exports.array(external_exports.string()).nullable(),
|
|
13700
13601
|
cliAgentType: external_exports.string()
|
|
13701
13602
|
});
|
|
13702
|
-
var runnersJobClaimContract =
|
|
13603
|
+
var runnersJobClaimContract = c10.router({
|
|
13703
13604
|
claim: {
|
|
13704
13605
|
method: "POST",
|
|
13705
13606
|
path: "/api/runners/jobs/:id/claim",
|
|
@@ -13740,7 +13641,7 @@ function getLegacySystemTemplateWarning(legacyFormat) {
|
|
|
13740
13641
|
return `Warning: "${legacyFormat}" format is deprecated. Use "vm0/codex:dev" instead.`;
|
|
13741
13642
|
}
|
|
13742
13643
|
if (legacyFormat.startsWith("vm0-github-cli")) {
|
|
13743
|
-
return `Warning: "${legacyFormat}" is deprecated
|
|
13644
|
+
return `Warning: "${legacyFormat}" is deprecated. Use "apps: [github]" in vm0.yaml instead.`;
|
|
13744
13645
|
}
|
|
13745
13646
|
return `Warning: "${legacyFormat}" format is deprecated.`;
|
|
13746
13647
|
}
|
|
@@ -13748,12 +13649,6 @@ function isLegacySystemTemplate(reference) {
|
|
|
13748
13649
|
return reference.startsWith("vm0-");
|
|
13749
13650
|
}
|
|
13750
13651
|
|
|
13751
|
-
// ../../packages/core/src/version-id.ts
|
|
13752
|
-
var VERSION_ID_DISPLAY_LENGTH = 8;
|
|
13753
|
-
function formatVersionIdForDisplay(versionId) {
|
|
13754
|
-
return versionId.slice(0, VERSION_ID_DISPLAY_LENGTH);
|
|
13755
|
-
}
|
|
13756
|
-
|
|
13757
13652
|
// ../../packages/core/src/storage-names.ts
|
|
13758
13653
|
function getInstructionsStorageName(agentName) {
|
|
13759
13654
|
return `agent-instructions@${agentName}`;
|
|
@@ -14260,9 +14155,43 @@ function getProviderDefaults(provider) {
|
|
|
14260
14155
|
function isProviderSupported(provider) {
|
|
14261
14156
|
return provider in PROVIDER_DEFAULTS;
|
|
14262
14157
|
}
|
|
14263
|
-
|
|
14158
|
+
var PROVIDER_APPS_IMAGES = {
|
|
14159
|
+
"claude-code": {
|
|
14160
|
+
github: {
|
|
14161
|
+
production: "vm0/claude-code-github:latest",
|
|
14162
|
+
development: "vm0/claude-code-github:dev"
|
|
14163
|
+
}
|
|
14164
|
+
},
|
|
14165
|
+
codex: {
|
|
14166
|
+
github: {
|
|
14167
|
+
production: "vm0/codex-github:latest",
|
|
14168
|
+
development: "vm0/codex-github:dev"
|
|
14169
|
+
}
|
|
14170
|
+
}
|
|
14171
|
+
};
|
|
14172
|
+
function parseAppString(appString) {
|
|
14173
|
+
const [app, tag] = appString.split(":");
|
|
14174
|
+
return {
|
|
14175
|
+
app: app ?? appString,
|
|
14176
|
+
tag: tag === "dev" ? "dev" : "latest"
|
|
14177
|
+
};
|
|
14178
|
+
}
|
|
14179
|
+
function getDefaultImageWithApps(provider, apps) {
|
|
14264
14180
|
const defaults = PROVIDER_DEFAULTS[provider];
|
|
14265
14181
|
if (!defaults) return void 0;
|
|
14182
|
+
if (apps && apps.length > 0) {
|
|
14183
|
+
const providerApps = PROVIDER_APPS_IMAGES[provider];
|
|
14184
|
+
if (providerApps) {
|
|
14185
|
+
const firstApp = apps[0];
|
|
14186
|
+
if (firstApp) {
|
|
14187
|
+
const { app, tag } = parseAppString(firstApp);
|
|
14188
|
+
const appImage = providerApps[app];
|
|
14189
|
+
if (appImage) {
|
|
14190
|
+
return tag === "dev" ? appImage.development : appImage.production;
|
|
14191
|
+
}
|
|
14192
|
+
}
|
|
14193
|
+
}
|
|
14194
|
+
}
|
|
14266
14195
|
const isDevelopment = process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test";
|
|
14267
14196
|
return isDevelopment ? defaults.image.development : defaults.image.production;
|
|
14268
14197
|
}
|
|
@@ -14459,6 +14388,41 @@ function validateAgentCompose(config2) {
|
|
|
14459
14388
|
}
|
|
14460
14389
|
}
|
|
14461
14390
|
}
|
|
14391
|
+
if (agent.apps !== void 0) {
|
|
14392
|
+
if (!Array.isArray(agent.apps)) {
|
|
14393
|
+
return {
|
|
14394
|
+
valid: false,
|
|
14395
|
+
error: "agent.apps must be an array of strings"
|
|
14396
|
+
};
|
|
14397
|
+
}
|
|
14398
|
+
for (const appEntry of agent.apps) {
|
|
14399
|
+
if (typeof appEntry !== "string") {
|
|
14400
|
+
return {
|
|
14401
|
+
valid: false,
|
|
14402
|
+
error: "Each entry in apps must be a string"
|
|
14403
|
+
};
|
|
14404
|
+
}
|
|
14405
|
+
const [appName, tag] = appEntry.split(":");
|
|
14406
|
+
if (!appName) {
|
|
14407
|
+
return {
|
|
14408
|
+
valid: false,
|
|
14409
|
+
error: `Invalid app format: "${appEntry}". Expected "app" or "app:tag"`
|
|
14410
|
+
};
|
|
14411
|
+
}
|
|
14412
|
+
if (!SUPPORTED_APPS.includes(appName)) {
|
|
14413
|
+
return {
|
|
14414
|
+
valid: false,
|
|
14415
|
+
error: `Invalid app: "${appName}". Supported apps: ${SUPPORTED_APPS.join(", ")}`
|
|
14416
|
+
};
|
|
14417
|
+
}
|
|
14418
|
+
if (tag !== void 0 && !SUPPORTED_APP_TAGS.includes(tag)) {
|
|
14419
|
+
return {
|
|
14420
|
+
valid: false,
|
|
14421
|
+
error: `Invalid app tag: "${tag}". Supported tags: ${SUPPORTED_APP_TAGS.join(", ")}`
|
|
14422
|
+
};
|
|
14423
|
+
}
|
|
14424
|
+
}
|
|
14425
|
+
}
|
|
14462
14426
|
const agentVolumes = agent.volumes;
|
|
14463
14427
|
if (agentVolumes && Array.isArray(agentVolumes) && agentVolumes.length > 0) {
|
|
14464
14428
|
const volumesSection = cfg.volumes;
|
|
@@ -15022,9 +14986,14 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
15022
14986
|
for (const [name, agentConfig] of Object.entries(agentsConfig)) {
|
|
15023
14987
|
const image = agentConfig.image;
|
|
15024
14988
|
if (image) {
|
|
14989
|
+
console.log(
|
|
14990
|
+
chalk2.yellow(
|
|
14991
|
+
`\u26A0 Agent "${name}": 'image' field is deprecated. Use 'apps' field for pre-installed tools.`
|
|
14992
|
+
)
|
|
14993
|
+
);
|
|
15025
14994
|
const warning = getLegacySystemTemplateWarning(image);
|
|
15026
14995
|
if (warning) {
|
|
15027
|
-
console.log(chalk2.yellow(
|
|
14996
|
+
console.log(chalk2.yellow(` ${warning}`));
|
|
15028
14997
|
}
|
|
15029
14998
|
}
|
|
15030
14999
|
}
|
|
@@ -15036,7 +15005,11 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
15036
15005
|
const defaults = getProviderDefaults(agent.provider);
|
|
15037
15006
|
if (defaults) {
|
|
15038
15007
|
if (!agent.image) {
|
|
15039
|
-
const
|
|
15008
|
+
const apps = agent.apps;
|
|
15009
|
+
const defaultImage = getDefaultImageWithApps(
|
|
15010
|
+
agent.provider,
|
|
15011
|
+
apps
|
|
15012
|
+
);
|
|
15040
15013
|
if (defaultImage) {
|
|
15041
15014
|
agent.image = defaultImage;
|
|
15042
15015
|
console.log(
|
|
@@ -15485,9 +15458,9 @@ var CodexEventParser = class {
|
|
|
15485
15458
|
}
|
|
15486
15459
|
}
|
|
15487
15460
|
if (itemType === "file_change" && item.changes && item.changes.length > 0) {
|
|
15488
|
-
const changes = item.changes.map((
|
|
15489
|
-
const action =
|
|
15490
|
-
return `${action}: ${
|
|
15461
|
+
const changes = item.changes.map((c11) => {
|
|
15462
|
+
const action = c11.kind === "add" ? "Created" : c11.kind === "modify" ? "Modified" : "Deleted";
|
|
15463
|
+
return `${action}: ${c11.path}`;
|
|
15491
15464
|
}).join("\n");
|
|
15492
15465
|
return {
|
|
15493
15466
|
type: "text",
|
|
@@ -15828,9 +15801,9 @@ var CodexEventRenderer = class {
|
|
|
15828
15801
|
return;
|
|
15829
15802
|
}
|
|
15830
15803
|
if (itemType === "file_change" && item.changes && item.changes.length > 0) {
|
|
15831
|
-
const summary = item.changes.map((
|
|
15832
|
-
const icon =
|
|
15833
|
-
return `${icon}${
|
|
15804
|
+
const summary = item.changes.map((c11) => {
|
|
15805
|
+
const icon = c11.kind === "add" ? "+" : c11.kind === "delete" ? "-" : "~";
|
|
15806
|
+
return `${icon}${c11.path}`;
|
|
15834
15807
|
}).join(", ");
|
|
15835
15808
|
console.log(chalk4.green("[files]") + ` ${summary}`);
|
|
15836
15809
|
return;
|
|
@@ -17719,7 +17692,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
17719
17692
|
}
|
|
17720
17693
|
var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
|
|
17721
17694
|
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(async (prompt, options) => {
|
|
17722
|
-
const shouldExit = await checkAndUpgrade("4.
|
|
17695
|
+
const shouldExit = await checkAndUpgrade("4.36.1", prompt);
|
|
17723
17696
|
if (shouldExit) {
|
|
17724
17697
|
process.exit(0);
|
|
17725
17698
|
}
|
|
@@ -18003,400 +17976,9 @@ cookCmd.command("resume").description(
|
|
|
18003
17976
|
});
|
|
18004
17977
|
var cookCommand = cookCmd;
|
|
18005
17978
|
|
|
18006
|
-
// src/commands/
|
|
18007
|
-
import { Command as Command22 } from "commander";
|
|
18008
|
-
|
|
18009
|
-
// src/commands/image/build.ts
|
|
17979
|
+
// src/commands/logs/index.ts
|
|
18010
17980
|
import { Command as Command18 } from "commander";
|
|
18011
17981
|
import chalk22 from "chalk";
|
|
18012
|
-
import { readFile as readFile8 } from "fs/promises";
|
|
18013
|
-
import { existsSync as existsSync9 } from "fs";
|
|
18014
|
-
|
|
18015
|
-
// src/lib/dockerfile-validator.ts
|
|
18016
|
-
var ALLOWED_INSTRUCTIONS = /* @__PURE__ */ new Set(["FROM", "RUN"]);
|
|
18017
|
-
function validateDockerfile(content) {
|
|
18018
|
-
const errors = [];
|
|
18019
|
-
const lines = content.split("\n");
|
|
18020
|
-
let inContinuation = false;
|
|
18021
|
-
for (let i = 0; i < lines.length; i++) {
|
|
18022
|
-
const line = lines[i];
|
|
18023
|
-
const trimmed = line.trim();
|
|
18024
|
-
if (!inContinuation && !trimmed) continue;
|
|
18025
|
-
if (!inContinuation && trimmed.startsWith("#")) continue;
|
|
18026
|
-
if (inContinuation) {
|
|
18027
|
-
inContinuation = trimmed.endsWith("\\");
|
|
18028
|
-
continue;
|
|
18029
|
-
}
|
|
18030
|
-
const match = trimmed.match(/^([A-Za-z]+)\s/);
|
|
18031
|
-
if (match) {
|
|
18032
|
-
const instruction = match[1].toUpperCase();
|
|
18033
|
-
if (!ALLOWED_INSTRUCTIONS.has(instruction)) {
|
|
18034
|
-
errors.push(`Unsupported instruction: ${instruction} (line ${i + 1})`);
|
|
18035
|
-
}
|
|
18036
|
-
}
|
|
18037
|
-
inContinuation = trimmed.endsWith("\\");
|
|
18038
|
-
}
|
|
18039
|
-
return {
|
|
18040
|
-
valid: errors.length === 0,
|
|
18041
|
-
errors
|
|
18042
|
-
};
|
|
18043
|
-
}
|
|
18044
|
-
|
|
18045
|
-
// src/commands/image/build.ts
|
|
18046
|
-
var sleep2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
18047
|
-
var buildCommand = new Command18().name("build").description("Build a custom image from a Dockerfile").requiredOption("-f, --file <path>", "Path to Dockerfile").requiredOption("-n, --name <name>", "Name for the image").option("--delete-existing", "Delete existing image before building").action(
|
|
18048
|
-
async (options) => {
|
|
18049
|
-
const { file: file2, name, deleteExisting } = options;
|
|
18050
|
-
if (!existsSync9(file2)) {
|
|
18051
|
-
console.error(chalk22.red(`\u2717 Dockerfile not found: ${file2}`));
|
|
18052
|
-
process.exit(1);
|
|
18053
|
-
}
|
|
18054
|
-
const nameRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,62}[a-zA-Z0-9]$/;
|
|
18055
|
-
if (!nameRegex.test(name)) {
|
|
18056
|
-
console.error(
|
|
18057
|
-
chalk22.red(
|
|
18058
|
-
"\u2717 Invalid name format. Must be 3-64 characters, letters, numbers, and hyphens only."
|
|
18059
|
-
)
|
|
18060
|
-
);
|
|
18061
|
-
process.exit(1);
|
|
18062
|
-
}
|
|
18063
|
-
if (name.startsWith("vm0-")) {
|
|
18064
|
-
console.error(
|
|
18065
|
-
chalk22.red(
|
|
18066
|
-
'\u2717 Invalid name. Cannot start with "vm0-" (reserved prefix).'
|
|
18067
|
-
)
|
|
18068
|
-
);
|
|
18069
|
-
process.exit(1);
|
|
18070
|
-
}
|
|
18071
|
-
try {
|
|
18072
|
-
const scope = await apiClient.getScope();
|
|
18073
|
-
const dockerfile = await readFile8(file2, "utf8");
|
|
18074
|
-
const validation = validateDockerfile(dockerfile);
|
|
18075
|
-
if (!validation.valid) {
|
|
18076
|
-
console.error(chalk22.red("\u2717 Dockerfile validation failed\n"));
|
|
18077
|
-
for (const error43 of validation.errors) {
|
|
18078
|
-
console.error(chalk22.red(` ${error43}`));
|
|
18079
|
-
}
|
|
18080
|
-
console.error();
|
|
18081
|
-
console.error(
|
|
18082
|
-
chalk22.yellow(
|
|
18083
|
-
" vm0 image build only supports FROM and RUN instructions."
|
|
18084
|
-
)
|
|
18085
|
-
);
|
|
18086
|
-
console.error(
|
|
18087
|
-
chalk22.yellow(
|
|
18088
|
-
" The purpose is to pre-install environment dependencies."
|
|
18089
|
-
)
|
|
18090
|
-
);
|
|
18091
|
-
process.exit(1);
|
|
18092
|
-
}
|
|
18093
|
-
console.log(chalk22.bold(`Building image: ${scope.slug}/${name}`));
|
|
18094
|
-
console.log();
|
|
18095
|
-
const buildInfo = await apiClient.createImage({
|
|
18096
|
-
dockerfile,
|
|
18097
|
-
alias: name,
|
|
18098
|
-
deleteExisting
|
|
18099
|
-
});
|
|
18100
|
-
const { imageId, buildId, versionId } = buildInfo;
|
|
18101
|
-
console.log(chalk22.dim(` Build ID: ${buildId}`));
|
|
18102
|
-
console.log();
|
|
18103
|
-
let logsOffset = 0;
|
|
18104
|
-
let status = "building";
|
|
18105
|
-
while (status === "building") {
|
|
18106
|
-
const statusResponse = await apiClient.get(
|
|
18107
|
-
`/api/images/${imageId}/builds/${buildId}?logsOffset=${logsOffset}`
|
|
18108
|
-
);
|
|
18109
|
-
if (!statusResponse.ok) {
|
|
18110
|
-
const error43 = await statusResponse.json();
|
|
18111
|
-
throw new Error(
|
|
18112
|
-
error43.error?.message || "Failed to get build status"
|
|
18113
|
-
);
|
|
18114
|
-
}
|
|
18115
|
-
const statusData = await statusResponse.json();
|
|
18116
|
-
for (const log of statusData.logs) {
|
|
18117
|
-
console.log(chalk22.dim(` ${log}`));
|
|
18118
|
-
}
|
|
18119
|
-
logsOffset = statusData.logsOffset;
|
|
18120
|
-
status = statusData.status;
|
|
18121
|
-
if (status === "building") {
|
|
18122
|
-
await sleep2(2e3);
|
|
18123
|
-
}
|
|
18124
|
-
}
|
|
18125
|
-
console.log();
|
|
18126
|
-
if (status === "ready") {
|
|
18127
|
-
const shortVersion = formatVersionIdForDisplay(versionId);
|
|
18128
|
-
console.log(
|
|
18129
|
-
chalk22.green(`\u2713 Image built: ${scope.slug}/${name}:${shortVersion}`)
|
|
18130
|
-
);
|
|
18131
|
-
} else {
|
|
18132
|
-
console.error(chalk22.red(`\u2717 Build failed`));
|
|
18133
|
-
process.exit(1);
|
|
18134
|
-
}
|
|
18135
|
-
} catch (error43) {
|
|
18136
|
-
if (error43 instanceof Error) {
|
|
18137
|
-
if (error43.message.includes("Not authenticated")) {
|
|
18138
|
-
console.error(
|
|
18139
|
-
chalk22.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
18140
|
-
);
|
|
18141
|
-
} else {
|
|
18142
|
-
console.error(chalk22.red(`\u2717 ${error43.message}`));
|
|
18143
|
-
}
|
|
18144
|
-
} else {
|
|
18145
|
-
console.error(chalk22.red("\u2717 An unexpected error occurred"));
|
|
18146
|
-
}
|
|
18147
|
-
process.exit(1);
|
|
18148
|
-
}
|
|
18149
|
-
}
|
|
18150
|
-
);
|
|
18151
|
-
|
|
18152
|
-
// src/commands/image/list.ts
|
|
18153
|
-
import { Command as Command19 } from "commander";
|
|
18154
|
-
import chalk23 from "chalk";
|
|
18155
|
-
var listCommand3 = new Command19().name("list").alias("ls").description("List your custom images").action(async () => {
|
|
18156
|
-
try {
|
|
18157
|
-
const response = await apiClient.get("/api/images");
|
|
18158
|
-
if (!response.ok) {
|
|
18159
|
-
const error43 = await response.json();
|
|
18160
|
-
throw new Error(
|
|
18161
|
-
error43.error?.message || "Failed to list images"
|
|
18162
|
-
);
|
|
18163
|
-
}
|
|
18164
|
-
const data = await response.json();
|
|
18165
|
-
const { images } = data;
|
|
18166
|
-
if (images.length === 0) {
|
|
18167
|
-
console.log(chalk23.dim("No images found."));
|
|
18168
|
-
console.log();
|
|
18169
|
-
console.log("Build your first image:");
|
|
18170
|
-
console.log(
|
|
18171
|
-
chalk23.cyan(" vm0 image build --file Dockerfile --name my-image")
|
|
18172
|
-
);
|
|
18173
|
-
return;
|
|
18174
|
-
}
|
|
18175
|
-
console.log(chalk23.bold("Your images:"));
|
|
18176
|
-
console.log();
|
|
18177
|
-
const imagesByAlias = /* @__PURE__ */ new Map();
|
|
18178
|
-
for (const image of images) {
|
|
18179
|
-
const list2 = imagesByAlias.get(image.alias) || [];
|
|
18180
|
-
list2.push(image);
|
|
18181
|
-
imagesByAlias.set(image.alias, list2);
|
|
18182
|
-
}
|
|
18183
|
-
const latestVersions = /* @__PURE__ */ new Map();
|
|
18184
|
-
for (const [alias, versions] of imagesByAlias) {
|
|
18185
|
-
const latestReady = versions.find((v) => v.status === "ready");
|
|
18186
|
-
latestVersions.set(alias, latestReady?.versionId || null);
|
|
18187
|
-
}
|
|
18188
|
-
console.log(
|
|
18189
|
-
chalk23.dim(
|
|
18190
|
-
`${"NAME".padEnd(40)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(20)}`
|
|
18191
|
-
)
|
|
18192
|
-
);
|
|
18193
|
-
console.log(chalk23.dim("-".repeat(72)));
|
|
18194
|
-
for (const image of images) {
|
|
18195
|
-
const statusColor = image.status === "ready" ? chalk23.green : image.status === "building" ? chalk23.yellow : chalk23.red;
|
|
18196
|
-
const createdAt = new Date(image.createdAt).toLocaleString();
|
|
18197
|
-
let displayName = image.alias;
|
|
18198
|
-
if (image.versionId) {
|
|
18199
|
-
const shortVersion = formatVersionIdForDisplay(image.versionId);
|
|
18200
|
-
displayName = `${image.alias}:${shortVersion}`;
|
|
18201
|
-
if (image.status === "ready" && latestVersions.get(image.alias) === image.versionId) {
|
|
18202
|
-
displayName = `${displayName} ${chalk23.cyan("latest")}`;
|
|
18203
|
-
}
|
|
18204
|
-
}
|
|
18205
|
-
console.log(
|
|
18206
|
-
`${displayName.padEnd(40)} ${statusColor(image.status.padEnd(12))} ${createdAt.padEnd(20)}`
|
|
18207
|
-
);
|
|
18208
|
-
if (image.status === "error" && image.errorMessage) {
|
|
18209
|
-
console.log(chalk23.red(` Error: ${image.errorMessage}`));
|
|
18210
|
-
}
|
|
18211
|
-
}
|
|
18212
|
-
console.log();
|
|
18213
|
-
console.log(chalk23.dim(`Total: ${images.length} version(s)`));
|
|
18214
|
-
} catch (error43) {
|
|
18215
|
-
if (error43 instanceof Error) {
|
|
18216
|
-
if (error43.message.includes("Not authenticated")) {
|
|
18217
|
-
console.error(chalk23.red("Not authenticated. Run: vm0 auth login"));
|
|
18218
|
-
} else {
|
|
18219
|
-
console.error(chalk23.red(`Error: ${error43.message}`));
|
|
18220
|
-
}
|
|
18221
|
-
} else {
|
|
18222
|
-
console.error(chalk23.red("An unexpected error occurred"));
|
|
18223
|
-
}
|
|
18224
|
-
process.exit(1);
|
|
18225
|
-
}
|
|
18226
|
-
});
|
|
18227
|
-
|
|
18228
|
-
// src/commands/image/delete.ts
|
|
18229
|
-
import { Command as Command20 } from "commander";
|
|
18230
|
-
import chalk24 from "chalk";
|
|
18231
|
-
var deleteCommand = new Command20().name("delete").alias("rm").description("Delete a custom image or specific version").argument("<name>", "Image name or name:version to delete").option("-f, --force", "Skip confirmation prompt").option("--all", "Delete all versions of the image").action(
|
|
18232
|
-
async (nameArg, options) => {
|
|
18233
|
-
try {
|
|
18234
|
-
const colonIndex = nameArg.lastIndexOf(":");
|
|
18235
|
-
const hasVersion = colonIndex > 0;
|
|
18236
|
-
const name = hasVersion ? nameArg.slice(0, colonIndex) : nameArg;
|
|
18237
|
-
const versionId = hasVersion ? nameArg.slice(colonIndex + 1) : null;
|
|
18238
|
-
const listResponse = await apiClient.get("/api/images");
|
|
18239
|
-
if (!listResponse.ok) {
|
|
18240
|
-
const error43 = await listResponse.json();
|
|
18241
|
-
throw new Error(
|
|
18242
|
-
error43.error?.message || "Failed to list images"
|
|
18243
|
-
);
|
|
18244
|
-
}
|
|
18245
|
-
const data = await listResponse.json();
|
|
18246
|
-
let imagesToDelete;
|
|
18247
|
-
if (versionId) {
|
|
18248
|
-
const matchingVersions = data.images.filter(
|
|
18249
|
-
(img) => img.alias === name && img.versionId && img.versionId.startsWith(versionId.toLowerCase())
|
|
18250
|
-
);
|
|
18251
|
-
if (matchingVersions.length === 0) {
|
|
18252
|
-
console.error(chalk24.red(`Image version not found: ${nameArg}`));
|
|
18253
|
-
process.exit(1);
|
|
18254
|
-
}
|
|
18255
|
-
if (matchingVersions.length > 1) {
|
|
18256
|
-
console.error(
|
|
18257
|
-
chalk24.red(
|
|
18258
|
-
`Ambiguous version prefix "${versionId}". Please use more characters.`
|
|
18259
|
-
)
|
|
18260
|
-
);
|
|
18261
|
-
process.exit(1);
|
|
18262
|
-
}
|
|
18263
|
-
imagesToDelete = [matchingVersions[0]];
|
|
18264
|
-
} else if (options.all) {
|
|
18265
|
-
imagesToDelete = data.images.filter((img) => img.alias === name);
|
|
18266
|
-
if (imagesToDelete.length === 0) {
|
|
18267
|
-
console.error(chalk24.red(`Image not found: ${name}`));
|
|
18268
|
-
process.exit(1);
|
|
18269
|
-
}
|
|
18270
|
-
} else {
|
|
18271
|
-
const matchingImages = data.images.filter(
|
|
18272
|
-
(img) => img.alias === name
|
|
18273
|
-
);
|
|
18274
|
-
if (matchingImages.length === 0) {
|
|
18275
|
-
console.error(chalk24.red(`Image not found: ${name}`));
|
|
18276
|
-
process.exit(1);
|
|
18277
|
-
}
|
|
18278
|
-
const latestReady = matchingImages.find(
|
|
18279
|
-
(img) => img.status === "ready"
|
|
18280
|
-
);
|
|
18281
|
-
if (latestReady) {
|
|
18282
|
-
imagesToDelete = [latestReady];
|
|
18283
|
-
} else {
|
|
18284
|
-
imagesToDelete = [matchingImages[0]];
|
|
18285
|
-
}
|
|
18286
|
-
}
|
|
18287
|
-
const firstImage = imagesToDelete[0];
|
|
18288
|
-
const firstVersionDisplay = firstImage.versionId ? `:${formatVersionIdForDisplay(firstImage.versionId)}` : "";
|
|
18289
|
-
const confirmMsg = imagesToDelete.length === 1 ? `Delete image "${firstImage.alias}${firstVersionDisplay}"?` : `Delete ${imagesToDelete.length} versions of "${name}"?`;
|
|
18290
|
-
if (!options.force) {
|
|
18291
|
-
const confirmed = await promptConfirm(confirmMsg, false);
|
|
18292
|
-
if (!confirmed) {
|
|
18293
|
-
console.log(chalk24.dim("Cancelled."));
|
|
18294
|
-
return;
|
|
18295
|
-
}
|
|
18296
|
-
}
|
|
18297
|
-
for (const image of imagesToDelete) {
|
|
18298
|
-
const deleteResponse = await apiClient.delete(
|
|
18299
|
-
`/api/images/${image.id}`
|
|
18300
|
-
);
|
|
18301
|
-
if (!deleteResponse.ok) {
|
|
18302
|
-
const error43 = await deleteResponse.json();
|
|
18303
|
-
throw new Error(
|
|
18304
|
-
error43.error?.message || "Failed to delete image"
|
|
18305
|
-
);
|
|
18306
|
-
}
|
|
18307
|
-
const displayName = image.versionId ? `${image.alias}:${formatVersionIdForDisplay(image.versionId)}` : image.alias;
|
|
18308
|
-
console.log(chalk24.green(`Deleted image: ${displayName}`));
|
|
18309
|
-
}
|
|
18310
|
-
} catch (error43) {
|
|
18311
|
-
if (error43 instanceof Error) {
|
|
18312
|
-
if (error43.message.includes("Not authenticated")) {
|
|
18313
|
-
console.error(chalk24.red("Not authenticated. Run: vm0 auth login"));
|
|
18314
|
-
} else {
|
|
18315
|
-
console.error(chalk24.red(`Error: ${error43.message}`));
|
|
18316
|
-
}
|
|
18317
|
-
} else {
|
|
18318
|
-
console.error(chalk24.red("An unexpected error occurred"));
|
|
18319
|
-
}
|
|
18320
|
-
process.exit(1);
|
|
18321
|
-
}
|
|
18322
|
-
}
|
|
18323
|
-
);
|
|
18324
|
-
|
|
18325
|
-
// src/commands/image/versions.ts
|
|
18326
|
-
import { Command as Command21 } from "commander";
|
|
18327
|
-
import chalk25 from "chalk";
|
|
18328
|
-
var versionsCommand = new Command21().name("versions").description("List all versions of an image").argument("<name>", "Name of the image").action(async (name) => {
|
|
18329
|
-
try {
|
|
18330
|
-
const response = await apiClient.get("/api/images");
|
|
18331
|
-
if (!response.ok) {
|
|
18332
|
-
const error43 = await response.json();
|
|
18333
|
-
throw new Error(
|
|
18334
|
-
error43.error?.message || "Failed to list images"
|
|
18335
|
-
);
|
|
18336
|
-
}
|
|
18337
|
-
const data = await response.json();
|
|
18338
|
-
const versions = data.images.filter((img) => img.alias === name);
|
|
18339
|
-
if (versions.length === 0) {
|
|
18340
|
-
console.error(chalk25.red(`Image not found: ${name}`));
|
|
18341
|
-
process.exit(1);
|
|
18342
|
-
}
|
|
18343
|
-
const latestReady = versions.find((v) => v.status === "ready");
|
|
18344
|
-
const latestVersionId = latestReady?.versionId || null;
|
|
18345
|
-
console.log(chalk25.bold(`Versions of ${name}:`));
|
|
18346
|
-
console.log();
|
|
18347
|
-
console.log(
|
|
18348
|
-
chalk25.dim(
|
|
18349
|
-
`${"VERSION".padEnd(20)} ${"STATUS".padEnd(12)} ${"CREATED".padEnd(24)}`
|
|
18350
|
-
)
|
|
18351
|
-
);
|
|
18352
|
-
console.log(chalk25.dim("-".repeat(56)));
|
|
18353
|
-
for (const version2 of versions) {
|
|
18354
|
-
const statusColor = version2.status === "ready" ? chalk25.green : version2.status === "building" ? chalk25.yellow : chalk25.red;
|
|
18355
|
-
const createdAt = new Date(version2.createdAt).toLocaleString();
|
|
18356
|
-
let versionDisplay = version2.versionId ? formatVersionIdForDisplay(version2.versionId) : "(legacy)";
|
|
18357
|
-
if (version2.status === "ready" && version2.versionId === latestVersionId) {
|
|
18358
|
-
versionDisplay = `${versionDisplay} ${chalk25.cyan("latest")}`;
|
|
18359
|
-
}
|
|
18360
|
-
console.log(
|
|
18361
|
-
`${versionDisplay.padEnd(20)} ${statusColor(version2.status.padEnd(12))} ${createdAt.padEnd(24)}`
|
|
18362
|
-
);
|
|
18363
|
-
if (version2.status === "error" && version2.errorMessage) {
|
|
18364
|
-
console.log(chalk25.red(` Error: ${version2.errorMessage}`));
|
|
18365
|
-
}
|
|
18366
|
-
}
|
|
18367
|
-
console.log();
|
|
18368
|
-
console.log(chalk25.dim(`Total: ${versions.length} version(s)`));
|
|
18369
|
-
console.log();
|
|
18370
|
-
console.log(chalk25.dim("Usage:"));
|
|
18371
|
-
console.log(chalk25.dim(` image: "${name}" # uses latest`));
|
|
18372
|
-
if (latestVersionId) {
|
|
18373
|
-
const shortVersion = formatVersionIdForDisplay(latestVersionId);
|
|
18374
|
-
console.log(
|
|
18375
|
-
chalk25.dim(
|
|
18376
|
-
` image: "${name}:${shortVersion}" # pin to specific version`
|
|
18377
|
-
)
|
|
18378
|
-
);
|
|
18379
|
-
}
|
|
18380
|
-
} catch (error43) {
|
|
18381
|
-
if (error43 instanceof Error) {
|
|
18382
|
-
if (error43.message.includes("Not authenticated")) {
|
|
18383
|
-
console.error(chalk25.red("Not authenticated. Run: vm0 auth login"));
|
|
18384
|
-
} else {
|
|
18385
|
-
console.error(chalk25.red(`Error: ${error43.message}`));
|
|
18386
|
-
}
|
|
18387
|
-
} else {
|
|
18388
|
-
console.error(chalk25.red("An unexpected error occurred"));
|
|
18389
|
-
}
|
|
18390
|
-
process.exit(1);
|
|
18391
|
-
}
|
|
18392
|
-
});
|
|
18393
|
-
|
|
18394
|
-
// src/commands/image/index.ts
|
|
18395
|
-
var imageCommand = new Command22().name("image").description("Manage custom images").addCommand(buildCommand).addCommand(listCommand3).addCommand(deleteCommand).addCommand(versionsCommand);
|
|
18396
|
-
|
|
18397
|
-
// src/commands/logs/index.ts
|
|
18398
|
-
import { Command as Command23 } from "commander";
|
|
18399
|
-
import chalk26 from "chalk";
|
|
18400
17982
|
|
|
18401
17983
|
// src/lib/time-parser.ts
|
|
18402
17984
|
function parseTime(timeStr) {
|
|
@@ -18458,23 +18040,23 @@ function formatMetric(metric) {
|
|
|
18458
18040
|
function formatNetworkLog(entry) {
|
|
18459
18041
|
let statusColor;
|
|
18460
18042
|
if (entry.status >= 200 && entry.status < 300) {
|
|
18461
|
-
statusColor =
|
|
18043
|
+
statusColor = chalk22.green;
|
|
18462
18044
|
} else if (entry.status >= 300 && entry.status < 400) {
|
|
18463
|
-
statusColor =
|
|
18045
|
+
statusColor = chalk22.yellow;
|
|
18464
18046
|
} else if (entry.status >= 400) {
|
|
18465
|
-
statusColor =
|
|
18047
|
+
statusColor = chalk22.red;
|
|
18466
18048
|
} else {
|
|
18467
|
-
statusColor =
|
|
18049
|
+
statusColor = chalk22.gray;
|
|
18468
18050
|
}
|
|
18469
18051
|
let latencyColor;
|
|
18470
18052
|
if (entry.latency_ms < 500) {
|
|
18471
|
-
latencyColor =
|
|
18053
|
+
latencyColor = chalk22.green;
|
|
18472
18054
|
} else if (entry.latency_ms < 2e3) {
|
|
18473
|
-
latencyColor =
|
|
18055
|
+
latencyColor = chalk22.yellow;
|
|
18474
18056
|
} else {
|
|
18475
|
-
latencyColor =
|
|
18057
|
+
latencyColor = chalk22.red;
|
|
18476
18058
|
}
|
|
18477
|
-
return `[${entry.timestamp}] ${entry.method.padEnd(6)} ${statusColor(entry.status)} ${latencyColor(entry.latency_ms + "ms")} ${formatBytes8(entry.request_size)}/${formatBytes8(entry.response_size)} ${
|
|
18059
|
+
return `[${entry.timestamp}] ${entry.method.padEnd(6)} ${statusColor(entry.status)} ${latencyColor(entry.latency_ms + "ms")} ${formatBytes8(entry.request_size)}/${formatBytes8(entry.response_size)} ${chalk22.dim(entry.url)}`;
|
|
18478
18060
|
}
|
|
18479
18061
|
function renderAgentEvent(event, provider) {
|
|
18480
18062
|
const eventData = event.eventData;
|
|
@@ -18497,7 +18079,7 @@ function getLogType(options) {
|
|
|
18497
18079
|
].filter(Boolean).length;
|
|
18498
18080
|
if (selected > 1) {
|
|
18499
18081
|
console.error(
|
|
18500
|
-
|
|
18082
|
+
chalk22.red(
|
|
18501
18083
|
"Options --agent, --system, --metrics, and --network are mutually exclusive"
|
|
18502
18084
|
)
|
|
18503
18085
|
);
|
|
@@ -18508,7 +18090,7 @@ function getLogType(options) {
|
|
|
18508
18090
|
if (options.network) return "network";
|
|
18509
18091
|
return "agent";
|
|
18510
18092
|
}
|
|
18511
|
-
var logsCommand = new
|
|
18093
|
+
var logsCommand = new Command18().name("logs").description("View logs for an agent run").argument("<runId>", "Run ID to fetch logs for").option("-a, --agent", "Show agent events (default)").option("-s, --system", "Show system log").option("-m, --metrics", "Show metrics").option("-n, --network", "Show network logs (proxy traffic)").option(
|
|
18512
18094
|
"--since <time>",
|
|
18513
18095
|
"Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z, 1705312200)"
|
|
18514
18096
|
).option("--tail <n>", "Show last N entries (default: 5, max: 100)").option("--head <n>", "Show first N entries (max: 100)").action(
|
|
@@ -18517,7 +18099,7 @@ var logsCommand = new Command23().name("logs").description("View logs for an age
|
|
|
18517
18099
|
const logType = getLogType(options);
|
|
18518
18100
|
if (options.tail !== void 0 && options.head !== void 0) {
|
|
18519
18101
|
console.error(
|
|
18520
|
-
|
|
18102
|
+
chalk22.red("Options --tail and --head are mutually exclusive")
|
|
18521
18103
|
);
|
|
18522
18104
|
process.exit(1);
|
|
18523
18105
|
}
|
|
@@ -18554,7 +18136,7 @@ var logsCommand = new Command23().name("logs").description("View logs for an age
|
|
|
18554
18136
|
async function showAgentEvents(runId, options) {
|
|
18555
18137
|
const response = await apiClient.getAgentEvents(runId, options);
|
|
18556
18138
|
if (response.events.length === 0) {
|
|
18557
|
-
console.log(
|
|
18139
|
+
console.log(chalk22.yellow("No agent events found for this run."));
|
|
18558
18140
|
return;
|
|
18559
18141
|
}
|
|
18560
18142
|
const events = options.order === "desc" ? [...response.events].reverse() : response.events;
|
|
@@ -18564,7 +18146,7 @@ async function showAgentEvents(runId, options) {
|
|
|
18564
18146
|
if (response.hasMore) {
|
|
18565
18147
|
console.log();
|
|
18566
18148
|
console.log(
|
|
18567
|
-
|
|
18149
|
+
chalk22.dim(
|
|
18568
18150
|
`Showing ${response.events.length} events. Use --tail to see more.`
|
|
18569
18151
|
)
|
|
18570
18152
|
);
|
|
@@ -18573,21 +18155,21 @@ async function showAgentEvents(runId, options) {
|
|
|
18573
18155
|
async function showSystemLog(runId, options) {
|
|
18574
18156
|
const response = await apiClient.getSystemLog(runId, options);
|
|
18575
18157
|
if (!response.systemLog) {
|
|
18576
|
-
console.log(
|
|
18158
|
+
console.log(chalk22.yellow("No system log found for this run."));
|
|
18577
18159
|
return;
|
|
18578
18160
|
}
|
|
18579
18161
|
console.log(response.systemLog);
|
|
18580
18162
|
if (response.hasMore) {
|
|
18581
18163
|
console.log();
|
|
18582
18164
|
console.log(
|
|
18583
|
-
|
|
18165
|
+
chalk22.dim("More log entries available. Use --tail to see more.")
|
|
18584
18166
|
);
|
|
18585
18167
|
}
|
|
18586
18168
|
}
|
|
18587
18169
|
async function showMetrics(runId, options) {
|
|
18588
18170
|
const response = await apiClient.getMetrics(runId, options);
|
|
18589
18171
|
if (response.metrics.length === 0) {
|
|
18590
|
-
console.log(
|
|
18172
|
+
console.log(chalk22.yellow("No metrics found for this run."));
|
|
18591
18173
|
return;
|
|
18592
18174
|
}
|
|
18593
18175
|
const metrics = options.order === "desc" ? [...response.metrics].reverse() : response.metrics;
|
|
@@ -18597,7 +18179,7 @@ async function showMetrics(runId, options) {
|
|
|
18597
18179
|
if (response.hasMore) {
|
|
18598
18180
|
console.log();
|
|
18599
18181
|
console.log(
|
|
18600
|
-
|
|
18182
|
+
chalk22.dim(
|
|
18601
18183
|
`Showing ${response.metrics.length} metrics. Use --tail to see more.`
|
|
18602
18184
|
)
|
|
18603
18185
|
);
|
|
@@ -18607,7 +18189,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
18607
18189
|
const response = await apiClient.getNetworkLogs(runId, options);
|
|
18608
18190
|
if (response.networkLogs.length === 0) {
|
|
18609
18191
|
console.log(
|
|
18610
|
-
|
|
18192
|
+
chalk22.yellow(
|
|
18611
18193
|
"No network logs found for this run. Network logs are only captured when beta_network_security is enabled."
|
|
18612
18194
|
)
|
|
18613
18195
|
);
|
|
@@ -18620,7 +18202,7 @@ async function showNetworkLogs(runId, options) {
|
|
|
18620
18202
|
if (response.hasMore) {
|
|
18621
18203
|
console.log();
|
|
18622
18204
|
console.log(
|
|
18623
|
-
|
|
18205
|
+
chalk22.dim(
|
|
18624
18206
|
`Showing ${response.networkLogs.length} network logs. Use --tail to see more.`
|
|
18625
18207
|
)
|
|
18626
18208
|
);
|
|
@@ -18629,31 +18211,31 @@ async function showNetworkLogs(runId, options) {
|
|
|
18629
18211
|
function handleError(error43, runId) {
|
|
18630
18212
|
if (error43 instanceof Error) {
|
|
18631
18213
|
if (error43.message.includes("Not authenticated")) {
|
|
18632
|
-
console.error(
|
|
18214
|
+
console.error(chalk22.red("Not authenticated. Run: vm0 auth login"));
|
|
18633
18215
|
} else if (error43.message.includes("not found")) {
|
|
18634
|
-
console.error(
|
|
18216
|
+
console.error(chalk22.red(`Run not found: ${runId}`));
|
|
18635
18217
|
} else if (error43.message.includes("Invalid time format")) {
|
|
18636
|
-
console.error(
|
|
18218
|
+
console.error(chalk22.red(error43.message));
|
|
18637
18219
|
} else {
|
|
18638
|
-
console.error(
|
|
18639
|
-
console.error(
|
|
18220
|
+
console.error(chalk22.red("Failed to fetch logs"));
|
|
18221
|
+
console.error(chalk22.dim(` ${error43.message}`));
|
|
18640
18222
|
}
|
|
18641
18223
|
} else {
|
|
18642
|
-
console.error(
|
|
18224
|
+
console.error(chalk22.red("An unexpected error occurred"));
|
|
18643
18225
|
}
|
|
18644
18226
|
}
|
|
18645
18227
|
|
|
18646
18228
|
// src/commands/scope/index.ts
|
|
18647
|
-
import { Command as
|
|
18229
|
+
import { Command as Command21 } from "commander";
|
|
18648
18230
|
|
|
18649
18231
|
// src/commands/scope/status.ts
|
|
18650
|
-
import { Command as
|
|
18651
|
-
import
|
|
18652
|
-
var statusCommand3 = new
|
|
18232
|
+
import { Command as Command19 } from "commander";
|
|
18233
|
+
import chalk23 from "chalk";
|
|
18234
|
+
var statusCommand3 = new Command19().name("status").description("View current scope status").action(async () => {
|
|
18653
18235
|
try {
|
|
18654
18236
|
const scope = await apiClient.getScope();
|
|
18655
|
-
console.log(
|
|
18656
|
-
console.log(` Slug: ${
|
|
18237
|
+
console.log(chalk23.bold("Scope Information:"));
|
|
18238
|
+
console.log(` Slug: ${chalk23.green(scope.slug)}`);
|
|
18657
18239
|
console.log(` Type: ${scope.type}`);
|
|
18658
18240
|
if (scope.displayName) {
|
|
18659
18241
|
console.log(` Display Name: ${scope.displayName}`);
|
|
@@ -18664,29 +18246,29 @@ var statusCommand3 = new Command24().name("status").description("View current sc
|
|
|
18664
18246
|
} catch (error43) {
|
|
18665
18247
|
if (error43 instanceof Error) {
|
|
18666
18248
|
if (error43.message.includes("Not authenticated")) {
|
|
18667
|
-
console.error(
|
|
18249
|
+
console.error(chalk23.red("\u2717 Not authenticated. Run: vm0 auth login"));
|
|
18668
18250
|
} else if (error43.message.includes("No scope configured")) {
|
|
18669
|
-
console.log(
|
|
18251
|
+
console.log(chalk23.yellow("No scope configured."));
|
|
18670
18252
|
console.log();
|
|
18671
18253
|
console.log("Set your scope with:");
|
|
18672
|
-
console.log(
|
|
18254
|
+
console.log(chalk23.cyan(" vm0 scope set <slug>"));
|
|
18673
18255
|
console.log();
|
|
18674
18256
|
console.log("Example:");
|
|
18675
|
-
console.log(
|
|
18257
|
+
console.log(chalk23.dim(" vm0 scope set myusername"));
|
|
18676
18258
|
} else {
|
|
18677
|
-
console.error(
|
|
18259
|
+
console.error(chalk23.red(`\u2717 ${error43.message}`));
|
|
18678
18260
|
}
|
|
18679
18261
|
} else {
|
|
18680
|
-
console.error(
|
|
18262
|
+
console.error(chalk23.red("\u2717 An unexpected error occurred"));
|
|
18681
18263
|
}
|
|
18682
18264
|
process.exit(1);
|
|
18683
18265
|
}
|
|
18684
18266
|
});
|
|
18685
18267
|
|
|
18686
18268
|
// src/commands/scope/set.ts
|
|
18687
|
-
import { Command as
|
|
18688
|
-
import
|
|
18689
|
-
var setCommand = new
|
|
18269
|
+
import { Command as Command20 } from "commander";
|
|
18270
|
+
import chalk24 from "chalk";
|
|
18271
|
+
var setCommand = new Command20().name("set").description("Set your scope slug").argument("<slug>", "The scope slug (e.g., your username)").option("--force", "Force change existing scope (may break references)").option("--display-name <name>", "Display name for the scope").action(
|
|
18690
18272
|
async (slug, options) => {
|
|
18691
18273
|
try {
|
|
18692
18274
|
let existingScope;
|
|
@@ -18701,56 +18283,56 @@ var setCommand = new Command25().name("set").description("Set your scope slug").
|
|
|
18701
18283
|
if (existingScope) {
|
|
18702
18284
|
if (!options.force) {
|
|
18703
18285
|
console.error(
|
|
18704
|
-
|
|
18286
|
+
chalk24.yellow(`You already have a scope: ${existingScope.slug}`)
|
|
18705
18287
|
);
|
|
18706
18288
|
console.error();
|
|
18707
18289
|
console.error("To change your scope, use --force:");
|
|
18708
|
-
console.error(
|
|
18290
|
+
console.error(chalk24.cyan(` vm0 scope set ${slug} --force`));
|
|
18709
18291
|
console.error();
|
|
18710
18292
|
console.error(
|
|
18711
|
-
|
|
18293
|
+
chalk24.yellow(
|
|
18712
18294
|
"Warning: Changing your scope may break existing image references."
|
|
18713
18295
|
)
|
|
18714
18296
|
);
|
|
18715
18297
|
process.exit(1);
|
|
18716
18298
|
}
|
|
18717
18299
|
scope = await apiClient.updateScope({ slug, force: true });
|
|
18718
|
-
console.log(
|
|
18300
|
+
console.log(chalk24.green(`\u2713 Scope updated to ${scope.slug}`));
|
|
18719
18301
|
} else {
|
|
18720
18302
|
scope = await apiClient.createScope({
|
|
18721
18303
|
slug,
|
|
18722
18304
|
displayName: options.displayName
|
|
18723
18305
|
});
|
|
18724
|
-
console.log(
|
|
18306
|
+
console.log(chalk24.green(`\u2713 Scope created: ${scope.slug}`));
|
|
18725
18307
|
}
|
|
18726
18308
|
console.log();
|
|
18727
18309
|
console.log("Your images will now be namespaced as:");
|
|
18728
|
-
console.log(
|
|
18310
|
+
console.log(chalk24.cyan(` ${scope.slug}/<image-name>`));
|
|
18729
18311
|
} catch (error43) {
|
|
18730
18312
|
if (error43 instanceof Error) {
|
|
18731
18313
|
if (error43.message.includes("Not authenticated")) {
|
|
18732
18314
|
console.error(
|
|
18733
|
-
|
|
18315
|
+
chalk24.red("\u2717 Not authenticated. Run: vm0 auth login")
|
|
18734
18316
|
);
|
|
18735
18317
|
} else if (error43.message.includes("already exists")) {
|
|
18736
18318
|
console.error(
|
|
18737
|
-
|
|
18319
|
+
chalk24.red(
|
|
18738
18320
|
`\u2717 Scope "${slug}" is already taken. Please choose a different slug.`
|
|
18739
18321
|
)
|
|
18740
18322
|
);
|
|
18741
18323
|
} else if (error43.message.includes("reserved")) {
|
|
18742
|
-
console.error(
|
|
18324
|
+
console.error(chalk24.red(`\u2717 ${error43.message}`));
|
|
18743
18325
|
} else if (error43.message.includes("vm0")) {
|
|
18744
18326
|
console.error(
|
|
18745
|
-
|
|
18327
|
+
chalk24.red(
|
|
18746
18328
|
"\u2717 Scope slugs cannot start with 'vm0' (reserved for system use)"
|
|
18747
18329
|
)
|
|
18748
18330
|
);
|
|
18749
18331
|
} else {
|
|
18750
|
-
console.error(
|
|
18332
|
+
console.error(chalk24.red(`\u2717 ${error43.message}`));
|
|
18751
18333
|
}
|
|
18752
18334
|
} else {
|
|
18753
|
-
console.error(
|
|
18335
|
+
console.error(chalk24.red("\u2717 An unexpected error occurred"));
|
|
18754
18336
|
}
|
|
18755
18337
|
process.exit(1);
|
|
18756
18338
|
}
|
|
@@ -18758,13 +18340,13 @@ var setCommand = new Command25().name("set").description("Set your scope slug").
|
|
|
18758
18340
|
);
|
|
18759
18341
|
|
|
18760
18342
|
// src/commands/scope/index.ts
|
|
18761
|
-
var scopeCommand = new
|
|
18343
|
+
var scopeCommand = new Command21().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
|
|
18762
18344
|
|
|
18763
18345
|
// src/commands/init.ts
|
|
18764
|
-
import { Command as
|
|
18765
|
-
import
|
|
18346
|
+
import { Command as Command22 } from "commander";
|
|
18347
|
+
import chalk25 from "chalk";
|
|
18766
18348
|
import path13 from "path";
|
|
18767
|
-
import { existsSync as
|
|
18349
|
+
import { existsSync as existsSync9 } from "fs";
|
|
18768
18350
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
18769
18351
|
var VM0_YAML_FILE = "vm0.yaml";
|
|
18770
18352
|
var AGENTS_MD_FILE = "AGENTS.md";
|
|
@@ -18799,18 +18381,18 @@ You are a HackerNews AI content curator.
|
|
|
18799
18381
|
}
|
|
18800
18382
|
function checkExistingFiles() {
|
|
18801
18383
|
const existingFiles = [];
|
|
18802
|
-
if (
|
|
18803
|
-
if (
|
|
18384
|
+
if (existsSync9(VM0_YAML_FILE)) existingFiles.push(VM0_YAML_FILE);
|
|
18385
|
+
if (existsSync9(AGENTS_MD_FILE)) existingFiles.push(AGENTS_MD_FILE);
|
|
18804
18386
|
return existingFiles;
|
|
18805
18387
|
}
|
|
18806
|
-
var initCommand3 = new
|
|
18388
|
+
var initCommand3 = new Command22().name("init").description("Initialize a new VM0 project in the current directory").option("-f, --force", "Overwrite existing files").option("-n, --name <name>", "Agent name (required in non-interactive mode)").action(async (options) => {
|
|
18807
18389
|
const existingFiles = checkExistingFiles();
|
|
18808
18390
|
if (existingFiles.length > 0 && !options.force) {
|
|
18809
18391
|
for (const file2 of existingFiles) {
|
|
18810
|
-
console.log(
|
|
18392
|
+
console.log(chalk25.red(`\u2717 ${file2} already exists`));
|
|
18811
18393
|
}
|
|
18812
18394
|
console.log();
|
|
18813
|
-
console.log(`To overwrite: ${
|
|
18395
|
+
console.log(`To overwrite: ${chalk25.cyan("vm0 init --force")}`);
|
|
18814
18396
|
process.exit(1);
|
|
18815
18397
|
}
|
|
18816
18398
|
let agentName;
|
|
@@ -18818,9 +18400,9 @@ var initCommand3 = new Command27().name("init").description("Initialize a new VM
|
|
|
18818
18400
|
agentName = options.name.trim();
|
|
18819
18401
|
} else if (!isInteractive()) {
|
|
18820
18402
|
console.error(
|
|
18821
|
-
|
|
18403
|
+
chalk25.red("\u2717 --name flag is required in non-interactive mode")
|
|
18822
18404
|
);
|
|
18823
|
-
console.error(
|
|
18405
|
+
console.error(chalk25.dim(" Usage: vm0 init --name <agent-name>"));
|
|
18824
18406
|
process.exit(1);
|
|
18825
18407
|
} else {
|
|
18826
18408
|
const dirName = path13.basename(process.cwd());
|
|
@@ -18836,40 +18418,40 @@ var initCommand3 = new Command27().name("init").description("Initialize a new VM
|
|
|
18836
18418
|
}
|
|
18837
18419
|
);
|
|
18838
18420
|
if (name === void 0) {
|
|
18839
|
-
console.log(
|
|
18421
|
+
console.log(chalk25.dim("Cancelled"));
|
|
18840
18422
|
return;
|
|
18841
18423
|
}
|
|
18842
18424
|
agentName = name;
|
|
18843
18425
|
}
|
|
18844
18426
|
if (!agentName || !validateAgentName(agentName)) {
|
|
18845
|
-
console.log(
|
|
18427
|
+
console.log(chalk25.red("\u2717 Invalid agent name"));
|
|
18846
18428
|
console.log(
|
|
18847
|
-
|
|
18429
|
+
chalk25.dim(" Must be 3-64 characters, alphanumeric and hyphens only")
|
|
18848
18430
|
);
|
|
18849
|
-
console.log(
|
|
18431
|
+
console.log(chalk25.dim(" Must start and end with letter or number"));
|
|
18850
18432
|
process.exit(1);
|
|
18851
18433
|
}
|
|
18852
18434
|
await writeFile7(VM0_YAML_FILE, generateVm0Yaml(agentName));
|
|
18853
18435
|
const vm0Status = existingFiles.includes(VM0_YAML_FILE) ? " (overwritten)" : "";
|
|
18854
|
-
console.log(
|
|
18436
|
+
console.log(chalk25.green(`\u2713 Created ${VM0_YAML_FILE}${vm0Status}`));
|
|
18855
18437
|
await writeFile7(AGENTS_MD_FILE, generateAgentsMd());
|
|
18856
18438
|
const agentsStatus = existingFiles.includes(AGENTS_MD_FILE) ? " (overwritten)" : "";
|
|
18857
|
-
console.log(
|
|
18439
|
+
console.log(chalk25.green(`\u2713 Created ${AGENTS_MD_FILE}${agentsStatus}`));
|
|
18858
18440
|
console.log();
|
|
18859
18441
|
console.log("Next steps:");
|
|
18860
18442
|
console.log(
|
|
18861
|
-
` 1. Get your Claude Code token: ${
|
|
18443
|
+
` 1. Get your Claude Code token: ${chalk25.cyan("claude setup-token")}`
|
|
18862
18444
|
);
|
|
18863
18445
|
console.log(` 2. Set the environment variable (or add to .env file):`);
|
|
18864
|
-
console.log(
|
|
18865
|
-
console.log(` 3. Run your agent: ${
|
|
18446
|
+
console.log(chalk25.dim(` export CLAUDE_CODE_OAUTH_TOKEN=<your-token>`));
|
|
18447
|
+
console.log(` 3. Run your agent: ${chalk25.cyan('vm0 cook "your prompt"')}`);
|
|
18866
18448
|
});
|
|
18867
18449
|
|
|
18868
18450
|
// src/commands/setup-github.ts
|
|
18869
|
-
import { Command as
|
|
18870
|
-
import
|
|
18871
|
-
import { existsSync as
|
|
18872
|
-
import { mkdir as mkdir7, readFile as
|
|
18451
|
+
import { Command as Command23 } from "commander";
|
|
18452
|
+
import chalk26 from "chalk";
|
|
18453
|
+
import { existsSync as existsSync10 } from "fs";
|
|
18454
|
+
import { mkdir as mkdir7, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
|
|
18873
18455
|
import { execSync, spawnSync } from "child_process";
|
|
18874
18456
|
import path14 from "path";
|
|
18875
18457
|
import { parse as parseYaml5 } from "yaml";
|
|
@@ -18910,67 +18492,67 @@ async function checkPrerequisites() {
|
|
|
18910
18492
|
console.log("Checking prerequisites...");
|
|
18911
18493
|
const gitRoot = getGitRoot();
|
|
18912
18494
|
if (!gitRoot) {
|
|
18913
|
-
console.log(
|
|
18495
|
+
console.log(chalk26.red("\u2717 Not in a git repository"));
|
|
18914
18496
|
console.log();
|
|
18915
18497
|
console.log("This command must be run from within a git repository.");
|
|
18916
18498
|
console.log();
|
|
18917
18499
|
console.log("To initialize a git repository, run:");
|
|
18918
|
-
console.log(` ${
|
|
18500
|
+
console.log(` ${chalk26.cyan("git init")}`);
|
|
18919
18501
|
process.exit(1);
|
|
18920
18502
|
}
|
|
18921
|
-
console.log(
|
|
18503
|
+
console.log(chalk26.green("\u2713 Git repository detected"));
|
|
18922
18504
|
if (!isGhInstalled()) {
|
|
18923
|
-
console.log(
|
|
18505
|
+
console.log(chalk26.red("\u2717 GitHub CLI (gh) is not installed"));
|
|
18924
18506
|
console.log();
|
|
18925
18507
|
console.log("GitHub CLI is required for this command.");
|
|
18926
18508
|
console.log();
|
|
18927
|
-
console.log(` macOS: ${
|
|
18928
|
-
console.log(` Other: ${
|
|
18509
|
+
console.log(` macOS: ${chalk26.cyan("brew install gh")}`);
|
|
18510
|
+
console.log(` Other: ${chalk26.cyan("https://cli.github.com/")}`);
|
|
18929
18511
|
console.log();
|
|
18930
18512
|
console.log("After installation, run:");
|
|
18931
|
-
console.log(` ${
|
|
18513
|
+
console.log(` ${chalk26.cyan("gh auth login")}`);
|
|
18932
18514
|
console.log();
|
|
18933
18515
|
console.log("Then try again:");
|
|
18934
|
-
console.log(` ${
|
|
18516
|
+
console.log(` ${chalk26.cyan("vm0 setup-github")}`);
|
|
18935
18517
|
process.exit(1);
|
|
18936
18518
|
}
|
|
18937
|
-
console.log(
|
|
18519
|
+
console.log(chalk26.green("\u2713 GitHub CLI (gh) is installed"));
|
|
18938
18520
|
if (!isGhAuthenticated()) {
|
|
18939
|
-
console.log(
|
|
18521
|
+
console.log(chalk26.red("\u2717 GitHub CLI is not authenticated"));
|
|
18940
18522
|
console.log();
|
|
18941
18523
|
console.log("Please authenticate GitHub CLI first:");
|
|
18942
|
-
console.log(` ${
|
|
18524
|
+
console.log(` ${chalk26.cyan("gh auth login")}`);
|
|
18943
18525
|
console.log();
|
|
18944
18526
|
console.log("Then try again:");
|
|
18945
|
-
console.log(` ${
|
|
18527
|
+
console.log(` ${chalk26.cyan("vm0 setup-github")}`);
|
|
18946
18528
|
process.exit(1);
|
|
18947
18529
|
}
|
|
18948
|
-
console.log(
|
|
18530
|
+
console.log(chalk26.green("\u2713 GitHub CLI is authenticated"));
|
|
18949
18531
|
const token = await getToken();
|
|
18950
18532
|
if (!token) {
|
|
18951
|
-
console.log(
|
|
18533
|
+
console.log(chalk26.red("\u2717 VM0 not authenticated"));
|
|
18952
18534
|
console.log();
|
|
18953
18535
|
console.log("Please authenticate with VM0 first:");
|
|
18954
|
-
console.log(` ${
|
|
18536
|
+
console.log(` ${chalk26.cyan("vm0 auth login")}`);
|
|
18955
18537
|
console.log();
|
|
18956
18538
|
console.log("Then try again:");
|
|
18957
|
-
console.log(` ${
|
|
18539
|
+
console.log(` ${chalk26.cyan("vm0 setup-github")}`);
|
|
18958
18540
|
process.exit(1);
|
|
18959
18541
|
}
|
|
18960
|
-
console.log(
|
|
18961
|
-
if (!
|
|
18962
|
-
console.log(
|
|
18542
|
+
console.log(chalk26.green("\u2713 VM0 authenticated"));
|
|
18543
|
+
if (!existsSync10("vm0.yaml")) {
|
|
18544
|
+
console.log(chalk26.red("\u2717 vm0.yaml not found"));
|
|
18963
18545
|
console.log();
|
|
18964
18546
|
console.log("This command requires a vm0.yaml configuration file.");
|
|
18965
18547
|
console.log();
|
|
18966
18548
|
console.log("To create one, run:");
|
|
18967
|
-
console.log(` ${
|
|
18549
|
+
console.log(` ${chalk26.cyan("vm0 init")}`);
|
|
18968
18550
|
console.log();
|
|
18969
18551
|
console.log("Then try again:");
|
|
18970
|
-
console.log(` ${
|
|
18552
|
+
console.log(` ${chalk26.cyan("vm0 setup-github")}`);
|
|
18971
18553
|
process.exit(1);
|
|
18972
18554
|
}
|
|
18973
|
-
console.log(
|
|
18555
|
+
console.log(chalk26.green("\u2713 vm0.yaml found"));
|
|
18974
18556
|
return { token, gitRoot };
|
|
18975
18557
|
}
|
|
18976
18558
|
function generatePublishYaml(workingDir) {
|
|
@@ -19127,7 +18709,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
|
|
|
19127
18709
|
if (secretStatuses.length > 0) {
|
|
19128
18710
|
console.log("\u2502 Secrets: \u2502");
|
|
19129
18711
|
for (const s of secretStatuses) {
|
|
19130
|
-
const status = s.found ?
|
|
18712
|
+
const status = s.found ? chalk26.green("\u2713") : chalk26.red("\u2717");
|
|
19131
18713
|
const source = s.found ? `(from ${s.source})` : "not found";
|
|
19132
18714
|
const paddedName = (s.name + " ").padEnd(23, ".");
|
|
19133
18715
|
console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
|
|
@@ -19136,7 +18718,7 @@ function displaySecretsTable(secretStatuses, varStatuses) {
|
|
|
19136
18718
|
if (varStatuses.length > 0) {
|
|
19137
18719
|
console.log("\u2502 Variables: \u2502");
|
|
19138
18720
|
for (const v of varStatuses) {
|
|
19139
|
-
const status = v.found ?
|
|
18721
|
+
const status = v.found ? chalk26.green("\u2713") : chalk26.red("\u2717");
|
|
19140
18722
|
const source = v.found ? `(from ${v.source})` : "not found";
|
|
19141
18723
|
const paddedName = (v.name + " ").padEnd(23, ".");
|
|
19142
18724
|
console.log(`\u2502 ${status} ${paddedName} ${source.padEnd(19)}\u2502`);
|
|
@@ -19148,17 +18730,17 @@ function showManualSetupInstructions(secrets, vars) {
|
|
|
19148
18730
|
console.log("Skipped automatic setup. Configure secrets manually:");
|
|
19149
18731
|
console.log();
|
|
19150
18732
|
console.log(" Step 1: Get your VM0 token");
|
|
19151
|
-
console.log(` ${
|
|
18733
|
+
console.log(` ${chalk26.cyan("vm0 auth setup-token")}`);
|
|
19152
18734
|
console.log();
|
|
19153
18735
|
console.log(" Step 2: Set GitHub secrets");
|
|
19154
18736
|
for (const s of secrets) {
|
|
19155
|
-
console.log(` ${
|
|
18737
|
+
console.log(` ${chalk26.cyan(`gh secret set ${s}`)}`);
|
|
19156
18738
|
}
|
|
19157
18739
|
if (vars.length > 0) {
|
|
19158
18740
|
console.log();
|
|
19159
18741
|
console.log(" Step 3: Set GitHub variables");
|
|
19160
18742
|
for (const v of vars) {
|
|
19161
|
-
console.log(` ${
|
|
18743
|
+
console.log(` ${chalk26.cyan(`gh variable set ${v}`)}`);
|
|
19162
18744
|
}
|
|
19163
18745
|
}
|
|
19164
18746
|
}
|
|
@@ -19201,7 +18783,7 @@ function showWorkflowsCreatedMessage() {
|
|
|
19201
18783
|
console.log("\u2502 3. Push to main branch to trigger publish \u2502");
|
|
19202
18784
|
console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
19203
18785
|
}
|
|
19204
|
-
var setupGithubCommand = new
|
|
18786
|
+
var setupGithubCommand = new Command23().name("setup-github").description("Initialize GitHub Actions workflows for agent deployment").option("-f, --force", "Overwrite existing workflow files").option("-y, --yes", "Auto-confirm all prompts").option("--skip-secrets", "Skip automatic secrets/variables setup").action(
|
|
19205
18787
|
async (options) => {
|
|
19206
18788
|
const prereqs = await checkPrerequisites();
|
|
19207
18789
|
if (!prereqs) {
|
|
@@ -19211,14 +18793,14 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
|
|
|
19211
18793
|
const workingDir = getRelativeWorkingDir(gitRoot);
|
|
19212
18794
|
console.log();
|
|
19213
18795
|
console.log("Analyzing vm0.yaml...");
|
|
19214
|
-
const content = await
|
|
18796
|
+
const content = await readFile8("vm0.yaml", "utf8");
|
|
19215
18797
|
const config2 = parseYaml5(content);
|
|
19216
18798
|
const agents = config2.agents;
|
|
19217
18799
|
const agentName = Object.keys(agents)[0];
|
|
19218
|
-
console.log(
|
|
18800
|
+
console.log(chalk26.green(`\u2713 Agent: ${agentName}`));
|
|
19219
18801
|
const { secrets, vars } = extractSecretsAndVars(config2);
|
|
19220
18802
|
console.log(
|
|
19221
|
-
|
|
18803
|
+
chalk26.green(
|
|
19222
18804
|
`\u2713 Found ${secrets.length} secrets, ${vars.length} variables`
|
|
19223
18805
|
)
|
|
19224
18806
|
);
|
|
@@ -19228,10 +18810,10 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
|
|
|
19228
18810
|
const displayPublishPath = ".github/workflows/publish.yml";
|
|
19229
18811
|
const displayRunPath = ".github/workflows/run.yml";
|
|
19230
18812
|
const existingFiles = [];
|
|
19231
|
-
if (
|
|
19232
|
-
if (
|
|
18813
|
+
if (existsSync10(publishPath)) existingFiles.push(displayPublishPath);
|
|
18814
|
+
if (existsSync10(runPath)) existingFiles.push(displayRunPath);
|
|
19233
18815
|
if (existingFiles.length > 0 && !options.force) {
|
|
19234
|
-
console.log(
|
|
18816
|
+
console.log(chalk26.yellow("\u26A0 Existing workflow files detected:"));
|
|
19235
18817
|
for (const file2 of existingFiles) {
|
|
19236
18818
|
console.log(` \u2022 ${file2}`);
|
|
19237
18819
|
}
|
|
@@ -19244,7 +18826,7 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
|
|
|
19244
18826
|
if (!overwrite) {
|
|
19245
18827
|
console.log();
|
|
19246
18828
|
console.log("Aborted. To force overwrite, run:");
|
|
19247
|
-
console.log(` ${
|
|
18829
|
+
console.log(` ${chalk26.cyan("vm0 setup-github --force")}`);
|
|
19248
18830
|
process.exit(0);
|
|
19249
18831
|
}
|
|
19250
18832
|
}
|
|
@@ -19254,13 +18836,13 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
|
|
|
19254
18836
|
await mkdir7(path14.join(gitRoot, ".github/workflows"), { recursive: true });
|
|
19255
18837
|
await writeFile8(publishPath, generatePublishYaml(workingDir));
|
|
19256
18838
|
const publishStatus = existingFiles.includes(displayPublishPath) ? "Overwrote" : "Created";
|
|
19257
|
-
console.log(
|
|
18839
|
+
console.log(chalk26.green(`\u2713 ${publishStatus} ${displayPublishPath}`));
|
|
19258
18840
|
await writeFile8(runPath, generateRunYaml(agentName, secrets, vars));
|
|
19259
18841
|
const runStatus = existingFiles.includes(displayRunPath) ? "Overwrote" : "Created";
|
|
19260
|
-
console.log(
|
|
18842
|
+
console.log(chalk26.green(`\u2713 ${runStatus} ${displayRunPath}`));
|
|
19261
18843
|
console.log();
|
|
19262
18844
|
if (options.skipSecrets) {
|
|
19263
|
-
console.log(
|
|
18845
|
+
console.log(chalk26.green("\u2713 Done (secrets setup skipped)"));
|
|
19264
18846
|
return;
|
|
19265
18847
|
}
|
|
19266
18848
|
const { secretStatuses, varStatuses } = await detectSecretValues(
|
|
@@ -19300,14 +18882,14 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
|
|
|
19300
18882
|
if (s.found && s.value) {
|
|
19301
18883
|
const success2 = setGitHubSecret(s.name, s.value);
|
|
19302
18884
|
if (success2) {
|
|
19303
|
-
console.log(` ${
|
|
18885
|
+
console.log(` ${chalk26.green("\u2713")} ${s.name}`);
|
|
19304
18886
|
} else {
|
|
19305
|
-
console.log(` ${
|
|
18887
|
+
console.log(` ${chalk26.red("\u2717")} ${s.name} (failed)`);
|
|
19306
18888
|
failedSecrets.push(s.name);
|
|
19307
18889
|
}
|
|
19308
18890
|
} else {
|
|
19309
18891
|
console.log(
|
|
19310
|
-
` ${
|
|
18892
|
+
` ${chalk26.yellow("\u26A0")} ${s.name} (skipped - not found)`
|
|
19311
18893
|
);
|
|
19312
18894
|
}
|
|
19313
18895
|
}
|
|
@@ -19319,14 +18901,14 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
|
|
|
19319
18901
|
if (v.found && v.value) {
|
|
19320
18902
|
const success2 = setGitHubVariable(v.name, v.value);
|
|
19321
18903
|
if (success2) {
|
|
19322
|
-
console.log(` ${
|
|
18904
|
+
console.log(` ${chalk26.green("\u2713")} ${v.name}`);
|
|
19323
18905
|
} else {
|
|
19324
|
-
console.log(` ${
|
|
18906
|
+
console.log(` ${chalk26.red("\u2717")} ${v.name} (failed)`);
|
|
19325
18907
|
failedVars.push(v.name);
|
|
19326
18908
|
}
|
|
19327
18909
|
} else {
|
|
19328
18910
|
console.log(
|
|
19329
|
-
` ${
|
|
18911
|
+
` ${chalk26.yellow("\u26A0")} ${v.name} (skipped - not found)`
|
|
19330
18912
|
);
|
|
19331
18913
|
}
|
|
19332
18914
|
}
|
|
@@ -19349,10 +18931,10 @@ var setupGithubCommand = new Command28().name("setup-github").description("Initi
|
|
|
19349
18931
|
);
|
|
19350
18932
|
|
|
19351
18933
|
// src/index.ts
|
|
19352
|
-
var program = new
|
|
19353
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.
|
|
18934
|
+
var program = new Command24();
|
|
18935
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("4.36.1");
|
|
19354
18936
|
program.command("info").description("Display environment information").action(async () => {
|
|
19355
|
-
console.log(
|
|
18937
|
+
console.log(chalk27.bold("System Information:"));
|
|
19356
18938
|
console.log(`Node Version: ${process.version}`);
|
|
19357
18939
|
console.log(`Platform: ${process.platform}`);
|
|
19358
18940
|
console.log(`Architecture: ${process.arch}`);
|
|
@@ -19377,7 +18959,6 @@ program.addCommand(runCommand);
|
|
|
19377
18959
|
program.addCommand(volumeCommand);
|
|
19378
18960
|
program.addCommand(artifactCommand);
|
|
19379
18961
|
program.addCommand(cookCommand);
|
|
19380
|
-
program.addCommand(imageCommand);
|
|
19381
18962
|
program.addCommand(logsCommand);
|
|
19382
18963
|
program.addCommand(scopeCommand);
|
|
19383
18964
|
program.addCommand(initCommand3);
|