@vm0/cli 5.2.0 → 5.3.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.
Files changed (2) hide show
  1. package/index.js +579 -213
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -6,13 +6,13 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/index.ts
9
- import { Command as Command34 } from "commander";
10
- import chalk35 from "chalk";
9
+ import { Command as Command35 } from "commander";
10
+ import chalk36 from "chalk";
11
11
 
12
- // src/lib/auth.ts
12
+ // src/lib/api/auth.ts
13
13
  import chalk from "chalk";
14
14
 
15
- // src/lib/config.ts
15
+ // src/lib/api/config.ts
16
16
  import { homedir } from "os";
17
17
  import { join } from "path";
18
18
  import { readFile, writeFile, mkdir, unlink } from "fs/promises";
@@ -53,7 +53,7 @@ async function clearConfig() {
53
53
  }
54
54
  }
55
55
 
56
- // src/lib/auth.ts
56
+ // src/lib/api/auth.ts
57
57
  function buildHeaders() {
58
58
  const headers = {
59
59
  "Content-Type": "application/json"
@@ -14511,7 +14511,7 @@ function getProviderDisplayName(provider) {
14511
14511
  return PROVIDER_DISPLAY_NAMES[provider];
14512
14512
  }
14513
14513
 
14514
- // src/lib/api-client.ts
14514
+ // src/lib/api/api-client.ts
14515
14515
  var ApiClient = class {
14516
14516
  async getHeaders() {
14517
14517
  const token = await getToken();
@@ -14641,22 +14641,6 @@ var ApiClient = class {
14641
14641
  }
14642
14642
  return await response.json();
14643
14643
  }
14644
- async getTelemetry(runId) {
14645
- const baseUrl = await this.getBaseUrl();
14646
- const headers = await this.getHeaders();
14647
- const response = await fetch(
14648
- `${baseUrl}/api/agent/runs/${runId}/telemetry`,
14649
- {
14650
- method: "GET",
14651
- headers
14652
- }
14653
- );
14654
- if (!response.ok) {
14655
- const error43 = await response.json();
14656
- throw new Error(error43.error?.message || "Failed to fetch telemetry");
14657
- }
14658
- return await response.json();
14659
- }
14660
14644
  async getSystemLog(runId, options) {
14661
14645
  const baseUrl = await this.getBaseUrl();
14662
14646
  const headers = await this.getHeaders();
@@ -14757,20 +14741,6 @@ var ApiClient = class {
14757
14741
  }
14758
14742
  return await response.json();
14759
14743
  }
14760
- async createImage(body) {
14761
- const baseUrl = await this.getBaseUrl();
14762
- const headers = await this.getHeaders();
14763
- const response = await fetch(`${baseUrl}/api/images`, {
14764
- method: "POST",
14765
- headers,
14766
- body: JSON.stringify(body)
14767
- });
14768
- if (!response.ok) {
14769
- const error43 = await response.json();
14770
- throw new Error(error43.error?.message || "Failed to create image");
14771
- }
14772
- return await response.json();
14773
- }
14774
14744
  /**
14775
14745
  * Get current user's scope
14776
14746
  */
@@ -14932,7 +14902,7 @@ var ApiClient = class {
14932
14902
  };
14933
14903
  var apiClient = new ApiClient();
14934
14904
 
14935
- // src/lib/provider-config.ts
14905
+ // src/lib/domain/provider-config.ts
14936
14906
  var PROVIDER_DEFAULTS = {
14937
14907
  "claude-code": {
14938
14908
  workingDir: "/home/user/workspace",
@@ -14996,7 +14966,7 @@ function getDefaultImageWithApps(provider, apps) {
14996
14966
  return isDevelopment ? defaults.image.development : defaults.image.production;
14997
14967
  }
14998
14968
 
14999
- // src/lib/yaml-validator.ts
14969
+ // src/lib/domain/yaml-validator.ts
15000
14970
  function validateAgentName(name) {
15001
14971
  const nameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{1,62}[a-zA-Z0-9])?$/;
15002
14972
  return nameRegex.test(name);
@@ -15263,12 +15233,12 @@ function validateAgentCompose(config2) {
15263
15233
  return { valid: true };
15264
15234
  }
15265
15235
 
15266
- // src/lib/system-storage.ts
15236
+ // src/lib/storage/system-storage.ts
15267
15237
  import * as fs4 from "fs/promises";
15268
15238
  import * as path4 from "path";
15269
15239
  import * as os3 from "os";
15270
15240
 
15271
- // src/lib/github-skills.ts
15241
+ // src/lib/domain/github-skills.ts
15272
15242
  import * as fs from "fs/promises";
15273
15243
  import * as path from "path";
15274
15244
  import * as os from "os";
@@ -15352,14 +15322,14 @@ async function readSkillFrontmatter(skillDir) {
15352
15322
  return parseSkillFrontmatter(content);
15353
15323
  }
15354
15324
 
15355
- // src/lib/direct-upload.ts
15325
+ // src/lib/storage/direct-upload.ts
15356
15326
  import { createHash } from "crypto";
15357
15327
  import * as fs3 from "fs";
15358
15328
  import * as path3 from "path";
15359
15329
  import * as os2 from "os";
15360
15330
  import * as tar2 from "tar";
15361
15331
 
15362
- // src/lib/file-utils.ts
15332
+ // src/lib/utils/file-utils.ts
15363
15333
  import * as fs2 from "fs";
15364
15334
  import * as path2 from "path";
15365
15335
  import * as tar from "tar";
@@ -15459,7 +15429,7 @@ async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
15459
15429
  return isEmpty;
15460
15430
  }
15461
15431
 
15462
- // src/lib/direct-upload.ts
15432
+ // src/lib/storage/direct-upload.ts
15463
15433
  async function hashFileStream(filePath) {
15464
15434
  return new Promise((resolve2, reject) => {
15465
15435
  const hash2 = createHash("sha256");
@@ -15674,7 +15644,7 @@ async function directUpload(storageName, storageType, cwd, options) {
15674
15644
  };
15675
15645
  }
15676
15646
 
15677
- // src/lib/system-storage.ts
15647
+ // src/lib/storage/system-storage.ts
15678
15648
  function getInstructionsFilename(provider) {
15679
15649
  const validatedProvider = getValidatedProvider(provider);
15680
15650
  if (validatedProvider === "codex") {
@@ -16000,7 +15970,7 @@ import * as fs5 from "fs";
16000
15970
  import * as path5 from "path";
16001
15971
  import { config as dotenvConfig } from "dotenv";
16002
15972
 
16003
- // src/lib/claude-event-parser.ts
15973
+ // src/lib/events/claude-event-parser.ts
16004
15974
  var ClaudeEventParser = class {
16005
15975
  /**
16006
15976
  * Parse a raw Claude Code JSONL event into a simplified format
@@ -16104,7 +16074,7 @@ var ClaudeEventParser = class {
16104
16074
  }
16105
16075
  };
16106
16076
 
16107
- // src/lib/codex-event-parser.ts
16077
+ // src/lib/events/codex-event-parser.ts
16108
16078
  var CodexEventParser = class {
16109
16079
  /**
16110
16080
  * Parse a raw Codex CLI JSONL event into a simplified format
@@ -16294,7 +16264,7 @@ ${changes}` }
16294
16264
  }
16295
16265
  };
16296
16266
 
16297
- // src/lib/event-parser-factory.ts
16267
+ // src/lib/events/event-parser-factory.ts
16298
16268
  function detectProviderFromEvent(rawEvent) {
16299
16269
  if (!rawEvent || typeof rawEvent !== "object") {
16300
16270
  return null;
@@ -16320,7 +16290,7 @@ function parseEvent(rawEvent, provider) {
16320
16290
  return Parser.parse(rawEvent);
16321
16291
  }
16322
16292
 
16323
- // src/lib/event-renderer.ts
16293
+ // src/lib/events/event-renderer.ts
16324
16294
  import chalk3 from "chalk";
16325
16295
  var EventRenderer = class {
16326
16296
  /**
@@ -16508,7 +16478,7 @@ var EventRenderer = class {
16508
16478
  }
16509
16479
  };
16510
16480
 
16511
- // src/lib/codex-event-renderer.ts
16481
+ // src/lib/events/codex-event-renderer.ts
16512
16482
  import chalk4 from "chalk";
16513
16483
  var CodexEventRenderer = class {
16514
16484
  /**
@@ -17178,7 +17148,7 @@ import { Command as Command3 } from "commander";
17178
17148
  import chalk6 from "chalk";
17179
17149
  import path7 from "path";
17180
17150
 
17181
- // src/lib/storage-utils.ts
17151
+ // src/lib/storage/storage-utils.ts
17182
17152
  import { readFile as readFile5, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
17183
17153
  import { existsSync as existsSync5 } from "fs";
17184
17154
  import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
@@ -17225,7 +17195,7 @@ async function writeStorageConfig(storageName, basePath = process.cwd(), type =
17225
17195
  await writeFile4(configPath, yamlContent, "utf8");
17226
17196
  }
17227
17197
 
17228
- // src/lib/prompt-utils.ts
17198
+ // src/lib/utils/prompt-utils.ts
17229
17199
  import prompts2 from "prompts";
17230
17200
  function isInteractive() {
17231
17201
  return process.stdout.isTTY === true;
@@ -17269,6 +17239,26 @@ async function promptConfirm(message, initial = true) {
17269
17239
  );
17270
17240
  return response.value;
17271
17241
  }
17242
+ async function promptSelect(message, choices, initial) {
17243
+ if (!isInteractive()) {
17244
+ return void 0;
17245
+ }
17246
+ const response = await prompts2(
17247
+ {
17248
+ type: "select",
17249
+ name: "value",
17250
+ message,
17251
+ choices,
17252
+ initial
17253
+ },
17254
+ {
17255
+ onCancel: () => {
17256
+ return false;
17257
+ }
17258
+ }
17259
+ );
17260
+ return response.value;
17261
+ }
17272
17262
 
17273
17263
  // src/commands/volume/init.ts
17274
17264
  var initCommand = new Command3().name("init").description("Initialize a volume in the current directory").option("-n, --name <name>", "Volume name (required in non-interactive mode)").action(async (options) => {
@@ -17403,7 +17393,7 @@ import * as fs6 from "fs";
17403
17393
  import * as os4 from "os";
17404
17394
  import * as tar3 from "tar";
17405
17395
 
17406
- // src/lib/pull-utils.ts
17396
+ // src/lib/storage/pull-utils.ts
17407
17397
  import chalk8 from "chalk";
17408
17398
  async function handleEmptyStorageResponse(cwd) {
17409
17399
  console.log(chalk8.dim("Syncing local files..."));
@@ -17639,7 +17629,7 @@ var listCommand = new Command7().name("list").alias("ls").description("List all
17639
17629
  import { Command as Command8 } from "commander";
17640
17630
  import chalk13 from "chalk";
17641
17631
 
17642
- // src/lib/clone-utils.ts
17632
+ // src/lib/storage/clone-utils.ts
17643
17633
  import chalk12 from "chalk";
17644
17634
  import path9 from "path";
17645
17635
  import * as fs7 from "fs";
@@ -18162,7 +18152,7 @@ import { spawn as spawn2 } from "child_process";
18162
18152
  import { parse as parseYaml4 } from "yaml";
18163
18153
  import { config as dotenvConfig2 } from "dotenv";
18164
18154
 
18165
- // src/lib/update-checker.ts
18155
+ // src/lib/utils/update-checker.ts
18166
18156
  import https from "https";
18167
18157
  import { spawn } from "child_process";
18168
18158
  import chalk20 from "chalk";
@@ -18270,7 +18260,7 @@ async function checkAndUpgrade(currentVersion, prompt) {
18270
18260
  return true;
18271
18261
  }
18272
18262
 
18273
- // src/lib/cook-state.ts
18263
+ // src/lib/domain/cook-state.ts
18274
18264
  import { homedir as homedir2 } from "os";
18275
18265
  import { join as join6 } from "path";
18276
18266
  import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
@@ -18495,7 +18485,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
18495
18485
  }
18496
18486
  var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
18497
18487
  cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(async (prompt, options) => {
18498
- const shouldExit = await checkAndUpgrade("5.2.0", prompt);
18488
+ const shouldExit = await checkAndUpgrade("5.3.1", prompt);
18499
18489
  if (shouldExit) {
18500
18490
  process.exit(0);
18501
18491
  }
@@ -18783,7 +18773,7 @@ var cookCommand = cookCmd;
18783
18773
  import { Command as Command18 } from "commander";
18784
18774
  import chalk22 from "chalk";
18785
18775
 
18786
- // src/lib/time-parser.ts
18776
+ // src/lib/utils/time-parser.ts
18787
18777
  function parseTime(timeStr) {
18788
18778
  const relativeMatch = timeStr.match(/^(\d+)([smhdw])$/);
18789
18779
  if (relativeMatch) {
@@ -19210,7 +19200,7 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
19210
19200
  import { Command as Command23 } from "commander";
19211
19201
  import chalk26 from "chalk";
19212
19202
 
19213
- // src/lib/source-derivation.ts
19203
+ // src/lib/domain/source-derivation.ts
19214
19204
  import * as fs9 from "fs/promises";
19215
19205
  import * as path13 from "path";
19216
19206
  import * as os7 from "os";
@@ -20059,19 +20049,445 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
20059
20049
  );
20060
20050
 
20061
20051
  // src/commands/schedule/index.ts
20062
- import { Command as Command33 } from "commander";
20052
+ import { Command as Command34 } from "commander";
20063
20053
 
20064
- // src/commands/schedule/deploy.ts
20054
+ // src/commands/schedule/init.ts
20065
20055
  import { Command as Command27 } from "commander";
20066
20056
  import chalk29 from "chalk";
20057
+ import { existsSync as existsSync12, writeFileSync } from "fs";
20058
+ import { stringify as stringifyYaml2 } from "yaml";
20059
+
20060
+ // src/lib/domain/schedule-utils.ts
20067
20061
  import { existsSync as existsSync11, readFileSync as readFileSync2 } from "fs";
20068
20062
  import { parse as parseYaml6 } from "yaml";
20063
+ var CONFIG_FILE4 = "vm0.yaml";
20064
+ function loadAgentName() {
20065
+ if (!existsSync11(CONFIG_FILE4)) {
20066
+ return { agentName: null };
20067
+ }
20068
+ try {
20069
+ const content = readFileSync2(CONFIG_FILE4, "utf8");
20070
+ const config2 = parseYaml6(content);
20071
+ const agentNames = Object.keys(config2.agents || {});
20072
+ return { agentName: agentNames[0] || null };
20073
+ } catch (err) {
20074
+ return {
20075
+ agentName: null,
20076
+ error: err instanceof Error ? err.message : "Failed to parse vm0.yaml"
20077
+ };
20078
+ }
20079
+ }
20080
+ function formatRelativeTime2(dateStr) {
20081
+ if (!dateStr) return "-";
20082
+ const date5 = new Date(dateStr);
20083
+ const now = /* @__PURE__ */ new Date();
20084
+ const diffMs = date5.getTime() - now.getTime();
20085
+ const diffAbs = Math.abs(diffMs);
20086
+ const minutes = Math.floor(diffAbs / (1e3 * 60));
20087
+ const hours = Math.floor(diffAbs / (1e3 * 60 * 60));
20088
+ const days = Math.floor(diffAbs / (1e3 * 60 * 60 * 24));
20089
+ const isPast = diffMs < 0;
20090
+ if (days > 0) {
20091
+ return isPast ? `${days}d ago` : `in ${days}d`;
20092
+ } else if (hours > 0) {
20093
+ return isPast ? `${hours}h ago` : `in ${hours}h`;
20094
+ } else if (minutes > 0) {
20095
+ return isPast ? `${minutes}m ago` : `in ${minutes}m`;
20096
+ } else {
20097
+ return isPast ? "just now" : "soon";
20098
+ }
20099
+ }
20100
+ function formatDateTime(dateStr) {
20101
+ if (!dateStr) return "-";
20102
+ const date5 = new Date(dateStr);
20103
+ const formatted = date5.toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC");
20104
+ const relative2 = formatRelativeTime2(dateStr);
20105
+ return `${formatted} (${relative2})`;
20106
+ }
20107
+ function generateCronExpression(frequency, time3, day) {
20108
+ const [hourStr, minuteStr] = time3.split(":");
20109
+ const hour = parseInt(hourStr ?? "0", 10);
20110
+ const minute = parseInt(minuteStr ?? "0", 10);
20111
+ switch (frequency) {
20112
+ case "daily":
20113
+ return `${minute} ${hour} * * *`;
20114
+ case "weekly":
20115
+ return `${minute} ${hour} * * ${day ?? 1}`;
20116
+ case "monthly":
20117
+ return `${minute} ${hour} ${day ?? 1} * *`;
20118
+ }
20119
+ }
20120
+ function detectTimezone() {
20121
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
20122
+ }
20123
+ function extractVarsAndSecrets() {
20124
+ const result = { vars: [], secrets: [] };
20125
+ if (!existsSync11(CONFIG_FILE4)) {
20126
+ return result;
20127
+ }
20128
+ try {
20129
+ const content = readFileSync2(CONFIG_FILE4, "utf8");
20130
+ const config2 = parseYaml6(content);
20131
+ const agents = Object.values(config2.agents || {});
20132
+ const agent = agents[0];
20133
+ if (!agent) {
20134
+ return result;
20135
+ }
20136
+ if (agent.experimental_vars) {
20137
+ result.vars.push(...agent.experimental_vars);
20138
+ }
20139
+ if (agent.experimental_secrets) {
20140
+ result.secrets.push(...agent.experimental_secrets);
20141
+ }
20142
+ if (agent.environment) {
20143
+ for (const value of Object.values(agent.environment)) {
20144
+ const varsMatches = value.matchAll(/\$\{\{\s*vars\.(\w+)\s*\}\}/g);
20145
+ for (const match of varsMatches) {
20146
+ if (match[1] && !result.vars.includes(match[1])) {
20147
+ result.vars.push(match[1]);
20148
+ }
20149
+ }
20150
+ const secretsMatches = value.matchAll(
20151
+ /\$\{\{\s*secrets\.(\w+)\s*\}\}/g
20152
+ );
20153
+ for (const match of secretsMatches) {
20154
+ if (match[1] && !result.secrets.includes(match[1])) {
20155
+ result.secrets.push(match[1]);
20156
+ }
20157
+ }
20158
+ }
20159
+ }
20160
+ return result;
20161
+ } catch {
20162
+ return result;
20163
+ }
20164
+ }
20165
+ function validateTimeFormat(time3) {
20166
+ const match = time3.match(/^(\d{1,2}):(\d{2})$/);
20167
+ if (!match) {
20168
+ return "Invalid format. Use HH:MM (e.g., 09:00)";
20169
+ }
20170
+ const hour = parseInt(match[1], 10);
20171
+ const minute = parseInt(match[2], 10);
20172
+ if (hour < 0 || hour > 23) {
20173
+ return "Hour must be 0-23";
20174
+ }
20175
+ if (minute < 0 || minute > 59) {
20176
+ return "Minute must be 0-59";
20177
+ }
20178
+ return true;
20179
+ }
20180
+
20181
+ // src/commands/schedule/init.ts
20182
+ var SCHEDULE_FILE = "schedule.yaml";
20183
+ var FREQUENCY_CHOICES = [
20184
+ { title: "Daily", value: "daily", description: "Run every day" },
20185
+ {
20186
+ title: "Weekly",
20187
+ value: "weekly",
20188
+ description: "Run once per week"
20189
+ },
20190
+ {
20191
+ title: "Monthly",
20192
+ value: "monthly",
20193
+ description: "Run once per month"
20194
+ },
20195
+ {
20196
+ title: "One-time",
20197
+ value: "once",
20198
+ description: "Run once at specific time"
20199
+ }
20200
+ ];
20201
+ var DAY_OF_WEEK_CHOICES = [
20202
+ { title: "Monday", value: 1 },
20203
+ { title: "Tuesday", value: 2 },
20204
+ { title: "Wednesday", value: 3 },
20205
+ { title: "Thursday", value: 4 },
20206
+ { title: "Friday", value: 5 },
20207
+ { title: "Saturday", value: 6 },
20208
+ { title: "Sunday", value: 0 }
20209
+ ];
20210
+ function parseDayOption(day, frequency) {
20211
+ if (frequency === "weekly") {
20212
+ const dayMap = {
20213
+ sun: 0,
20214
+ mon: 1,
20215
+ tue: 2,
20216
+ wed: 3,
20217
+ thu: 4,
20218
+ fri: 5,
20219
+ sat: 6
20220
+ };
20221
+ return dayMap[day.toLowerCase()];
20222
+ } else if (frequency === "monthly") {
20223
+ const num = parseInt(day, 10);
20224
+ if (num >= 1 && num <= 31) {
20225
+ return num;
20226
+ }
20227
+ }
20228
+ return void 0;
20229
+ }
20230
+ var initCommand4 = new Command27().name("init").description("Create a schedule.yaml interactively").option("-n, --name <name>", "Schedule name").option("-f, --frequency <type>", "Frequency: daily|weekly|monthly|once").option("-t, --time <HH:MM>", "Time to run (24-hour format)").option("-d, --day <day>", "Day of week (mon-sun) or day of month (1-31)").option("-z, --timezone <tz>", "IANA timezone").option("-p, --prompt <text>", "Prompt to run").option("--no-vars", "Don't include vars from vm0.yaml").option("--force", "Overwrite existing schedule.yaml").action(
20231
+ async (options) => {
20232
+ try {
20233
+ const { agentName, error: error43 } = loadAgentName();
20234
+ if (error43) {
20235
+ console.error(chalk29.red(`\u2717 Invalid vm0.yaml: ${error43}`));
20236
+ process.exit(1);
20237
+ }
20238
+ if (!agentName) {
20239
+ console.error(chalk29.red("\u2717 No vm0.yaml found"));
20240
+ console.error(
20241
+ chalk29.dim(" Run this command from an agent directory")
20242
+ );
20243
+ process.exit(1);
20244
+ }
20245
+ if (existsSync12(SCHEDULE_FILE) && !options.force) {
20246
+ if (!isInteractive()) {
20247
+ console.error(chalk29.red("\u2717 schedule.yaml already exists"));
20248
+ console.error(chalk29.dim(" Use --force to overwrite"));
20249
+ process.exit(1);
20250
+ }
20251
+ const overwrite = await promptConfirm(
20252
+ "schedule.yaml exists. Overwrite?",
20253
+ false
20254
+ );
20255
+ if (!overwrite) {
20256
+ console.log(chalk29.dim("Cancelled"));
20257
+ return;
20258
+ }
20259
+ }
20260
+ let scheduleName = options.name;
20261
+ if (!scheduleName) {
20262
+ if (!isInteractive()) {
20263
+ console.error(
20264
+ chalk29.red("\u2717 --name is required in non-interactive mode")
20265
+ );
20266
+ process.exit(1);
20267
+ }
20268
+ scheduleName = await promptText(
20269
+ "Schedule name",
20270
+ `${agentName}-schedule`
20271
+ );
20272
+ if (!scheduleName) {
20273
+ console.log(chalk29.dim("Cancelled"));
20274
+ return;
20275
+ }
20276
+ }
20277
+ let frequency = options.frequency;
20278
+ if (!frequency || !["daily", "weekly", "monthly", "once"].includes(frequency)) {
20279
+ if (!isInteractive()) {
20280
+ console.error(
20281
+ chalk29.red(
20282
+ "\u2717 --frequency is required (daily|weekly|monthly|once)"
20283
+ )
20284
+ );
20285
+ process.exit(1);
20286
+ }
20287
+ frequency = await promptSelect(
20288
+ "Schedule frequency",
20289
+ FREQUENCY_CHOICES,
20290
+ 0
20291
+ );
20292
+ if (!frequency) {
20293
+ console.log(chalk29.dim("Cancelled"));
20294
+ return;
20295
+ }
20296
+ }
20297
+ let day;
20298
+ if (frequency === "weekly" || frequency === "monthly") {
20299
+ if (options.day) {
20300
+ day = parseDayOption(options.day, frequency);
20301
+ if (day === void 0) {
20302
+ console.error(
20303
+ chalk29.red(
20304
+ `\u2717 Invalid day: ${options.day}. Use mon-sun for weekly or 1-31 for monthly.`
20305
+ )
20306
+ );
20307
+ process.exit(1);
20308
+ }
20309
+ } else if (isInteractive()) {
20310
+ if (frequency === "weekly") {
20311
+ day = await promptSelect("Day of week", DAY_OF_WEEK_CHOICES, 0);
20312
+ if (day === void 0) {
20313
+ console.log(chalk29.dim("Cancelled"));
20314
+ return;
20315
+ }
20316
+ } else {
20317
+ const dayStr = await promptText("Day of month (1-31)", "1");
20318
+ if (!dayStr) {
20319
+ console.log(chalk29.dim("Cancelled"));
20320
+ return;
20321
+ }
20322
+ day = parseInt(dayStr, 10);
20323
+ if (isNaN(day) || day < 1 || day > 31) {
20324
+ console.error(chalk29.red("\u2717 Day must be between 1 and 31"));
20325
+ process.exit(1);
20326
+ }
20327
+ }
20328
+ } else {
20329
+ console.error(chalk29.red("\u2717 --day is required for weekly/monthly"));
20330
+ process.exit(1);
20331
+ }
20332
+ }
20333
+ let time3 = options.time;
20334
+ let atTime;
20335
+ if (frequency === "once") {
20336
+ if (!isInteractive()) {
20337
+ console.error(
20338
+ chalk29.red("\u2717 One-time schedules require interactive mode")
20339
+ );
20340
+ console.error(
20341
+ chalk29.dim(" Use cron frequency for non-interactive mode")
20342
+ );
20343
+ process.exit(1);
20344
+ }
20345
+ const dateStr = await promptText(
20346
+ "Date and time (YYYY-MM-DD HH:MM)",
20347
+ new Date(Date.now() + 24 * 60 * 60 * 1e3).toISOString().slice(0, 16).replace("T", " ")
20348
+ );
20349
+ if (!dateStr) {
20350
+ console.log(chalk29.dim("Cancelled"));
20351
+ return;
20352
+ }
20353
+ atTime = (/* @__PURE__ */ new Date(dateStr.replace(" ", "T") + ":00Z")).toISOString();
20354
+ } else {
20355
+ if (!time3) {
20356
+ if (!isInteractive()) {
20357
+ console.error(chalk29.red("\u2717 --time is required (HH:MM format)"));
20358
+ process.exit(1);
20359
+ }
20360
+ time3 = await promptText(
20361
+ "Time (HH:MM)",
20362
+ "09:00",
20363
+ validateTimeFormat
20364
+ );
20365
+ if (!time3) {
20366
+ console.log(chalk29.dim("Cancelled"));
20367
+ return;
20368
+ }
20369
+ } else {
20370
+ const validation = validateTimeFormat(time3);
20371
+ if (validation !== true) {
20372
+ console.error(chalk29.red(`\u2717 Invalid time: ${validation}`));
20373
+ process.exit(1);
20374
+ }
20375
+ }
20376
+ }
20377
+ const detectedTimezone = detectTimezone();
20378
+ let timezone = options.timezone;
20379
+ if (!timezone) {
20380
+ if (isInteractive()) {
20381
+ timezone = await promptText("Timezone", detectedTimezone);
20382
+ if (!timezone) {
20383
+ console.log(chalk29.dim("Cancelled"));
20384
+ return;
20385
+ }
20386
+ } else {
20387
+ timezone = detectedTimezone;
20388
+ }
20389
+ }
20390
+ let promptText_ = options.prompt;
20391
+ if (!promptText_) {
20392
+ if (!isInteractive()) {
20393
+ console.error(chalk29.red("\u2717 --prompt is required"));
20394
+ process.exit(1);
20395
+ }
20396
+ promptText_ = await promptText(
20397
+ "Prompt to run",
20398
+ "let's start working."
20399
+ );
20400
+ if (!promptText_) {
20401
+ console.log(chalk29.dim("Cancelled"));
20402
+ return;
20403
+ }
20404
+ }
20405
+ let vars;
20406
+ let secrets;
20407
+ if (options.vars) {
20408
+ const extracted = extractVarsAndSecrets();
20409
+ if (extracted.vars.length > 0 || extracted.secrets.length > 0) {
20410
+ let includeVars = true;
20411
+ if (isInteractive()) {
20412
+ const varCount = extracted.vars.length;
20413
+ const secretCount = extracted.secrets.length;
20414
+ const parts = [];
20415
+ if (varCount > 0) parts.push(`${varCount} variable(s)`);
20416
+ if (secretCount > 0) parts.push(`${secretCount} secret(s)`);
20417
+ const itemList = [
20418
+ ...extracted.vars.map((v) => `vars.${v}`),
20419
+ ...extracted.secrets.map((s) => `secrets.${s}`)
20420
+ ];
20421
+ includeVars = await promptConfirm(
20422
+ `Include ${parts.join(" and ")} from vm0.yaml? (${itemList.join(", ")})`,
20423
+ true
20424
+ ) ?? true;
20425
+ }
20426
+ if (includeVars) {
20427
+ if (extracted.vars.length > 0) {
20428
+ vars = {};
20429
+ for (const v of extracted.vars) {
20430
+ vars[v] = `\${${v}}`;
20431
+ }
20432
+ }
20433
+ if (extracted.secrets.length > 0) {
20434
+ secrets = {};
20435
+ for (const s of extracted.secrets) {
20436
+ secrets[s] = `\${${s}}`;
20437
+ }
20438
+ }
20439
+ }
20440
+ }
20441
+ }
20442
+ const scheduleYaml = {
20443
+ version: "1.0",
20444
+ schedules: {
20445
+ [scheduleName]: {
20446
+ on: {
20447
+ timezone
20448
+ },
20449
+ run: {
20450
+ agent: agentName,
20451
+ prompt: promptText_
20452
+ }
20453
+ }
20454
+ }
20455
+ };
20456
+ if (atTime) {
20457
+ scheduleYaml.schedules[scheduleName].on.at = atTime;
20458
+ } else if (time3 && frequency !== "once") {
20459
+ scheduleYaml.schedules[scheduleName].on.cron = generateCronExpression(frequency, time3, day);
20460
+ }
20461
+ if (vars && Object.keys(vars).length > 0) {
20462
+ scheduleYaml.schedules[scheduleName].run.vars = vars;
20463
+ }
20464
+ if (secrets && Object.keys(secrets).length > 0) {
20465
+ scheduleYaml.schedules[scheduleName].run.secrets = secrets;
20466
+ }
20467
+ writeFileSync(SCHEDULE_FILE, stringifyYaml2(scheduleYaml));
20468
+ console.log(chalk29.green(`\u2713 Created ${SCHEDULE_FILE}`));
20469
+ console.log(chalk29.dim(" Deploy with: vm0 schedule deploy"));
20470
+ } catch (error43) {
20471
+ console.error(chalk29.red("\u2717 Failed to create schedule.yaml"));
20472
+ if (error43 instanceof Error) {
20473
+ console.error(chalk29.dim(` ${error43.message}`));
20474
+ }
20475
+ process.exit(1);
20476
+ }
20477
+ }
20478
+ );
20479
+
20480
+ // src/commands/schedule/deploy.ts
20481
+ import { Command as Command28 } from "commander";
20482
+ import chalk30 from "chalk";
20483
+ import { existsSync as existsSync13, readFileSync as readFileSync3 } from "fs";
20484
+ import { parse as parseYaml7 } from "yaml";
20069
20485
  function expandEnvVars(value) {
20070
20486
  return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
20071
20487
  const envValue = process.env[varName];
20072
20488
  if (envValue === void 0) {
20073
20489
  console.warn(
20074
- chalk29.yellow(` Warning: Environment variable ${varName} not set`)
20490
+ chalk30.yellow(` Warning: Environment variable ${varName} not set`)
20075
20491
  );
20076
20492
  return match;
20077
20493
  }
@@ -20086,30 +20502,30 @@ function expandEnvVarsInObject(obj) {
20086
20502
  }
20087
20503
  return result;
20088
20504
  }
20089
- var deployCommand = new Command27().name("deploy").description("Deploy a schedule from schedule.yaml (create or update)").argument("[file]", "Path to schedule.yaml", "schedule.yaml").action(async (file2) => {
20505
+ var deployCommand = new Command28().name("deploy").description("Deploy a schedule from schedule.yaml (create or update)").argument("[file]", "Path to schedule.yaml", "schedule.yaml").action(async (file2) => {
20090
20506
  try {
20091
- if (!existsSync11(file2)) {
20092
- console.error(chalk29.red(`\u2717 File not found: ${file2}`));
20093
- console.error(chalk29.dim(" Create a schedule.yaml file first"));
20507
+ if (!existsSync13(file2)) {
20508
+ console.error(chalk30.red(`\u2717 File not found: ${file2}`));
20509
+ console.error(chalk30.dim(" Create a schedule.yaml file first"));
20094
20510
  process.exit(1);
20095
20511
  }
20096
- const content = readFileSync2(file2, "utf-8");
20512
+ const content = readFileSync3(file2, "utf-8");
20097
20513
  let parsed;
20098
20514
  try {
20099
- parsed = parseYaml6(content);
20515
+ parsed = parseYaml7(content);
20100
20516
  } catch (err) {
20101
- console.error(chalk29.red("\u2717 Invalid YAML syntax"));
20517
+ console.error(chalk30.red("\u2717 Invalid YAML syntax"));
20102
20518
  if (err instanceof Error) {
20103
- console.error(chalk29.dim(` ${err.message}`));
20519
+ console.error(chalk30.dim(` ${err.message}`));
20104
20520
  }
20105
20521
  process.exit(1);
20106
20522
  }
20107
20523
  const result = scheduleYamlSchema.safeParse(parsed);
20108
20524
  if (!result.success) {
20109
- console.error(chalk29.red("\u2717 Invalid schedule.yaml format"));
20525
+ console.error(chalk30.red("\u2717 Invalid schedule.yaml format"));
20110
20526
  for (const issue2 of result.error.issues) {
20111
20527
  console.error(
20112
- chalk29.dim(` ${issue2.path.join(".")}: ${issue2.message}`)
20528
+ chalk30.dim(` ${issue2.path.join(".")}: ${issue2.message}`)
20113
20529
  );
20114
20530
  }
20115
20531
  process.exit(1);
@@ -20117,18 +20533,18 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20117
20533
  const scheduleYaml = result.data;
20118
20534
  const scheduleEntries = Object.entries(scheduleYaml.schedules);
20119
20535
  if (scheduleEntries.length === 0) {
20120
- console.error(chalk29.red("\u2717 No schedules defined in file"));
20536
+ console.error(chalk30.red("\u2717 No schedules defined in file"));
20121
20537
  process.exit(1);
20122
20538
  }
20123
20539
  if (scheduleEntries.length > 1) {
20124
20540
  console.error(
20125
- chalk29.red("\u2717 Multiple schedules per file not supported yet")
20541
+ chalk30.red("\u2717 Multiple schedules per file not supported yet")
20126
20542
  );
20127
- console.error(chalk29.dim(" Please use one schedule per file"));
20543
+ console.error(chalk30.dim(" Please use one schedule per file"));
20128
20544
  process.exit(1);
20129
20545
  }
20130
20546
  const [scheduleName, schedule] = scheduleEntries[0];
20131
- console.log(`Deploying schedule ${chalk29.cyan(scheduleName)}...`);
20547
+ console.log(`Deploying schedule ${chalk30.cyan(scheduleName)}...`);
20132
20548
  const agentRef = schedule.run.agent;
20133
20549
  let composeId;
20134
20550
  try {
@@ -20137,8 +20553,8 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20137
20553
  const compose = await apiClient.getComposeByName(agentName);
20138
20554
  composeId = compose.id;
20139
20555
  } catch {
20140
- console.error(chalk29.red(`\u2717 Agent not found: ${agentRef}`));
20141
- console.error(chalk29.dim(" Make sure the agent is pushed first"));
20556
+ console.error(chalk30.red(`\u2717 Agent not found: ${agentRef}`));
20557
+ console.error(chalk30.dim(" Make sure the agent is pushed first"));
20142
20558
  process.exit(1);
20143
20559
  }
20144
20560
  const expandedVars = expandEnvVarsInObject(schedule.run.vars);
@@ -20166,33 +20582,33 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20166
20582
  const deployResult = await response.json();
20167
20583
  if (deployResult.created) {
20168
20584
  console.log(
20169
- chalk29.green(`\u2713 Created schedule ${chalk29.cyan(scheduleName)}`)
20585
+ chalk30.green(`\u2713 Created schedule ${chalk30.cyan(scheduleName)}`)
20170
20586
  );
20171
20587
  } else {
20172
20588
  console.log(
20173
- chalk29.green(`\u2713 Updated schedule ${chalk29.cyan(scheduleName)}`)
20589
+ chalk30.green(`\u2713 Updated schedule ${chalk30.cyan(scheduleName)}`)
20174
20590
  );
20175
20591
  }
20176
20592
  if (deployResult.schedule.nextRunAt) {
20177
20593
  const nextRun = new Date(deployResult.schedule.nextRunAt);
20178
- console.log(chalk29.dim(` Next run: ${nextRun.toLocaleString()}`));
20594
+ console.log(chalk30.dim(` Next run: ${nextRun.toLocaleString()}`));
20179
20595
  }
20180
20596
  if (deployResult.schedule.cronExpression) {
20181
20597
  console.log(
20182
- chalk29.dim(
20598
+ chalk30.dim(
20183
20599
  ` Cron: ${deployResult.schedule.cronExpression} (${deployResult.schedule.timezone})`
20184
20600
  )
20185
20601
  );
20186
20602
  } else if (deployResult.schedule.atTime) {
20187
- console.log(chalk29.dim(` At: ${deployResult.schedule.atTime}`));
20603
+ console.log(chalk30.dim(` At: ${deployResult.schedule.atTime}`));
20188
20604
  }
20189
20605
  } catch (error43) {
20190
- console.error(chalk29.red("\u2717 Failed to deploy schedule"));
20606
+ console.error(chalk30.red("\u2717 Failed to deploy schedule"));
20191
20607
  if (error43 instanceof Error) {
20192
20608
  if (error43.message.includes("Not authenticated")) {
20193
- console.error(chalk29.dim(" Run: vm0 auth login"));
20609
+ console.error(chalk30.dim(" Run: vm0 auth login"));
20194
20610
  } else {
20195
- console.error(chalk29.dim(` ${error43.message}`));
20611
+ console.error(chalk30.dim(` ${error43.message}`));
20196
20612
  }
20197
20613
  }
20198
20614
  process.exit(1);
@@ -20200,59 +20616,9 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20200
20616
  });
20201
20617
 
20202
20618
  // src/commands/schedule/list.ts
20203
- import { Command as Command28 } from "commander";
20204
- import chalk30 from "chalk";
20205
-
20206
- // src/lib/schedule-utils.ts
20207
- import { existsSync as existsSync12, readFileSync as readFileSync3 } from "fs";
20208
- import { parse as parseYaml7 } from "yaml";
20209
- var CONFIG_FILE4 = "vm0.yaml";
20210
- function loadAgentName() {
20211
- if (!existsSync12(CONFIG_FILE4)) {
20212
- return { agentName: null };
20213
- }
20214
- try {
20215
- const content = readFileSync3(CONFIG_FILE4, "utf8");
20216
- const config2 = parseYaml7(content);
20217
- const agentNames = Object.keys(config2.agents || {});
20218
- return { agentName: agentNames[0] || null };
20219
- } catch (err) {
20220
- return {
20221
- agentName: null,
20222
- error: err instanceof Error ? err.message : "Failed to parse vm0.yaml"
20223
- };
20224
- }
20225
- }
20226
- function formatRelativeTime2(dateStr) {
20227
- if (!dateStr) return "-";
20228
- const date5 = new Date(dateStr);
20229
- const now = /* @__PURE__ */ new Date();
20230
- const diffMs = date5.getTime() - now.getTime();
20231
- const diffAbs = Math.abs(diffMs);
20232
- const minutes = Math.floor(diffAbs / (1e3 * 60));
20233
- const hours = Math.floor(diffAbs / (1e3 * 60 * 60));
20234
- const days = Math.floor(diffAbs / (1e3 * 60 * 60 * 24));
20235
- const isPast = diffMs < 0;
20236
- if (days > 0) {
20237
- return isPast ? `${days}d ago` : `in ${days}d`;
20238
- } else if (hours > 0) {
20239
- return isPast ? `${hours}h ago` : `in ${hours}h`;
20240
- } else if (minutes > 0) {
20241
- return isPast ? `${minutes}m ago` : `in ${minutes}m`;
20242
- } else {
20243
- return isPast ? "just now" : "soon";
20244
- }
20245
- }
20246
- function formatDateTime(dateStr) {
20247
- if (!dateStr) return "-";
20248
- const date5 = new Date(dateStr);
20249
- const formatted = date5.toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC");
20250
- const relative2 = formatRelativeTime2(dateStr);
20251
- return `${formatted} (${relative2})`;
20252
- }
20253
-
20254
- // src/commands/schedule/list.ts
20255
- var listCommand4 = new Command28().name("list").alias("ls").description("List all schedules").action(async () => {
20619
+ import { Command as Command29 } from "commander";
20620
+ import chalk31 from "chalk";
20621
+ var listCommand4 = new Command29().name("list").alias("ls").description("List all schedules").action(async () => {
20256
20622
  try {
20257
20623
  const response = await apiClient.get("/api/agent/schedules");
20258
20624
  if (!response.ok) {
@@ -20261,9 +20627,9 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20261
20627
  }
20262
20628
  const result = await response.json();
20263
20629
  if (result.schedules.length === 0) {
20264
- console.log(chalk30.dim("No schedules found"));
20630
+ console.log(chalk31.dim("No schedules found"));
20265
20631
  console.log(
20266
- chalk30.dim(" Create one with: vm0 schedule deploy schedule.yaml")
20632
+ chalk31.dim(" Create one with: vm0 schedule deploy schedule.yaml")
20267
20633
  );
20268
20634
  return;
20269
20635
  }
@@ -20288,10 +20654,10 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20288
20654
  "STATUS".padEnd(8),
20289
20655
  "NEXT RUN"
20290
20656
  ].join(" ");
20291
- console.log(chalk30.dim(header));
20657
+ console.log(chalk31.dim(header));
20292
20658
  for (const schedule of result.schedules) {
20293
20659
  const trigger = schedule.cronExpression ? `${schedule.cronExpression} (${schedule.timezone})` : schedule.atTime || "-";
20294
- const status = schedule.enabled ? chalk30.green("enabled") : chalk30.yellow("disabled");
20660
+ const status = schedule.enabled ? chalk31.green("enabled") : chalk31.yellow("disabled");
20295
20661
  const nextRun = schedule.enabled ? formatRelativeTime2(schedule.nextRunAt) : "-";
20296
20662
  const row = [
20297
20663
  schedule.name.padEnd(nameWidth),
@@ -20304,12 +20670,12 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20304
20670
  console.log(row);
20305
20671
  }
20306
20672
  } catch (error43) {
20307
- console.error(chalk30.red("\u2717 Failed to list schedules"));
20673
+ console.error(chalk31.red("\u2717 Failed to list schedules"));
20308
20674
  if (error43 instanceof Error) {
20309
20675
  if (error43.message.includes("Not authenticated")) {
20310
- console.error(chalk30.dim(" Run: vm0 auth login"));
20676
+ console.error(chalk31.dim(" Run: vm0 auth login"));
20311
20677
  } else {
20312
- console.error(chalk30.dim(` ${error43.message}`));
20678
+ console.error(chalk31.dim(` ${error43.message}`));
20313
20679
  }
20314
20680
  }
20315
20681
  process.exit(1);
@@ -20317,32 +20683,32 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20317
20683
  });
20318
20684
 
20319
20685
  // src/commands/schedule/status.ts
20320
- import { Command as Command29 } from "commander";
20321
- import chalk31 from "chalk";
20686
+ import { Command as Command30 } from "commander";
20687
+ import chalk32 from "chalk";
20322
20688
  function formatDateTimeStyled(dateStr) {
20323
- if (!dateStr) return chalk31.dim("-");
20689
+ if (!dateStr) return chalk32.dim("-");
20324
20690
  const formatted = formatDateTime(dateStr);
20325
- return formatted.replace(/\(([^)]+)\)$/, chalk31.dim("($1)"));
20691
+ return formatted.replace(/\(([^)]+)\)$/, chalk32.dim("($1)"));
20326
20692
  }
20327
20693
  function formatTrigger(schedule) {
20328
20694
  if (schedule.cronExpression) {
20329
- return `${schedule.cronExpression} ${chalk31.dim(`(${schedule.timezone})`)}`;
20695
+ return `${schedule.cronExpression} ${chalk32.dim(`(${schedule.timezone})`)}`;
20330
20696
  }
20331
20697
  if (schedule.atTime) {
20332
- return `${schedule.atTime} ${chalk31.dim("(one-time)")}`;
20698
+ return `${schedule.atTime} ${chalk32.dim("(one-time)")}`;
20333
20699
  }
20334
- return chalk31.dim("-");
20700
+ return chalk32.dim("-");
20335
20701
  }
20336
- var statusCommand4 = new Command29().name("status").description("Show detailed status of a schedule").argument("<name>", "Schedule name").action(async (name) => {
20702
+ var statusCommand4 = new Command30().name("status").description("Show detailed status of a schedule").argument("<name>", "Schedule name").action(async (name) => {
20337
20703
  try {
20338
20704
  const result = loadAgentName();
20339
20705
  if (result.error) {
20340
- console.error(chalk31.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20706
+ console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20341
20707
  process.exit(1);
20342
20708
  }
20343
20709
  if (!result.agentName) {
20344
- console.error(chalk31.red("\u2717 No vm0.yaml found in current directory"));
20345
- console.error(chalk31.dim(" Run this command from the agent directory"));
20710
+ console.error(chalk32.red("\u2717 No vm0.yaml found in current directory"));
20711
+ console.error(chalk32.dim(" Run this command from the agent directory"));
20346
20712
  process.exit(1);
20347
20713
  }
20348
20714
  const agentName = result.agentName;
@@ -20351,8 +20717,8 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20351
20717
  const compose = await apiClient.getComposeByName(agentName);
20352
20718
  composeId = compose.id;
20353
20719
  } catch {
20354
- console.error(chalk31.red(`\u2717 Agent not found: ${agentName}`));
20355
- console.error(chalk31.dim(" Make sure the agent is pushed first"));
20720
+ console.error(chalk32.red(`\u2717 Agent not found: ${agentName}`));
20721
+ console.error(chalk32.dim(" Make sure the agent is pushed first"));
20356
20722
  process.exit(1);
20357
20723
  }
20358
20724
  const response = await apiClient.get(
@@ -20364,12 +20730,12 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20364
20730
  }
20365
20731
  const schedule = await response.json();
20366
20732
  console.log();
20367
- console.log(`Schedule: ${chalk31.cyan(schedule.name)}`);
20368
- console.log(chalk31.dim("\u2501".repeat(50)));
20369
- const statusText = schedule.enabled ? chalk31.green("enabled") : chalk31.yellow("disabled");
20733
+ console.log(`Schedule: ${chalk32.cyan(schedule.name)}`);
20734
+ console.log(chalk32.dim("\u2501".repeat(50)));
20735
+ const statusText = schedule.enabled ? chalk32.green("enabled") : chalk32.yellow("disabled");
20370
20736
  console.log(`${"Status:".padEnd(16)}${statusText}`);
20371
20737
  console.log(
20372
- `${"Agent:".padEnd(16)}${schedule.composeName} ${chalk31.dim(`(${schedule.scopeSlug})`)}`
20738
+ `${"Agent:".padEnd(16)}${schedule.composeName} ${chalk32.dim(`(${schedule.scopeSlug})`)}`
20373
20739
  );
20374
20740
  console.log(`${"Trigger:".padEnd(16)}${formatTrigger(schedule)}`);
20375
20741
  if (schedule.enabled) {
@@ -20378,11 +20744,11 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20378
20744
  );
20379
20745
  }
20380
20746
  if (schedule.lastRunAt) {
20381
- const lastRunInfo = schedule.lastRunId ? `${formatDateTimeStyled(schedule.lastRunAt)} ${chalk31.dim(`[${schedule.lastRunId.slice(0, 8)}]`)}` : formatDateTimeStyled(schedule.lastRunAt);
20747
+ const lastRunInfo = schedule.lastRunId ? `${formatDateTimeStyled(schedule.lastRunAt)} ${chalk32.dim(`[${schedule.lastRunId.slice(0, 8)}]`)}` : formatDateTimeStyled(schedule.lastRunAt);
20382
20748
  console.log(`${"Last Run:".padEnd(16)}${lastRunInfo}`);
20383
20749
  }
20384
20750
  const promptPreview = schedule.prompt.length > 60 ? schedule.prompt.slice(0, 57) + "..." : schedule.prompt;
20385
- console.log(`${"Prompt:".padEnd(16)}${chalk31.dim(promptPreview)}`);
20751
+ console.log(`${"Prompt:".padEnd(16)}${chalk32.dim(promptPreview)}`);
20386
20752
  if (schedule.vars && Object.keys(schedule.vars).length > 0) {
20387
20753
  console.log(
20388
20754
  `${"Variables:".padEnd(16)}${Object.keys(schedule.vars).join(", ")}`
@@ -20404,26 +20770,26 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20404
20770
  }
20405
20771
  console.log();
20406
20772
  console.log(
20407
- chalk31.dim(
20773
+ chalk32.dim(
20408
20774
  `Created: ${new Date(schedule.createdAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
20409
20775
  )
20410
20776
  );
20411
20777
  console.log(
20412
- chalk31.dim(
20778
+ chalk32.dim(
20413
20779
  `Updated: ${new Date(schedule.updatedAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
20414
20780
  )
20415
20781
  );
20416
- console.log(chalk31.dim(`ID: ${schedule.id}`));
20782
+ console.log(chalk32.dim(`ID: ${schedule.id}`));
20417
20783
  console.log();
20418
20784
  } catch (error43) {
20419
- console.error(chalk31.red("\u2717 Failed to get schedule status"));
20785
+ console.error(chalk32.red("\u2717 Failed to get schedule status"));
20420
20786
  if (error43 instanceof Error) {
20421
20787
  if (error43.message.includes("Not authenticated")) {
20422
- console.error(chalk31.dim(" Run: vm0 auth login"));
20788
+ console.error(chalk32.dim(" Run: vm0 auth login"));
20423
20789
  } else if (error43.message.includes("not found") || error43.message.includes("Not found")) {
20424
- console.error(chalk31.dim(` Schedule "${name}" not found`));
20790
+ console.error(chalk32.dim(` Schedule "${name}" not found`));
20425
20791
  } else {
20426
- console.error(chalk31.dim(` ${error43.message}`));
20792
+ console.error(chalk32.dim(` ${error43.message}`));
20427
20793
  }
20428
20794
  }
20429
20795
  process.exit(1);
@@ -20431,8 +20797,8 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20431
20797
  });
20432
20798
 
20433
20799
  // src/commands/schedule/delete.ts
20434
- import { Command as Command30 } from "commander";
20435
- import chalk32 from "chalk";
20800
+ import { Command as Command31 } from "commander";
20801
+ import chalk33 from "chalk";
20436
20802
  import * as readline from "readline";
20437
20803
  async function confirm(message) {
20438
20804
  const rl = readline.createInterface({
@@ -20446,16 +20812,16 @@ async function confirm(message) {
20446
20812
  });
20447
20813
  });
20448
20814
  }
20449
- var deleteCommand = new Command30().name("delete").alias("rm").description("Delete a schedule").argument("<name>", "Schedule name to delete").option("-f, --force", "Skip confirmation prompt").action(async (name, options) => {
20815
+ var deleteCommand = new Command31().name("delete").alias("rm").description("Delete a schedule").argument("<name>", "Schedule name to delete").option("-f, --force", "Skip confirmation prompt").action(async (name, options) => {
20450
20816
  try {
20451
20817
  const result = loadAgentName();
20452
20818
  if (result.error) {
20453
- console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20819
+ console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20454
20820
  process.exit(1);
20455
20821
  }
20456
20822
  if (!result.agentName) {
20457
- console.error(chalk32.red("\u2717 No vm0.yaml found in current directory"));
20458
- console.error(chalk32.dim(" Run this command from the agent directory"));
20823
+ console.error(chalk33.red("\u2717 No vm0.yaml found in current directory"));
20824
+ console.error(chalk33.dim(" Run this command from the agent directory"));
20459
20825
  process.exit(1);
20460
20826
  }
20461
20827
  const agentName = result.agentName;
@@ -20464,14 +20830,14 @@ var deleteCommand = new Command30().name("delete").alias("rm").description("Dele
20464
20830
  const compose = await apiClient.getComposeByName(agentName);
20465
20831
  composeId = compose.id;
20466
20832
  } catch {
20467
- console.error(chalk32.red(`\u2717 Agent not found: ${agentName}`));
20468
- console.error(chalk32.dim(" Make sure the agent is pushed first"));
20833
+ console.error(chalk33.red(`\u2717 Agent not found: ${agentName}`));
20834
+ console.error(chalk33.dim(" Make sure the agent is pushed first"));
20469
20835
  process.exit(1);
20470
20836
  }
20471
20837
  if (!options.force) {
20472
- const confirmed = await confirm(`Delete schedule ${chalk32.cyan(name)}?`);
20838
+ const confirmed = await confirm(`Delete schedule ${chalk33.cyan(name)}?`);
20473
20839
  if (!confirmed) {
20474
- console.log(chalk32.dim("Cancelled"));
20840
+ console.log(chalk33.dim("Cancelled"));
20475
20841
  return;
20476
20842
  }
20477
20843
  }
@@ -20482,14 +20848,14 @@ var deleteCommand = new Command30().name("delete").alias("rm").description("Dele
20482
20848
  const error43 = await response.json();
20483
20849
  throw new Error(error43.error?.message || "Delete failed");
20484
20850
  }
20485
- console.log(chalk32.green(`\u2713 Deleted schedule ${chalk32.cyan(name)}`));
20851
+ console.log(chalk33.green(`\u2713 Deleted schedule ${chalk33.cyan(name)}`));
20486
20852
  } catch (error43) {
20487
- console.error(chalk32.red("\u2717 Failed to delete schedule"));
20853
+ console.error(chalk33.red("\u2717 Failed to delete schedule"));
20488
20854
  if (error43 instanceof Error) {
20489
20855
  if (error43.message.includes("Not authenticated")) {
20490
- console.error(chalk32.dim(" Run: vm0 auth login"));
20856
+ console.error(chalk33.dim(" Run: vm0 auth login"));
20491
20857
  } else {
20492
- console.error(chalk32.dim(` ${error43.message}`));
20858
+ console.error(chalk33.dim(` ${error43.message}`));
20493
20859
  }
20494
20860
  }
20495
20861
  process.exit(1);
@@ -20497,18 +20863,18 @@ var deleteCommand = new Command30().name("delete").alias("rm").description("Dele
20497
20863
  });
20498
20864
 
20499
20865
  // src/commands/schedule/enable.ts
20500
- import { Command as Command31 } from "commander";
20501
- import chalk33 from "chalk";
20502
- var enableCommand = new Command31().name("enable").description("Enable a schedule").argument("<name>", "Schedule name to enable").action(async (name) => {
20866
+ import { Command as Command32 } from "commander";
20867
+ import chalk34 from "chalk";
20868
+ var enableCommand = new Command32().name("enable").description("Enable a schedule").argument("<name>", "Schedule name to enable").action(async (name) => {
20503
20869
  try {
20504
20870
  const result = loadAgentName();
20505
20871
  if (result.error) {
20506
- console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20872
+ console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20507
20873
  process.exit(1);
20508
20874
  }
20509
20875
  if (!result.agentName) {
20510
- console.error(chalk33.red("\u2717 No vm0.yaml found in current directory"));
20511
- console.error(chalk33.dim(" Run this command from the agent directory"));
20876
+ console.error(chalk34.red("\u2717 No vm0.yaml found in current directory"));
20877
+ console.error(chalk34.dim(" Run this command from the agent directory"));
20512
20878
  process.exit(1);
20513
20879
  }
20514
20880
  const agentName = result.agentName;
@@ -20517,8 +20883,8 @@ var enableCommand = new Command31().name("enable").description("Enable a schedul
20517
20883
  const compose = await apiClient.getComposeByName(agentName);
20518
20884
  composeId = compose.id;
20519
20885
  } catch {
20520
- console.error(chalk33.red(`\u2717 Agent not found: ${agentName}`));
20521
- console.error(chalk33.dim(" Make sure the agent is pushed first"));
20886
+ console.error(chalk34.red(`\u2717 Agent not found: ${agentName}`));
20887
+ console.error(chalk34.dim(" Make sure the agent is pushed first"));
20522
20888
  process.exit(1);
20523
20889
  }
20524
20890
  const response = await apiClient.post(
@@ -20529,14 +20895,14 @@ var enableCommand = new Command31().name("enable").description("Enable a schedul
20529
20895
  const error43 = await response.json();
20530
20896
  throw new Error(error43.error?.message || "Enable failed");
20531
20897
  }
20532
- console.log(chalk33.green(`\u2713 Enabled schedule ${chalk33.cyan(name)}`));
20898
+ console.log(chalk34.green(`\u2713 Enabled schedule ${chalk34.cyan(name)}`));
20533
20899
  } catch (error43) {
20534
- console.error(chalk33.red("\u2717 Failed to enable schedule"));
20900
+ console.error(chalk34.red("\u2717 Failed to enable schedule"));
20535
20901
  if (error43 instanceof Error) {
20536
20902
  if (error43.message.includes("Not authenticated")) {
20537
- console.error(chalk33.dim(" Run: vm0 auth login"));
20903
+ console.error(chalk34.dim(" Run: vm0 auth login"));
20538
20904
  } else {
20539
- console.error(chalk33.dim(` ${error43.message}`));
20905
+ console.error(chalk34.dim(` ${error43.message}`));
20540
20906
  }
20541
20907
  }
20542
20908
  process.exit(1);
@@ -20544,18 +20910,18 @@ var enableCommand = new Command31().name("enable").description("Enable a schedul
20544
20910
  });
20545
20911
 
20546
20912
  // src/commands/schedule/disable.ts
20547
- import { Command as Command32 } from "commander";
20548
- import chalk34 from "chalk";
20549
- var disableCommand = new Command32().name("disable").description("Disable a schedule").argument("<name>", "Schedule name to disable").action(async (name) => {
20913
+ import { Command as Command33 } from "commander";
20914
+ import chalk35 from "chalk";
20915
+ var disableCommand = new Command33().name("disable").description("Disable a schedule").argument("<name>", "Schedule name to disable").action(async (name) => {
20550
20916
  try {
20551
20917
  const result = loadAgentName();
20552
20918
  if (result.error) {
20553
- console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20919
+ console.error(chalk35.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20554
20920
  process.exit(1);
20555
20921
  }
20556
20922
  if (!result.agentName) {
20557
- console.error(chalk34.red("\u2717 No vm0.yaml found in current directory"));
20558
- console.error(chalk34.dim(" Run this command from the agent directory"));
20923
+ console.error(chalk35.red("\u2717 No vm0.yaml found in current directory"));
20924
+ console.error(chalk35.dim(" Run this command from the agent directory"));
20559
20925
  process.exit(1);
20560
20926
  }
20561
20927
  const agentName = result.agentName;
@@ -20564,8 +20930,8 @@ var disableCommand = new Command32().name("disable").description("Disable a sche
20564
20930
  const compose = await apiClient.getComposeByName(agentName);
20565
20931
  composeId = compose.id;
20566
20932
  } catch {
20567
- console.error(chalk34.red(`\u2717 Agent not found: ${agentName}`));
20568
- console.error(chalk34.dim(" Make sure the agent is pushed first"));
20933
+ console.error(chalk35.red(`\u2717 Agent not found: ${agentName}`));
20934
+ console.error(chalk35.dim(" Make sure the agent is pushed first"));
20569
20935
  process.exit(1);
20570
20936
  }
20571
20937
  const response = await apiClient.post(
@@ -20576,14 +20942,14 @@ var disableCommand = new Command32().name("disable").description("Disable a sche
20576
20942
  const error43 = await response.json();
20577
20943
  throw new Error(error43.error?.message || "Disable failed");
20578
20944
  }
20579
- console.log(chalk34.green(`\u2713 Disabled schedule ${chalk34.cyan(name)}`));
20945
+ console.log(chalk35.green(`\u2713 Disabled schedule ${chalk35.cyan(name)}`));
20580
20946
  } catch (error43) {
20581
- console.error(chalk34.red("\u2717 Failed to disable schedule"));
20947
+ console.error(chalk35.red("\u2717 Failed to disable schedule"));
20582
20948
  if (error43 instanceof Error) {
20583
20949
  if (error43.message.includes("Not authenticated")) {
20584
- console.error(chalk34.dim(" Run: vm0 auth login"));
20950
+ console.error(chalk35.dim(" Run: vm0 auth login"));
20585
20951
  } else {
20586
- console.error(chalk34.dim(` ${error43.message}`));
20952
+ console.error(chalk35.dim(` ${error43.message}`));
20587
20953
  }
20588
20954
  }
20589
20955
  process.exit(1);
@@ -20591,13 +20957,13 @@ var disableCommand = new Command32().name("disable").description("Disable a sche
20591
20957
  });
20592
20958
 
20593
20959
  // src/commands/schedule/index.ts
20594
- var scheduleCommand = new Command33().name("schedule").description("Manage agent schedules").addCommand(deployCommand).addCommand(listCommand4).addCommand(statusCommand4).addCommand(deleteCommand).addCommand(enableCommand).addCommand(disableCommand);
20960
+ var scheduleCommand = new Command34().name("schedule").description("Manage agent schedules").addCommand(initCommand4).addCommand(deployCommand).addCommand(listCommand4).addCommand(statusCommand4).addCommand(deleteCommand).addCommand(enableCommand).addCommand(disableCommand);
20595
20961
 
20596
20962
  // src/index.ts
20597
- var program = new Command34();
20598
- program.name("vm0").description("VM0 CLI - A modern build tool").version("5.2.0");
20963
+ var program = new Command35();
20964
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("5.3.1");
20599
20965
  program.command("info").description("Display environment information").action(async () => {
20600
- console.log(chalk35.bold("System Information:"));
20966
+ console.log(chalk36.bold("System Information:"));
20601
20967
  console.log(`Node Version: ${process.version}`);
20602
20968
  console.log(`Platform: ${process.platform}`);
20603
20969
  console.log(`Architecture: ${process.arch}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "5.2.0",
3
+ "version": "5.3.1",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",