@proagentstore/cli 0.1.13 → 0.1.15
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 +214 -11
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -989,16 +989,119 @@ function createRunnerCommand() {
|
|
|
989
989
|
|
|
990
990
|
// src/commands/up.ts
|
|
991
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
|
+
async function waitForKey(keys) {
|
|
1057
|
+
return new Promise((resolve5) => {
|
|
1058
|
+
readline.emitKeypressEvents(process.stdin);
|
|
1059
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(true);
|
|
1060
|
+
process.stdin.resume();
|
|
1061
|
+
const onKeypress = (str, key) => {
|
|
1062
|
+
if (key?.ctrl && key.name === "c") {
|
|
1063
|
+
cleanup();
|
|
1064
|
+
process.exit(0);
|
|
1065
|
+
}
|
|
1066
|
+
const val = (str || "").trim().toLowerCase();
|
|
1067
|
+
if (keys.includes(val)) {
|
|
1068
|
+
cleanup();
|
|
1069
|
+
resolve5(val);
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
const cleanup = () => {
|
|
1073
|
+
process.stdin.off("keypress", onKeypress);
|
|
1074
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
1075
|
+
process.stdin.pause();
|
|
1076
|
+
};
|
|
1077
|
+
process.stdin.on("keypress", onKeypress);
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// src/commands/up.ts
|
|
992
1082
|
var API_BASE2 = "https://api.proagentstore.online";
|
|
993
1083
|
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) => {
|
|
994
1084
|
const session = requireSession();
|
|
995
|
-
|
|
996
|
-
|
|
1085
|
+
const state = {
|
|
1086
|
+
user: session.user.login,
|
|
1087
|
+
instances: [],
|
|
1088
|
+
activeInstance: "",
|
|
1089
|
+
runner: "starting",
|
|
1090
|
+
tunnel: "offline",
|
|
1091
|
+
tunnelUrl: "",
|
|
1092
|
+
registration: "pending",
|
|
1093
|
+
lastEvent: "Fetching instances...",
|
|
1094
|
+
taskCount: 0
|
|
1095
|
+
};
|
|
1096
|
+
clearScreen();
|
|
1097
|
+
printLogo();
|
|
1098
|
+
printStep("Signed in as " + session.user.login, "ok");
|
|
1099
|
+
printStep("Fetching instances...", "wait");
|
|
997
1100
|
const res = await fetch(`${API_BASE2}/v1/instances/my/instances`, {
|
|
998
1101
|
headers: { Authorization: `Bearer ${session.token}` }
|
|
999
1102
|
});
|
|
1000
1103
|
if (!res.ok) {
|
|
1001
|
-
|
|
1104
|
+
printStep("Failed to fetch instances: " + res.status, "fail");
|
|
1002
1105
|
process.exit(1);
|
|
1003
1106
|
}
|
|
1004
1107
|
const data = await res.json();
|
|
@@ -1007,27 +1110,127 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1007
1110
|
instances = instances.filter((i) => i.id === opts.instance || i.slug === opts.instance);
|
|
1008
1111
|
}
|
|
1009
1112
|
if (instances.length === 0) {
|
|
1010
|
-
|
|
1113
|
+
printStep("No active instances found", "fail");
|
|
1114
|
+
writeLine(" Subscribe to an agent at https://proagentstore.online");
|
|
1011
1115
|
process.exit(1);
|
|
1012
1116
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1117
|
+
state.instances = instances.map((i) => ({ id: i.id, name: i.name || i.slug || i.id.slice(0, 8) }));
|
|
1118
|
+
printStep(`Found ${instances.length} instance${instances.length === 1 ? "" : "s"}`, "ok");
|
|
1119
|
+
for (const inst of state.instances) {
|
|
1120
|
+
writeLine(` ${inst.name} (${inst.id.slice(0, 8)}...)`);
|
|
1016
1121
|
}
|
|
1017
1122
|
const target = instances[0];
|
|
1018
|
-
|
|
1019
|
-
Connecting
|
|
1123
|
+
state.activeInstance = target.name || target.slug || target.id.slice(0, 8);
|
|
1124
|
+
printStep(`Connecting: ${state.activeInstance}`, "wait");
|
|
1020
1125
|
const { spawn: spawn3 } = await import("child_process");
|
|
1021
1126
|
const cliPath = process.argv[1];
|
|
1022
1127
|
const args = [cliPath, "runner", "connect", target.id];
|
|
1023
1128
|
if (opts.headless) args.push("--headless");
|
|
1024
1129
|
const child = spawn3(process.execPath, args, {
|
|
1025
|
-
stdio: "
|
|
1130
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1026
1131
|
env: { ...process.env, PAGS_TOKEN: session.token }
|
|
1027
1132
|
});
|
|
1133
|
+
const logs = [];
|
|
1134
|
+
const handleOutput = (data2) => {
|
|
1135
|
+
const text = data2.toString("utf-8");
|
|
1136
|
+
for (const line of text.split("\n")) {
|
|
1137
|
+
const trimmed = line.trim();
|
|
1138
|
+
if (!trimmed) continue;
|
|
1139
|
+
logs.push(trimmed);
|
|
1140
|
+
if (logs.length > 200) logs.shift();
|
|
1141
|
+
const tunnelMatch = trimmed.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/i);
|
|
1142
|
+
if (tunnelMatch) {
|
|
1143
|
+
state.tunnel = "online";
|
|
1144
|
+
state.tunnelUrl = tunnelMatch[0];
|
|
1145
|
+
state.lastEvent = "Tunnel created";
|
|
1146
|
+
printStatus(state);
|
|
1147
|
+
continue;
|
|
1148
|
+
}
|
|
1149
|
+
if (trimmed.includes("FAGS browser runtime listening")) {
|
|
1150
|
+
state.runner = "online";
|
|
1151
|
+
state.lastEvent = "Runner started";
|
|
1152
|
+
printStatus(state);
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
if (trimmed.includes("Runtime registered") || trimmed.includes("CONNECTED")) {
|
|
1156
|
+
state.registration = "registered";
|
|
1157
|
+
state.lastEvent = "Registered with PAGS \u2014 ready for tasks";
|
|
1158
|
+
printStatus(state);
|
|
1159
|
+
continue;
|
|
1160
|
+
}
|
|
1161
|
+
if (trimmed.includes("fetch failed")) {
|
|
1162
|
+
state.registration = "failed";
|
|
1163
|
+
state.lastEvent = "PAGS registration failed (will retry on next task)";
|
|
1164
|
+
printStatus(state);
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
if (trimmed.includes("INF ")) continue;
|
|
1168
|
+
if (/error|Error|EADDRINUSE|ECONNREFUSED|failed/i.test(trimmed)) {
|
|
1169
|
+
state.lastEvent = trimmed.slice(0, 80);
|
|
1170
|
+
printStatus(state);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
child.stdout?.on("data", handleOutput);
|
|
1175
|
+
child.stderr?.on("data", handleOutput);
|
|
1176
|
+
let childDead = false;
|
|
1028
1177
|
child.on("exit", (code) => {
|
|
1029
|
-
|
|
1178
|
+
childDead = true;
|
|
1179
|
+
if (code && code !== 0) {
|
|
1180
|
+
state.runner = "error";
|
|
1181
|
+
state.lastEvent = `Runner exited (code ${code})`;
|
|
1182
|
+
const recent = logs.slice(-5).filter((l) => !l.includes("INF "));
|
|
1183
|
+
if (recent.length) state.lastEvent += ": " + recent[recent.length - 1].slice(0, 60);
|
|
1184
|
+
printStatus(state);
|
|
1185
|
+
}
|
|
1030
1186
|
});
|
|
1187
|
+
const shutdown = () => {
|
|
1188
|
+
child.kill();
|
|
1189
|
+
clearScreen();
|
|
1190
|
+
writeLine(" Runner stopped.");
|
|
1191
|
+
process.exit(0);
|
|
1192
|
+
};
|
|
1193
|
+
process.on("SIGINT", shutdown);
|
|
1194
|
+
process.on("SIGTERM", shutdown);
|
|
1195
|
+
while (true) {
|
|
1196
|
+
const key = await waitForKey(["r", "l", "q"]);
|
|
1197
|
+
if (key === "q") {
|
|
1198
|
+
shutdown();
|
|
1199
|
+
break;
|
|
1200
|
+
}
|
|
1201
|
+
if (key === "l") {
|
|
1202
|
+
clearScreen();
|
|
1203
|
+
writeLine(" Recent logs (last 30 lines):");
|
|
1204
|
+
writeLine("");
|
|
1205
|
+
for (const line of logs.slice(-30)) {
|
|
1206
|
+
writeLine(" " + line);
|
|
1207
|
+
}
|
|
1208
|
+
writeLine("");
|
|
1209
|
+
writeLine(" Press any key to go back...");
|
|
1210
|
+
await waitForKey(["r", "l", "q", " ", "\r"]);
|
|
1211
|
+
printStatus(state);
|
|
1212
|
+
}
|
|
1213
|
+
if (key === "r") {
|
|
1214
|
+
if (childDead) {
|
|
1215
|
+
writeLine(" Restarting runner...");
|
|
1216
|
+
state.runner = "starting";
|
|
1217
|
+
state.tunnel = "offline";
|
|
1218
|
+
state.tunnelUrl = "";
|
|
1219
|
+
state.registration = "pending";
|
|
1220
|
+
state.lastEvent = "Restarting...";
|
|
1221
|
+
const { execSync } = await import("child_process");
|
|
1222
|
+
try {
|
|
1223
|
+
execSync(`${process.execPath} ${process.argv[1]} up${opts.headless ? " --headless" : ""}`, {
|
|
1224
|
+
stdio: "inherit",
|
|
1225
|
+
env: process.env
|
|
1226
|
+
});
|
|
1227
|
+
} catch {
|
|
1228
|
+
}
|
|
1229
|
+
process.exit(0);
|
|
1230
|
+
}
|
|
1231
|
+
printStatus(state);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1031
1234
|
});
|
|
1032
1235
|
|
|
1033
1236
|
// src/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proagentstore/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
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"
|