@proagentstore/cli 0.1.12 → 0.1.14
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/dist/index.js +148 -26
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -848,9 +848,6 @@ function createRunnerCommand() {
|
|
|
848
848
|
setTimeout(() => reject(new Error("timed out waiting for cloudflared tunnel URL")), 45e3).unref();
|
|
849
849
|
});
|
|
850
850
|
writeLine(`Tunnel ready: ${tunnelUrl}`);
|
|
851
|
-
writeLine("Waiting for tunnel DNS to propagate (up to 60s)...");
|
|
852
|
-
await waitForLocalRunner({ url: tunnelUrl, token: runnerToken, instanceId }, 6e4);
|
|
853
|
-
writeLine("Tunnel health check passed \u2713");
|
|
854
851
|
const capabilities = await requestRunner("GET", "/capabilities", {
|
|
855
852
|
url: tunnelUrl,
|
|
856
853
|
token: runnerToken,
|
|
@@ -864,18 +861,6 @@ function createRunnerCommand() {
|
|
|
864
861
|
runnerVersion: clean(opts.runnerVersion) || ""
|
|
865
862
|
});
|
|
866
863
|
writeLine("Runtime registered with PAGS \u2713");
|
|
867
|
-
if (!opts.skipProbe) {
|
|
868
|
-
try {
|
|
869
|
-
await requestPags(
|
|
870
|
-
"GET",
|
|
871
|
-
`/v1/instances/${apiPathSegment(instanceId)}/runtime/status`,
|
|
872
|
-
opts
|
|
873
|
-
);
|
|
874
|
-
writeLine("PAGS can reach your runtime \u2713");
|
|
875
|
-
} catch {
|
|
876
|
-
writeLine("\u26A0\uFE0F PAGS probe failed \u2014 the tunnel may need more time");
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
864
|
writeLine("");
|
|
880
865
|
writeLine("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
881
866
|
writeLine(" \u2705 CONNECTED \u2014 Browser runner is live");
|
|
@@ -1004,16 +989,95 @@ function createRunnerCommand() {
|
|
|
1004
989
|
|
|
1005
990
|
// src/commands/up.ts
|
|
1006
991
|
import { Command as Command7 } from "commander";
|
|
992
|
+
|
|
993
|
+
// src/tui.ts
|
|
994
|
+
import chalk from "chalk";
|
|
995
|
+
import readline from "readline";
|
|
996
|
+
var ACCENT = "#7c3aed";
|
|
997
|
+
var c = chalk.hex(ACCENT);
|
|
998
|
+
var d = chalk.dim;
|
|
999
|
+
var w = chalk.white;
|
|
1000
|
+
var pad = " ";
|
|
1001
|
+
var LOGO = [
|
|
1002
|
+
"\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
|
|
1003
|
+
"\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D",
|
|
1004
|
+
"\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
|
|
1005
|
+
"\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551",
|
|
1006
|
+
"\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551",
|
|
1007
|
+
"\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
|
|
1008
|
+
];
|
|
1009
|
+
function clearScreen() {
|
|
1010
|
+
console.clear();
|
|
1011
|
+
}
|
|
1012
|
+
function printLogo() {
|
|
1013
|
+
console.log("");
|
|
1014
|
+
for (const line of LOGO) {
|
|
1015
|
+
console.log(pad + c(line));
|
|
1016
|
+
}
|
|
1017
|
+
console.log("");
|
|
1018
|
+
}
|
|
1019
|
+
function printStatus(state) {
|
|
1020
|
+
clearScreen();
|
|
1021
|
+
printLogo();
|
|
1022
|
+
const statusIcon = (s) => {
|
|
1023
|
+
if (s === "online" || s === "registered") return chalk.green("\u25CF");
|
|
1024
|
+
if (s === "starting" || s === "pending") return chalk.yellow("\u25C9");
|
|
1025
|
+
if (s === "error" || s === "failed") return chalk.red("\u25CF");
|
|
1026
|
+
return d("\u25CB");
|
|
1027
|
+
};
|
|
1028
|
+
const statusText = (s) => {
|
|
1029
|
+
if (s === "online" || s === "registered") return chalk.green(s);
|
|
1030
|
+
if (s === "starting" || s === "pending") return chalk.yellow(s);
|
|
1031
|
+
if (s === "error" || s === "failed") return chalk.red(s);
|
|
1032
|
+
return d(s);
|
|
1033
|
+
};
|
|
1034
|
+
console.log(pad + d("User ") + w(state.user));
|
|
1035
|
+
console.log(pad + d("Instance ") + w(state.activeInstance));
|
|
1036
|
+
console.log(pad + d("Runner ") + statusIcon(state.runner) + " " + statusText(state.runner));
|
|
1037
|
+
console.log(pad + d("Tunnel ") + statusIcon(state.tunnel) + " " + statusText(state.tunnel));
|
|
1038
|
+
console.log(pad + d("PAGS ") + statusIcon(state.registration) + " " + statusText(state.registration));
|
|
1039
|
+
if (state.tunnelUrl) {
|
|
1040
|
+
console.log(pad + d("URL ") + c(state.tunnelUrl));
|
|
1041
|
+
}
|
|
1042
|
+
console.log("");
|
|
1043
|
+
if (state.lastEvent) {
|
|
1044
|
+
console.log(pad + d("Last: ") + d(state.lastEvent));
|
|
1045
|
+
}
|
|
1046
|
+
console.log("");
|
|
1047
|
+
console.log(
|
|
1048
|
+
pad + c("r") + d(" Refresh ") + c("l") + d(" Logs ") + c("q") + d(" Quit")
|
|
1049
|
+
);
|
|
1050
|
+
console.log("");
|
|
1051
|
+
}
|
|
1052
|
+
function printStep(label, status) {
|
|
1053
|
+
const icon = status === "ok" ? chalk.green("\u2713") : status === "fail" ? chalk.red("\u2717") : chalk.yellow("\u2026");
|
|
1054
|
+
console.log(pad + icon + " " + label);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// src/commands/up.ts
|
|
1007
1058
|
var API_BASE2 = "https://api.proagentstore.online";
|
|
1008
1059
|
var upCommand = new Command7("up").description("Start the browser runner for all your agent instances").option("--headless", "Run browser in headless mode").option("--instance <id>", "Connect to a specific instance only").action(async (opts) => {
|
|
1009
1060
|
const session = requireSession();
|
|
1010
|
-
|
|
1011
|
-
|
|
1061
|
+
const state = {
|
|
1062
|
+
user: session.user.login,
|
|
1063
|
+
instances: [],
|
|
1064
|
+
activeInstance: "",
|
|
1065
|
+
runner: "starting",
|
|
1066
|
+
tunnel: "offline",
|
|
1067
|
+
tunnelUrl: "",
|
|
1068
|
+
registration: "pending",
|
|
1069
|
+
lastEvent: "Fetching instances...",
|
|
1070
|
+
taskCount: 0
|
|
1071
|
+
};
|
|
1072
|
+
clearScreen();
|
|
1073
|
+
printLogo();
|
|
1074
|
+
printStep("Signed in as " + session.user.login, "ok");
|
|
1075
|
+
printStep("Fetching instances...", "wait");
|
|
1012
1076
|
const res = await fetch(`${API_BASE2}/v1/instances/my/instances`, {
|
|
1013
1077
|
headers: { Authorization: `Bearer ${session.token}` }
|
|
1014
1078
|
});
|
|
1015
1079
|
if (!res.ok) {
|
|
1016
|
-
|
|
1080
|
+
printStep("Failed to fetch instances: " + res.status, "fail");
|
|
1017
1081
|
process.exit(1);
|
|
1018
1082
|
}
|
|
1019
1083
|
const data = await res.json();
|
|
@@ -1022,26 +1086,84 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1022
1086
|
instances = instances.filter((i) => i.id === opts.instance || i.slug === opts.instance);
|
|
1023
1087
|
}
|
|
1024
1088
|
if (instances.length === 0) {
|
|
1025
|
-
|
|
1089
|
+
printStep("No active instances found", "fail");
|
|
1090
|
+
writeLine(" Subscribe to an agent at https://proagentstore.online");
|
|
1026
1091
|
process.exit(1);
|
|
1027
1092
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1093
|
+
state.instances = instances.map((i) => ({ id: i.id, name: i.name || i.slug || i.id.slice(0, 8) }));
|
|
1094
|
+
printStep(`Found ${instances.length} instance${instances.length === 1 ? "" : "s"}`, "ok");
|
|
1095
|
+
for (const inst of state.instances) {
|
|
1096
|
+
writeLine(` ${inst.name} (${inst.id.slice(0, 8)}...)`);
|
|
1031
1097
|
}
|
|
1032
1098
|
const target = instances[0];
|
|
1033
|
-
|
|
1034
|
-
Connecting
|
|
1099
|
+
state.activeInstance = target.name || target.slug || target.id.slice(0, 8);
|
|
1100
|
+
printStep(`Connecting: ${state.activeInstance}`, "wait");
|
|
1035
1101
|
const { spawn: spawn3 } = await import("child_process");
|
|
1036
1102
|
const cliPath = process.argv[1];
|
|
1037
1103
|
const args = [cliPath, "runner", "connect", target.id];
|
|
1038
1104
|
if (opts.headless) args.push("--headless");
|
|
1039
1105
|
const child = spawn3(process.execPath, args, {
|
|
1040
|
-
stdio: "
|
|
1106
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1041
1107
|
env: { ...process.env, PAGS_TOKEN: session.token }
|
|
1042
1108
|
});
|
|
1109
|
+
let tunnelUrl = "";
|
|
1110
|
+
const handleOutput = (data2) => {
|
|
1111
|
+
const text = data2.toString("utf-8");
|
|
1112
|
+
for (const line of text.split("\n")) {
|
|
1113
|
+
const trimmed = line.trim();
|
|
1114
|
+
if (!trimmed) continue;
|
|
1115
|
+
const tunnelMatch = trimmed.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/i);
|
|
1116
|
+
if (tunnelMatch) {
|
|
1117
|
+
tunnelUrl = tunnelMatch[0];
|
|
1118
|
+
state.tunnel = "online";
|
|
1119
|
+
state.tunnelUrl = tunnelUrl;
|
|
1120
|
+
state.lastEvent = "Tunnel created";
|
|
1121
|
+
printStatus(state);
|
|
1122
|
+
continue;
|
|
1123
|
+
}
|
|
1124
|
+
if (trimmed.includes("FAGS browser runtime listening")) {
|
|
1125
|
+
state.runner = "online";
|
|
1126
|
+
state.lastEvent = "Runner started";
|
|
1127
|
+
printStatus(state);
|
|
1128
|
+
continue;
|
|
1129
|
+
}
|
|
1130
|
+
if (trimmed.includes("Runtime registered") || trimmed.includes("CONNECTED")) {
|
|
1131
|
+
state.registration = "registered";
|
|
1132
|
+
state.lastEvent = "Registered with PAGS";
|
|
1133
|
+
printStatus(state);
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
if (trimmed.includes("fetch failed") || trimmed.includes("error")) {
|
|
1137
|
+
state.lastEvent = trimmed.slice(0, 80);
|
|
1138
|
+
if (trimmed.includes("fetch failed")) {
|
|
1139
|
+
state.registration = "failed";
|
|
1140
|
+
}
|
|
1141
|
+
printStatus(state);
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
if (trimmed.includes("INF ") && !tunnelMatch) continue;
|
|
1145
|
+
state.lastEvent = trimmed.slice(0, 80);
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
child.stdout?.on("data", handleOutput);
|
|
1149
|
+
child.stderr?.on("data", handleOutput);
|
|
1043
1150
|
child.on("exit", (code) => {
|
|
1044
|
-
|
|
1151
|
+
if (code && code !== 0) {
|
|
1152
|
+
state.runner = "error";
|
|
1153
|
+
state.lastEvent = `Runner exited with code ${code}`;
|
|
1154
|
+
printStatus(state);
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
const shutdown = () => {
|
|
1158
|
+
child.kill();
|
|
1159
|
+
clearScreen();
|
|
1160
|
+
writeLine(" Runner stopped.");
|
|
1161
|
+
process.exit(0);
|
|
1162
|
+
};
|
|
1163
|
+
process.on("SIGINT", shutdown);
|
|
1164
|
+
process.on("SIGTERM", shutdown);
|
|
1165
|
+
await new Promise((resolve5) => {
|
|
1166
|
+
child.on("exit", () => resolve5());
|
|
1045
1167
|
});
|
|
1046
1168
|
});
|
|
1047
1169
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proagentstore/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "CLI for creating, publishing, and running ProAgentStore agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,14 +30,15 @@
|
|
|
30
30
|
"typecheck": "tsc --noEmit"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"chalk": "^5.6.2",
|
|
33
34
|
"commander": "^13.0.0",
|
|
34
35
|
"playwright": "^1.60.0"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
38
|
+
"@types/node": "^22.0.0",
|
|
37
39
|
"tsup": "^8.4.0",
|
|
38
40
|
"tsx": "^4.21.0",
|
|
39
|
-
"typescript": "^5.7.0"
|
|
40
|
-
"@types/node": "^22.0.0"
|
|
41
|
+
"typescript": "^5.7.0"
|
|
41
42
|
},
|
|
42
43
|
"files": [
|
|
43
44
|
"dist"
|