@proagentstore/cli 0.3.1 → 0.3.3

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.
@@ -55,6 +55,17 @@ Endpoints:
55
55
  process.exit(0);
56
56
  }
57
57
  const config = configFromArgs();
58
+ // SECURITY: the runner's endpoints spawn CLIs and drive a browser as the user.
59
+ // Without a token, `authorize()` allows every request, so a tokenless runner must
60
+ // never be reachable off the local machine. Refuse to start if bound to a
61
+ // non-loopback address without a token. (`pags up` always generates one; this
62
+ // only guards the low-level binary run manually with --host 0.0.0.0 and no token.)
63
+ const LOOPBACK = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
64
+ if (!config.token && !LOOPBACK.has(config.host)) {
65
+ process.stderr.write(`Refusing to start: --host ${config.host} exposes the runner off-machine with no --token. ` +
66
+ `Set --token (or PAGS_RUNNER_TOKEN), or bind to 127.0.0.1.\n`);
67
+ process.exit(1);
68
+ }
58
69
  const started = await startRunnerServer(config);
59
70
  process.stdout.write(`FAGS browser runtime listening at ${started.url}\n`);
60
71
  process.stdout.write(`Data dir: ${config.dataDir}\n`);
package/dist/index.js CHANGED
@@ -379,7 +379,6 @@ import { Command as Command3 } from "commander";
379
379
  var CONFIG_DIR = join3(homedir(), ".config", "proagentstore");
380
380
  var TOKEN_FILE = join3(CONFIG_DIR, "session.json");
381
381
  var API_BASE = "https://api.proagentstore.online";
382
- var FAS_API = "https://api.freeappstore.online";
383
382
  function loadSession() {
384
383
  try {
385
384
  if (!existsSync3(TOKEN_FILE)) return null;
@@ -422,34 +421,32 @@ var loginCommand = new Command3("login").description("Sign in with Google or Git
422
421
  res.end();
423
422
  return;
424
423
  }
425
- const fasSession = url.searchParams.get("fas_session");
426
- if (!fasSession) {
424
+ const session = url.searchParams.get("session");
425
+ if (!session) {
427
426
  res.writeHead(400, { "Content-Type": "text/html" });
428
427
  res.end("<h1>Sign-in failed</h1><p>No session received.</p>");
429
428
  clearTimeout(timeout);
430
429
  server.close();
431
- reject(new Error("No fas_session in callback"));
430
+ reject(new Error("No session in callback"));
432
431
  return;
433
432
  }
434
433
  try {
435
- const exchangeRes = await fetch(`${API_BASE}/v1/auth/exchange`, {
436
- method: "POST",
437
- headers: { "Content-Type": "application/json" },
438
- body: JSON.stringify({ fas_session: fasSession })
434
+ const meRes = await fetch(`${API_BASE}/v1/auth/me`, {
435
+ headers: { Authorization: `Bearer ${session}` }
439
436
  });
440
- const data = await exchangeRes.json();
441
- if (!data.token) throw new Error(data.error || "Exchange failed");
437
+ if (!meRes.ok) throw new Error("Session validation failed");
438
+ const me = await meRes.json();
442
439
  saveSession({
443
- token: data.token,
444
- user: data.user,
440
+ token: session,
441
+ user: { id: me.id, login: me.login, avatar: me.avatar },
445
442
  expiresAt: Date.now() + 29 * 24 * 60 * 60 * 1e3
446
443
  // ~29 days
447
444
  });
448
445
  res.writeHead(200, { "Content-Type": "text/html" });
449
- res.end(`<h1>Signed in as ${data.user?.login}</h1><p>You can close this tab and return to the terminal.</p><script>window.close()</script>`);
446
+ res.end(`<h1>Signed in as ${me.login}</h1><p>You can close this tab and return to the terminal.</p><script>window.close()</script>`);
450
447
  clearTimeout(timeout);
451
448
  server.close();
452
- resolve5(data.token);
449
+ resolve5(session);
453
450
  } catch (err) {
454
451
  res.writeHead(500, { "Content-Type": "text/html" });
455
452
  res.end(`<h1>Sign-in failed</h1><p>${err instanceof Error ? err.message : String(err)}</p>`);
@@ -460,8 +457,8 @@ var loginCommand = new Command3("login").description("Sign in with Google or Git
460
457
  });
461
458
  server.listen(port, "127.0.0.1");
462
459
  });
463
- const oauthBase = provider === "google" ? `${FAS_API}/v1/auth/google/start` : `${FAS_API}/v1/auth/github/start`;
464
- const oauthUrl = `${oauthBase}?app_id=pags-cli&response_mode=query&return_to=${encodeURIComponent(callbackUrl)}`;
460
+ const oauthBase = provider === "google" ? `${API_BASE}/v1/auth/google/start` : `${API_BASE}/v1/auth/github/start`;
461
+ const oauthUrl = `${oauthBase}?return_to=${encodeURIComponent(callbackUrl)}`;
465
462
  const open = (await import("child_process")).exec;
466
463
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
467
464
  open(`${cmd} "${oauthUrl}"`);
@@ -827,7 +824,8 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
827
824
  }
828
825
  }
829
826
  for (const id of instanceIds) {
830
- openRelaySocket(id, apiBase, pagsToken, localUrl, runnerToken, force);
827
+ const mintToken = () => requestPags("POST", `/v1/relay/${apiPathSegment(id)}/token`, { ...opts, pagsToken }, {}).then((r) => r.token);
828
+ openRelaySocket(id, apiBase, mintToken, localUrl, runnerToken, force);
831
829
  }
832
830
  writeLine("Runtime registered with PAGS \u2713");
833
831
  writeLine("");
@@ -847,11 +845,24 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
847
845
  };
