@vm0/cli 5.1.2 → 5.2.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 +779 -42
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -6,8 +6,8 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // src/index.ts
9
- import { Command as Command27 } from "commander";
10
- import chalk29 from "chalk";
9
+ import { Command as Command34 } from "commander";
10
+ import chalk35 from "chalk";
11
11
 
12
12
  // src/lib/auth.ts
13
13
  import chalk from "chalk";
@@ -2760,7 +2760,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
2760
2760
  function isValidBase64URL(data) {
2761
2761
  if (!base64url.test(data))
2762
2762
  return false;
2763
- const base643 = data.replace(/[-_]/g, (c15) => c15 === "-" ? "+" : "/");
2763
+ const base643 = data.replace(/[-_]/g, (c16) => c16 === "-" ? "+" : "/");
2764
2764
  const padded = base643.padEnd(Math.ceil(base643.length / 4) * 4, "=");
2765
2765
  return isValidBase64(padded);
2766
2766
  }
@@ -11672,9 +11672,9 @@ var ZodDate = /* @__PURE__ */ $constructor("ZodDate", (inst, def) => {
11672
11672
  ZodType.init(inst, def);
11673
11673
  inst.min = (value, params) => inst.check(_gte(value, params));
11674
11674
  inst.max = (value, params) => inst.check(_lte(value, params));
11675
- const c15 = inst._zod.bag;
11676
- inst.minDate = c15.minimum ? new Date(c15.minimum) : null;
11677
- inst.maxDate = c15.maximum ? new Date(c15.maximum) : null;
11675
+ const c16 = inst._zod.bag;
11676
+ inst.minDate = c16.minimum ? new Date(c16.minimum) : null;
11677
+ inst.maxDate = c16.maximum ? new Date(c16.maximum) : null;
11678
11678
  });
11679
11679
  function date3(params) {
11680
11680
  return _date(ZodDate, params);
@@ -13679,6 +13679,203 @@ var checkpointsByIdContract = c10.router({
13679
13679
  }
13680
13680
  });
13681
13681
 
