@vm0/cli 5.7.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 +612 -388
- 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,120 +2716,116 @@ 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
|
-
|
|
2727
|
-
|
|
2728
|
-
if (options?.limit !== void 0) {
|
|
2729
|
-
params.set("limit", String(options.limit));
|
|
2730
|
-
}
|
|
2731
|
-
if (options?.order !== void 0) {
|
|
2732
|
-
params.set("order", options.order);
|
|
2733
|
-
}
|
|
2734
|
-
const queryString = params.toString();
|
|
2735
|
-
const url = `${baseUrl}/api/agent/runs/${runId}/telemetry/system-log${queryString ? `?${queryString}` : ""}`;
|
|
2736
|
-
const response = await fetch(url, {
|
|
2737
|
-
method: "GET",
|
|
2738
|
-
headers
|
|
2741
|
+
const client = initClient(runSystemLogContract, {
|
|
2742
|
+
baseUrl,
|
|
2743
|
+
baseHeaders: headers,
|
|
2744
|
+
jsonQuery: true
|
|
2739
2745
|
});
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
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;
|
|
2743
2756
|
}
|
|
2744
|
-
|
|
2757
|
+
const errorBody = result.body;
|
|
2758
|
+
const message = errorBody.error?.message || "Failed to fetch system log";
|
|
2759
|
+
throw new Error(message);
|
|
2745
2760
|
}
|
|
2746
2761
|
async getMetrics(runId, options) {
|
|
2747
2762
|
const baseUrl = await this.getBaseUrl();
|
|
2748
2763
|
const headers = await this.getHeaders();
|
|
2749
|
-
const
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
if (options?.limit !== void 0) {
|
|
2754
|
-
params.set("limit", String(options.limit));
|
|
2755
|
-
}
|
|
2756
|
-
if (options?.order !== void 0) {
|
|
2757
|
-
params.set("order", options.order);
|
|
2758
|
-
}
|
|
2759
|
-
const queryString = params.toString();
|
|
2760
|
-
const url = `${baseUrl}/api/agent/runs/${runId}/telemetry/metrics${queryString ? `?${queryString}` : ""}`;
|
|
2761
|
-
const response = await fetch(url, {
|
|
2762
|
-
method: "GET",
|
|
2763
|
-
headers
|
|
2764
|
+
const client = initClient(runMetricsContract, {
|
|
2765
|
+
baseUrl,
|
|
2766
|
+
baseHeaders: headers,
|
|
2767
|
+
jsonQuery: true
|
|
2764
2768
|
});
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
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;
|
|
2768
2779
|
}
|
|
2769
|
-
|
|
2780
|
+
const errorBody = result.body;
|
|
2781
|
+
const message = errorBody.error?.message || "Failed to fetch metrics";
|
|
2782
|
+
throw new Error(message);
|
|
2770
2783
|
}
|
|
2771
2784
|
async getAgentEvents(runId, options) {
|
|
2772
2785
|
const baseUrl = await this.getBaseUrl();
|
|
2773
2786
|
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
|
|
2787
|
+
const client = initClient(runAgentEventsContract, {
|
|
2788
|
+
baseUrl,
|
|
2789
|
+
baseHeaders: headers,
|
|
2790
|
+
jsonQuery: true
|
|
2789
2791
|
});
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
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;
|
|
2793
2802
|
}
|
|
2794
|
-
|
|
2803
|
+
const errorBody = result.body;
|
|
2804
|
+
const message = errorBody.error?.message || "Failed to fetch agent events";
|
|
2805
|
+
throw new Error(message);
|
|
2795
2806
|
}
|
|
2796
2807
|
async getNetworkLogs(runId, options) {
|
|
2797
2808
|
const baseUrl = await this.getBaseUrl();
|
|
2798
2809
|
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
|
|
2810
|
+
const client = initClient(runNetworkLogsContract, {
|
|
2811
|
+
baseUrl,
|
|
2812
|
+
baseHeaders: headers,
|
|
2813
|
+
jsonQuery: true
|
|
2814
2814
|
});
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
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;
|
|
2818
2825
|
}
|
|
2819
|
-
|
|
2826
|
+
const errorBody = result.body;
|
|
2827
|
+
const message = errorBody.error?.message || "Failed to fetch network logs";
|
|
2828
|
+
throw new Error(message);
|
|
2820
2829
|
}
|
|
2821
2830
|
/**
|
|
2822
2831
|
* Get current user's scope
|
|
@@ -2824,15 +2833,18 @@ var ApiClient = class {
|
|
|
2824
2833
|
async getScope() {
|
|
2825
2834
|
const baseUrl = await this.getBaseUrl();
|
|
2826
2835
|
const headers = await this.getHeaders();
|
|
2827
|
-
const
|
|
2828
|
-
|
|
2829
|
-
headers
|
|
2836
|
+
const client = initClient(scopeContract, {
|
|
2837
|
+
baseUrl,
|
|
2838
|
+
baseHeaders: headers,
|
|
2839
|
+
jsonQuery: true
|
|
2830
2840
|
});
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2841
|
+
const result = await client.get();
|
|
2842
|
+
if (result.status === 200) {
|
|
2843
|
+
return result.body;
|
|
2834
2844
|
}
|
|
2835
|
-
|
|
2845
|
+
const errorBody = result.body;
|
|
2846
|
+
const message = errorBody.error?.message || "Failed to get scope";
|
|
2847
|
+
throw new Error(message);
|
|
2836
2848
|
}
|
|
2837
2849
|
/**
|
|
2838
2850
|
* Create user's scope
|
|
@@ -2840,16 +2852,18 @@ var ApiClient = class {
|
|
|
2840
2852
|
async createScope(body) {
|
|
2841
2853
|
const baseUrl = await this.getBaseUrl();
|
|
2842
2854
|
const headers = await this.getHeaders();
|
|
2843
|
-
const
|
|
2844
|
-
|
|
2845
|
-
headers,
|
|
2846
|
-
|
|
2855
|
+
const client = initClient(scopeContract, {
|
|
2856
|
+
baseUrl,
|
|
2857
|
+
baseHeaders: headers,
|
|
2858
|
+
jsonQuery: true
|
|
2847
2859
|
});
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2860
|
+
const result = await client.create({ body });
|
|
2861
|
+
if (result.status === 201) {
|
|
2862
|
+
return result.body;
|
|
2851
2863
|
}
|
|
2852
|
-
|
|
2864
|
+
const errorBody = result.body;
|
|
2865
|
+
const message = errorBody.error?.message || "Failed to create scope";
|
|
2866
|
+
throw new Error(message);
|
|
2853
2867
|
}
|
|
2854
2868
|
/**
|
|
2855
2869
|
* Update user's scope slug
|
|
@@ -2857,16 +2871,18 @@ var ApiClient = class {
|
|
|
2857
2871
|
async updateScope(body) {
|
|
2858
2872
|
const baseUrl = await this.getBaseUrl();
|
|
2859
2873
|
const headers = await this.getHeaders();
|
|
2860
|
-
const
|
|
2861
|
-
|
|
2862
|
-
headers,
|
|
2863
|
-
|
|
2874
|
+
const client = initClient(scopeContract, {
|
|
2875
|
+
baseUrl,
|
|
2876
|
+
baseHeaders: headers,
|
|
2877
|
+
jsonQuery: true
|
|
2864
2878
|
});
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2879
|
+
const result = await client.update({ body });
|
|
2880
|
+
if (result.status === 200) {
|
|
2881
|
+
return result.body;
|
|
2868
2882
|
}
|
|
2869
|
-
|
|
2883
|
+
const errorBody = result.body;
|
|
2884
|
+
const message = errorBody.error?.message || "Failed to update scope";
|
|
2885
|
+
throw new Error(message);
|
|
2870
2886
|
}
|
|
2871
2887
|
/**
|
|
2872
2888
|
* Get session by ID
|
|
@@ -2875,17 +2891,20 @@ var ApiClient = class {
|
|
|
2875
2891
|
async getSession(sessionId) {
|
|
2876
2892
|
const baseUrl = await this.getBaseUrl();
|
|
2877
2893
|
const headers = await this.getHeaders();
|
|
2878
|
-
const
|
|
2879
|
-
|
|
2880
|
-
headers
|
|
2894
|
+
const client = initClient(sessionsByIdContract, {
|
|
2895
|
+
baseUrl,
|
|
2896
|
+
baseHeaders: headers,
|
|
2897
|
+
jsonQuery: true
|
|
2881
2898
|
});
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2899
|
+
const result = await client.getById({
|
|
2900
|
+
params: { id: sessionId }
|
|
2901
|
+
});
|
|
2902
|
+
if (result.status === 200) {
|
|
2903
|
+
return result.body;
|
|
2887
2904
|
}
|
|
2888
|
-
|
|
2905
|
+
const errorBody = result.body;
|
|
2906
|
+
const message = errorBody.error?.message || `Session not found: ${sessionId}`;
|
|
2907
|
+
throw new Error(message);
|
|
2889
2908
|
}
|
|
2890
2909
|
/**
|
|
2891
2910
|
* Get checkpoint by ID
|
|
@@ -2894,20 +2913,348 @@ var ApiClient = class {
|
|
|
2894
2913
|
async getCheckpoint(checkpointId) {
|
|
2895
2914
|
const baseUrl = await this.getBaseUrl();
|
|
2896
2915
|
const headers = await this.getHeaders();
|
|
2897
|
-
const
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
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
|
|
2902
2985
|
}
|
|
2903
|
-
);
|
|
2904
|
-
if (
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
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) {
|
|
3121
|
+
const baseUrl = await this.getBaseUrl();
|
|
3122
|
+
const headers = await this.getHeaders();
|
|
3123
|
+
const client = initClient(schedulesEnableContract, {
|
|
3124
|
+
baseUrl,
|
|
3125
|
+
baseHeaders: headers,
|
|
3126
|
+
jsonQuery: true
|
|
3127
|
+
});
|
|
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;
|
|
3134
|
+
}
|
|
3135
|
+
const errorBody = result.body;
|
|
3136
|
+
const message = errorBody.error?.message || `Failed to disable schedule "${params.name}"`;
|
|
3137
|
+
throw new Error(message);
|
|
3138
|
+
}
|
|
3139
|
+
/**
|
|
3140
|
+
* List recent runs for a schedule
|
|
3141
|
+
*/
|
|
3142
|
+
async listScheduleRuns(params) {
|
|
3143
|
+
const baseUrl = await this.getBaseUrl();
|
|
3144
|
+
const headers = await this.getHeaders();
|
|
3145
|
+
const client = initClient(scheduleRunsContract, {
|
|
3146
|
+
baseUrl,
|
|
3147
|
+
baseHeaders: headers,
|
|
3148
|
+
jsonQuery: true
|
|
3149
|
+
});
|
|
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;
|
|
3159
|
+
}
|
|
3160
|
+
const errorBody = result.body;
|
|
3161
|
+
const message = errorBody.error?.message || `Failed to list runs for schedule "${params.name}"`;
|
|
3162
|
+
throw new Error(message);
|
|
3163
|
+
}
|
|
3164
|
+
/**
|
|
3165
|
+
* List public agents
|
|
3166
|
+
*/
|
|
3167
|
+
async listPublicAgents(query) {
|
|
3168
|
+
const baseUrl = await this.getBaseUrl();
|
|
3169
|
+
const headers = await this.getHeaders();
|
|
3170
|
+
const client = initClient(publicAgentsListContract, {
|
|
3171
|
+
baseUrl,
|
|
3172
|
+
baseHeaders: headers,
|
|
3173
|
+
jsonQuery: true
|
|
3174
|
+
});
|
|
3175
|
+
const result = await client.list({ query: query ?? {} });
|
|
3176
|
+
if (result.status === 200) {
|
|
3177
|
+
return result.body;
|
|
2909
3178
|
}
|
|
2910
|
-
|
|
3179
|
+
const errorBody = result.body;
|
|
3180
|
+
const message = errorBody.error?.message || "Failed to list agents";
|
|
3181
|
+
throw new Error(message);
|
|
3182
|
+
}
|
|
3183
|
+
/**
|
|
3184
|
+
* List public artifacts
|
|
3185
|
+
*/
|
|
3186
|
+
async listPublicArtifacts(query) {
|
|
3187
|
+
const baseUrl = await this.getBaseUrl();
|
|
3188
|
+
const headers = await this.getHeaders();
|
|
3189
|
+
const client = initClient(publicArtifactsListContract, {
|
|
3190
|
+
baseUrl,
|
|
3191
|
+
baseHeaders: headers,
|
|
3192
|
+
jsonQuery: true
|
|
3193
|
+
});
|
|
3194
|
+
const result = await client.list({ query: query ?? {} });
|
|
3195
|
+
if (result.status === 200) {
|
|
3196
|
+
return result.body;
|
|
3197
|
+
}
|
|
3198
|
+
const errorBody = result.body;
|
|
3199
|
+
const message = errorBody.error?.message || "Failed to list artifacts";
|
|
3200
|
+
throw new Error(message);
|
|
3201
|
+
}
|
|
3202
|
+
/**
|
|
3203
|
+
* Get public artifact by ID
|
|
3204
|
+
*/
|
|
3205
|
+
async getPublicArtifact(id) {
|
|
3206
|
+
const baseUrl = await this.getBaseUrl();
|
|
3207
|
+
const headers = await this.getHeaders();
|
|
3208
|
+
const client = initClient(publicArtifactByIdContract, {
|
|
3209
|
+
baseUrl,
|
|
3210
|
+
baseHeaders: headers,
|
|
3211
|
+
jsonQuery: true
|
|
3212
|
+
});
|
|
3213
|
+
const result = await client.get({ params: { id } });
|
|
3214
|
+
if (result.status === 200) {
|
|
3215
|
+
return result.body;
|
|
3216
|
+
}
|
|
3217
|
+
const errorBody = result.body;
|
|
3218
|
+
const message = errorBody.error?.message || `Artifact "${id}" not found`;
|
|
3219
|
+
throw new Error(message);
|
|
3220
|
+
}
|
|
3221
|
+
/**
|
|
3222
|
+
* List public volumes
|
|
3223
|
+
*/
|
|
3224
|
+
async listPublicVolumes(query) {
|
|
3225
|
+
const baseUrl = await this.getBaseUrl();
|
|
3226
|
+
const headers = await this.getHeaders();
|
|
3227
|
+
const client = initClient(publicVolumesListContract, {
|
|
3228
|
+
baseUrl,
|
|
3229
|
+
baseHeaders: headers,
|
|
3230
|
+
jsonQuery: true
|
|
3231
|
+
});
|
|
3232
|
+
const result = await client.list({ query: query ?? {} });
|
|
3233
|
+
if (result.status === 200) {
|
|
3234
|
+
return result.body;
|
|
3235
|
+
}
|
|
3236
|
+
const errorBody = result.body;
|
|
3237
|
+
const message = errorBody.error?.message || "Failed to list volumes";
|
|
3238
|
+
throw new Error(message);
|
|
3239
|
+
}
|
|
3240
|
+
/**
|
|
3241
|
+
* Get public volume by ID
|
|
3242
|
+
*/
|
|
3243
|
+
async getPublicVolume(id) {
|
|
3244
|
+
const baseUrl = await this.getBaseUrl();
|
|
3245
|
+
const headers = await this.getHeaders();
|
|
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;
|
|
3254
|
+
}
|
|
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.7.
|
|
6735
|
+
const shouldExit = await checkAndUpgrade("5.7.2", prompt);
|
|
6476
6736
|
if (shouldExit) {
|
|
6477
6737
|
process.exit(0);
|
|
6478
6738
|
}
|
|
@@ -8660,14 +8920,7 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8660
8920
|
artifactVersion: schedule.run.artifactVersion,
|
|
8661
8921
|
volumeVersions: schedule.run.volumeVersions
|
|
8662
8922
|
};
|
|
8663
|
-
const
|
|
8664
|
-
body: JSON.stringify(body)
|
|
8665
|
-
});
|
|
8666
|
-
if (!response.ok) {
|
|
8667
|
-
const error = await response.json();
|
|
8668
|
-
throw new Error(error.error?.message || "Deploy failed");
|
|
8669
|
-
}
|
|
8670
|
-
const deployResult = await response.json();
|
|
8923
|
+
const deployResult = await apiClient.deploySchedule(body);
|
|
8671
8924
|
if (deployResult.created) {
|
|
8672
8925
|
console.log(
|
|
8673
8926
|
chalk30.green(`\u2713 Created schedule ${chalk30.cyan(scheduleName)}`)
|
|
@@ -8714,12 +8967,7 @@ import { Command as Command29 } from "commander";
|
|
|
8714
8967
|
import chalk31 from "chalk";
|
|
8715
8968
|
var listCommand4 = new Command29().name("list").alias("ls").description("List all schedules").action(async () => {
|
|
8716
8969
|
try {
|
|
8717
|
-
const
|
|
8718
|
-
if (!response.ok) {
|
|
8719
|
-
const error = await response.json();
|
|
8720
|
-
throw new Error(error.error?.message || "List failed");
|
|
8721
|
-
}
|
|
8722
|
-
const result = await response.json();
|
|
8970
|
+
const result = await apiClient.listSchedules();
|
|
8723
8971
|
if (result.schedules.length === 0) {
|
|
8724
8972
|
console.log(chalk31.dim("No schedules found"));
|
|
8725
8973
|
console.log(
|
|
@@ -8855,14 +9103,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8855
9103
|
console.error(chalk32.dim(" Make sure the agent is pushed first"));
|
|
8856
9104
|
process.exit(1);
|
|
8857
9105
|
}
|
|
8858
|
-
const
|
|
8859
|
-
`/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
|
|
8860
|
-
);
|
|
8861
|
-
if (!response.ok) {
|
|
8862
|
-
const error = await response.json();
|
|
8863
|
-
throw new Error(error.error?.message || "Failed to get schedule");
|
|
8864
|
-
}
|
|
8865
|
-
const schedule = await response.json();
|
|
9106
|
+
const schedule = await apiClient.getScheduleByName({ name, composeId });
|
|
8866
9107
|
console.log();
|
|
8867
9108
|
console.log(`Schedule: ${chalk32.cyan(schedule.name)}`);
|
|
8868
9109
|
console.log(chalk32.dim("\u2501".repeat(50)));
|
|
@@ -8905,11 +9146,12 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8905
9146
|
100
|
|
8906
9147
|
);
|
|
8907
9148
|
if (limit > 0) {
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
9149
|
+
try {
|
|
9150
|
+
const { runs } = await apiClient.listScheduleRuns({
|
|
9151
|
+
name,
|
|
9152
|
+
composeId,
|
|
9153
|
+
limit
|
|
9154
|
+
});
|
|
8913
9155
|
if (runs.length > 0) {
|
|
8914
9156
|
console.log();
|
|
8915
9157
|
console.log("Recent Runs:");
|
|
@@ -8925,7 +9167,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8925
9167
|
console.log(`${id} ${status} ${created}`);
|
|
8926
9168
|
}
|
|
8927
9169
|
}
|
|
8928
|
-
}
|
|
9170
|
+
} catch {
|
|
8929
9171
|
console.log();
|
|
8930
9172
|
console.log(chalk32.dim("Recent Runs: (unable to fetch)"));
|
|
8931
9173
|
}
|
|
@@ -8968,8 +9210,8 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8968
9210
|
"[name]",
|
|
8969
9211
|
"Schedule name (auto-detected from schedule.yaml if omitted)"
|
|
8970
9212
|
).option("-f, --force", "Skip confirmation prompt").action(async (nameArg, options) => {
|
|
9213
|
+
let name = nameArg;
|
|
8971
9214
|
try {
|
|
8972
|
-
let name = nameArg;
|
|
8973
9215
|
if (!name) {
|
|
8974
9216
|
const scheduleResult = loadScheduleName();
|
|
8975
9217
|
if (scheduleResult.error) {
|
|
@@ -9014,19 +9256,15 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
9014
9256
|
return;
|
|
9015
9257
|
}
|
|
9016
9258
|
}
|
|
9017
|
-
|
|
9018
|
-
`/api/agent/schedules/${encodeURIComponent(name)}?composeId=${encodeURIComponent(composeId)}`
|
|
9019
|
-
);
|
|
9020
|
-
if (!response.ok) {
|
|
9021
|
-
const error = await response.json();
|
|
9022
|
-
throw new Error(error.error?.message || "Delete failed");
|
|
9023
|
-
}
|
|
9259
|
+
await apiClient.deleteSchedule({ name, composeId });
|
|
9024
9260
|
console.log(chalk33.green(`\u2713 Deleted schedule ${chalk33.cyan(name)}`));
|
|
9025
9261
|
} catch (error) {
|
|
9026
9262
|
console.error(chalk33.red("\u2717 Failed to delete schedule"));
|
|
9027
9263
|
if (error instanceof Error) {
|
|
9028
9264
|
if (error.message.includes("Not authenticated")) {
|
|
9029
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`));
|
|
9030
9268
|
} else {
|
|
9031
9269
|
console.error(chalk33.dim(` ${error.message}`));
|
|
9032
9270
|
}
|
|
@@ -9081,14 +9319,7 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
9081
9319
|
console.error(chalk34.dim(" Make sure the agent is pushed first"));
|
|
9082
9320
|
process.exit(1);
|
|
9083
9321
|
}
|
|
9084
|
-
|
|
9085
|
-
`/api/agent/schedules/${encodeURIComponent(name)}/enable`,
|
|
9086
|
-
{ body: JSON.stringify({ composeId }) }
|
|
9087
|
-
);
|
|
9088
|
-
if (!response.ok) {
|
|
9089
|
-
const error = await response.json();
|
|
9090
|
-
throw new Error(error.error?.message || "Enable failed");
|
|
9091
|
-
}
|
|
9322
|
+
await apiClient.enableSchedule({ name, composeId });
|
|
9092
9323
|
console.log(chalk34.green(`\u2713 Enabled schedule ${chalk34.cyan(name)}`));
|
|
9093
9324
|
} catch (error) {
|
|
9094
9325
|
console.error(chalk34.red("\u2717 Failed to enable schedule"));
|
|
@@ -9149,14 +9380,7 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9149
9380
|
console.error(chalk35.dim(" Make sure the agent is pushed first"));
|
|
9150
9381
|
process.exit(1);
|
|
9151
9382
|
}
|
|
9152
|
-
|
|
9153
|
-
`/api/agent/schedules/${encodeURIComponent(name)}/disable`,
|
|
9154
|
-
{ body: JSON.stringify({ composeId }) }
|
|
9155
|
-
);
|
|
9156
|
-
if (!response.ok) {
|
|
9157
|
-
const error = await response.json();
|
|
9158
|
-
throw new Error(error.error?.message || "Disable failed");
|
|
9159
|
-
}
|
|
9383
|
+
await apiClient.disableSchedule({ name, composeId });
|
|
9160
9384
|
console.log(chalk35.green(`\u2713 Disabled schedule ${chalk35.cyan(name)}`));
|
|
9161
9385
|
} catch (error) {
|
|
9162
9386
|
console.error(chalk35.red("\u2717 Failed to disable schedule"));
|
|
@@ -9176,7 +9400,7 @@ var scheduleCommand = new Command34().name("schedule").description("Manage agent
|
|
|
9176
9400
|
|
|
9177
9401
|
// src/index.ts
|
|
9178
9402
|
var program = new Command35();
|
|
9179
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.7.
|
|
9403
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.7.2");
|
|
9180
9404
|
program.command("info").description("Display environment information").action(async () => {
|
|
9181
9405
|
console.log(chalk36.bold("System Information:"));
|
|
9182
9406
|
console.log(`Node Version: ${process.version}`);
|