@proagentstore/cli 0.2.10 → 0.2.11
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 +45 -23
- package/package.json +1 -1
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 as
|
|
10
|
+
import { createRequire as createRequire3 } from "module";
|
|
11
11
|
import { Command as Command8 } from "commander";
|
|
12
12
|
|
|
13
13
|
// src/commands/check.ts
|
|
@@ -620,7 +620,15 @@ import { arch, homedir as homedir2, hostname, platform } from "os";
|
|
|
620
620
|
import { resolve as resolve4 } from "path";
|
|
621
621
|
import { createServer as createServer2 } from "net";
|
|
622
622
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
623
|
+
import { createRequire } from "module";
|
|
623
624
|
import { Command as Command6 } from "commander";
|
|
625
|
+
var CLI_VERSION = (() => {
|
|
626
|
+
try {
|
|
627
|
+
return createRequire(import.meta.url)("../package.json").version;
|
|
628
|
+
} catch {
|
|
629
|
+
return "";
|
|
630
|
+
}
|
|
631
|
+
})();
|
|
624
632
|
async function findFreePort2(start) {
|
|
625
633
|
for (let p = start; p < start + 25; p++) {
|
|
626
634
|
const free = await new Promise((res) => {
|
|
@@ -906,29 +914,42 @@ function responseErrorMessage(data, text, statusText) {
|
|
|
906
914
|
function collectCapability(value, previous = []) {
|
|
907
915
|
return [...previous, value];
|
|
908
916
|
}
|
|
909
|
-
async function connectViaRelay(instanceIds, localUrl, runnerToken, opts) {
|
|
917
|
+
async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force = false) {
|
|
910
918
|
const apiBase = pagsApiBase(opts.apiBase).replace(/^http/, "ws");
|
|
911
919
|
const pagsToken = clean(opts.pagsToken) || clean(process.env.PAGS_TOKEN) || clean(loadSession()?.token);
|
|
912
920
|
if (!pagsToken) throw new Error("PAGS token required for WebSocket relay");
|
|
913
921
|
const capabilities = await requestRunner("GET", "/capabilities", { url: localUrl, token: runnerToken, instanceId: instanceIds[0] });
|
|
914
922
|
const caps = Array.isArray(capabilities.capabilities) ? capabilities.capabilities.filter((item) => typeof item === "string") : [];
|
|
915
923
|
for (const id of instanceIds) {
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
+
try {
|
|
925
|
+
await requestPags("POST", `/v1/instances/${apiPathSegment(id)}/runtime`, opts, {
|
|
926
|
+
endpointUrl: localUrl,
|
|
927
|
+
token: runnerToken,
|
|
928
|
+
placement: "local",
|
|
929
|
+
capabilities: caps,
|
|
930
|
+
runnerVersion: CLI_VERSION,
|
|
931
|
+
runnerNode: hostname(),
|
|
932
|
+
force
|
|
933
|
+
});
|
|
934
|
+
} catch (e) {
|
|
935
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
936
|
+
if (msg.includes("409") && msg.includes("Another machine")) {
|
|
937
|
+
writeError(msg);
|
|
938
|
+
writeLine("");
|
|
939
|
+
writeLine(" To take over, run: pags up --tunnel ws --force");
|
|
940
|
+
writeLine("");
|
|
941
|
+
throw new Error("Another machine is already connected");
|
|
942
|
+
}
|
|
943
|
+
writeError(`register ${id.slice(0, 8)}\u2026 failed: ${msg}`);
|
|
944
|
+
}
|
|
924
945
|
}
|
|
925
946
|
for (const id of instanceIds) {
|
|
926
|
-
openRelaySocket(id, apiBase, pagsToken, localUrl, runnerToken);
|
|
947
|
+
openRelaySocket(id, apiBase, pagsToken, localUrl, runnerToken, force);
|
|
927
948
|
}
|
|
928
949
|
writeLine("Runtime registered with PAGS \u2713");
|
|
929
950
|
writeLine("");
|
|
930
951
|
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");
|
|
931
|
-
writeLine(
|
|
952
|
+
writeLine(` \u2705 CONNECTED \u2014 WebSocket relay \xB7 ${hostname()}`);
|
|
932
953
|
writeLine(` Agents: ${instanceIds.length} instance${instanceIds.length === 1 ? "" : "s"}`);
|
|
933
954
|
writeLine(" No cloudflared needed. Ctrl+C to disconnect.");
|
|
934
955
|
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");
|
|
@@ -943,11 +964,11 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts) {
|
|
|
943
964
|
};
|
|
944
965
|
heartbeat();
|
|
945
966
|
}
|
|
946
|
-
function openRelaySocket(instanceId, wsBase, pagsToken, localUrl, runnerToken) {
|
|
967
|
+
function openRelaySocket(instanceId, wsBase, pagsToken, localUrl, runnerToken, force = false) {
|
|
947
968
|
let backoffMs = 1e3;
|
|
948
969
|
let reconnecting = false;
|
|
949
970
|
const connect = () => {
|
|
950
|
-
const url = `${wsBase}/v1/relay/${encodeURIComponent(instanceId)}/connect?token=${encodeURIComponent(pagsToken)}`;
|
|
971
|
+
const url = `${wsBase}/v1/relay/${encodeURIComponent(instanceId)}/connect?token=${encodeURIComponent(pagsToken)}${force ? "&force=1" : ""}`;
|
|
951
972
|
const ws = new WebSocket(url);
|
|
952
973
|
ws.onopen = () => {
|
|
953
974
|
backoffMs = 1e3;
|
|
@@ -1022,7 +1043,7 @@ function createRunnerCommand() {
|
|
|
1022
1043
|
command.command("start").description("Start the local FAGS browser runtime in the foreground").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>", "Require this bearer token").option("--instance-id <id>", "Bind runner requests to a PAGS instance id").option("--headless", "Run Playwright headless").action(async (opts) => {
|
|
1023
1044
|
await startRunnerForeground(opts);
|
|
1024
1045
|
});
|
|
1025
|
-
command.command("connect <instanceIds...>").description("Start ONE local runtime, open a Cloudflare quick tunnel, and register it for every given PAGS instance").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").option("--tunnel <mode>", "Tunnel mode: 'ws' (WebSocket relay), 'named' (
|
|
1046
|
+
command.command("connect <instanceIds...>").description("Start ONE local runtime, open a Cloudflare quick tunnel, and register it for every given PAGS instance").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").option("--tunnel <mode>", "Tunnel mode: 'ws' (WebSocket relay, default), 'named' (stable hostname), or 'quick' (cloudflared)", "ws").option("--force", "Take over from another connected machine").action(async (instanceIds, opts) => {
|
|
1026
1047
|
const runnerToken = clean(opts.token) || clean(process.env.PAGS_RUNNER_TOKEN) || `pags_runner_${randomUUID()}`;
|
|
1027
1048
|
const host = clean(opts.host) || "127.0.0.1";
|
|
1028
1049
|
const port = clean(opts.port) || String(await findFreePort2(49171));
|
|
@@ -1062,7 +1083,7 @@ function createRunnerCommand() {
|
|
|
1062
1083
|
await waitForLocalRunner({ url: localUrl, token: runnerToken, instanceId: primary });
|
|
1063
1084
|
writeLine(`Local FAGS runtime healthy at ${localUrl}`);
|
|
1064
1085
|
if (opts.tunnel === "ws") {
|
|
1065
|
-
await connectViaRelay(instanceIds, localUrl, runnerToken, opts);
|
|
1086
|
+
await connectViaRelay(instanceIds, localUrl, runnerToken, opts, Boolean(opts.force));
|
|
1066
1087
|
await new Promise((resolvePromise) => {
|
|
1067
1088
|
runner.on("exit", () => resolvePromise());
|
|
1068
1089
|
});
|
|
@@ -1363,7 +1384,7 @@ function createRunnerCommand() {
|
|
|
1363
1384
|
}
|
|
1364
1385
|
|
|
1365
1386
|
// src/commands/up.ts
|
|
1366
|
-
import { createRequire } from "module";
|
|
1387
|
+
import { createRequire as createRequire2 } from "module";
|
|
1367
1388
|
import { Command as Command7 } from "commander";
|
|
1368
1389
|
|
|
1369
1390
|
// src/tui.ts
|
|
@@ -1470,7 +1491,7 @@ async function waitForKey(keys) {
|
|
|
1470
1491
|
|
|
1471
1492
|
// src/commands/up.ts
|
|
1472
1493
|
var API_BASE2 = "https://api.proagentstore.online";
|
|
1473
|
-
var
|
|
1494
|
+
var CLI_VERSION2 = createRequire2(import.meta.url)("../package.json").version;
|
|
1474
1495
|
async function stopRunnerProcesses() {
|
|
1475
1496
|
if (process.platform === "win32") return false;
|
|
1476
1497
|
const { execSync } = await import("child_process");
|
|
@@ -1490,7 +1511,7 @@ async function stopRunnerProcesses() {
|
|
|
1490
1511
|
}
|
|
1491
1512
|
return stopped;
|
|
1492
1513
|
}
|
|
1493
|
-
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").option("--tunnel <mode>", "Tunnel mode: 'ws' (WebSocket relay,
|
|
1514
|
+
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").option("--tunnel <mode>", "Tunnel mode: 'ws' (WebSocket relay, default), 'named' (stable hostname), or 'quick' (cloudflared)", "ws").option("--force", "Take over from another connected machine").action(async (opts) => {
|
|
1494
1515
|
const session = requireSession();
|
|
1495
1516
|
const state = {
|
|
1496
1517
|
user: session.user.login,
|
|
@@ -1502,10 +1523,10 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1502
1523
|
registration: "pending",
|
|
1503
1524
|
lastEvent: "Fetching instances...",
|
|
1504
1525
|
taskCount: 0,
|
|
1505
|
-
version:
|
|
1526
|
+
version: CLI_VERSION2
|
|
1506
1527
|
};
|
|
1507
1528
|
clearScreen();
|
|
1508
|
-
printLogo(
|
|
1529
|
+
printLogo(CLI_VERSION2);
|
|
1509
1530
|
printStep("Signed in as " + session.user.login, "ok");
|
|
1510
1531
|
printStep("Fetching instances...", "wait");
|
|
1511
1532
|
const res = await fetch(`${API_BASE2}/v1/instances/my/instances`, {
|
|
@@ -1539,6 +1560,7 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1539
1560
|
if (opts.headless) args.push("--headless");
|
|
1540
1561
|
if (opts.tunnel === "named") args.push("--tunnel", "named");
|
|
1541
1562
|
if (opts.tunnel === "ws") args.push("--tunnel", "ws");
|
|
1563
|
+
if (opts.force) args.push("--force");
|
|
1542
1564
|
const child = spawn3(process.execPath, args, {
|
|
1543
1565
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1544
1566
|
env: { ...process.env, PAGS_TOKEN: session.token }
|
|
@@ -1662,7 +1684,7 @@ var upCommand = new Command7("up").description("Start the browser runner for all
|
|
|
1662
1684
|
});
|
|
1663
1685
|
var downCommand = new Command7("down").description("Stop the browser runner and disconnect (cleans up any stuck processes)").action(async () => {
|
|
1664
1686
|
clearScreen();
|
|
1665
|
-
printLogo(
|
|
1687
|
+
printLogo(CLI_VERSION2);
|
|
1666
1688
|
if (process.platform === "win32") {
|
|
1667
1689
|
writeLine(" On Windows: switch to the 'pags up' window and press Ctrl+C to disconnect.");
|
|
1668
1690
|
writeLine("");
|
|
@@ -1680,7 +1702,7 @@ var downCommand = new Command7("down").description("Stop the browser runner and
|
|
|
1680
1702
|
});
|
|
1681
1703
|
|
|
1682
1704
|
// src/index.ts
|
|
1683
|
-
var require2 =
|
|
1705
|
+
var require2 = createRequire3(import.meta.url);
|
|
1684
1706
|
var { version } = require2("../package.json");
|
|
1685
1707
|
var program = new Command8();
|
|
1686
1708
|
program.name("pags").description(
|