@vendian/cli 0.0.32 → 0.0.34
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/cli-wrapper.mjs +202 -105
- package/package.json +1 -1
package/cli-wrapper.mjs
CHANGED
|
@@ -1107,7 +1107,7 @@ import path8 from "node:path";
|
|
|
1107
1107
|
import readline from "node:readline";
|
|
1108
1108
|
|
|
1109
1109
|
// src/version.js
|
|
1110
|
-
var CLI_VERSION = true ? "0.0.
|
|
1110
|
+
var CLI_VERSION = true ? "0.0.34" : 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;
|
|
@@ -2387,6 +2387,9 @@ function setCursorVisible(visible) {
|
|
|
2387
2387
|
if (!process.stdout.isTTY) return;
|
|
2388
2388
|
process.stdout.write(visible ? "\x1B[?25h" : "\x1B[?25l");
|
|
2389
2389
|
}
|
|
2390
|
+
function clearScreen() {
|
|
2391
|
+
if (process.stdout.isTTY) process.stdout.write("\x1B[2J\x1B[H");
|
|
2392
|
+
}
|
|
2390
2393
|
function makeRl() {
|
|
2391
2394
|
return readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
2392
2395
|
}
|
|
@@ -2403,7 +2406,7 @@ async function ask(question, defaultValue = "") {
|
|
|
2403
2406
|
async function pressEnterToContinue({ grabActive = true } = {}) {
|
|
2404
2407
|
return new Promise((resolve) => {
|
|
2405
2408
|
const rl = makeRl();
|
|
2406
|
-
process.stdout.write("\n Press Enter to continue
|
|
2409
|
+
process.stdout.write("\n Press Enter to continue... ");
|
|
2407
2410
|
rl.once("line", () => {
|
|
2408
2411
|
rl.close();
|
|
2409
2412
|
resolve();
|
|
@@ -2411,6 +2414,82 @@ async function pressEnterToContinue({ grabActive = true } = {}) {
|
|
|
2411
2414
|
rl.once("close", resolve);
|
|
2412
2415
|
});
|
|
2413
2416
|
}
|
|
2417
|
+
async function pickMenu(items, { allowBack = true } = {}) {
|
|
2418
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
2419
|
+
return pickMenuNumeric(items, allowBack);
|
|
2420
|
+
}
|
|
2421
|
+
const backIdx = allowBack ? items.length : -1;
|
|
2422
|
+
const total = items.length + (allowBack ? 1 : 0);
|
|
2423
|
+
let sel = 0;
|
|
2424
|
+
function renderLine(i) {
|
|
2425
|
+
const isBack = allowBack && i === items.length;
|
|
2426
|
+
const label = isBack ? col.gray("Back") : items[i];
|
|
2427
|
+
const pfx = i === sel ? col.cyan("\u25BA") : " ";
|
|
2428
|
+
const num = col.gray(isBack ? "0" : String(i + 1));
|
|
2429
|
+
return ` ${pfx} ${num} ${label}\x1B[K`;
|
|
2430
|
+
}
|
|
2431
|
+
setCursorVisible(false);
|
|
2432
|
+
for (let i = 0; i < total; i++) {
|
|
2433
|
+
process.stdout.write(renderLine(i) + "\n");
|
|
2434
|
+
}
|
|
2435
|
+
return new Promise((resolve) => {
|
|
2436
|
+
readline.emitKeypressEvents(process.stdin);
|
|
2437
|
+
process.stdin.setRawMode(true);
|
|
2438
|
+
process.stdin.resume();
|
|
2439
|
+
function redraw() {
|
|
2440
|
+
process.stdout.write(`\x1B[${total}A`);
|
|
2441
|
+
for (let i = 0; i < total; i++) {
|
|
2442
|
+
process.stdout.write(renderLine(i) + "\n");
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
function done(result) {
|
|
2446
|
+
process.stdin.off("keypress", onKey);
|
|
2447
|
+
try {
|
|
2448
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
2449
|
+
} catch {
|
|
2450
|
+
}
|
|
2451
|
+
setCursorVisible(true);
|
|
2452
|
+
resolve(result);
|
|
2453
|
+
}
|
|
2454
|
+
function onKey(str, key) {
|
|
2455
|
+
if (!key) return;
|
|
2456
|
+
if (key.name === "up") {
|
|
2457
|
+
sel = (sel - 1 + total) % total;
|
|
2458
|
+
redraw();
|
|
2459
|
+
} else if (key.name === "down") {
|
|
2460
|
+
sel = (sel + 1) % total;
|
|
2461
|
+
redraw();
|
|
2462
|
+
} else if (key.name === "return") {
|
|
2463
|
+
done(sel === backIdx ? -1 : sel);
|
|
2464
|
+
} else if (key.name === "escape") {
|
|
2465
|
+
done(-1);
|
|
2466
|
+
} else if (key.ctrl && key.name === "c") {
|
|
2467
|
+
done(null);
|
|
2468
|
+
} else if (/^\d$/.test(str || "")) {
|
|
2469
|
+
const n = parseInt(str, 10);
|
|
2470
|
+
if (n === 0 && allowBack) {
|
|
2471
|
+
done(-1);
|
|
2472
|
+
return;
|
|
2473
|
+
}
|
|
2474
|
+
if (n >= 1 && n <= items.length) {
|
|
2475
|
+
done(n - 1);
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
process.stdin.on("keypress", onKey);
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
async function pickMenuNumeric(items, allowBack) {
|
|
2484
|
+
items.forEach((item, i) => print(` ${col.blue(String(i + 1))} ${item}`));
|
|
2485
|
+
if (allowBack) print(` ${col.gray("0 Back")}`);
|
|
2486
|
+
print("");
|
|
2487
|
+
const ans = await ask("Choose");
|
|
2488
|
+
const n = parseInt(ans, 10);
|
|
2489
|
+
if (n === 0 && allowBack) return -1;
|
|
2490
|
+
if (n >= 1 && n <= items.length) return n - 1;
|
|
2491
|
+
return -1;
|
|
2492
|
+
}
|
|
2414
2493
|
async function withOutputMode(label, fn) {
|
|
2415
2494
|
setCursorVisible(true);
|
|
2416
2495
|
print("");
|
|
@@ -2449,20 +2528,19 @@ var HOME_ACTIONS = [
|
|
|
2449
2528
|
{ value: "exit", label: "Exit", desc: "" }
|
|
2450
2529
|
];
|
|
2451
2530
|
async function showHome({ env, platform }) {
|
|
2531
|
+
clearScreen();
|
|
2452
2532
|
print("");
|
|
2453
2533
|
printHeader({ env, platform });
|
|
2454
2534
|
print("");
|
|
2455
2535
|
print(col.bold(" What would you like to do?"));
|
|
2456
2536
|
print("");
|
|
2457
|
-
HOME_ACTIONS.
|
|
2458
|
-
const desc =
|
|
2459
|
-
|
|
2537
|
+
const items = HOME_ACTIONS.map((a) => {
|
|
2538
|
+
const desc = a.desc ? col.gray(` - ${a.desc}`) : "";
|
|
2539
|
+
return `${a.label.padEnd(22)}${desc}`;
|
|
2460
2540
|
});
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
if (!Number.isFinite(n) || n < 1 || n > HOME_ACTIONS.length) return "home";
|
|
2465
|
-
return HOME_ACTIONS[n - 1].value;
|
|
2541
|
+
const idx = await pickMenu(items, { allowBack: false });
|
|
2542
|
+
if (idx === null || idx < 0) return null;
|
|
2543
|
+
return HOME_ACTIONS[idx].value;
|
|
2466
2544
|
}
|
|
2467
2545
|
var ENDPOINTS = [
|
|
2468
2546
|
{ key: "prod", label: "Production", subtitle: "Recommended for live use" },
|
|
@@ -2472,33 +2550,27 @@ var ENDPOINTS = [
|
|
|
2472
2550
|
];
|
|
2473
2551
|
async function showConnect({ env, platform }) {
|
|
2474
2552
|
while (true) {
|
|
2553
|
+
clearScreen();
|
|
2475
2554
|
print("");
|
|
2476
2555
|
printHeader({ env, platform });
|
|
2477
2556
|
print("");
|
|
2478
2557
|
print(col.bold(" Login / Switch environment:"));
|
|
2479
2558
|
print("");
|
|
2480
2559
|
const rows = endpointRows({ env, platform });
|
|
2481
|
-
const
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
print("");
|
|
2492
|
-
const ans = await ask("Choose a number, or 0 to go back");
|
|
2493
|
-
const n = parseInt(ans, 10);
|
|
2494
|
-
if (n === 0 || isNaN(n)) return "home";
|
|
2495
|
-
if (n === items.length) return "home";
|
|
2496
|
-
if (n < 1 || n > items.length) continue;
|
|
2497
|
-
if (n === items.length - 1) {
|
|
2560
|
+
const epItems = ENDPOINTS.map((ep2) => {
|
|
2561
|
+
const row = rows.find((r) => r.key === ep2.key);
|
|
2562
|
+
const badge = row?.active ? col.green(" \u25CF active") : row?.status === "signed in" ? col.cyan(" \u25CB signed in") : col.gray(` - ${ep2.subtitle}`);
|
|
2563
|
+
return `${ep2.label.padEnd(26)}${badge}`;
|
|
2564
|
+
});
|
|
2565
|
+
const allItems = [...epItems, "Custom server URL..."];
|
|
2566
|
+
const idx = await pickMenu(allItems, { allowBack: true });
|
|
2567
|
+
if (idx === null) return null;
|
|
2568
|
+
if (idx === -1) return "home";
|
|
2569
|
+
if (idx === allItems.length - 1) {
|
|
2498
2570
|
await connectCustomUrl({ env, platform });
|
|
2499
2571
|
continue;
|
|
2500
2572
|
}
|
|
2501
|
-
const ep = ENDPOINTS[
|
|
2573
|
+
const ep = ENDPOINTS[idx];
|
|
2502
2574
|
print("");
|
|
2503
2575
|
const outcome = await connectEndpointInteractive({ backend: ep.key, label: ep.label, env, platform });
|
|
2504
2576
|
if (outcome.promptedInTui) {
|
|
@@ -2513,7 +2585,7 @@ async function connectCustomUrl({ env, platform }) {
|
|
|
2513
2585
|
const url = await ask("URL", "https://");
|
|
2514
2586
|
if (!url || url === "https://") return;
|
|
2515
2587
|
print("");
|
|
2516
|
-
print(col.gray(" Connecting
|
|
2588
|
+
print(col.gray(" Connecting..."));
|
|
2517
2589
|
const outcome = await connectEndpointInteractive({ apiUrl: url, label: url, env, platform });
|
|
2518
2590
|
if (outcome.promptedInTui) {
|
|
2519
2591
|
await pressEnterToContinue();
|
|
@@ -2534,14 +2606,20 @@ var COMMAND_GROUPS = [
|
|
|
2534
2606
|
{ cmd: "vendian cloud local serve --agents-dir .", desc: "Start agents" },
|
|
2535
2607
|
{ cmd: "vendian login --backend staging", desc: "Sign in to staging" }
|
|
2536
2608
|
] },
|
|
2609
|
+
{ section: "Syncing & deploying", commands: [
|
|
2610
|
+
{ cmd: "vendian cloud local push --collection-id ID --project-id PID", desc: "Push code to project repo" },
|
|
2611
|
+
{ cmd: "vendian cloud local push --branch feature/x --from dev", desc: "Push to a new branch" },
|
|
2612
|
+
{ cmd: "vendian cloud local deploy --collection-id ID --project-id PID", desc: "Deploy to cloud" }
|
|
2613
|
+
] },
|
|
2537
2614
|
{ section: "Maintenance", commands: [
|
|
2538
2615
|
{ cmd: "vendian doctor", desc: "Check if everything is set up" },
|
|
2539
2616
|
{ cmd: "vendian update", desc: "Update to the latest version" }
|
|
2540
2617
|
] }
|
|
2541
2618
|
];
|
|
2542
2619
|
async function showCommands() {
|
|
2620
|
+
clearScreen();
|
|
2543
2621
|
print("");
|
|
2544
|
-
print(col.bold(` \u2191 VENDIAN v${CLI_VERSION}
|
|
2622
|
+
print(col.bold(` \u2191 VENDIAN v${CLI_VERSION} - All Commands`));
|
|
2545
2623
|
print("");
|
|
2546
2624
|
for (const g of COMMAND_GROUPS) {
|
|
2547
2625
|
print(col.blue(col.bold(` ${g.section}`)));
|
|
@@ -2555,6 +2633,7 @@ async function showCommands() {
|
|
|
2555
2633
|
}
|
|
2556
2634
|
async function pickAgentsToRun({ env, platform, candidates }) {
|
|
2557
2635
|
if (candidates.length === 0) {
|
|
2636
|
+
clearScreen();
|
|
2558
2637
|
print("");
|
|
2559
2638
|
print(col.yellow(" Couldn't find any agents. Enter your agents folder path:"));
|
|
2560
2639
|
const input = await ask("Folder", "./agents");
|
|
@@ -2569,21 +2648,18 @@ async function pickAgentsToRun({ env, platform, candidates }) {
|
|
|
2569
2648
|
return pickProject({ env, platform, candidates });
|
|
2570
2649
|
}
|
|
2571
2650
|
async function pickProject({ env, platform, candidates }) {
|
|
2572
|
-
|
|
2651
|
+
clearScreen();
|
|
2573
2652
|
printHeader({ env, platform });
|
|
2574
2653
|
print("");
|
|
2575
2654
|
print(col.bold(" Which project do you want to run?"));
|
|
2576
2655
|
print("");
|
|
2577
|
-
candidates.
|
|
2656
|
+
const items = candidates.map((candidate) => {
|
|
2578
2657
|
const name = readManifestName(candidate.absolutePath) || friendlyName(path8.basename(candidate.absolutePath) || candidate.path);
|
|
2579
|
-
|
|
2658
|
+
return `${name.padEnd(32)} ${col.gray(`${candidate.agentCount} agent${candidate.agentCount === 1 ? "" : "s"}`)}`;
|
|
2580
2659
|
});
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
const
|
|
2584
|
-
const n = parseInt(ans, 10);
|
|
2585
|
-
if (n === 0 || isNaN(n) || n > candidates.length) return null;
|
|
2586
|
-
const chosen = candidates[n - 1];
|
|
2660
|
+
const idx = await pickMenu(items, { allowBack: true });
|
|
2661
|
+
if (idx === null || idx === -1) return null;
|
|
2662
|
+
const chosen = candidates[idx];
|
|
2587
2663
|
if (chosen.agentCount <= 1) return { agentsDir: chosen.path };
|
|
2588
2664
|
return pickAgentsFromFolder({ env, platform, candidate: chosen });
|
|
2589
2665
|
}
|
|
@@ -2594,23 +2670,23 @@ async function pickAgentsFromFolder({ env, platform, candidate }) {
|
|
|
2594
2670
|
...f,
|
|
2595
2671
|
displayName: readManifestName(f.absolutePath) || friendlyName(f.name || path8.basename(f.path))
|
|
2596
2672
|
}));
|
|
2597
|
-
|
|
2673
|
+
clearScreen();
|
|
2598
2674
|
printHeader({ env, platform });
|
|
2599
2675
|
print("");
|
|
2600
2676
|
print(col.bold(" Which agents do you want to start?"));
|
|
2601
2677
|
print("");
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
const
|
|
2607
|
-
|
|
2608
|
-
if (
|
|
2609
|
-
|
|
2610
|
-
return { agentsDir: named[n - 2].path };
|
|
2678
|
+
const items = [
|
|
2679
|
+
col.bold(`Run all ${folders.length} agents`),
|
|
2680
|
+
...named.map((f) => f.displayName)
|
|
2681
|
+
];
|
|
2682
|
+
const idx = await pickMenu(items, { allowBack: true });
|
|
2683
|
+
if (idx === null || idx === -1) return null;
|
|
2684
|
+
if (idx === 0) return { agentsDir: candidate.path };
|
|
2685
|
+
return { agentsDir: named[idx - 1].path };
|
|
2611
2686
|
}
|
|
2612
2687
|
async function pickSingleAgentToRun({ env, platform, candidates }) {
|
|
2613
2688
|
if (candidates.length === 0) {
|
|
2689
|
+
clearScreen();
|
|
2614
2690
|
print("");
|
|
2615
2691
|
print(col.yellow(" Couldn't find any agents."));
|
|
2616
2692
|
const input = await ask("Agent folder", "./agents/my-agent");
|
|
@@ -2631,24 +2707,19 @@ async function pickSingleAgentToRun({ env, platform, candidates }) {
|
|
|
2631
2707
|
}];
|
|
2632
2708
|
});
|
|
2633
2709
|
if (agents.length === 1) return agents[0];
|
|
2634
|
-
|
|
2710
|
+
clearScreen();
|
|
2635
2711
|
printHeader({ env, platform });
|
|
2636
2712
|
print("");
|
|
2637
2713
|
print(col.bold(" Which agent do you want to run?"));
|
|
2638
2714
|
print("");
|
|
2639
|
-
agents.
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
print("");
|
|
2644
|
-
const ans = await ask("Choose");
|
|
2645
|
-
const n = parseInt(ans, 10);
|
|
2646
|
-
if (n === 0 || isNaN(n) || n > agents.length) return null;
|
|
2647
|
-
return agents[n - 1];
|
|
2715
|
+
const items = agents.map((a) => `${a.displayName.padEnd(32)} ${col.gray(a.path)}`);
|
|
2716
|
+
const idx = await pickMenu(items, { allowBack: true });
|
|
2717
|
+
if (idx === null || idx === -1) return null;
|
|
2718
|
+
return agents[idx];
|
|
2648
2719
|
}
|
|
2649
2720
|
async function chooseCloudWorkspace({ env, platform, loadingTitle, pickerTitle } = {}) {
|
|
2650
2721
|
print("");
|
|
2651
|
-
process.stdout.write(` ${col.gray(loadingTitle || "Loading workspaces
|
|
2722
|
+
process.stdout.write(` ${col.gray(loadingTitle || "Loading workspaces...")}
|
|
2652
2723
|
`);
|
|
2653
2724
|
let wsResult;
|
|
2654
2725
|
try {
|
|
@@ -2679,22 +2750,20 @@ async function chooseCloudWorkspace({ env, platform, loadingTitle, pickerTitle }
|
|
|
2679
2750
|
const ws2 = wsResult.workspaces[0];
|
|
2680
2751
|
return { id: ws2.id || "", label: workspaceLabel(ws2) };
|
|
2681
2752
|
}
|
|
2753
|
+
clearScreen();
|
|
2682
2754
|
print("");
|
|
2683
|
-
|
|
2755
|
+
printHeader({ env, platform });
|
|
2684
2756
|
print("");
|
|
2685
|
-
|
|
2686
|
-
print(` ${col.blue(String(i + 1))} ${workspaceLabel(ws2)}`);
|
|
2687
|
-
});
|
|
2688
|
-
print(` ${col.gray("0 Back")}`);
|
|
2757
|
+
print(col.bold(` ${pickerTitle || "Choose a workspace:"}`));
|
|
2689
2758
|
print("");
|
|
2690
|
-
const
|
|
2691
|
-
const
|
|
2692
|
-
if (
|
|
2693
|
-
const ws = wsResult.workspaces[
|
|
2759
|
+
const items = wsResult.workspaces.map((ws2) => workspaceLabel(ws2));
|
|
2760
|
+
const idx = await pickMenu(items, { allowBack: true });
|
|
2761
|
+
if (idx === null || idx === -1) return null;
|
|
2762
|
+
const ws = wsResult.workspaces[idx];
|
|
2694
2763
|
return { id: ws.id || "", label: workspaceLabel(ws) };
|
|
2695
2764
|
}
|
|
2696
2765
|
async function showCreate({ env, platform }) {
|
|
2697
|
-
|
|
2766
|
+
clearScreen();
|
|
2698
2767
|
printHeader({ env, platform });
|
|
2699
2768
|
print("");
|
|
2700
2769
|
print(col.bold(" Create a new agent"));
|
|
@@ -2715,7 +2784,7 @@ async function showRun({ env, platform }) {
|
|
|
2715
2784
|
const workspace = await chooseCloudWorkspace({
|
|
2716
2785
|
env,
|
|
2717
2786
|
platform,
|
|
2718
|
-
loadingTitle: "Getting ready to run this agent
|
|
2787
|
+
loadingTitle: "Getting ready to run this agent...",
|
|
2719
2788
|
pickerTitle: "Which project should own this run?"
|
|
2720
2789
|
});
|
|
2721
2790
|
if (!workspace) return "home";
|
|
@@ -2738,7 +2807,7 @@ async function showServe({ env, platform }) {
|
|
|
2738
2807
|
const workspace = await chooseCloudWorkspace({
|
|
2739
2808
|
env,
|
|
2740
2809
|
platform,
|
|
2741
|
-
loadingTitle: "Getting ready to run your agents
|
|
2810
|
+
loadingTitle: "Getting ready to run your agents...",
|
|
2742
2811
|
pickerTitle: "Which project do you want to run?"
|
|
2743
2812
|
});
|
|
2744
2813
|
if (!workspace) return "home";
|
|
@@ -2754,7 +2823,11 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId, wsLab
|
|
|
2754
2823
|
let stopTimer = null;
|
|
2755
2824
|
let dashboardClosed = false;
|
|
2756
2825
|
let logStore = null;
|
|
2826
|
+
let lastAgentOnlinePrint = 0;
|
|
2827
|
+
let agentsSeenOnline = false;
|
|
2828
|
+
let initialSetupDone = false;
|
|
2757
2829
|
const W = Math.min(process.stdout.columns || 80, 100);
|
|
2830
|
+
clearScreen();
|
|
2758
2831
|
setCursorVisible(false);
|
|
2759
2832
|
print("");
|
|
2760
2833
|
print(col.gray("\u2550".repeat(W)));
|
|
@@ -2787,23 +2860,60 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId, wsLab
|
|
|
2787
2860
|
if (!event) return;
|
|
2788
2861
|
const type = String(event.type || "");
|
|
2789
2862
|
const agentPath = String(event.relativePath || event.path || "");
|
|
2790
|
-
const agentName = agentPath ? friendlyName(path8.basename(agentPath)) || agentPath : "";
|
|
2863
|
+
const agentName = agentPath ? friendlyName(path8.basename(agentPath)) || agentPath : ".";
|
|
2864
|
+
if (type === "daemon_wake_received") return;
|
|
2865
|
+
if (type === "lease_claim_no_job") return;
|
|
2866
|
+
if (type === "dispatch_job_received" || type === "dispatch_job_acked") return;
|
|
2867
|
+
if (type === "inventory_synced") {
|
|
2868
|
+
const agents = Array.isArray(event.agents) ? event.agents : [];
|
|
2869
|
+
const hasProblems = agents.some((a) => a.status === "error" || a.status === "disabled");
|
|
2870
|
+
const allOnline = agents.length > 0 && agents.every((a) => a.status === "online");
|
|
2871
|
+
const now = Date.now();
|
|
2872
|
+
if (!hasProblems && allOnline && agentsSeenOnline && now - lastAgentOnlinePrint < 12e4) return;
|
|
2873
|
+
for (const a of agents) {
|
|
2874
|
+
const name = friendlyName(path8.basename(a.relativePath || ".")) || a.manifestName || a.relativePath || "?";
|
|
2875
|
+
if (a.status === "error") {
|
|
2876
|
+
printAgent(name, col.red(`\u2716 Error: ${a.errorMessage || ""}`));
|
|
2877
|
+
continue;
|
|
2878
|
+
}
|
|
2879
|
+
if (a.status === "disabled") {
|
|
2880
|
+
printAgent(name, col.yellow(`\u26A0 Disabled: ${a.disabledReason || ""}`));
|
|
2881
|
+
continue;
|
|
2882
|
+
}
|
|
2883
|
+
if (a.status === "online") {
|
|
2884
|
+
printAgent(name, col.green("\u25CF Online"));
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
if (allOnline) {
|
|
2888
|
+
lastAgentOnlinePrint = now;
|
|
2889
|
+
agentsSeenOnline = true;
|
|
2890
|
+
initialSetupDone = true;
|
|
2891
|
+
}
|
|
2892
|
+
return;
|
|
2893
|
+
}
|
|
2791
2894
|
if (type === "job_started") {
|
|
2792
|
-
|
|
2895
|
+
print("");
|
|
2896
|
+
printRun(agentName, col.blue("\u25B6"), col.bold(`Started run ${shortId2(event.runId || "")}`));
|
|
2793
2897
|
return;
|
|
2794
2898
|
}
|
|
2795
2899
|
if (type === "job_completed") {
|
|
2796
2900
|
const ok = event.success !== false;
|
|
2797
|
-
|
|
2901
|
+
const errText = ok ? "" : fmtErr(event.error) || "check serve logs for details";
|
|
2902
|
+
printRun(agentName, ok ? col.green("\u2714") : col.red("\u2716"), ok ? col.green("Completed") : col.red(`Failed: ${errText}`));
|
|
2903
|
+
print("");
|
|
2798
2904
|
return;
|
|
2799
2905
|
}
|
|
2800
2906
|
if (type === "run_log") {
|
|
2801
2907
|
const lvl = String(event.level || "info");
|
|
2802
|
-
const
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2908
|
+
const evtType = String(event.eventType || "");
|
|
2909
|
+
const msg = String(
|
|
2910
|
+
event.message || (event.data?.label ? event.data.label : null) || (event.stepId ? `${evtType === "step_event" ? "Step" : evtType}: ${event.stepId}` : null) || evtType || ""
|
|
2911
|
+
);
|
|
2912
|
+
if (!msg || msg === "heartbeat") return;
|
|
2913
|
+
if (evtType === "start" && msg === "Run started") return;
|
|
2914
|
+
const isCompletionEvent = evtType === "completion";
|
|
2915
|
+
const icon = lvl === "error" ? col.red("\u2716") : isCompletionEvent ? event.success !== false ? col.green("\u2714") : col.red("\u2716") : col.cyan("\u2502");
|
|
2916
|
+
printRun(agentName, icon, clip(msg, 90));
|
|
2807
2917
|
return;
|
|
2808
2918
|
}
|
|
2809
2919
|
if (type === "error" && agentPath) {
|
|
@@ -2811,7 +2921,7 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId, wsLab
|
|
|
2811
2921
|
return;
|
|
2812
2922
|
}
|
|
2813
2923
|
if (type === "agent_prepare_started") {
|
|
2814
|
-
printAgent(agentName, col.gray("Preparing
|
|
2924
|
+
printAgent(agentName, col.gray("Preparing..."));
|
|
2815
2925
|
return;
|
|
2816
2926
|
}
|
|
2817
2927
|
if (type === "agent_prepare_progress") {
|
|
@@ -2831,28 +2941,10 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId, wsLab
|
|
|
2831
2941
|
printAgent(agentName, col.green("\u2714 Ready"));
|
|
2832
2942
|
return;
|
|
2833
2943
|
}
|
|
2834
|
-
if (type === "inventory_synced") {
|
|
2835
|
-
const agents = Array.isArray(event.agents) ? event.agents : [];
|
|
2836
|
-
for (const a of agents) {
|
|
2837
|
-
const name = friendlyName(path8.basename(a.relativePath || ".")) || a.manifestName || a.relativePath || "?";
|
|
2838
|
-
if (a.status === "error") {
|
|
2839
|
-
printAgent(name, col.red(`\u2716 Error: ${a.errorMessage || ""}`));
|
|
2840
|
-
continue;
|
|
2841
|
-
}
|
|
2842
|
-
if (a.status === "disabled") {
|
|
2843
|
-
printAgent(name, col.yellow(`\u26A0 Disabled: ${a.disabledReason || ""}`));
|
|
2844
|
-
continue;
|
|
2845
|
-
}
|
|
2846
|
-
if (a.status === "online") {
|
|
2847
|
-
printAgent(name, col.green("\u25CF Online"));
|
|
2848
|
-
continue;
|
|
2849
|
-
}
|
|
2850
|
-
}
|
|
2851
|
-
return;
|
|
2852
|
-
}
|
|
2853
2944
|
const dbgArr = serveDebugEntries([event], 1);
|
|
2854
2945
|
if (dbgArr.length > 0) {
|
|
2855
2946
|
const dbg = dbgArr[0];
|
|
2947
|
+
if (initialSetupDone && dbg.level === "info") return;
|
|
2856
2948
|
const msg = dbg.level === "error" ? col.red(dbg.message) : dbg.level === "warn" ? col.yellow(dbg.message) : col.gray(dbg.message);
|
|
2857
2949
|
printDaemon(dbg.eventType, msg);
|
|
2858
2950
|
}
|
|
@@ -2871,7 +2963,7 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId, wsLab
|
|
|
2871
2963
|
platform,
|
|
2872
2964
|
onProgress: (msg) => {
|
|
2873
2965
|
if (dashboardClosed) return;
|
|
2874
|
-
process.stdout.write(`\r ${col.gray(clip(msg || "Preparing
|
|
2966
|
+
process.stdout.write(`\r ${col.gray(clip(msg || "Preparing...", 70))} `);
|
|
2875
2967
|
}
|
|
2876
2968
|
});
|
|
2877
2969
|
process.stdout.write("\r" + " ".repeat(80) + "\r");
|
|
@@ -2988,7 +3080,10 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId, wsLab
|
|
|
2988
3080
|
const text = String(chunk).trim();
|
|
2989
3081
|
if (!text) return;
|
|
2990
3082
|
stderrChunks.push(text);
|
|
2991
|
-
|
|
3083
|
+
const isNoise = /^\[local\]\s+(running|uploading|preparing)/i.test(text) || /^(Resolved|Audited|Using Python)\b/i.test(text);
|
|
3084
|
+
if (!isNoise) {
|
|
3085
|
+
printDaemon("stderr", col.yellow(clip(text, 120)));
|
|
3086
|
+
}
|
|
2992
3087
|
state = applyServeEvent(state, {
|
|
2993
3088
|
type: "daemon_stderr",
|
|
2994
3089
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3016,7 +3111,7 @@ async function runServeDashboard({ env, platform, agentsDir, collectionId, wsLab
|
|
|
3016
3111
|
} catch {
|
|
3017
3112
|
}
|
|
3018
3113
|
removeKeypress();
|
|
3019
|
-
process.stdout.write("\n Press Enter to return to menu
|
|
3114
|
+
process.stdout.write("\n Press Enter to return to menu... ");
|
|
3020
3115
|
const rl = makeRl();
|
|
3021
3116
|
rl.once("line", () => {
|
|
3022
3117
|
rl.close();
|
|
@@ -3128,7 +3223,7 @@ async function connectEndpointInteractive({
|
|
|
3128
3223
|
const status = cloudAuthStatus({ backend, apiUrl, env, platform });
|
|
3129
3224
|
const destination = label || envLabel(status.apiUrl);
|
|
3130
3225
|
if (status.authenticated) {
|
|
3131
|
-
print(col.gray(` Connecting to ${destination}
|
|
3226
|
+
print(col.gray(` Connecting to ${destination}...`));
|
|
3132
3227
|
try {
|
|
3133
3228
|
await switchOrLoginEndpoint({ backend, apiUrl, env, platform, setupFn, activateFn });
|
|
3134
3229
|
print(col.green(` ${fig.check} ${successLabel || `Signed in to ${destination} successfully`}`));
|
|
@@ -3189,6 +3284,8 @@ function helpText() {
|
|
|
3189
3284
|
" vendian validate ./agents/my-agent --runtime",
|
|
3190
3285
|
" vendian models",
|
|
3191
3286
|
" vendian cloud local serve --agents-dir ./agents",
|
|
3287
|
+
" vendian cloud local push --collection-id ID --project-id PID --branch dev",
|
|
3288
|
+
" vendian cloud local push --branch feature/x --from dev",
|
|
3192
3289
|
" vendian doctor",
|
|
3193
3290
|
" vendian update",
|
|
3194
3291
|
"",
|
|
@@ -3213,7 +3310,7 @@ function readManifestName(absoluteFolderPath) {
|
|
|
3213
3310
|
}
|
|
3214
3311
|
function clip(value, length) {
|
|
3215
3312
|
const text = String(value || "");
|
|
3216
|
-
return text.length <= length ? text : `${text.slice(0, Math.max(0, length - 1))}
|
|
3313
|
+
return text.length <= length ? text : `${text.slice(0, Math.max(0, length - 1))}...`;
|
|
3217
3314
|
}
|
|
3218
3315
|
function errMsg(error) {
|
|
3219
3316
|
return error && typeof error.message === "string" ? error.message : String(error);
|