bitfab-cli 0.2.186 → 0.2.187

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 +109 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9566,6 +9566,40 @@ function updateActiveStudioSession(updates) {
9566
9566
  writeStateFile(sessionFilePath(), updated);
9567
9567
  return updated;
9568
9568
  }
9569
+ function clearActiveStudioSession(sessionId, opts = {}) {
9570
+ try {
9571
+ const current = readStateFile(sessionFilePath());
9572
+ if (!current) {
9573
+ return clearLegacySession(sessionId, opts);
9574
+ }
9575
+ if (current.sessionId !== sessionId) {
9576
+ return false;
9577
+ }
9578
+ if (!opts.force && current.pollerPid != null && current.pollerPid !== process.pid && isProcessAlive(current.pollerPid)) {
9579
+ return false;
9580
+ }
9581
+ fs7.unlinkSync(sessionFilePath());
9582
+ return true;
9583
+ } catch {
9584
+ return false;
9585
+ }
9586
+ }
9587
+ function clearLegacySession(sessionId, opts = {}) {
9588
+ try {
9589
+ const raw = fs7.readFileSync(legacyFilePath(), "utf-8");
9590
+ const parsed = JSON.parse(raw);
9591
+ if (parsed.sessionId !== sessionId) {
9592
+ return false;
9593
+ }
9594
+ if (!opts.force && typeof parsed.pid === "number" && parsed.pid !== process.pid && isProcessAlive(parsed.pid)) {
9595
+ return false;
9596
+ }
9597
+ fs7.unlinkSync(legacyFilePath());
9598
+ return true;
9599
+ } catch {
9600
+ return false;
9601
+ }
9602
+ }
9569
9603
  function isProcessAlive(pid) {
9570
9604
  try {
9571
9605
  process.kill(pid, 0);
@@ -11003,6 +11037,48 @@ async function resolveChannel(apiKey, serviceUrl) {
11003
11037
  return new DirectChannel(apiKey, serviceUrl);
11004
11038
  }
11005
11039
 
11040
+ // ../bitfab-plugin-lib/dist/studioTeardown.js
11041
+ function killStudioWindow(sessionId) {
11042
+ const record2 = readActiveStudioSession();
11043
+ if (record2?.sessionId !== sessionId || record2.windowPid == null) {
11044
+ return;
11045
+ }
11046
+ try {
11047
+ process.kill(record2.windowPid, "SIGTERM");
11048
+ } catch {
11049
+ }
11050
+ }
11051
+ function killPollerProcess(sessionId) {
11052
+ const record2 = readActiveStudioSession();
11053
+ if (record2?.sessionId !== sessionId || record2.pollerPid == null || record2.pollerPid === process.pid) {
11054
+ return;
11055
+ }
11056
+ try {
11057
+ process.kill(record2.pollerPid, "SIGTERM");
11058
+ } catch {
11059
+ }
11060
+ }
11061
+
11062
+ // ../bitfab-plugin-lib/dist/commands/clearStudioSession.js
11063
+ async function clearStudioSessionById(sessionId, record2) {
11064
+ killStudioWindow(sessionId);
11065
+ const alreadyClosed = record2?.sessionId === sessionId && record2.windowState === "closed";
11066
+ if (!alreadyClosed) {
11067
+ closeStudioWindowsBySession(sessionId);
11068
+ }
11069
+ killPollerProcess(sessionId);
11070
+ try {
11071
+ const channel = await resolveChannel("", record2?.serviceUrl ?? "");
11072
+ try {
11073
+ await channel.clearSession(sessionId);
11074
+ } finally {
11075
+ channel.destroy();
11076
+ }
11077
+ } catch {
11078
+ }
11079
+ return clearActiveStudioSession(sessionId, { force: true });
11080
+ }
11081
+
11006
11082
  // ../bitfab-plugin-lib/dist/replayCapabilities.js
11007
11083
  var semver = __toESM(require_semver2(), 1);
11008
11084
 
@@ -11451,6 +11527,13 @@ Already logged in as ${identity}${endpoint}. Run the login command with --force
11451
11527
  return;
11452
11528
  }
11453
11529
  }
