@dinglebear/labby 2.6.2 → 2.7.0-dev.5

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.
package/lib/platform.js CHANGED
@@ -38,7 +38,16 @@ function targetFor(platform = process.platform, arch = process.arch) {
38
38
 
39
39
  function releaseVersion(env = process.env) {
40
40
  const raw = env.LABBY_VERSION || env.LABBY_BINARY_VERSION || packageVersion();
41
- return raw.startsWith("v") ? raw : `v${raw}`;
41
+ const tag = raw.startsWith("v") ? raw : `v${raw}`;
42
+ const match = /^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-dev\.[1-9][0-9]*)?$/.exec(tag);
43
+ if (!match || match[0] !== tag) throw new Error(`Invalid immutable Labby release tag: ${tag}`);
44
+ const channel = match[4] ? "dev" : "stable";
45
+ // The package version is itself an explicit exact-version choice. Ambient
46
+ // channel settings cannot turn a stable npm package into a dev downloader.
47
+ if (env.LABBY_INSTALL_CHANNEL && env.LABBY_INSTALL_CHANNEL !== channel) {
48
+ throw new Error(`Release tag ${tag} does not match LABBY_INSTALL_CHANNEL=${env.LABBY_INSTALL_CHANNEL}`);
49
+ }
50
+ return tag;
42
51
  }
43
52
 
44
53
  function releaseBaseUrl(env = process.env) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dinglebear/labby",
3
- "version": "2.6.2",
3
+ "version": "2.7.0-dev.5",
4
4
  "license": "AGPL-3.0-only",
5
5
  "description": "Rust MCP gateway with Code Mode, authentication, setup, logs, CLI, HTTP API, and operator web UI.",
6
6
  "homepage": "https://github.com/dinglebear-ai/labby#readme",
@@ -157,10 +157,11 @@ async function main() {
157
157
 
158
158
  const target = targetFor();
159
159
  const destination = binaryPath();
160
+ const version = releaseVersion();
160
161
 
161
162
  recoverInstallation(installRoot());
162
- if (installationValid(installRoot(), target, releaseVersion())) {
163
- log(`${path.basename(destination)} already installed for ${releaseVersion()}`);
163
+ if (installationValid(installRoot(), target, version)) {
164
+ log(`${path.basename(destination)} already installed for ${version}`);
164
165
  return;
165
166
  }
166
167
 
@@ -172,7 +173,7 @@ async function main() {
172
173
  log(`downloading ${url}`);
173
174
  await download(url, archive);
174
175
  await verifyChecksum(url, archive);
175
- installArchive(archive, installRoot(), target, releaseVersion());
176
+ installArchive(archive, installRoot(), target, version);
176
177
  log(`installed ${destination}`);
177
178
  } finally {
178
179
  fs.rmSync(tempDir, { recursive: true, force: true });
@@ -180,8 +181,8 @@ async function main() {
180
181
  }
181
182
 
182
183
  function requiresCompanions(version) {
183
- const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(version);
184
- if (!match) throw new Error("invalid release version");
184
+ const match = /^v?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-dev\.[1-9][0-9]*)?$/.exec(version);
185
+ if (!match || match[0] !== version) throw new Error("invalid release version");
185
186
  // Published v2.5.0 archives contain only the binary. Later releases require the bundle.
186
187
  const [, major, minor, patch] = match.map(Number);
187
188
  return major > 2 || (major === 2 && (minor > 5 || (minor === 5 && patch > 0)));
@@ -247,6 +248,10 @@ function installArchive(archive, root, target, version) {
247
248
  extract(archive, stage, target.archiveType);
248
249
  validateInstallation(stage, target, version);
249
250
  fs.chmodSync(path.join(stage, target.binary), 0o755);
251
+ // Publish the selected channel with the verified binary directory, so a
252
+ // failed activation restores both through the existing directory backup.
253
+ const channel = /-dev\.[1-9][0-9]*$/.test(version) ? "dev" : "stable";
254
+ fs.writeFileSync(path.join(stage, ".labby-update-channel"), `${channel}\n`, { mode: 0o600 });
250
255
  // Preserve the prior complete directory until the new pair has been published.
251
256
  if (fs.existsSync(backup)) fs.rmSync(backup, { recursive: true, force: true });
252
257
  if (fs.existsSync(root)) fs.renameSync(root, backup);