@proagentstore/cli 0.1.19 → 0.1.21
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/browser-runner/index.js +9 -0
- package/dist/index.js +104 -33
- package/package.json +1 -1
|
@@ -57,3 +57,12 @@ const shutdown = async () => {
|
|
|
57
57
|
};
|
|
58
58
|
process.on("SIGINT", () => void shutdown());
|
|
59
59
|
process.on("SIGTERM", () => void shutdown());
|
|
60
|
+
// Self-exit if our parent (the `runner connect` CLI) dies — otherwise we'd orphan
|
|
61
|
+
// and keep holding the port, making the NEXT `pags up` fail with EADDRINUSE / a 401
|
|
62
|
+
// against our stale token. When the parent dies we're reparented (ppid changes to
|
|
63
|
+
// launchd/init), so a changed ppid means it's gone.
|
|
64
|
+
const parentPid = process.ppid;
|
|
65
|
+
setInterval(() => {
|
|
66
|
+
if (process.ppid !== parentPid)
|
|
67
|
+
void shutdown();
|
|
68
|
+
}, 3000).unref();
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/index.ts
|
|
10
|
-
import { createRequire } from "module";
|
|
10
|
+
import { createRequire as createRequire2 } from "module";
|
|
11
11
|
import { Command as Command8 } from "commander";
|
|
12
12
|
|
|
13
13
|
// src/commands/check.ts
|
|
@@ -618,8 +618,21 @@ import { chmod, mkdir, writeFile } from "fs/promises";
|
|
|
618
618
|
import { gunzipSync } from "zlib";
|
|
619
619
|
import { arch, homedir as homedir2, platform } from "os";
|
|
620
620
|
import { resolve as resolve4 } from "path";
|
|
621
|
+
import { createServer as createServer2 } from "net";
|
|
621
622
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
622
623
|
import { Command as Command6 } from "commander";
|
|
624
|
+
async function findFreePort2(start) {
|
|
625
|
+
for (let p = start; p < start + 25; p++) {
|
|
626
|
+
const free = await new Promise((res) => {
|
|
627
|
+
const s = createServer2();
|
|
628
|
+
s.once("error", () => res(false));
|
|
629
|
+
s.once("listening", () => s.close(() => res(true)));
|
|
630
|
+
s.listen(p, "127.0.0.1");
|
|
631
|
+
});
|
|
632
|
+
if (free) return p;
|
|
633
|
+
}
|
|
634
|
+
return start;
|
|
635
|
+
}
|
|
623
636
|
var runnerCommand = createRunnerCommand();
|
|
624
637
|
function runnerBaseUrl(url) {
|
|
625
638
|
return (clean(url) || clean(process.env.PAGS_RUNNER_URL) || "http://127.0.0.1:49171").replace(/\/$/, "");
|
|
@@ -761,7 +774,11 @@ async function resolveCloudflaredCommand(requested) {
|
|
|
761
774
|
return downloadCloudflared(cloudflaredAssetForPlatform());
|
|
762
775
|
}
|
|
763
776
|
function parseCloudflaredTunnelUrl(text) {
|
|
764
|
-
|
|
777
|
+
const matches = text.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/gi) || [];
|
|
778
|
+
for (const m of matches) {
|
|
779
|
+
if (!/^https:\/\/api\.trycloudflare\.com/i.test(m)) return m;
|
|
780
|
+
}
|
|
781
|
+
return null;
|
|
765
782
|
}
|
|
766
783
|
function buildRuntimeRegistrationBody(opts, capabilities = []) {
|
|
767
784
|
return {
|
|
@@ -898,7 +915,7 @@ function createRunnerCommand() {
|
|
|
898
915
|
command.command("connect <instanceId>").description("Start the local FAGS runtime, open a Cloudflare quick tunnel, and register it with PAGS").option("--host <host>", "Host to bind", "127.0.0.1").option("--port <port>", "Port to bind", "49171").option("--data-dir <path>", "Runner data directory").option("--token <token>", "Runner bearer token. Defaults to PAGS_RUNNER_TOKEN or a generated token").option("--headless", "Run Playwright headless").option("--api-base <url>", "PAGS API base URL").option("--pags-token <token>", "PAGS session token. Defaults to PAGS_TOKEN").option("--cloudflared <path>", "cloudflared executable").option("--runner-version <version>", "Runner version").option("--skip-probe", "Skip PAGS FAGS-runtime probe after registration").action(async (instanceId, opts) => {
|
|
899
916
|
const runnerToken = clean(opts.token) || clean(process.env.PAGS_RUNNER_TOKEN) || `pags_runner_${randomUUID()}`;
|
|
900
917
|
const host = clean(opts.host) || "127.0.0.1";
|
|
901
|
-
const port = clean(opts.port) ||
|
|
918
|
+
const port = clean(opts.port) || String(await findFreePort2(49171));
|
|
902
919
|
const localUrl = `http://${host}:${port}`;
|
|
903
920
|
const runnerOpts = {
|
|
904
921
|
...opts,
|
|
@@ -964,7 +981,9 @@ function createRunnerCommand() {
|
|
|
964
981
|
const first = await openTunnel();
|
|
965
982
|
tunnel = first.proc;
|
|
966
983
|
let tunnelUrl = first.url;
|
|
967
|
-
await registerRuntime(tunnelUrl)
|
|
984
|
+
await registerRuntime(tunnelUrl).catch((error) => {
|
|
985
|
+
writeError(`registration will retry (${error instanceof Error ? error.message : String(error)})`);
|
|
986
|
+
});
|
|
968
987
|
writeLine("Runtime registered with PAGS \u2713");
|
|
969
988
|
writeLine("");
|
|
970
989
|
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");
|
|
@@ -991,7 +1010,10 @@ function createRunnerCommand() {
|
|
|
991
1010
|
await new Promise((r) => setTimeout(r, 3e4));
|
|
992
1011
|
if (stopped) break;
|
|
993
1012
|
if (await probeTunnel(tunnelUrl)) {
|
|
994
|
-
await requestPags("POST", heartbeatPath, opts, {}).catch(() =>
|
|
1013
|
+
const beat = await requestPags("POST", heartbeatPath, opts, {}).then(() => true).catch(() => false);
|
|
1014
|
+
if (!beat) {
|
|
1015
|
+
await registerRuntime(tunnelUrl).then(() => writeLine("\u2705 Re-registered with PAGS")).catch(() => void 0);
|
|
1016
|
+
}
|
|
995
1017
|
continue;
|
|
996
1018
|
}
|
|
997
1019
|
writeLine("\u26A0 Tunnel unreachable \u2014 reconnecting\u2026");
|
|
@@ -1129,6 +1151,7 @@ function createRunnerCommand() {
|
|
|
1129
1151
|
}
|
|
1130
1152
|
|
|
1131
1153
|
// src/commands/up.ts
|
|
1154
|
+
import { createRequire } from "module";
|
|
1132
1155
|
import { Command as Command7 } from "commander";
|
|
1133
1156
|
|
|
1134
1157
|
// src/tui.ts
|
|
@@ -1150,43 +1173,56 @@ var LOGO = [
|
|
|
1150
1173
|
function clearScreen() {
|
|
1151
1174
|
console.clear();
|
|
1152
1175
|
}
|
|
1153
|
-
function printLogo() {
|
|
1176
|
+
function printLogo(version2) {
|
|
1154
1177
|
console.log("");
|
|
1155
1178
|
for (const line of LOGO) {
|
|
1156
1179
|
console.log(pad + c(line));
|
|
1157
1180
|
}
|
|
1181
|
+
console.log(pad + d(" Browser runner") + (version2 ? d(` \xB7 v${version2}`) : ""));
|
|
1158
1182
|
console.log("");
|
|
1159
1183
|
}
|
|
1184
|
+
function describe(kind, s) {
|
|
1185
|
+
const ok = s === "online" || s === "registered";
|
|
1186
|
+
const busy = s === "starting" || s === "pending";
|
|
1187
|
+
const icon = ok ? chalk.green("\u2713") : busy ? chalk.yellow("\u2026") : chalk.red("\u2717");
|
|
1188
|
+
const map = {
|
|
1189
|
+
runner: { label: "Browser", ok: "running on your computer", busy: "starting up\u2026", bad: "stopped \u2014 press r to retry" },
|
|
1190
|
+
tunnel: { label: "Secure link", ok: "connected to ProAgentStore", busy: "opening\u2026", bad: "offline" },
|
|
1191
|
+
pags: { label: "ProAgentStore", ok: "connected \u2014 ready for jobs", busy: "registering\u2026", bad: "not registered (retries automatically)" }
|
|
1192
|
+
};
|
|
1193
|
+
const m = map[kind];
|
|
1194
|
+
return { icon, label: m.label, note: ok ? m.ok : busy ? m.busy : m.bad };
|
|
1195
|
+
}
|
|
1160
1196
|
function printStatus(state) {
|
|
1161
1197
|
clearScreen();
|
|
1162
|
-
printLogo();
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
const statusText = (s) => {
|
|
1170
|
-
if (s === "online" || s === "registered") return chalk.green(s);
|
|
1171
|
-
if (s === "starting" || s === "pending") return chalk.yellow(s);
|
|
1172
|
-
if (s === "error" || s === "failed") return chalk.red(s);
|
|
1173
|
-
return d(s);
|
|
1198
|
+
printLogo(state.version);
|
|
1199
|
+
const connected = state.runner === "online" && state.tunnel === "online" && state.registration === "registered";
|
|
1200
|
+
console.log(pad + d("Signed in as ") + w(state.user) + d(" \xB7 agent: ") + w(state.activeInstance));
|
|
1201
|
+
console.log("");
|
|
1202
|
+
const row = (kind, s) => {
|
|
1203
|
+
const { icon, label, note } = describe(kind, s);
|
|
1204
|
+
console.log(pad + icon + " " + w(label.padEnd(13)) + d(note));
|
|
1174
1205
|
};
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
console.log(pad + d("Tunnel ") + statusIcon(state.tunnel) + " " + statusText(state.tunnel));
|
|
1179
|
-
console.log(pad + d("PAGS ") + statusIcon(state.registration) + " " + statusText(state.registration));
|
|
1180
|
-
if (state.tunnelUrl) {
|
|
1181
|
-
console.log(pad + d("URL ") + c(state.tunnelUrl));
|
|
1182
|
-
}
|
|
1206
|
+
row("runner", state.runner);
|
|
1207
|
+
row("tunnel", state.tunnel);
|
|
1208
|
+
row("pags", state.registration);
|
|
1183
1209
|
console.log("");
|
|
1184
|
-
if (
|
|
1185
|
-
console.log(pad +
|
|
1210
|
+
if (connected) {
|
|
1211
|
+
console.log(pad + chalk.green("\u2713 You're all set!") + d(" Your agent can now act on the web."));
|
|
1212
|
+
console.log("");
|
|
1213
|
+
console.log(pad + w("What to do next:"));
|
|
1214
|
+
console.log(pad + d(" 1. Open ") + c("https://proagentstore.online/console"));
|
|
1215
|
+
console.log(pad + d(" 2. Pick your agent and paste a job link to apply"));
|
|
1216
|
+
console.log(pad + d(" 3. Keep ") + w("this window open") + d(" while your agent works"));
|
|
1217
|
+
console.log("");
|
|
1218
|
+
console.log(pad + d("The website can take a few seconds to show \u201Conline\u201D \u2014 that's normal."));
|
|
1219
|
+
} else {
|
|
1220
|
+
console.log(pad + d("Setting things up\u2026 this takes a few seconds. Keep this window open."));
|
|
1221
|
+
if (state.lastEvent) console.log(pad + d("Status: ") + d(state.lastEvent));
|
|
1186
1222
|
}
|
|
1187
1223
|
console.log("");
|
|
1188
1224
|
console.log(
|
|
1189
|
-
pad + c("r") + d("
|
|
1225
|
+
pad + c("r") + d(" Reconnect ") + c("l") + d(" View logs ") + c("q") + d(" Quit (disconnect)")
|
|
1190
1226
|
);
|
|
1191
1227
|
console.log("");
|
|
1192
1228
|
}
|
|
@@ -1221,6 +1257,7 @@ async function waitForKey(keys) {
|
|
|
1221
1257
|
|
|
1222
1258
|
// src/commands/up.ts
|
|
1223
1259
|
var API_BASE2 = "https://api.proagentstore.online";
|
|
1260
|
+
var CLI_VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
1224
1261
|
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) => {
|
|
1225
1262
|
const session = requireSession();
|
|
1226
1263
|
const state = {
|
|
@@ -1232,10 +1269,11 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1232
1269
|
tunnelUrl: "",
|
|
1233
1270
|
registration: "pending",
|
|
1234
1271
|
lastEvent: "Fetching instances...",
|
|
1235
|
-
taskCount: 0
|
|
1272
|
+
taskCount: 0,
|
|
1273
|
+
version: CLI_VERSION
|
|
1236
1274
|
};
|
|
1237
1275
|
clearScreen();
|
|
1238
|
-
printLogo();
|
|
1276
|
+
printLogo(CLI_VERSION);
|
|
1239
1277
|
printStep("Signed in as " + session.user.login, "ok");
|
|
1240
1278
|
printStep("Fetching instances...", "wait");
|
|
1241
1279
|
const res = await fetch(`${API_BASE2}/v1/instances/my/instances`, {
|
|
@@ -1280,7 +1318,7 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1280
1318
|
logs.push(trimmed);
|
|
1281
1319
|
if (logs.length > 200) logs.shift();
|
|
1282
1320
|
const tunnelMatch = trimmed.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/i);
|
|
1283
|
-
if (tunnelMatch) {
|
|
1321
|
+
if (tunnelMatch && !/^https:\/\/api\.trycloudflare\.com/i.test(tunnelMatch[0])) {
|
|
1284
1322
|
state.tunnel = "online";
|
|
1285
1323
|
state.tunnelUrl = tunnelMatch[0];
|
|
1286
1324
|
state.lastEvent = "Tunnel created";
|
|
@@ -1373,9 +1411,41 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1373
1411
|
}
|
|
1374
1412
|
}
|
|
1375
1413
|
});
|
|
1414
|
+
var downCommand = new Command7("down").description("Stop the browser runner and disconnect (cleans up any stuck processes)").action(async () => {
|
|
1415
|
+
clearScreen();
|
|
1416
|
+
printLogo(CLI_VERSION);
|
|
1417
|
+
if (process.platform === "win32") {
|
|
1418
|
+
writeLine(" On Windows: switch to the 'pags up' window and press Ctrl+C to disconnect.");
|
|
1419
|
+
writeLine("");
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
const { execSync } = await import("child_process");
|
|
1423
|
+
const patterns = [
|
|
1424
|
+
"dist/browser-runner/index.js",
|
|
1425
|
+
"browser-runner/src/index",
|
|
1426
|
+
"runner connect",
|
|
1427
|
+
"tunnel --url http://127.0.0.1"
|
|
1428
|
+
];
|
|
1429
|
+
let stopped = false;
|
|
1430
|
+
for (const p of patterns) {
|
|
1431
|
+
try {
|
|
1432
|
+
execSync(`pkill -f ${JSON.stringify(p)}`, { stdio: "ignore" });
|
|
1433
|
+
stopped = true;
|
|
1434
|
+
} catch {
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
if (stopped) {
|
|
1438
|
+
writeLine(" \u2713 Runner stopped \u2014 you're disconnected.");
|
|
1439
|
+
writeLine("");
|
|
1440
|
+
writeLine(" Your agent won't act on the web until you run 'pags up' again.");
|
|
1441
|
+
} else {
|
|
1442
|
+
writeLine(" No runner was running \u2014 nothing to stop.");
|
|
1443
|
+
}
|
|
1444
|
+
writeLine("");
|
|
1445
|
+
});
|
|
1376
1446
|
|
|
1377
1447
|
// src/index.ts
|
|
1378
|
-
var require2 =
|
|
1448
|
+
var require2 = createRequire2(import.meta.url);
|
|
1379
1449
|
var { version } = require2("../package.json");
|
|
1380
1450
|
var program = new Command8();
|
|
1381
1451
|
program.name("pags").description(
|
|
@@ -1385,6 +1455,7 @@ program.addCommand(loginCommand);
|
|
|
1385
1455
|
program.addCommand(logoutCommand);
|
|
1386
1456
|
program.addCommand(whoamiCommand);
|
|
1387
1457
|
program.addCommand(upCommand);
|
|
1458
|
+
program.addCommand(downCommand);
|
|
1388
1459
|
program.addCommand(initCommand);
|
|
1389
1460
|
program.addCommand(checkCommand);
|
|
1390
1461
|
program.addCommand(publishCommand);
|