@vm0/cli 5.2.0 → 5.3.0

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 +571 -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.0", 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,437 @@ 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("Prompt to run");
20397
+ if (!promptText_) {
20398
+ console.log(chalk29.dim("Cancelled"));
20399
+ return;
20400
+ }
20401
+ }
20402
+ let vars;
20403
+ let secrets;
20404
+ if (options.vars) {
20405
+ const extracted = extractVarsAndSecrets();
20406
+ if (extracted.vars.length > 0 || extracted.secrets.length > 0) {
20407
+ let includeVars = true;
20408
+ if (isInteractive()) {
20409
+ const varList = [
20410
+ ...extracted.vars.map((v) => `vars.${v}`),
20411
+ ...extracted.secrets.map((s) => `secrets.${s}`)
20412
+ ];
20413
+ includeVars = await promptConfirm(
20414
+ `Include ${varList.length} variable(s) from vm0.yaml? (${varList.join(", ")})`,
20415
+ true
20416
+ ) ?? true;
20417
+ }
20418
+ if (includeVars) {
20419
+ if (extracted.vars.length > 0) {
20420
+ vars = {};
20421
+ for (const v of extracted.vars) {
20422
+ vars[v] = `\${${v}}`;
20423
+ }
20424
+ }
20425
+ if (extracted.secrets.length > 0) {
20426
+ secrets = {};
20427
+ for (const s of extracted.secrets) {
20428
+ secrets[s] = `\${${s}}`;
20429
+ }
20430
+ }
20431
+ }
20432
+ }
20433
+ }
20434
+ const scheduleYaml = {
20435
+ version: "1.0",
20436
+ schedules: {
20437
+ [scheduleName]: {
20438
+ on: {
20439
+ timezone
20440
+ },
20441
+ run: {
20442
+ agent: agentName,
20443
+ prompt: promptText_
20444
+ }
20445
+ }
20446
+ }
20447
+ };
20448
+ if (atTime) {
20449
+ scheduleYaml.schedules[scheduleName].on.at = atTime;
20450
+ } else if (time3 && frequency !== "once") {
20451
+ scheduleYaml.schedules[scheduleName].on.cron = generateCronExpression(frequency, time3, day);
20452
+ }
20453
+ if (vars && Object.keys(vars).length > 0) {
20454
+ scheduleYaml.schedules[scheduleName].run.vars = vars;
20455
+ }
20456
+ if (secrets && Object.keys(secrets).length > 0) {
20457
+ scheduleYaml.schedules[scheduleName].run.secrets = secrets;
20458
+ }
20459
+ writeFileSync(SCHEDULE_FILE, stringifyYaml2(scheduleYaml));
20460
+ console.log(chalk29.green(`\u2713 Created ${SCHEDULE_FILE}`));
20461
+ console.log(chalk29.dim(" Deploy with: vm0 schedule deploy"));
20462
+ } catch (error43) {
20463
+ console.error(chalk29.red("\u2717 Failed to create schedule.yaml"));
20464
+ if (error43 instanceof Error) {
20465
+ console.error(chalk29.dim(` ${error43.message}`));
20466
+ }
20467
+ process.exit(1);
20468
+ }
20469
+ }
20470
+ );
20471
+
20472
+ // src/commands/schedule/deploy.ts
20473
+ import { Command as Command28 } from "commander";
20474
+ import chalk30 from "chalk";
20475
+ import { existsSync as existsSync13, readFileSync as readFileSync3 } from "fs";
20476
+ import { parse as parseYaml7 } from "yaml";
20069
20477
  function expandEnvVars(value) {
20070
20478
  return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
20071
20479
  const envValue = process.env[varName];
20072
20480
  if (envValue === void 0) {
20073
20481
  console.warn(
20074
- chalk29.yellow(` Warning: Environment variable ${varName} not set`)
20482
+ chalk30.yellow(` Warning: Environment variable ${varName} not set`)
20075
20483
  );
20076
20484
  return match;
20077
20485
  }
@@ -20086,30 +20494,30 @@ function expandEnvVarsInObject(obj) {
20086
20494
  }
20087
20495
  return result;
20088
20496
  }
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) => {
20497
+ 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
20498
  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"));
20499
+ if (!existsSync13(file2)) {
20500
+ console.error(chalk30.red(`\u2717 File not found: ${file2}`));
20501
+ console.error(chalk30.dim(" Create a schedule.yaml file first"));
20094
20502
  process.exit(1);
20095
20503
  }
20096
- const content = readFileSync2(file2, "utf-8");
20504
+ const content = readFileSync3(file2, "utf-8");
20097
20505
  let parsed;
20098
20506
  try {
20099
- parsed = parseYaml6(content);
20507
+ parsed = parseYaml7(content);
20100
20508
  } catch (err) {
20101
- console.error(chalk29.red("\u2717 Invalid YAML syntax"));
20509
+ console.error(chalk30.red("\u2717 Invalid YAML syntax"));
20102
20510
  if (err instanceof Error) {
20103
- console.error(chalk29.dim(` ${err.message}`));
20511
+ console.error(chalk30.dim(` ${err.message}`));
20104
20512
  }
20105
20513
  process.exit(1);
20106
20514
  }
20107
20515
  const result = scheduleYamlSchema.safeParse(parsed);
20108
20516
  if (!result.success) {
20109
- console.error(chalk29.red("\u2717 Invalid schedule.yaml format"));
20517
+ console.error(chalk30.red("\u2717 Invalid schedule.yaml format"));
20110
20518
  for (const issue2 of result.error.issues) {
20111
20519
  console.error(
20112
- chalk29.dim(` ${issue2.path.join(".")}: ${issue2.message}`)
20520
+ chalk30.dim(` ${issue2.path.join(".")}: ${issue2.message}`)
20113
20521
  );
20114
20522
  }
20115
20523
  process.exit(1);
@@ -20117,18 +20525,18 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20117
20525
  const scheduleYaml = result.data;
20118
20526
  const scheduleEntries = Object.entries(scheduleYaml.schedules);
20119
20527
  if (scheduleEntries.length === 0) {
20120
- console.error(chalk29.red("\u2717 No schedules defined in file"));
20528
+ console.error(chalk30.red("\u2717 No schedules defined in file"));
20121
20529
  process.exit(1);
20122
20530
  }
20123
20531
  if (scheduleEntries.length > 1) {
20124
20532
  console.error(
20125
- chalk29.red("\u2717 Multiple schedules per file not supported yet")
20533
+ chalk30.red("\u2717 Multiple schedules per file not supported yet")
20126
20534
  );
20127
- console.error(chalk29.dim(" Please use one schedule per file"));
20535
+ console.error(chalk30.dim(" Please use one schedule per file"));
20128
20536
  process.exit(1);
20129
20537
  }
20130
20538
  const [scheduleName, schedule] = scheduleEntries[0];
20131
- console.log(`Deploying schedule ${chalk29.cyan(scheduleName)}...`);
20539
+ console.log(`Deploying schedule ${chalk30.cyan(scheduleName)}...`);
20132
20540
  const agentRef = schedule.run.agent;
20133
20541
  let composeId;
20134
20542
  try {
@@ -20137,8 +20545,8 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20137
20545
  const compose = await apiClient.getComposeByName(agentName);
20138
20546
  composeId = compose.id;
20139
20547
  } catch {
20140
- console.error(chalk29.red(`\u2717 Agent not found: ${agentRef}`));
20141
- console.error(chalk29.dim(" Make sure the agent is pushed first"));
20548
+ console.error(chalk30.red(`\u2717 Agent not found: ${agentRef}`));
20549
+ console.error(chalk30.dim(" Make sure the agent is pushed first"));
20142
20550
  process.exit(1);
20143
20551
  }
20144
20552
  const expandedVars = expandEnvVarsInObject(schedule.run.vars);
@@ -20166,33 +20574,33 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20166
20574
  const deployResult = await response.json();
20167
20575
  if (deployResult.created) {
20168
20576
  console.log(
20169
- chalk29.green(`\u2713 Created schedule ${chalk29.cyan(scheduleName)}`)
20577
+ chalk30.green(`\u2713 Created schedule ${chalk30.cyan(scheduleName)}`)
20170
20578
  );
20171
20579
  } else {
20172
20580
  console.log(
20173
- chalk29.green(`\u2713 Updated schedule ${chalk29.cyan(scheduleName)}`)
20581
+ chalk30.green(`\u2713 Updated schedule ${chalk30.cyan(scheduleName)}`)
20174
20582
  );
20175
20583
  }
20176
20584
  if (deployResult.schedule.nextRunAt) {
20177
20585
  const nextRun = new Date(deployResult.schedule.nextRunAt);
20178
- console.log(chalk29.dim(` Next run: ${nextRun.toLocaleString()}`));
20586
+ console.log(chalk30.dim(` Next run: ${nextRun.toLocaleString()}`));
20179
20587
  }
20180
20588
  if (deployResult.schedule.cronExpression) {
20181
20589
  console.log(
20182
- chalk29.dim(
20590
+ chalk30.dim(
20183
20591
  ` Cron: ${deployResult.schedule.cronExpression} (${deployResult.schedule.timezone})`
20184
20592
  )
20185
20593
  );
20186
20594
  } else if (deployResult.schedule.atTime) {
20187
- console.log(chalk29.dim(` At: ${deployResult.schedule.atTime}`));
20595
+ console.log(chalk30.dim(` At: ${deployResult.schedule.atTime}`));
20188
20596
  }
20189
20597
  } catch (error43) {
20190
- console.error(chalk29.red("\u2717 Failed to deploy schedule"));
20598
+ console.error(chalk30.red("\u2717 Failed to deploy schedule"));
20191
20599
  if (error43 instanceof Error) {
20192
20600
  if (error43.message.includes("Not authenticated")) {
20193
- console.error(chalk29.dim(" Run: vm0 auth login"));
20601
+ console.error(chalk30.dim(" Run: vm0 auth login"));
20194
20602
  } else {
20195
- console.error(chalk29.dim(` ${error43.message}`));
20603
+ console.error(chalk30.dim(` ${error43.message}`));
20196
20604
  }
20197
20605
  }
20198
20606
  process.exit(1);
@@ -20200,59 +20608,9 @@ var deployCommand = new Command27().name("deploy").description("Deploy a schedul
20200
20608
  });
20201
20609
 
20202
20610
  // 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 () => {
20611
+ import { Command as Command29 } from "commander";
20612
+ import chalk31 from "chalk";
20613
+ var listCommand4 = new Command29().name("list").alias("ls").description("List all schedules").action(async () => {
20256
20614
  try {
20257
20615
  const response = await apiClient.get("/api/agent/schedules");
20258
20616
  if (!response.ok) {
@@ -20261,9 +20619,9 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20261
20619
  }
20262
20620
  const result = await response.json();
20263
20621
  if (result.schedules.length === 0) {
20264
- console.log(chalk30.dim("No schedules found"));
20622
+ console.log(chalk31.dim("No schedules found"));
20265
20623
  console.log(
20266
- chalk30.dim(" Create one with: vm0 schedule deploy schedule.yaml")
20624
+ chalk31.dim(" Create one with: vm0 schedule deploy schedule.yaml")
20267
20625
  );
20268
20626
  return;
20269
20627
  }
@@ -20288,10 +20646,10 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20288
20646
  "STATUS".padEnd(8),
20289
20647
  "NEXT RUN"
20290
20648
  ].join(" ");
20291
- console.log(chalk30.dim(header));
20649
+ console.log(chalk31.dim(header));
20292
20650
  for (const schedule of result.schedules) {
20293
20651
  const trigger = schedule.cronExpression ? `${schedule.cronExpression} (${schedule.timezone})` : schedule.atTime || "-";
20294
- const status = schedule.enabled ? chalk30.green("enabled") : chalk30.yellow("disabled");
20652
+ const status = schedule.enabled ? chalk31.green("enabled") : chalk31.yellow("disabled");
20295
20653
  const nextRun = schedule.enabled ? formatRelativeTime2(schedule.nextRunAt) : "-";
20296
20654
  const row = [
20297
20655
  schedule.name.padEnd(nameWidth),
@@ -20304,12 +20662,12 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20304
20662
  console.log(row);
20305
20663
  }
20306
20664
  } catch (error43) {
20307
- console.error(chalk30.red("\u2717 Failed to list schedules"));
20665
+ console.error(chalk31.red("\u2717 Failed to list schedules"));
20308
20666
  if (error43 instanceof Error) {
20309
20667
  if (error43.message.includes("Not authenticated")) {
20310
- console.error(chalk30.dim(" Run: vm0 auth login"));
20668
+ console.error(chalk31.dim(" Run: vm0 auth login"));
20311
20669
  } else {
20312
- console.error(chalk30.dim(` ${error43.message}`));
20670
+ console.error(chalk31.dim(` ${error43.message}`));
20313
20671
  }
20314
20672
  }
20315
20673
  process.exit(1);
@@ -20317,32 +20675,32 @@ var listCommand4 = new Command28().name("list").alias("ls").description("List al
20317
20675
  });
20318
20676
 
20319
20677
  // src/commands/schedule/status.ts
20320
- import { Command as Command29 } from "commander";
20321
- import chalk31 from "chalk";
20678
+ import { Command as Command30 } from "commander";
20679
+ import chalk32 from "chalk";
20322
20680
  function formatDateTimeStyled(dateStr) {
20323
- if (!dateStr) return chalk31.dim("-");
20681
+ if (!dateStr) return chalk32.dim("-");
20324
20682
  const formatted = formatDateTime(dateStr);
20325
- return formatted.replace(/\(([^)]+)\)$/, chalk31.dim("($1)"));
20683
+ return formatted.replace(/\(([^)]+)\)$/, chalk32.dim("($1)"));
20326
20684
  }
20327
20685
  function formatTrigger(schedule) {
20328
20686
  if (schedule.cronExpression) {
20329
- return `${schedule.cronExpression} ${chalk31.dim(`(${schedule.timezone})`)}`;
20687
+ return `${schedule.cronExpression} ${chalk32.dim(`(${schedule.timezone})`)}`;
20330
20688
  }
20331
20689
  if (schedule.atTime) {
20332
- return `${schedule.atTime} ${chalk31.dim("(one-time)")}`;
20690
+ return `${schedule.atTime} ${chalk32.dim("(one-time)")}`;
20333
20691
  }
20334
- return chalk31.dim("-");
20692
+ return chalk32.dim("-");
20335
20693
  }
20336
- var statusCommand4 = new Command29().name("status").description("Show detailed status of a schedule").argument("<name>", "Schedule name").action(async (name) => {
20694
+ var statusCommand4 = new Command30().name("status").description("Show detailed status of a schedule").argument("<name>", "Schedule name").action(async (name) => {
20337
20695
  try {
20338
20696
  const result = loadAgentName();
20339
20697
  if (result.error) {
20340
- console.error(chalk31.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20698
+ console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20341
20699
  process.exit(1);
20342
20700
  }
20343
20701
  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"));
20702
+ console.error(chalk32.red("\u2717 No vm0.yaml found in current directory"));
20703
+ console.error(chalk32.dim(" Run this command from the agent directory"));
20346
20704
  process.exit(1);
20347
20705
  }
20348
20706
  const agentName = result.agentName;
@@ -20351,8 +20709,8 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20351
20709
  const compose = await apiClient.getComposeByName(agentName);
20352
20710
  composeId = compose.id;
20353
20711
  } catch {
20354
- console.error(chalk31.red(`\u2717 Agent not found: ${agentName}`));
20355
- console.error(chalk31.dim(" Make sure the agent is pushed first"));
20712
+ console.error(chalk32.red(`\u2717 Agent not found: ${agentName}`));
20713
+ console.error(chalk32.dim(" Make sure the agent is pushed first"));
20356
20714
  process.exit(1);
20357
20715
  }
20358
20716
  const response = await apiClient.get(
@@ -20364,12 +20722,12 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20364
20722
  }
20365
20723
  const schedule = await response.json();
20366
20724
  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");
20725
+ console.log(`Schedule: ${chalk32.cyan(schedule.name)}`);
20726
+ console.log(chalk32.dim("\u2501".repeat(50)));
20727
+ const statusText = schedule.enabled ? chalk32.green("enabled") : chalk32.yellow("disabled");
20370
20728
  console.log(`${"Status:".padEnd(16)}${statusText}`);
20371
20729
  console.log(
20372
- `${"Agent:".padEnd(16)}${schedule.composeName} ${chalk31.dim(`(${schedule.scopeSlug})`)}`
20730
+ `${"Agent:".padEnd(16)}${schedule.composeName} ${chalk32.dim(`(${schedule.scopeSlug})`)}`
20373
20731
  );
20374
20732
  console.log(`${"Trigger:".padEnd(16)}${formatTrigger(schedule)}`);
20375
20733
  if (schedule.enabled) {
@@ -20378,11 +20736,11 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20378
20736
  );
20379
20737
  }
20380
20738
  if (schedule.lastRunAt) {
20381
- const lastRunInfo = schedule.lastRunId ? `${formatDateTimeStyled(schedule.lastRunAt)} ${chalk31.dim(`[${schedule.lastRunId.slice(0, 8)}]`)}` : formatDateTimeStyled(schedule.lastRunAt);
20739
+ const lastRunInfo = schedule.lastRunId ? `${formatDateTimeStyled(schedule.lastRunAt)} ${chalk32.dim(`[${schedule.lastRunId.slice(0, 8)}]`)}` : formatDateTimeStyled(schedule.lastRunAt);
20382
20740
  console.log(`${"Last Run:".padEnd(16)}${lastRunInfo}`);
20383
20741
  }
20384
20742
  const promptPreview = schedule.prompt.length > 60 ? schedule.prompt.slice(0, 57) + "..." : schedule.prompt;
20385
- console.log(`${"Prompt:".padEnd(16)}${chalk31.dim(promptPreview)}`);
20743
+ console.log(`${"Prompt:".padEnd(16)}${chalk32.dim(promptPreview)}`);
20386
20744
  if (schedule.vars && Object.keys(schedule.vars).length > 0) {
20387
20745
  console.log(
20388
20746
  `${"Variables:".padEnd(16)}${Object.keys(schedule.vars).join(", ")}`
@@ -20404,26 +20762,26 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20404
20762
  }
20405
20763
  console.log();
20406
20764
  console.log(
20407
- chalk31.dim(
20765
+ chalk32.dim(
20408
20766
  `Created: ${new Date(schedule.createdAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
20409
20767
  )
20410
20768
  );
20411
20769
  console.log(
20412
- chalk31.dim(
20770
+ chalk32.dim(
20413
20771
  `Updated: ${new Date(schedule.updatedAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
20414
20772
  )
20415
20773
  );
20416
- console.log(chalk31.dim(`ID: ${schedule.id}`));
20774
+ console.log(chalk32.dim(`ID: ${schedule.id}`));
20417
20775
  console.log();
20418
20776
  } catch (error43) {
20419
- console.error(chalk31.red("\u2717 Failed to get schedule status"));
20777
+ console.error(chalk32.red("\u2717 Failed to get schedule status"));
20420
20778
  if (error43 instanceof Error) {
20421
20779
  if (error43.message.includes("Not authenticated")) {
20422
- console.error(chalk31.dim(" Run: vm0 auth login"));
20780
+ console.error(chalk32.dim(" Run: vm0 auth login"));
20423
20781
  } else if (error43.message.includes("not found") || error43.message.includes("Not found")) {
20424
- console.error(chalk31.dim(` Schedule "${name}" not found`));
20782
+ console.error(chalk32.dim(` Schedule "${name}" not found`));
20425
20783
  } else {
20426
- console.error(chalk31.dim(` ${error43.message}`));
20784
+ console.error(chalk32.dim(` ${error43.message}`));
20427
20785
  }
20428
20786
  }
20429
20787
  process.exit(1);
@@ -20431,8 +20789,8 @@ var statusCommand4 = new Command29().name("status").description("Show detailed s
20431
20789
  });
20432
20790
 
20433
20791
  // src/commands/schedule/delete.ts
20434
- import { Command as Command30 } from "commander";
20435
- import chalk32 from "chalk";
20792
+ import { Command as Command31 } from "commander";
20793
+ import chalk33 from "chalk";
20436
20794
  import * as readline from "readline";
20437
20795
  async function confirm(message) {
20438
20796
  const rl = readline.createInterface({
@@ -20446,16 +20804,16 @@ async function confirm(message) {
20446
20804
  });
20447
20805
  });
20448
20806
  }
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) => {
20807
+ 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
20808
  try {
20451
20809
  const result = loadAgentName();
20452
20810
  if (result.error) {
20453
- console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20811
+ console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20454
20812
  process.exit(1);
20455
20813
  }
20456
20814
  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"));
20815
+ console.error(chalk33.red("\u2717 No vm0.yaml found in current directory"));
20816
+ console.error(chalk33.dim(" Run this command from the agent directory"));
20459
20817
  process.exit(1);
20460
20818
  }
20461
20819
  const agentName = result.agentName;
@@ -20464,14 +20822,14 @@ var deleteCommand = new Command30().name("delete").alias("rm").description("Dele
20464
20822
  const compose = await apiClient.getComposeByName(agentName);
20465
20823
  composeId = compose.id;
20466
20824
  } catch {
20467
- console.error(chalk32.red(`\u2717 Agent not found: ${agentName}`));
20468
- console.error(chalk32.dim(" Make sure the agent is pushed first"));
20825
+ console.error(chalk33.red(`\u2717 Agent not found: ${agentName}`));
20826
+ console.error(chalk33.dim(" Make sure the agent is pushed first"));
20469
20827
  process.exit(1);
20470
20828
  }
20471
20829
  if (!options.force) {
20472
- const confirmed = await confirm(`Delete schedule ${chalk32.cyan(name)}?`);
20830
+ const confirmed = await confirm(`Delete schedule ${chalk33.cyan(name)}?`);
20473
20831
  if (!confirmed) {
20474
- console.log(chalk32.dim("Cancelled"));
20832
+ console.log(chalk33.dim("Cancelled"));
20475
20833
  return;
20476
20834
  }
20477
20835
  }
@@ -20482,14 +20840,14 @@ var deleteCommand = new Command30().name("delete").alias("rm").description("Dele
20482
20840
  const error43 = await response.json();
20483
20841
  throw new Error(error43.error?.message || "Delete failed");
20484
20842
  }
20485
- console.log(chalk32.green(`\u2713 Deleted schedule ${chalk32.cyan(name)}`));
20843
+ console.log(chalk33.green(`\u2713 Deleted schedule ${chalk33.cyan(name)}`));
20486
20844
  } catch (error43) {
20487
- console.error(chalk32.red("\u2717 Failed to delete schedule"));
20845
+ console.error(chalk33.red("\u2717 Failed to delete schedule"));
20488
20846
  if (error43 instanceof Error) {
20489
20847
  if (error43.message.includes("Not authenticated")) {
20490
- console.error(chalk32.dim(" Run: vm0 auth login"));
20848
+ console.error(chalk33.dim(" Run: vm0 auth login"));
20491
20849
  } else {
20492
- console.error(chalk32.dim(` ${error43.message}`));
20850
+ console.error(chalk33.dim(` ${error43.message}`));
20493
20851
  }
20494
20852
  }
20495
20853
  process.exit(1);
@@ -20497,18 +20855,18 @@ var deleteCommand = new Command30().name("delete").alias("rm").description("Dele
20497
20855
  });
20498
20856
 
20499
20857
  // 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) => {
20858
+ import { Command as Command32 } from "commander";
20859
+ import chalk34 from "chalk";
20860
+ var enableCommand = new Command32().name("enable").description("Enable a schedule").argument("<name>", "Schedule name to enable").action(async (name) => {
20503
20861
  try {
20504
20862
  const result = loadAgentName();
20505
20863
  if (result.error) {
20506
- console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20864
+ console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20507
20865
  process.exit(1);
20508
20866
  }
20509
20867
  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"));
20868
+ console.error(chalk34.red("\u2717 No vm0.yaml found in current directory"));
20869
+ console.error(chalk34.dim(" Run this command from the agent directory"));
20512
20870
  process.exit(1);
20513
20871
  }
20514
20872
  const agentName = result.agentName;
@@ -20517,8 +20875,8 @@ var enableCommand = new Command31().name("enable").description("Enable a schedul
20517
20875
  const compose = await apiClient.getComposeByName(agentName);
20518
20876
  composeId = compose.id;
20519
20877
  } catch {
20520
- console.error(chalk33.red(`\u2717 Agent not found: ${agentName}`));
20521
- console.error(chalk33.dim(" Make sure the agent is pushed first"));
20878
+ console.error(chalk34.red(`\u2717 Agent not found: ${agentName}`));
20879
+ console.error(chalk34.dim(" Make sure the agent is pushed first"));
20522
20880
  process.exit(1);
20523
20881
  }
20524
20882
  const response = await apiClient.post(
@@ -20529,14 +20887,14 @@ var enableCommand = new Command31().name("enable").description("Enable a schedul
20529
20887
  const error43 = await response.json();
20530
20888
  throw new Error(error43.error?.message || "Enable failed");
20531
20889
  }
20532
- console.log(chalk33.green(`\u2713 Enabled schedule ${chalk33.cyan(name)}`));
20890
+ console.log(chalk34.green(`\u2713 Enabled schedule ${chalk34.cyan(name)}`));
20533
20891
  } catch (error43) {
20534
- console.error(chalk33.red("\u2717 Failed to enable schedule"));
20892
+ console.error(chalk34.red("\u2717 Failed to enable schedule"));
20535
20893
  if (error43 instanceof Error) {
20536
20894
  if (error43.message.includes("Not authenticated")) {
20537
- console.error(chalk33.dim(" Run: vm0 auth login"));
20895
+ console.error(chalk34.dim(" Run: vm0 auth login"));
20538
20896
  } else {
20539
- console.error(chalk33.dim(` ${error43.message}`));
20897
+ console.error(chalk34.dim(` ${error43.message}`));
20540
20898
  }
20541
20899
  }
20542
20900
  process.exit(1);
@@ -20544,18 +20902,18 @@ var enableCommand = new Command31().name("enable").description("Enable a schedul
20544
20902
  });
20545
20903
 
20546
20904
  // 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) => {
20905
+ import { Command as Command33 } from "commander";
20906
+ import chalk35 from "chalk";
20907
+ var disableCommand = new Command33().name("disable").description("Disable a schedule").argument("<name>", "Schedule name to disable").action(async (name) => {
20550
20908
  try {
20551
20909
  const result = loadAgentName();
20552
20910
  if (result.error) {
20553
- console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20911
+ console.error(chalk35.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20554
20912
  process.exit(1);
20555
20913
  }
20556
20914
  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"));
20915
+ console.error(chalk35.red("\u2717 No vm0.yaml found in current directory"));
20916
+ console.error(chalk35.dim(" Run this command from the agent directory"));
20559
20917
  process.exit(1);
20560
20918
  }
20561
20919
  const agentName = result.agentName;
@@ -20564,8 +20922,8 @@ var disableCommand = new Command32().name("disable").description("Disable a sche
20564
20922
  const compose = await apiClient.getComposeByName(agentName);
20565
20923
  composeId = compose.id;
20566
20924
  } catch {
20567
- console.error(chalk34.red(`\u2717 Agent not found: ${agentName}`));
20568
- console.error(chalk34.dim(" Make sure the agent is pushed first"));
20925
+ console.error(chalk35.red(`\u2717 Agent not found: ${agentName}`));
20926
+ console.error(chalk35.dim(" Make sure the agent is pushed first"));
20569
20927
  process.exit(1);
20570
20928
  }
20571
20929
  const response = await apiClient.post(
@@ -20576,14 +20934,14 @@ var disableCommand = new Command32().name("disable").description("Disable a sche
20576
20934
  const error43 = await response.json();
20577
20935
  throw new Error(error43.error?.message || "Disable failed");
20578
20936
  }
20579
- console.log(chalk34.green(`\u2713 Disabled schedule ${chalk34.cyan(name)}`));
20937
+ console.log(chalk35.green(`\u2713 Disabled schedule ${chalk35.cyan(name)}`));
20580
20938
  } catch (error43) {
20581
- console.error(chalk34.red("\u2717 Failed to disable schedule"));
20939
+ console.error(chalk35.red("\u2717 Failed to disable schedule"));
20582
20940
  if (error43 instanceof Error) {
20583
20941
  if (error43.message.includes("Not authenticated")) {
20584
- console.error(chalk34.dim(" Run: vm0 auth login"));
20942
+ console.error(chalk35.dim(" Run: vm0 auth login"));
20585
20943
  } else {
20586
- console.error(chalk34.dim(` ${error43.message}`));
20944
+ console.error(chalk35.dim(` ${error43.message}`));
20587
20945
  }
20588
20946
  }
20589
20947
  process.exit(1);
@@ -20591,13 +20949,13 @@ var disableCommand = new Command32().name("disable").description("Disable a sche
20591
20949
  });
20592
20950
 
20593
20951
  // 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);
20952
+ 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
20953
 
20596
20954
  // src/index.ts
20597
- var program = new Command34();
20598
- program.name("vm0").description("VM0 CLI - A modern build tool").version("5.2.0");
20955
+ var program = new Command35();
20956
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("5.3.0");
20599
20957
  program.command("info").description("Display environment information").action(async () => {
20600
- console.log(chalk35.bold("System Information:"));
20958
+ console.log(chalk36.bold("System Information:"));
20601
20959
  console.log(`Node Version: ${process.version}`);
20602
20960
  console.log(`Platform: ${process.platform}`);
20603
20961
  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.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",