@vendian/cli 0.0.27 → 0.0.28
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/README.md +4 -1
- package/cli-wrapper.mjs +184 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ vendian
|
|
|
8
8
|
vendian login
|
|
9
9
|
vendian init --output-dir ./agents
|
|
10
10
|
vendian create "My Agent" --output-dir ./agents
|
|
11
|
+
vendian cloud local run --collection-id YOUR_COLLECTION --path ./agents/my-agent --input-json '{}'
|
|
11
12
|
vendian cloud local serve --agents-dir ./agents
|
|
12
13
|
```
|
|
13
14
|
|
|
@@ -23,11 +24,13 @@ vendian create "My Agent" --output-dir ./agents
|
|
|
23
24
|
vendian validate ./agents/my-agent --runtime
|
|
24
25
|
vendian test ./agents/my-agent --dry-run --mock-credentials
|
|
25
26
|
vendian models
|
|
27
|
+
vendian cloud local run --collection-id YOUR_COLLECTION --path ./agents/my-agent --input-json '{}'
|
|
26
28
|
vendian cloud local serve --agents-dir ./agents
|
|
27
29
|
```
|
|
28
30
|
|
|
29
31
|
Run `vendian` with no arguments to open the interactive menu. It shows your
|
|
30
|
-
current endpoint connections and guides common local workflows
|
|
32
|
+
current endpoint connections and guides common local workflows, including
|
|
33
|
+
running one local agent immediately or starting the long-lived local daemon.
|
|
31
34
|
|
|
32
35
|
`vendian login` opens a browser sign-in, prepares the local runtime, and stores
|
|
33
36
|
the credentials needed by the CLI for the selected endpoint. `vendian setup` is
|
package/cli-wrapper.mjs
CHANGED
|
@@ -1107,7 +1107,7 @@ import path8 from "node:path";
|
|
|
1107
1107
|
import readlinePromises from "node:readline/promises";
|
|
1108
1108
|
|
|
1109
1109
|
// src/version.js
|
|
1110
|
-
var CLI_VERSION = true ? "0.0.
|
|
1110
|
+
var CLI_VERSION = true ? "0.0.28" : process.env.npm_package_version || "0.0.0-dev";
|
|
1111
1111
|
|
|
1112
1112
|
// src/npm-update.js
|
|
1113
1113
|
var NPM_CHECK_INTERVAL_MS = 30 * 60 * 1e3;
|
|
@@ -2412,12 +2412,12 @@ async function runTui({
|
|
|
2412
2412
|
await refreshInteractiveManagedRuntime({ env, platform, output });
|
|
2413
2413
|
await loadTerm();
|
|
2414
2414
|
term.fullscreen(true);
|
|
2415
|
-
|
|
2415
|
+
setCursorVisible(false);
|
|
2416
2416
|
term.grabInput({ mouse: "motion" });
|
|
2417
2417
|
const cleanup = () => {
|
|
2418
2418
|
try {
|
|
2419
2419
|
term.grabInput(false);
|
|
2420
|
-
|
|
2420
|
+
setCursorVisible(true);
|
|
2421
2421
|
term.fullscreen(false);
|
|
2422
2422
|
} catch {
|
|
2423
2423
|
}
|
|
@@ -2451,6 +2451,9 @@ async function mainLoop({ env, platform }) {
|
|
|
2451
2451
|
while (true) {
|
|
2452
2452
|
let next;
|
|
2453
2453
|
switch (screen) {
|
|
2454
|
+
case "run":
|
|
2455
|
+
next = await showRun({ env, platform });
|
|
2456
|
+
break;
|
|
2454
2457
|
case "home":
|
|
2455
2458
|
next = await showHome({ env, platform });
|
|
2456
2459
|
break;
|
|
@@ -2532,6 +2535,7 @@ var HOME_ACTIONS = [
|
|
|
2532
2535
|
{ value: "connect", label: "Sign in", desc: "Connect to a different account or environment" },
|
|
2533
2536
|
{ value: "create", label: "Create Agent", desc: "Build a new agent from a template" },
|
|
2534
2537
|
{ value: "commands", label: "Commands", desc: "Show all available CLI commands" },
|
|
2538
|
+
{ value: "run", label: "Run once", desc: "Execute one local agent immediately" },
|
|
2535
2539
|
{ value: "exit", label: "Exit", desc: "" }
|
|
2536
2540
|
];
|
|
2537
2541
|
async function showHome({ env, platform }) {
|
|
@@ -2628,6 +2632,41 @@ async function showCreate({ env, platform }) {
|
|
|
2628
2632
|
);
|
|
2629
2633
|
return "home";
|
|
2630
2634
|
}
|
|
2635
|
+
async function showRun({ env, platform }) {
|
|
2636
|
+
const candidates = findAgentDirectoryCandidates();
|
|
2637
|
+
const picked = await pickSingleAgentToRun({ env, platform, candidates });
|
|
2638
|
+
if (!picked) return "home";
|
|
2639
|
+
const workspace = await chooseCloudWorkspace({
|
|
2640
|
+
env,
|
|
2641
|
+
platform,
|
|
2642
|
+
loadingTitle: " Getting ready to run this agent\u2026",
|
|
2643
|
+
pickerTitle: " Which project should own this run?\n\n"
|
|
2644
|
+
});
|
|
2645
|
+
if (!workspace) return "home";
|
|
2646
|
+
term.clear();
|
|
2647
|
+
drawHeader({ env, platform });
|
|
2648
|
+
term("\n");
|
|
2649
|
+
term.bold(` Run ${picked.displayName}
|
|
2650
|
+
|
|
2651
|
+
`);
|
|
2652
|
+
term.gray(` Agent: ${picked.path}
|
|
2653
|
+
`);
|
|
2654
|
+
term.gray(` Project: ${workspace.label}
|
|
2655
|
+
|
|
2656
|
+
`);
|
|
2657
|
+
term.gray(" Input JSON: ");
|
|
2658
|
+
const inputJson = await term.inputField({ cancelable: true, style: term.cyan, default: "{}" }).promise;
|
|
2659
|
+
if (inputJson === null) return "home";
|
|
2660
|
+
await withOutputMode(
|
|
2661
|
+
`Running ${picked.displayName}`,
|
|
2662
|
+
() => forwardToPythonVendian(buildLocalRunArgs({
|
|
2663
|
+
agentPath: picked.path,
|
|
2664
|
+
collectionId: workspace.id,
|
|
2665
|
+
inputJson: inputJson || "{}"
|
|
2666
|
+
}), { env, platform })
|
|
2667
|
+
);
|
|
2668
|
+
return "home";
|
|
2669
|
+
}
|
|
2631
2670
|
var COMMAND_GROUPS = [
|
|
2632
2671
|
{ section: "Getting started", commands: [
|
|
2633
2672
|
{ cmd: "vendian login", desc: "Sign in and set up your computer" },
|
|
@@ -2640,6 +2679,7 @@ var COMMAND_GROUPS = [
|
|
|
2640
2679
|
{ cmd: "vendian models", desc: "List available AI models" }
|
|
2641
2680
|
] },
|
|
2642
2681
|
{ section: "Running agents", commands: [
|
|
2682
|
+
{ cmd: "vendian cloud local run --collection-id ID --path . --input-json '{}'", desc: "Run one local agent once" },
|
|
2643
2683
|
{ cmd: "vendian cloud local serve --agents-dir .", desc: "Start agents (advanced mode)" },
|
|
2644
2684
|
{ cmd: "vendian login --backend staging", desc: "Sign in to staging environment" }
|
|
2645
2685
|
] },
|
|
@@ -2680,57 +2720,14 @@ async function showServe({ env, platform }) {
|
|
|
2680
2720
|
const picked = await pickAgentsToRun({ env, platform, candidates });
|
|
2681
2721
|
if (!picked) return "home";
|
|
2682
2722
|
const { agentsDir } = picked;
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
wsResult = await listCloudWorkspaces({
|
|
2692
|
-
env,
|
|
2693
|
-
platform,
|
|
2694
|
-
onProgress: (msg) => {
|
|
2695
|
-
term.moveTo(1, HEADER_ROWS_BASE + 3);
|
|
2696
|
-
term.eraseLine();
|
|
2697
|
-
term.gray(` ${clip(msg, 60)}
|
|
2698
|
-
`);
|
|
2699
|
-
}
|
|
2700
|
-
});
|
|
2701
|
-
} catch (error) {
|
|
2702
|
-
term.red(`
|
|
2703
|
-
Couldn't connect to the server: ${errMsg(error)}
|
|
2704
|
-
`);
|
|
2705
|
-
term.gray(" Make sure you are signed in (choose Sign in from the main menu).\n");
|
|
2706
|
-
await pressEnterToContinue({ grabActive: false });
|
|
2707
|
-
return "home";
|
|
2708
|
-
}
|
|
2709
|
-
if (!wsResult.ok) {
|
|
2710
|
-
term.red(`
|
|
2711
|
-
${fig.cross} ${wsResult.error}
|
|
2712
|
-
`);
|
|
2713
|
-
await pressEnterToContinue({ grabActive: false });
|
|
2714
|
-
return "home";
|
|
2715
|
-
}
|
|
2716
|
-
let collectionId = wsResult.workspaces[0]?.id || "";
|
|
2717
|
-
if (wsResult.workspaces.length > 1) {
|
|
2718
|
-
term.clear();
|
|
2719
|
-
drawHeader({ env, platform });
|
|
2720
|
-
term("\n");
|
|
2721
|
-
term.bold(" Which project do you want to run?\n\n");
|
|
2722
|
-
const wsItems = [...wsResult.workspaces.map((w) => workspaceLabel(w)), "\u2190 Back"];
|
|
2723
|
-
const wsResp = await term.singleColumnMenu(wsItems, {
|
|
2724
|
-
cancelable: true,
|
|
2725
|
-
style: term.gray,
|
|
2726
|
-
selectedStyle: term.bgCyan.black.bold,
|
|
2727
|
-
leftPadding: " ",
|
|
2728
|
-
selectedLeftPadding: " \u203A "
|
|
2729
|
-
}).promise;
|
|
2730
|
-
if (wsResp.canceled || wsResp.selectedIndex === wsItems.length - 1) return "home";
|
|
2731
|
-
collectionId = wsResult.workspaces[wsResp.selectedIndex]?.id || "";
|
|
2732
|
-
}
|
|
2733
|
-
return await runServeDashboard({ env, platform, agentsDir, collectionId });
|
|
2723
|
+
const workspace = await chooseCloudWorkspace({
|
|
2724
|
+
env,
|
|
2725
|
+
platform,
|
|
2726
|
+
loadingTitle: " Getting ready to run your agents\u2026",
|
|
2727
|
+
pickerTitle: " Which project do you want to run?\n\n"
|
|
2728
|
+
});
|
|
2729
|
+
if (!workspace) return "home";
|
|
2730
|
+
return await runServeDashboard({ env, platform, agentsDir, collectionId: workspace.id });
|
|
2734
2731
|
}
|
|
2735
2732
|
async function pickAgentsToRun({ env, platform, candidates }) {
|
|
2736
2733
|
if (candidates.length === 0) {
|
|
@@ -2804,6 +2801,107 @@ async function pickAgentsFromFolder({ env, platform, candidate }) {
|
|
|
2804
2801
|
if (resp.selectedIndex === 0) return { agentsDir: candidate.path };
|
|
2805
2802
|
return { agentsDir: named[resp.selectedIndex - 1].path };
|
|
2806
2803
|
}
|
|
2804
|
+
async function pickSingleAgentToRun({ env, platform, candidates }) {
|
|
2805
|
+
if (candidates.length === 0) {
|
|
2806
|
+
term.clear();
|
|
2807
|
+
drawHeader({ env, platform });
|
|
2808
|
+
term("\n");
|
|
2809
|
+
term.bold(" I couldn't find any agents on your computer.\n\n");
|
|
2810
|
+
term.gray(" Enter the path to one agent folder:\n\n");
|
|
2811
|
+
term.gray(" Folder: ");
|
|
2812
|
+
const input = await term.inputField({ cancelable: true, style: term.cyan, default: "./agents/my-agent" }).promise;
|
|
2813
|
+
if (input === null) return null;
|
|
2814
|
+
const agentPath = input || "./agents/my-agent";
|
|
2815
|
+
return { path: agentPath, displayName: friendlyName(path8.basename(agentPath) || "Agent") };
|
|
2816
|
+
}
|
|
2817
|
+
const agents = candidates.flatMap((candidate) => {
|
|
2818
|
+
const folders = findAgentFolders(candidate.absolutePath);
|
|
2819
|
+
if (folders.length > 0) {
|
|
2820
|
+
return folders.map((folder) => ({
|
|
2821
|
+
path: folder.path,
|
|
2822
|
+
displayName: readManifestName(folder.absolutePath) || friendlyName(folder.name || path8.basename(folder.path))
|
|
2823
|
+
}));
|
|
2824
|
+
}
|
|
2825
|
+
return [{
|
|
2826
|
+
path: candidate.path,
|
|
2827
|
+
displayName: readManifestName(candidate.absolutePath) || friendlyName(path8.basename(candidate.absolutePath) || candidate.path)
|
|
2828
|
+
}];
|
|
2829
|
+
});
|
|
2830
|
+
if (agents.length === 1) return agents[0];
|
|
2831
|
+
term.clear();
|
|
2832
|
+
drawHeader({ env, platform });
|
|
2833
|
+
term("\n");
|
|
2834
|
+
term.bold(" Which agent do you want to run now?\n\n");
|
|
2835
|
+
const items = [...agents.map((agent) => `${agent.displayName.padEnd(32)} ${agent.path}`), "\u2190 Back"];
|
|
2836
|
+
const resp = await term.singleColumnMenu(items, {
|
|
2837
|
+
cancelable: true,
|
|
2838
|
+
style: term.gray,
|
|
2839
|
+
selectedStyle: term.bgCyan.black.bold,
|
|
2840
|
+
leftPadding: " ",
|
|
2841
|
+
selectedLeftPadding: " \u203A "
|
|
2842
|
+
}).promise;
|
|
2843
|
+
if (resp.canceled || resp.selectedIndex === items.length - 1) return null;
|
|
2844
|
+
return agents[resp.selectedIndex];
|
|
2845
|
+
}
|
|
2846
|
+
async function chooseCloudWorkspace({
|
|
2847
|
+
env,
|
|
2848
|
+
platform,
|
|
2849
|
+
loadingTitle,
|
|
2850
|
+
pickerTitle
|
|
2851
|
+
} = {}) {
|
|
2852
|
+
term.clear();
|
|
2853
|
+
drawHeader({ env, platform });
|
|
2854
|
+
term("\n");
|
|
2855
|
+
term.bold(`${loadingTitle}
|
|
2856
|
+
|
|
2857
|
+
`);
|
|
2858
|
+
let wsResult;
|
|
2859
|
+
try {
|
|
2860
|
+
wsResult = await listCloudWorkspaces({
|
|
2861
|
+
env,
|
|
2862
|
+
platform,
|
|
2863
|
+
onProgress: (msg) => {
|
|
2864
|
+
term.moveTo(1, HEADER_ROWS_BASE + 3);
|
|
2865
|
+
term.eraseLine();
|
|
2866
|
+
term.gray(` ${clip(msg, 60)}
|
|
2867
|
+
`);
|
|
2868
|
+
}
|
|
2869
|
+
});
|
|
2870
|
+
} catch (error) {
|
|
2871
|
+
term.red(`
|
|
2872
|
+
Couldn't connect to the server: ${errMsg(error)}
|
|
2873
|
+
`);
|
|
2874
|
+
term.gray(" Make sure you are signed in (choose Sign in from the main menu).\n");
|
|
2875
|
+
await pressEnterToContinue({ grabActive: false });
|
|
2876
|
+
return null;
|
|
2877
|
+
}
|
|
2878
|
+
if (!wsResult.ok) {
|
|
2879
|
+
term.red(`
|
|
2880
|
+
${fig.cross} ${wsResult.error}
|
|
2881
|
+
`);
|
|
2882
|
+
await pressEnterToContinue({ grabActive: false });
|
|
2883
|
+
return null;
|
|
2884
|
+
}
|
|
2885
|
+
if (wsResult.workspaces.length <= 1) {
|
|
2886
|
+
const workspace2 = wsResult.workspaces[0];
|
|
2887
|
+
return workspace2 ? { id: workspace2.id || "", label: workspaceLabel(workspace2) } : null;
|
|
2888
|
+
}
|
|
2889
|
+
term.clear();
|
|
2890
|
+
drawHeader({ env, platform });
|
|
2891
|
+
term("\n");
|
|
2892
|
+
term.bold(pickerTitle);
|
|
2893
|
+
const wsItems = [...wsResult.workspaces.map((w) => workspaceLabel(w)), "\u2190 Back"];
|
|
2894
|
+
const wsResp = await term.singleColumnMenu(wsItems, {
|
|
2895
|
+
cancelable: true,
|
|
2896
|
+
style: term.gray,
|
|
2897
|
+
selectedStyle: term.bgCyan.black.bold,
|
|
2898
|
+
leftPadding: " ",
|
|
2899
|
+
selectedLeftPadding: " \u203A "
|
|
2900
|
+
}).promise;
|
|
2901
|
+
if (wsResp.canceled || wsResp.selectedIndex === wsItems.length - 1) return null;
|
|
2902
|
+
const workspace = wsResult.workspaces[wsResp.selectedIndex];
|
|
2903
|
+
return { id: workspace?.id || "", label: workspaceLabel(workspace) };
|
|
2904
|
+
}
|
|
2807
2905
|
async function runServeDashboard({ env, platform, agentsDir, collectionId }) {
|
|
2808
2906
|
let state = initialServeState();
|
|
2809
2907
|
let child = null;
|
|
@@ -3350,7 +3448,7 @@ function attachServeChild(child, onUpdate, onExit, logStore = null) {
|
|
|
3350
3448
|
}
|
|
3351
3449
|
async function withOutputMode(label, fn) {
|
|
3352
3450
|
term.fullscreen(false);
|
|
3353
|
-
|
|
3451
|
+
setCursorVisible(true);
|
|
3354
3452
|
term.grabInput(false);
|
|
3355
3453
|
process.stdout.write(`
|
|
3356
3454
|
${label}
|
|
@@ -3366,7 +3464,7 @@ async function withOutputMode(label, fn) {
|
|
|
3366
3464
|
}
|
|
3367
3465
|
await pressEnterToContinue({ grabActive: false });
|
|
3368
3466
|
term.fullscreen(true);
|
|
3369
|
-
|
|
3467
|
+
setCursorVisible(false);
|
|
3370
3468
|
term.grabInput({ mouse: "motion" });
|
|
3371
3469
|
}
|
|
3372
3470
|
function waitForKey(keys = null) {
|
|
@@ -3380,6 +3478,19 @@ function waitForKey(keys = null) {
|
|
|
3380
3478
|
term.on("key", handler);
|
|
3381
3479
|
});
|
|
3382
3480
|
}
|
|
3481
|
+
function setCursorVisible(visible) {
|
|
3482
|
+
if (typeof term?.hideCursor === "function") {
|
|
3483
|
+
term.hideCursor(!visible);
|
|
3484
|
+
return;
|
|
3485
|
+
}
|
|
3486
|
+
if (visible && typeof term?.showCursor === "function") {
|
|
3487
|
+
term.showCursor();
|
|
3488
|
+
return;
|
|
3489
|
+
}
|
|
3490
|
+
if (!visible && typeof term?.hideCursor === "function") {
|
|
3491
|
+
term.hideCursor();
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3383
3494
|
async function pressEnterToContinue({ grabActive = true } = {}) {
|
|
3384
3495
|
if (grabActive) {
|
|
3385
3496
|
term("\n Press any key to continue\u2026");
|
|
@@ -3499,6 +3610,23 @@ function endpointErrorStatus(error) {
|
|
|
3499
3610
|
const message = error && typeof error.message === "string" ? error.message : String(error || "Connection failed");
|
|
3500
3611
|
return `${fig.cross} ${message}`;
|
|
3501
3612
|
}
|
|
3613
|
+
function buildLocalRunArgs({
|
|
3614
|
+
agentPath = ".",
|
|
3615
|
+
collectionId = "",
|
|
3616
|
+
inputJson = "{}"
|
|
3617
|
+
} = {}) {
|
|
3618
|
+
return [
|
|
3619
|
+
"cloud",
|
|
3620
|
+
"local",
|
|
3621
|
+
"run",
|
|
3622
|
+
"--collection-id",
|
|
3623
|
+
collectionId,
|
|
3624
|
+
"--path",
|
|
3625
|
+
agentPath || ".",
|
|
3626
|
+
"--input-json",
|
|
3627
|
+
inputJson || "{}"
|
|
3628
|
+
];
|
|
3629
|
+
}
|
|
3502
3630
|
function runtimeSummary({ env = process.env, platform = process.platform, now = Date.now() } = {}) {
|
|
3503
3631
|
const config = loadConfig(env, platform);
|
|
3504
3632
|
const venvPath = managedVenvPath(env, platform);
|