switchroom 0.15.34 → 0.15.35

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.
@@ -50574,8 +50574,8 @@ var {
50574
50574
  } = import__.default;
50575
50575
 
50576
50576
  // src/build-info.ts
50577
- var VERSION = "0.15.34";
50578
- var COMMIT_SHA = "508eb512";
50577
+ var VERSION = "0.15.35";
50578
+ var COMMIT_SHA = "beafcff6";
50579
50579
 
50580
50580
  // src/cli/agent.ts
50581
50581
  init_source();
@@ -54544,6 +54544,23 @@ function resolveRelease(opts) {
54544
54544
  return opts.root;
54545
54545
  return;
54546
54546
  }
54547
+ function parseSemverTag(tag) {
54548
+ if (!tag)
54549
+ return null;
54550
+ const m = /^v(\d+)\.(\d+)\.(\d+)$/.exec(tag.trim());
54551
+ return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
54552
+ }
54553
+ function compareReleaseTags(a, b) {
54554
+ const pa = parseSemverTag(a);
54555
+ const pb = parseSemverTag(b);
54556
+ if (!pa || !pb)
54557
+ return null;
54558
+ for (let i = 0;i < 3; i++) {
54559
+ if (pa[i] !== pb[i])
54560
+ return pa[i] < pb[i] ? -1 : 1;
54561
+ }
54562
+ return 0;
54563
+ }
54547
54564
  // src/cli/operator-uid.ts