13682
+ // ../../packages/core/src/contracts/schedules.ts
13683
+ var c11 = initContract();
13684
+ var scheduleTriggerSchema = external_exports.object({
13685
+ cron: external_exports.string().optional(),
13686
+ at: external_exports.string().optional(),
13687
+ timezone: external_exports.string().default("UTC")
13688
+ }).refine((data) => data.cron && !data.at || !data.cron && data.at, {
13689
+ message: "Exactly one of 'cron' or 'at' must be specified"
13690
+ });
13691
+ var scheduleRunConfigSchema = external_exports.object({
13692
+ agent: external_exports.string().min(1, "Agent reference required"),
13693
+ prompt: external_exports.string().min(1, "Prompt required"),
13694
+ vars: external_exports.record(external_exports.string(), external_exports.string()).optional(),
13695
+ secrets: external_exports.record(external_exports.string(), external_exports.string()).optional(),
13696
+ artifactName: external_exports.string().optional(),
13697
+ artifactVersion: external_exports.string().optional(),
13698
+ volumeVersions: external_exports.record(external_exports.string(), external_exports.string()).optional()
13699
+ });
13700
+ var scheduleDefinitionSchema = external_exports.object({
13701
+ on: scheduleTriggerSchema,
13702
+ run: scheduleRunConfigSchema
13703
+ });
13704
+ var scheduleYamlSchema = external_exports.object({
13705
+ version: external_exports.literal("1.0"),
13706
+ schedules: external_exports.record(external_exports.string(), scheduleDefinitionSchema)
13707
+ });
13708
+ var deployScheduleRequestSchema = external_exports.object({
13709
+ name: external_exports.string().min(1).max(64, "Schedule name max 64 chars"),
13710
+ cronExpression: external_exports.string().optional(),
13711
+ atTime: external_exports.string().optional(),
13712
+ timezone: external_exports.string().default("UTC"),
13713
+ prompt: external_exports.string().min(1, "Prompt required"),
13714
+ vars: external_exports.record(external_exports.string(), external_exports.string()).optional(),
13715
+ secrets: external_exports.record(external_exports.string(), external_exports.string()).optional(),
13716
+ artifactName: external_exports.string().optional(),
13717
+ artifactVersion: external_exports.string().optional(),
13718
+ volumeVersions: external_exports.record(external_exports.string(), external_exports.string()).optional(),
13719
+ // Resolved agent compose ID (CLI resolves scope/name:version → composeId)
13720
+ composeId: external_exports.string().uuid("Invalid compose ID")
13721
+ }).refine(
13722
+ (data) => data.cronExpression && !data.atTime || !data.cronExpression && data.atTime,
13723
+ {
13724
+ message: "Exactly one of 'cronExpression' or 'atTime' must be specified"
13725
+ }
13726
+ );
13727
+ var scheduleResponseSchema = external_exports.object({
13728
+ id: external_exports.string().uuid(),
13729
+ composeId: external_exports.string().uuid(),
13730
+ composeName: external_exports.string(),
13731
+ scopeSlug: external_exports.string(),
13732
+ name: external_exports.string(),
13733
+ cronExpression: external_exports.string().nullable(),
13734
+ atTime: external_exports.string().nullable(),
13735
+ timezone: external_exports.string(),
13736
+ prompt: external_exports.string(),
13737
+ vars: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13738
+ // Secret names only (values are never returned)
13739
+ secretNames: external_exports.array(external_exports.string()).nullable(),
13740
+ artifactName: external_exports.string().nullable(),
13741
+ artifactVersion: external_exports.string().nullable(),
13742
+ volumeVersions: external_exports.record(external_exports.string(), external_exports.string()).nullable(),
13743
+ enabled: external_exports.boolean(),
13744
+ nextRunAt: external_exports.string().nullable(),
13745
+ lastRunAt: external_exports.string().nullable(),
13746
+ lastRunId: external_exports.string().nullable(),
13747
+ createdAt: external_exports.string(),
13748
+ updatedAt: external_exports.string()
13749
+ });
13750
+ var scheduleListResponseSchema = external_exports.object({
13751
+ schedules: external_exports.array(scheduleResponseSchema)
13752
+ });
13753
+ var deployScheduleResponseSchema = external_exports.object({
13754
+ schedule: scheduleResponseSchema,
13755
+ created: external_exports.boolean()
13756
+ // true if created, false if updated
13757
+ });
13758
+ var schedulesMainContract = c11.router({
13759
+ /**
13760
+ * POST /api/agent/schedules
13761
+ * Deploy (create or update) a schedule
13762
+ */
13763
+ deploy: {
13764
+ method: "POST",
13765
+ path: "/api/agent/schedules",
13766
+ body: deployScheduleRequestSchema,
13767
+ responses: {
13768
+ 200: deployScheduleResponseSchema,
13769
+ // Updated
13770
+ 201: deployScheduleResponseSchema,
13771
+ // Created
13772
+ 400: apiErrorSchema,
13773
+ 401: apiErrorSchema,
13774
+ 404: apiErrorSchema,
13775
+ 409: apiErrorSchema
13776
+ // Schedule limit reached
13777
+ },
13778
+ summary: "Deploy schedule (create or update)"
13779
+ },
13780
+ /**
13781
+ * GET /api/agent/schedules
13782
+ * List all schedules for the user
13783
+ */
13784
+ list: {
13785
+ method: "GET",
13786
+ path: "/api/agent/schedules",
13787
+ responses: {
13788
+ 200: scheduleListResponseSchema,
13789
+ 401: apiErrorSchema
13790
+ },
13791
+ summary: "List all schedules"
13792
+ }
13793
+ });
13794
+ var schedulesByNameContract = c11.router({
13795
+ /**
13796
+ * GET /api/agent/schedules/:name
13797
+ * Get schedule by name
13798
+ */
13799
+ getByName: {
13800
+ method: "GET",
13801
+ path: "/api/agent/schedules/:name",
13802
+ pathParams: external_exports.object({
13803
+ name: external_exports.string().min(1, "Schedule name required")
13804
+ }),
13805
+ query: external_exports.object({
13806
+ composeId: external_exports.string().uuid("Compose ID required")
13807
+ }),
13808
+ responses: {
13809
+ 200: scheduleResponseSchema,
13810
+ 401: apiErrorSchema,
13811
+ 404: apiErrorSchema
13812
+ },
13813
+ summary: "Get schedule by name"
13814
+ },
13815
+ /**
13816
+ * DELETE /api/agent/schedules/:name
13817
+ * Delete schedule by name
13818
+ */
13819
+ delete: {
13820
+ method: "DELETE",
13821
+ path: "/api/agent/schedules/:name",
13822
+ pathParams: external_exports.object({
13823
+ name: external_exports.string().min(1, "Schedule name required")
13824
+ }),
13825
+ query: external_exports.object({
13826
+ composeId: external_exports.string().uuid("Compose ID required")
13827
+ }),
13828
+ responses: {
13829
+ 204: external_exports.undefined(),
13830
+ 401: apiErrorSchema,
13831
+ 404: apiErrorSchema
13832
+ },
13833
+ summary: "Delete schedule"
13834
+ }
13835
+ });
13836
+ var schedulesEnableContract = c11.router({
13837
+ /**
13838
+ * POST /api/agent/schedules/:name/enable
13839
+ * Enable a disabled schedule
13840
+ */
13841
+ enable: {
13842
+ method: "POST",
13843
+ path: "/api/agent/schedules/:name/enable",
13844
+ pathParams: external_exports.object({
13845
+ name: external_exports.string().min(1, "Schedule name required")
13846
+ }),
13847
+ body: external_exports.object({
13848
+ composeId: external_exports.string().uuid("Compose ID required")
13849
+ }),
13850
+ responses: {
13851
+ 200: scheduleResponseSchema,
13852
+ 401: apiErrorSchema,
13853
+ 404: apiErrorSchema
13854
+ },
13855
+ summary: "Enable schedule"
13856
+ },
13857
+ /**
13858
+ * POST /api/agent/schedules/:name/disable
13859
+ * Disable an enabled schedule
13860
+ */
13861
+ disable: {
13862
+ method: "POST",
13863
+ path: "/api/agent/schedules/:name/disable",
13864
+ pathParams: external_exports.object({
13865
+ name: external_exports.string().min(1, "Schedule name required")
13866
+ }),
13867
+ body: external_exports.object({
13868
+ composeId: external_exports.string().uuid("Compose ID required")
13869
+ }),
13870
+ responses: {
13871
+ 200: scheduleResponseSchema,
13872
+ 401: apiErrorSchema,
13873
+ 404: apiErrorSchema
13874
+ },
13875
+ summary: "Disable schedule"
13876
+ }
13877
+ });
13878
+
13682
13879
  // ../../packages/core/src/contracts/public/common.ts
