@bigbrainforge/setup 3.21.0 → 3.23.0

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/README.md CHANGED
@@ -38,7 +38,7 @@ resolves this package itself (it lives on the public npm registry, not your
38
38
  Forge instance) — if a later step fails and you need to run setup again, use:
39
39
 
40
40
  ```
41
- npx --@bigbrainforge:registry=https://registry.npmjs.org @bigbrainforge/setup
41
+ npx --@bigbrainforge:registry=https://registry.npmjs.org "@bigbrainforge/setup"
42
42
  ```
43
43
 
44
44
  This one-shot override is what any printed "rerun" fix hint means when it
package/dist/setup.cjs CHANGED
@@ -224,7 +224,21 @@ var require_sanitize_terminal = __commonJS({
224
224
  const text = value === null || value === void 0 ? "" : String(value);
225
225
  return text.replace(TERMINAL_CONTROL_RE, "");
226
226
  }
227
- module2.exports = { sanitizeForTerminal: sanitizeForTerminal2 };
227
+ function printableRegistryTarget2(target) {
228
+ const cleaned = sanitizeForTerminal2(target);
229
+ try {
230
+ const u = new URL(cleaned);
231
+ if (u.username || u.password) {
232
+ u.username = "";
233
+ u.password = "";
234
+ return u.toString();
235
+ }
236
+ return cleaned;
237
+ } catch {
238
+ return cleaned.replace(/\/\/[^@/\s]*@/, "//");
239
+ }
240
+ }
241
+ module2.exports = { sanitizeForTerminal: sanitizeForTerminal2, printableRegistryTarget: printableRegistryTarget2 };
228
242
  }
229
243
  });
230
244
 
@@ -297,9 +311,17 @@ var require_discover_instance = __commonJS({
297
311
  }
298
312
  }
299
313
  config.mcp_url = instanceUrl.replace(/\/$/, "");