54548
54565
  import {
54549
54566
  chownSync,
@@ -86916,7 +86933,46 @@ init_helpers();
86916
86933
  import { existsSync as existsSync84, mkdirSync as mkdirSync47, readdirSync as readdirSync33, readFileSync as readFileSync72, writeFileSync as writeFileSync41, statSync as statSync35, copyFileSync as copyFileSync12 } from "node:fs";
86917
86934
  import { homedir as homedir49 } from "node:os";
86918
86935
  import { join as join83 } from "node:path";
86936
+ import { spawnSync as spawnSync16 } from "node:child_process";
86937
+
86938
+ // src/cli/deploy-version-guard.ts
86919
86939
  import { spawnSync as spawnSync15 } from "node:child_process";
86940
+ var defaultRunner2 = (args) => {
86941
+ const r = spawnSync15("docker", args, { encoding: "utf8" });
86942
+ return { ok: r.status === 0, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
86943
+ };
86944
+ function deployedImageTag(container, run = defaultRunner2) {
86945
+ const r = run(["inspect", "-f", "{{.Config.Image}}", container]);
86946
+ if (!r.ok)
86947
+ return null;
86948
+ const ref = r.stdout.trim();
86949
+ if (!ref)
86950
+ return null;
86951
+ const noDigest = ref.split("@")[0];
86952
+ const colon = noDigest.lastIndexOf(":");
86953
+ if (colon < 0)
86954
+ return null;
86955
+ const tag = noDigest.slice(colon + 1);
86956
+ return tag && !tag.includes("/") ? tag : null;
86957
+ }
86958
+ function checkDowngrade(opts) {
86959
+ const running = deployedImageTag(opts.container, opts.run);
86960
+ if (opts.allowDowngrade)
86961
+ return { skip: false, running };
86962
+ const cmp = compareReleaseTags(opts.targetTag, running);
86963
+ if (cmp !== null && cmp < 0) {
86964
+ return {
86965
+ skip: true,
86966
+ running,
86967
+ message: `Skipping ${opts.container} deploy \u2014 it is already on ${running}, newer than the ` + `requested ${opts.targetTag}.
86968
+ ` + ` Refusing to downgrade: this guards against a concurrent rollout/update ` + `reverting a newer build.
86969
+ ` + ` To force the downgrade, re-run with --allow-downgrade.`
86970
+ };
86971
+ }
86972
+ return { skip: false, running };
86973
+ }
86974
+
86975
+ // src/cli/hostd.ts
86920
86976
  init_audit_reader();
86921
86977
  function resolveHostdImageTag(explicitTag, release) {
86922
86978
  if (explicitTag)
@@ -87054,7 +87110,7 @@ function backupExistingCompose() {
87054
87110
  return bak;
87055
87111
  }
87056
87112
  function runDocker(args) {
87057
- const r = spawnSync15("docker", args, { encoding: "utf8" });
87113
+ const r = spawnSync16("docker", args, { encoding: "utf8" });
87058
87114
  return {
87059
87115
  ok: r.status === 0,
87060
87116
  stdout: r.stdout ?? "",
@@ -87081,6 +87137,15 @@ async function doInstall(opts, program3) {
87081
87137
  const composePath = hostdComposePath();
87082
87138
  mkdirSync47(dir, { recursive: true });
87083
87139
  const imageTag = resolveHostdImageTag(opts.tag, cfg.release);
87140
+ const guard = checkDowngrade({
87141
+ container: "switchroom-hostd",
87142
+ targetTag: imageTag,
87143
+ allowDowngrade: opts.allowDowngrade
87144
+ });
87145
+ if (guard.skip) {
87146
+ console.log(source_default.yellow(` \u23ed ${opts.dryRun ? "[dry-run] " : ""}${guard.message}`));
87147
+ return;
87148
+ }
87084
87149
  const yaml = renderHostdComposeFile({
87085
87150
  hostHome: resolveHostdHostHome(),
87086
87151
  imageTag,
@@ -87190,7 +87255,7 @@ ${down.stderr}`));
87190
87255
  }
87191
87256
  function registerHostdCommand(program3) {
87192
87257
  const hostd = program3.command("hostd").description("Manage switchroom-hostd, the host-control daemon for admin agents (RFC C)");
87193
- hostd.command("install").description("Install or refresh the hostd container (writes ~/.switchroom/hostd/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").action(withConfigError(async (opts) => {
87258
+ hostd.command("install").description("Install or refresh the hostd container (writes ~/.switchroom/hostd/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").option("--allow-downgrade", "Deploy even if the running container is on a newer version (overrides the anti-revert guard)").action(withConfigError(async (opts) => {
87194
87259
  await doInstall(opts, program3);
87195
87260
  }));
87196
87261
  hostd.command("status").description("Show daemon state and bound sockets").action(() => doStatus());
@@ -87247,7 +87312,7 @@ init_helpers();
87247
87312
  import { existsSync as existsSync85, mkdirSync as mkdirSync48, writeFileSync as writeFileSync42, copyFileSync as copyFileSync13 } from "node:fs";
87248
87313
  import { homedir as homedir50 } from "node:os";
87249
87314
  import { join as join84 } from "node:path";
87250
- import { spawnSync as spawnSync16 } from "node:child_process";
87315
+ import { spawnSync as spawnSync17 } from "node:child_process";
87251
87316
  function resolveWebImageTag(explicitTag, release) {
87252
87317
  if (explicitTag)
87253
87318
  return explicitTag;
@@ -87346,7 +87411,7 @@ function backupExistingCompose2() {
87346
87411
  return bak;
87347
87412
  }
87348
87413
  function runDocker2(args) {
87349
- const r = spawnSync16("docker", args, { encoding: "utf8" });
87414
+ const r = spawnSync17("docker", args, { encoding: "utf8" });
87350
87415
  return {
87351
87416
  ok: r.status === 0,
87352
87417
  stdout: r.stdout ?? "",
@@ -87366,6 +87431,15 @@ async function doInstall2(opts, program3) {
87366
87431
  mkdirSync48(dir, { recursive: true });
87367
87432
  const cfg = getConfig(program3);
87368
87433
  const imageTag = resolveWebImageTag(opts.tag, cfg.release);
87434
+ const guard = checkDowngrade({
87435
+ container: "switchroom-web",
87436
+ targetTag: imageTag,
87437
+ allowDowngrade: opts.allowDowngrade
87438
+ });
87439
+ if (guard.skip) {
87440
+ console.log(source_default.yellow(` \u23ed ${opts.dryRun ? "[dry-run] " : ""}${guard.message}`));
87441
+ return;
87442
+ }
87369
87443
  const yaml = renderWebComposeFile({
87370
87444
  hostHome: homedir50(),
87371
87445
  imageTag,
@@ -87456,7 +87530,7 @@ ${down.stderr}`));
87456
87530
  }
87457
87531
  function registerWebdCommand(program3) {
87458
87532
  const webd = program3.command("webd").description("Manage switchroom-web, the dashboard + GitHub-webhook receiver container");
87459
- webd.command("install").description("Install or refresh the web container (writes ~/.switchroom/web/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").action(withConfigError(async (opts) => {
87533
+ webd.command("install").description("Install or refresh the web container (writes ~/.switchroom/web/docker-compose.yml + docker compose up -d)").option("--tag <tag>", "Image tag override (default: resolved from release.pin in switchroom.yaml, else latest)").option("--dry-run", "Print the compose file and the docker commands without writing or running anything").option("--allow-downgrade", "Deploy even if the running container is on a newer version (overrides the anti-revert guard)").action(withConfigError(async (opts) => {
87460
87534
  await doInstall2(opts, program3);
87461
87535
  }));
87462
87536
  webd.command("status").description("Show web-service container state").action(() => doStatus2());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switchroom",
3
- "version": "0.15.34",
3
+ "version": "0.15.35",
4
4
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -54460,10 +54460,10 @@ function readTurnActiveMarkerAgeMs(stateDir, now) {
54460
54460
  }
54461
54461
 
54462
54462
  // ../src/build-info.ts
54463
- var VERSION = "0.15.34";
54464
- var COMMIT_SHA = "508eb512";
54465
- var COMMIT_DATE = "2026-06-16T02:47:01Z";
54466
- var LATEST_PR = 2389;
54463
+ var VERSION = "0.15.35";
54464
+ var COMMIT_SHA = "beafcff6";
54465
+ var COMMIT_DATE = "2026-06-16T07:06:45Z";
54466
+ var LATEST_PR = 2391;
54467
54467
  var COMMITS_AHEAD_OF_TAG = 0;
54468
54468
 
54469
54469
  // gateway/boot-version.ts