848
846
  heartbeat();
849
847
  }
850
- function openRelaySocket(instanceId, wsBase, pagsToken, localUrl, runnerToken, force = false) {
848
+ function openRelaySocket(instanceId, wsBase, mintToken, localUrl, runnerToken, force = false) {
851
849
  let backoffMs = 1e3;
852
850
  let reconnecting = false;
853
- const connect = () => {
854
- const url = `${wsBase}/v1/relay/${encodeURIComponent(instanceId)}/connect?token=${encodeURIComponent(pagsToken)}${force ? "&force=1" : ""}`;
851
+ const connect = async () => {
852
+ let relayToken;
853
+ try {
854
+ relayToken = await mintToken();
855
+ } catch (e) {
856
+ const msg = e instanceof Error ? e.message : String(e);
857
+ const hint = /401|token|sign/i.test(msg) ? " (run `pags login`)" : "";
858
+ writeLine(`Relay token mint failed: ${instanceId.slice(0, 8)}\u2026${hint} \u2014 retrying in ${Math.round(backoffMs / 1e3)}s`);
859
+ setTimeout(() => {
860
+ connect();
861
+ }, backoffMs);
862
+ backoffMs = Math.min(backoffMs * 2, 3e4);
863
+ return;
864
+ }
865
+ const url = `${wsBase}/v1/relay/${encodeURIComponent(instanceId)}/connect?token=${encodeURIComponent(relayToken)}${force ? "&force=1" : ""}`;
855
866
  const ws = new WebSocket(url);
856
867
  ws.onopen = () => {
857
868
  backoffMs = 1e3;
package/package.json CHANGED
@@ -1,46 +1,46 @@
1
1
  {
2
- "name": "@proagentstore/cli",
3
- "version": "0.3.1",
4
- "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "pags": "dist/index.js"
9
- },
10
- "homepage": "https://github.com/ProAgentStore/platform#readme",
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/ProAgentStore/platform.git",
14
- "directory": "packages/cli"
15
- },
16
- "keywords": [
17
- "proagentstore",
18
- "pags",
19
- "cli",
20
- "agents",
21
- "mcp",
22
- "browser-runner"
23
- ],
24
- "publishConfig": {
25
- "access": "public"
26
- },
27
- "scripts": {
28
- "build": "pnpm --filter @proagentstore/browser-runner build && tsup src/index.ts --format esm --dts && node scripts/copy-browser-runner.mjs",
29
- "dev": "tsx src/index.ts",
30
- "typecheck": "tsc --noEmit"
31
- },
32
- "dependencies": {
33
- "chalk": "^5.6.2",
34
- "commander": "^13.0.0",
35
- "playwright": "^1.60.0"
36
- },
37
- "devDependencies": {
38
- "@types/node": "^22.0.0",
39
- "tsup": "^8.4.0",
40
- "tsx": "^4.21.0",
41
- "typescript": "^5.7.0"
42
- },
43
- "files": [
44
- "dist"
45
- ]
2
+ "name": "@proagentstore/cli",
3
+ "version": "0.3.3",
4
+ "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "pags": "dist/index.js"
9
+ },
10
+ "homepage": "https://github.com/ProAgentStore/platform#readme",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/ProAgentStore/platform.git",
14
+ "directory": "packages/cli"
15
+ },
16
+ "keywords": [
17
+ "proagentstore",
18
+ "pags",
19
+ "cli",
20
+ "agents",
21
+ "mcp",
22
+ "browser-runner"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "scripts": {
28
+ "build": "pnpm --filter @proagentstore/browser-runner build && tsup src/index.ts --format esm --dts && node scripts/copy-browser-runner.mjs",
29
+ "dev": "tsx src/index.ts",
30
+ "typecheck": "tsc --noEmit"
31
+ },
32
+ "dependencies": {
33
+ "chalk": "^5.6.2",
34
+ "commander": "^13.0.0",
35
+ "playwright": "^1.60.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^22.0.0",
39
+ "tsup": "^8.4.0",
40
+ "tsx": "^4.21.0",
41
+ "typescript": "^5.7.0"
42
+ },
43
+ "files": [
44
+ "dist"
45
+ ]
46
46
  }