@scalequality/cli 0.4.17 → 0.4.19

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "sdkVersion": "0.3.281",
3
- "sha256": "6c665b6984a46ff5938f21b154f1eb1b35168f0db486ad34ab83fe45150f59c8",
4
- "sourceCommit": "8280566269e7d1a7843ef40f5470d7be8f5325b1"
3
+ "sha256": "b2a5530d1c275c47eb296b65d8f7c42b9a7eeddd6394e62264e0aad6644b9f81",
4
+ "sourceCommit": "8c4feb2574f6847724a26ad6bc37d8d47fe59610"
5
5
  }
package/dist/connect.cjs CHANGED
@@ -2084,15 +2084,14 @@ var HttpSessionTransport = class {
2084
2084
  } catch (e) {
2085
2085
  throw new TransportError(`${method} ${routeLabel(path)} failed: ${e.name}`, null, true);
2086
2086
  }
2087
- if (this.gone.has(res.status)) {
2088
- await res.body?.cancel().catch(() => void 0);
2089
- throw new SessionGoneError(res.status);
2090
- }
2091
2087
  if (!res.ok) {
2092
- const code = await res.text().then((t) => JSON.parse(t)?.code, () => void 0).catch(() => void 0);
2093
- const retryable = res.status === 429 || res.status >= 500;
2088
+ const raw = await res.text().then((t) => JSON.parse(t)?.code, () => void 0).catch(() => void 0);
2089
+ const code = typeof raw === "string" && /^[A-Z_]{3,80}$/.test(raw) ? raw : void 0;
2090
+ const edge = (res.status === 401 || res.status === 403) && !code;
2091
+ if (this.gone.has(res.status) && !edge) throw new SessionGoneError(res.status);
2092
+ const retryable = edge || res.status === 429 || res.status >= 500;
2094
2093
  const error = new TransportError(`${method} ${routeLabel(path)} answered ${res.status}`, res.status, retryable);
2095
- if (typeof code === "string" && /^[A-Z_]{3,80}$/.test(code)) error.code = code;
2094
+ if (code) error.code = code;
2096
2095
  throw error;
2097
2096
  }
2098
2097
  if (res.status === 204) return void 0;
