@vm0/cli 5.1.3 → 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.
- package/index.js +1184 -93
- 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
|
|
10
|
-
import
|
|
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"
|
|
@@ -2760,7 +2760,7 @@ var $ZodBase64 = /* @__PURE__ */ $constructor("$ZodBase64", (inst, def) => {
|
|
|
2760
2760
|
function isValidBase64URL(data) {
|
|
2761
2761
|
if (!base64url.test(data))
|
|
2762
2762
|
return false;
|
|
2763
|
-
const base643 = data.replace(/[-_]/g, (
|
|
2763
|
+
const base643 = data.replace(/[-_]/g, (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
|
|
11676
|
-
inst.minDate =
|
|
11677
|
-
inst.maxDate =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
14402
|
+
var publicVolumeDownloadContract = c15.router({
|
|
14206
14403
|
download: {
|
|
14207
14404
|
method: "GET",
|
|
14208
14405
|
path: "/v1/volumes/:id/download",
|
|
@@ -14314,7 +14511,7 @@ function getProviderDisplayName(provider) {
|
|
|
14314
14511
|
return PROVIDER_DISPLAY_NAMES[provider];
|
|
14315
14512
|
}
|
|
14316
14513
|
|
|
14317
|
-
// src/lib/api-client.ts
|
|
14514
|
+
// src/lib/api/api-client.ts
|
|
14318
14515
|
var ApiClient = class {
|
|
14319
14516
|
async getHeaders() {
|
|
14320
14517
|
const token = await getToken();
|
|
@@ -14444,22 +14641,6 @@ var ApiClient = class {
|
|
|
14444
14641
|
}
|
|
14445
14642
|
return await response.json();
|
|
14446
14643
|
}
|
|
14447
|
-
async getTelemetry(runId) {
|
|
14448
|
-
const baseUrl = await this.getBaseUrl();
|
|
14449
|
-
const headers = await this.getHeaders();
|
|
14450
|
-
const response = await fetch(
|
|
14451
|
-
`${baseUrl}/api/agent/runs/${runId}/telemetry`,
|
|
14452
|
-
{
|
|
14453
|
-
method: "GET",
|
|
14454
|
-
headers
|
|
14455
|
-
}
|
|
14456
|
-
);
|
|
14457
|
-
if (!response.ok) {
|
|
14458
|
-
const error43 = await response.json();
|
|
14459
|
-
throw new Error(error43.error?.message || "Failed to fetch telemetry");
|
|
14460
|
-
}
|
|
14461
|
-
return await response.json();
|
|
14462
|
-
}
|
|
14463
14644
|
async getSystemLog(runId, options) {
|
|
14464
14645
|
const baseUrl = await this.getBaseUrl();
|
|
14465
14646
|
const headers = await this.getHeaders();
|
|
@@ -14560,20 +14741,6 @@ var ApiClient = class {
|
|
|
14560
14741
|
}
|
|
14561
14742
|
return await response.json();
|
|
14562
14743
|
}
|
|
14563
|
-
async createImage(body) {
|
|
14564
|
-
const baseUrl = await this.getBaseUrl();
|
|
14565
|
-
const headers = await this.getHeaders();
|
|
14566
|
-
const response = await fetch(`${baseUrl}/api/images`, {
|
|
14567
|
-
method: "POST",
|
|
14568
|
-
headers,
|
|
14569
|
-
body: JSON.stringify(body)
|
|
14570
|
-
});
|
|
14571
|
-
if (!response.ok) {
|
|
14572
|
-
const error43 = await response.json();
|
|
14573
|
-
throw new Error(error43.error?.message || "Failed to create image");
|
|
14574
|
-
}
|
|
14575
|
-
return await response.json();
|
|
14576
|
-
}
|
|
14577
14744
|
/**
|
|
14578
14745
|
* Get current user's scope
|
|
14579
14746
|
*/
|
|
@@ -14735,7 +14902,7 @@ var ApiClient = class {
|
|
|
14735
14902
|
};
|
|
14736
14903
|
var apiClient = new ApiClient();
|
|
14737
14904
|
|
|
14738
|
-
// src/lib/provider-config.ts
|
|
14905
|
+
// src/lib/domain/provider-config.ts
|
|
14739
14906
|
var PROVIDER_DEFAULTS = {
|
|
14740
14907
|
"claude-code": {
|
|
14741
14908
|
workingDir: "/home/user/workspace",
|
|
@@ -14799,7 +14966,7 @@ function getDefaultImageWithApps(provider, apps) {
|
|
|
14799
14966
|
return isDevelopment ? defaults.image.development : defaults.image.production;
|
|
14800
14967
|
}
|
|
14801
14968
|
|
|
14802
|
-
// src/lib/yaml-validator.ts
|
|
14969
|
+
// src/lib/domain/yaml-validator.ts
|
|
14803
14970
|
function validateAgentName(name) {
|
|
14804
14971
|
const nameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{1,62}[a-zA-Z0-9])?$/;
|
|
14805
14972
|
return nameRegex.test(name);
|
|
@@ -15066,12 +15233,12 @@ function validateAgentCompose(config2) {
|
|
|
15066
15233
|
return { valid: true };
|
|
15067
15234
|
}
|
|
15068
15235
|
|
|
15069
|
-
// src/lib/system-storage.ts
|
|
15236
|
+
// src/lib/storage/system-storage.ts
|
|
15070
15237
|
import * as fs4 from "fs/promises";
|
|
15071
15238
|
import * as path4 from "path";
|
|
15072
15239
|
import * as os3 from "os";
|
|
15073
15240
|
|
|
15074
|
-
// src/lib/github-skills.ts
|
|
15241
|
+
// src/lib/domain/github-skills.ts
|
|
15075
15242
|
import * as fs from "fs/promises";
|
|
15076
15243
|
import * as path from "path";
|
|
15077
15244
|
import * as os from "os";
|
|
@@ -15155,14 +15322,14 @@ async function readSkillFrontmatter(skillDir) {
|
|
|
15155
15322
|
return parseSkillFrontmatter(content);
|
|
15156
15323
|
}
|
|
15157
15324
|
|
|
15158
|
-
// src/lib/direct-upload.ts
|
|
15325
|
+
// src/lib/storage/direct-upload.ts
|
|
15159
15326
|
import { createHash } from "crypto";
|
|
15160
15327
|
import * as fs3 from "fs";
|
|
15161
15328
|
import * as path3 from "path";
|
|
15162
15329
|
import * as os2 from "os";
|
|
15163
15330
|
import * as tar2 from "tar";
|
|
15164
15331
|
|
|
15165
|
-
// src/lib/file-utils.ts
|
|
15332
|
+
// src/lib/utils/file-utils.ts
|
|
15166
15333
|
import * as fs2 from "fs";
|
|
15167
15334
|
import * as path2 from "path";
|
|
15168
15335
|
import * as tar from "tar";
|
|
@@ -15262,7 +15429,7 @@ async function removeEmptyDirs(dir, excludeDirs = [".vm0"]) {
|
|
|
15262
15429
|
return isEmpty;
|
|
15263
15430
|
}
|
|
15264
15431
|
|
|
15265
|
-
// src/lib/direct-upload.ts
|
|
15432
|
+
// src/lib/storage/direct-upload.ts
|
|
15266
15433
|
async function hashFileStream(filePath) {
|
|
15267
15434
|
return new Promise((resolve2, reject) => {
|
|
15268
15435
|
const hash2 = createHash("sha256");
|
|
@@ -15477,7 +15644,7 @@ async function directUpload(storageName, storageType, cwd, options) {
|
|
|
15477
15644
|
};
|
|
15478
15645
|
}
|
|
15479
15646
|
|
|
15480
|
-
// src/lib/system-storage.ts
|
|
15647
|
+
// src/lib/storage/system-storage.ts
|
|
15481
15648
|
function getInstructionsFilename(provider) {
|
|
15482
15649
|
const validatedProvider = getValidatedProvider(provider);
|
|
15483
15650
|
if (validatedProvider === "codex") {
|
|
@@ -15803,7 +15970,7 @@ import * as fs5 from "fs";
|
|
|
15803
15970
|
import * as path5 from "path";
|
|
15804
15971
|
import { config as dotenvConfig } from "dotenv";
|
|
15805
15972
|
|
|
15806
|
-
// src/lib/claude-event-parser.ts
|
|
15973
|
+
// src/lib/events/claude-event-parser.ts
|
|
15807
15974
|
var ClaudeEventParser = class {
|
|
15808
15975
|
/**
|
|
15809
15976
|
* Parse a raw Claude Code JSONL event into a simplified format
|
|
@@ -15907,7 +16074,7 @@ var ClaudeEventParser = class {
|
|
|
15907
16074
|
}
|
|
15908
16075
|
};
|
|
15909
16076
|
|
|
15910
|
-
// src/lib/codex-event-parser.ts
|
|
16077
|
+
// src/lib/events/codex-event-parser.ts
|
|
15911
16078
|
var CodexEventParser = class {
|
|
15912
16079
|
/**
|
|
15913
16080
|
* Parse a raw Codex CLI JSONL event into a simplified format
|
|
@@ -16061,9 +16228,9 @@ var CodexEventParser = class {
|
|
|
16061
16228
|
}
|
|
16062
16229
|
}
|
|
16063
16230
|
if (itemType === "file_change" && item.changes && item.changes.length > 0) {
|
|
16064
|
-
const changes = item.changes.map((
|
|
16065
|
-
const action =
|
|
16066
|
-
return `${action}: ${
|
|
16231
|
+
const changes = item.changes.map((c16) => {
|
|
16232
|
+
const action = c16.kind === "add" ? "Created" : c16.kind === "modify" ? "Modified" : "Deleted";
|
|
16233
|
+
return `${action}: ${c16.path}`;
|
|
16067
16234
|
}).join("\n");
|
|
16068
16235
|
return {
|
|
16069
16236
|
type: "text",
|
|
@@ -16097,7 +16264,7 @@ ${changes}` }
|
|
|
16097
16264
|
}
|
|
16098
16265
|
};
|
|
16099
16266
|
|
|
16100
|
-
// src/lib/event-parser-factory.ts
|
|
16267
|
+
// src/lib/events/event-parser-factory.ts
|
|
16101
16268
|
function detectProviderFromEvent(rawEvent) {
|
|
16102
16269
|
if (!rawEvent || typeof rawEvent !== "object") {
|
|
16103
16270
|
return null;
|
|
@@ -16123,7 +16290,7 @@ function parseEvent(rawEvent, provider) {
|
|
|
16123
16290
|
return Parser.parse(rawEvent);
|
|
16124
16291
|
}
|
|
16125
16292
|
|
|
16126
|
-
// src/lib/event-renderer.ts
|
|
16293
|
+
// src/lib/events/event-renderer.ts
|
|
16127
16294
|
import chalk3 from "chalk";
|
|
16128
16295
|
var EventRenderer = class {
|
|
16129
16296
|
/**
|
|
@@ -16311,7 +16478,7 @@ var EventRenderer = class {
|
|
|
16311
16478
|
}
|
|
16312
16479
|
};
|
|
16313
16480
|
|
|
16314
|
-
// src/lib/codex-event-renderer.ts
|
|
16481
|
+
// src/lib/events/codex-event-renderer.ts
|
|
16315
16482
|
import chalk4 from "chalk";
|
|
16316
16483
|
var CodexEventRenderer = class {
|
|
16317
16484
|
/**
|
|
@@ -16404,9 +16571,9 @@ var CodexEventRenderer = class {
|
|
|
16404
16571
|
return;
|
|
16405
16572
|
}
|
|
16406
16573
|
if (itemType === "file_change" && item.changes && item.changes.length > 0) {
|
|
16407
|
-
const summary = item.changes.map((
|
|
16408
|
-
const icon =
|
|
16409
|
-
return `${icon}${
|
|
16574
|
+
const summary = item.changes.map((c16) => {
|
|
16575
|
+
const icon = c16.kind === "add" ? "+" : c16.kind === "delete" ? "-" : "~";
|
|
16576
|
+
return `${icon}${c16.path}`;
|
|
16410
16577
|
}).join(", ");
|
|
16411
16578
|
console.log(chalk4.green("[files]") + ` ${summary}`);
|
|
16412
16579
|
return;
|
|
@@ -16981,7 +17148,7 @@ import { Command as Command3 } from "commander";
|
|
|
16981
17148
|
import chalk6 from "chalk";
|
|
16982
17149
|
import path7 from "path";
|
|
16983
17150
|
|
|
16984
|
-
// src/lib/storage-utils.ts
|
|
17151
|
+
// src/lib/storage/storage-utils.ts
|
|
16985
17152
|
import { readFile as readFile5, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
|
|
16986
17153
|
import { existsSync as existsSync5 } from "fs";
|
|
16987
17154
|
import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
|
|
@@ -17028,7 +17195,7 @@ async function writeStorageConfig(storageName, basePath = process.cwd(), type =
|
|
|
17028
17195
|
await writeFile4(configPath, yamlContent, "utf8");
|
|
17029
17196
|
}
|
|
17030
17197
|
|
|
17031
|
-
// src/lib/prompt-utils.ts
|
|
17198
|
+
// src/lib/utils/prompt-utils.ts
|
|
17032
17199
|
import prompts2 from "prompts";
|
|
17033
17200
|
function isInteractive() {
|
|
17034
17201
|
return process.stdout.isTTY === true;
|
|
@@ -17072,6 +17239,26 @@ async function promptConfirm(message, initial = true) {
|
|
|
17072
17239
|
);
|
|
17073
17240
|
return response.value;
|
|
17074
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
|
+
}
|
|
17075
17262
|
|
|
17076
17263
|
// src/commands/volume/init.ts
|
|
17077
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) => {
|
|
@@ -17206,7 +17393,7 @@ import * as fs6 from "fs";
|
|
|
17206
17393
|
import * as os4 from "os";
|
|
17207
17394
|
import * as tar3 from "tar";
|
|
17208
17395
|
|
|
17209
|
-
// src/lib/pull-utils.ts
|
|
17396
|
+
// src/lib/storage/pull-utils.ts
|
|
17210
17397
|
import chalk8 from "chalk";
|
|
17211
17398
|
async function handleEmptyStorageResponse(cwd) {
|
|
17212
17399
|
console.log(chalk8.dim("Syncing local files..."));
|
|
@@ -17442,7 +17629,7 @@ var listCommand = new Command7().name("list").alias("ls").description("List all
|
|
|
17442
17629
|
import { Command as Command8 } from "commander";
|
|
17443
17630
|
import chalk13 from "chalk";
|
|
17444
17631
|
|
|
17445
|
-
// src/lib/clone-utils.ts
|
|
17632
|
+
// src/lib/storage/clone-utils.ts
|
|
17446
17633
|
import chalk12 from "chalk";
|
|
17447
17634
|
import path9 from "path";
|
|
17448
17635
|
import * as fs7 from "fs";
|
|
@@ -17965,7 +18152,7 @@ import { spawn as spawn2 } from "child_process";
|
|
|
17965
18152
|
import { parse as parseYaml4 } from "yaml";
|
|
17966
18153
|
import { config as dotenvConfig2 } from "dotenv";
|
|
17967
18154
|
|
|
17968
|
-
// src/lib/update-checker.ts
|
|
18155
|
+
// src/lib/utils/update-checker.ts
|
|
17969
18156
|
import https from "https";
|
|
17970
18157
|
import { spawn } from "child_process";
|
|
17971
18158
|
import chalk20 from "chalk";
|
|
@@ -18073,7 +18260,7 @@ async function checkAndUpgrade(currentVersion, prompt) {
|
|
|
18073
18260
|
return true;
|
|
18074
18261
|
}
|
|
18075
18262
|
|
|
18076
|
-
// src/lib/cook-state.ts
|
|
18263
|
+
// src/lib/domain/cook-state.ts
|
|
18077
18264
|
import { homedir as homedir2 } from "os";
|
|
18078
18265
|
import { join as join6 } from "path";
|
|
18079
18266
|
import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
@@ -18298,7 +18485,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
18298
18485
|
}
|
|
18299
18486
|
var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
|
|
18300
18487
|
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(async (prompt, options) => {
|
|
18301
|
-
const shouldExit = await checkAndUpgrade("5.
|
|
18488
|
+
const shouldExit = await checkAndUpgrade("5.3.0", prompt);
|
|
18302
18489
|
if (shouldExit) {
|
|
18303
18490
|
process.exit(0);
|
|
18304
18491
|
}
|
|
@@ -18586,7 +18773,7 @@ var cookCommand = cookCmd;
|
|
|
18586
18773
|
import { Command as Command18 } from "commander";
|
|
18587
18774
|
import chalk22 from "chalk";
|
|
18588
18775
|
|
|
18589
|
-
// src/lib/time-parser.ts
|
|
18776
|
+
// src/lib/utils/time-parser.ts
|
|
18590
18777
|
function parseTime(timeStr) {
|
|
18591
18778
|
const relativeMatch = timeStr.match(/^(\d+)([smhdw])$/);
|
|
18592
18779
|
if (relativeMatch) {
|
|
@@ -18982,7 +19169,7 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
18982
19169
|
);
|
|
18983
19170
|
return;
|
|
18984
19171
|
}
|
|
18985
|
-
const nameWidth = Math.max(4, ...data.composes.map((
|
|
19172
|
+
const nameWidth = Math.max(4, ...data.composes.map((c16) => c16.name.length));
|
|
18986
19173
|
const header = ["NAME".padEnd(nameWidth), "VERSION", "UPDATED"].join(
|
|
18987
19174
|
" "
|
|
18988
19175
|
);
|
|
@@ -19013,7 +19200,7 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
19013
19200
|
import { Command as Command23 } from "commander";
|
|
19014
19201
|
import chalk26 from "chalk";
|
|
19015
19202
|
|
|
19016
|
-
// src/lib/source-derivation.ts
|
|
19203
|
+
// src/lib/domain/source-derivation.ts
|
|
19017
19204
|
import * as fs9 from "fs/promises";
|
|
19018
19205
|
import * as path13 from "path";
|
|
19019
19206
|
import * as os7 from "os";
|
|
@@ -19861,11 +20048,914 @@ var setupGithubCommand = new Command26().name("setup-github").description("Initi
|
|
|
19861
20048
|
}
|
|
19862
20049
|
);
|
|
19863
20050
|
|
|
20051
|
+
// src/commands/schedule/index.ts
|
|
20052
|
+
import { Command as Command34 } from "commander";
|
|
20053
|
+
|
|
20054
|
+
// src/commands/schedule/init.ts
|
|
20055
|
+
import { Command as Command27 } from "commander";
|
|
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
|
|
20061
|
+
import { existsSync as existsSync11, readFileSync as readFileSync2 } from "fs";
|
|
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";
|
|
20477
|
+
function expandEnvVars(value) {
|
|
20478
|
+
return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
|
|
20479
|
+
const envValue = process.env[varName];
|
|
20480
|
+
if (envValue === void 0) {
|
|
20481
|
+
console.warn(
|
|
20482
|
+
chalk30.yellow(` Warning: Environment variable ${varName} not set`)
|
|
20483
|
+
);
|
|
20484
|
+
return match;
|
|
20485
|
+
}
|
|
20486
|
+
return envValue;
|
|
20487
|
+
});
|
|
20488
|
+
}
|
|
20489
|
+
function expandEnvVarsInObject(obj) {
|
|
20490
|
+
if (!obj) return void 0;
|
|
20491
|
+
const result = {};
|
|
20492
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
20493
|
+
result[key] = expandEnvVars(value);
|
|
20494
|
+
}
|
|
20495
|
+
return result;
|
|
20496
|
+
}
|
|
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) => {
|
|
20498
|
+
try {
|
|
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"));
|
|
20502
|
+
process.exit(1);
|
|
20503
|
+
}
|
|
20504
|
+
const content = readFileSync3(file2, "utf-8");
|
|
20505
|
+
let parsed;
|
|
20506
|
+
try {
|
|
20507
|
+
parsed = parseYaml7(content);
|
|
20508
|
+
} catch (err) {
|
|
20509
|
+
console.error(chalk30.red("\u2717 Invalid YAML syntax"));
|
|
20510
|
+
if (err instanceof Error) {
|
|
20511
|
+
console.error(chalk30.dim(` ${err.message}`));
|
|
20512
|
+
}
|
|
20513
|
+
process.exit(1);
|
|
20514
|
+
}
|
|
20515
|
+
const result = scheduleYamlSchema.safeParse(parsed);
|
|
20516
|
+
if (!result.success) {
|
|
20517
|
+
console.error(chalk30.red("\u2717 Invalid schedule.yaml format"));
|
|
20518
|
+
for (const issue2 of result.error.issues) {
|
|
20519
|
+
console.error(
|
|
20520
|
+
chalk30.dim(` ${issue2.path.join(".")}: ${issue2.message}`)
|
|
20521
|
+
);
|
|
20522
|
+
}
|
|
20523
|
+
process.exit(1);
|
|
20524
|
+
}
|
|
20525
|
+
const scheduleYaml = result.data;
|
|
20526
|
+
const scheduleEntries = Object.entries(scheduleYaml.schedules);
|
|
20527
|
+
if (scheduleEntries.length === 0) {
|
|
20528
|
+
console.error(chalk30.red("\u2717 No schedules defined in file"));
|
|
20529
|
+
process.exit(1);
|
|
20530
|
+
}
|
|
20531
|
+
if (scheduleEntries.length > 1) {
|
|
20532
|
+
console.error(
|
|
20533
|
+
chalk30.red("\u2717 Multiple schedules per file not supported yet")
|
|
20534
|
+
);
|
|
20535
|
+
console.error(chalk30.dim(" Please use one schedule per file"));
|
|
20536
|
+
process.exit(1);
|
|
20537
|
+
}
|
|
20538
|
+
const [scheduleName, schedule] = scheduleEntries[0];
|
|
20539
|
+
console.log(`Deploying schedule ${chalk30.cyan(scheduleName)}...`);
|
|
20540
|
+
const agentRef = schedule.run.agent;
|
|
20541
|
+
let composeId;
|
|
20542
|
+
try {
|
|
20543
|
+
const namePart = agentRef.includes("/") ? agentRef.split("/").pop() : agentRef;
|
|
20544
|
+
const agentName = namePart.includes(":") ? namePart.split(":")[0] : namePart;
|
|
20545
|
+
const compose = await apiClient.getComposeByName(agentName);
|
|
20546
|
+
composeId = compose.id;
|
|
20547
|
+
} catch {
|
|
20548
|
+
console.error(chalk30.red(`\u2717 Agent not found: ${agentRef}`));
|
|
20549
|
+
console.error(chalk30.dim(" Make sure the agent is pushed first"));
|
|
20550
|
+
process.exit(1);
|
|
20551
|
+
}
|
|
20552
|
+
const expandedVars = expandEnvVarsInObject(schedule.run.vars);
|
|
20553
|
+
const expandedSecrets = expandEnvVarsInObject(schedule.run.secrets);
|
|
20554
|
+
const body = {
|
|
20555
|
+
name: scheduleName,
|
|
20556
|
+
composeId,
|
|
20557
|
+
cronExpression: schedule.on.cron,
|
|
20558
|
+
atTime: schedule.on.at,
|
|
20559
|
+
timezone: schedule.on.timezone || "UTC",
|
|
20560
|
+
prompt: schedule.run.prompt,
|
|
20561
|
+
vars: expandedVars,
|
|
20562
|
+
secrets: expandedSecrets,
|
|
20563
|
+
artifactName: schedule.run.artifactName,
|
|
20564
|
+
artifactVersion: schedule.run.artifactVersion,
|
|
20565
|
+
volumeVersions: schedule.run.volumeVersions
|
|
20566
|
+
};
|
|
20567
|
+
const response = await apiClient.post("/api/agent/schedules", {
|
|
20568
|
+
body: JSON.stringify(body)
|
|
20569
|
+
});
|
|
20570
|
+
if (!response.ok) {
|
|
20571
|
+
const error43 = await response.json();
|
|
20572
|
+
throw new Error(error43.error?.message || "Deploy failed");
|
|
20573
|
+
}
|
|
20574
|
+
const deployResult = await response.json();
|
|
20575
|
+
if (deployResult.created) {
|
|
20576
|
+
console.log(
|
|
20577
|
+
chalk30.green(`\u2713 Created schedule ${chalk30.cyan(scheduleName)}`)
|
|
20578
|
+
);
|
|
20579
|
+
} else {
|
|
20580
|
+
console.log(
|
|
20581
|
+
chalk30.green(`\u2713 Updated schedule ${chalk30.cyan(scheduleName)}`)
|
|
20582
|
+
);
|
|
20583
|
+
}
|
|
20584
|
+
if (deployResult.schedule.nextRunAt) {
|
|
20585
|
+
const nextRun = new Date(deployResult.schedule.nextRunAt);
|
|
20586
|
+
console.log(chalk30.dim(` Next run: ${nextRun.toLocaleString()}`));
|
|
20587
|
+
}
|
|
20588
|
+
if (deployResult.schedule.cronExpression) {
|
|
20589
|
+
console.log(
|
|
20590
|
+
chalk30.dim(
|
|
20591
|
+
` Cron: ${deployResult.schedule.cronExpression} (${deployResult.schedule.timezone})`
|
|
20592
|
+
)
|
|
20593
|
+
);
|
|
20594
|
+
} else if (deployResult.schedule.atTime) {
|
|
20595
|
+
console.log(chalk30.dim(` At: ${deployResult.schedule.atTime}`));
|
|
20596
|
+
}
|
|
20597
|
+
} catch (error43) {
|
|
20598
|
+
console.error(chalk30.red("\u2717 Failed to deploy schedule"));
|
|
20599
|
+
if (error43 instanceof Error) {
|
|
20600
|
+
if (error43.message.includes("Not authenticated")) {
|
|
20601
|
+
console.error(chalk30.dim(" Run: vm0 auth login"));
|
|
20602
|
+
} else {
|
|
20603
|
+
console.error(chalk30.dim(` ${error43.message}`));
|
|
20604
|
+
}
|
|
20605
|
+
}
|
|
20606
|
+
process.exit(1);
|
|
20607
|
+
}
|
|
20608
|
+
});
|
|
20609
|
+
|
|
20610
|
+
// src/commands/schedule/list.ts
|
|
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 () => {
|
|
20614
|
+
try {
|
|
20615
|
+
const response = await apiClient.get("/api/agent/schedules");
|
|
20616
|
+
if (!response.ok) {
|
|
20617
|
+
const error43 = await response.json();
|
|
20618
|
+
throw new Error(error43.error?.message || "List failed");
|
|
20619
|
+
}
|
|
20620
|
+
const result = await response.json();
|
|
20621
|
+
if (result.schedules.length === 0) {
|
|
20622
|
+
console.log(chalk31.dim("No schedules found"));
|
|
20623
|
+
console.log(
|
|
20624
|
+
chalk31.dim(" Create one with: vm0 schedule deploy schedule.yaml")
|
|
20625
|
+
);
|
|
20626
|
+
return;
|
|
20627
|
+
}
|
|
20628
|
+
const nameWidth = Math.max(
|
|
20629
|
+
4,
|
|
20630
|
+
...result.schedules.map((s) => s.name.length)
|
|
20631
|
+
);
|
|
20632
|
+
const agentWidth = Math.max(
|
|
20633
|
+
5,
|
|
20634
|
+
...result.schedules.map((s) => s.composeName.length)
|
|
20635
|
+
);
|
|
20636
|
+
const triggerWidth = Math.max(
|
|
20637
|
+
7,
|
|
20638
|
+
...result.schedules.map(
|
|
20639
|
+
(s) => s.cronExpression ? s.cronExpression.length + s.timezone.length + 3 : s.atTime?.length || 0
|
|
20640
|
+
)
|
|
20641
|
+
);
|
|
20642
|
+
const header = [
|
|
20643
|
+
"NAME".padEnd(nameWidth),
|
|
20644
|
+
"AGENT".padEnd(agentWidth),
|
|
20645
|
+
"TRIGGER".padEnd(triggerWidth),
|
|
20646
|
+
"STATUS".padEnd(8),
|
|
20647
|
+
"NEXT RUN"
|
|
20648
|
+
].join(" ");
|
|
20649
|
+
console.log(chalk31.dim(header));
|
|
20650
|
+
for (const schedule of result.schedules) {
|
|
20651
|
+
const trigger = schedule.cronExpression ? `${schedule.cronExpression} (${schedule.timezone})` : schedule.atTime || "-";
|
|
20652
|
+
const status = schedule.enabled ? chalk31.green("enabled") : chalk31.yellow("disabled");
|
|
20653
|
+
const nextRun = schedule.enabled ? formatRelativeTime2(schedule.nextRunAt) : "-";
|
|
20654
|
+
const row = [
|
|
20655
|
+
schedule.name.padEnd(nameWidth),
|
|
20656
|
+
schedule.composeName.padEnd(agentWidth),
|
|
20657
|
+
trigger.padEnd(triggerWidth),
|
|
20658
|
+
status.padEnd(8 + (schedule.enabled ? 0 : 2)),
|
|
20659
|
+
// Account for chalk chars
|
|
20660
|
+
nextRun
|
|
20661
|
+
].join(" ");
|
|
20662
|
+
console.log(row);
|
|
20663
|
+
}
|
|
20664
|
+
} catch (error43) {
|
|
20665
|
+
console.error(chalk31.red("\u2717 Failed to list schedules"));
|
|
20666
|
+
if (error43 instanceof Error) {
|
|
20667
|
+
if (error43.message.includes("Not authenticated")) {
|
|
20668
|
+
console.error(chalk31.dim(" Run: vm0 auth login"));
|
|
20669
|
+
} else {
|
|
20670
|
+
console.error(chalk31.dim(` ${error43.message}`));
|
|
20671
|
+
}
|
|
20672
|
+
}
|
|
20673
|
+
process.exit(1);
|
|
20674
|
+
}
|
|
20675
|
+
});
|
|
20676
|
+
|
|
20677
|
+
// src/commands/schedule/status.ts
|
|
20678
|
+
import { Command as Command30 } from "commander";
|
|
20679
|
+
import chalk32 from "chalk";
|
|
20680
|
+
function formatDateTimeStyled(dateStr) {
|
|
20681
|
+
if (!dateStr) return chalk32.dim("-");
|
|
20682
|
+
const formatted = formatDateTime(dateStr);
|
|
20683
|
+
return formatted.replace(/\(([^)]+)\)$/, chalk32.dim("($1)"));
|
|
20684
|
+
}
|
|
20685
|
+
function formatTrigger(schedule) {
|
|
20686
|
+
if (schedule.cronExpression) {
|
|
20687
|
+
return `${schedule.cronExpression} ${chalk32.dim(`(${schedule.timezone})`)}`;
|
|
20688
|
+
}
|
|
20689
|
+
if (schedule.atTime) {
|
|
20690
|
+
return `${schedule.atTime} ${chalk32.dim("(one-time)")}`;
|
|
20691
|
+
}
|
|
20692
|
+
return chalk32.dim("-");
|
|
20693
|
+
}
|
|
20694
|
+
var statusCommand4 = new Command30().name("status").description("Show detailed status of a schedule").argument("<name>", "Schedule name").action(async (name) => {
|
|
20695
|
+
try {
|
|
20696
|
+
const result = loadAgentName();
|
|
20697
|
+
if (result.error) {
|
|
20698
|
+
console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
20699
|
+
process.exit(1);
|
|
20700
|
+
}
|
|
20701
|
+
if (!result.agentName) {
|
|
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"));
|
|
20704
|
+
process.exit(1);
|
|
20705
|
+
}
|
|
20706
|
+
const agentName = result.agentName;
|
|
20707
|
+
let composeId;
|
|
20708
|
+
try {
|
|
20709
|
+
const compose = await apiClient.getComposeByName(agentName);
|
|
20710
|
+
composeId = compose.id;
|
|
20711
|
+
} catch {
|
|
20712
|
+
console.error(chalk32.red(`\u2717 Agent not found: ${agentName}`));
|
|
20713
|
+
console.error(chalk32.dim(" Make sure the agent is pushed first"));
|
|
20714
|
+
process.exit(1);
|
|
20715
|
+
}
|
|
20716
|
+
const response = await apiClient.get(
|
|
20717
|
+
`/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
|
|
20718
|
+
);
|
|
20719
|
+
if (!response.ok) {
|
|
20720
|
+
const error43 = await response.json();
|
|
20721
|
+
throw new Error(error43.error?.message || "Failed to get schedule");
|
|
20722
|
+
}
|
|
20723
|
+
const schedule = await response.json();
|
|
20724
|
+
console.log();
|
|
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");
|
|
20728
|
+
console.log(`${"Status:".padEnd(16)}${statusText}`);
|
|
20729
|
+
console.log(
|
|
20730
|
+
`${"Agent:".padEnd(16)}${schedule.composeName} ${chalk32.dim(`(${schedule.scopeSlug})`)}`
|
|
20731
|
+
);
|
|
20732
|
+
console.log(`${"Trigger:".padEnd(16)}${formatTrigger(schedule)}`);
|
|
20733
|
+
if (schedule.enabled) {
|
|
20734
|
+
console.log(
|
|
20735
|
+
`${"Next Run:".padEnd(16)}${formatDateTimeStyled(schedule.nextRunAt)}`
|
|
20736
|
+
);
|
|
20737
|
+
}
|
|
20738
|
+
if (schedule.lastRunAt) {
|
|
20739
|
+
const lastRunInfo = schedule.lastRunId ? `${formatDateTimeStyled(schedule.lastRunAt)} ${chalk32.dim(`[${schedule.lastRunId.slice(0, 8)}]`)}` : formatDateTimeStyled(schedule.lastRunAt);
|
|
20740
|
+
console.log(`${"Last Run:".padEnd(16)}${lastRunInfo}`);
|
|
20741
|
+
}
|
|
20742
|
+
const promptPreview = schedule.prompt.length > 60 ? schedule.prompt.slice(0, 57) + "..." : schedule.prompt;
|
|
20743
|
+
console.log(`${"Prompt:".padEnd(16)}${chalk32.dim(promptPreview)}`);
|
|
20744
|
+
if (schedule.vars && Object.keys(schedule.vars).length > 0) {
|
|
20745
|
+
console.log(
|
|
20746
|
+
`${"Variables:".padEnd(16)}${Object.keys(schedule.vars).join(", ")}`
|
|
20747
|
+
);
|
|
20748
|
+
}
|
|
20749
|
+
if (schedule.secretNames && schedule.secretNames.length > 0) {
|
|
20750
|
+
console.log(
|
|
20751
|
+
`${"Secrets:".padEnd(16)}${schedule.secretNames.join(", ")}`
|
|
20752
|
+
);
|
|
20753
|
+
}
|
|
20754
|
+
if (schedule.artifactName) {
|
|
20755
|
+
const artifactInfo = schedule.artifactVersion ? `${schedule.artifactName}:${schedule.artifactVersion}` : schedule.artifactName;
|
|
20756
|
+
console.log(`${"Artifact:".padEnd(16)}${artifactInfo}`);
|
|
20757
|
+
}
|
|
20758
|
+
if (schedule.volumeVersions && Object.keys(schedule.volumeVersions).length > 0) {
|
|
20759
|
+
console.log(
|
|
20760
|
+
`${"Volumes:".padEnd(16)}${Object.keys(schedule.volumeVersions).join(", ")}`
|
|
20761
|
+
);
|
|
20762
|
+
}
|
|
20763
|
+
console.log();
|
|
20764
|
+
console.log(
|
|
20765
|
+
chalk32.dim(
|
|
20766
|
+
`Created: ${new Date(schedule.createdAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
|
|
20767
|
+
)
|
|
20768
|
+
);
|
|
20769
|
+
console.log(
|
|
20770
|
+
chalk32.dim(
|
|
20771
|
+
`Updated: ${new Date(schedule.updatedAt).toISOString().replace("T", " ").replace(/\.\d+Z$/, " UTC")}`
|
|
20772
|
+
)
|
|
20773
|
+
);
|
|
20774
|
+
console.log(chalk32.dim(`ID: ${schedule.id}`));
|
|
20775
|
+
console.log();
|
|
20776
|
+
} catch (error43) {
|
|
20777
|
+
console.error(chalk32.red("\u2717 Failed to get schedule status"));
|
|
20778
|
+
if (error43 instanceof Error) {
|
|
20779
|
+
if (error43.message.includes("Not authenticated")) {
|
|
20780
|
+
console.error(chalk32.dim(" Run: vm0 auth login"));
|
|
20781
|
+
} else if (error43.message.includes("not found") || error43.message.includes("Not found")) {
|
|
20782
|
+
console.error(chalk32.dim(` Schedule "${name}" not found`));
|
|
20783
|
+
} else {
|
|
20784
|
+
console.error(chalk32.dim(` ${error43.message}`));
|
|
20785
|
+
}
|
|
20786
|
+
}
|
|
20787
|
+
process.exit(1);
|
|
20788
|
+
}
|
|
20789
|
+
});
|
|
20790
|
+
|
|
20791
|
+
// src/commands/schedule/delete.ts
|
|
20792
|
+
import { Command as Command31 } from "commander";
|
|
20793
|
+
import chalk33 from "chalk";
|
|
20794
|
+
import * as readline from "readline";
|
|
20795
|
+
async function confirm(message) {
|
|
20796
|
+
const rl = readline.createInterface({
|
|
20797
|
+
input: process.stdin,
|
|
20798
|
+
output: process.stdout
|
|
20799
|
+
});
|
|
20800
|
+
return new Promise((resolve2) => {
|
|
20801
|
+
rl.question(`${message} (y/N) `, (answer) => {
|
|
20802
|
+
rl.close();
|
|
20803
|
+
resolve2(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
20804
|
+
});
|
|
20805
|
+
});
|
|
20806
|
+
}
|
|
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) => {
|
|
20808
|
+
try {
|
|
20809
|
+
const result = loadAgentName();
|
|
20810
|
+
if (result.error) {
|
|
20811
|
+
console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
20812
|
+
process.exit(1);
|
|
20813
|
+
}
|
|
20814
|
+
if (!result.agentName) {
|
|
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"));
|
|
20817
|
+
process.exit(1);
|
|
20818
|
+
}
|
|
20819
|
+
const agentName = result.agentName;
|
|
20820
|
+
let composeId;
|
|
20821
|
+
try {
|
|
20822
|
+
const compose = await apiClient.getComposeByName(agentName);
|
|
20823
|
+
composeId = compose.id;
|
|
20824
|
+
} catch {
|
|
20825
|
+
console.error(chalk33.red(`\u2717 Agent not found: ${agentName}`));
|
|
20826
|
+
console.error(chalk33.dim(" Make sure the agent is pushed first"));
|
|
20827
|
+
process.exit(1);
|
|
20828
|
+
}
|
|
20829
|
+
if (!options.force) {
|
|
20830
|
+
const confirmed = await confirm(`Delete schedule ${chalk33.cyan(name)}?`);
|
|
20831
|
+
if (!confirmed) {
|
|
20832
|
+
console.log(chalk33.dim("Cancelled"));
|
|
20833
|
+
return;
|
|
20834
|
+
}
|
|
20835
|
+
}
|
|
20836
|
+
const response = await apiClient.delete(
|
|
20837
|
+
`/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
|
|
20838
|
+
);
|
|
20839
|
+
if (!response.ok) {
|
|
20840
|
+
const error43 = await response.json();
|
|
20841
|
+
throw new Error(error43.error?.message || "Delete failed");
|
|
20842
|
+
}
|
|
20843
|
+
console.log(chalk33.green(`\u2713 Deleted schedule ${chalk33.cyan(name)}`));
|
|
20844
|
+
} catch (error43) {
|
|
20845
|
+
console.error(chalk33.red("\u2717 Failed to delete schedule"));
|
|
20846
|
+
if (error43 instanceof Error) {
|
|
20847
|
+
if (error43.message.includes("Not authenticated")) {
|
|
20848
|
+
console.error(chalk33.dim(" Run: vm0 auth login"));
|
|
20849
|
+
} else {
|
|
20850
|
+
console.error(chalk33.dim(` ${error43.message}`));
|
|
20851
|
+
}
|
|
20852
|
+
}
|
|
20853
|
+
process.exit(1);
|
|
20854
|
+
}
|
|
20855
|
+
});
|
|
20856
|
+
|
|
20857
|
+
// src/commands/schedule/enable.ts
|
|
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) => {
|
|
20861
|
+
try {
|
|
20862
|
+
const result = loadAgentName();
|
|
20863
|
+
if (result.error) {
|
|
20864
|
+
console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
20865
|
+
process.exit(1);
|
|
20866
|
+
}
|
|
20867
|
+
if (!result.agentName) {
|
|
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"));
|
|
20870
|
+
process.exit(1);
|
|
20871
|
+
}
|
|
20872
|
+
const agentName = result.agentName;
|
|
20873
|
+
let composeId;
|
|
20874
|
+
try {
|
|
20875
|
+
const compose = await apiClient.getComposeByName(agentName);
|
|
20876
|
+
composeId = compose.id;
|
|
20877
|
+
} catch {
|
|
20878
|
+
console.error(chalk34.red(`\u2717 Agent not found: ${agentName}`));
|
|
20879
|
+
console.error(chalk34.dim(" Make sure the agent is pushed first"));
|
|
20880
|
+
process.exit(1);
|
|
20881
|
+
}
|
|
20882
|
+
const response = await apiClient.post(
|
|
20883
|
+
`/api/agent/schedules/${encodeURIComponent(name)}/enable`,
|
|
20884
|
+
{ body: JSON.stringify({ composeId }) }
|
|
20885
|
+
);
|
|
20886
|
+
if (!response.ok) {
|
|
20887
|
+
const error43 = await response.json();
|
|
20888
|
+
throw new Error(error43.error?.message || "Enable failed");
|
|
20889
|
+
}
|
|
20890
|
+
console.log(chalk34.green(`\u2713 Enabled schedule ${chalk34.cyan(name)}`));
|
|
20891
|
+
} catch (error43) {
|
|
20892
|
+
console.error(chalk34.red("\u2717 Failed to enable schedule"));
|
|
20893
|
+
if (error43 instanceof Error) {
|
|
20894
|
+
if (error43.message.includes("Not authenticated")) {
|
|
20895
|
+
console.error(chalk34.dim(" Run: vm0 auth login"));
|
|
20896
|
+
} else {
|
|
20897
|
+
console.error(chalk34.dim(` ${error43.message}`));
|
|
20898
|
+
}
|
|
20899
|
+
}
|
|
20900
|
+
process.exit(1);
|
|
20901
|
+
}
|
|
20902
|
+
});
|
|
20903
|
+
|
|
20904
|
+
// src/commands/schedule/disable.ts
|
|
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) => {
|
|
20908
|
+
try {
|
|
20909
|
+
const result = loadAgentName();
|
|
20910
|
+
if (result.error) {
|
|
20911
|
+
console.error(chalk35.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
20912
|
+
process.exit(1);
|
|
20913
|
+
}
|
|
20914
|
+
if (!result.agentName) {
|
|
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"));
|
|
20917
|
+
process.exit(1);
|
|
20918
|
+
}
|
|
20919
|
+
const agentName = result.agentName;
|
|
20920
|
+
let composeId;
|
|
20921
|
+
try {
|
|
20922
|
+
const compose = await apiClient.getComposeByName(agentName);
|
|
20923
|
+
composeId = compose.id;
|
|
20924
|
+
} catch {
|
|
20925
|
+
console.error(chalk35.red(`\u2717 Agent not found: ${agentName}`));
|
|
20926
|
+
console.error(chalk35.dim(" Make sure the agent is pushed first"));
|
|
20927
|
+
process.exit(1);
|
|
20928
|
+
}
|
|
20929
|
+
const response = await apiClient.post(
|
|
20930
|
+
`/api/agent/schedules/${encodeURIComponent(name)}/disable`,
|
|
20931
|
+
{ body: JSON.stringify({ composeId }) }
|
|
20932
|
+
);
|
|
20933
|
+
if (!response.ok) {
|
|
20934
|
+
const error43 = await response.json();
|
|
20935
|
+
throw new Error(error43.error?.message || "Disable failed");
|
|
20936
|
+
}
|
|
20937
|
+
console.log(chalk35.green(`\u2713 Disabled schedule ${chalk35.cyan(name)}`));
|
|
20938
|
+
} catch (error43) {
|
|
20939
|
+
console.error(chalk35.red("\u2717 Failed to disable schedule"));
|
|
20940
|
+
if (error43 instanceof Error) {
|
|
20941
|
+
if (error43.message.includes("Not authenticated")) {
|
|
20942
|
+
console.error(chalk35.dim(" Run: vm0 auth login"));
|
|
20943
|
+
} else {
|
|
20944
|
+
console.error(chalk35.dim(` ${error43.message}`));
|
|
20945
|
+
}
|
|
20946
|
+
}
|
|
20947
|
+
process.exit(1);
|
|
20948
|
+
}
|
|
20949
|
+
});
|
|
20950
|
+
|
|
20951
|
+
// src/commands/schedule/index.ts
|
|
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);
|
|
20953
|
+
|
|
19864
20954
|
// src/index.ts
|
|
19865
|
-
var program = new
|
|
19866
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.
|
|
20955
|
+
var program = new Command35();
|
|
20956
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.3.0");
|
|
19867
20957
|
program.command("info").description("Display environment information").action(async () => {
|
|
19868
|
-
console.log(
|
|
20958
|
+
console.log(chalk36.bold("System Information:"));
|
|
19869
20959
|
console.log(`Node Version: ${process.version}`);
|
|
19870
20960
|
console.log(`Platform: ${process.platform}`);
|
|
19871
20961
|
console.log(`Architecture: ${process.arch}`);
|
|
@@ -19895,6 +20985,7 @@ program.addCommand(scopeCommand);
|
|
|
19895
20985
|
program.addCommand(agentsCommand);
|
|
19896
20986
|
program.addCommand(initCommand3);
|
|
19897
20987
|
program.addCommand(setupGithubCommand);
|
|
20988
|
+
program.addCommand(scheduleCommand);
|
|
19898
20989
|
if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
|
|
19899
20990
|
program.parse();
|
|
19900
20991
|
}
|