bitfab-cli 0.2.115 → 0.2.117

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 +29 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8766,7 +8766,9 @@ var STUDIO_ROUTE_PATTERNS = [
8766
8766
  /^\/studio$/,
8767
8767
  /^\/studio\/experiments$/,
8768
8768
  /^\/studio\/close$/,
8769
- /^\/studio\/sign-in$/,
8769
+ // Catch-all sign-in route ([[...rest]]) so Clerk can path-route its sub-steps
8770
+ // (sso-callback, factor-one, continue); matches /studio/sign-in and any child.
8771
+ /^\/studio\/sign-in(\/.*)?$/,
8770
8772
  /^\/studio\/trace-plan\/[^/]+$/,
8771
8773
  // Matches both real dataset ids and the legacy "labeled" segment; old plugin
8772
8774
  // versions still navigate to /datasets/labeled, which the server redirects.
@@ -10439,6 +10441,9 @@ function buildStudioSessionUrl(args) {
10439
10441
  }
10440
10442
 
10441
10443
  // ../bitfab-plugin-lib/dist/studioChannel.js
10444
+ function stripSessionId(path19, sessionId) {
10445
+ return sessionId ? path19.split(sessionId).join("__SID__") : path19;
10446
+ }
10442
10447
  var DirectChannel = class {
10443
10448
  apiKey;
10444
10449
  serviceUrl;
@@ -10456,6 +10461,10 @@ var DirectChannel = class {
10456
10461
  if (!this.apiKey) {
10457
10462
  const sessionId2 = opts?.sessionId ?? crypto7.randomUUID();
10458
10463
  const initialPath = resolveStudioInitialPath(path19);
10464
+ const live = readActiveStudioSession();
10465
+ if (live && live.source === "direct" && !live.authenticated && live.windowState !== "closed" && live.serviceUrl === this.serviceUrl && live.currentPath != null && stripSessionId(live.currentPath, live.sessionId) === stripSessionId(initialPath, sessionId2)) {
10466
+ return { sessionId: live.sessionId, opened: false };
10467
+ }
10459
10468
  const url2 = buildStudioSessionUrl({
10460
10469
  serviceUrl: this.serviceUrl,
10461
10470
  path: initialPath,
@@ -10466,7 +10475,13 @@ var DirectChannel = class {
10466
10475
  sessionId: sessionId2,
10467
10476
  serviceUrl: this.serviceUrl,
10468
10477
  windowPid,
10469
- currentPath: initialPath
10478
+ currentPath: initialPath,
10479
+ // A keyless login window is pre-auth: writeActiveStudioSession defaults
10480
+ // authenticated to true, but this window has no token yet. Record it as
10481
+ // unauthenticated so the keyless reuse gate above (!live.authenticated)
10482
+ // actually matches it, and so the login-completion flip to authenticated
10483
+ // (openStudioTo) is what later excludes it from reuse.
10484
+ authenticated: false
10470
10485
  });
10471
10486
  return { sessionId: sessionId2, opened: true };
10472
10487
  }
@@ -10480,6 +10495,7 @@ var DirectChannel = class {
10480
10495
  if (!ack.acked) {
10481
10496
  throw new StudioNavigationError(ack.reason ?? "unknown", ack.blockedReason, existing.sessionId);
10482
10497
  }
10498
+ updateActiveStudioSession({ currentPath: path19 });
10483
10499
  return { sessionId: existing.sessionId, opened: false };
10484
10500
  }
10485
10501
  truncateStudioEventLog(resolveAgentSessionKey());
@@ -11045,17 +11061,20 @@ async function openStudioTo(path19, opts = {}) {
11045
11061
  };
11046
11062
  };
11047
11063
  if (!apiKey) {
11048
- const sessionId2 = crypto8.randomUUID();
11049
11064
  const destination = opts.freshWindowPath ?? path19;
11050
11065
  const destSeparator = destination.includes("?") ? "&" : "?";
11051
- const redirectPath = `${destination}${destSeparator}session=${encodeURIComponent(sessionId2)}&pluginLogin=true`;
11052
- const signInInitialPath = `/studio/sign-in?redirect_url=${encodeURIComponent(redirectPath)}&session=${encodeURIComponent(sessionId2)}`;
11053
- await channel.openOrNavigate(signInInitialPath, {
11066
+ const buildSignInPath = (sid) => {
11067
+ const redirectPath = `${destination}${destSeparator}session=${encodeURIComponent(sid)}&pluginLogin=true`;
11068
+ return `/studio/sign-in?redirect_url=${encodeURIComponent(redirectPath)}&session=${encodeURIComponent(sid)}`;
11069
+ };
11070
+ const requestedSessionId = crypto8.randomUUID();
11071
+ const openResult = await channel.openOrNavigate(buildSignInPath(requestedSessionId), {
11054
11072
  clientHeaders: opts.clientHeaders,
11055
- sessionId: sessionId2,
11073
+ sessionId: requestedSessionId,
11056
11074
  focusTarget: focusTarget ?? void 0
11057
11075
  });
11058
- const signInUrl = `${serviceUrl}${signInInitialPath}`;
11076
+ const sessionId2 = openResult.sessionId;
11077
+ const signInUrl = `${serviceUrl}${buildSignInPath(sessionId2)}`;
11059
11078
  opts.onLoginRequired?.(sessionId2, signInUrl);
11060
11079
  const loginApiKey = await new Promise((resolve, reject) => {
11061
11080
  const timer = setTimeout(() => {
@@ -11079,9 +11098,10 @@ async function openStudioTo(path19, opts = {}) {
11079
11098
  });
11080
11099
  });
11081
11100
  saveCredentials(loginApiKey);
11101
+ updateActiveStudioSession({ authenticated: true });
11082
11102
  opts.onAuthenticated?.(sessionId2);
11083
11103
  channel.setApiKey(loginApiKey);
11084
- return finish(sessionId2, true, loginApiKey);
11104
+ return finish(sessionId2, openResult.opened, loginApiKey);
11085
11105
  }
11086
11106
  const { sessionId, opened } = await channel.openOrNavigate(path19, {
11087
11107
  clientHeaders: opts.clientHeaders,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.115",
3
+ "version": "0.2.117",
4
4
  "description": "Install and configure the Bitfab plugin in Claude Code, Codex, or Cursor.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",