claude-use 11.6.2 → 11.7.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/dist/cli.cjs CHANGED
@@ -34007,7 +34007,7 @@ var init_package = __esm({
34007
34007
  "package.json"() {
34008
34008
  package_default = {
34009
34009
  name: "claude-use",
34010
- version: "11.6.2",
34010
+ version: "11.7.0",
34011
34011
  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.",
34012
34012
  license: "MIT",
34013
34013
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -114230,6 +114230,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
114230
114230
  ports.doorHealth.generation({ providerPort: http8.port, connectPort: connect3.port, directPort: direct.port });
114231
114231
  fs23.removeRecursive(paths.frontdoorLockFile);
114232
114232
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http8.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
114233
+ const watchdog = ports.startWatchdog?.();
114233
114234
  let idleSince;
114234
114235
  let ticks = 0;
114235
114236
  const supersedingOwner = () => {
@@ -114243,6 +114244,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
114243
114244
  return current !== void 0 && servingBinary !== void 0 && (current.dev !== servingBinary.dev || current.ino !== servingBinary.ino || current.size !== servingBinary.size || current.mtimeMs !== servingBinary.mtimeMs);
114244
114245
  };
114245
114246
  const closeServing = async () => {
114247
+ watchdog?.stop();
114246
114248
  await direct.close();
114247
114249
  await connect3.close();
114248
114250
  await http8.close();
@@ -114257,7 +114259,9 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
114257
114259
  return 0;
114258
114260
  };
114259
114261
  for (; ; ) {
114262
+ watchdog?.beat();
114260
114263
  if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
114264
+ watchdog?.stop();
114261
114265
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
114262
114266
  }
114263
114267
  ticks += 1;
@@ -130991,6 +130995,93 @@ function createRcStreamHub(deps) {
130991
130995
  };
130992
130996
  }
130993
130997
 
130998
+ // src/frontdoor/watchdog.ts
130999
+ var import_node_worker_threads2 = require("node:worker_threads");
131000
+ init_ensure2();
131001
+ init_probe();
131002
+ var DOOR_STALL_BOUND_MS = 2 * FRONTDOOR_PROBE_ATTEMPTS * PROBE_TIMEOUT_MS;
131003
+ var CHECKS_PER_PROBE_DEADLINE = 2;
131004
+ var DOOR_WATCHDOG_CHECK_MS = PROBE_TIMEOUT_MS / CHECKS_PER_PROBE_DEADLINE;
131005
+ var WATCHDOG_SOURCE = `
131006
+ const { workerData, parentPort } = require("node:worker_threads");
131007
+ const fs = require("node:fs");
131008
+ const { shared, boundMs, checkEveryMs, stateFile, ownPid, action } = workerData;
131009
+ const counter = new Int32Array(shared);
131010
+ let lastValue = Atomics.load(counter, 0);
131011
+ let lastChangeAt = Date.now();
131012
+ let lastCheckAt = Date.now();
131013
+ let stopped = false;
131014
+ const record = (message) => {
131015
+ try {
131016
+ const existing = JSON.parse(fs.readFileSync(stateFile, "utf8"));
131017
+ const next = Object.assign({}, existing, { lastError: message });
131018
+ const temporary = stateFile + "." + String(ownPid) + ".watchdog";
131019
+ fs.writeFileSync(temporary, JSON.stringify(next, null, 2) + "\\n", { mode: 0o600 });
131020
+ fs.renameSync(temporary, stateFile);
131021
+ } catch (error) {
131022
+ // The state file is a courtesy to whoever looks next; the process still has to end.
131023
+ }
131024
+ };
131025
+ const timer = setInterval(() => {
131026
+ if (stopped) return;
131027
+ const now = Date.now();
131028
+ const sinceLastCheck = now - lastCheckAt;
131029
+ lastCheckAt = now;
131030
+ const value = Atomics.load(counter, 0);
131031
+ if (value !== lastValue || sinceLastCheck > checkEveryMs * 2) {
131032
+ lastValue = value;
131033
+ lastChangeAt = now;
131034
+ return;
131035
+ }
131036
+ if (now - lastChangeAt >= boundMs) {
131037
+ const message = "the front door's event loop did not run for " + String(now - lastChangeAt) + "ms; its watchdog ended the process so the next launch starts a fresh door on the same ports";
131038
+ record(message);
131039
+ stopped = true;
131040
+ clearInterval(timer);
131041
+ if (action === "kill-process") {
131042
+ process.kill(ownPid, "SIGKILL");
131043
+ } else {
131044
+ parentPort.postMessage({ stalled: true, message });
131045
+ }
131046
+ }
131047
+ }, checkEveryMs);
131048
+ parentPort.on("message", (message) => {
131049
+ if (message === "stop") {
131050
+ stopped = true;
131051
+ clearInterval(timer);
131052
+ process.exit(0);
131053
+ }
131054
+ });
131055
+ `;
131056
+ function startThreadWatchdog(params) {
131057
+ const shared = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT);
131058
+ const counter = new Int32Array(shared);
131059
+ const worker = new import_node_worker_threads2.Worker(WATCHDOG_SOURCE, {
131060
+ eval: true,
131061
+ workerData: { shared, boundMs: params.boundMs, checkEveryMs: params.checkEveryMs, stateFile: params.stateFile, ownPid: params.ownPid, action: params.action }
131062
+ });
131063
+ worker.unref();
131064
+ worker.on("message", (message) => {
131065
+ if (typeof message === "object" && message !== null && "message" in message && typeof message.message === "string") {
131066
+ params.onReport?.(message.message);
131067
+ }
131068
+ });
131069
+ let stopped = false;
131070
+ return {
131071
+ beat: () => {
131072
+ Atomics.add(counter, 0, 1);
131073
+ },
131074
+ stop: () => {
131075
+ if (stopped) {
131076
+ return;
131077
+ }
131078
+ stopped = true;
131079
+ worker.postMessage("stop");
131080
+ void worker.terminate();
131081
+ }
131082
+ };
131083
+ }
131084
+
130994
131085
  // src/frontdoor/status.ts
130995
131086
  init_socket();
130996
131087
  init_state2();
@@ -131482,6 +131573,7 @@ function realFrontDoorSupervisorPorts(paths) {
131482
131573
  return { port: handle.port, close: handle.close };
131483
131574
  },
131484
131575
  closeRcStreamHub: rcHub.close,
131576
+ startWatchdog: () => startThreadWatchdog({ stateFile: paths.frontdoorStateFile, ownPid: process.pid, boundMs: DOOR_STALL_BOUND_MS, checkEveryMs: DOOR_WATCHDOG_CHECK_MS, action: "kill-process" }),
131485
131577
  // 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.
131486
131578
  observeLaunchRegistry: createLaunchEventPublisher(doorEvents, () => Date.now()).observe,
131487
131579
  doorHealth,
package/dist/index.cjs CHANGED
@@ -2787,7 +2787,7 @@ var init_package = __esm({
2787
2787
  "package.json"() {
2788
2788
  package_default = {
2789
2789
  name: "claude-use",
2790
- version: "11.6.2",
2790
+ version: "11.7.0",
2791
2791
  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.",
2792
2792
  license: "MIT",
2793
2793
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -9512,6 +9512,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
9512
9512
  ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
9513
9513
  fs12.removeRecursive(paths.frontdoorLockFile);
9514
9514
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
9515
+ const watchdog = ports.startWatchdog?.();
9515
9516
  let idleSince;
9516
9517
  let ticks = 0;
9517
9518
  const supersedingOwner = () => {
@@ -9525,6 +9526,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
9525
9526
  return current !== void 0 && servingBinary !== void 0 && (current.dev !== servingBinary.dev || current.ino !== servingBinary.ino || current.size !== servingBinary.size || current.mtimeMs !== servingBinary.mtimeMs);
9526
9527
  };
9527
9528
  const closeServing = async () => {
9529
+ watchdog?.stop();
9528
9530
  await direct.close();
9529
9531
  await connect3.close();
9530
9532
  await http3.close();
@@ -9539,7 +9541,9 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
9539
9541
  return 0;
9540
9542
  };
9541
9543
  for (; ; ) {
9544
+ watchdog?.beat();
9542
9545
  if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
9546
+ watchdog?.stop();
9543
9547
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
9544
9548
  }
9545
9549
  ticks += 1;
package/dist/index.mjs CHANGED
@@ -2763,7 +2763,7 @@ var init_package = __esm({
2763
2763
  "package.json"() {
2764
2764
  package_default = {
2765
2765
  name: "claude-use",
2766
- version: "11.6.2",
2766
+ version: "11.7.0",
2767
2767
  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.",
2768
2768
  license: "MIT",
2769
2769
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -9099,6 +9099,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
9099
9099
  ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
9100
9100
  fs12.removeRecursive(paths.frontdoorLockFile);
9101
9101
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
9102
+ const watchdog = ports.startWatchdog?.();
9102
9103
  let idleSince;
9103
9104
  let ticks = 0;
9104
9105
  const supersedingOwner = () => {
@@ -9112,6 +9113,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
9112
9113
  return current !== void 0 && servingBinary !== void 0 && (current.dev !== servingBinary.dev || current.ino !== servingBinary.ino || current.size !== servingBinary.size || current.mtimeMs !== servingBinary.mtimeMs);
9113
9114
  };
9114
9115
  const closeServing = async () => {
9116
+ watchdog?.stop();
9115
9117
  await direct.close();
9116
9118
  await connect3.close();
9117
9119
  await http3.close();
@@ -9126,7 +9128,9 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
9126
9128
  return 0;
9127
9129
  };
9128
9130
  for (; ; ) {
9131
+ watchdog?.beat();
9129
9132
  if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
9133
+ watchdog?.stop();
9130
9134
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
9131
9135
  }
9132
9136
  ticks += 1;
@@ -12555,6 +12555,14 @@ declare function ensureFrontDoor(params: {
12555
12555
  readonly token: string;
12556
12556
  };
12557
12557
 
12558
+ /** What the supervisor holds: a beat from each tick of its main loop, and a stop when it begins to retire. */
12559
+ interface DoorWatchdog {
12560
+ /** Records that the main event loop ran. Called from the supervisor's tick, which only runs while the loop serves. */
12561
+ readonly beat: () => void;
12562
+ /** Ends the watchdog before the door begins an orderly retirement, so a slow close is never taken for a stall. Idempotent. */
12563
+ readonly stop: () => void;
12564
+ }
12565
+
12558
12566
  /** A bound front-door listener in this process, and how to stop it. */
12559
12567
  interface FrontDoorListenerHandle {
12560
12568
  readonly port: number;
@@ -12600,6 +12608,10 @@ interface FrontDoorSupervisorPorts {
12600
12608
  * Stops the Remote Control stream hub: persists every live attachment's sequence cursor synchronously, then frees the dials. Called exactly once on every exit the supervisor owns, after every listener it started is down (a live listener could still settle an observed Remote Control exchange, and the reconcile that follows would re-attach a stream the close had just ended) and before the final state write and the process's exit.
12601
12609
  */
12602
12610
  readonly closeRcStreamHub: () => void;
12611
+ /**
12612
+ * Starts the watchdog that ends this process when its main event loop stops running: it lives on its own thread, so a loop that is blocked cannot stall it. The supervisor beats it every tick and stops it before it begins to retire, so it only ever judges a door that is meant to be serving. Optional because ending the process is only right when the process is the door: the CLI's `__frontdoor-supervisor` supplies it, and a library host that runs the door inside its own process does not get its application killed by default.
12613
+ */
12614
+ readonly startWatchdog?: () => DoorWatchdog;
12603
12615
  /**
12604
12616
  * Reports one tick's session-registry facts to the door's event backbone: the sessions the tick's listing saw (taken before the prune, so a pruned launch's record is still there to name its start time) and the pids the tick's prune removed. The launch lifecycle publisher turns the diff between ticks into source-tagged events; the listing is also this loop's own idle input, so the two read one fact instead of two.
12605
12617
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-use",
3
- "version": "11.6.2",
3
+ "version": "11.7.0",
4
4
  "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.",
5
5
  "license": "MIT",
6
6
  "author": "Joseph Mearman <joseph@mearman.co.uk>",