13683
13880
  var publicApiErrorTypeSchema = external_exports.enum([
13684
13881
  "api_error",
@@ -13719,7 +13916,7 @@ var requestIdSchema = external_exports.string().uuid();
13719
13916
  var timestampSchema = external_exports.string().datetime();
13720
13917
 
13721
13918
  // ../../packages/core/src/contracts/public/agents.ts
13722
- var c11 = initContract();
13919
+ var c12 = initContract();
13723
13920
  var publicAgentSchema = external_exports.object({
13724
13921
  id: external_exports.string(),
13725
13922
  name: external_exports.string(),
@@ -13739,7 +13936,7 @@ var paginatedAgentVersionsSchema = createPaginatedResponseSchema(agentVersionSch
13739
13936
  var agentListQuerySchema = listQuerySchema.extend({
13740
13937
  name: external_exports.string().optional()
13741
13938
  });
13742
- var publicAgentsListContract = c11.router({
13939
+ var publicAgentsListContract = c12.router({
13743
13940
  list: {
13744
13941
  method: "GET",
13745
13942
  path: "/v1/agents",
@@ -13753,7 +13950,7 @@ var publicAgentsListContract = c11.router({
13753
13950
  description: "List all agents in the current scope with pagination. Use the `name` query parameter to filter by agent name."
13754
13951
  }
13755
13952
  });
13756
- var publicAgentByIdContract = c11.router({
13953
+ var publicAgentByIdContract = c12.router({
13757
13954
  get: {
13758
13955
  method: "GET",
13759
13956
  path: "/v1/agents/:id",
@@ -13770,7 +13967,7 @@ var publicAgentByIdContract = c11.router({
13770
13967
  description: "Get agent details by ID"
13771
13968
  }
13772
13969
  });
13773
- var publicAgentVersionsContract = c11.router({
13970
+ var publicAgentVersionsContract = c12.router({
13774
13971
  list: {
13775
13972
  method: "GET",
13776
13973
  path: "/v1/agents/:id/versions",
@@ -13790,7 +13987,7 @@ var publicAgentVersionsContract = c11.router({
13790
13987
  });
13791
13988
 
13792
13989
  // ../../packages/core/src/contracts/public/runs.ts
13793
- var c12 = initContract();
13990
+ var c13 = initContract();
13794
13991
  var publicRunStatusSchema = external_exports.enum([
13795
13992
  "pending",
13796
13993
  "running",
@@ -13848,7 +14045,7 @@ var runListQuerySchema = listQuerySchema.extend({
13848
14045
  status: publicRunStatusSchema.optional(),
13849
14046
  since: timestampSchema.optional()
13850
14047
  });
13851
- var publicRunsListContract = c12.router({
14048
+ var publicRunsListContract = c13.router({
13852
14049
  list: {
13853
14050
  method: "GET",
13854
14051
  path: "/v1/runs",
@@ -13877,7 +14074,7 @@ var publicRunsListContract = c12.router({
13877
14074
  description: "Create and execute a new agent run. Returns 202 Accepted as runs execute asynchronously."
13878
14075
  }
13879
14076
  });
13880
- var publicRunByIdContract = c12.router({
14077
+ var publicRunByIdContract = c13.router({
13881
14078
  get: {
13882
14079
  method: "GET",
13883
14080
  path: "/v1/runs/:id",
@@ -13894,7 +14091,7 @@ var publicRunByIdContract = c12.router({
13894
14091
  description: "Get run details by ID"
13895
14092
  }
13896
14093
  });
13897
- var publicRunCancelContract = c12.router({
14094
+ var publicRunCancelContract = c13.router({
13898
14095
  cancel: {
13899
14096
  method: "POST",
13900
14097
  path: "/v1/runs/:id/cancel",
@@ -13928,7 +14125,7 @@ var logsQuerySchema = listQuerySchema.extend({
13928
14125
  until: timestampSchema.optional(),
13929
14126
  order: external_exports.enum(["asc", "desc"]).default("asc")
13930
14127
  });
13931
- var publicRunLogsContract = c12.router({
14128
+ var publicRunLogsContract = c13.router({
13932
14129
  getLogs: {
13933
14130
  method: "GET",
13934
14131
  path: "/v1/runs/:id/logs",
@@ -13963,7 +14160,7 @@ var metricsResponseSchema2 = external_exports.object({
13963
14160
  data: external_exports.array(metricPointSchema),
13964
14161
  summary: metricsSummarySchema
13965
14162
  });
13966
- var publicRunMetricsContract = c12.router({
14163
+ var publicRunMetricsContract = c13.router({
13967
14164
  getMetrics: {
13968
14165
  method: "GET",
13969
14166
  path: "/v1/runs/:id/metrics",
@@ -13998,7 +14195,7 @@ var sseEventSchema = external_exports.object({
13998
14195
  id: external_exports.string().optional()
13999
14196
  // For Last-Event-ID reconnection
14000
14197
  });
14001
- var publicRunEventsContract = c12.router({
14198
+ var publicRunEventsContract = c13.router({
14002
14199
  streamEvents: {
14003
14200
  method: "GET",
14004
14201
  path: "/v1/runs/:id/events",
@@ -14022,7 +14219,7 @@ var publicRunEventsContract = c12.router({
14022
14219
  });
14023
14220
 
14024
14221
  // ../../packages/core/src/contracts/public/artifacts.ts
14025
- var c13 = initContract();
14222
+ var c14 = initContract();
14026
14223
  var publicArtifactSchema = external_exports.object({
14027
14224
  id: external_exports.string(),
14028
14225
  name: external_exports.string(),
@@ -14052,7 +14249,7 @@ var paginatedArtifactsSchema = createPaginatedResponseSchema(publicArtifactSchem
14052
14249
  var paginatedArtifactVersionsSchema = createPaginatedResponseSchema(
14053
14250
  artifactVersionSchema
14054
14251
  );
14055
- var publicArtifactsListContract = c13.router({
14252
+ var publicArtifactsListContract = c14.router({
14056
14253
  list: {
14057
14254
  method: "GET",
14058
14255
  path: "/v1/artifacts",
@@ -14066,7 +14263,7 @@ var publicArtifactsListContract = c13.router({
14066
14263
  description: "List all artifacts in the current scope with pagination"
14067
14264
  }
14068
14265
  });
14069
- var publicArtifactByIdContract = c13.router({
14266
+ var publicArtifactByIdContract = c14.router({
14070
14267
  get: {
14071
14268
  method: "GET",
14072
14269
  path: "/v1/artifacts/:id",
@@ -14083,7 +14280,7 @@ var publicArtifactByIdContract = c13.router({
14083
14280
  description: "Get artifact details by ID"
14084
14281
  }
14085
14282
  });
14086
- var publicArtifactVersionsContract = c13.router({
14283
+ var publicArtifactVersionsContract = c14.router({
14087
14284
  list: {
14088
14285
  method: "GET",
14089
14286
  path: "/v1/artifacts/:id/versions",
@@ -14101,7 +14298,7 @@ var publicArtifactVersionsContract = c13.router({
14101
14298
  description: "List all versions of an artifact with pagination"
14102
14299
  }
14103
14300
  });
14104
- var publicArtifactDownloadContract = c13.router({
14301
+ var publicArtifactDownloadContract = c14.router({
14105
14302
  download: {
14106
14303
  method: "GET",
14107
14304
  path: "/v1/artifacts/:id/download",
@@ -14125,7 +14322,7 @@ var publicArtifactDownloadContract = c13.router({
14125
14322
  });
14126
14323
 
14127
14324
  // ../../packages/core/src/contracts/public/volumes.ts
14128
- var c14 = initContract();
14325
+ var c15 = initContract();
14129
14326
  var publicVolumeSchema = external_exports.object({
14130
14327
  id: external_exports.string(),
14131
14328
  name: external_exports.string(),
@@ -14153,7 +14350,7 @@ var publicVolumeDetailSchema = publicVolumeSchema.extend({
14153
14350
  });
14154
14351
  var paginatedVolumesSchema = createPaginatedResponseSchema(publicVolumeSchema);
14155
14352
  var paginatedVolumeVersionsSchema = createPaginatedResponseSchema(volumeVersionSchema);
14156
- var publicVolumesListContract = c14.router({
14353
+ var publicVolumesListContract = c15.router({
14157
14354
  list: {
14158
14355
  method: "GET",
14159
14356
  path: "/v1/volumes",
@@ -14167,7 +14364,7 @@ var publicVolumesListContract = c14.router({
14167
14364
  description: "List all volumes in the current scope with pagination"
14168
14365
  }
14169
14366
  });
14170
- var publicVolumeByIdContract = c14.router({
14367
+ var publicVolumeByIdContract = c15.router({
14171
14368
  get: {
14172
14369
  method: "GET",
14173
14370
  path: "/v1/volumes/:id",
@@ -14184,7 +14381,7 @@ var publicVolumeByIdContract = c14.router({
14184
14381
  description: "Get volume details by ID"
14185
14382
  }
14186
14383
  });
14187
- var publicVolumeVersionsContract = c14.router({
14384
+ var publicVolumeVersionsContract = c15.router({
14188
14385
  list: {
14189
14386
  method: "GET",
14190
14387
  path: "/v1/volumes/:id/versions",
@@ -14202,7 +14399,7 @@ var publicVolumeVersionsContract = c14.router({
14202
14399
  description: "List all versions of a volume with pagination"
14203
14400
  }
14204
14401
  });
14205
- var publicVolumeDownloadContract = c14.router({
14402
+ var publicVolumeDownloadContract = c15.router({
14206
14403
  download: {
14207
14404
  method: "GET",
14208
14405
  path: "/v1/volumes/:id/download",
@@ -14378,8 +14575,9 @@ var ApiClient = class {
14378
14575
  async getComposeVersion(composeId, version2) {
14379
14576
  const baseUrl = await this.getBaseUrl();
14380
14577
  const headers = await this.getHeaders();
14578
+ const quotedVersion = JSON.stringify(version2);
14381
14579
  const response = await fetch(
14382
- `${baseUrl}/api/agent/composes/versions?composeId=${encodeURIComponent(composeId)}&version=${encodeURIComponent(version2)}`,
14580
+ `${baseUrl}/api/agent/composes/versions?composeId=${encodeURIComponent(composeId)}&version=${encodeURIComponent(quotedVersion)}`,
14383
14581
  {
14384
14582
  method: "GET",
14385
14583
  headers
@@ -16060,9 +16258,9 @@ var CodexEventParser = class {
16060
16258
  }
16061
16259
  }
16062
16260
  if (itemType === "file_change" && item.changes && item.changes.length > 0) {
16063
- const changes = item.changes.map((c15) => {
16064
- const action = c15.kind === "add" ? "Created" : c15.kind === "modify" ? "Modified" : "Deleted";
16065
- return `${action}: ${c15.path}`;
16261
+ const changes = item.changes.map((c16) => {
16262
+ const action = c16.kind === "add" ? "Created" : c16.kind === "modify" ? "Modified" : "Deleted";
16263
+ return `${action}: ${c16.path}`;
16066
16264
  }).join("\n");
16067
16265
  return {
16068
16266
  type: "text",
@@ -16403,9 +16601,9 @@ var CodexEventRenderer = class {
16403
16601
  return;
16404
16602
  }
16405
16603
  if (itemType === "file_change" && item.changes && item.changes.length > 0) {
16406
- const summary = item.changes.map((c15) => {
16407
- const icon = c15.kind === "add" ? "+" : c15.kind === "delete" ? "-" : "~";
16408
- return `${icon}${c15.path}`;
16604
+ const summary = item.changes.map((c16) => {
16605
+ const icon = c16.kind === "add" ? "+" : c16.kind === "delete" ? "-" : "~";
16606
+ return `${icon}${c16.path}`;
16409
16607
  }).join(", ");
16410
16608
  console.log(chalk4.green("[files]") + ` ${summary}`);
16411
16609
  return;
@@ -17242,7 +17440,8 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
17242
17440
  console.log(chalk9.dim("Getting download URL..."));
17243
17441
  let url2 = `/api/storages/download?name=${encodeURIComponent(config2.name)}&type=volume`;
17244
17442
  if (versionId) {
17245
- url2 += `&version=${encodeURIComponent(versionId)}`;
17443
+ const quotedVersion = JSON.stringify(versionId);
17444
+ url2 += `&version=${encodeURIComponent(quotedVersion)}`;
17246
17445
  }
17247
17446
  const response = await apiClient.get(url2);
17248
17447
  if (!response.ok) {
@@ -17454,7 +17653,8 @@ async function cloneStorage(name, type, destination, options = {}) {
17454
17653
  console.log(chalk12.dim(`Checking remote ${typeLabel}...`));
17455
17654
  let url2 = `/api/storages/download?name=${encodeURIComponent(name)}&type=${type}`;
17456
17655
  if (options.version) {
17457
- url2 += `&version=${encodeURIComponent(options.version)}`;
17656
+ const quotedVersion = JSON.stringify(options.version);
17657
+ url2 += `&version=${encodeURIComponent(quotedVersion)}`;
17458
17658
  }
17459
17659
  const response = await apiClient.get(url2);
17460
17660
  if (!response.ok) {
@@ -17735,7 +17935,8 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
17735
17935
  console.log(chalk16.dim("Getting download URL..."));
17736
17936
  let url2 = `/api/storages/download?name=${encodeURIComponent(config2.name)}&type=artifact`;
17737
17937
  if (versionId) {
17738
- url2 += `&version=${encodeURIComponent(versionId)}`;
17938
+ const quotedVersion = JSON.stringify(versionId);
17939
+ url2 += `&version=${encodeURIComponent(quotedVersion)}`;
17739
17940
  }
17740
17941
  const response = await apiClient.get(url2);
17741
17942
  if (!response.ok) {
@@ -18294,7 +18495,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
18294
18495
  }
18295
18496
  var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
18296
18497
  cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(async (prompt, options) => {
18297
- const shouldExit = await checkAndUpgrade("5.1.2", prompt);
18498
+ const shouldExit = await checkAndUpgrade("5.2.0", prompt);
18298
18499
  if (shouldExit) {
18299
18500
  process.exit(0);
18300
18501
  }
@@ -18978,7 +19179,7 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
18978
19179
  );
18979
19180
  return;
18980
19181
  }
18981
- const nameWidth = Math.max(4, ...data.composes.map((c15) => c15.name.length));
19182
+ const nameWidth = Math.max(4, ...data.composes.map((c16) => c16.name.length));
18982
19183
  const header = ["NAME".padEnd(nameWidth), "VERSION", "UPDATED"].join(
18983
19184
  " "
18984
19185
  );
@@ -19857,11 +20058,546 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
19857
20058
  }
19858
20059
  );
19859
20060
 
20061
+ // src/commands/schedule/index.ts
20062
+ import { Command as Command33 } from "commander";
20063
+
20064
+ // src/commands/schedule/deploy.ts
20065
+ import { Command as Command27 } from "commander";
20066
+ import chalk29 from "chalk";
20067
+ import { existsSync as existsSync11, readFileSync as readFileSync2 } from "fs";
20068
+ import { parse as parseYaml6 } from "yaml";
20069
+ function expandEnvVars(value) {
20070
+ return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
20071
+ const envValue = process.env[varName];
20072
+ if (envValue === void 0) {
20073
+ console.warn(
20074
+ chalk29.yellow(` Warning: Environment variable ${varName} not set`)
20075
+ );
20076
+ return match;
20077
+ }
20078
+ return envValue;
20079
+ });
20080
+ }
20081
+ function expandEnvVarsInObject(obj) {
20082
+ if (!obj) return void 0;
20083
+ const result = {};
20084
+ for (const [key, value] of Object.entries(obj)) {
20085
+ result[key] = expandEnvVars(value);
20086
+ }
20087
+ return result;
20088
+ }
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) => {
20090
+ 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"));
20094
+ process.exit(1);
20095
+ }
20096
+ const content = readFileSync2(file2, "utf-8");
20097
+ let parsed;
20098
+ try {
20099
+ parsed = parseYaml6(content);
20100
+ } catch (err) {
20101
+ console.error(chalk29.red("\u2717 Invalid YAML syntax"));
20102
+ if (err instanceof Error) {
20103
+ console.error(chalk29.dim(` ${err.message}`));
20104
+ }
20105
+ process.exit(1);
20106
+ }
20107
+ const result = scheduleYamlSchema.safeParse(parsed);
20108
+ if (!result.success) {
20109
+ console.error(chalk29.red("\u2717 Invalid schedule.yaml format"));
20110
+ for (const issue2 of result.error.issues) {
20111
+ console.error(
20112
+ chalk29.dim(` ${issue2.path.join(".")}: ${issue2.message}`)
20113
+ );
20114
+ }
20115
+ process.exit(1);
20116
+ }
20117
+ const scheduleYaml = result.data;
20118
+ const scheduleEntries = Object.entries(scheduleYaml.schedules);
20119
+ if (scheduleEntries.length === 0) {
20120
+ console.error(chalk29.red("\u2717 No schedules defined in file"));
20121
+ process.exit(1);
20122
+ }
20123
+ if (scheduleEntries.length > 1) {
20124
+ console.error(
20125
+ chalk29.red("\u2717 Multiple schedules per file not supported yet")
20126
+ );
20127
+ console.error(chalk29.dim(" Please use one schedule per file"));
20128
+ process.exit(1);
20129
+ }
20130
+ const [scheduleName, schedule] = scheduleEntries[0];
20131
+ console.log(`Deploying schedule ${chalk29.cyan(scheduleName)}...`);
20132
+ const agentRef = schedule.run.agent;
20133
+ let composeId;
20134
+ try {
20135
+ const namePart = agentRef.includes("/") ? agentRef.split("/").pop() : agentRef;
20136
+ const agentName = namePart.includes(":") ? namePart.split(":")[0] : namePart;
20137
+ const compose = await apiClient.getComposeByName(agentName);
20138
+ composeId = compose.id;
20139
+ } catch {
20140
+ console.error(chalk29.red(`\u2717 Agent not found: ${agentRef}`));
20141
+ console.error(chalk29.dim(" Make sure the agent is pushed first"));
20142
+ process.exit(1);
20143
+ }
20144
+ const expandedVars = expandEnvVarsInObject(schedule.run.vars);
20145
+ const expandedSecrets = expandEnvVarsInObject(schedule.run.secrets);
20146
+ const body = {
20147
+ name: scheduleName,
20148
+ composeId,
20149
+ cronExpression: schedule.on.cron,
20150
+ atTime: schedule.on.at,
20151
+ timezone: schedule.on.timezone || "UTC",
20152
+ prompt: schedule.run.prompt,
20153
+ vars: expandedVars,
20154
+ secrets: expandedSecrets,
20155
+ artifactName: schedule.run.artifactName,
20156
+ artifactVersion: schedule.run.artifactVersion,
20157
+ volumeVersions: schedule.run.volumeVersions
20158
+ };
20159
+ const response = await apiClient.post("/api/agent/schedules", {
20160
+ body: JSON.stringify(body)
20161
+ });
20162
+ if (!response.ok) {
20163
+ const error43 = await response.json();
20164
+ throw new Error(error43.error?.message || "Deploy failed");
20165
+ }
20166
+ const deployResult = await response.json();
20167
+ if (deployResult.created) {
20168
+ console.log(
20169
+ chalk29.green(`\u2713 Created schedule ${chalk29.cyan(scheduleName)}`)
20170
+ );
20171
+ } else {
20172
+ console.log(
20173
+ chalk29.green(`\u2713 Updated schedule ${chalk29.cyan(scheduleName)}`)
20174
+ );
20175
+ }
20176
+ if (deployResult.schedule.nextRunAt) {
20177
+ const nextRun = new Date(deployResult.schedule.nextRunAt);
20178
+ console.log(chalk29.dim(` Next run: ${nextRun.toLocaleString()}`));
20179
+ }
20180
+ if (deployResult.schedule.cronExpression) {
20181
+ console.log(
20182
+ chalk29.dim(
20183
+ ` Cron: ${deployResult.schedule.cronExpression} (${deployResult.schedule.timezone})`
20184
+ )
20185
+ );
20186
+ } else if (deployResult.schedule.atTime) {
20187
+ console.log(chalk29.dim(` At: ${deployResult.schedule.atTime}`));
20188
+ }
20189
+ } catch (error43) {
20190
+ console.error(chalk29.red("\u2717 Failed to deploy schedule"));
20191
+ if (error43 instanceof Error) {
20192
+ if (error43.message.includes("Not authenticated")) {
20193
+ console.error(chalk29.dim(" Run: vm0 auth login"));
20194
+ } else {
20195
+ console.error(chalk29.dim(` ${error43.message}`));
20196
+ }
20197
+ }
20198
+ process.exit(1);
20199
+ }
20200
+ });
20201
+
20202
+ // 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 () => {
20256
+ try {
20257
+ const response = await apiClient.get("/api/agent/schedules");
20258
+ if (!response.ok) {
20259
+ const error43 = await response.json();
20260
+ throw new Error(error43.error?.message || "List failed");
20261
+ }
20262
+ const result = await response.json();
20263
+ if (result.schedules.length === 0) {
20264
+ console.log(chalk30.dim("No schedules found"));
20265
+ console.log(
20266
+ chalk30.dim(" Create one with: vm0 schedule deploy schedule.yaml")
20267
+ );
20268
+ return;
20269
+ }
20270
+ const nameWidth = Math.max(
20271
+ 4,
20272
+ ...result.schedules.map((s) => s.name.length)
20273
+ );
20274
+ const agentWidth = Math.max(
20275
+ 5,
20276
+ ...result.schedules.map((s) => s.composeName.length)
20277
+ );
20278
+ const triggerWidth = Math.max(
20279
+ 7,
20280
+ ...result.schedules.map(
20281
+ (s) => s.cronExpression ? s.cronExpression.length + s.timezone.length + 3 : s.atTime?.length || 0
20282
+ )
20283
+ );
20284
+ const header = [
20285
+ "NAME".padEnd(nameWidth),
20286
+ "AGENT".padEnd(agentWidth),
20287
+ "TRIGGER".padEnd(triggerWidth),
20288
+ "STATUS".padEnd(8),
20289
+ "NEXT RUN"
20290
+ ].join(" ");
20291
+ console.log(chalk30.dim(header));
20292
+ for (const schedule of result.schedules) {
20293
+ const trigger = schedule.cronExpression ? `${schedule.cronExpression} (${schedule.timezone})` : schedule.atTime || "-";
20294
+ const status = schedule.enabled ? chalk30.green("enabled") : chalk30.yellow("disabled");
20295
+ const nextRun = schedule.enabled ? formatRelativeTime2(schedule.nextRunAt) : "-";
20296
+ const row = [
20297
+ schedule.name.padEnd(nameWidth),
20298
+ schedule.composeName.padEnd(agentWidth),
20299
+ trigger.padEnd(triggerWidth),
20300
+ status.padEnd(8 + (schedule.enabled ? 0 : 2)),
20301
+ // Account for chalk chars
20302
+ nextRun
20303
+ ].join(" ");
20304
+ console.log(row);
20305
+ }
20306
+ } catch (error43) {
20307
+ console.error(chalk30.red("\u2717 Failed to list schedules"));
20308
+ if (error43 instanceof Error) {
20309
+ if (error43.message.includes("Not authenticated")) {
20310
+ console.error(chalk30.dim(" Run: vm0 auth login"));
20311
+ } else {
20312
+ console.error(chalk30.dim(` ${error43.message}`));
20313
+ }
20314
+ }
20315
+ process.exit(1);
20316
+ }
20317
+ });
20318
+
20319
+ // src/commands/schedule/status.ts
20320
+ import { Command as Command29 } from "commander";
20321
+ import chalk31 from "chalk";
20322
+ function formatDateTimeStyled(dateStr) {
20323
+ if (!dateStr) return chalk31.dim("-");
20324
+ const formatted = formatDateTime(dateStr);
20325
+ return formatted.replace(/\(([^)]+)\)$/, chalk31.dim("($1)"));
20326
+ }
20327
+ function formatTrigger(schedule) {
20328
+ if (schedule.cronExpression) {
20329
+ return `${schedule.cronExpression} ${chalk31.dim(`(${schedule.timezone})`)}`;
20330
+ }
20331
+ if (schedule.atTime) {
20332
+ return `${schedule.atTime} ${chalk31.dim("(one-time)")}`;
20333
+ }
20334
+ return chalk31.dim("-");
20335
+ }
20336
+ var statusCommand4 = new Command29().name("status").description("Show detailed status of a schedule").argument("<name>", "Schedule name").action(async (name) => {
20337
+ try {
20338
+ const result = loadAgentName();
20339
+ if (result.error) {
20340
+ console.error(chalk31.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20341
+ process.exit(1);
20342
+ }
20343
+ 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"));
20346
+ process.exit(1);
20347
+ }
20348
+ const agentName = result.agentName;
20349
+ let composeId;
20350
+ try {
20351
+ const compose = await apiClient.getComposeByName(agentName);
20352
+ composeId = compose.id;
20353
+ } catch {
20354
+ console.error(chalk31.red(`\u2717 Agent not found: ${agentName}`));
20355
+ console.error(chalk31.dim(" Make sure the agent is pushed first"));
20356
+ process.exit(1);
20357
+ }
20358
+ const response = await apiClient.get(
20359
+ `/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
20360
+ );
20361
+ if (!response.ok) {
20362
+ const error43 = await response.json();
20363
+ throw new Error(error43.error?.message || "Failed to get schedule");
20364
+ }
20365
+ const schedule = await response.json();
20366
+ 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");
20370
+ console.log(`${"Status:".padEnd(16)}${statusText}`);
20371
+ console.log(
20372
+ `${"Agent:".padEnd(16)}${schedule.composeName} ${chalk31.dim(`(${schedule.scopeSlug})`)}`
20373
+ );
20374
+ console.log(`${"Trigger:".padEnd(16)}${formatTrigger(schedule)}`);
20375
+ if (schedule.enabled) {
20376
+ console.log(
20377
+ `${"Next Run:".padEnd(16)}${formatDateTimeStyled(schedule.nextRunAt)}`
20378
+ );
20379
+ }
20380
+ if (schedule.lastRunAt) {
20381
+ const lastRunInfo = schedule.lastRunId ? `${formatDateTimeStyled(schedule.lastRunAt)} ${chalk31.dim(`[${schedule.lastRunId.slice(0, 8)}]`)}` : formatDateTimeStyled(schedule.lastRunAt);
20382
+ console.log(`${"Last Run:".padEnd(16)}${lastRunInfo}`);
20383
+ }
20384
+ const promptPreview = schedule.prompt.length > 60 ? schedule.prompt.slice(0, 57) + "..." : schedule.prompt;
20385
+ console.log(`${"Prompt:".padEnd(16)}${chalk31.dim(promptPreview)}`);
20386
+ if (schedule.vars && Object.keys(schedule.vars).length > 0) {
20387
+ console.log(
20388
+ `${"Variables:".padEnd(16)}${Object.keys(schedule.vars).join(", ")}`
20389
+ );
20390
+ }
20391
+ if (schedule.secretNames && schedule.secretNames.length > 0) {
20392
+ console.log(
20393
+ `${"Secrets:".padEnd(16)}${schedule.secretNames.join(", ")}`
20394
+ );
20395
+ }
20396
+ if (schedule.artifactName) {
20397
+ const artifactInfo = schedule.artifactVersion ? `${schedule.artifactName}:${schedule.artifactVersion}` : schedule.artifactName;
20398
+ console.log(`${"Artifact:".padEnd(16)}${artifactInfo}`);
20399
+ }
20400
+ if (schedule.volumeVersions && Object.keys(schedule.volumeVersions).length > 0) {
20401
+ console.log(
20402
+ `${"Volumes:".padEnd(16)}${Object.keys(schedule.volumeVersions).join(", ")}`
20403
+ );
20404
+ }
20405
+ console.log();
20406
+ console.log(
20407
+ chalk31.dim(
20408
+ `Created: ${new Date(schedule.createdAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
20409
+ )
20410
+ );
20411
+ console.log(
20412
+ chalk31.dim(
20413
+ `Updated: ${new Date(schedule.updatedAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
20414
+ )
20415
+ );
20416
+ console.log(chalk31.dim(`ID: ${schedule.id}`));
20417
+ console.log();
20418
+ } catch (error43) {
20419
+ console.error(chalk31.red("\u2717 Failed to get schedule status"));
20420
+ if (error43 instanceof Error) {
20421
+ if (error43.message.includes("Not authenticated")) {
20422
+ console.error(chalk31.dim(" Run: vm0 auth login"));
20423
+ } else if (error43.message.includes("not found") || error43.message.includes("Not found")) {
20424
+ console.error(chalk31.dim(` Schedule "${name}" not found`));
20425
+ } else {
20426
+ console.error(chalk31.dim(` ${error43.message}`));
20427
+ }
20428
+ }
20429
+ process.exit(1);
20430
+ }
20431
+ });
20432
+
20433
+ // src/commands/schedule/delete.ts
20434
+ import { Command as Command30 } from "commander";
20435
+ import chalk32 from "chalk";
20436
+ import * as readline from "readline";
20437
+ async function confirm(message) {
20438
+ const rl = readline.createInterface({
20439
+ input: process.stdin,
20440
+ output: process.stdout
20441
+ });
20442
+ return new Promise((resolve2) => {
20443
+ rl.question(`${message} (y/N) `, (answer) => {
20444
+ rl.close();
20445
+ resolve2(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
20446
+ });
20447
+ });
20448
+ }
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) => {
20450
+ try {
20451
+ const result = loadAgentName();
20452
+ if (result.error) {
20453
+ console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20454
+ process.exit(1);
20455
+ }
20456
+ 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"));
20459
+ process.exit(1);
20460
+ }
20461
+ const agentName = result.agentName;
20462
+ let composeId;
20463
+ try {
20464
+ const compose = await apiClient.getComposeByName(agentName);
20465
+ composeId = compose.id;
20466
+ } catch {
20467
+ console.error(chalk32.red(`\u2717 Agent not found: ${agentName}`));
20468
+ console.error(chalk32.dim(" Make sure the agent is pushed first"));
20469
+ process.exit(1);
20470
+ }
20471
+ if (!options.force) {
20472
+ const confirmed = await confirm(`Delete schedule ${chalk32.cyan(name)}?`);
20473
+ if (!confirmed) {
20474
+ console.log(chalk32.dim("Cancelled"));
20475
+ return;
20476
+ }
20477
+ }
20478
+ const response = await apiClient.delete(
20479
+ `/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
20480
+ );
20481
+ if (!response.ok) {
20482
+ const error43 = await response.json();
20483
+ throw new Error(error43.error?.message || "Delete failed");
20484
+ }
20485
+ console.log(chalk32.green(`\u2713 Deleted schedule ${chalk32.cyan(name)}`));
20486
+ } catch (error43) {
20487
+ console.error(chalk32.red("\u2717 Failed to delete schedule"));
20488
+ if (error43 instanceof Error) {
20489
+ if (error43.message.includes("Not authenticated")) {
20490
+ console.error(chalk32.dim(" Run: vm0 auth login"));
20491
+ } else {
20492
+ console.error(chalk32.dim(` ${error43.message}`));
20493
+ }
20494
+ }
20495
+ process.exit(1);
20496
+ }
20497
+ });
20498
+
20499
+ // 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) => {
20503
+ try {
20504
+ const result = loadAgentName();
20505
+ if (result.error) {
20506
+ console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20507
+ process.exit(1);
20508
+ }
20509
+ 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"));
20512
+ process.exit(1);
20513
+ }
20514
+ const agentName = result.agentName;
20515
+ let composeId;
20516
+ try {
20517
+ const compose = await apiClient.getComposeByName(agentName);
20518
+ composeId = compose.id;
20519
+ } catch {
20520
+ console.error(chalk33.red(`\u2717 Agent not found: ${agentName}`));
20521
+ console.error(chalk33.dim(" Make sure the agent is pushed first"));
20522
+ process.exit(1);
20523
+ }
20524
+ const response = await apiClient.post(
20525
+ `/api/agent/schedules/${encodeURIComponent(name)}/enable`,
20526
+ { body: JSON.stringify({ composeId }) }
20527
+ );
20528
+ if (!response.ok) {
20529
+ const error43 = await response.json();
20530
+ throw new Error(error43.error?.message || "Enable failed");
20531
+ }
20532
+ console.log(chalk33.green(`\u2713 Enabled schedule ${chalk33.cyan(name)}`));
20533
+ } catch (error43) {
20534
+ console.error(chalk33.red("\u2717 Failed to enable schedule"));
20535
+ if (error43 instanceof Error) {
20536
+ if (error43.message.includes("Not authenticated")) {
20537
+ console.error(chalk33.dim(" Run: vm0 auth login"));
20538
+ } else {
20539
+ console.error(chalk33.dim(` ${error43.message}`));
20540
+ }
20541
+ }
20542
+ process.exit(1);
20543
+ }
20544
+ });
20545
+
20546
+ // 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) => {
20550
+ try {
20551
+ const result = loadAgentName();
20552
+ if (result.error) {
20553
+ console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
20554
+ process.exit(1);
20555
+ }
20556
+ 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"));
20559
+ process.exit(1);
20560
+ }
20561
+ const agentName = result.agentName;
20562
+ let composeId;
20563
+ try {
20564
+ const compose = await apiClient.getComposeByName(agentName);
20565
+ composeId = compose.id;
20566
+ } catch {
20567
+ console.error(chalk34.red(`\u2717 Agent not found: ${agentName}`));
20568
+ console.error(chalk34.dim(" Make sure the agent is pushed first"));
20569
+ process.exit(1);
20570
+ }
20571
+ const response = await apiClient.post(
20572
+ `/api/agent/schedules/${encodeURIComponent(name)}/disable`,
20573
+ { body: JSON.stringify({ composeId }) }
20574
+ );
20575
+ if (!response.ok) {
20576
+ const error43 = await response.json();
20577
+ throw new Error(error43.error?.message || "Disable failed");
20578
+ }
20579
+ console.log(chalk34.green(`\u2713 Disabled schedule ${chalk34.cyan(name)}`));
20580
+ } catch (error43) {
20581
+ console.error(chalk34.red("\u2717 Failed to disable schedule"));
20582
+ if (error43 instanceof Error) {
20583
+ if (error43.message.includes("Not authenticated")) {
20584
+ console.error(chalk34.dim(" Run: vm0 auth login"));
20585
+ } else {
20586
+ console.error(chalk34.dim(` ${error43.message}`));
20587
+ }
20588
+ }
20589
+ process.exit(1);
20590
+ }
20591
+ });
20592
+
20593
+ // 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);
20595
+
19860
20596
  // src/index.ts
19861
- var program = new Command27();
19862
- program.name("vm0").description("VM0 CLI - A modern build tool").version("5.1.2");
20597
+ var program = new Command34();
20598
+ program.name("vm0").description("VM0 CLI - A modern build tool").version("5.2.0");
19863
20599
  program.command("info").description("Display environment information").action(async () => {
19864
- console.log(chalk29.bold("System Information:"));
20600
+ console.log(chalk35.bold("System Information:"));
19865
20601
  console.log(`Node Version: ${process.version}`);
19866
20602
  console.log(`Platform: ${process.platform}`);
19867
20603
  console.log(`Architecture: ${process.arch}`);
@@ -19891,6 +20627,7 @@ program.addCommand(scopeCommand);
19891
20627
  program.addCommand(agentsCommand);
19892
20628
  program.addCommand(initCommand3);
19893
20629
  program.addCommand(setupGithubCommand);
20630
+ program.addCommand(scheduleCommand);
19894
20631
  if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
19895
20632
  program.parse();
19896
20633
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "5.1.2",
3
+ "version": "5.2.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",