300
- fs.mkdirSync(path2.dirname(target), { recursive: true });
301
- fs.writeFileSync(target, `${JSON.stringify(config, null, 2)}
314
+ try {
315
+ fs.mkdirSync(path2.dirname(target), { recursive: true });
316
+ fs.writeFileSync(target, `${JSON.stringify(config, null, 2)}
302
317
  `, "utf8");
318
+ } catch (err) {
319
+ return {
320
+ ok: false,
321
+ unwritable: true,
322
+ error: `could not pin mcp_url into ${target} (${err && err.code ? err.code : String(err && err.message)}) \u2014 make that path writable, then rerun`
323
+ };
324
+ }
303
325
  return { ok: true, mcp_url: config.mcp_url };
304
326
  }
305
327
  function sameHost(a, b) {
@@ -389,17 +411,26 @@ var require_discover_instance = __commonJS({
389
411
  if (conflict) {
390
412
  return conflict;
391
413
  }
414
+ let pinError = null;
392
415
  if (!pinned || !sameHost(pinned, discovered)) {
393
416
  const pinResult = pinInstanceUrl(io, discovered);
394
417
  if (!pinResult.ok) {
395
- return failure("discovery_unreachable", pinResult.error);
418
+ if (!pinResult.unwritable) {
419
+ return failure("discovery_unreachable", pinResult.error);
420
+ }
421
+ pinError = pinResult.error;
422
+ const warn = typeof io.warn === "function" ? io.warn : (line) => process.stderr.write(`${sanitizeForTerminal2(line)}
423
+ `);
424
+ warn(pinError);
396
425
  }
397
426
  }
398
427
  return {
399
428
  ok: true,
400
429
  instance_url: discovered,
401
430
  deployment_model: deploymentModel,
402
- source: "discovery"
431
+ source: "discovery",
432
+ pinned: pinError === null,
433
+ ...pinError === null ? {} : { pin_error: pinError }
403
434
  };
404
435
  }
405
436
  module2.exports = { discoverInstance: discoverInstance2, DEFAULT_LICENSING_URL: DEFAULT_LICENSING_URL2, isSecureUrl: isSecureUrl2 };
@@ -681,7 +712,8 @@ var require_plugin_bundle = __commonJS({
681
712
  const dest = path2.join(tmp, "unpacked");
682
713
  fs.mkdirSync(dest);
683
714
  try {
684
- execFileSync("tar", ["-xzf", tgz, "-C", dest, "--strip-components=1"], {
715
+ execFileSync("tar", ["-xzf", "bundle.tgz", "-C", "unpacked", "--strip-components=1"], {
716
+ cwd: tmp,
685
717
  stdio: ["ignore", "pipe", "pipe"]
686
718
  });
687
719
  } catch (err) {
@@ -1005,12 +1037,20 @@ var {
1005
1037
  assertSafeVersion
1006
1038
  } = require_plugin_bundle();
1007
1039
  var { resolveSpawn } = require_exec_cli();
1008
- var { sanitizeForTerminal } = require_sanitize_terminal();
1040
+ var {
1041
+ sanitizeForTerminal,
1042
+ printableRegistryTarget
1043
+ } = require_sanitize_terminal();
1009
1044
  var { isPromptAbort, promptAbortError } = require_prompt_abort();
1010
1045
  var LICENSE_RE = /^forge_lic_[0-9A-Za-z]{43}$/;
1011
1046
  var DEFAULT_LICENSING_URL = "https://licensing.bigbrainforge.com";
1012
1047
  var DEFAULT_DIST_URL = "https://licensing.bigbrainforge.com";
1013
- var RERUN_SETUP_CMD = "npx --@bigbrainforge:registry=https://registry.npmjs.org @bigbrainforge/setup";
1048
+ var RERUN_SETUP_CMD = (
1049
+ // The package name is double-quoted per the repo shell-safety contract
1050
+ // (no bare `@`-leading argv token in operator-facing text — PowerShell
1051
+ // splatting consumes some `@…` shapes; the quotes are inert in bash/zsh).
1052
+ 'npx --@bigbrainforge:registry=https://registry.npmjs.org "@bigbrainforge/setup"'
1053
+ );
1014
1054
  function runShim(io, cmd, args) {
1015
1055
  const platform = io.platform ?? process.platform;
1016
1056
  const env = io.env ?? process.env;
@@ -1143,7 +1183,10 @@ async function runSetup(argv, io = defaultIo()) {
1143
1183
  env: io.env,
1144
1184
  fetchImpl: discoveryFetch,
1145
1185
  forceDiscovery: true,
1146
- acceptNewInstance
1186
+ acceptNewInstance,
1187
+ warn: () => {
1188
+ }
1189
+ // pinned:false is reported below, once
1147
1190
  });
1148
1191
  if (!discovered.ok) {
1149
1192
  return fail(
@@ -1160,6 +1203,14 @@ async function runSetup(argv, io = defaultIo()) {
1160
1203
  ) : `check network egress to ${licensingUrl} (it must be on your allowlist)`
1161
1204
  );
1162
1205
  }
1206
+ if (discovered.pinned === false) {
1207
+ return fail(
1208
+ io,
1209
+ "instance pin",
1210
+ discovered.pin_error,
1211
+ `make that path writable (usually permissions on ~/.claude/forge), then rerun: ${RERUN_SETUP_CMD}`
1212
+ );
1213
+ }
1163
1214
  print(`\u2713 instance pinned: ${discovered.instance_url} (${discovered.deployment_model})`);
1164
1215
  let npmrc;
1165
1216
  try {
@@ -1174,8 +1225,9 @@ async function runSetup(argv, io = defaultIo()) {
1174
1225
  }
1175
1226
  if (npmrc.status === "declined") {
1176
1227
  const legacyNote = npmrc.replacedLegacy ? " (a legacy npm.pkg.github.com credential line found alongside it was removed)" : "";
1228
+ const printableTarget = printableRegistryTarget(npmrc.foreignScopeTarget);
1177
1229
  print(
1178
- npmrc.foreignScopeTarget === "" ? `! npm NOT seeded \u2014 ~/.npmrc has a malformed @bigbrainforge:registry= line (no value). Fix or remove that line, then rerun setup; otherwise no action is needed.${legacyNote}` : `! npm NOT seeded \u2014 @bigbrainforge:registry already points at ${npmrc.foreignScopeTarget} (an enterprise proxy or other custom config). If that isn't your organization's proxy, remove that line from ~/.npmrc and rerun setup; otherwise no action is needed.${legacyNote}`
1230
+ npmrc.foreignScopeTarget === "" ? `! npm NOT seeded \u2014 ~/.npmrc has a malformed @bigbrainforge:registry= line (no value). Fix or remove that line, then rerun setup; otherwise no action is needed.${legacyNote}` : `! npm NOT seeded \u2014 @bigbrainforge:registry already points at ${printableTarget} (an enterprise proxy or other custom config). If that isn't your organization's proxy, remove that line from ~/.npmrc and rerun setup; otherwise no action is needed.${legacyNote}`
1179
1231
  );
1180
1232
  } else {
1181
1233
  print(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigbrainforge/setup",
3
- "version": "3.21.0",
3
+ "version": "3.23.0",
4
4
  "description": "Forge workstation setup — paste one license, get a working Forge install.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://github.com/bigbrainforge/forge",