11530
+ if (force) {
11531
+ const record2 = readActiveStudioSession();
11532
+ if (record2) {
11533
+ await clearStudioSessionById(record2.sessionId, record2).catch(() => {
11534
+ });
11535
+ }
11536
+ }
11454
11537
  try {
11455
11538
  let printedSignInUrl = false;
11456
11539
  const result = await openStudioTo("/studio", {
@@ -11495,7 +11578,7 @@ ${greeting}`);
11495
11578
  } catch (err) {
11496
11579
  if (exitOnComplete) {
11497
11580
  if (err instanceof StudioNavigationError && err.staleSessionId) {
11498
- console.error("\nA Studio window is recorded as open but is not responding. Close it (or run the clearStudioSession command), then try again.");
11581
+ console.error("\nA Studio window is recorded as open but is not responding. Close the Studio window and try again. To force-clear a stale session, a user can re-run with `bitfab login --force` (manual recovery - automated agents should not run it).");
11499
11582
  } else {
11500
11583
  console.error(`
11501
11584
  ${err.message}`);
@@ -33004,7 +33087,7 @@ var GLOBAL_HELP_TEXT = `Usage: bitfab <command> [options]
33004
33087
  Commands:
33005
33088
  init [--editor <name>] Full onboarding: plugin-install, login, and setup
33006
33089
  plugin-install [--editor <name>] Install the Bitfab plugin in one editor
33007
- login Authenticate with Bitfab (opens browser)
33090
+ login [--force] Authenticate with Bitfab (opens browser)
33008
33091
  logout Remove stored credentials
33009
33092
  session-logs [status|enable|disable] Read or update session log collection
33010
33093
  setup [--editor <name>] Launch /bitfab:setup in the editor
@@ -33021,6 +33104,7 @@ Options:
33021
33104
  --no-upload-logs analyze-repo: keep session logs local (skips the prompt)
33022
33105
  --limit <n> analyze-repo: cap how many draft trace plans to upload (default 5)
33023
33106
  --prompt, -p <text> analyze-repo: free-text guidance steering what to focus on
33107
+ --force login: re-authenticate and clear any stale Studio session first
33024
33108
 
33025
33109
  Examples:
33026
33110
  bitfab init Full setup (detect editor, install, login, setup)
@@ -33028,6 +33112,7 @@ Examples:
33028
33112
  bitfab analyze-repo Scan the repo and upload draft trace plans (headless)
33029
33113
  bitfab analyze-repo --limit 3 Scan the repo and upload at most 3 draft trace plans
33030
33114
  bitfab analyze-repo "focus on billing" Scan with free-text guidance on what to prioritize
33115
+ bitfab login --force Re-authenticate and clear a stale Studio session
33031
33116
  bitfab session-logs enable Enable session log collection
33032
33117
  bitfab session-logs disable Disable session log collection
33033
33118
  bitfab assistant investigate Investigate traces
@@ -33060,15 +33145,16 @@ Examples:
33060
33145
  bitfab plugin-install
33061
33146
  bitfab plugin-install --editor cursor
33062
33147
  `,
33063
- login: `Usage: bitfab login
33148
+ login: `Usage: bitfab login [--force]
33064
33149
 
33065
33150
  Authenticate with Bitfab in the browser and save credentials locally.
33066
33151
 
33067
33152
  Options:
33068
- This command has no options.
33153
+ --force Re-authenticate even when already signed in, and clear any stale Studio session first
33069
33154
 
33070
33155
  Examples:
33071
33156
  bitfab login
33157
+ bitfab login --force
33072
33158
  `,
33073
33159
  logout: `Usage: bitfab logout
33074
33160
 
@@ -33230,7 +33316,7 @@ function wantsHelp(argv) {
33230
33316
  var COMMAND_SPECS = {
33231
33317
  init: { flags: ["editor", "skipPermissions"], unknownOption: "error" },
33232
33318
  "plugin-install": { flags: ["editor"], unknownOption: "error" },
33233
- login: { flags: [], unknownOption: "error" },
33319
+ login: { flags: ["force"], unknownOption: "error" },
33234
33320
  logout: { flags: [], unknownOption: "error" },
33235
33321
  "session-logs": { flags: [], unknownOption: "error" },
33236
33322
  setup: { flags: ["editor", "skipPermissions"], unknownOption: "error" },
@@ -33304,6 +33390,12 @@ function applyFlag(key, token, next, values) {
33304
33390
  return 1;
33305
33391
  }
33306
33392
  return null;
33393
+ case "force":
33394
+ if (token === "--force") {
33395
+ values.force = true;
33396
+ return 1;
33397
+ }
33398
+ return null;
33307
33399
  }
33308
33400
  }
33309
33401
  function parseArgs2(argv) {
@@ -33350,6 +33442,7 @@ function parseArgs2(argv) {
33350
33442
  uploadLogs: values.uploadLogs,
33351
33443
  limit: values.limit,
33352
33444
  prompt: values.prompt,
33445
+ force: values.force,
33353
33446
  rest
33354
33447
  };
33355
33448
  }
@@ -33369,7 +33462,16 @@ ${GLOBAL_HELP_TEXT}`
33369
33462
  process.stdout.write(helpText);
33370
33463
  return;
33371
33464
  }
33372
- const { command, editor, skipPermissions, uploadLogs, limit, prompt, rest } = parseArgs2(argv);
33465
+ const {
33466
+ command,
33467
+ editor,
33468
+ skipPermissions,
33469
+ uploadLogs,
33470
+ limit,
33471
+ prompt,
33472
+ force,
33473
+ rest
33474
+ } = parseArgs2(argv);
33373
33475
  const abortUpdateCheck = startUpdateCheck();
33374
33476
  if (command === "init") {
33375
33477
  await runInit({ editor, skipPermissions });
@@ -33382,7 +33484,7 @@ ${GLOBAL_HELP_TEXT}`
33382
33484
  return;
33383
33485
  }
33384
33486
  if (command === "login") {
33385
- await runLoginCommand();
33487
+ await runLoginCommand({ force });
33386
33488
  abortUpdateCheck();
33387
33489
  return;
33388
33490
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.186",
3
+ "version": "0.2.187",
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",