@proagentstore/cli 0.4.150 → 0.4.152

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 +163 -105
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -381,6 +381,7 @@ jobs:
381
381
  });
382
382
 
383
383
  // src/commands/login.ts
384
+ import { spawn } from "child_process";
384
385
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
385
386
  import { createServer } from "http";
386
387
  import { homedir } from "os";
@@ -414,9 +415,21 @@ function requireSession() {
414
415
  }
415
416
  return session;
416
417
  }
418
+ function browserCommand(url, platform = process.platform) {
419
+ if (platform === "win32") return { file: "rundll32", args: ["url.dll,FileProtocolHandler", url] };
420
+ return { file: platform === "darwin" ? "open" : "xdg-open", args: [url] };
421
+ }
422
+ function openBrowser(url) {
423
+ const { file, args } = browserCommand(url);
424
+ try {
425
+ const child = spawn(file, args, { stdio: "ignore", detached: true, windowsHide: true });
426
+ child.on("error", () => void 0);
427
+ child.unref();
428
+ } catch {
429
+ }
430
+ }
417
431
  var loginCommand = new Command3("login").description("Sign in with Google or GitHub (opens browser)").option("--github", "Use GitHub instead of Google").action(async (opts) => {
418
432
  const provider = opts.github ? "github" : "google";
419
- writeLine(`Opening browser for ${provider} sign-in...`);
420
433
  const port = await findFreePort();
421
434
  const callbackUrl = `http://127.0.0.1:${port}/callback`;
422
435
  const tokenPromise = new Promise((resolve5, reject) => {
@@ -469,9 +482,9 @@ var loginCommand = new Command3("login").description("Sign in with Google or Git
469
482
  });
470
483
  const oauthBase = provider === "google" ? `${API_BASE}/v1/auth/google/start` : `${API_BASE}/v1/auth/github/start`;
471
484
  const oauthUrl = `${oauthBase}?return_to=${encodeURIComponent(callbackUrl)}`;
472
- const open = (await import("child_process")).exec;
473
- const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
474
- open(`${cmd} "${oauthUrl}"`);
485
+ writeLine(`Opening your browser for ${provider} sign-in. If it does not open, paste this URL into a browser on this machine:`);
486
+ writeLine(` ${oauthUrl}`);
487
+ openBrowser(oauthUrl);
475
488
  try {
476
489
  await tokenPromise;
477
490
  const session = loadSession();
@@ -990,14 +1003,14 @@ var unclaimCommand = new Command4("unclaim").description("Remove a mistaken mach
990
1003
  var machinesCommand = new Command4("machines").description("Show and claim the machine names ProAgentStore has for this account").addCommand(listCommand, { isDefault: true }).addCommand(claimCommand).addCommand(unclaimCommand);
991
1004
 
992
1005
  // src/commands/mcp.ts
993
- import { spawn } from "child_process";
1006
+ import { spawn as spawn2 } from "child_process";
994
1007
  import { Command as Command5 } from "commander";
995
1008
  var DEFAULT_MCP_URL = "https://mcp.proagentstore.online/mcp";
996
1009
  function buildMcpRemoteArgs(opts, extraArgs = []) {
997
1010
  return ["-y", "mcp-remote", opts.url || DEFAULT_MCP_URL, ...extraArgs];
998
1011
  }
999
1012
  async function runMcpProxy(opts, extraArgs = []) {
1000
- const child = spawn("npx", buildMcpRemoteArgs(opts, extraArgs), {
1013
+ const child = spawn2("npx", buildMcpRemoteArgs(opts, extraArgs), {
1001
1014
  stdio: "inherit",
1002
1015
  env: process.env
1003
1016
  });
@@ -1180,12 +1193,12 @@ var publishCommand = new Command7("publish").description("Publish an agent to Pr
1180
1193
  });
1181
1194
 
1182
1195
  // src/commands/runner/command.ts
1183
- import { spawn as spawn4 } from "child_process";
1196
+ import { spawn as spawn5 } from "child_process";
1184
1197
  import { randomUUID as randomUUID4 } from "crypto";
1185
1198
  import { Command as Command8 } from "commander";
1186
1199
 
1187
1200
  // src/commands/runner/process.ts
1188
- import { spawn as spawn2 } from "child_process";
1201
+ import { spawn as spawn3 } from "child_process";
1189
1202
  import { existsSync as existsSync6 } from "fs";
1190
1203
  import { resolve as resolve4, win32 } from "path";
1191
1204
  import { createServer as createServer2 } from "net";
@@ -1260,7 +1273,7 @@ function runnerSpawnSpec(opts) {
1260
1273
  function startRunnerForeground(opts) {
1261
1274
  const spec = runnerSpawnSpec(opts);
1262
1275
  return new Promise((resolvePromise, reject) => {
1263
- const child = spawn2(spec.command, spec.args, {
1276
+ const child = spawn3(spec.command, spec.args, {
1264
1277
  cwd: spec.cwd,
1265
1278
  stdio: "inherit",
1266
1279
  shell: spec.shell
@@ -1336,7 +1349,7 @@ function sampleResources(read = os, now = Date.now(), extra = {}) {
1336
1349
  }
1337
1350
 
1338
1351
  // src/commands/runner/self-update.ts
1339
- import { spawn as spawn3 } from "child_process";
1352
+ import { spawn as spawn4 } from "child_process";
1340
1353
  var RUNNER_UPDATE_PATH = "/pags/runner/update";
1341
1354
  var RUNNER_RESTART_PATH = "/pags/runner/restart";
1342
1355
  var RUNNER_RESTART_EXIT_CODE = 75;
@@ -1367,7 +1380,7 @@ function deferredUpdateLease(value, now = Date.now()) {
1367
1380
  function deferredUpdateLeaseActive(lease, now = Date.now()) {
1368
1381
  return now < lease.expiresAt;
1369
1382
  }
1370
- function leaveForRestart(restarter, deps = { spawn: spawn3, exit: (code) => process.exit(code) }) {
1383
+ function leaveForRestart(restarter, deps = { spawn: spawn4, exit: (code) => process.exit(code) }) {
1371
1384
  logUpdateStep(`restart: leaving for the ${restarter} restarter (${restarter === "command" ? "restart command started, exit 0" : `exit ${RUNNER_RESTART_EXIT_CODE}`})`);
1372
1385
  if (restarter === "command") {
1373
1386
  deps.spawn(process.env[RESTART_COMMAND_ENV], { shell: true, detached: true, stdio: "ignore", env: process.env }).unref();
@@ -2395,6 +2408,101 @@ function releaseTrial(version2, cell, log, env = process.env, root = payloadRoot
2395
2408
  };
2396
2409
  }
2397
2410
 
2411
+ // src/commands/up-restart.ts
2412
+ import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
2413
+ var UP_LAUNCHER_ENV = "PAGS_UP_LAUNCHER";
2414
+ var UP_LAUNCHER_PID_ENV = "PAGS_UP_LAUNCHER_PID";
2415
+ var RUNNER_DIED_EXIT_CODE = 76;
2416
+ function upRestartMode(env, parent = { pid: process.ppid, alive: pidAlive }) {
2417
+ if (env[SERVICE_ENV] === "1") return "service";
2418
+ if (env[RESTART_COMMAND_ENV]?.trim()) return "command";
2419
+ const launcher = Number(env[UP_LAUNCHER_PID_ENV]);
2420
+ if (env[UP_LAUNCHER_ENV] === "1" && launcher === parent.pid && parent.alive(launcher)) return "launcher-child";
2421
+ return "launcher";
2422
+ }
2423
+ function runnerExitAction(code, stopping) {
2424
+ if (code === RUNNER_RESTART_EXIT_CODE) return "restart";
2425
+ if (stopping) return "ignore";
2426
+ return code === 0 ? "stop" : "died";
2427
+ }
2428
+ function restartOwner(env = process.env, alive = pidAlive) {
2429
+ if (env[SERVICE_ENV] === "1") return "service";
2430
+ return env[UP_LAUNCHER_ENV] === "1" && alive(Number(env[UP_LAUNCHER_PID_ENV])) ? "launcher" : "none";
2431
+ }
2432
+ function relaunchDelayMs(failures) {
2433
+ return Math.min(5 * 6e4, 1e4 * 2 ** Math.max(0, failures - 1));
2434
+ }
2435
+ var RAN_MS = 6e4;
2436
+ var RESET_MS = 10 * 6e4;
2437
+ function processRestartDeps() {
2438
+ return {
2439
+ env: process.env,
2440
+ execPath: process.execPath,
2441
+ execArgv: process.execArgv,
2442
+ script: process.argv[1],
2443
+ spawn: nodeSpawn,
2444
+ spawnSync: nodeSpawnSync,
2445
+ exit: (code) => process.exit(code),
2446
+ log: () => {
2447
+ },
2448
+ sleep: (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms),
2449
+ step: (line) => logUpdateStep(line),
2450
+ parent: { pid: process.ppid, alive: pidAlive },
2451
+ pid: process.pid,
2452
+ now: Date.now
2453
+ };
2454
+ }
2455
+ function restartPagsUp(args, extraEnv, deps, opts = {}) {
2456
+ const env = { ...deps.env, ...extraEnv };
2457
+ const argv = [...deps.execArgv, deps.script, ...args];
2458
+ const exitCode = opts.exitCode ?? RUNNER_RESTART_EXIT_CODE;
2459
+ const mode = upRestartMode(env, deps.parent);
2460
+ deps.step(`${opts.initial ? "start" : "restart"}: pags ${args.join(" ")} \u2014 ${opts.initial ? "as" : "leaving via"} ${mode}${exitCode === RUNNER_DIED_EXIT_CODE ? " (the runner died)" : ""}`);
2461
+ if (mode === "service") {
2462
+ deps.exit(exitCode);
2463
+ return;
2464
+ }
2465
+ if (mode === "command") {
2466
+ leaveForRestart(mode, { spawn: deps.spawn, exit: deps.exit });
2467
+ return;
2468
+ }
2469
+ if (mode === "launcher-child") {
2470
+ deps.exit(exitCode);
2471
+ return;
2472
+ }
2473
+ const childEnv = { ...env, [UP_LAUNCHER_ENV]: "1", [UP_LAUNCHER_PID_ENV]: String(deps.pid) };
2474
+ let failures = 0;
2475
+ for (let first = true; ; first = false) {
2476
+ const unattended = !first || env.PAGS_NO_PROMPT === "1";
2477
+ deps.step(`launcher: starting pags up${unattended ? " (unattended)" : ""}`);
2478
+ const startedAt = deps.now();
2479
+ const r = deps.spawnSync(deps.execPath, argv, { stdio: "inherit", env: first ? childEnv : { ...childEnv, PAGS_NO_PROMPT: "1" } });
2480
+ const ran = deps.now() - startedAt;
2481
+ const how = r.error ? `could not start (${r.error.message})` : r.signal ? `was killed by ${r.signal}` : `exited ${r.status}`;
2482
+ deps.step(`launcher: pags up ${how} after ${Math.round(ran / 1e3)}s`);
2483
+ if (ran >= RESET_MS) failures = 0;
2484
+ if (r.status === RUNNER_RESTART_EXIT_CODE) {
2485
+ failures = 0;
2486
+ continue;
2487
+ }
2488
+ if (!r.error && (r.status === 0 || r.signal === "SIGINT")) {
2489
+ deps.exit(0);
2490
+ return;
2491
+ }
2492
+ if (unattended || r.status === RUNNER_DIED_EXIT_CODE || ran >= RAN_MS) {
2493
+ failures++;
2494
+ const wait = relaunchDelayMs(failures);
2495
+ deps.log(`pags up ${how} \u2014 starting it again in ${Math.round(wait / 1e3)}s (attempt ${failures + 1}).`);
2496
+ deps.step(`launcher: retrying in ${Math.round(wait / 1e3)}s (failure ${failures})`);
2497
+ deps.sleep(wait);
2498
+ continue;
2499
+ }
2500
+ if (!opts.initial) deps.log(`Restart failed${typeof r.status === "number" ? ` (exit ${r.status})` : ""} \u2014 the runner is NOT running. Run 'pags up' again.`);
2501
+ deps.exit(typeof r.status === "number" && r.status !== 0 ? r.status : 1);
2502
+ return;
2503
+ }
2504
+ }
2505
+
2398
2506
  // src/commands/runner/relay.ts
2399
2507
  var MEMBERSHIP_SYNC_PATH = "/pags/membership/sync";
2400
2508
  var CLI_CONTROL_PATHS = /* @__PURE__ */ new Set([MEMBERSHIP_SYNC_PATH, RUNNER_UPDATE_PATH, RUNNER_RESTART_PATH]);
@@ -2690,7 +2798,9 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
2690
2798
  // #896: who is heartbeating. Set by `runner connect` from the lock it took.
2691
2799
  ...process.env.PAGS_RUNNER_RSID ? { rsid: process.env.PAGS_RUNNER_RSID } : {},
2692
2800
  pid: process.pid,
2693
- ...process.env.PAGS_RUNNER_LAUNCH ? { launch: process.env.PAGS_RUNNER_LAUNCH } : {}
2801
+ ...process.env.PAGS_RUNNER_LAUNCH ? { launch: process.env.PAGS_RUNNER_LAUNCH } : {},
2802
+ supervisor: restartOwner()
2803
+ // #1154: what starts it again if it dies
2694
2804
  },
2695
2805
  relayRttMs,
2696
2806
  sessions: sessions ?? void 0
@@ -3257,6 +3367,8 @@ function createRunnerCommand() {
3257
3367
  process.exit(1);
3258
3368
  }
3259
3369
  lockHeld = { path: taken.path, rsid: taken.lock.rsid, nonce: taken.lock.nonce, launch: taken.lock.launch };
3370
+ process.env.PAGS_RUNNER_RSID = taken.lock.rsid;
3371
+ process.env.PAGS_RUNNER_LAUNCH = taken.lock.launch;
3260
3372
  writeLine(`STATUS runner-session=${taken.lock.rsid}`);
3261
3373
  }
3262
3374
  const releaseHeldLock = () => {
@@ -3268,7 +3380,7 @@ function createRunnerCommand() {
3268
3380
  const spec = runnerSpawnSpec(runnerOpts);
3269
3381
  const crashAccount = lockAccount || loadSession()?.user.login || "";
3270
3382
  const crashes = crashAccount ? crashPaths(configDir(), crashAccount, opts.dataDir) : null;
3271
- const runner = spawn4(spec.command, spec.args, {
3383
+ const runner = spawn5(spec.command, spec.args, {
3272
3384
  cwd: spec.cwd,
3273
3385
  stdio: ["ignore", "pipe", "pipe"],
3274
3386
  shell: spec.shell,
@@ -3453,7 +3565,7 @@ import { readFileSync as readFileSync11, statSync as statSync2, watchFile } from
3453
3565
  import { Command as Command9 } from "commander";
3454
3566
 
3455
3567
  // src/background.ts
3456
- import { spawn as nodeSpawn } from "child_process";
3568
+ import { spawn as nodeSpawn2 } from "child_process";
3457
3569
  import { closeSync as closeSync3, existsSync as existsSync10, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync10, renameSync as renameSync4, statSync, writeFileSync as writeFileSync6 } from "fs";
3458
3570
  import { dirname as dirname5, join as join11 } from "path";
3459
3571
  var BACKGROUND_ENV = "PAGS_BACKGROUND";
@@ -3492,12 +3604,12 @@ function backgroundRestartCommand(execPath, script, upArgs, platform = process.p
3492
3604
  const argv = [execPath, script, ...upArgs, "--background"].map((a) => shellQuote(a, platform)).join(" ");
3493
3605
  return platform === "win32" ? `set ${BACKGROUND_RESTART_ENV}=1&& ${argv}` : `${BACKGROUND_RESTART_ENV}=1 ${argv}`;
3494
3606
  }
3495
- function spawnDetached(command, args, env, logPath, spawn5 = nodeSpawn) {
3607
+ function spawnDetached(command, args, env, logPath, spawn6 = nodeSpawn2) {
3496
3608
  mkdirSync8(dirname5(logPath), { recursive: true });
3497
3609
  rotateLog(logPath);
3498
3610
  const fd = openSync3(logPath, "a", 384);
3499
3611
  try {
3500
- const child = spawn5(command, args, { detached: true, stdio: ["ignore", fd, fd], env, windowsHide: true });
3612
+ const child = spawn6(command, args, { detached: true, stdio: ["ignore", fd, fd], env, windowsHide: true });
3501
3613
  child.unref();
3502
3614
  if (!child.pid) throw new Error("the runner process did not start");
3503
3615
  return child.pid;
@@ -3709,75 +3821,6 @@ async function waitForKey(keys, onInterrupt) {
3709
3821
  });
3710
3822
  }
3711
3823
 
3712
- // src/commands/up-restart.ts
3713
- import { spawn as nodeSpawn2, spawnSync as nodeSpawnSync } from "child_process";
3714
- var UP_LAUNCHER_ENV = "PAGS_UP_LAUNCHER";
3715
- function upRestartMode(env) {
3716
- if (env[SERVICE_ENV] === "1") return "service";
3717
- if (env[RESTART_COMMAND_ENV]?.trim()) return "command";
3718
- if (env[UP_LAUNCHER_ENV] === "1") return "launcher-child";
3719
- return "launcher";
3720
- }
3721
- function relaunchDelayMs(failures) {
3722
- return Math.min(5 * 6e4, 1e4 * 2 ** Math.max(0, failures - 1));
3723
- }
3724
- function processRestartDeps() {
3725
- return {
3726
- env: process.env,
3727
- execPath: process.execPath,
3728
- execArgv: process.execArgv,
3729
- script: process.argv[1],
3730
- spawn: nodeSpawn2,
3731
- spawnSync: nodeSpawnSync,
3732
- exit: (code) => process.exit(code),
3733
- log: () => {
3734
- },
3735
- sleep: (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms),
3736
- step: (line) => logUpdateStep(line)
3737
- };
3738
- }
3739
- function restartPagsUp(args, extraEnv, deps) {
3740
- const env = { ...deps.env, ...extraEnv };
3741
- const argv = [...deps.execArgv, deps.script, ...args];
3742
- const mode = upRestartMode(env);
3743
- deps.step(`restart: pags ${args.join(" ")} \u2014 leaving via ${mode}`);
3744
- if (mode === "service" || mode === "command") {
3745
- leaveForRestart(mode, { spawn: deps.spawn, exit: deps.exit });
3746
- return;
3747
- }
3748
- if (mode === "launcher-child") {
3749
- deps.exit(RUNNER_RESTART_EXIT_CODE);
3750
- return;
3751
- }
3752
- let failures = 0;
3753
- for (let first = true; ; first = false) {
3754
- const unattended = !first || env.PAGS_NO_PROMPT === "1";
3755
- deps.step(`launcher: starting pags up${unattended ? " (unattended)" : ""}`);
3756
- const r = deps.spawnSync(deps.execPath, argv, { stdio: "inherit", env: { ...env, [UP_LAUNCHER_ENV]: "1", ...first ? {} : { PAGS_NO_PROMPT: "1" } } });
3757
- const how = r.error ? `could not start (${r.error.message})` : r.signal ? `was killed by ${r.signal}` : `exited ${r.status}`;
3758
- deps.step(`launcher: pags up ${how}`);
3759
- if (r.status === RUNNER_RESTART_EXIT_CODE) {
3760
- failures = 0;
3761
- continue;
3762
- }
3763
- if (!r.error && r.status === 0) {
3764
- deps.exit(0);
3765
- return;
3766
- }
3767
- if (unattended) {
3768
- failures++;
3769
- const wait = relaunchDelayMs(failures);
3770
- deps.log(`pags up ${how} \u2014 starting it again in ${Math.round(wait / 1e3)}s (attempt ${failures + 1}).`);
3771
- deps.step(`launcher: retrying in ${Math.round(wait / 1e3)}s (failure ${failures})`);
3772
- deps.sleep(wait);
3773
- continue;
3774
- }
3775
- deps.log(`Restart failed${typeof r.status === "number" ? ` (exit ${r.status})` : ""} \u2014 the runner is NOT running. Run 'pags up' again.`);
3776
- deps.exit(typeof r.status === "number" && r.status !== 0 ? r.status : 1);
3777
- return;
3778
- }
3779
- }
3780
-
3781
3824
  // src/runner-replace.ts
3782
3825
  var REPLACE_EXIT_TIMEOUT_MS = 3e4;
3783
3826
  function describeWork(work) {
@@ -3987,6 +4030,15 @@ start();
3987
4030
  var xml = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3988
4031
  var unitWord = (s) => `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
3989
4032
  var ps = (s) => `'${s.replace(/'/g, "''")}'`;
4033
+ function versionManagedNode(nodePath) {
4034
+ if (/[\\/]n[\\/]versions[\\/]/.test(nodePath)) return "n";
4035
+ const m = /[\\/]\.?(nvm|fnm|volta|asdf|nodenv)[\\/]/i.exec(nodePath);
4036
+ return m ? m[1].toLowerCase() : null;
4037
+ }
4038
+ var pinnedNodeNote = (ctx) => {
4039
+ const manager = versionManagedNode(ctx.nodePath);
4040
+ return manager ? [`It runs Node ${ctx.nodePath}, installed by ${manager}. Removing or switching away from that Node version stops the service; after changing Node, run \`pags up --install-service\` again.`] : [];
4041
+ };
3990
4042
  function servicePlan(ctx) {
3991
4043
  const supervisor = supervisorPath(ctx);
3992
4044
  const log = serviceLogPath(ctx);
@@ -4010,6 +4062,7 @@ function servicePlan(ctx) {
4010
4062
  <key>KeepAlive</key><true/>
4011
4063
  <key>ThrottleInterval</key><integer>30</integer>
4012
4064
  <key>ProcessType</key><string>Background</string>
4065
+ <key>WorkingDirectory</key><string>${xml(ctx.home)}</string>
4013
4066
  <key>StandardOutPath</key><string>${xml(log)}</string>
4014
4067
  <key>StandardErrorPath</key><string>${xml(log)}</string>
4015
4068
  </dict>
@@ -4025,6 +4078,7 @@ function servicePlan(ctx) {
4025
4078
  { file: "launchctl", args: ["kickstart", "-k", `${domain}/${SERVICE_LABEL}`], why: "start it now" }
4026
4079
  ],
4027
4080
  notes: [
4081
+ ...pinnedNodeNote(ctx),
4028
4082
  `LaunchAgent ${plist} \u2014 runs while this user is logged in. On a machine that must survive a reboot unattended, turn on automatic login for this user.`,
4029
4083
  `Remove it with: pags up --uninstall-service`
4030
4084
  ]
@@ -4039,8 +4093,11 @@ function servicePlan(ctx) {
4039
4093
  $ErrorActionPreference = 'Stop'
4040
4094
  $action = New-ScheduledTaskAction -Execute ${ps(ctx.nodePath)} -Argument ${ps(`"${supervisor}"`)}
4041
4095
  $trigger = New-ScheduledTaskTrigger -AtStartup
4096
+ # Task Scheduler restarts a task that failed to START; a supervisor killed later just ends. Re-trigger it every five
4097
+ # minutes, forever \u2014 MultipleInstances IgnoreNew makes a trigger that finds it running do nothing (#1154).
4098
+ $trigger.Repetition = (New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5)).Repetition
4042
4099
  $principal = New-ScheduledTaskPrincipal -UserId ${ps(principal)} -LogonType S4U -RunLevel Limited
4043
- $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) -RestartCount 999 -RestartInterval (New-TimeSpan -Minutes 1) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
4100
+ $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) -RestartCount 999 -RestartInterval (New-TimeSpan -Minutes 1) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew
4044
4101
  Unregister-ScheduledTask -TaskName ${ps(WINDOWS_TASK)} -Confirm:$false -ErrorAction SilentlyContinue
4045
4102
  Register-ScheduledTask -TaskName ${ps(WINDOWS_TASK)} -Action $action -Trigger $trigger -Principal $principal -Settings $settings | Out-Null
4046
4103
  Start-ScheduledTask -TaskName ${ps(WINDOWS_TASK)}
@@ -4051,6 +4108,7 @@ Start-ScheduledTask -TaskName ${ps(WINDOWS_TASK)}
4051
4108
  files,
4052
4109
  commands: [{ file: "powershell.exe", args: ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", task], why: "register and start the Scheduled Task" }],
4053
4110
  notes: [
4111
+ ...pinnedNodeNote(ctx),
4054
4112
  `Scheduled Task "${WINDOWS_TASK}" \u2014 starts at boot as ${principal || "this user"}, with nobody logged in. Registering it needs an elevated PowerShell: if it was refused, run ${task} from one.`,
4055
4113
  `Remove it with: pags up --uninstall-service`
4056
4114
  ]
@@ -4085,7 +4143,7 @@ WantedBy=default.target
4085
4143
  { file: "systemctl", args: ["--user", "enable", "--now", SYSTEMD_UNIT], why: "enable and start it" },
4086
4144
  { file: "loginctl", args: ["enable-linger", ...ctx.user ? [ctx.user] : []], optional: true, why: "keep it running with nobody logged in" }
4087
4145
  ],
4088
- notes: [`systemd user unit ${unit}. Logs: ${log} (and journalctl --user -u ${SYSTEMD_UNIT}).`, `Remove it with: pags up --uninstall-service`]
4146
+ notes: [...pinnedNodeNote(ctx), `systemd user unit ${unit}. Logs: ${log} (and journalctl --user -u ${SYSTEMD_UNIT}).`, `Remove it with: pags up --uninstall-service`]
4089
4147
  };
4090
4148
  }
4091
4149
  function serviceRemovalPlan(ctx) {
@@ -4149,6 +4207,10 @@ var upCommand = new Command10("up").description("Start the browser runner for al
4149
4207
  for (const line of uninstallService(serviceContext()).lines) writeLine(line);
4150
4208
  return;
4151
4209
  }
4210
+ if (!opts.background && !opts.installService && upRestartMode(process.env) === "launcher") {
4211
+ restartPagsUp(process.argv.slice(2), {}, { ...processRestartDeps(), log: (line) => writeLine(` ${line}`) }, { initial: true });
4212
+ return;
4213
+ }
4152
4214
  const session = requireSession();
4153
4215
  if (opts.installService) {
4154
4216
  const result = installService(serviceContext());
@@ -4269,7 +4331,7 @@ var upCommand = new Command10("up").description("Start the browser runner for al
4269
4331
  }
4270
4332
  for (const line of replaced.lines) printStep(line, "ok");
4271
4333
  }
4272
- const { spawn: spawn5 } = await import("child_process");
4334
+ const { spawn: spawn6 } = await import("child_process");
4273
4335
  const cliPath = process.argv[1];
4274
4336
  const args = [cliPath, "runner", "connect", ...instances.map((i) => i.id)];
4275
4337
  if (opts.headless) args.push("--headless");
@@ -4279,7 +4341,7 @@ var upCommand = new Command10("up").description("Start the browser runner for al
4279
4341
  const code = await startInBackground({ session, opts, runnerArgs: args, instances: state.instances, lockFile, watching: !opts.instance });
4280
4342
  process.exit(code);
4281
4343
  }
4282
- const child = spawn5(process.execPath, args, {
4344
+ const child = spawn6(process.execPath, args, {
4283
4345
  stdio: ["ignore", "pipe", "pipe"],
4284
4346
  // The child is the lock HOLDER (#896): it owns the relay sockets, so it is what a
4285
4347
  // contender must find and what `--replace` must be able to stop.
@@ -4355,33 +4417,29 @@ var upCommand = new Command10("up").description("Start the browser runner for al
4355
4417
  void deliverCrashReports({ apiBase: API_BASE3, token: session.token, account: session.user.login, paths: crashes }).catch(() => void 0);
4356
4418
  };
4357
4419
  child.on("exit", (code, signal) => {
4358
- if (code === RUNNER_RESTART_EXIT_CODE) {
4420
+ const action = runnerExitAction(code, stopping);
4421
+ if (action === "restart") {
4359
4422
  logUpdateStep("restart: runner connect asked for a restart (exit 75)");
4360
4423
  restartUp("Runner updated remotely \u2014 restarting pags up on the new version\u2026", { PAGS_NO_PROMPT: "1" });
4361
4424
  return;
4362
4425
  }
4363
4426
  childDead = true;
4364
4427
  logUpdateStep(`runner connect ${signal ? `was killed by ${signal}` : `exited ${code}`}${stopping ? " (stopping)" : ""}`);
4365
- if (code !== 0 && !stopping) recordConnectExit(code, signal ?? null, logs.slice(-20));
4366
- if (code === null) {
4367
- state.runner = "error";
4368
- state.lastEvent = "Runner stopped by another process (signal) \u2014 it is not connected any more";
4369
- printStatus(state);
4370
- return;
4371
- }
4372
- if (code !== 0) {
4373
- state.runner = "error";
4374
- state.lastEvent = `Runner exited (code ${code})`;
4375
- const recent = logs.slice(-5);
4376
- if (recent.length) state.lastEvent += ": " + recent[recent.length - 1].slice(0, 60);
4377
- printStatus(state);
4428
+ if (action === "ignore") return;
4429
+ if (action === "stop") {
4430
+ clearScreen();
4431
+ writeLine(" Runner stopped (pags down, or replaced by another pags up).");
4432
+ process.exit(0);
4378
4433
  }
4434
+ recordConnectExit(code, signal ?? null, logs.slice(-20));
4435
+ const recent = logs.slice(-5).at(-1);
4436
+ restartUp(`Runner ${signal ? `was killed by ${signal}` : `exited (code ${code})`}${recent ? `: ${recent.slice(0, 60)}` : ""} \u2014 starting it again\u2026`, { PAGS_NO_PROMPT: "1" }, RUNNER_DIED_EXIT_CODE);
4379
4437
  });
4380
- function restartUp(why, env = {}) {
4438
+ function restartUp(why, env = {}, exitCode) {
4381
4439
  writeLine(` ${why}`);
4382
4440
  if (process.stdin.isTTY) process.stdin.setRawMode(false);
4383
4441
  process.stdin.pause();
4384
- restartPagsUp(restartUpArgs(opts), env, { ...processRestartDeps(), log: (line) => writeLine(` ${line}`) });
4442
+ restartPagsUp(restartUpArgs(opts), env, { ...processRestartDeps(), log: (line) => writeLine(` ${line}`) }, { exitCode });
4385
4443
  process.exit(1);
4386
4444
  }
4387
4445
  const shutdown = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.4.150",
3
+ "version": "0.4.152",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",