claude-use 11.44.4 → 11.44.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/dist/cli.cjs CHANGED
@@ -34701,7 +34701,7 @@ var init_package = __esm({
34701
34701
  "package.json"() {
34702
34702
  package_default = {
34703
34703
  name: "claude-use",
34704
- version: "11.44.4",
34704
+ version: "11.44.5",
34705
34705
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
34706
34706
  license: "MIT",
34707
34707
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -135075,7 +135075,7 @@ const { workerData, parentPort } = require("node:worker_threads");
135075
135075
  const fs = require("node:fs");
135076
135076
  const os = require("node:os");
135077
135077
  const inspector = require("node:inspector");
135078
- const { shared, boundMs, checkEveryMs, pauseWaitMs, stateFile, ownPid, action, logFile, respawn, respawnGeneration, respawnMaxGeneration, awaitPidEnv, respawnGenerationEnv } = workerData;
135078
+ const { shared, boundMs, checkEveryMs, pauseWaitMs, stateFile, ownPid, action, logFile, respawn, respawnGeneration, respawnMaxGeneration, startLockFile, awaitPidEnv, respawnGenerationEnv } = workerData;
135079
135079
  const counter = new Int32Array(shared);
135080
135080
  let lastValue = Atomics.load(counter, 0);
135081
135081
  let lastChangeAt = Date.now();
@@ -135139,17 +135139,59 @@ const describeMainThread = (waitMs, resume) => new Promise((resolve) => {
135139
135139
  finish("the main thread could not be inspected: " + (error instanceof Error ? error.message : String(error)));
135140
135140
  }
135141
135141
  });
135142
+ // Whether a process is alive: signal 0 only tests, and EPERM means it exists under another user.
135143
+ const isRunning = (pid) => {
135144
+ try {
135145
+ process.kill(pid, 0);
135146
+ return true;
135147
+ } catch (error) {
135148
+ return error.code === "EPERM";
135149
+ }
135150
+ };
135151
+ // The pid holding the start lock when that holder is alive, which means a door is already being started and another must not be: the launcher's ensure and this respawn are the two things that start a door, and the lock is the one protocol that keeps them from starting two. A dead holder's lock is litter and is cleared, exactly as the launcher's ensure clears it.
135152
+ const liveLockHolder = () => {
135153
+ let holder;
135154
+ try {
135155
+ holder = JSON.parse(fs.readFileSync(startLockFile, "utf8")).pid;
135156
+ } catch (error) {
135157
+ return undefined;
135158
+ }
135159
+ if (typeof holder === "number" && isRunning(holder)) return holder;
135160
+ fs.rmSync(startLockFile, { force: true });
135161
+ return undefined;
135162
+ };
135163
+ // Creates the lock naming the replacement as its holder, atomically (the wx flag), so the launcher's ensure sees a live holder while the replacement boots and waits for it instead of starting a door of its own; the replacement removes the lock once it is serving, as every door does.
135164
+ const claimStartLock = (holder) => {
135165
+ try {
135166
+ fs.writeFileSync(startLockFile, JSON.stringify({ pid: holder, at: Date.now() }) + "\\n", { flag: "wx" });
135167
+ return true;
135168
+ } catch (error) {
135169
+ if (error.code === "EEXIST") return false;
135170
+ throw error;
135171
+ }
135172
+ };
135142
135173
  const spawnReplacement = () => {
135143
135174
  if (respawn === undefined || logFile === undefined) return;
135144
135175
  if (respawnGeneration >= respawnMaxGeneration) {
135145
135176
  log("not starting another replacement: this door was replacement generation " + String(respawnGeneration) + " of " + String(respawnMaxGeneration) + ", so the stall has recurred through consecutive doors and the machine, not the door, is the one refusing to serve; leaving the next launch's ensure to start one");
135146
135177
  return;
135147
135178
  }
135179
+ const startingBy = liveLockHolder();
135180
+ if (startingBy !== undefined) {
135181
+ log("not starting a replacement: process " + String(startingBy) + " holds the start lock, so a door is already being started and a second one would race it for the sticky ports");
135182
+ return;
135183
+ }
135148
135184
  try {
135149
135185
  const out = fs.openSync(logFile, "a");
135150
135186
  const child = require("node:child_process").spawn(respawn.command, respawn.args, { detached: true, stdio: ["ignore", out, out], env: Object.assign({}, respawn.env, { [awaitPidEnv]: String(ownPid), [respawnGenerationEnv]: String(respawnGeneration + 1) }) });
135151
135187
  child.unref();
135152
135188
  fs.closeSync(out);
135189
+ if (!claimStartLock(child.pid)) {
135190
+ // A launcher took the lock between the check and the spawn, so its door is the one that is starting: this one must not also bind.
135191
+ process.kill(child.pid, "SIGKILL");
135192
+ log("withdrew replacement door " + String(child.pid) + ": a launcher took the start lock first and its door is the one starting");
135193
+ return;
135194
+ }
135153
135195
  log("started replacement door " + String(child.pid) + " of generation " + String(respawnGeneration + 1) + ", which binds once this process is gone");
135154
135196
  } catch (error) {
135155
135197
  log("could not start a replacement door: " + (error instanceof Error ? error.message : String(error)));
@@ -135198,7 +135240,7 @@ function startThreadWatchdog(params) {
135198
135240
  const counter = new Int32Array(shared);
135199
135241
  const worker = new import_node_worker_threads2.Worker(WATCHDOG_SOURCE, {
135200
135242
  eval: true,
135201
- workerData: { shared, boundMs: params.boundMs, checkEveryMs: params.checkEveryMs, pauseWaitMs: params.pauseWaitMs, stateFile: params.stateFile, ownPid: params.ownPid, action: params.action, logFile: params.logFile, respawn: params.respawn, respawnGeneration: params.respawnGeneration, respawnMaxGeneration: params.respawnMaxGeneration, awaitPidEnv: DOOR_AWAIT_PID_ENV, respawnGenerationEnv: DOOR_RESPAWN_GENERATION_ENV }
135243
+ workerData: { shared, boundMs: params.boundMs, checkEveryMs: params.checkEveryMs, pauseWaitMs: params.pauseWaitMs, stateFile: params.stateFile, ownPid: params.ownPid, action: params.action, logFile: params.logFile, respawn: params.respawn, respawnGeneration: params.respawnGeneration, respawnMaxGeneration: params.respawnMaxGeneration, startLockFile: params.startLockFile, awaitPidEnv: DOOR_AWAIT_PID_ENV, respawnGenerationEnv: DOOR_RESPAWN_GENERATION_ENV }
135202
135244
  });
135203
135245
  worker.unref();
135204
135246
  worker.on("message", (message) => {
@@ -135774,7 +135816,8 @@ function realFrontDoorSupervisorPorts(paths, respawnGeneration) {
135774
135816
  logFile: paths.frontdoorLogPath,
135775
135817
  respawn: respawnInvocation(paths),
135776
135818
  respawnGeneration,
135777
- respawnMaxGeneration: DOOR_RESPAWN_MAX_GENERATIONS
135819
+ respawnMaxGeneration: DOOR_RESPAWN_MAX_GENERATIONS,
135820
+ startLockFile: paths.frontdoorLockFile
135778
135821
  }),
135779
135822
  // The launch lifecycle publisher over the same backbone the typed API serves: the tick's registry facts go in here, and the door's own register, prune and end moments come out as source-tagged events.
135780
135823
  observeLaunchRegistry: createLaunchEventPublisher(doorEvents, () => Date.now()).observe,
package/dist/index.cjs CHANGED
@@ -3151,7 +3151,7 @@ var init_package = __esm({
3151
3151
  "package.json"() {
3152
3152
  package_default = {
3153
3153
  name: "claude-use",
3154
- version: "11.44.4",
3154
+ version: "11.44.5",
3155
3155
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
3156
3156
  license: "MIT",
3157
3157
  author: "Joseph Mearman <joseph@mearman.co.uk>",
package/dist/index.mjs CHANGED
@@ -3127,7 +3127,7 @@ var init_package = __esm({
3127
3127
  "package.json"() {
3128
3128
  package_default = {
3129
3129
  name: "claude-use",
3130
- version: "11.44.4",
3130
+ version: "11.44.5",
3131
3131
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
3132
3132
  license: "MIT",
3133
3133
  author: "Joseph Mearman <joseph@mearman.co.uk>",