@vm0/cli 5.7.0 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +1016 -562
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
5
|
-
import
|
|
4
|
+
import { Command as Command36 } from "commander";
|
|
5
|
+
import chalk37 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/lib/api/auth.ts
|
|
8
8
|
import chalk from "chalk";
|
|
@@ -333,7 +333,9 @@ var storedExecutionContextSchema = z2.object({
|
|
|
333
333
|
encryptedSecrets: z2.string().nullable(),
|
|
334
334
|
// AES-256-GCM encrypted secrets
|
|
335
335
|
cliAgentType: z2.string(),
|
|
336
|
-
experimentalFirewall: experimentalFirewallSchema.optional()
|
|
336
|
+
experimentalFirewall: experimentalFirewallSchema.optional(),
|
|
337
|
+
// Debug flag to force real Claude in mock environments (internal use only)
|
|
338
|
+
debugNoMockClaude: z2.boolean().optional()
|
|
337
339
|
});
|
|
338
340
|
var executionContextSchema = z2.object({
|
|
339
341
|
runId: z2.string().uuid(),
|
|
@@ -351,7 +353,9 @@ var executionContextSchema = z2.object({
|
|
|
351
353
|
secretValues: z2.array(z2.string()).nullable(),
|
|
352
354
|
cliAgentType: z2.string(),
|
|
353
355
|
// Experimental firewall configuration
|
|
354
|
-
experimentalFirewall: experimentalFirewallSchema.optional()
|
|
356
|
+
experimentalFirewall: experimentalFirewallSchema.optional(),
|
|
357
|
+
// Debug flag to force real Claude in mock environments (internal use only)
|
|
358
|
+
debugNoMockClaude: z2.boolean().optional()
|
|
355
359
|
});
|
|
356
360
|
var runnersJobClaimContract = c.router({
|
|
357
361
|
claim: {
|
|
@@ -634,6 +638,8 @@ var unifiedRunRequestSchema = z4.object({
|
|
|
634
638
|
vars: z4.record(z4.string(), z4.string()).optional(),
|
|
635
639
|
secrets: z4.record(z4.string(), z4.string()).optional(),
|
|
636
640
|
volumeVersions: z4.record(z4.string(), z4.string()).optional(),
|
|
641
|
+
// Debug flag to force real Claude in mock environments (internal use only)
|
|
642
|
+
debugNoMockClaude: z4.boolean().optional(),
|
|
637
643
|
// Required
|
|
638
644
|
prompt: z4.string().min(1, "Missing prompt")
|
|
639
645
|
});
|
|
@@ -2586,6 +2592,16 @@ function getProviderDisplayName(provider) {
|
|
|
2586
2592
|
return PROVIDER_DISPLAY_NAMES[provider];
|
|
2587
2593
|
}
|
|
2588
2594
|
|
|
2595
|
+
// ../../packages/core/src/feature-switch.ts
|
|
2596
|
+
var PricingSwitch = {
|
|
2597
|
+
key: "pricing" /* Pricing */,
|
|
2598
|
+
maintainer: "ethan@vm0.ai",
|
|
2599
|
+
enabled: false
|
|
2600
|
+
};
|
|
2601
|
+
var FEATURE_SWITCHES = {
|
|
2602
|
+
["pricing" /* Pricing */]: PricingSwitch
|
|
2603
|
+
};
|
|
2604
|
+
|
|
2589
2605
|
// src/lib/api/api-client.ts
|
|
2590
2606
|
import { initClient } from "@ts-rest/core";
|
|
2591
2607
|
var ApiClient = class {
|
|
@@ -2595,8 +2611,7 @@ var ApiClient = class {
|
|
|
2595
2611
|
throw new Error("Not authenticated. Run: vm0 auth login");
|
|
2596
2612
|
}
|
|
2597
2613
|
const headers = {
|
|
2598
|
-
Authorization: `Bearer ${token}
|
|
2599
|
-
"Content-Type": "application/json"
|
|
2614
|
+
Authorization: `Bearer ${token}`
|
|
2600
2615
|
};
|
|
2601
2616
|
const bypassSecret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
|
2602
2617
|
if (bypassSecret) {
|
|
@@ -2614,35 +2629,41 @@ var ApiClient = class {
|
|
|
2614
2629
|
async getComposeByName(name, scope) {
|
|
2615
2630
|
const baseUrl = await this.getBaseUrl();
|
|
2616
2631
|
const headers = await this.getHeaders();
|
|
2617
|
-
const
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
{
|
|
2624
|
-
|
|
2625
|
-
|
|
2632
|
+
const client = initClient(composesMainContract, {
|
|
2633
|
+
baseUrl,
|
|
2634
|
+
baseHeaders: headers,
|
|
2635
|
+
jsonQuery: true
|
|
2636
|
+
});
|
|
2637
|
+
const result = await client.getByName({
|
|
2638
|
+
query: {
|
|
2639
|
+
name,
|
|
2640
|
+
scope
|
|
2626
2641
|
}
|
|
2627
|
-
);
|
|
2628
|
-
if (
|
|
2629
|
-
|
|
2630
|
-
throw new Error(error.error?.message || `Compose not found: ${name}`);
|
|
2642
|
+
});
|
|
2643
|
+
if (result.status === 200) {
|
|
2644
|
+
return result.body;
|
|
2631
2645
|
}
|
|
2632
|
-
|
|
2646
|
+
const errorBody = result.body;
|
|
2647
|
+
const message = errorBody.error?.message || `Compose not found: ${name}`;
|
|
2648
|
+
throw new Error(message);
|
|
2633
2649
|
}
|
|
2634
2650
|
async getComposeById(id) {
|
|
2635
2651
|
const baseUrl = await this.getBaseUrl();
|
|
2636
2652
|
const headers = await this.getHeaders();
|
|
2637
|
-
const
|
|
2638
|
-
|
|
2639
|
-
headers
|
|
2653
|
+
const client = initClient(composesByIdContract, {
|
|
2654
|
+
baseUrl,
|
|
2655
|
+
baseHeaders: headers,
|
|
2656
|
+
jsonQuery: true
|
|
2640
2657
|
});
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2658
|
+
const result = await client.getById({
|
|
2659
|
+
params: { id }
|
|
2660
|
+
});
|
|
2661
|
+
if (result.status === 200) {
|
|
2662
|
+
return result.body;
|
|
2644
2663
|
}
|
|
2645
|
-
|
|
2664
|
+
const errorBody = result.body;
|
|
2665
|
+
const message = errorBody.error?.message || `Compose not found: ${id}`;
|
|
2666
|
+
throw new Error(message);
|
|
2646
2667
|
}
|
|
2647
2668
|
/**
|
|
2648
2669
|
* Resolve a version specifier to a full version ID
|
|
@@ -2651,33 +2672,41 @@ var ApiClient = class {
|
|
|
2651
2672
|
async getComposeVersion(composeId, version) {
|
|
2652
2673
|
const baseUrl = await this.getBaseUrl();
|
|
2653
2674
|
const headers = await this.getHeaders();
|
|
2654
|
-
const
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2675
|
+
const client = initClient(composesVersionsContract, {
|
|
2676
|
+
baseUrl,
|
|
2677
|
+
baseHeaders: headers,
|
|
2678
|
+
jsonQuery: true
|
|
2679
|
+
});
|
|
2680
|
+
const result = await client.resolveVersion({
|
|
2681
|
+
query: {
|
|
2682
|
+
composeId,
|
|
2683
|
+
version
|
|
2660
2684
|
}
|
|
2661
|
-
);
|
|
2662
|
-
if (
|
|
2663
|
-
|
|
2664
|
-
throw new Error(error.error?.message || `Version not found: ${version}`);
|
|
2685
|
+
});
|
|
2686
|
+
if (result.status === 200) {
|
|
2687
|
+
return result.body;
|
|
2665
2688
|
}
|
|
2666
|
-
|
|
2689
|
+
const errorBody = result.body;
|
|
2690
|
+
const message = errorBody.error?.message || `Version not found: ${version}`;
|
|
2691
|
+
throw new Error(message);
|
|
2667
2692
|
}
|
|
2668
2693
|
async createOrUpdateCompose(body) {
|
|
2669
2694
|
const baseUrl = await this.getBaseUrl();
|
|
2670
2695
|
const headers = await this.getHeaders();
|
|
2671
|
-
const
|
|
2672
|
-
|
|
2673
|
-
headers,
|
|
2674
|
-
|
|
2696
|
+
const client = initClient(composesMainContract, {
|
|
2697
|
+
baseUrl,
|
|
2698
|
+
baseHeaders: headers,
|
|
2699
|
+
jsonQuery: true
|
|
2675
2700
|
});
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2701
|
+
const result = await client.create({
|
|
2702
|
+
body
|
|
2703
|
+
});
|
|
2704
|
+
if (result.status === 200 || result.status === 201) {
|
|
2705
|
+
return result.body;
|
|
2679
2706
|
}
|
|
2680
|
-
|
|
2707
|
+
const errorBody = result.body;
|
|
2708
|
+
const message = errorBody.error?.message || "Failed to create compose";
|
|
2709
|
+
throw new Error(message);
|
|
2681
2710
|
}
|
|
2682
2711
|
/**
|
|
2683
2712
|
* Create a run with unified request format
|
|
@@ -2703,120 +2732,116 @@ var ApiClient = class {
|
|
|
2703
2732
|
async getEvents(runId, options) {
|
|
2704
2733
|
const baseUrl = await this.getBaseUrl();
|
|
2705
2734
|
const headers = await this.getHeaders();
|
|
2706
|
-
const
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2735
|
+
const client = initClient(runEventsContract, {
|
|
2736
|
+
baseUrl,
|
|
2737
|
+
baseHeaders: headers,
|
|
2738
|
+
jsonQuery: true
|
|
2739
|
+
});
|
|
2740
|
+
const result = await client.getEvents({
|
|
2741
|
+
params: { id: runId },
|
|
2742
|
+
query: {
|
|
2743
|
+
since: options?.since ?? 0,
|
|
2744
|
+
limit: options?.limit ?? 100
|
|
2713
2745
|
}
|
|
2714
|
-
);
|
|
2715
|
-
if (
|
|
2716
|
-
|
|
2717
|
-
throw new Error(error.error?.message || "Failed to fetch events");
|
|
2746
|
+
});
|
|
2747
|
+
if (result.status === 200) {
|
|
2748
|
+
return result.body;
|
|
2718
2749
|
}
|
|
2719
|
-
|
|
2750
|
+
const errorBody = result.body;
|
|
2751
|
+
const message = errorBody.error?.message || "Failed to fetch events";
|
|
2752
|
+
throw new Error(message);
|
|
2720
2753
|
}
|
|
2721
2754
|
async getSystemLog(runId, options) {
|
|
2722
2755
|
const baseUrl = await this.getBaseUrl();
|
|
2723
2756
|
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
|
|
2757
|
+
const client = initClient(runSystemLogContract, {
|
|
2758
|
+
baseUrl,
|
|
2759
|
+
baseHeaders: headers,
|
|
2760
|
+
jsonQuery: true
|
|
2739
2761
|
});
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2762
|
+
const result = await client.getSystemLog({
|
|
2763
|
+
params: { id: runId },
|
|
2764
|
+
query: {
|
|
2765
|
+
since: options?.since,
|
|
2766
|
+
limit: options?.limit,
|
|
2767
|
+
order: options?.order
|
|
2768
|
+
}
|
|
2769
|
+
});
|
|
2770
|
+
if (result.status === 200) {
|
|
2771
|
+
return result.body;
|
|
2743
2772
|
}
|
|
2744
|
-
|
|
2773
|
+
const errorBody = result.body;
|
|
2774
|
+
const message = errorBody.error?.message || "Failed to fetch system log";
|
|
2775
|
+
throw new Error(message);
|
|
2745
2776
|
}
|
|
2746
2777
|
async getMetrics(runId, options) {
|
|
2747
2778
|
const baseUrl = await this.getBaseUrl();
|
|
2748
2779
|
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
|
|
2780
|
+
const client = initClient(runMetricsContract, {
|
|
2781
|
+
baseUrl,
|
|
2782
|
+
baseHeaders: headers,
|
|
2783
|
+
jsonQuery: true
|
|
2764
2784
|
});
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2785
|
+
const result = await client.getMetrics({
|
|
2786
|
+
params: { id: runId },
|
|
2787
|
+
query: {
|
|
2788
|
+
since: options?.since,
|
|
2789
|
+
limit: options?.limit,
|
|
2790
|
+
order: options?.order
|
|
2791
|
+
}
|
|
2792
|
+
});
|
|
2793
|
+
if (result.status === 200) {
|
|
2794
|
+
return result.body;
|
|
2768
2795
|
}
|
|
2769
|
-
|
|
2796
|
+
const errorBody = result.body;
|
|
2797
|
+
const message = errorBody.error?.message || "Failed to fetch metrics";
|
|
2798
|
+
throw new Error(message);
|
|
2770
2799
|
}
|
|
2771
2800
|
async getAgentEvents(runId, options) {
|
|
2772
2801
|
const baseUrl = await this.getBaseUrl();
|
|
2773
2802
|
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
|
|
2803
|
+
const client = initClient(runAgentEventsContract, {
|
|
2804
|
+
baseUrl,
|
|
2805
|
+
baseHeaders: headers,
|
|
2806
|
+
jsonQuery: true
|
|
2789
2807
|
});
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2808
|
+
const result = await client.getAgentEvents({
|
|
2809
|
+
params: { id: runId },
|
|
2810
|
+
query: {
|
|
2811
|
+
since: options?.since,
|
|
2812
|
+
limit: options?.limit,
|
|
2813
|
+
order: options?.order
|
|
2814
|
+
}
|
|
2815
|
+
});
|
|
2816
|
+
if (result.status === 200) {
|
|
2817
|
+
return result.body;
|
|
2793
2818
|
}
|
|
2794
|
-
|
|
2819
|
+
const errorBody = result.body;
|
|
2820
|
+
const message = errorBody.error?.message || "Failed to fetch agent events";
|
|
2821
|
+
throw new Error(message);
|
|
2795
2822
|
}
|
|
2796
2823
|
async getNetworkLogs(runId, options) {
|
|
2797
2824
|
const baseUrl = await this.getBaseUrl();
|
|
2798
2825
|
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
|
|
2826
|
+
const client = initClient(runNetworkLogsContract, {
|
|
2827
|
+
baseUrl,
|
|
2828
|
+
baseHeaders: headers,
|
|
2829
|
+
jsonQuery: true
|
|
2814
2830
|
});
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2831
|
+
const result = await client.getNetworkLogs({
|
|
2832
|
+
params: { id: runId },
|
|
2833
|
+
query: {
|
|
2834
|
+
since: options?.since,
|
|
2835
|
+
limit: options?.limit,
|
|
2836
|
+
order: options?.order
|
|
2837
|
+
}
|
|
2838
|
+
});
|
|
2839
|
+
if (result.status === 200) {
|
|
2840
|
+
return result.body;
|
|
2818
2841
|
}
|
|
2819
|
-
|
|
2842
|
+
const errorBody = result.body;
|
|
2843
|
+
const message = errorBody.error?.message || "Failed to fetch network logs";
|
|
2844
|
+
throw new Error(message);
|
|
2820
2845
|
}
|
|
2821
2846
|
/**
|
|
2822
2847
|
* Get current user's scope
|
|
@@ -2824,15 +2849,18 @@ var ApiClient = class {
|
|
|
2824
2849
|
async getScope() {
|
|
2825
2850
|
const baseUrl = await this.getBaseUrl();
|
|
2826
2851
|
const headers = await this.getHeaders();
|
|
2827
|
-
const
|
|
2828
|
-
|
|
2829
|
-
headers
|
|
2852
|
+
const client = initClient(scopeContract, {
|
|
2853
|
+
baseUrl,
|
|
2854
|
+
baseHeaders: headers,
|
|
2855
|
+
jsonQuery: true
|
|
2830
2856
|
});
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2857
|
+
const result = await client.get();
|
|
2858
|
+
if (result.status === 200) {
|
|
2859
|
+
return result.body;
|
|
2834
2860
|
}
|
|
2835
|
-
|
|
2861
|
+
const errorBody = result.body;
|
|
2862
|
+
const message = errorBody.error?.message || "Failed to get scope";
|
|
2863
|
+
throw new Error(message);
|
|
2836
2864
|
}
|
|
2837
2865
|
/**
|
|
2838
2866
|
* Create user's scope
|
|
@@ -2840,16 +2868,18 @@ var ApiClient = class {
|
|
|
2840
2868
|
async createScope(body) {
|
|
2841
2869
|
const baseUrl = await this.getBaseUrl();
|
|
2842
2870
|
const headers = await this.getHeaders();
|
|
2843
|
-
const
|
|
2844
|
-
|
|
2845
|
-
headers,
|
|
2846
|
-
|
|
2871
|
+
const client = initClient(scopeContract, {
|
|
2872
|
+
baseUrl,
|
|
2873
|
+
baseHeaders: headers,
|
|
2874
|
+
jsonQuery: true
|
|
2847
2875
|
});
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2876
|
+
const result = await client.create({ body });
|
|
2877
|
+
if (result.status === 201) {
|
|
2878
|
+
return result.body;
|
|
2851
2879
|
}
|
|
2852
|
-
|
|
2880
|
+
const errorBody = result.body;
|
|
2881
|
+
const message = errorBody.error?.message || "Failed to create scope";
|
|
2882
|
+
throw new Error(message);
|
|
2853
2883
|
}
|
|
2854
2884
|
/**
|
|
2855
2885
|
* Update user's scope slug
|
|
@@ -2857,16 +2887,18 @@ var ApiClient = class {
|
|
|
2857
2887
|
async updateScope(body) {
|
|
2858
2888
|
const baseUrl = await this.getBaseUrl();
|
|
2859
2889
|
const headers = await this.getHeaders();
|
|
2860
|
-
const
|
|
2861
|
-
|
|
2862
|
-
headers,
|
|
2863
|
-
|
|
2890
|
+
const client = initClient(scopeContract, {
|
|
2891
|
+
baseUrl,
|
|
2892
|
+
baseHeaders: headers,
|
|
2893
|
+
jsonQuery: true
|
|
2864
2894
|
});
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2895
|
+
const result = await client.update({ body });
|
|
2896
|
+
if (result.status === 200) {
|
|
2897
|
+
return result.body;
|
|
2868
2898
|
}
|
|
2869
|
-
|
|
2899
|
+
const errorBody = result.body;
|
|
2900
|
+
const message = errorBody.error?.message || "Failed to update scope";
|
|
2901
|
+
throw new Error(message);
|
|
2870
2902
|
}
|
|
2871
2903
|
/**
|
|
2872
2904
|
* Get session by ID
|
|
@@ -2875,17 +2907,20 @@ var ApiClient = class {
|
|
|
2875
2907
|
async getSession(sessionId) {
|
|
2876
2908
|
const baseUrl = await this.getBaseUrl();
|
|
2877
2909
|
const headers = await this.getHeaders();
|
|
2878
|
-
const
|
|
2879
|
-
|
|
2880
|
-
headers
|
|
2910
|
+
const client = initClient(sessionsByIdContract, {
|
|
2911
|
+
baseUrl,
|
|
2912
|
+
baseHeaders: headers,
|
|
2913
|
+
jsonQuery: true
|
|
2881
2914
|
});
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2915
|
+
const result = await client.getById({
|
|
2916
|
+
params: { id: sessionId }
|
|
2917
|
+
});
|
|
2918
|
+
if (result.status === 200) {
|
|
2919
|
+
return result.body;
|
|
2887
2920
|
}
|
|
2888
|
-
|
|
2921
|
+
const errorBody = result.body;
|
|
2922
|
+
const message = errorBody.error?.message || `Session not found: ${sessionId}`;
|
|
2923
|
+
throw new Error(message);
|
|
2889
2924
|
}
|
|
2890
2925
|
/**
|
|
2891
2926
|
* Get checkpoint by ID
|
|
@@ -2894,20 +2929,368 @@ var ApiClient = class {
|
|
|
2894
2929
|
async getCheckpoint(checkpointId) {
|
|
2895
2930
|
const baseUrl = await this.getBaseUrl();
|
|
2896
2931
|
const headers = await this.getHeaders();
|
|
2897
|
-
const
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2932
|
+
const client = initClient(checkpointsByIdContract, {
|
|
2933
|
+
baseUrl,
|
|
2934
|
+
baseHeaders: headers,
|
|
2935
|
+
jsonQuery: true
|
|
2936
|
+
});
|
|
2937
|
+
const result = await client.getById({
|
|
2938
|
+
params: { id: checkpointId }
|
|
2939
|
+
});
|
|
2940
|
+
if (result.status === 200) {
|
|
2941
|
+
return result.body;
|
|
2942
|
+
}
|
|
2943
|
+
const errorBody = result.body;
|
|
2944
|
+
const message = errorBody.error?.message || `Checkpoint not found: ${checkpointId}`;
|
|
2945
|
+
throw new Error(message);
|
|
2946
|
+
}
|
|
2947
|
+
/**
|
|
2948
|
+
* Prepare storage for direct S3 upload
|
|
2949
|
+
*/
|
|
2950
|
+
async prepareStorage(body) {
|
|
2951
|
+
const baseUrl = await this.getBaseUrl();
|
|
2952
|
+
const headers = await this.getHeaders();
|
|
2953
|
+
const client = initClient(storagesPrepareContract, {
|
|
2954
|
+
baseUrl,
|
|
2955
|
+
baseHeaders: headers,
|
|
2956
|
+
jsonQuery: true
|
|
2957
|
+
});
|
|
2958
|
+
const result = await client.prepare({ body });
|
|
2959
|
+
if (result.status === 200) {
|
|
2960
|
+
return result.body;
|
|
2961
|
+
}
|
|
2962
|
+
const errorBody = result.body;
|
|
2963
|
+
const message = errorBody.error?.message || "Failed to prepare storage";
|
|
2964
|
+
throw new Error(message);
|
|
2965
|
+
}
|
|
2966
|
+
/**
|
|
2967
|
+
* Commit storage after S3 upload
|
|
2968
|
+
*/
|
|
2969
|
+
async commitStorage(body) {
|
|
2970
|
+
const baseUrl = await this.getBaseUrl();
|
|
2971
|
+
const headers = await this.getHeaders();
|
|
2972
|
+
const client = initClient(storagesCommitContract, {
|
|
2973
|
+
baseUrl,
|
|
2974
|
+
baseHeaders: headers,
|
|
2975
|
+
jsonQuery: true
|
|
2976
|
+
});
|
|
2977
|
+
const result = await client.commit({ body });
|
|
2978
|
+
if (result.status === 200) {
|
|
2979
|
+
return result.body;
|
|
2980
|
+
}
|
|
2981
|
+
const errorBody = result.body;
|
|
2982
|
+
const message = errorBody.error?.message || "Failed to commit storage";
|
|
2983
|
+
throw new Error(message);
|
|
2984
|
+
}
|
|
2985
|
+
/**
|
|
2986
|
+
* Get download URL for storage (volume or artifact)
|
|
2987
|
+
*/
|
|
2988
|
+
async getStorageDownload(query) {
|
|
2989
|
+
const baseUrl = await this.getBaseUrl();
|
|
2990
|
+
const headers = await this.getHeaders();
|
|
2991
|
+
const client = initClient(storagesDownloadContract, {
|
|
2992
|
+
baseUrl,
|
|
2993
|
+
baseHeaders: headers,
|
|
2994
|
+
jsonQuery: true
|
|
2995
|
+
});
|
|
2996
|
+
const result = await client.download({
|
|
2997
|
+
query: {
|
|
2998
|
+
name: query.name,
|
|
2999
|
+
type: query.type,
|
|
3000
|
+
version: query.version
|
|
2902
3001
|
}
|
|
2903
|
-
);
|
|
3002
|
+
});
|
|
3003
|
+
if (result.status === 200) {
|
|
3004
|
+
return result.body;
|
|
3005
|
+
}
|
|
3006
|
+
const errorBody = result.body;
|
|
3007
|
+
const message = errorBody.error?.message || `Storage "${query.name}" not found`;
|
|
3008
|
+
throw new Error(message);
|
|
3009
|
+
}
|
|
3010
|
+
/**
|
|
3011
|
+
* List storages (volumes or artifacts)
|
|
3012
|
+
*/
|
|
3013
|
+
async listStorages(query) {
|
|
3014
|
+
const baseUrl = await this.getBaseUrl();
|
|
3015
|
+
const headers = await this.getHeaders();
|
|
3016
|
+
const client = initClient(storagesListContract, {
|
|
3017
|
+
baseUrl,
|
|
3018
|
+
baseHeaders: headers,
|
|
3019
|
+
jsonQuery: true
|
|
3020
|
+
});
|
|
3021
|
+
const result = await client.list({ query });
|
|
3022
|
+
if (result.status === 200) {
|
|
3023
|
+
return result.body;
|
|
3024
|
+
}
|
|
3025
|
+
const errorBody = result.body;
|
|
3026
|
+
const message = errorBody.error?.message || `Failed to list ${query.type}s`;
|
|
3027
|
+
throw new Error(message);
|
|
3028
|
+
}
|
|
3029
|
+
/**
|
|
3030
|
+
* Deploy schedule (create or update)
|
|
3031
|
+
*/
|
|
3032
|
+
async deploySchedule(body) {
|
|
3033
|
+
const baseUrl = await this.getBaseUrl();
|
|
3034
|
+
const headers = await this.getHeaders();
|
|
3035
|
+
const client = initClient(schedulesMainContract, {
|
|
3036
|
+
baseUrl,
|
|
3037
|
+
baseHeaders: headers,
|
|
3038
|
+
jsonQuery: true
|
|
3039
|
+
});
|
|
3040
|
+
const result = await client.deploy({ body });
|
|
3041
|
+
if (result.status === 200 || result.status === 201) {
|
|
3042
|
+
return result.body;
|
|
3043
|
+
}
|
|
3044
|
+
const errorBody = result.body;
|
|
3045
|
+
const message = errorBody.error?.message || "Failed to deploy schedule";
|
|
3046
|
+
throw new Error(message);
|
|
3047
|
+
}
|
|
3048
|
+
/**
|
|
3049
|
+
* List all schedules
|
|
3050
|
+
*/
|
|
3051
|
+
async listSchedules() {
|
|
3052
|
+
const baseUrl = await this.getBaseUrl();
|
|
3053
|
+
const headers = await this.getHeaders();
|
|
3054
|
+
const client = initClient(schedulesMainContract, {
|
|
3055
|
+
baseUrl,
|
|
3056
|
+
baseHeaders: headers,
|
|
3057
|
+
jsonQuery: true
|
|
3058
|
+
});
|
|
3059
|
+
const result = await client.list();
|
|
3060
|
+
if (result.status === 200) {
|
|
3061
|
+
return result.body;
|
|
3062
|
+
}
|
|
3063
|
+
const errorBody = result.body;
|
|
3064
|
+
const message = errorBody.error?.message || "Failed to list schedules";
|
|
3065
|
+
throw new Error(message);
|
|
3066
|
+
}
|
|
3067
|
+
/**
|
|
3068
|
+
* Get schedule by name
|
|
3069
|
+
*/
|
|
3070
|
+
async getScheduleByName(params) {
|
|
3071
|
+
const baseUrl = await this.getBaseUrl();
|
|
3072
|
+
const headers = await this.getHeaders();
|
|
3073
|
+
const client = initClient(schedulesByNameContract, {
|
|
3074
|
+
baseUrl,
|
|
3075
|
+
baseHeaders: headers,
|
|
3076
|
+
jsonQuery: true
|
|
3077
|
+
});
|
|
3078
|
+
const result = await client.getByName({
|
|
3079
|
+
params: { name: params.name },
|
|
3080
|
+
query: { composeId: params.composeId }
|
|
3081
|
+
});
|
|
3082
|
+
if (result.status === 200) {
|
|
3083
|
+
return result.body;
|
|
3084
|
+
}
|
|
3085
|
+
const errorBody = result.body;
|
|
3086
|
+
const message = errorBody.error?.message || `Schedule "${params.name}" not found`;
|
|
3087
|
+
throw new Error(message);
|
|
3088
|
+
}
|
|
3089
|
+
/**
|
|
3090
|
+
* Delete schedule by name
|
|
3091
|
+
*/
|
|
3092
|
+
async deleteSchedule(params) {
|
|
3093
|
+
const baseUrl = await this.getBaseUrl();
|
|
3094
|
+
const headers = await this.getHeaders();
|
|
3095
|
+
const client = initClient(schedulesByNameContract, {
|
|
3096
|
+
baseUrl,
|
|
3097
|
+
baseHeaders: headers,
|
|
3098
|
+
jsonQuery: true
|
|
3099
|
+
});
|
|
3100
|
+
const result = await client.delete({
|
|
3101
|
+
params: { name: params.name },
|
|
3102
|
+
query: { composeId: params.composeId }
|
|
3103
|
+
});
|
|
3104
|
+
if (result.status === 204) {
|
|
3105
|
+
return;
|
|
3106
|
+
}
|
|
3107
|
+
const errorBody = result.body;
|
|
3108
|
+
const message = errorBody.error?.message || `Schedule "${params.name}" not found on remote`;
|
|
3109
|
+
throw new Error(message);
|
|
3110
|
+
}
|
|
3111
|
+
/**
|
|
3112
|
+
* Enable schedule
|
|
3113
|
+
*/
|
|
3114
|
+
async enableSchedule(params) {
|
|
3115
|
+
const baseUrl = await this.getBaseUrl();
|
|
3116
|
+
const headers = await this.getHeaders();
|
|
3117
|
+
const client = initClient(schedulesEnableContract, {
|
|
3118
|
+
baseUrl,
|
|
3119
|
+
baseHeaders: headers,
|
|
3120
|
+
jsonQuery: true
|
|
3121
|
+
});
|
|
3122
|
+
const result = await client.enable({
|
|
3123
|
+
params: { name: params.name },
|
|
3124
|
+
body: { composeId: params.composeId }
|
|
3125
|
+
});
|
|
3126
|
+
if (result.status === 200) {
|
|
3127
|
+
return result.body;
|
|
3128
|
+
}
|
|
3129
|
+
const errorBody = result.body;
|
|
3130
|
+
const message = errorBody.error?.message || `Failed to enable schedule "${params.name}"`;
|
|
3131
|
+
throw new Error(message);
|
|
3132
|
+
}
|
|
3133
|
+
/**
|
|
3134
|
+
* Disable schedule
|
|
3135
|
+
*/
|
|
3136
|
+
async disableSchedule(params) {
|
|
3137
|
+
const baseUrl = await this.getBaseUrl();
|
|
3138
|
+
const headers = await this.getHeaders();
|
|
3139
|
+
const client = initClient(schedulesEnableContract, {
|
|
3140
|
+
baseUrl,
|
|
3141
|
+
baseHeaders: headers,
|
|
3142
|
+
jsonQuery: true
|
|
3143
|
+
});
|
|
3144
|
+
const result = await client.disable({
|
|
3145
|
+
params: { name: params.name },
|
|
3146
|
+
body: { composeId: params.composeId }
|
|
3147
|
+
});
|
|
3148
|
+
if (result.status === 200) {
|
|
3149
|
+
return result.body;
|
|
3150
|
+
}
|
|
3151
|
+
const errorBody = result.body;
|
|
3152
|
+
const message = errorBody.error?.message || `Failed to disable schedule "${params.name}"`;
|
|
3153
|
+
throw new Error(message);
|
|
3154
|
+
}
|
|
3155
|
+
/**
|
|
3156
|
+
* List recent runs for a schedule
|
|
3157
|
+
*/
|
|
3158
|
+
async listScheduleRuns(params) {
|
|
3159
|
+
const baseUrl = await this.getBaseUrl();
|
|
3160
|
+
const headers = await this.getHeaders();
|
|
3161
|
+
const client = initClient(scheduleRunsContract, {
|
|
3162
|
+
baseUrl,
|
|
3163
|
+
baseHeaders: headers,
|
|
3164
|
+
jsonQuery: true
|
|
3165
|
+
});
|
|
3166
|
+
const result = await client.listRuns({
|
|
3167
|
+
params: { name: params.name },
|
|
3168
|
+
query: {
|
|
3169
|
+
composeId: params.composeId,
|
|
3170
|
+
limit: params.limit ?? 5
|
|
3171
|
+
}
|
|
3172
|
+
});
|
|
3173
|
+
if (result.status === 200) {
|
|
3174
|
+
return result.body;
|
|
3175
|
+
}
|
|
3176
|
+
const errorBody = result.body;
|
|
3177
|
+
const message = errorBody.error?.message || `Failed to list runs for schedule "${params.name}"`;
|
|
3178
|
+
throw new Error(message);
|
|
3179
|
+
}
|
|
3180
|
+
/**
|
|
3181
|
+
* List public agents
|
|
3182
|
+
*/
|
|
3183
|
+
async listPublicAgents(query) {
|
|
3184
|
+
const baseUrl = await this.getBaseUrl();
|
|
3185
|
+
const headers = await this.getHeaders();
|
|
3186
|
+
const client = initClient(publicAgentsListContract, {
|
|
3187
|
+
baseUrl,
|
|
3188
|
+
baseHeaders: headers,
|
|
3189
|
+
jsonQuery: true
|
|
3190
|
+
});
|
|
3191
|
+
const result = await client.list({ query: query ?? {} });
|
|
3192
|
+
if (result.status === 200) {
|
|
3193
|
+
return result.body;
|
|
3194
|
+
}
|
|
3195
|
+
const errorBody = result.body;
|
|
3196
|
+
const message = errorBody.error?.message || "Failed to list agents";
|
|
3197
|
+
throw new Error(message);
|
|
3198
|
+
}
|
|
3199
|
+
/**
|
|
3200
|
+
* List public artifacts
|
|
3201
|
+
*/
|
|
3202
|
+
async listPublicArtifacts(query) {
|
|
3203
|
+
const baseUrl = await this.getBaseUrl();
|
|
3204
|
+
const headers = await this.getHeaders();
|
|
3205
|
+
const client = initClient(publicArtifactsListContract, {
|
|
3206
|
+
baseUrl,
|
|
3207
|
+
baseHeaders: headers,
|
|
3208
|
+
jsonQuery: true
|
|
3209
|
+
});
|
|
3210
|
+
const result = await client.list({ query: query ?? {} });
|
|
3211
|
+
if (result.status === 200) {
|
|
3212
|
+
return result.body;
|
|
3213
|
+
}
|
|
3214
|
+
const errorBody = result.body;
|
|
3215
|
+
const message = errorBody.error?.message || "Failed to list artifacts";
|
|
3216
|
+
throw new Error(message);
|
|
3217
|
+
}
|
|
3218
|
+
/**
|
|
3219
|
+
* Get public artifact by ID
|
|
3220
|
+
*/
|
|
3221
|
+
async getPublicArtifact(id) {
|
|
3222
|
+
const baseUrl = await this.getBaseUrl();
|
|
3223
|
+
const headers = await this.getHeaders();
|
|
3224
|
+
const client = initClient(publicArtifactByIdContract, {
|
|
3225
|
+
baseUrl,
|
|
3226
|
+
baseHeaders: headers,
|
|
3227
|
+
jsonQuery: true
|
|
3228
|
+
});
|
|
3229
|
+
const result = await client.get({ params: { id } });
|
|
3230
|
+
if (result.status === 200) {
|
|
3231
|
+
return result.body;
|
|
3232
|
+
}
|
|
3233
|
+
const errorBody = result.body;
|
|
3234
|
+
const message = errorBody.error?.message || `Artifact "${id}" not found`;
|
|
3235
|
+
throw new Error(message);
|
|
3236
|
+
}
|
|
3237
|
+
/**
|
|
3238
|
+
* List public volumes
|
|
3239
|
+
*/
|
|
3240
|
+
async listPublicVolumes(query) {
|
|
3241
|
+
const baseUrl = await this.getBaseUrl();
|
|
3242
|
+
const headers = await this.getHeaders();
|
|
3243
|
+
const client = initClient(publicVolumesListContract, {
|
|
3244
|
+
baseUrl,
|
|
3245
|
+
baseHeaders: headers,
|
|
3246
|
+
jsonQuery: true
|
|
3247
|
+
});
|
|
3248
|
+
const result = await client.list({ query: query ?? {} });
|
|
3249
|
+
if (result.status === 200) {
|
|
3250
|
+
return result.body;
|
|
3251
|
+
}
|
|
3252
|
+
const errorBody = result.body;
|
|
3253
|
+
const message = errorBody.error?.message || "Failed to list volumes";
|
|
3254
|
+
throw new Error(message);
|
|
3255
|
+
}
|
|
3256
|
+
/**
|
|
3257
|
+
* Get public volume by ID
|
|
3258
|
+
*/
|
|
3259
|
+
async getPublicVolume(id) {
|
|
3260
|
+
const baseUrl = await this.getBaseUrl();
|
|
3261
|
+
const headers = await this.getHeaders();
|
|
3262
|
+
const client = initClient(publicVolumeByIdContract, {
|
|
3263
|
+
baseUrl,
|
|
3264
|
+
baseHeaders: headers,
|
|
3265
|
+
jsonQuery: true
|
|
3266
|
+
});
|
|
3267
|
+
const result = await client.get({ params: { id } });
|
|
3268
|
+
if (result.status === 200) {
|
|
3269
|
+
return result.body;
|
|
3270
|
+
}
|
|
3271
|
+
const errorBody = result.body;
|
|
3272
|
+
const message = errorBody.error?.message || `Volume "${id}" not found`;
|
|
3273
|
+
throw new Error(message);
|
|
3274
|
+
}
|
|
3275
|
+
/**
|
|
3276
|
+
* Get usage statistics
|
|
3277
|
+
*/
|
|
3278
|
+
async getUsage(options) {
|
|
3279
|
+
const baseUrl = await this.getBaseUrl();
|
|
3280
|
+
const headers = await this.getHeaders();
|
|
3281
|
+
const params = new URLSearchParams({
|
|
3282
|
+
start_date: options.startDate,
|
|
3283
|
+
end_date: options.endDate
|
|
3284
|
+
});
|
|
3285
|
+
const response = await fetch(`${baseUrl}/api/usage?${params}`, {
|
|
3286
|
+
method: "GET",
|
|
3287
|
+
headers
|
|
3288
|
+
});
|
|
2904
3289
|
if (!response.ok) {
|
|
2905
3290
|
const error = await response.json();
|
|
2906
|
-
throw new Error(
|
|
2907
|
-
error.error?.message || `Checkpoint not found: ${checkpointId}`
|
|
2908
|
-
);
|
|
3291
|
+
throw new Error(error.error?.message || "Failed to fetch usage data");
|
|
2909
3292
|
}
|
|
2910
|
-
return
|
|
3293
|
+
return response.json();
|
|
2911
3294
|
}
|
|
2912
3295
|
/**
|
|
2913
3296
|
* Generic GET request
|
|
@@ -3549,34 +3932,20 @@ async function directUpload(storageName, storageType, cwd, options) {
|
|
|
3549
3932
|
onProgress?.("Computing file hashes...");
|
|
3550
3933
|
const fileEntries = await collectFileMetadata(cwd, files, onProgress);
|
|
3551
3934
|
onProgress?.("Preparing upload...");
|
|
3552
|
-
const
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
force
|
|
3558
|
-
})
|
|
3935
|
+
const prepareResult = await apiClient.prepareStorage({
|
|
3936
|
+
storageName,
|
|
3937
|
+
storageType,
|
|
3938
|
+
files: fileEntries,
|
|
3939
|
+
force
|
|
3559
3940
|
});
|
|
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
3941
|
if (prepareResult.existing) {
|
|
3566
3942
|
onProgress?.("Version exists, updating HEAD...");
|
|
3567
|
-
const
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
files: fileEntries
|
|
3573
|
-
})
|
|
3943
|
+
const commitResult2 = await apiClient.commitStorage({
|
|
3944
|
+
storageName,
|
|
3945
|
+
storageType,
|
|
3946
|
+
versionId: prepareResult.versionId,
|
|
3947
|
+
files: fileEntries
|
|
3574
3948
|
});
|
|
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
3949
|
return {
|
|
3581
3950
|
versionId: commitResult2.versionId,
|
|
3582
3951
|
size: commitResult2.size,
|
|
@@ -3609,19 +3978,12 @@ async function directUpload(storageName, storageType, cwd, options) {
|
|
|
3609
3978
|
"application/json"
|
|
3610
3979
|
);
|
|
3611
3980
|
onProgress?.("Committing...");
|
|
3612
|
-
const
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
files: fileEntries
|
|
3618
|
-
})
|
|
3981
|
+
const commitResult = await apiClient.commitStorage({
|
|
3982
|
+
storageName,
|
|
3983
|
+
storageType,
|
|
3984
|
+
versionId: prepareResult.versionId,
|
|
3985
|
+
files: fileEntries
|
|
3619
3986
|
});
|
|
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
3987
|
return {
|
|
3626
3988
|
versionId: commitResult.versionId,
|
|
3627
3989
|
size: commitResult.size,
|
|
@@ -4777,7 +5139,7 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
4777
5139
|
).option(
|
|
4778
5140
|
"--conversation <id>",
|
|
4779
5141
|
"Resume from conversation ID (for fine-grained control)"
|
|
4780
|
-
).option("-v, --verbose", "Show verbose output with timing information").action(
|
|
5142
|
+
).option("-v, --verbose", "Show verbose output with timing information").option("--debug-no-mock-claude").action(
|
|
4781
5143
|
async (identifier, prompt, options) => {
|
|
4782
5144
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
4783
5145
|
const verbose = options.verbose;
|
|
@@ -4878,7 +5240,8 @@ var runCmd = new Command2().name("run").description("Execute an agent").argument
|
|
|
4878
5240
|
artifactName: options.artifactName,
|
|
4879
5241
|
artifactVersion: options.artifactVersion,
|
|
4880
5242
|
volumeVersions: Object.keys(options.volumeVersion).length > 0 ? options.volumeVersion : void 0,
|
|
4881
|
-
conversationId: options.conversation
|
|
5243
|
+
conversationId: options.conversation,
|
|
5244
|
+
debugNoMockClaude: options.debugNoMockClaude || void 0
|
|
4882
5245
|
});
|
|
4883
5246
|
if (response.status === "failed") {
|
|
4884
5247
|
console.error(chalk5.red("\u2717 Run preparation failed"));
|
|
@@ -4943,7 +5306,7 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
4943
5306
|
"Volume version override (repeatable)",
|
|
4944
5307
|
collectVolumeVersions,
|
|
4945
5308
|
{}
|
|
4946
|
-
).option("-v, --verbose", "Show verbose output with timing information").action(
|
|
5309
|
+
).option("-v, --verbose", "Show verbose output with timing information").option("--debug-no-mock-claude").action(
|
|
4947
5310
|
async (checkpointId, prompt, options, command) => {
|
|
4948
5311
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
4949
5312
|
const allOpts = command.optsWithGlobals();
|
|
@@ -4984,7 +5347,8 @@ runCmd.command("resume").description("Resume an agent run from a checkpoint (use
|
|
|
4984
5347
|
prompt,
|
|
4985
5348
|
vars: Object.keys(vars).length > 0 ? vars : void 0,
|
|
4986
5349
|
secrets: loadedSecrets,
|
|
4987
|
-
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0
|
|
5350
|
+
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0,
|
|
5351
|
+
debugNoMockClaude: options.debugNoMockClaude || allOpts.debugNoMockClaude || void 0
|
|
4988
5352
|
});
|
|
4989
5353
|
if (response.status === "failed") {
|
|
4990
5354
|
console.error(chalk5.red("\u2717 Run preparation failed"));
|
|
@@ -5041,7 +5405,7 @@ runCmd.command("continue").description(
|
|
|
5041
5405
|
"Volume version override (repeatable)",
|
|
5042
5406
|
collectVolumeVersions,
|
|
5043
5407
|
{}
|
|
5044
|
-
).option("-v, --verbose", "Show verbose output with timing information").action(
|
|
5408
|
+
).option("-v, --verbose", "Show verbose output with timing information").option("--debug-no-mock-claude").action(
|
|
5045
5409
|
async (agentSessionId, prompt, options, command) => {
|
|
5046
5410
|
const startTimestamp = /* @__PURE__ */ new Date();
|
|
5047
5411
|
const allOpts = command.optsWithGlobals();
|
|
@@ -5083,7 +5447,8 @@ runCmd.command("continue").description(
|
|
|
5083
5447
|
prompt,
|
|
5084
5448
|
vars: Object.keys(vars).length > 0 ? vars : void 0,
|
|
5085
5449
|
secrets: loadedSecrets,
|
|
5086
|
-
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0
|
|
5450
|
+
volumeVersions: Object.keys(allOpts.volumeVersion).length > 0 ? allOpts.volumeVersion : void 0,
|
|
5451
|
+
debugNoMockClaude: options.debugNoMockClaude || allOpts.debugNoMockClaude || void 0
|
|
5087
5452
|
});
|
|
5088
5453
|
if (response.status === "failed") {
|
|
5089
5454
|
console.error(chalk5.red("\u2717 Run preparation failed"));
|
|
@@ -5415,39 +5780,21 @@ var pullCommand = new Command5().name("pull").description("Pull cloud files to l
|
|
|
5415
5780
|
console.log(`Pulling volume: ${config.name}`);
|
|
5416
5781
|
}
|
|
5417
5782
|
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) {
|
|
5783
|
+
const downloadInfo = await apiClient.getStorageDownload({
|
|
5784
|
+
name: config.name,
|
|
5785
|
+
type: "volume",
|
|
5786
|
+
version: versionId
|
|
5787
|
+
});
|
|
5788
|
+
if ("empty" in downloadInfo) {
|
|
5443
5789
|
await handleEmptyStorageResponse(cwd);
|
|
5444
5790
|
return;
|
|
5445
5791
|
}
|
|
5446
|
-
|
|
5792
|
+
const downloadUrl = downloadInfo.url;
|
|
5793
|
+
if (!downloadUrl) {
|
|
5447
5794
|
throw new Error("No download URL returned");
|
|
5448
5795
|
}
|
|
5449
5796
|
console.log(chalk9.dim("Downloading from S3..."));
|
|
5450
|
-
const s3Response = await fetch(
|
|
5797
|
+
const s3Response = await fetch(downloadUrl);
|
|
5451
5798
|
if (!s3Response.ok) {
|
|
5452
5799
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
5453
5800
|
}
|
|
@@ -5519,21 +5866,12 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5519
5866
|
process.exit(1);
|
|
5520
5867
|
}
|
|
5521
5868
|
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();
|
|
5869
|
+
const info = await apiClient.getStorageDownload({
|
|
5870
|
+
name: config.name,
|
|
5871
|
+
type: "volume"
|
|
5872
|
+
});
|
|
5535
5873
|
const shortVersion = info.versionId.slice(0, 8);
|
|
5536
|
-
if (info
|
|
5874
|
+
if ("empty" in info) {
|
|
5537
5875
|
console.log(chalk10.green("\u2713 Found (empty)"));
|
|
5538
5876
|
console.log(chalk10.dim(` Version: ${shortVersion}`));
|
|
5539
5877
|
} else {
|
|
@@ -5543,12 +5881,17 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5543
5881
|
console.log(chalk10.dim(` Size: ${formatBytes4(info.size)}`));
|
|
5544
5882
|
}
|
|
5545
5883
|
} catch (error) {
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5884
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
5885
|
+
console.error(chalk10.red("\u2717 Not found on remote"));
|
|
5886
|
+
console.error(chalk10.dim(" Run: vm0 volume push"));
|
|
5887
|
+
} else {
|
|
5888
|
+
console.error(chalk10.red("\u2717 Status check failed"));
|
|
5889
|
+
if (error instanceof Error) {
|
|
5890
|
+
if (error.message.includes("Not authenticated")) {
|
|
5891
|
+
console.error(chalk10.dim(" Run: vm0 auth login"));
|
|
5892
|
+
} else {
|
|
5893
|
+
console.error(chalk10.dim(` ${error.message}`));
|
|
5894
|
+
}
|
|
5552
5895
|
}
|
|
5553
5896
|
}
|
|
5554
5897
|
process.exit(1);
|
|
@@ -5558,15 +5901,9 @@ var statusCommand = new Command6().name("status").description("Show status of cl
|
|
|
5558
5901
|
// src/commands/volume/list.ts
|
|
5559
5902
|
import { Command as Command7 } from "commander";
|
|
5560
5903
|
import chalk11 from "chalk";
|
|
5561
|
-
var listCommand = new Command7().name("list").alias("ls").description("List all remote volumes").action(async () => {
|
|
5562
|
-
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();
|
|
5904
|
+
var listCommand = new Command7().name("list").alias("ls").description("List all remote volumes").action(async () => {
|
|
5905
|
+
try {
|
|
5906
|
+
const items = await apiClient.listStorages({ type: "volume" });
|
|
5570
5907
|
if (items.length === 0) {
|
|
5571
5908
|
console.log(chalk11.dim("No volumes found"));
|
|
5572
5909
|
console.log(
|
|
@@ -5628,25 +5965,14 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5628
5965
|
throw new Error(`Directory "${destination}" already exists`);
|
|
5629
5966
|
}
|
|
5630
5967
|
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();
|
|
5968
|
+
const downloadInfo = await apiClient.getStorageDownload({
|
|
5969
|
+
name,
|
|
5970
|
+
type,
|
|
5971
|
+
version: options.version
|
|
5972
|
+
});
|
|
5647
5973
|
console.log(chalk12.dim(`Creating directory: ${destination}/`));
|
|
5648
5974
|
await fs7.promises.mkdir(destination, { recursive: true });
|
|
5649
|
-
if (downloadInfo
|
|
5975
|
+
if ("empty" in downloadInfo) {
|
|
5650
5976
|
await writeStorageConfig(name, destination, type);
|
|
5651
5977
|
console.log(chalk12.green(`\u2713 Cloned empty ${typeLabel}: ${name}`));
|
|
5652
5978
|
console.log(chalk12.dim(`\u2713 Initialized .vm0/storage.yaml`));
|
|
@@ -5657,11 +5983,12 @@ async function cloneStorage(name, type, destination, options = {}) {
|
|
|
5657
5983
|
versionId: downloadInfo.versionId
|
|
5658
5984
|
};
|
|
5659
5985
|
}
|
|
5660
|
-
|
|
5986
|
+
const downloadUrl = downloadInfo.url;
|
|
5987
|
+
if (!downloadUrl) {
|
|
5661
5988
|
throw new Error("No download URL returned");
|
|
5662
5989
|
}
|
|
5663
5990
|
console.log(chalk12.dim("Downloading from S3..."));
|
|
5664
|
-
const s3Response = await fetch(
|
|
5991
|
+
const s3Response = await fetch(downloadUrl);
|
|
5665
5992
|
if (!s3Response.ok) {
|
|
5666
5993
|
await fs7.promises.rm(destination, { recursive: true, force: true });
|
|
5667
5994
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
@@ -5910,39 +6237,21 @@ var pullCommand2 = new Command12().name("pull").description("Pull cloud artifact
|
|
|
5910
6237
|
console.log(`Pulling artifact: ${config.name}`);
|
|
5911
6238
|
}
|
|
5912
6239
|
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) {
|
|
6240
|
+
const downloadInfo = await apiClient.getStorageDownload({
|
|
6241
|
+
name: config.name,
|
|
6242
|
+
type: "artifact",
|
|
6243
|
+
version: versionId
|
|
6244
|
+
});
|
|
6245
|
+
if ("empty" in downloadInfo) {
|
|
5938
6246
|
await handleEmptyStorageResponse(cwd);
|
|
5939
6247
|
return;
|
|
5940
6248
|
}
|
|
5941
|
-
|
|
6249
|
+
const downloadUrl = downloadInfo.url;
|
|
6250
|
+
if (!downloadUrl) {
|
|
5942
6251
|
throw new Error("No download URL returned");
|
|
5943
6252
|
}
|
|
5944
6253
|
console.log(chalk16.dim("Downloading from S3..."));
|
|
5945
|
-
const s3Response = await fetch(
|
|
6254
|
+
const s3Response = await fetch(downloadUrl);
|
|
5946
6255
|
if (!s3Response.ok) {
|
|
5947
6256
|
throw new Error(`S3 download failed: ${s3Response.status}`);
|
|
5948
6257
|
}
|
|
@@ -6010,21 +6319,12 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6010
6319
|
process.exit(1);
|
|
6011
6320
|
}
|
|
6012
6321
|
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();
|
|
6322
|
+
const info = await apiClient.getStorageDownload({
|
|
6323
|
+
name: config.name,
|
|
6324
|
+
type: "artifact"
|
|
6325
|
+
});
|
|
6026
6326
|
const shortVersion = info.versionId.slice(0, 8);
|
|
6027
|
-
if (info
|
|
6327
|
+
if ("empty" in info) {
|
|
6028
6328
|
console.log(chalk17.green("\u2713 Found (empty)"));
|
|
6029
6329
|
console.log(chalk17.dim(` Version: ${shortVersion}`));
|
|
6030
6330
|
} else {
|
|
@@ -6034,9 +6334,14 @@ var statusCommand2 = new Command13().name("status").description("Show status of
|
|
|
6034
6334
|
console.log(chalk17.dim(` Size: ${formatBytes7(info.size)}`));
|
|
6035
6335
|
}
|
|
6036
6336
|
} catch (error) {
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
console.error(chalk17.dim(
|
|
6337
|
+
if (error instanceof Error && error.message.includes("not found")) {
|
|
6338
|
+
console.error(chalk17.red("\u2717 Not found on remote"));
|
|
6339
|
+
console.error(chalk17.dim(" Run: vm0 artifact push"));
|
|
6340
|
+
} else {
|
|
6341
|
+
console.error(chalk17.red("\u2717 Status check failed"));
|
|
6342
|
+
if (error instanceof Error) {
|
|
6343
|
+
console.error(chalk17.dim(` ${error.message}`));
|
|
6344
|
+
}
|
|
6040
6345
|
}
|
|
6041
6346
|
process.exit(1);
|
|
6042
6347
|
}
|
|
@@ -6047,13 +6352,7 @@ import { Command as Command14 } from "commander";
|
|
|
6047
6352
|
import chalk18 from "chalk";
|
|
6048
6353
|
var listCommand2 = new Command14().name("list").alias("ls").description("List all remote artifacts").action(async () => {
|
|
6049
6354
|
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();
|
|
6355
|
+
const items = await apiClient.listStorages({ type: "artifact" });
|
|
6057
6356
|
if (items.length === 0) {
|
|
6058
6357
|
console.log(chalk18.dim("No artifacts found"));
|
|
6059
6358
|
console.log(
|
|
@@ -6471,180 +6770,186 @@ async function autoPullArtifact(runOutput, artifactDir) {
|
|
|
6471
6770
|
}
|
|
6472
6771
|
}
|
|
6473
6772
|
var cookCmd = new Command17().name("cook").description("One-click agent preparation and execution from vm0.yaml");
|
|
6474
|
-
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").action(
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
const cwd = process.cwd();
|
|
6480
|
-
console.log(chalk21.bold(`Reading config: ${CONFIG_FILE3}`));
|
|
6481
|
-
if (!existsSync8(CONFIG_FILE3)) {
|
|
6482
|
-
console.error(chalk21.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
|
|
6483
|
-
process.exit(1);
|
|
6484
|
-
}
|
|
6485
|
-
let config;
|
|
6486
|
-
try {
|
|
6487
|
-
const content = await readFile7(CONFIG_FILE3, "utf8");
|
|
6488
|
-
config = parseYaml4(content);
|
|
6489
|
-
} catch (error) {
|
|
6490
|
-
console.error(chalk21.red("\u2717 Invalid YAML format"));
|
|
6491
|
-
if (error instanceof Error) {
|
|
6492
|
-
console.error(chalk21.dim(` ${error.message}`));
|
|
6773
|
+
cookCmd.argument("[prompt]", "Prompt for the agent").option("-y, --yes", "Skip confirmation prompts").option("--debug-no-mock-claude").action(
|
|
6774
|
+
async (prompt, options) => {
|
|
6775
|
+
const shouldExit = await checkAndUpgrade("5.8.0", prompt);
|
|
6776
|
+
if (shouldExit) {
|
|
6777
|
+
process.exit(0);
|
|
6493
6778
|
}
|
|
6494
|
-
process.
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
if (requiredVarNames.length > 0) {
|
|
6509
|
-
const envFilePath = path12.join(cwd, ".env");
|
|
6510
|
-
const missingVars = checkMissingVariables(requiredVarNames, envFilePath);
|
|
6511
|
-
if (missingVars.length > 0) {
|
|
6512
|
-
await generateEnvPlaceholders(missingVars, envFilePath);
|
|
6513
|
-
console.log();
|
|
6514
|
-
console.log(
|
|
6515
|
-
chalk21.yellow(
|
|
6516
|
-
`\u26A0 Missing environment variables. Please fill in values in .env file:`
|
|
6517
|
-
)
|
|
6518
|
-
);
|
|
6519
|
-
for (const varName of missingVars) {
|
|
6520
|
-
console.log(chalk21.yellow(` ${varName}`));
|
|
6779
|
+
const cwd = process.cwd();
|
|
6780
|
+
console.log(chalk21.bold(`Reading config: ${CONFIG_FILE3}`));
|
|
6781
|
+
if (!existsSync8(CONFIG_FILE3)) {
|
|
6782
|
+
console.error(chalk21.red(`\u2717 Config file not found: ${CONFIG_FILE3}`));
|
|
6783
|
+
process.exit(1);
|
|
6784
|
+
}
|
|
6785
|
+
let config;
|
|
6786
|
+
try {
|
|
6787
|
+
const content = await readFile7(CONFIG_FILE3, "utf8");
|
|
6788
|
+
config = parseYaml4(content);
|
|
6789
|
+
} catch (error) {
|
|
6790
|
+
console.error(chalk21.red("\u2717 Invalid YAML format"));
|
|
6791
|
+
if (error instanceof Error) {
|
|
6792
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6521
6793
|
}
|
|
6522
6794
|
process.exit(1);
|
|
6523
6795
|
}
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6796
|
+
const validation = validateAgentCompose(config);
|
|
6797
|
+
if (!validation.valid) {
|
|
6798
|
+
console.error(chalk21.red(`\u2717 ${validation.error}`));
|
|
6799
|
+
process.exit(1);
|
|
6800
|
+
}
|
|
6801
|
+
const agentNames = Object.keys(config.agents);
|
|
6802
|
+
const agentName = agentNames[0];
|
|
6803
|
+
const volumeCount = config.volumes ? Object.keys(config.volumes).length : 0;
|
|
6804
|
+
console.log(
|
|
6805
|
+
chalk21.green(`\u2713 Config validated: 1 agent, ${volumeCount} volume(s)`)
|
|
6806
|
+
);
|
|
6807
|
+
const requiredVarNames = extractRequiredVarNames(config);
|
|
6808
|
+
if (requiredVarNames.length > 0) {
|
|
6809
|
+
const envFilePath = path12.join(cwd, ".env");
|
|
6810
|
+
const missingVars = checkMissingVariables(
|
|
6811
|
+
requiredVarNames,
|
|
6812
|
+
envFilePath
|
|
6813
|
+
);
|
|
6814
|
+
if (missingVars.length > 0) {
|
|
6815
|
+
await generateEnvPlaceholders(missingVars, envFilePath);
|
|
6816
|
+
console.log();
|
|
6817
|
+
console.log(
|
|
6818
|
+
chalk21.yellow(
|
|
6819
|
+
`\u26A0 Missing environment variables. Please fill in values in .env file:`
|
|
6534
6820
|
)
|
|
6535
6821
|
);
|
|
6822
|
+
for (const varName of missingVars) {
|
|
6823
|
+
console.log(chalk21.yellow(` ${varName}`));
|
|
6824
|
+
}
|
|
6536
6825
|
process.exit(1);
|
|
6537
6826
|
}
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6827
|
+
}
|
|
6828
|
+
if (config.volumes && Object.keys(config.volumes).length > 0) {
|
|
6829
|
+
console.log();
|
|
6830
|
+
console.log(chalk21.bold("Processing volumes:"));
|
|
6831
|
+
for (const volumeConfig of Object.values(config.volumes)) {
|
|
6832
|
+
const volumeDir = path12.join(cwd, volumeConfig.name);
|
|
6833
|
+
if (!existsSync8(volumeDir)) {
|
|
6834
|
+
console.error(
|
|
6835
|
+
chalk21.red(
|
|
6836
|
+
`\u2717 Directory not found: ${volumeConfig.name}. Create the directory and add files first.`
|
|
6837
|
+
)
|
|
6549
6838
|
);
|
|
6839
|
+
process.exit(1);
|
|
6550
6840
|
}
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6841
|
+
try {
|
|
6842
|
+
printCommand(`cd ${volumeConfig.name}`);
|
|
6843
|
+
const existingConfig = await readStorageConfig(volumeDir);
|
|
6844
|
+
if (!existingConfig) {
|
|
6845
|
+
printCommand(`vm0 volume init --name ${volumeConfig.name}`);
|
|
6846
|
+
await execVm0Command(
|
|
6847
|
+
["volume", "init", "--name", volumeConfig.name],
|
|
6848
|
+
{
|
|
6849
|
+
cwd: volumeDir,
|
|
6850
|
+
silent: true
|
|
6851
|
+
}
|
|
6852
|
+
);
|
|
6853
|
+
}
|
|
6854
|
+
printCommand("vm0 volume push");
|
|
6855
|
+
await execVm0Command(["volume", "push"], {
|
|
6856
|
+
cwd: volumeDir,
|
|
6857
|
+
silent: true
|
|
6858
|
+
});
|
|
6859
|
+
printCommand("cd ..");
|
|
6860
|
+
} catch (error) {
|
|
6861
|
+
console.error(chalk21.red(`\u2717 Failed`));
|
|
6862
|
+
if (error instanceof Error) {
|
|
6863
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6864
|
+
}
|
|
6865
|
+
process.exit(1);
|
|
6561
6866
|
}
|
|
6562
|
-
process.exit(1);
|
|
6563
6867
|
}
|
|
6564
6868
|
}
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6869
|
+
console.log();
|
|
6870
|
+
console.log(chalk21.bold("Processing artifact:"));
|
|
6871
|
+
const artifactDir = path12.join(cwd, ARTIFACT_DIR);
|
|
6872
|
+
try {
|
|
6873
|
+
if (!existsSync8(artifactDir)) {
|
|
6874
|
+
printCommand(`mkdir ${ARTIFACT_DIR}`);
|
|
6875
|
+
await mkdir6(artifactDir, { recursive: true });
|
|
6876
|
+
}
|
|
6877
|
+
printCommand(`cd ${ARTIFACT_DIR}`);
|
|
6878
|
+
const existingConfig = await readStorageConfig(artifactDir);
|
|
6879
|
+
if (!existingConfig) {
|
|
6880
|
+
printCommand(`vm0 artifact init --name ${ARTIFACT_DIR}`);
|
|
6881
|
+
await execVm0Command(["artifact", "init", "--name", ARTIFACT_DIR], {
|
|
6882
|
+
cwd: artifactDir,
|
|
6883
|
+
silent: true
|
|
6884
|
+
});
|
|
6885
|
+
}
|
|
6886
|
+
printCommand("vm0 artifact push");
|
|
6887
|
+
await execVm0Command(["artifact", "push"], {
|
|
6579
6888
|
cwd: artifactDir,
|
|
6580
6889
|
silent: true
|
|
6581
6890
|
});
|
|
6891
|
+
printCommand("cd ..");
|
|
6892
|
+
} catch (error) {
|
|
6893
|
+
console.error(chalk21.red(`\u2717 Failed`));
|
|
6894
|
+
if (error instanceof Error) {
|
|
6895
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6896
|
+
}
|
|
6897
|
+
process.exit(1);
|
|
6582
6898
|
}
|
|
6583
|
-
printCommand("vm0 artifact push");
|
|
6584
|
-
await execVm0Command(["artifact", "push"], {
|
|
6585
|
-
cwd: artifactDir,
|
|
6586
|
-
silent: true
|
|
6587
|
-
});
|
|
6588
|
-
printCommand("cd ..");
|
|
6589
|
-
} catch (error) {
|
|
6590
|
-
console.error(chalk21.red(`\u2717 Failed`));
|
|
6591
|
-
if (error instanceof Error) {
|
|
6592
|
-
console.error(chalk21.dim(` ${error.message}`));
|
|
6593
|
-
}
|
|
6594
|
-
process.exit(1);
|
|
6595
|
-
}
|
|
6596
|
-
console.log();
|
|
6597
|
-
console.log(chalk21.bold("Composing agent:"));
|
|
6598
|
-
const composeArgs = options.yes ? ["compose", "--yes", CONFIG_FILE3] : ["compose", CONFIG_FILE3];
|
|
6599
|
-
printCommand(`vm0 ${composeArgs.join(" ")}`);
|
|
6600
|
-
try {
|
|
6601
|
-
await execVm0Command(composeArgs, {
|
|
6602
|
-
cwd
|
|
6603
|
-
});
|
|
6604
|
-
} catch (error) {
|
|
6605
|
-
console.error(chalk21.red(`\u2717 Compose failed`));
|
|
6606
|
-
if (error instanceof Error) {
|
|
6607
|
-
console.error(chalk21.dim(` ${error.message}`));
|
|
6608
|
-
}
|
|
6609
|
-
process.exit(1);
|
|
6610
|
-
}
|
|
6611
|
-
if (prompt) {
|
|
6612
|
-
console.log();
|
|
6613
|
-
console.log(chalk21.bold("Running agent:"));
|
|
6614
|
-
printCommand(
|
|
6615
|
-
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
|
|
6616
|
-
);
|
|
6617
6899
|
console.log();
|
|
6618
|
-
|
|
6900
|
+
console.log(chalk21.bold("Composing agent:"));
|
|
6901
|
+
const composeArgs = options.yes ? ["compose", "--yes", CONFIG_FILE3] : ["compose", CONFIG_FILE3];
|
|
6902
|
+
printCommand(`vm0 ${composeArgs.join(" ")}`);
|
|
6619
6903
|
try {
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
} catch {
|
|
6904
|
+
await execVm0Command(composeArgs, {
|
|
6905
|
+
cwd
|
|
6906
|
+
});
|
|
6907
|
+
} catch (error) {
|
|
6908
|
+
console.error(chalk21.red(`\u2717 Compose failed`));
|
|
6909
|
+
if (error instanceof Error) {
|
|
6910
|
+
console.error(chalk21.dim(` ${error.message}`));
|
|
6911
|
+
}
|
|
6629
6912
|
process.exit(1);
|
|
6630
6913
|
}
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6914
|
+
if (prompt) {
|
|
6915
|
+
console.log();
|
|
6916
|
+
console.log(chalk21.bold("Running agent:"));
|
|
6917
|
+
printCommand(
|
|
6918
|
+
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "${prompt}"`
|
|
6919
|
+
);
|
|
6920
|
+
console.log();
|
|
6921
|
+
let runOutput;
|
|
6922
|
+
try {
|
|
6923
|
+
const runArgs = [
|
|
6924
|
+
"run",
|
|
6925
|
+
agentName,
|
|
6926
|
+
"--artifact-name",
|
|
6927
|
+
ARTIFACT_DIR,
|
|
6928
|
+
...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
6929
|
+
prompt
|
|
6930
|
+
];
|
|
6931
|
+
runOutput = await execVm0RunWithCapture(runArgs, { cwd });
|
|
6932
|
+
} catch {
|
|
6933
|
+
process.exit(1);
|
|
6934
|
+
}
|
|
6935
|
+
const runIds = parseRunIdsFromOutput(runOutput);
|
|
6936
|
+
if (runIds.runId || runIds.sessionId || runIds.checkpointId) {
|
|
6937
|
+
await saveCookState({
|
|
6938
|
+
lastRunId: runIds.runId,
|
|
6939
|
+
lastSessionId: runIds.sessionId,
|
|
6940
|
+
lastCheckpointId: runIds.checkpointId
|
|
6941
|
+
});
|
|
6942
|
+
}
|
|
6943
|
+
await autoPullArtifact(runOutput, artifactDir);
|
|
6944
|
+
} else {
|
|
6945
|
+
console.log();
|
|
6946
|
+
console.log("To run your agent:");
|
|
6947
|
+
printCommand(
|
|
6948
|
+
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "your prompt"`
|
|
6949
|
+
);
|
|
6638
6950
|
}
|
|
6639
|
-
await autoPullArtifact(runOutput, artifactDir);
|
|
6640
|
-
} else {
|
|
6641
|
-
console.log();
|
|
6642
|
-
console.log("To run your agent:");
|
|
6643
|
-
printCommand(
|
|
6644
|
-
`vm0 run ${agentName} --artifact-name ${ARTIFACT_DIR} "your prompt"`
|
|
6645
|
-
);
|
|
6646
6951
|
}
|
|
6647
|
-
|
|
6952
|
+
);
|
|
6648
6953
|
cookCmd.command("logs").description("View logs from the last cook run").option("-a, --agent", "Show agent events (default)").option("-s, --system", "Show system log").option("-m, --metrics", "Show metrics").option("-n, --network", "Show network logs (proxy traffic)").option(
|
|
6649
6954
|
"--since <time>",
|
|
6650
6955
|
"Show logs since timestamp (e.g., 5m, 2h, 1d, 2024-01-15T10:30:00Z)"
|
|
@@ -6692,7 +6997,7 @@ cookCmd.command("logs").description("View logs from the last cook run").option("
|
|
|
6692
6997
|
);
|
|
6693
6998
|
cookCmd.command("continue").description(
|
|
6694
6999
|
"Continue from the last session (latest conversation and artifact)"
|
|
6695
|
-
).argument("<prompt>", "Prompt for the continued agent").action(async (prompt) => {
|
|
7000
|
+
).argument("<prompt>", "Prompt for the continued agent").option("--debug-no-mock-claude").action(async (prompt, options) => {
|
|
6696
7001
|
const state = await loadCookState();
|
|
6697
7002
|
if (!state.lastSessionId) {
|
|
6698
7003
|
console.error(chalk21.red("\u2717 No previous session found"));
|
|
@@ -6706,7 +7011,13 @@ cookCmd.command("continue").description(
|
|
|
6706
7011
|
let runOutput;
|
|
6707
7012
|
try {
|
|
6708
7013
|
runOutput = await execVm0RunWithCapture(
|
|
6709
|
-
[
|
|
7014
|
+
[
|
|
7015
|
+
"run",
|
|
7016
|
+
"continue",
|
|
7017
|
+
state.lastSessionId,
|
|
7018
|
+
...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
7019
|
+
prompt
|
|
7020
|
+
],
|
|
6710
7021
|
{ cwd }
|
|
6711
7022
|
);
|
|
6712
7023
|
} catch {
|
|
@@ -6724,7 +7035,7 @@ cookCmd.command("continue").description(
|
|
|
6724
7035
|
});
|
|
6725
7036
|
cookCmd.command("resume").description(
|
|
6726
7037
|
"Resume from the last checkpoint (snapshotted conversation and artifact)"
|
|
6727
|
-
).argument("<prompt>", "Prompt for the resumed agent").action(async (prompt) => {
|
|
7038
|
+
).argument("<prompt>", "Prompt for the resumed agent").option("--debug-no-mock-claude").action(async (prompt, options) => {
|
|
6728
7039
|
const state = await loadCookState();
|
|
6729
7040
|
if (!state.lastCheckpointId) {
|
|
6730
7041
|
console.error(chalk21.red("\u2717 No previous checkpoint found"));
|
|
@@ -6738,7 +7049,13 @@ cookCmd.command("resume").description(
|
|
|
6738
7049
|
let runOutput;
|
|
6739
7050
|
try {
|
|
6740
7051
|
runOutput = await execVm0RunWithCapture(
|
|
6741
|
-
[
|
|
7052
|
+
[
|
|
7053
|
+
"run",
|
|
7054
|
+
"resume",
|
|
7055
|
+
state.lastCheckpointId,
|
|
7056
|
+
...options.debugNoMockClaude ? ["--debug-no-mock-claude"] : [],
|
|
7057
|
+
prompt
|
|
7058
|
+
],
|
|
6742
7059
|
{ cwd }
|
|
6743
7060
|
);
|
|
6744
7061
|
} catch {
|
|
@@ -7134,10 +7451,10 @@ var setCommand = new Command20().name("set").description("Set your scope slug").
|
|
|
7134
7451
|
// src/commands/scope/index.ts
|
|
7135
7452
|
var scopeCommand = new Command21().name("scope").description("Manage your scope (namespace for images)").addCommand(statusCommand3).addCommand(setCommand);
|
|
7136
7453
|
|
|
7137
|
-
// src/commands/
|
|
7454
|
+
// src/commands/agent/index.ts
|
|
7138
7455
|
import { Command as Command24 } from "commander";
|
|
7139
7456
|
|
|
7140
|
-
// src/commands/
|
|
7457
|
+
// src/commands/agent/list.ts
|
|
7141
7458
|
import { Command as Command22 } from "commander";
|
|
7142
7459
|
import chalk25 from "chalk";
|
|
7143
7460
|
var listCommand3 = new Command22().name("list").alias("ls").description("List all agent composes").option("-s, --scope <scope>", "Scope to list composes from").action(async (options) => {
|
|
@@ -7183,7 +7500,7 @@ var listCommand3 = new Command22().name("list").alias("ls").description("List al
|
|
|
7183
7500
|
}
|
|
7184
7501
|
});
|
|
7185
7502
|
|
|
7186
|
-
// src/commands/
|
|
7503
|
+
// src/commands/agent/inspect.ts
|
|
7187
7504
|
import { Command as Command23 } from "commander";
|
|
7188
7505
|
import chalk26 from "chalk";
|
|
7189
7506
|
|
|
@@ -7293,7 +7610,7 @@ async function deriveComposeVariableSources(content, options) {
|
|
|
7293
7610
|
return results;
|
|
7294
7611
|
}
|
|
7295
7612
|
|
|
7296
|
-
// src/commands/
|
|
7613
|
+
// src/commands/agent/inspect.ts
|
|
7297
7614
|
function formatComposeOutput(name, versionId, content, variableSources) {
|
|
7298
7615
|
console.log(chalk26.bold("Name:") + ` ${name}`);
|
|
7299
7616
|
console.log(chalk26.bold("Version:") + ` ${versionId}`);
|
|
@@ -7375,7 +7692,7 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7375
7692
|
} catch (error) {
|
|
7376
7693
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
7377
7694
|
console.error(chalk26.red(`\u2717 Agent compose not found: ${name}`));
|
|
7378
|
-
console.error(chalk26.dim(" Run: vm0
|
|
7695
|
+
console.error(chalk26.dim(" Run: vm0 agent list"));
|
|
7379
7696
|
process.exit(1);
|
|
7380
7697
|
}
|
|
7381
7698
|
throw error;
|
|
@@ -7442,8 +7759,8 @@ var inspectCommand = new Command23().name("inspect").description("Inspect an age
|
|
|
7442
7759
|
}
|
|
7443
7760
|
);
|
|
7444
7761
|
|
|
7445
|
-
// src/commands/
|
|
7446
|
-
var
|
|
7762
|
+
// src/commands/agent/index.ts
|
|
7763
|
+
var agentCommand = new Command24().name("agent").description("Manage agent composes").addCommand(listCommand3).addCommand(inspectCommand);
|
|
7447
7764
|
|
|
7448
7765
|
// src/commands/init.ts
|
|
7449
7766
|
import { Command as Command25 } from "commander";
|
|
@@ -8660,14 +8977,7 @@ var deployCommand = new Command28().name("deploy").description("Deploy a schedul
|
|
|
8660
8977
|
artifactVersion: schedule.run.artifactVersion,
|
|
8661
8978
|
volumeVersions: schedule.run.volumeVersions
|
|
8662
8979
|
};
|
|
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();
|
|
8980
|
+
const deployResult = await apiClient.deploySchedule(body);
|
|
8671
8981
|
if (deployResult.created) {
|
|
8672
8982
|
console.log(
|
|
8673
8983
|
chalk30.green(`\u2713 Created schedule ${chalk30.cyan(scheduleName)}`)
|
|
@@ -8714,12 +9024,7 @@ import { Command as Command29 } from "commander";
|
|
|
8714
9024
|
import chalk31 from "chalk";
|
|
8715
9025
|
var listCommand4 = new Command29().name("list").alias("ls").description("List all schedules").action(async () => {
|
|
8716
9026
|
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();
|
|
9027
|
+
const result = await apiClient.listSchedules();
|
|
8723
9028
|
if (result.schedules.length === 0) {
|
|
8724
9029
|
console.log(chalk31.dim("No schedules found"));
|
|
8725
9030
|
console.log(
|
|
@@ -8855,14 +9160,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8855
9160
|
console.error(chalk32.dim(" Make sure the agent is pushed first"));
|
|
8856
9161
|
process.exit(1);
|
|
8857
9162
|
}
|
|
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();
|
|
9163
|
+
const schedule = await apiClient.getScheduleByName({ name, composeId });
|
|
8866
9164
|
console.log();
|
|
8867
9165
|
console.log(`Schedule: ${chalk32.cyan(schedule.name)}`);
|
|
8868
9166
|
console.log(chalk32.dim("\u2501".repeat(50)));
|
|
@@ -8905,11 +9203,12 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8905
9203
|
100
|
|
8906
9204
|
);
|
|
8907
9205
|
if (limit > 0) {
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
9206
|
+
try {
|
|
9207
|
+
const { runs } = await apiClient.listScheduleRuns({
|
|
9208
|
+
name,
|
|
9209
|
+
composeId,
|
|
9210
|
+
limit
|
|
9211
|
+
});
|
|
8913
9212
|
if (runs.length > 0) {
|
|
8914
9213
|
console.log();
|
|
8915
9214
|
console.log("Recent Runs:");
|
|
@@ -8925,7 +9224,7 @@ var statusCommand4 = new Command30().name("status").description("Show detailed s
|
|
|
8925
9224
|
console.log(`${id} ${status} ${created}`);
|
|
8926
9225
|
}
|
|
8927
9226
|
}
|
|
8928
|
-
}
|
|
9227
|
+
} catch {
|
|
8929
9228
|
console.log();
|
|
8930
9229
|
console.log(chalk32.dim("Recent Runs: (unable to fetch)"));
|
|
8931
9230
|
}
|
|
@@ -8968,8 +9267,8 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
8968
9267
|
"[name]",
|
|
8969
9268
|
"Schedule name (auto-detected from schedule.yaml if omitted)"
|
|
8970
9269
|
).option("-f, --force", "Skip confirmation prompt").action(async (nameArg, options) => {
|
|
9270
|
+
let name = nameArg;
|
|
8971
9271
|
try {
|
|
8972
|
-
let name = nameArg;
|
|
8973
9272
|
if (!name) {
|
|
8974
9273
|
const scheduleResult = loadScheduleName();
|
|
8975
9274
|
if (scheduleResult.error) {
|
|
@@ -9014,19 +9313,15 @@ var deleteCommand = new Command31().name("delete").alias("rm").description("Dele
|
|
|
9014
9313
|
return;
|
|
9015
9314
|
}
|
|
9016
9315
|
}
|
|
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
|
-
}
|
|
9316
|
+
await apiClient.deleteSchedule({ name, composeId });
|
|
9024
9317
|
console.log(chalk33.green(`\u2713 Deleted schedule ${chalk33.cyan(name)}`));
|
|
9025
9318
|
} catch (error) {
|
|
9026
9319
|
console.error(chalk33.red("\u2717 Failed to delete schedule"));
|
|
9027
9320
|
if (error instanceof Error) {
|
|
9028
9321
|
if (error.message.includes("Not authenticated")) {
|
|
9029
9322
|
console.error(chalk33.dim(" Run: vm0 auth login"));
|
|
9323
|
+
} else if (error.message.toLowerCase().includes("not found")) {
|
|
9324
|
+
console.error(chalk33.dim(` Schedule "${name}" not found`));
|
|
9030
9325
|
} else {
|
|
9031
9326
|
console.error(chalk33.dim(` ${error.message}`));
|
|
9032
9327
|
}
|
|
@@ -9081,14 +9376,7 @@ var enableCommand = new Command32().name("enable").description("Enable a schedul
|
|
|
9081
9376
|
console.error(chalk34.dim(" Make sure the agent is pushed first"));
|
|
9082
9377
|
process.exit(1);
|
|
9083
9378
|
}
|
|
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
|
-
}
|
|
9379
|
+
await apiClient.enableSchedule({ name, composeId });
|
|
9092
9380
|
console.log(chalk34.green(`\u2713 Enabled schedule ${chalk34.cyan(name)}`));
|
|
9093
9381
|
} catch (error) {
|
|
9094
9382
|
console.error(chalk34.red("\u2717 Failed to enable schedule"));
|
|
@@ -9149,14 +9437,7 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9149
9437
|
console.error(chalk35.dim(" Make sure the agent is pushed first"));
|
|
9150
9438
|
process.exit(1);
|
|
9151
9439
|
}
|
|
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
|
-
}
|
|
9440
|
+
await apiClient.disableSchedule({ name, composeId });
|
|
9160
9441
|
console.log(chalk35.green(`\u2713 Disabled schedule ${chalk35.cyan(name)}`));
|
|
9161
9442
|
} catch (error) {
|
|
9162
9443
|
console.error(chalk35.red("\u2717 Failed to disable schedule"));
|
|
@@ -9174,11 +9455,183 @@ var disableCommand = new Command33().name("disable").description("Disable a sche
|
|
|
9174
9455
|
// src/commands/schedule/index.ts
|
|
9175
9456
|
var scheduleCommand = new Command34().name("schedule").description("Manage agent schedules").addCommand(initCommand4).addCommand(deployCommand).addCommand(listCommand4).addCommand(statusCommand4).addCommand(deleteCommand).addCommand(enableCommand).addCommand(disableCommand);
|
|
9176
9457
|
|
|
9458
|
+
// src/commands/usage.ts
|
|
9459
|
+
import { Command as Command35 } from "commander";
|
|
9460
|
+
import chalk36 from "chalk";
|
|
9461
|
+
|
|
9462
|
+
// src/lib/utils/duration-formatter.ts
|
|
9463
|
+
function formatDuration(ms) {
|
|
9464
|
+
if (ms === null || ms === void 0 || ms === 0) {
|
|
9465
|
+
return "-";
|
|
9466
|
+
}
|
|
9467
|
+
if (ms < 0) {
|
|
9468
|
+
return "-";
|
|
9469
|
+
}
|
|
9470
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
9471
|
+
if (totalSeconds === 0) {
|
|
9472
|
+
return "< 1s";
|
|
9473
|
+
}
|
|
9474
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
9475
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
9476
|
+
const seconds = totalSeconds % 60;
|
|
9477
|
+
const parts = [];
|
|
9478
|
+
if (hours > 0) {
|
|
9479
|
+
parts.push(`${hours}h`);
|
|
9480
|
+
}
|
|
9481
|
+
if (minutes > 0) {
|
|
9482
|
+
parts.push(`${minutes}m`);
|
|
9483
|
+
}
|
|
9484
|
+
if (seconds > 0) {
|
|
9485
|
+
parts.push(`${seconds}s`);
|
|
9486
|
+
}
|
|
9487
|
+
return parts.join(" ");
|
|
9488
|
+
}
|
|
9489
|
+
|
|
9490
|
+
// src/commands/usage.ts
|
|
9491
|
+
var MAX_RANGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
9492
|
+
var DEFAULT_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
9493
|
+
function formatDateDisplay(dateStr) {
|
|
9494
|
+
const date = new Date(dateStr);
|
|
9495
|
+
return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
9496
|
+
}
|
|
9497
|
+
function formatDateRange(start, end) {
|
|
9498
|
+
const startDate = new Date(start);
|
|
9499
|
+
const endDate = new Date(end);
|
|
9500
|
+
endDate.setDate(endDate.getDate() - 1);
|
|
9501
|
+
const startStr = startDate.toLocaleDateString("en-US", {
|
|
9502
|
+
month: "short",
|
|
9503
|
+
day: "numeric"
|
|
9504
|
+
});
|
|
9505
|
+
const endStr = endDate.toLocaleDateString("en-US", {
|
|
9506
|
+
month: "short",
|
|
9507
|
+
day: "numeric",
|
|
9508
|
+
year: "numeric"
|
|
9509
|
+
});
|
|
9510
|
+
return `${startStr} - ${endStr}`;
|
|
9511
|
+
}
|
|
9512
|
+
function fillMissingDates(daily, startDate, endDate) {
|
|
9513
|
+
const dateMap = /* @__PURE__ */ new Map();
|
|
9514
|
+
for (const day of daily) {
|
|
9515
|
+
dateMap.set(day.date, day);
|
|
9516
|
+
}
|
|
9517
|
+
const result = [];
|
|
9518
|
+
const current = new Date(startDate);
|
|
9519
|
+
current.setUTCHours(0, 0, 0, 0);
|
|
9520
|
+
while (current < endDate) {
|
|
9521
|
+
const dateStr = current.toISOString().split("T")[0];
|
|
9522
|
+
const existing = dateMap.get(dateStr);
|
|
9523
|
+
if (existing) {
|
|
9524
|
+
result.push(existing);
|
|
9525
|
+
} else {
|
|
9526
|
+
result.push({ date: dateStr, run_count: 0, run_time_ms: 0 });
|
|
9527
|
+
}
|
|
9528
|
+
current.setDate(current.getDate() + 1);
|
|
9529
|
+
}
|
|
9530
|
+
result.sort((a, b) => b.date.localeCompare(a.date));
|
|
9531
|
+
return result;
|
|
9532
|
+
}
|
|
9533
|
+
var usageCommand = new Command35().name("usage").description("View usage statistics").option("--since <date>", "Start date (ISO format or relative: 7d, 30d)").option(
|
|
9534
|
+
"--until <date>",
|
|
9535
|
+
"End date (ISO format or relative, defaults to now)"
|
|
9536
|
+
).action(async (options) => {
|
|
9537
|
+
try {
|
|
9538
|
+
const now = /* @__PURE__ */ new Date();
|
|
9539
|
+
let endDate;
|
|
9540
|
+
let startDate;
|
|
9541
|
+
if (options.until) {
|
|
9542
|
+
try {
|
|
9543
|
+
const untilMs = parseTime(options.until);
|
|
9544
|
+
endDate = new Date(untilMs);
|
|
9545
|
+
} catch {
|
|
9546
|
+
console.error(
|
|
9547
|
+
chalk36.red(
|
|
9548
|
+
"Error: Invalid --until format. Use ISO (2026-01-01) or relative (7d, 30d)"
|
|
9549
|
+
)
|
|
9550
|
+
);
|
|
9551
|
+
process.exit(1);
|
|
9552
|
+
}
|
|
9553
|
+
} else {
|
|
9554
|
+
endDate = now;
|
|
9555
|
+
}
|
|
9556
|
+
if (options.since) {
|
|
9557
|
+
try {
|
|
9558
|
+
const sinceMs = parseTime(options.since);
|
|
9559
|
+
startDate = new Date(sinceMs);
|
|
9560
|
+
} catch {
|
|
9561
|
+
console.error(
|
|
9562
|
+
chalk36.red(
|
|
9563
|
+
"Error: Invalid --since format. Use ISO (2026-01-01) or relative (7d, 30d)"
|
|
9564
|
+
)
|
|
9565
|
+
);
|
|
9566
|
+
process.exit(1);
|
|
9567
|
+
}
|
|
9568
|
+
} else {
|
|
9569
|
+
startDate = new Date(endDate.getTime() - DEFAULT_RANGE_MS);
|
|
9570
|
+
}
|
|
9571
|
+
if (startDate >= endDate) {
|
|
9572
|
+
console.error(chalk36.red("Error: --since must be before --until"));
|
|
9573
|
+
process.exit(1);
|
|
9574
|
+
}
|
|
9575
|
+
const rangeMs = endDate.getTime() - startDate.getTime();
|
|
9576
|
+
if (rangeMs > MAX_RANGE_MS) {
|
|
9577
|
+
console.error(
|
|
9578
|
+
chalk36.red(
|
|
9579
|
+
"Error: Time range exceeds maximum of 30 days. Use --until to specify an end date."
|
|
9580
|
+
)
|
|
9581
|
+
);
|
|
9582
|
+
process.exit(1);
|
|
9583
|
+
}
|
|
9584
|
+
const usage = await apiClient.getUsage({
|
|
9585
|
+
startDate: startDate.toISOString(),
|
|
9586
|
+
endDate: endDate.toISOString()
|
|
9587
|
+
});
|
|
9588
|
+
const filledDaily = fillMissingDates(
|
|
9589
|
+
usage.daily,
|
|
9590
|
+
new Date(usage.period.start),
|
|
9591
|
+
new Date(usage.period.end)
|
|
9592
|
+
);
|
|
9593
|
+
console.log();
|
|
9594
|
+
console.log(
|
|
9595
|
+
chalk36.bold(
|
|
9596
|
+
`Usage Summary (${formatDateRange(usage.period.start, usage.period.end)})`
|
|
9597
|
+
)
|
|
9598
|
+
);
|
|
9599
|
+
console.log();
|
|
9600
|
+
console.log(chalk36.dim("DATE RUNS RUN TIME"));
|
|
9601
|
+
for (const day of filledDaily) {
|
|
9602
|
+
const dateDisplay = formatDateDisplay(day.date).padEnd(10);
|
|
9603
|
+
const runsDisplay = String(day.run_count).padStart(6);
|
|
9604
|
+
const timeDisplay = formatDuration(day.run_time_ms);
|
|
9605
|
+
console.log(`${dateDisplay}${runsDisplay} ${timeDisplay}`);
|
|
9606
|
+
}
|
|
9607
|
+
console.log(chalk36.dim("\u2500".repeat(29)));
|
|
9608
|
+
const totalRunsDisplay = String(usage.summary.total_runs).padStart(6);
|
|
9609
|
+
const totalTimeDisplay = formatDuration(usage.summary.total_run_time_ms);
|
|
9610
|
+
console.log(
|
|
9611
|
+
`${"TOTAL".padEnd(10)}${totalRunsDisplay} ${totalTimeDisplay}`
|
|
9612
|
+
);
|
|
9613
|
+
console.log();
|
|
9614
|
+
} catch (error) {
|
|
9615
|
+
if (error instanceof Error) {
|
|
9616
|
+
if (error.message.includes("Not authenticated")) {
|
|
9617
|
+
console.error(
|
|
9618
|
+
chalk36.red("Error: Not authenticated. Run: vm0 auth login")
|
|
9619
|
+
);
|
|
9620
|
+
} else {
|
|
9621
|
+
console.error(chalk36.red(`Error: ${error.message}`));
|
|
9622
|
+
}
|
|
9623
|
+
} else {
|
|
9624
|
+
console.error(chalk36.red("Error: An unexpected error occurred"));
|
|
9625
|
+
}
|
|
9626
|
+
process.exit(1);
|
|
9627
|
+
}
|
|
9628
|
+
});
|
|
9629
|
+
|
|
9177
9630
|
// src/index.ts
|
|
9178
|
-
var program = new
|
|
9179
|
-
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.
|
|
9631
|
+
var program = new Command36();
|
|
9632
|
+
program.name("vm0").description("VM0 CLI - A modern build tool").version("5.8.0");
|
|
9180
9633
|
program.command("info").description("Display environment information").action(async () => {
|
|
9181
|
-
console.log(
|
|
9634
|
+
console.log(chalk37.bold("System Information:"));
|
|
9182
9635
|
console.log(`Node Version: ${process.version}`);
|
|
9183
9636
|
console.log(`Platform: ${process.platform}`);
|
|
9184
9637
|
console.log(`Architecture: ${process.arch}`);
|
|
@@ -9205,10 +9658,11 @@ program.addCommand(artifactCommand);
|
|
|
9205
9658
|
program.addCommand(cookCommand);
|
|
9206
9659
|
program.addCommand(logsCommand);
|
|
9207
9660
|
program.addCommand(scopeCommand);
|
|
9208
|
-
program.addCommand(
|
|
9661
|
+
program.addCommand(agentCommand);
|
|
9209
9662
|
program.addCommand(initCommand3);
|
|
9210
9663
|
program.addCommand(setupGithubCommand);
|
|
9211
9664
|
program.addCommand(scheduleCommand);
|
|
9665
|
+
program.addCommand(usageCommand);
|
|
9212
9666
|
if (process.argv[1]?.endsWith("index.js") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.endsWith("vm0")) {
|
|
9213
9667
|
program.parse();
|
|
9214
9668
|
}
|