@proagentstore/cli 0.4.112 → 0.4.114

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 +105 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1260,6 +1260,7 @@ import { execFile, spawn as spawn3 } from "child_process";
1260
1260
  import { promisify } from "util";
1261
1261
  var run = promisify(execFile);
1262
1262
  var RUNNER_UPDATE_PATH = "/pags/runner/update";
1263
+ var RUNNER_RESTART_PATH = "/pags/runner/restart";
1263
1264
  var RUNNER_RESTART_EXIT_CODE = 75;
1264
1265
  var SUPERVISED_ENV = "PAGS_UP_SUPERVISED";
1265
1266
  var SUPERVISOR_RESTARTS = "2";
@@ -1317,6 +1318,28 @@ function planRunnerUpdate(f) {
1317
1318
  if (f.busy.length > 0) return { action: "wait", current: f.current, latest: f.latest, waitingFor: f.busy };
1318
1319
  return { action: "update", current: f.current, latest: f.latest, restarter: f.restarter };
1319
1320
  }
1321
+ function planRunnerRestart(f) {
1322
+ if (!f.restarter) {
1323
+ return {
1324
+ action: "refused",
1325
+ current: f.current,
1326
+ reason: `Nothing would start this runner again after a restart: it was not started by \`pags up\`, and neither ${SERVICE_ENV}=1 nor ${RESTART_COMMAND_ENV} is set. Restart it at the machine.`
1327
+ };
1328
+ }
1329
+ if (!f.force) {
1330
+ if (f.busy === null || f.busy.includes("runner-work-observation-unavailable")) {
1331
+ return {
1332
+ action: "refused",
1333
+ current: f.current,
1334
+ reason: "The local runtime did not answer the work check, so this machine cannot be shown idle \u2014 it may be the part that is wedged. Restart with force to restart anyway; any run in progress on this machine is lost."
1335
+ };
1336
+ }
1337
+ if (f.busy.length > 0) {
1338
+ return { action: "refused", current: f.current, waitingFor: f.busy, reason: `${f.busy.length} piece(s) of work are running here. Restart when they finish, or with force (that work is lost).` };
1339
+ }
1340
+ }
1341
+ return { action: "restart", current: f.current, restarter: f.restarter };
1342
+ }
1320
1343
  async function installVersion(version2) {
1321
1344
  if (process.env[BOOTSTRAP_ENV]) {
1322
1345
  await installPayload(version2);
@@ -2222,7 +2245,7 @@ function createInstallBridge(deps) {
2222
2245
 
2223
2246
  // src/commands/runner/relay.ts
2224
2247
  var MEMBERSHIP_SYNC_PATH = "/pags/membership/sync";
2225
- var CLI_CONTROL_PATHS = /* @__PURE__ */ new Set([MEMBERSHIP_SYNC_PATH, RUNNER_UPDATE_PATH]);
2248
+ var CLI_CONTROL_PATHS = /* @__PURE__ */ new Set([MEMBERSHIP_SYNC_PATH, RUNNER_UPDATE_PATH, RUNNER_RESTART_PATH]);
2226
2249
  async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force = false, watchInstances = false) {
2227
2250
  const apiBase = pagsApiBase(opts.apiBase).replace(/^http/, "ws");
2228
2251
  const pagsToken = clean(opts.pagsToken) || clean(process.env.PAGS_TOKEN) || clean(loadSession()?.token);
@@ -2279,7 +2302,7 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
2279
2302
  writeLine(formatStatusLine({ registration: state, agents, reason: state === "ok" ? void 0 : lastRegisterError }));
2280
2303
  };
2281
2304
  for (const id of instanceIds) await registerRuntime(id);
2282
- const updateFacts = async (signal) => {
2305
+ const workLook = async (signal) => {
2283
2306
  const [sessionsResult, healthResult] = await Promise.allSettled([
2284
2307
  requestRunner("GET", "/coding/sessions", {
2285
2308
  url: localUrl,
@@ -2288,7 +2311,10 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
2288
2311
  }, void 0, signal),
2289
2312
  requestRunner("GET", "/health", { url: localUrl, token: runnerToken, instanceId: instanceIds[0] }, void 0, signal)
2290
2313
  ]);
2291
- const { busy, observations } = readWorkLook(sessionsResult, healthResult, Date.now());
2314
+ return readWorkLook(sessionsResult, healthResult, Date.now());
2315
+ };
2316
+ const updateFacts = async (signal) => {
2317
+ const { busy, observations } = await workLook(signal);
2292
2318
  return {
2293
2319
  observations,
2294
2320
  current: CLI_VERSION,
@@ -2389,8 +2415,21 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
2389
2415
  setTimeout(() => leaveForRestart(plan.restarter), 25).unref();
2390
2416
  return { status: 200, result: { action: "restarting", current: plan.current, latest: plan.latest, restartedBy: plan.restarter, ...supervisor ? { supervisor } : {} } };
2391
2417
  };
2418
+ const answerRestart = async (body) => {
2419
+ const request = body;
2420
+ const dryRun = request?.dryRun === true;
2421
+ const force2 = request?.force === true;
2422
+ if (bridge.inFlight()) return { status: 409, result: { error: "A runner update is installing or restarting; nothing else restarted." } };
2423
+ const look = force2 ? null : await boundedWork((signal) => workLook(signal));
2424
+ const plan = planRunnerRestart({ current: CLI_VERSION, restarter: restarterFrom(process.env), busy: force2 ? [] : look?.busy ?? null, force: force2 });
2425
+ if (dryRun || plan.action === "refused") return { status: 200, result: { ...plan, dryRun } };
2426
+ setTimeout(() => leaveForRestart(plan.restarter), 25).unref();
2427
+ const supervisor = supervisorNote(plan.restarter);
2428
+ return { status: 200, result: { action: "restarting", current: plan.current, latest: plan.current, restartedBy: plan.restarter, forced: force2, ...supervisor ? { supervisor } : {} } };
2429
+ };
2392
2430
  const answerControl = async (path, body) => {
2393
2431
  if (path === RUNNER_UPDATE_PATH) return answerUpdate(body);
2432
+ if (path === RUNNER_RESTART_PATH) return answerRestart(body);
2394
2433
  if (path !== MEMBERSHIP_SYNC_PATH) return { status: 404, result: { error: `Unknown runner control ${path}` } };
2395
2434
  const request = body;
2396
2435
  const named = typeof request?.attach === "string" ? request.attach : "";
@@ -2956,7 +2995,6 @@ function createRunnerCommand() {
2956
2995
  var runnerCommand = createRunnerCommand();
2957
2996
 
2958
2997
  // src/commands/up.ts
2959
- import { execFileSync as execFileSync3 } from "child_process";
2960
2998
  import { createRequire as createRequire2 } from "module";
2961
2999
  import { Command as Command8 } from "commander";
2962
3000
  import { hostname as hostname6 } from "os";
@@ -3078,6 +3116,65 @@ async function waitForKey(keys, onInterrupt) {
3078
3116
  });
3079
3117
  }
3080
3118
 
3119
+ // src/commands/up-restart.ts
3120
+ import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
3121
+ var UP_LAUNCHER_ENV = "PAGS_UP_LAUNCHER";
3122
+ function upRestartMode(env, platform, canExecve) {
3123
+ if (env[SERVICE_ENV] === "1") return "service";
3124
+ if (env[RESTART_COMMAND_ENV]?.trim()) return "command";
3125
+ if (env[UP_LAUNCHER_ENV] === "1") return "launcher-child";
3126
+ return platform !== "win32" && canExecve ? "exec" : "launcher";
3127
+ }
3128
+ function processRestartDeps() {
3129
+ const execve = process.execve;
3130
+ return {
3131
+ env: process.env,
3132
+ platform: process.platform,
3133
+ execPath: process.execPath,
3134
+ execArgv: process.execArgv,
3135
+ script: process.argv[1],
3136
+ execve: typeof execve === "function" ? execve.bind(process) : void 0,
3137
+ spawn: nodeSpawn,
3138
+ spawnSync: nodeSpawnSync,
3139
+ exit: (code) => process.exit(code),
3140
+ log: () => {
3141
+ }
3142
+ };
3143
+ }
3144
+ function restartPagsUp(args, extraEnv, deps) {
3145
+ const env = { ...deps.env, ...extraEnv };
3146
+ const argv = [...deps.execArgv, deps.script, ...args];
3147
+ const mode = upRestartMode(env, deps.platform, !!deps.execve);
3148
+ if (mode === "service" || mode === "command") {
3149
+ leaveForRestart(mode, { spawn: deps.spawn, exit: deps.exit });
3150
+ return;
3151
+ }
3152
+ if (mode === "launcher-child") {
3153
+ deps.exit(RUNNER_RESTART_EXIT_CODE);
3154
+ return;
3155
+ }
3156
+ if (mode === "exec") {
3157
+ try {
3158
+ deps.execve(deps.execPath, [deps.execPath, ...argv], env);
3159
+ } catch (e) {
3160
+ deps.log(`Restart failed (${e instanceof Error ? e.message : String(e)}) \u2014 the runner is NOT running. Run 'pags up' again.`);
3161
+ deps.exit(1);
3162
+ }
3163
+ return;
3164
+ }
3165
+ for (let first = true; ; first = false) {
3166
+ const r = deps.spawnSync(deps.execPath, argv, { stdio: "inherit", env: { ...env, [UP_LAUNCHER_ENV]: "1", ...first ? {} : { PAGS_NO_PROMPT: "1" } } });
3167
+ if (r.status === RUNNER_RESTART_EXIT_CODE) continue;
3168
+ if (r.error || r.status !== 0) {
3169
+ deps.log(`Restart failed${typeof r.status === "number" ? ` (exit ${r.status})` : ""} \u2014 the runner is NOT running. Run 'pags up' again.`);
3170
+ deps.exit(typeof r.status === "number" && r.status !== 0 ? r.status : 1);
3171
+ return;
3172
+ }
3173
+ deps.exit(0);
3174
+ return;
3175
+ }
3176
+ }
3177
+
3081
3178
  // src/runner-replace.ts
3082
3179
  var REPLACE_EXIT_TIMEOUT_MS = 3e4;
3083
3180
  function describeWork(work) {
@@ -3358,16 +3455,10 @@ var upCommand = new Command8("up").description("Start the browser runner for all
3358
3455
  });
3359
3456
  function restartUp(why, env = {}) {
3360
3457
  writeLine(` ${why}`);
3361
- try {
3362
- if (process.stdin.isTTY) process.stdin.setRawMode(false);
3363
- process.stdin.pause();
3364
- execFileSync3(process.execPath, [process.argv[1], ...restartUpArgs(opts)], { stdio: "inherit", env: { ...process.env, ...env } });
3365
- } catch (e) {
3366
- const status = e.status;
3367
- writeLine(` Restart failed${typeof status === "number" ? ` (exit ${status})` : ""} \u2014 the runner is NOT running. Run 'pags up' again.`);
3368
- process.exit(typeof status === "number" && status !== 0 ? status : 1);
3369
- }
3370
- process.exit(0);
3458
+ if (process.stdin.isTTY) process.stdin.setRawMode(false);
3459
+ process.stdin.pause();
3460
+ restartPagsUp(restartUpArgs(opts), env, { ...processRestartDeps(), log: (line) => writeLine(` ${line}`) });
3461
+ process.exit(1);
3371
3462
  }
3372
3463
  const shutdown = () => {
3373
3464
  child.kill();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.4.112",
3
+ "version": "0.4.114",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",