@vm0/cli 5.6.0 → 5.7.2
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 +740 -407
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -2595,8 +2595,7 @@ var ApiClient = class {
|
|
|
2595
2595
|
throw new Error("Not authenticated. Run: vm0 auth login");
|
|
2596
2596
|
}
|
|
2597
2597
|
const headers = {
|
|
2598
|
-
Authorization: `Bearer ${token}
|
|
2599
|
-
"Content-Type": "application/json"
|
|
2598
|
+
Authorization: `Bearer ${token}`
|
|
2600
2599
|
};
|
|
2601
2600
|
const bypassSecret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
|
2602
2601
|
if (bypassSecret) {
|
|
@@ -2614,35 +2613,41 @@ var ApiClient = class {
|
|
|
2614
2613
|
async getComposeByName(name, scope) {
|
|
2615
2614
|
const baseUrl = await this.getBaseUrl();
|
|
2616
2615
|
const headers = await this.getHeaders();
|
|
2617
|
-
const
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
{
|
|
2624
|
-
|
|
2625
|
-
|
|
2616
|
+
const client = initClient(composesMainContract, {
|
|
2617
|
+
baseUrl,
|
|
2618
|
+
baseHeaders: headers,
|
|
2619
|
+
jsonQuery: true
|
|
2620
|
+
});
|
|
2621
|
+
const result = await client.getByName({
|
|
2622
|
+
query: {
|
|
2623
|
+
name,
|
|
2624
|
+
scope
|
|
2626
2625
|
}
|
|
2627
|
-
);
|
|
2628
|
-
if (
|
|
2629
|
-
|
|
2630
|
-
throw new Error(error.error?.message || `Compose not found: ${name}`);
|
|
2626
|
+
});
|
|
2627
|
+
if (result.status === 200) {
|
|
2628
|
+
return result.body;
|
|
2631
2629
|
}
|
|
2632
|
-
|
|
2630
|
+
const errorBody = result.body;
|
|
2631
|
+
const message = errorBody.error?.message || `Compose not found: ${name}`;
|
|
2632
|
+
throw new Error(message);
|
|
2633
2633
|
}
|
|
2634
2634
|
async getComposeById(id) {
|
|
2635
2635
|
const baseUrl = await this.getBaseUrl();
|
|
2636
2636
|
const headers = await this.getHeaders();
|
|
2637
|
-
const
|
|
2638
|
-
|
|
2639
|
-
headers
|
|
2637
|
+
const client = initClient(composesByIdContract, {
|
|
2638
|
+
baseUrl,
|
|
2639
|
+
baseHeaders: headers,
|
|
2640
|
+
jsonQuery: true
|
|
2640
2641
|
});
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2642
|
+
const result = await client.getById({
|
|
2643
|
+
params: { id }
|
|
2644
|
+
});
|
|
2645
|
+
if (result.status === 200) {
|
|
2646
|
+
return result.body;
|
|
2644
2647
|
}
|
|
2645
|
-
|
|
2648
|
+
const errorBody = result.body;
|
|
2649
|
+
const message = errorBody.error?.message || `Compose not found: ${id}`;
|
|
2650
|
+
throw new Error(message);
|
|
2646
2651
|
}
|
|
2647
2652
|
/**
|
|
2648
2653
|
* Resolve a version specifier to a full version ID
|
|
@@ -2651,33 +2656,41 @@ var ApiClient = class {
|
|
|
2651
2656
|
async getComposeVersion(composeId, version) {
|
|
2652
2657
|
const baseUrl = await this.getBaseUrl();
|
|
2653
2658
|
const headers = await this.getHeaders();
|
|
2654
|
-
const
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2659
|
+
const client = initClient(composesVersionsContract, {
|
|
2660
|
+
baseUrl,
|
|
2661
|
+
baseHeaders: headers,
|
|
2662
|
+
jsonQuery: true
|
|
2663
|
+
});
|
|
2664
|
+
const result = await client.resolveVersion({
|
|
2665
|
+
query: {
|
|
2666
|
+
composeId,
|
|
2667
|
+
version
|
|
2660
2668
|
}
|
|
2661
|
-
);
|
|
2662
|
-
if (
|
|
2663
|
-
|
|
2664
|
-
throw new Error(error.error?.message || `Version not found: ${version}`);
|
|
2669
|
+
});
|
|
2670
|
+
if (result.status === 200) {
|
|
2671
|
+
return result.body;
|
|
2665
2672
|
}
|
|
2666
|
-
|
|
2673
|
+
const errorBody = result.body;
|
|
2674
|
+
const message = errorBody.error?.message || `Version not found: ${version}`;
|
|
2675
|
+
throw new Error(message);
|
|
2667
2676
|
}
|
|
2668
2677
|
async createOrUpdateCompose(body) {
|
|
2669
2678
|
const baseUrl = await this.getBaseUrl();
|
|
2670
2679
|
const headers = await this.getHeaders();
|
|
2671
|
-
const
|
|
2672
|
-
|
|
2673
|
-
headers,
|
|
2674
|
-
|
|
2680
|
+
const client = initClient(composesMainContract, {
|
|
2681
|
+
baseUrl,
|
|
2682
|
+
baseHeaders: headers,
|
|
2683
|
+
jsonQuery: true
|
|
2675
2684
|
});
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2685
|
+
const result = await client.create({
|
|
2686
|
+
body
|
|
2687
|
+
});
|
|
2688
|
+
if (result.status === 200 || result.status === 201) {
|
|
2689
|
+
return result.body;
|
|
2679
2690
|
}
|
|
2680
|
-
|
|
2691
|
+
const errorBody = result.body;
|
|
2692
|
+
const message = errorBody.error?.message || "Failed to create compose";
|
|
2693
|
+
throw new Error(message);
|
|
2681
2694
|
}
|
|
2682
2695
|
/**
|
|
2683
2696
|
* Create a run with unified request format
|
|
@@ -2703,211 +2716,545 @@ var ApiClient = class {
|
|
|
2703
2716
|
async getEvents(runId, options) {
|
|
2704
2717
|
const baseUrl = await this.getBaseUrl();
|
|
2705
2718
|
const headers = await this.getHeaders();
|
|
2706
|
-
const
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2719
|
+
const client = initClient(runEventsContract, {
|
|
2720
|
+
baseUrl,
|
|
2721
|
+
baseHeaders: headers,
|
|
2722
|
+
jsonQuery: true
|
|
2723
|
+
});
|
|
2724
|
+
const result = await client.getEvents({
|
|
2725
|
+
params: { id: runId },
|
|
2726
|
+
query: {
|
|
2727
|
+
since: options?.since ?? 0,
|
|
2728
|
+
limit: options?.limit ?? 100
|
|
2713
2729
|
}
|
|
2714
|
-
);
|
|
2715
|
-
if (
|
|
2716
|
-
|
|
2717
|
-
throw new Error(error.error?.message || "Failed to fetch events");
|
|
2730
|
+
});
|
|
2731
|
+
if (result.status === 200) {
|
|
2732
|
+
return result.body;
|
|
2718
2733
|
}
|
|
2719
|
-
|
|
2734
|
+
const errorBody = result.body;
|
|
2735
|
+
const message = errorBody.error?.message || "Failed to fetch events";
|
|
2736
|
+
throw new Error(message);
|
|
2720
2737
|
}
|
|
2721
2738
|
async getSystemLog(runId, options) {
|
|
2722
2739
|
const baseUrl = await this.getBaseUrl();
|
|
2723
2740
|
const headers = await this.getHeaders();
|
|
2724
|
-
const
|
|
2725
|
-
|
|
2726
|
-
|
|
2741
|
+
const client = initClient(runSystemLogContract, {
|
|
2742
|
+
baseUrl,
|
|
2743
|
+
baseHeaders: headers,
|
|
2744
|
+
jsonQuery: true
|
|
2745
|
+
});
|
|
2746
|
+
const result = await client.getSystemLog({
|
|
2747
|
+
params: { id: runId },
|
|
2748
|
+
query: {
|
|
2749
|
+
since: options?.since,
|
|
2750
|
+
limit: options?.limit,
|
|
2751
|
+
order: options?.order
|
|
2752
|
+
}
|
|
2753
|
+
});
|
|
2754
|
+
if (result.status === 200) {
|
|
2755
|
+
return result.body;
|
|
2727
2756
|
}
|
|
2728
|
-
|
|
2729
|
-
|
|
2757
|
+
const errorBody = result.body;
|
|
2758
|
+
const message = errorBody.error?.message || "Failed to fetch system log";
|
|
2759
|
+
throw new Error(message);
|
|
2760
|
+
}
|
|
2761
|
+
async getMetrics(runId, options) {
|
|
2762
|
+
const baseUrl = await this.getBaseUrl();
|
|
2763
|
+
const headers = await this.getHeaders();
|
|
2764
|
+
const client = initClient(runMetricsContract, {
|
|
2765
|
+
baseUrl,
|
|
2766
|
+
baseHeaders: headers,
|
|
2767
|
+
jsonQuery: true
|
|
2768
|
+
});
|
|
2769
|
+
const result = await client.getMetrics({
|
|
2770
|
+
params: { id: runId },
|
|
2771
|
+
query: {
|
|
2772
|
+
since: options?.since,
|
|
2773
|
+
limit: options?.limit,
|
|
2774
|
+
order: options?.order
|
|
2775
|
+
}
|
|
2776
|
+
});
|
|
2777
|
+
if (result.status === 200) {
|
|
2778
|
+
return result.body;
|
|
2730
2779
|
}
|
|
2731
|
-
|
|
2732
|
-
|
|
2780
|
+
const errorBody = result.body;
|
|
2781
|
+
const message = errorBody.error?.message || "Failed to fetch metrics";
|
|
2782
|
+
throw new Error(message);
|
|
2783
|
+
}
|
|
2784
|
+
async getAgentEvents(runId, options) {
|
|
2785
|
+
const baseUrl = await this.getBaseUrl();
|
|
2786
|
+
const headers = await this.getHeaders();
|
|
2787
|
+
const client = initClient(runAgentEventsContract, {
|
|
2788
|
+
baseUrl,
|
|
2789
|
+
baseHeaders: headers,
|
|
2790
|
+
jsonQuery: true
|
|
2791
|
+
});
|
|
2792
|
+
const result = await client.getAgentEvents({
|
|
2793
|
+
params: { id: runId },
|
|
2794
|
+
query: {
|
|
2795
|
+
since: options?.since,
|
|
2796
|
+
limit: options?.limit,
|
|
2797
|
+
order: options?.order
|
|
2798
|
+
}
|
|
2799
|
+
});
|
|
2800
|
+
if (result.status === 200) {
|
|
2801
|
+
return result.body;
|
|
2733
2802
|
}
|
|
2734
|
-
const
|
|
2735
|
-
const
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2803
|
+
const errorBody = result.body;
|
|
2804
|
+
const message = errorBody.error?.message || "Failed to fetch agent events";
|
|
2805
|
+
throw new Error(message);
|
|
2806
|
+
}
|
|
2807
|
+
async getNetworkLogs(runId, options) {
|
|
2808
|
+
const baseUrl = await this.getBaseUrl();
|
|
2809
|
+
const headers = await this.getHeaders();
|
|
2810
|
+
const client = initClient(runNetworkLogsContract, {
|
|
2811
|
+
baseUrl,
|
|
2812
|
+
baseHeaders: headers,
|
|
2813
|
+
jsonQuery: true
|
|
2739
2814
|
});
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2815
|
+
const result = await client.getNetworkLogs({
|
|
2816
|
+
params: { id: runId },
|
|
2817
|
+
query: {
|
|
2818
|
+
since: options?.since,
|
|
2819
|
+
limit: options?.limit,
|
|
2820
|
+
order: options?.order
|
|
2821
|
+
}
|
|
2822
|
+
});
|
|
2823
|
+
if (result.status === 200) {
|
|
2824
|
+
return result.body;
|
|
2743
2825
|
}
|
|
2744
|
-
|
|
2826
|
+
const errorBody = result.body;
|
|
2827
|
+
const message = errorBody.error?.message || "Failed to fetch network logs";
|
|
2828
|
+
throw new Error(message);
|
|
2745
2829
|
}
|
|
2746
|
-
|
|
2830
|
+
/**
|
|
2831
|
+
* Get current user's scope
|
|
2832
|
+
*/
|
|
2833
|
+
async getScope() {
|
|
2747
2834
|
const baseUrl = await this.getBaseUrl();
|
|
2748
2835
|
const headers = await this.getHeaders();
|
|
2749
|
-
const
|
|
2750
|
-
|
|
2751
|
-
|
|
2836
|
+
const client = initClient(scopeContract, {
|
|
2837
|
+
baseUrl,
|
|
2838
|
+
baseHeaders: headers,
|
|
2839
|
+
jsonQuery: true
|
|
2840
|
+
});
|
|
2841
|
+
const result = await client.get();
|
|
2842
|
+
if (result.status === 200) {
|
|
2843
|
+
return result.body;
|
|
2752
2844
|
}
|
|
2753
|
-
|
|
2754
|
-
|
|
2845
|
+
const errorBody = result.body;
|
|
2846
|
+
const message = errorBody.error?.message || "Failed to get scope";
|
|
2847
|
+
throw new Error(message);
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* Create user's scope
|
|
2851
|
+
*/
|
|
2852
|
+
async createScope(body) {
|
|
2853
|
+
const baseUrl = await this.getBaseUrl();
|
|
2854
|
+
const headers = await this.getHeaders();
|
|
2855
|
+
const client = initClient(scopeContract, {
|
|
2856
|
+
baseUrl,
|
|
2857
|
+
baseHeaders: headers,
|
|
2858
|
+
jsonQuery: true
|
|
2859
|
+
});
|
|
2860
|
+
const result = await client.create({ body });
|
|
2861
|
+
if (result.status === 201) {
|
|
2862
|
+
return result.body;
|
|
2755
2863
|
}
|
|
2756
|
-
|
|
2757
|
-
|
|
2864
|
+
const errorBody = result.body;
|
|
2865
|
+
const message = errorBody.error?.message || "Failed to create scope";
|
|
2866
|
+
throw new Error(message);
|
|
2867
|
+
}
|
|
2868
|
+
/**
|
|
2869
|
+
* Update user's scope slug
|
|
2870
|
+
*/
|
|
2871
|
+
async updateScope(body) {
|
|
2872
|
+
const baseUrl = await this.getBaseUrl();
|
|
2873
|
+
const headers = await this.getHeaders();
|
|
2874
|
+
const client = initClient(scopeContract, {
|
|
2875
|
+
baseUrl,
|
|
2876
|
+
baseHeaders: headers,
|
|
2877
|
+
jsonQuery: true
|
|
2878
|
+
});
|
|
2879
|
+
const result = await client.update({ body });
|
|
2880
|
+
if (result.status === 200) {
|
|
2881
|
+
return result.body;
|
|
2758
2882
|
}
|
|
2759
|
-
const
|
|
2760
|
-
const
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2883
|
+
const errorBody = result.body;
|
|
2884
|
+
const message = errorBody.error?.message || "Failed to update scope";
|
|
2885
|
+
throw new Error(message);
|
|
2886
|
+
}
|
|
2887
|
+
/**
|
|
2888
|
+
* Get session by ID
|
|
2889
|
+
* Used by run continue to fetch session info including secretNames
|
|
2890
|
+
*/
|
|
2891
|
+
async getSession(sessionId) {
|
|
2892
|
+
const baseUrl = await this.getBaseUrl();
|
|
2893
|
+
const headers = await this.getHeaders();
|
|
2894
|
+
const client = initClient(sessionsByIdContract, {
|
|
2895
|
+
baseUrl,
|
|
2896
|
+
baseHeaders: headers,
|
|
2897
|
+
jsonQuery: true
|
|
2764
2898
|
});
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2899
|
+
const result = await client.getById({
|
|
2900
|
+
params: { id: sessionId }
|
|
2901
|
+
});
|
|
2902
|
+
if (result.status === 200) {
|
|
2903
|
+
return result.body;
|
|
2768
2904
|
}
|
|
2769
|
-
|
|
2905
|
+
const errorBody = result.body;
|
|
2906
|
+
const message = errorBody.error?.message || `Session not found: ${sessionId}`;
|
|
2907
|
+
throw new Error(message);
|
|
2770
2908
|
}
|
|
2771
|
-
|
|
2909
|
+
/**
|
|
2910
|
+
* Get checkpoint by ID
|
|
2911
|
+
* Used by run resume to fetch checkpoint info including secretNames
|
|
2912
|
+
*/
|
|
2913
|
+
async getCheckpoint(checkpointId) {
|
|
2914
|
+
const baseUrl = await this.getBaseUrl();
|
|
2915
|
+
const headers = await this.getHeaders();
|
|
2916
|
+
const client = initClient(checkpointsByIdContract, {
|
|
2917
|
+
baseUrl,
|
|
2918
|
+
baseHeaders: headers,
|
|
2919
|
+
jsonQuery: true
|
|
2920
|
+
});
|
|
2921
|
+
const result = await client.getById({
|
|
2922
|
+
params: { id: checkpointId }
|
|
2923
|
+
});
|
|
2924
|
+
if (result.status === 200) {
|
|
2925
|
+
return result.body;
|
|
2926
|
+
}
|
|
2927
|
+
const errorBody = result.body;
|
|
2928
|
+
const message = errorBody.error?.message || `Checkpoint not found: ${checkpointId}`;
|
|
2929
|
+
throw new Error(message);
|
|
2930
|
+
}
|
|
2931
|
+
/**
|
|
2932
|
+
* Prepare storage for direct S3 upload
|
|
2933
|
+
*/
|
|
2934
|
+
async prepareStorage(body) {
|
|
2935
|
+
const baseUrl = await this.getBaseUrl();
|
|
2936
|
+
const headers = await this.getHeaders();
|
|
2937
|
+
const client = initClient(storagesPrepareContract, {
|
|
2938
|
+
baseUrl,
|
|
2939
|
+
baseHeaders: headers,
|
|
2940
|
+
jsonQuery: true
|
|
2941
|
+
});
|
|
2942
|
+
const result = await client.prepare({ body });
|
|
2943
|
+
if (result.status === 200) {
|
|
2944
|
+
return result.body;
|
|
2945
|
+
}
|
|
2946
|
+
const errorBody = result.body;
|
|
2947
|
+
const message = errorBody.error?.message || "Failed to prepare storage";
|
|
2948
|
+
throw new Error(message);
|
|
2949
|
+
}
|
|
2950
|
+
/**
|
|
2951
|
+
* Commit storage after S3 upload
|
|
2952
|
+
*/
|
|
2953
|
+
async commitStorage(body) {
|
|
2954
|
+
const baseUrl = await this.getBaseUrl();
|
|
2955
|
+
const headers = await this.getHeaders();
|
|
2956
|
+
const client = initClient(storagesCommitContract, {
|
|
2957
|
+
baseUrl,
|
|
2958
|
+
baseHeaders: headers,
|
|
2959
|
+
jsonQuery: true
|
|
2960
|
+
});
|
|
2961
|
+
const result = await client.commit({ body });
|
|
2962
|
+
if (result.status === 200) {
|
|
2963
|
+
return result.body;
|
|
2964
|
+
}
|
|
2965
|
+
const errorBody = result.body;
|
|
2966
|
+
const message = errorBody.error?.message || "Failed to commit storage";
|
|
2967
|
+
throw new Error(message);
|
|
2968
|
+
}
|
|
2969
|
+
/**
|
|
2970
|
+
* Get download URL for storage (volume or artifact)
|
|
2971
|
+
*/
|
|
2972
|
+
async getStorageDownload(query) {
|
|
2973
|
+
const baseUrl = await this.getBaseUrl();
|
|
2974
|
+
const headers = await this.getHeaders();
|
|
2975
|
+
const client = initClient(storagesDownloadContract, {
|
|
2976
|
+
baseUrl,
|
|
2977
|
+
baseHeaders: headers,
|
|
2978
|
+
jsonQuery: true
|
|
2979
|
+
});
|
|
2980
|
+
const result = await client.download({
|
|
2981
|
+
query: {
|
|
2982
|
+
name: query.name,
|
|
2983
|
+
type: query.type,
|
|
2984
|
+
version: query.version
|
|
2985
|
+
}
|
|
2986
|
+
});
|
|
2987
|
+
if (result.status === 200) {
|
|
2988
|
+
return result.body;
|
|
2989
|
+
}
|
|
2990
|
+
const errorBody = result.body;
|
|
2991
|
+
const message = errorBody.error?.message || `Storage "${query.name}" not found`;
|
|
2992
|
+
throw new Error(message);
|
|
2993
|
+
}
|
|
2994
|
+
/**
|
|
2995
|
+
* List storages (volumes or artifacts)
|
|
2996
|
+
*/
|
|
2997
|
+
async listStorages(query) {
|
|
2998
|
+
const baseUrl = await this.getBaseUrl();
|
|
2999
|
+
const headers = await this.getHeaders();
|
|
3000
|
+
const client = initClient(storagesListContract, {
|
|
3001
|
+
baseUrl,
|
|
3002
|
+
baseHeaders: headers,
|
|
3003
|
+
jsonQuery: true
|
|
3004
|
+
});
|
|
3005
|
+
const result = await client.list({ query });
|
|
3006
|
+
if (result.status === 200) {
|
|
3007
|
+
return result.body;
|
|
3008
|
+
}
|
|
3009
|
+
const errorBody = result.body;
|
|
3010
|
+
const message = errorBody.error?.message || `Failed to list ${query.type}s`;
|
|
3011
|
+
throw new Error(message);
|
|
3012
|
+
}
|
|
3013
|
+
/**
|
|
3014
|
+
* Deploy schedule (create or update)
|
|
3015
|
+
*/
|
|
3016
|
+
async deploySchedule(body) {
|
|
3017
|
+
const baseUrl = await this.getBaseUrl();
|
|
3018
|
+
const headers = await this.getHeaders();
|
|
3019
|
+
const client = initClient(schedulesMainContract, {
|
|
3020
|
+
baseUrl,
|
|
3021
|
+
baseHeaders: headers,
|
|
3022
|
+
jsonQuery: true
|
|
3023
|
+
});
|
|
3024
|
+
const result = await client.deploy({ body });
|
|
3025
|
+
if (result.status === 200 || result.status === 201) {
|
|
3026
|
+
return result.body;
|
|
3027
|
+
}
|
|
3028
|
+
const errorBody = result.body;
|
|
3029
|
+
const message = errorBody.error?.message || "Failed to deploy schedule";
|
|
3030
|
+
throw new Error(message);
|
|
3031
|
+
}
|
|
3032
|
+
/**
|
|
3033
|
+
* List all schedules
|
|
3034
|
+
*/
|
|
3035
|
+
async listSchedules() {
|
|
3036
|
+
const baseUrl = await this.getBaseUrl();
|
|
3037
|
+
const headers = await this.getHeaders();
|
|
3038
|
+
const client = initClient(schedulesMainContract, {
|
|
3039
|
+
baseUrl,
|
|
3040
|
+
baseHeaders: headers,
|
|
3041
|
+
jsonQuery: true
|
|
3042
|
+
});
|
|
3043
|
+
const result = await client.list();
|
|
3044
|
+
if (result.status === 200) {
|
|
3045
|
+
return result.body;
|
|
3046
|
+
}
|
|
3047
|
+
const errorBody = result.body;
|
|
3048
|
+
const message = errorBody.error?.message || "Failed to list schedules";
|
|
3049
|
+
throw new Error(message);
|
|
3050
|
+
}
|
|
3051
|
+
/**
|
|
3052
|
+
* Get schedule by name
|
|
3053
|
+
*/
|
|
3054
|
+
async getScheduleByName(params) {
|
|
3055
|
+
const baseUrl = await this.getBaseUrl();
|
|
3056
|
+
const headers = await this.getHeaders();
|
|
3057
|
+
const client = initClient(schedulesByNameContract, {
|
|
3058
|
+
baseUrl,
|
|
3059
|
+
baseHeaders: headers,
|
|
3060
|
+
jsonQuery: true
|
|
3061
|
+
});
|
|
3062
|
+
const result = await client.getByName({
|
|
3063
|
+
params: { name: params.name },
|
|
3064
|
+
query: { composeId: params.composeId }
|
|
3065
|
+
});
|
|
3066
|
+
if (result.status === 200) {
|
|
3067
|
+
return result.body;
|
|
3068
|
+
}
|
|
3069
|
+
const errorBody = result.body;
|
|
3070
|
+
const message = errorBody.error?.message || `Schedule "${params.name}" not found`;
|
|
3071
|
+
throw new Error(message);
|
|
3072
|
+
}
|
|
3073
|
+
/**
|
|
3074
|
+
* Delete schedule by name
|
|
3075
|
+
*/
|
|
3076
|
+
async deleteSchedule(params) {
|
|
3077
|
+
const baseUrl = await this.getBaseUrl();
|
|
3078
|
+
const headers = await this.getHeaders();
|
|
3079
|
+
const client = initClient(schedulesByNameContract, {
|
|
3080
|
+
baseUrl,
|
|
3081
|
+
baseHeaders: headers,
|
|
3082
|
+
jsonQuery: true
|
|
3083
|
+
});
|
|
3084
|
+
const result = await client.delete({
|
|
3085
|
+
params: { name: params.name },
|
|
3086
|
+
query: { composeId: params.composeId }
|
|
3087
|
+
});
|
|
3088
|
+
if (result.status === 204) {
|
|
3089
|
+
return;
|
|
3090
|
+
}
|
|
3091
|
+
const errorBody = result.body;
|
|
3092
|
+
const message = errorBody.error?.message || `Schedule "${params.name}" not found on remote`;
|
|
3093
|
+
throw new Error(message);
|
|
3094
|
+
}
|
|
3095
|
+
/**
|
|
3096
|
+
* Enable schedule
|
|
3097
|
+
*/
|
|
3098
|
+
async enableSchedule(params) {
|
|
3099
|
+
const baseUrl = await this.getBaseUrl();
|
|
3100
|
+
const headers = await this.getHeaders();
|
|
3101
|
+
const client = initClient(schedulesEnableContract, {
|
|
3102
|
+
baseUrl,
|
|
3103
|
+
baseHeaders: headers,
|
|
3104
|
+
jsonQuery: true
|
|
3105
|
+
});
|
|
3106
|
+
const result = await client.enable({
|
|
3107
|
+
params: { name: params.name },
|
|
3108
|
+
body: { composeId: params.composeId }
|
|
3109
|
+
});
|
|
3110
|
+
if (result.status === 200) {
|
|
3111
|
+
return result.body;
|
|
3112
|
+
}
|
|
3113
|
+
const errorBody = result.body;
|
|
3114
|
+
const message = errorBody.error?.message || `Failed to enable schedule "${params.name}"`;
|
|
3115
|
+
throw new Error(message);
|
|
3116
|
+
}
|
|
3117
|
+
/**
|
|
3118
|
+
* Disable schedule
|
|
3119
|
+
*/
|
|
3120
|
+
async disableSchedule(params) {
|
|
2772
3121
|
const baseUrl = await this.getBaseUrl();
|
|
2773
3122
|
const headers = await this.getHeaders();
|
|
2774
|
-
const
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
if (options?.limit !== void 0) {
|
|
2779
|
-
params.set("limit", String(options.limit));
|
|
2780
|
-
}
|
|
2781
|
-
if (options?.order !== void 0) {
|
|
2782
|
-
params.set("order", options.order);
|
|
2783
|
-
}
|
|
2784
|
-
const queryString = params.toString();
|
|
2785
|
-
const url = `${baseUrl}/api/agent/runs/${runId}/telemetry/agent${queryString ? `?${queryString}` : ""}`;
|
|
2786
|
-
const response = await fetch(url, {
|
|
2787
|
-
method: "GET",
|
|
2788
|
-
headers
|
|
3123
|
+
const client = initClient(schedulesEnableContract, {
|
|
3124
|
+
baseUrl,
|
|
3125
|
+
baseHeaders: headers,
|
|
3126
|
+
jsonQuery: true
|
|
2789
3127
|
});
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
3128
|
+
const result = await client.disable({
|
|
3129
|
+
params: { name: params.name },
|
|
3130
|
+
body: { composeId: params.composeId }
|
|
3131
|
+
});
|
|
3132
|
+
if (result.status === 200) {
|
|
3133
|
+
return result.body;
|
|
2793
3134
|
}
|
|
2794
|
-
|
|
3135
|
+
const errorBody = result.body;
|
|
3136
|
+
const message = errorBody.error?.message || `Failed to disable schedule "${params.name}"`;
|
|
3137
|
+
throw new Error(message);
|
|
2795
3138
|
}
|
|
2796
|
-
|
|
3139
|
+
/**
|
|
3140
|
+
* List recent runs for a schedule
|
|
3141
|
+
*/
|
|
3142
|
+
async listScheduleRuns(params) {
|
|
2797
3143
|
const baseUrl = await this.getBaseUrl();
|
|
2798
3144
|
const headers = await this.getHeaders();
|
|
2799
|
-
const
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
if (options?.limit !== void 0) {
|
|
2804
|
-
params.set("limit", String(options.limit));
|
|
2805
|
-
}
|
|
2806
|
-
if (options?.order !== void 0) {
|
|
2807
|
-
params.set("order", options.order);
|
|
2808
|
-
}
|
|
2809
|
-
const queryString = params.toString();
|
|
2810
|
-
const url = `${baseUrl}/api/agent/runs/${runId}/telemetry/network${queryString ? `?${queryString}` : ""}`;
|
|
2811
|
-
const response = await fetch(url, {
|
|
2812
|
-
method: "GET",
|
|
2813
|
-
headers
|
|
3145
|
+
const client = initClient(scheduleRunsContract, {
|
|
3146
|
+
baseUrl,
|
|
3147
|
+
baseHeaders: headers,
|
|
3148
|
+
jsonQuery: true
|
|
2814
3149
|
});
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
3150
|
+
const result = await client.listRuns({
|
|
3151
|
+
params: { name: params.name },
|
|
3152
|
+
query: {
|
|
3153
|
+
composeId: params.composeId,
|
|
3154
|
+
limit: params.limit ?? 5
|
|
3155
|
+
}
|
|
3156
|
+
});
|
|
3157
|
+
if (result.status === 200) {
|
|
3158
|
+
return result.body;
|
|
2818
3159
|
}
|
|
2819
|
-
|
|
3160
|
+
const errorBody = result.body;
|
|
3161
|
+
const message = errorBody.error?.message || `Failed to list runs for schedule "${params.name}"`;
|
|
3162
|
+
throw new Error(message);
|
|
2820
3163
|
}
|
|
2821
3164
|
/**
|
|
2822
|
-
*
|
|
3165
|
+
* List public agents
|
|
2823
3166
|
*/
|
|
2824
|
-
async
|
|
3167
|
+
async listPublicAgents(query) {
|
|
2825
3168
|
const baseUrl = await this.getBaseUrl();
|
|
2826
3169
|
const headers = await this.getHeaders();
|
|
2827
|
-
const
|
|
2828
|
-
|
|
2829
|
-
headers
|
|
3170
|
+
const client = initClient(publicAgentsListContract, {
|
|
3171
|
+
baseUrl,
|
|
3172
|
+
baseHeaders: headers,
|
|
3173
|
+
jsonQuery: true
|
|
2830
3174
|
});
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
3175
|
+
const result = await client.list({ query: query ?? {} });
|
|
3176
|
+
if (result.status === 200) {
|
|
3177
|
+
return result.body;
|
|
2834
3178
|
}
|
|
2835
|
-
|
|
3179
|
+
const errorBody = result.body;
|
|
3180
|
+
const message = errorBody.error?.message || "Failed to list agents";
|
|
3181
|
+
throw new Error(message);
|
|
2836
3182
|
}
|
|
2837
3183
|
/**
|
|
2838
|
-
*
|
|
3184
|
+
* List public artifacts
|
|
2839
3185
|
*/
|
|
2840
|
-
async
|
|
3186
|
+
async listPublicArtifacts(query) {
|
|
2841
3187
|
const baseUrl = await this.getBaseUrl();
|
|
2842
3188
|
const headers = await this.getHeaders();
|
|
2843
|
-
const
|
|
2844
|
-
|
|
2845
|
-
headers,
|
|
2846
|
-
|
|
3189
|
+
const client = initClient(publicArtifactsListContract, {
|
|
3190
|
+
baseUrl,
|
|
3191
|
+
baseHeaders: headers,
|
|
3192
|
+
jsonQuery: true
|
|
2847
3193
|
});
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
3194
|
+
const result = await client.list({ query: query ?? {} });
|
|
3195
|
+
if (result.status === 200) {
|
|
3196
|
+
return result.body;
|
|
2851
3197
|
}
|
|
2852
|
-
|
|
3198
|
+
const errorBody = result.body;
|
|
3199
|
+
const message = errorBody.error?.message || "Failed to list artifacts";
|
|
3200
|
+
throw new Error(message);
|
|
2853
3201
|
}
|
|
2854
3202
|
/**
|
|
2855
|
-
*
|
|
3203
|
+
* Get public artifact by ID
|
|
2856
3204
|
*/
|
|
2857
|
-
async
|
|
3205
|
+
async getPublicArtifact(id) {
|
|
2858
3206
|
const baseUrl = await this.getBaseUrl();
|
|
2859
3207
|
const headers = await this.getHeaders();
|
|
2860
|
-
const
|
|
2861
|
-
|
|
2862
|
-
headers,
|
|
2863
|
-
|
|
3208
|
+
const client = initClient(publicArtifactByIdContract, {
|
|
3209
|
+
baseUrl,
|
|
3210
|
+
baseHeaders: headers,
|
|
3211
|
+
jsonQuery: true
|
|
2864
3212
|
});
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
3213
|
+
const result = await client.get({ params: { id } });
|
|
3214
|
+
if (result.status === 200) {
|
|
3215
|
+
return result.body;
|
|
2868
3216
|
}
|
|
2869
|
-
|
|
3217
|
+
const errorBody = result.body;
|
|
3218
|
+
const message = errorBody.error?.message || `Artifact "${id}" not found`;
|
|
3219
|
+
throw new Error(message);
|
|
2870
3220
|
}
|
|
2871
3221
|
/**
|
|
2872
|
-
*
|
|
2873
|
-
* Used by run continue to fetch session info including secretNames
|
|
3222
|
+
* List public volumes
|
|
2874
3223
|
*/
|
|
2875
|
-
async
|
|
3224
|
+
async listPublicVolumes(query) {
|
|
2876
3225
|
const baseUrl = await this.getBaseUrl();
|
|
2877
3226
|
const headers = await this.getHeaders();
|
|
2878
|
-
const
|
|
2879
|
-
|
|
2880
|
-
headers
|
|
3227
|
+
const client = initClient(publicVolumesListContract, {
|
|
3228
|
+
baseUrl,
|
|
3229
|
+
baseHeaders: headers,
|
|
3230
|
+
jsonQuery: true
|
|
2881
3231
|
});
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
error.error?.message || `Session not found: ${sessionId}`
|
|
2886
|
-
);
|
|
3232
|
+
const result = await client.list({ query: query ?? {} });
|
|
3233
|
+
if (result.status === 200) {
|
|
3234
|
+
return result.body;
|
|
2887
3235
|
}
|
|
2888
|
-
|
|
3236
|
+
const errorBody = result.body;
|
|
3237
|
+
const message = errorBody.error?.message || "Failed to list volumes";
|
|
3238
|
+
throw new Error(message);
|
|
2889
3239
|
}
|
|
2890
3240
|
/**
|
|
2891
|
-
* Get
|
|
2892
|
-
* Used by run resume to fetch checkpoint info including secretNames
|
|
3241
|
+
* Get public volume by ID
|
|
2893
3242
|
*/
|
|
2894
|
-
async
|
|
3243
|
+
async getPublicVolume(id) {
|
|
2895
3244
|
const baseUrl = await this.getBaseUrl();
|
|
2896
3245
|
const headers = await this.getHeaders();
|
|
2897
|
-
const
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
)
|
|
2904
|
-
|
|
2905
|
-
const error = await response.json();
|
|
2906
|
-
throw new Error(
|
|
2907
|
-
error.error?.message || `Checkpoint not found: ${checkpointId}`
|
|
2908
|
-
);
|
|
3246
|
+
const client = initClient(publicVolumeByIdContract, {
|
|
3247
|
+
baseUrl,
|
|
3248
|
+
baseHeaders: headers,
|
|
3249
|
+
jsonQuery: true
|
|
3250
|
+
});
|
|
3251
|
+
const result = await client.get({ params: { id } });
|
|
3252
|
+
if (result.status === 200) {
|
|
3253
|
+
return result.body;
|
|
2909
3254
|
}
|
|
2910
|
-
|
|
3255
|
+
const errorBody = result.body;
|
|
3256
|
+
const message = errorBody.error?.message || `Volume "${id}" not found`;
|
|
3257
|
+
throw new Error(message);
|
|
2911
3258
|
}
|
|
2912
3259
|
/**
|
|
2913
3260
|
* Generic GET request
|
|
@@ -3549,34 +3896,20 @@ async function directUpload(storageName, storageType, cwd, options) {
|
|
|
3549
3896
|
onProgress?.("Computing file hashes...");
|
|
3550
3897
|
const fileEntries = await collectFileMetadata(cwd, files, onProgress);
|
|
3551
3898
|
onProgress?.("Preparing upload...");
|
|
3552
|
-
const
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
force
|
|
3558
|
-
})
|
|
3899
|
+
const prepareResult = await apiClient.prepareStorage({
|
|
3900
|
+
storageName,
|
|
3901
|
+
storageType,
|
|
3902
|
+
files: fileEntries,
|
|
3903
|
+
force
|
|
3559
3904
|
});
|
|
3560
|
-
if (!prepareResponse.ok) {
|
|
3561
|
-
const error = await prepareResponse.json();
|
|
3562
|
-
throw new Error(error.error?.message || "Prepare failed");
|
|
3563
|
-
}
|
|
3564
|
-
const prepareResult = await prepareResponse.json();
|
|
3565
3905
|
if (prepareResult.existing) {
|
|
3566
3906
|
onProgress?.("Version exists, updating HEAD...");
|
|
3567
|
-
const
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
files: fileEntries
|
|
3573
|
-
})
|
|
3907
|
+
const commitResult2 = await apiClient.commitStorage({
|
|
3908
|
+
storageName,
|
|
3909
|
+
storageType,
|
|
3910
|
+
versionId: prepareResult.versionId,
|
|
3911
|
+
files: fileEntries
|
|
3574
3912
|
});
|
|
3575
|
-
if (!commitResponse2.ok) {
|
|
3576
|
-
const error = await commitResponse2.json();
|
|
3577
|
-
throw new Error(error.error?.message || "Commit failed");
|
|
3578
|
-
}
|
|
3579
|
-
const commitResult2 = await commitResponse2.json();
|
|
3580
3913
|
return {
|
|
3581
3914
|
versionId: commitResult2.versionId,
|
|
3582
3915
|
size: commitResult2.size,
|
|
@@ -3609,19 +3942,12 @@ async function directUpload(storageName, storageType, cwd, options) {
|
|
|
3609
3942
|
"application/json"
|
|
3610
3943
|
);
|
|
3611
3944
|
onProgress?.("Committing...");
|
|
3612
|
-
const
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
files: fileEntries
|
|
3618
|
-
})
|
|
3945
|
+
const commitResult = await apiClient.commitStorage({
|
|
3946
|
+
storageName,
|
|
3947
|
+
storageType,
|
|
3948
|
+
versionId: prepareResult.versionId,
|
|
3949
|
+
files: fileEntries
|
|
3619
3950
|
});
|
|
3620
|
-
if (!commitResponse.ok) {
|
|
3621
|
-
const error = await commitResponse.json();
|
|
3622
|
-
throw new Error(error.error?.message || "Commit failed");
|
|
3623
|
-
}
|
|
3624
|
-
const commitResult = await commitResponse.json();
|
|
3625
3951
|
return {
|
|
3626
3952
|
versionId: commitResult.versionId,
|
|
3627
3953
|
size: commitResult.size,
|
|
@@ -5415,39 +5741,21 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5415
5741
|
console.log(`Pulling volume: ${config.name}`);
|
|
5416
5742
|
}
|
|
5417
5743
|
console.log(chalk9.dim("Getting download URL..."));
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
}
|
|
5423
|
-
|
|
5424
|
-
if (!response.ok) {
|
|
5425
|
-
if (response.status === 404) {
|
|
5426
|
-
console.error(chalk9.red(`\u2717 Volume "${config.name}" not found`));
|
|
5427
|
-
console.error(
|
|
5428
|
-
chalk9.dim(
|
|
5429
|
-
" Make sure the volume name is correct in .vm0/storage.yaml"
|
|
5430
|
-
)
|
|
5431
|
-
);
|
|
5432
|
-
console.error(
|
|
5433
|
-
chalk9.dim(" Or push the volume first with: vm0 volume push")
|
|
5434
|
-
);
|
|
5435
|
-
} else {
|
|
5436
|
-
const error = await response.json();
|
|
5437
|
-
throw new Error(error.error?.message || "Download failed");
|
|
5438
|
-
}
|
|
5439
|
-
process.exit(1);
|
|
5440
|
-
}
|
|
5441
|
-
const downloadInfo = await response.json();
|
|
5442
|
-
if (downloadInfo.empty) {
|
|
5744
|
+
const downloadInfo = await apiClient.getStorageDownload({
|
|
5745
|
+
name: config.name,
|
|
5746
|
+
type: "volume",
|
|
5747
|
+
version: versionId
|
|
5748
|
+
});
|
|
5749
|
+
if ("empty" in downloadInfo) {
|
|
5443
5750
|
await handleEmptyStorageResponse(cwd);
|
|
5444
5751
|
return;
|
|
5445
5752
|
}
|
|
5446
|
-
|
|
5753
|
+
const downloadUrl = downloadInfo.url;
|
|
5754
|
+
if (!downloadUrl) {
|
|
5447
5755
|
throw new Error("No download URL returned");
|
|
5448
5756
|
}
|
|
5449
5757
|
console.log(chalk9.dim("Downloading from S3..."));
|
|
5450
|
-
const s3Response = await fetch(
|
|
5758
|
+
const s3Response = await fetch(downloadUrl);
|
|
5451
5759
|
if (!s3Response.ok) {
|
|
5452
5760
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
5453
5761
|
}
|
|
@@ -5519,21 +5827,12 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5519
5827
|
process.exit(1);
|
|
5520
5828
|
}
|
|
5521
5829
|
console.log(`Checking volume: ${config.name}`);
|
|
5522
|
-
const
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
console.error(chalk10.red("\u2717 Not found on remote"));
|
|
5527
|
-
console.error(chalk10.dim(" Run: vm0 volume push"));
|
|
5528
|
-
} else {
|
|
5529
|
-
const error = await response.json();
|
|
5530
|
-
throw new Error(error.error?.message || "Status check failed");
|
|
5531
|
-
}
|
|
5532
|
-
process.exit(1);
|
|
5533
|
-
}
|
|
5534
|
-
const info = await response.json();
|
|
5830
|
+
const info = await apiClient.getStorageDownload({
|
|
5831
|
+
name: config.name,
|
|
5832
|
+
type: "volume"
|
|
5833
|
+
});
|
|
5535
5834
|
const shortVersion = info.versionId.slice(0, 8);
|
|
5536
|
-
if (info
|
|
5835
|
+
if ("empty" in info) {
|
|
5537
5836
|
console.log(chalk10.green("\u2713 Found (empty)"));
|
|
5538
5837
|
console.log(chalk10.dim(` Version: ${shortVersion}`));
|
|
5539
5838
|
} else {
|
|
@@ -5543,12 +5842,17 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5543
5842
|
console.log(chalk10.dim(` Size: ${formatBytes4(info.size)}`));
|
|
5544
5843
|
}
|
|
5545
5844
|
} catch (error) {
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5845
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
5846
|
+
console.error(chalk10.red("\u2717 Not found on remote"));
|
|
5847
|
+
console.error(chalk10.dim(" Run: vm0 volume push"));
|
|
5848
|
+
} else {
|
|
5849
|
+
console.error(chalk10.red("\u2717 Status check failed"));
|
|
5850
|
+
if (error instanceof Error) {
|
|
5851
|
+
if (error.message.includes("Not authenticated")) {
|
|
5852
|
+
console.error(chalk10.dim(" Run: vm0 auth login"));
|
|
5853
|
+
} else {
|
|
5854
|
+
console.error(chalk10.dim(` ${error.message}`));
|
|
5855
|
+
}
|
|
5552
5856
|
}
|
|
5553
5857
|
}
|
|
5554
5858
|
process.exit(1);
|
|
@@ -5560,13 +5864,7 @@ import { Command as Command7 } from "commander";
|
|
|
5560
5864
|
import chalk11 from "chalk";
|
|
5561
5865
|
var listCommand = new Command7().name("list").alias("ls").description("List all remote volumes").action(async () => {
|
|
5562
5866
|
try {
|
|
5563
|
-
const
|
|
5564
|
-
const response = await apiClient.get(url);
|
|
5565
|
-
if (!response.ok) {
|
|
5566
|
-
const error = await response.json();
|
|
5567
|
-
throw new Error(error.error?.message || "List failed");
|
|
5568
|
-
}
|
|
5569
|
-
const items = await response.json();
|
|
5867
|
+
const items = await apiClient.listStorages({ type: "volume" });
|
|
5570
5868
|
if (items.length === 0) {
|
|
5571
5869
|
console.log(chalk11.dim("No volumes found"));
|
|
5572
5870
|
console.log(
|
|
@@ -5628,25 +5926,14 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5628
5926
|
throw new Error(`Directory "${destination}" already exists`);
|
|
5629
5927
|
}
|
|
5630
5928
|
console.log(chalk12.dim(`Checking remote ${typeLabel}...`));
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
}
|
|
5636
|
-
const response = await apiClient.get(url);
|
|
5637
|
-
if (!response.ok) {
|
|
5638
|
-
if (response.status === 404) {
|
|
5639
|
-
throw new Error(
|
|
5640
|
-
`${typeLabel.charAt(0).toUpperCase() + typeLabel.slice(1)} "${name}" not found`
|
|
5641
|
-
);
|
|
5642
|
-
}
|
|
5643
|
-
const error = await response.json();
|
|
5644
|
-
throw new Error(error.error?.message || "Clone failed");
|
|
5645
|
-
}
|
|
5646
|
-
const downloadInfo = await response.json();
|
|
5929
|
+
const downloadInfo = await apiClient.getStorageDownload({
|
|
5930
|
+
name,
|
|
5931
|
+
type,
|
|
5932
|
+
version: options.version
|
|
5933
|
+
});
|
|
5647
5934
|
console.log(chalk12.dim(`Creating directory: ${destination}/`));
|
|
5648
5935
|
await fs7.promises.mkdir(destination, { recursive: true });
|
|
5649
|
-
if (downloadInfo
|
|
5936
|
+
if ("empty" in downloadInfo) {
|
|
5650
5937
|
await writeStorageConfig(name, destination, type);
|
|
5651
5938
|
console.log(chalk12.green(`\u2713 Cloned empty ${typeLabel}: ${name}`));
|
|
5652
5939
|
console.log(chalk12.dim(`\u2713 Initialized .vm0/storage.yaml`));
|
|
@@ -5657,11 +5944,12 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5657
5944
|
versionId: downloadInfo.versionId
|
|
5658
5945
|
};
|
|
5659
5946
|
}
|
|
5660
|
-
|
|
5947
|
+
const downloadUrl = downloadInfo.url;
|
|
5948
|
+
if (!downloadUrl) {
|
|
5661
5949
|
throw new Error("No download URL returned");
|
|
5662
5950
|
}
|
|
5663
5951
|
console.log(chalk12.dim("Downloading from S3..."));
|
|
5664
|
-
const s3Response = await fetch(
|
|
5952
|
+
const s3Response = await fetch(downloadUrl);
|
|
5665
5953
|
if (!s3Response.ok) {
|
|
5666
5954
|
await fs7.promises.rm(destination, { recursive: true, force: true });
|
|
5667
5955
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
@@ -5910,39 +6198,21 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
5910
6198
|
console.log(`Pulling artifact: ${config.name}`);
|
|
5911
6199
|
}
|
|
5912
6200
|
console.log(chalk16.dim("Getting download URL..."));
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
}
|
|
5918
|
-
|
|
5919
|
-
if (!response.ok) {
|
|
5920
|
-
if (response.status === 404) {
|
|
5921
|
-
console.error(chalk16.red(`\u2717 Artifact "${config.name}" not found`));
|
|
5922
|
-
console.error(
|
|
5923
|
-
chalk16.dim(
|
|
5924
|
-
" Make sure the artifact name is correct in .vm0/storage.yaml"
|
|
5925
|
-
)
|
|
5926
|
-
);
|
|
5927
|
-
console.error(
|
|
5928
|
-
chalk16.dim(" Or push the artifact first with: vm0 artifact push")
|
|
5929
|
-
);
|
|
5930
|
-
} else {
|
|
5931
|
-
const error = await response.json();
|
|
5932
|
-
throw new Error(error.error?.message || "Download failed");
|
|
5933
|
-
}
|
|
5934
|
-
process.exit(1);
|
|
5935
|
-
}
|
|
5936
|
-
const downloadInfo = await response.json();
|
|
5937
|
-
if (downloadInfo.empty) {
|
|
6201
|
+
const downloadInfo = await apiClient.getStorageDownload({
|
|
6202
|
+
name: config.name,
|
|
6203
|
+
type: "artifact",
|
|
6204
|
+
version: versionId
|
|
6205
|
+
});
|
|
6206
|
+
if ("empty" in downloadInfo) {
|
|
5938
6207
|
await handleEmptyStorageResponse(cwd);
|
|
5939
6208
|
return;
|
|
5940
6209
|
}
|
|
5941
|
-
|
|
6210
|
+
const downloadUrl = downloadInfo.url;
|
|
6211
|
+
if (!downloadUrl) {
|
|
5942
6212
|
throw new Error("No download URL returned");
|
|
5943
6213
|
}
|
|
5944
6214
|
console.log(chalk16.dim("Downloading from S3..."));
|
|
5945
|
-
const s3Response = await fetch(
|
|
6215
|
+
const s3Response = await fetch(downloadUrl);
|
|
5946
6216
|
if (!s3Response.ok) {
|
|
5947
6217
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
5948
6218
|
}
|
|
@@ -6010,21 +6280,12 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6010
6280
|
process.exit(1);
|
|
6011
6281
|
}
|
|
6012
6282
|
console.log(`Checking artifact: ${config.name}`);
|
|
6013
|
-
const
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
console.error(chalk17.red("\u2717 Not found on remote"));
|
|
6018
|
-
console.error(chalk17.dim(" Run: vm0 artifact push"));
|
|
6019
|
-
} else {
|
|
6020
|
-
const error = await response.json();
|
|
6021
|
-
throw new Error(error.error?.message || "Status check failed");
|
|
6022
|
-
}
|
|
6023
|
-
process.exit(1);
|
|
6024
|
-
}
|
|
6025
|
-
const info = await response.json();
|
|
6283
|
+
const info = await apiClient.getStorageDownload({
|
|
6284
|
+
name: config.name,
|
|
6285
|
+
type: "artifact"
|
|
6286
|
+
});
|
|
6026
6287
|
const shortVersion = info.versionId.slice(0, 8);
|
|
6027
|
-
if (info
|
|
6288
|
+
if ("empty" in info) {
|
|
6028
6289
|
console.log(chalk17.green("\u2713 Found (empty)"));
|
|
6029
6290
|
console.log(chalk17.dim(` Version: ${shortVersion}`));
|
|
6030
6291
|
} else {
|
|
@@ -6034,9 +6295,14 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6034
6295
|
console.log(chalk17.dim(` Size: ${formatBytes7(info.size)}`));
|
|
6035
6296
|
}
|
|
6036
6297
|
} catch (error) {
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
console.error(chalk17.dim(
|
|
6298
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
6299
|
+
console.error(chalk17.red("\u2717 Not found on remote"));
|
|
6300
|
+
console.error(chalk17.dim(" Run: vm0 artifact push"));
|
|
6301
|
+
} else {
|
|
6302
|
+
console.error(chalk17.red("\u2717 Status check failed"));
|
|
6303
|
+
if (error instanceof Error) {
|
|
6304
|
+
console.error(chalk17.dim(` ${error.message}`));
|
|
6305
|
+
}
|
|
6040
6306
|
}
|
|
6041
6307
|
process.exit(1);
|
|
6042
6308
|
}
|
|
@@ -6047,13 +6313,7 @@ import { Command as Command14 } from "commander";
|
|
|
6047
6313
|
import chalk18 from "chalk";
|
|
6048
6314
|
var listCommand2 = new Command14().name("list").alias("ls").description("List all remote artifacts").action(async () => {
|
|
6049
6315
|
try {
|
|
6050
|
-
const
|
|
6051
|
-
const response = await apiClient.get(url);
|
|
6052
|
-
if (!response.ok) {
|
|
6053
|
-
const error = await response.json();
|
|
6054
|
-
throw new Error(error.error?.message || "List failed");
|
|
6055
|
-
}
|
|
6056
|
-
const items = await response.json();
|
|
6316
|
+
const items = await apiClient.listStorages({ type: "artifact" });
|
|
6057
6317
|
if (items.length === 0) {
|
|
6058
6318
|
console.log(chalk18.dim("No artifacts found"));
|
|
6059
6319
|
console.log(
|
|
@@ -6472,7 +6732,7 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
6472
6732
|
}
|
|
6473
6733
|
var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
|
|
6474
6734
|
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(async (prompt, options) => {
|
|
6475
|
-
const shouldExit = await checkAndUpgrade("5.
|
|
6735
|
+
const shouldExit = await checkAndUpgrade("5.7.2", prompt);
|
|
6476
6736
|
if (shouldExit) {
|
|
6477
6737
|
process.exit(0);
|
|
6478
6738
|
}
|
|
@@ -8048,6 +8308,7 @@ import { stringify as stringifyYaml2 } from "yaml";
|
|
|
8048
8308
|
import { existsSync as existsSync11, readFileSync as readFileSync2 } from "fs";
|
|
8049
8309
|
import { parse as parseYaml6 } from "yaml";
|
|
8050
8310
|
var CONFIG_FILE4 = "vm0.yaml";
|
|
8311
|
+
var SCHEDULE_FILE = "schedule.yaml";
|
|
8051
8312
|
function loadAgentName() {
|
|
8052
8313
|
if (!existsSync11(CONFIG_FILE4)) {
|
|
8053
8314
|
return { agentName: null };
|
|
@@ -8064,6 +8325,28 @@ function loadAgentName() {
|
|
|
8064
8325
|
};
|
|
8065
8326
|
}
|
|
8066
8327
|
}
|
|
8328
|
+
function loadScheduleName() {
|
|
8329
|
+
if (!existsSync11(SCHEDULE_FILE)) {
|
|
8330
|
+
return { scheduleName: null };
|
|
8331
|
+
}
|
|
8332
|
+
try {
|
|
8333
|
+
const content = readFileSync2(SCHEDULE_FILE, "utf8");
|
|
8334
|
+
const parsed = parseYaml6(content);
|
|
8335
|
+
if (!parsed?.schedules) {
|
|
8336
|
+
return {
|
|
8337
|
+
scheduleName: null,
|
|
8338
|
+
error: "No schedules defined in schedule.yaml"
|
|
8339
|
+
};
|
|
8340
|
+
}
|
|
8341
|
+
const scheduleNames = Object.keys(parsed.schedules);
|
|
8342
|
+
return { scheduleName: scheduleNames[0] || null };
|
|
8343
|
+
} catch (err) {
|
|
8344
|
+
return {
|
|
8345
|
+
scheduleName: null,
|
|
8346
|
+
error: err instanceof Error ? err.message : "Failed to parse schedule.yaml"
|
|
8347
|
+
};
|
|
8348
|
+
}
|
|
8349
|
+
}
|
|
8067
8350
|
function formatRelativeTime2(dateStr) {
|
|
8068
8351
|
if (!dateStr) return "-";
|
|
8069
8352
|
const date = new Date(dateStr);
|
|
@@ -8216,7 +8499,7 @@ function toISODateTime(dateTimeStr) {
|
|
|
8216
8499
|
}
|
|
8217
8500
|
|
|
8218
8501
|
// src/commands/schedule/init.ts
|
|
8219
|
-
var
|
|
8502
|
+
var SCHEDULE_FILE2 = "schedule.yaml";
|
|
8220
8503
|
var FREQUENCY_CHOICES = [
|
|
8221
8504
|
{ title: "Daily", value: "daily", description: "Run every day" },
|
|
8222
8505
|
{
|
|
@@ -8279,7 +8562,7 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8279
8562
|
);
|
|
8280
8563
|
process.exit(1);
|
|
8281
8564
|
}
|
|
8282
|
-
if (existsSync12(
|
|
8565
|
+
if (existsSync12(SCHEDULE_FILE2) && !options.force) {
|
|
8283
8566
|
if (!isInteractive()) {
|
|
8284
8567
|
console.error(chalk29.red("\u2717 schedule.yaml already exists"));
|
|
8285
8568
|
console.error(chalk29.dim(" Use --force to overwrite"));
|
|
@@ -8514,8 +8797,8 @@ var initCommand4 = new Command27().name("init").description("Create a schedule.y
|
|
|
8514
8797
|
if (secrets && Object.keys(secrets).length > 0) {
|
|
8515
8798
|
scheduleYaml.schedules[scheduleName].run.secrets = secrets;
|
|
8516
8799
|
}
|
|
8517
|
-
writeFileSync(
|
|
8518
|
-
console.log(chalk29.green(`\u2713 Created ${
|
|
8800
|
+
writeFileSync(SCHEDULE_FILE2, stringifyYaml2(scheduleYaml));
|
|
8801
|
+
console.log(chalk29.green(`\u2713 Created ${SCHEDULE_FILE2}`));
|
|
8519
8802
|
console.log(chalk29.dim(" Deploy with: vm0 schedule deploy"));
|
|
8520
8803
|
} catch (error) {
|
|
8521
8804
|
console.error(chalk29.red("\u2717 Failed to create schedule.yaml"));
|
|
@@ -8637,14 +8920,7 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8637
8920
|
artifactVersion: schedule.run.artifactVersion,
|
|
8638
8921
|
volumeVersions: schedule.run.volumeVersions
|
|
8639
8922
|
};
|
|
8640
|
-
const
|
|
8641
|
-
body: JSON.stringify(body)
|
|
8642
|
-
});
|
|
8643
|
-
if (!response.ok) {
|
|
8644
|
-
const error = await response.json();
|
|
8645
|
-
throw new Error(error.error?.message || "Deploy failed");
|
|
8646
|
-
}
|
|
8647
|
-
const deployResult = await response.json();
|
|
8923
|
+
const deployResult = await apiClient.deploySchedule(body);
|
|
8648
8924
|
if (deployResult.created) {
|
|
8649
8925
|
console.log(
|
|
8650
8926
|
chalk30.green(`\u2713 Created schedule ${chalk30.cyan(scheduleName)}`)
|
|
@@ -8691,12 +8967,7 @@ import { Command as Command29 } from "commander";
|
|
|
8691
8967
|
import chalk31 from "chalk";
|
|
8692
8968
|
var listCommand4 = new Command29().name("list").alias("ls").description("List all schedules").action(async () => {
|
|
8693
8969
|
try {
|
|
8694
|
-
const
|
|
8695
|
-
if (!response.ok) {
|
|
8696
|
-
const error = await response.json();
|
|
8697
|
-
throw new Error(error.error?.message || "List failed");
|
|
8698
|
-
}
|
|
8699
|
-
const result = await response.json();
|
|
8970
|
+
const result = await apiClient.listSchedules();
|
|
8700
8971
|
if (result.schedules.length === 0) {
|
|
8701
8972
|
console.log(chalk31.dim("No schedules found"));
|
|
8702
8973
|
console.log(
|
|
@@ -8785,12 +9056,33 @@ function formatRunStatus(status) {
|
|
|
8785
9056
|
return status;
|
|
8786
9057
|
}
|
|
8787
9058
|
}
|
|
8788
|
-
var statusCommand4 = new Command30().name("status").description("Show detailed status of a schedule").argument(
|
|
9059
|
+
var statusCommand4 = new Command30().name("status").description("Show detailed status of a schedule").argument(
|
|
9060
|
+
"[name]",
|
|
9061
|
+
"Schedule name (auto-detected from schedule.yaml if omitted)"
|
|
9062
|
+
).option(
|
|
8789
9063
|
"-l, --limit <number>",
|
|
8790
9064
|
"Number of recent runs to show (0 to hide)",
|
|
8791
9065
|
"5"
|
|
8792
|
-
).action(async (
|
|
9066
|
+
).action(async (nameArg, options) => {
|
|
8793
9067
|
try {
|
|
9068
|
+
let name = nameArg;
|
|
9069
|
+
if (!name) {
|
|
9070
|
+
const scheduleResult = loadScheduleName();
|
|
9071
|
+
if (scheduleResult.error) {
|
|
9072
|
+
console.error(chalk32.red(`\u2717 ${scheduleResult.error}`));
|
|
9073
|
+
process.exit(1);
|
|
9074
|
+
}
|
|
9075
|
+
if (!scheduleResult.scheduleName) {
|
|
9076
|
+
console.error(chalk32.red("\u2717 Schedule name required"));
|
|
9077
|
+
console.error(
|
|
9078
|
+
chalk32.dim(
|
|
9079
|
+
" Provide name or run from directory with schedule.yaml"
|
|
9080
|
+
)
|
|
9081
|
+
);
|
|
9082
|
+
process.exit(1);
|
|
9083
|
+
}
|
|
9084
|
+
name = scheduleResult.scheduleName;
|
|
9085
|
+
}
|
|
8794
9086
|
const result = loadAgentName();
|
|
8795
9087
|
if (result.error) {
|
|
8796
9088
|
console.error(chalk32.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
@@ -8811,14 +9103,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8811
9103
|
console.error(chalk32.dim(" Make sure the agent is pushed first"));
|
|
8812
9104
|
process.exit(1);
|
|
8813
9105
|
}
|
|
8814
|
-
const
|
|
8815
|
-
`/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
|
|
8816
|
-
);
|
|
8817
|
-
if (!response.ok) {
|
|
8818
|
-
const error = await response.json();
|
|
8819
|
-
throw new Error(error.error?.message || "Failed to get schedule");
|
|
8820
|
-
}
|
|
8821
|
-
const schedule = await response.json();
|
|
9106
|
+
const schedule = await apiClient.getScheduleByName({ name, composeId });
|
|
8822
9107
|
console.log();
|
|
8823
9108
|
console.log(`Schedule: ${chalk32.cyan(schedule.name)}`);
|
|
8824
9109
|
console.log(chalk32.dim("\u2501".repeat(50)));
|
|
@@ -8861,11 +9146,12 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8861
9146
|
100
|
|
8862
9147
|
);
|
|
8863
9148
|
if (limit > 0) {
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
9149
|
+
try {
|
|
9150
|
+
const { runs } = await apiClient.listScheduleRuns({
|
|
9151
|
+
name,
|
|
9152
|
+
composeId,
|
|
9153
|
+
limit
|
|
9154
|
+
});
|
|
8869
9155
|
if (runs.length > 0) {
|
|
8870
9156
|
console.log();
|
|
8871
9157
|
console.log("Recent Runs:");
|
|
@@ -8881,7 +9167,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8881
9167
|
console.log(`${id} ${status} ${created}`);
|
|
8882
9168
|
}
|
|
8883
9169
|
}
|
|
8884
|
-
}
|
|
9170
|
+
} catch {
|
|
8885
9171
|
console.log();
|
|
8886
9172
|
console.log(chalk32.dim("Recent Runs: (unable to fetch)"));
|
|
8887
9173
|
}
|
|
@@ -8893,7 +9179,9 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8893
9179
|
if (error.message.includes("Not authenticated")) {
|
|
8894
9180
|
console.error(chalk32.dim(" Run: vm0 auth login"));
|
|
8895
9181
|
} else if (error.message.includes("not found") || error.message.includes("Not found")) {
|
|
8896
|
-
console.error(
|
|
9182
|
+
console.error(
|
|
9183
|
+
chalk32.dim(` Schedule "${nameArg ?? "unknown"}" not found`)
|
|
9184
|
+
);
|
|
8897
9185
|
} else {
|
|
8898
9186
|
console.error(chalk32.dim(` ${error.message}`));
|
|
8899
9187
|
}
|
|
@@ -8918,8 +9206,29 @@ async function confirm(message) {
|
|
|
8918
9206
|
});
|
|
8919
9207
|
});
|
|
8920
9208
|
}
|
|
8921
|
-
var deleteCommand = new Command31().name("delete").alias("rm").description("Delete a schedule").argument(
|
|
9209
|
+
var deleteCommand = new Command31().name("delete").alias("rm").description("Delete a schedule").argument(
|
|
9210
|
+
"[name]",
|
|
9211
|
+
"Schedule name (auto-detected from schedule.yaml if omitted)"
|
|
9212
|
+
).option("-f, --force", "Skip confirmation prompt").action(async (nameArg, options) => {
|
|
9213
|
+
let name = nameArg;
|
|
8922
9214
|
try {
|
|
9215
|
+
if (!name) {
|
|
9216
|
+
const scheduleResult = loadScheduleName();
|
|
9217
|
+
if (scheduleResult.error) {
|
|
9218
|
+
console.error(chalk33.red(`\u2717 ${scheduleResult.error}`));
|
|
9219
|
+
process.exit(1);
|
|
9220
|
+
}
|
|
9221
|
+
if (!scheduleResult.scheduleName) {
|
|
9222
|
+
console.error(chalk33.red("\u2717 Schedule name required"));
|
|
9223
|
+
console.error(
|
|
9224
|
+
chalk33.dim(
|
|
9225
|
+
" Provide name or run from directory with schedule.yaml"
|
|
9226
|
+
)
|
|
9227
|
+
);
|
|
9228
|
+
process.exit(1);
|
|
9229
|
+
}
|
|
9230
|
+
name = scheduleResult.scheduleName;
|
|
9231
|
+
}
|
|
8923
9232
|
const result = loadAgentName();
|
|
8924
9233
|
if (result.error) {
|
|
8925
9234
|
console.error(chalk33.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
@@ -8947,19 +9256,15 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8947
9256
|
return;
|
|
8948
9257
|
}
|
|
8949
9258
|
}
|
|
8950
|
-
|
|
8951
|
-
`/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
|
|
8952
|
-
);
|
|
8953
|
-
if (!response.ok) {
|
|
8954
|
-
const error = await response.json();
|
|
8955
|
-
throw new Error(error.error?.message || "Delete failed");
|
|
8956
|
-
}
|
|
9259
|
+
await apiClient.deleteSchedule({ name, composeId });
|
|
8957
9260
|
console.log(chalk33.green(`\u2713 Deleted schedule ${chalk33.cyan(name)}`));
|
|
8958
9261
|
} catch (error) {
|
|
8959
9262
|
console.error(chalk33.red("\u2717 Failed to delete schedule"));
|
|
8960
9263
|
if (error instanceof Error) {
|
|
8961
9264
|
if (error.message.includes("Not authenticated")) {
|
|
8962
9265
|
console.error(chalk33.dim(" Run: vm0 auth login"));
|
|
9266
|
+
} else if (error.message.toLowerCase().includes("not found")) {
|
|
9267
|
+
console.error(chalk33.dim(` Schedule "${name}" not found`));
|
|
8963
9268
|
} else {
|
|
8964
9269
|
console.error(chalk33.dim(` ${error.message}`));
|
|
8965
9270
|
}
|
|
@@ -8971,8 +9276,29 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8971
9276
|
// src/commands/schedule/enable.ts
|
|
8972
9277
|
import { Command as Command32 } from "commander";
|
|
8973
9278
|
import chalk34 from "chalk";
|
|
8974
|
-
var enableCommand = new Command32().name("enable").description("Enable a schedule").argument(
|
|
9279
|
+
var enableCommand = new Command32().name("enable").description("Enable a schedule").argument(
|
|
9280
|
+
"[name]",
|
|
9281
|
+
"Schedule name (auto-detected from schedule.yaml if omitted)"
|
|
9282
|
+
).action(async (nameArg) => {
|
|
8975
9283
|
try {
|
|
9284
|
+
let name = nameArg;
|
|
9285
|
+
if (!name) {
|
|
9286
|
+
const scheduleResult = loadScheduleName();
|
|
9287
|
+
if (scheduleResult.error) {
|
|
9288
|
+
console.error(chalk34.red(`\u2717 ${scheduleResult.error}`));
|
|
9289
|
+
process.exit(1);
|
|
9290
|
+
}
|
|
9291
|
+
if (!scheduleResult.scheduleName) {
|
|
9292
|
+
console.error(chalk34.red("\u2717 Schedule name required"));
|
|
9293
|
+
console.error(
|
|
9294
|
+
chalk34.dim(
|
|
9295
|
+
" Provide name or run from directory with schedule.yaml"
|
|
9296
|
+
)
|
|
9297
|
+
);
|
|
9298
|
+
process.exit(1);
|
|
9299
|
+
}
|
|
9300
|
+
name = scheduleResult.scheduleName;
|
|
9301
|
+
}
|
|
8976
9302
|
const result = loadAgentName();
|
|
8977
9303
|
if (result.error) {
|
|
8978
9304
|
console.error(chalk34.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
@@ -8993,14 +9319,7 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
8993
9319
|
console.error(chalk34.dim(" Make sure the agent is pushed first"));
|
|
8994
9320
|
process.exit(1);
|
|
8995
9321
|
}
|
|
8996
|
-
|
|
8997
|
-
`/api/agent/schedules/${encodeURIComponent(name)}/enable`,
|
|
8998
|
-
{ body: JSON.stringify({ composeId }) }
|
|
8999
|
-
);
|
|
9000
|
-
if (!response.ok) {
|
|
9001
|
-
const error = await response.json();
|
|
9002
|
-
throw new Error(error.error?.message || "Enable failed");
|
|
9003
|
-
}
|
|
9322
|
+
await apiClient.enableSchedule({ name, composeId });
|
|
9004
9323
|
console.log(chalk34.green(`\u2713 Enabled schedule ${chalk34.cyan(name)}`));
|
|
9005
9324
|
} catch (error) {
|
|
9006
9325
|
console.error(chalk34.red("\u2717 Failed to enable schedule"));
|
|
@@ -9018,8 +9337,29 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
9018
9337
|
// src/commands/schedule/disable.ts
|
|
9019
9338
|
import { Command as Command33 } from "commander";
|
|
9020
9339
|
import chalk35 from "chalk";
|
|
9021
|
-
var disableCommand = new Command33().name("disable").description("Disable a schedule").argument(
|
|
9340
|
+
var disableCommand = new Command33().name("disable").description("Disable a schedule").argument(
|
|
9341
|
+
"[name]",
|
|
9342
|
+
"Schedule name (auto-detected from schedule.yaml if omitted)"
|
|
9343
|
+
).action(async (nameArg) => {
|
|
9022
9344
|
try {
|
|
9345
|
+
let name = nameArg;
|
|
9346
|
+
if (!name) {
|
|
9347
|
+
const scheduleResult = loadScheduleName();
|
|
9348
|
+
if (scheduleResult.error) {
|
|
9349
|
+
console.error(chalk35.red(`\u2717 ${scheduleResult.error}`));
|
|
9350
|
+
process.exit(1);
|
|
9351
|
+
}
|
|
9352
|
+
if (!scheduleResult.scheduleName) {
|
|
9353
|
+
console.error(chalk35.red("\u2717 Schedule name required"));
|
|
9354
|
+
console.error(
|
|
9355
|
+
chalk35.dim(
|
|
9356
|
+
" Provide name or run from directory with schedule.yaml"
|
|
9357
|
+
)
|
|
9358
|
+
);
|
|
9359
|
+
process.exit(1);
|
|
9360
|
+
}
|
|
9361
|
+
name = scheduleResult.scheduleName;
|
|
9362
|
+
}
|
|
9023
9363
|
const result = loadAgentName();
|
|
9024
9364
|
if (result.error) {
|
|
9025
9365
|
console.error(chalk35.red(`\u2717 Invalid vm0.yaml: ${result.error}`));
|
|
@@ -9040,14 +9380,7 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9040
9380
|
console.error(chalk35.dim(" Make sure the agent is pushed first"));
|
|
9041
9381
|
process.exit(1);
|
|
9042
9382
|
}
|
|
9043
|
-
|
|
9044
|
-
`/api/agent/schedules/${encodeURIComponent(name)}/disable`,
|
|
9045
|
-
{ body: JSON.stringify({ composeId }) }
|
|
9046
|
-
);
|
|
9047
|
-
if (!response.ok) {
|
|
9048
|
-
const error = await response.json();
|
|
9049
|
-
throw new Error(error.error?.message || "Disable failed");
|
|
9050
|
-
}
|
|
9383
|
+
await apiClient.disableSchedule({ name, composeId });
|
|
9051
9384
|
console.log(chalk35.green(`\u2713 Disabled schedule ${chalk35.cyan(name)}`));
|
|
9052
9385
|
} catch (error) {
|
|
9053
9386
|
console.error(chalk35.red("\u2717 Failed to disable schedule"));
|
|
@@ -9067,7 +9400,7 @@ var scheduleCommand = new Command34().name("schedule").description("Manage agent
|
|
|
9067
9400
|
|
|
9068
9401
|
// src/index.ts
|
|
9069
9402
|
var program = new Command35();
|
|
9070
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.
|
|
9403
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.7.2");
|
|
9071
9404
|
program.command("info").description("Display environment information").action(async () => {
|
|
9072
9405
|
console.log(chalk36.bold("System Information:"));
|
|
9073
9406
|
console.log(`Node Version: ${process.version}`);
|