@@ -3411,7 +3410,8 @@ var MACHINE_USAGE = {
3411
3410
  "The background service that keeps this computer connected.",
3412
3411
  "",
3413
3412
  " install Install (or update) and start it for the connected computer.",
3414
- " start Start it again (the same as install).",
3413
+ " start Start it again (the same as install). On a computer that is not",
3414
+ " connected, it connects it first (the same as login).",
3415
3415
  ' uninstall Stop and remove it. The computer stays paired; "scalequality',
3416
3416
  ' logout" disconnects it.',
3417
3417
  " status Whether it is installed and running, and where it logs.",
@@ -4440,6 +4440,7 @@ var MachineClient = class {
4440
4440
  }
4441
4441
  if (!res.ok) {
4442
4442
  const code = typeof parsed?.code === "string" && /^[A-Z_]{3,80}$/.test(parsed.code) ? parsed.code : null;
4443
+ if ((res.status === 401 || res.status === 403) && !code) throw new MachineApiError(null, null);
4443
4444
  throw new MachineApiError(res.status, code, parsed);
4444
4445
  }
4445
4446
  return parsed;
@@ -11669,7 +11670,19 @@ ${String(item.content)}` : String(item.content);
11669
11670
  this.turnAbort?.abort();
11670
11671
  return;
11671
11672
  }
11672
- if (live.between || live.turnEnded) return;
11673
+ if (live.between || live.turnEnded) {
11674
+ if (!live.accepting) {
11675
+ this.deps.log.info("stopping background work after the turn");
11676
+ live.abort.abort();
11677
+ return;
11678
+ }
11679
+ try {
11680
+ await Promise.race([Promise.resolve(q.interrupt()), new Promise((_, reject) => setTimeout(() => reject(new Error("INTERRUPT_TIMEOUT")), INTERRUPT_TIMEOUT_MS))]);
11681
+ } catch (e) {
11682
+ this.deps.log.warn("interrupt between turns failed", { error: this.redactor.text(e.message) });
11683
+ }
11684
+ return;
11685
+ }
11673
11686
  live.interrupted = true;
11674
11687
  const ac = live.abort;
11675
11688
  if (!live.stopGuard) {
@@ -13596,6 +13609,7 @@ var REGISTRY_LATEST = "https://registry.npmjs.org/@scalequality%2fcli/latest";
13596
13609
  var UPDATE_FIRST_CHECK_MS = 2 * 6e4;
13597
13610
  var UPDATE_INTERVAL_MS = 6 * 36e5;
13598
13611
  var UPDATE_IDLE_POLL_MS = 6e4;
13612
+ var UPDATE_RETRY_MS = 15 * 6e4;
13599
13613
  var CONFIRM_AFTER_MS = 9e4;
13600
13614
  var RESTART_EXIT_CODE = 75;
13601
13615
  var MAX_START_ATTEMPTS = 3;
@@ -13739,6 +13753,11 @@ var UpdateError = class extends Error {
13739
13753
  }
13740
13754
  code;
13741
13755
  };
13756
+ function npmReason(output) {
13757
+ const lines2 = output.split("\n").map((l) => l.trim()).filter(Boolean);
13758
+ const errors = lines2.filter((l) => /^npm (error|ERR!)/.test(l) && !/complete log of this run/i.test(l));
13759
+ return (errors.length ? errors.slice(0, 2).join(" ") : lines2.slice(-1)[0] ?? "").slice(0, 240);
13760
+ }
13742
13761
  async function installVersion(o) {
13743
13762
  const npm = o.npm === void 0 ? npmCli(o.nodePath) : o.npm;
13744
13763
  if (!npm) throw new UpdateError("NPM_NOT_FOUND", `npm was not found next to ${o.nodePath}.`);
@@ -13756,10 +13775,11 @@ async function installVersion(o) {
13756
13775
  "--no-fund",
13757
13776
  "--ignore-scripts",
13758
13777
  "--omit=dev",
13778
+ "--prefer-online",
13759
13779
  "--registry=https://registry.npmjs.org/",
13760
13780
  `@scalequality/cli@${o.version}`
13761
13781
  ]);
13762
- if (r.code !== 0) throw new UpdateError("NPM_INSTALL_FAILED", `npm could not install @scalequality/cli@${o.version}: ${`${r.stderr || r.stdout}`.trim().split("\n").slice(-1)[0]?.slice(0, 200) ?? r.code}`);
13782
+ if (r.code !== 0) throw new UpdateError("NPM_INSTALL_FAILED", `npm could not install @scalequality/cli@${o.version}: ${npmReason(`${r.stderr || r.stdout}`) || r.code}`);
13763
13783
  const root = (0, import_path16.join)(staging, "node_modules", "@scalequality", "cli");
13764
13784
  const pkg = readJson2((0, import_path16.join)(root, "package.json"));
13765
13785
  if (pkg?.name !== "@scalequality/cli" || pkg?.version !== o.version) throw new UpdateError("WRONG_PACKAGE", `npm installed ${String(pkg?.name)}@${String(pkg?.version)} instead of ${o.version}.`);
@@ -14243,7 +14263,7 @@ function startSelfUpdate(api, busy, restart) {
14243
14263
  if (checking) return;
14244
14264
  checking = true;
14245
14265
  try {
14246
- await checkForUpdate({
14266
+ const result = await checkForUpdate({
14247
14267
  home: HOME,
14248
14268
  env: process.env,
14249
14269
  version: cliVersion,
@@ -14254,6 +14274,7 @@ function startSelfUpdate(api, busy, restart) {
14254
14274
  launched: () => process.env.SCALEQUALITY_LAUNCHER === "1",
14255
14275
  restart
14256
14276
  });
14277
+ if (result === "SKIPPED") setTimeout(() => void check(), UPDATE_RETRY_MS).unref();
14257
14278
  } catch (e) {
14258
14279
  say(`[warn] update check failed: ${e.message}`);
14259
14280
  } finally {
@@ -14316,6 +14337,11 @@ async function serviceMain(action, api, lines2, toggle = null) {
14316
14337
  say(toggle === "on" ? "Automatic updates are on: the service installs new versions by itself while no session runs." : "Automatic updates are off. Update by hand with: npx @scalequality/cli@latest login");
14317
14338
  return;
14318
14339
  }
14340
+ if (action === "start" && !credentials.get(api)) {
14341
+ say(`This computer is not connected to ${api}. Connecting it now.`);
14342
+ await loginMain(api, null, true, false);
14343
+ return;
14344
+ }
14319
14345
  if (action === "install" || action === "start") {
14320
14346
  if (!credentials.get(api)) {
14321
14347
  say(style.red(`This computer is not connected to ${api}. Run scalequality login${apiFlag(api)} first.`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalequality/cli",
3
- "version": "0.4.17",
3
+ "version": "0.4.19",
4
4
  "description": "ScaleQuality CLI. Connect your computer to the ScaleQuality AI Workspace (`scalequality login`), run its coding engine in any folder of your computer, and import your Claude Code and Codex conversations.",
5
5
  "type": "module",
6
6
  "bin": {