@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.
Files changed (2) hide show
  1. package/dist/index.js +45 -23
  2. 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 createRequire2 } from "module";
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
- await requestPags("POST", `/v1/instances/${apiPathSegment(id)}/runtime`, opts, {
917
- endpointUrl: localUrl,
918
- token: runnerToken,
919
- placement: "local",
920
- capabilities: caps,
921
- runnerVersion: "",
922
- runnerNode: hostname()
923
- }).catch((e) => writeError(`register ${id.slice(0, 8)}\u2026 failed: ${e instanceof Error ? e.message : String(e)}`));
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(" \u2705 CONNECTED \u2014 WebSocket relay (no tunnel)");
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' (production), or 'quick' (default)", "quick").action(async (instanceIds, opts) => {
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 CLI_VERSION = createRequire(import.meta.url)("../package.json").version;
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, recommended), 'named' (production, stable), or 'quick' (default, trycloudflare.com)", "quick").action(async (opts) => {
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: CLI_VERSION
1526
+ version: CLI_VERSION2
1506
1527
  };
1507
1528
  clearScreen();
1508
- printLogo(CLI_VERSION);
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(CLI_VERSION);
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 = createRequire2(import.meta.url);
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(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",