claude-use 11.62.3 → 11.63.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/index.cjs CHANGED
@@ -3923,14 +3923,15 @@ function pruneDeadFrontDoorSessions(fs14, sessionsDir, listed, isRunning) {
3923
3923
  }
3924
3924
  return removed;
3925
3925
  }
3926
- var import_node_path9, import_zod5, FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
3926
+ var import_node_path9, import_zod5, FRONT_DOOR_PROTOCOL, FRONT_DOOR_HANDOVER_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
3927
3927
  var init_state = __esm({
3928
3928
  "src/frontdoor/state.ts"() {
3929
3929
  "use strict";
3930
3930
  import_node_path9 = __toESM(require("node:path"), 1);
3931
3931
  import_zod5 = require("zod");
3932
3932
  init_schema();
3933
- FRONT_DOOR_PROTOCOL = 5;
3933
+ FRONT_DOOR_PROTOCOL = 6;
3934
+ FRONT_DOOR_HANDOVER_PROTOCOL = 6;
3934
3935
  FrontDoorSessionSchema = import_zod5.z.strictObject({ pid: import_zod5.z.number().int().positive(), startedAt: import_zod5.z.number(), token: import_zod5.z.string().min(1), supervisorPid: import_zod5.z.number().int().positive().optional(), sessionId: import_zod5.z.string().min(1).optional(), models: ModelsConfigSchema.optional() });
3935
3936
  FrontDoorStateSchema = import_zod5.z.strictObject({
3936
3937
  /**
@@ -4026,18 +4027,24 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4026
4027
  ...lastConnectPort === void 0 ? {} : { lastConnectPort },
4027
4028
  ...lastDirectPort === void 0 ? {} : { lastDirectPort }
4028
4029
  });
4030
+ const { predecessor } = ports;
4031
+ const sourceOf = (listener, preferredPort) => predecessor === void 0 ? { preferredPort } : { inherit: async () => await predecessor.take(listener) };
4029
4032
  const fail = (message) => {
4030
4033
  ports.closeRcStreamHub();
4031
- writeFrontDoorState(fs14, paths.frontdoorStateFile, { lastError: message, ...sticky() });
4032
- fs14.removeRecursive(paths.frontdoorLockFile);
4034
+ if (predecessor === void 0) {
4035
+ writeFrontDoorState(fs14, paths.frontdoorStateFile, { lastError: message, ...sticky() });
4036
+ fs14.removeRecursive(paths.frontdoorLockFile);
4037
+ }
4033
4038
  ports.log(`agent-shim frontdoor supervisor: ${message}`);
4034
4039
  return 1;
4035
4040
  };
4036
- writeFrontDoorState(fs14, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
4041
+ if (predecessor === void 0) {
4042
+ writeFrontDoorState(fs14, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
4043
+ }
4037
4044
  const previousSticky = lastPort;
4038
4045
  let http3;
4039
4046
  try {
4040
- http3 = await ports.startProviderListener(lastPort);
4047
+ http3 = await ports.startProviderListener(sourceOf("provider", lastPort));
4041
4048
  } catch (error) {
4042
4049
  ports.doorHealth.listenerFailed("provider", error instanceof Error ? error.message : String(error));
4043
4050
  return fail(`could not start the provider listener: ${error instanceof Error ? error.message : String(error)}`);
@@ -4049,7 +4056,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4049
4056
  const previousStickyConnect = lastConnectPort;
4050
4057
  let connect3;
4051
4058
  try {
4052
- connect3 = await ports.startConnectListener(lastConnectPort);
4059
+ connect3 = await ports.startConnectListener(sourceOf("connect", lastConnectPort));
4053
4060
  } catch (error) {
4054
4061
  await http3.close();
4055
4062
  ports.doorHealth.listenerFailed("connect", error instanceof Error ? error.message : String(error));
@@ -4062,7 +4069,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4062
4069
  const previousStickyDirect = lastDirectPort;
4063
4070
  let direct;
4064
4071
  try {
4065
- direct = await ports.startDirectListener(lastDirectPort);
4072
+ direct = await ports.startDirectListener(sourceOf("direct", lastDirectPort));
4066
4073
  } catch (error) {
4067
4074
  await connect3.close();
4068
4075
  await http3.close();
@@ -4076,8 +4083,12 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4076
4083
  writeFrontDoorDirectRecord(fs14, paths.frontdoorDirectRecordsDir, { pid: ports.ownPid, directPort: direct.port });
4077
4084
  writeFrontDoorState(fs14, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
4078
4085
  ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
4079
- fs14.removeRecursive(paths.frontdoorLockFile);
4080
- 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)}`);
4086
+ if (predecessor === void 0) {
4087
+ fs14.removeRecursive(paths.frontdoorLockFile);
4088
+ } else {
4089
+ predecessor.serving();
4090
+ }
4091
+ 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)}${predecessor === void 0 ? "" : ", taken over from the door it replaced"}`);
4081
4092
  const watchdog = ports.startWatchdog?.();
4082
4093
  let idleSince;
4083
4094
  let ticks = 0;
@@ -4097,14 +4108,16 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4097
4108
  resolve();
4098
4109
  };
4099
4110
  ports.retire?.addEventListener("abort", wake, { once: true });
4111
+ ports.handover?.requested.addEventListener("abort", wake, { once: true });
4100
4112
  void ports.sleep(FRONTDOOR_POLL_MS).then(() => {
4101
4113
  ports.retire?.removeEventListener("abort", wake);
4114
+ ports.handover?.requested.removeEventListener("abort", wake);
4102
4115
  resolve();
4103
4116
  });
4104
4117
  });
4105
4118
  };
4106
4119
  const retireByDrain = async () => {
4107
- ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: asked to exit; releasing the front door's addresses and finishing the connections it carries`);
4120
+ ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: releasing the front door's addresses and finishing the connections it carries`);
4108
4121
  watchdog?.stop();
4109
4122
  ports.stopBackgroundWork?.();
4110
4123
  const drained = [direct.drain(), connect3.drain(), http3.drain()];
@@ -4119,6 +4132,17 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4119
4132
  ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: the connections this door carried have ended; exiting`);
4120
4133
  return 0;
4121
4134
  };
4135
+ const handOverThenDrain = async (run) => {
4136
+ ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: asked to hand the front door's listeners to a successor; accepting on them until it serves`);
4137
+ const outcome = await run({ provider: http3.listening, connect: connect3.listening, direct: direct.listening });
4138
+ if (outcome.ok) {
4139
+ ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: successor ${String(outcome.successorPid)} serves the front door's listeners`);
4140
+ ports.doorHealth.superseded(outcome.successorPid);
4141
+ } else {
4142
+ ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: the handover failed (${outcome.reason}); retiring by drain so a successor is started on the released addresses`);
4143
+ }
4144
+ return await retireByDrain();
4145
+ };
4122
4146
  const closeServing = async () => {
4123
4147
  watchdog?.stop();
4124
4148
  await direct.close();
@@ -4136,8 +4160,12 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
4136
4160
  };
4137
4161
  for (; ; ) {
4138
4162
  if (ports.retire?.aborted === true) {
4163
+ ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: asked to exit`);
4139
4164
  return await retireByDrain();
4140
4165
  }
4166
+ if (ports.handover?.requested.aborted === true && supersededBy === void 0) {
4167
+ return await handOverThenDrain(ports.handover.run);
4168
+ }
4141
4169
  if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
4142
4170
  watchdog?.stop();
4143
4171
  return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
@@ -4274,8 +4302,10 @@ function caParses(ca) {
4274
4302
  return false;
4275
4303
  }
4276
4304
  }
4277
- async function startConnectServer(config, effects, preferredPort) {
4305
+ async function startConnectServer(config, effects, source) {
4278
4306
  const tunnelTokens = /* @__PURE__ */ new WeakMap();
4307
+ const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
4308
+ const lateSessionDeadlines = /* @__PURE__ */ new WeakMap();
4279
4309
  const onUpgrade = (host) => (request4, socket, head) => {
4280
4310
  config.capture?.upgrade(request4);
4281
4311
  if (head.length > 0) {
@@ -4297,6 +4327,12 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
4297
4327
  return { host, serveSecure: serveSecure2, tlsAcceptor: tlsAcceptor2 };
4298
4328
  }
4299
4329
  const handleHostRequest = async (request4, response) => {
4330
+ if (ledger.retiring()) {
4331
+ clearTimeout(lateSessionDeadlines.get(request4.socket));
4332
+ response.once("close", () => {
4333
+ request4.socket.end();
4334
+ });
4335
+ }
4300
4336
  if (config.localSurface !== void 0 && await config.localSurface.serve(host, request4, response)) {
4301
4337
  return;
4302
4338
  }
@@ -4316,13 +4352,19 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
4316
4352
  const httpSession = effects.createHttpSession(handler, onUpgrade(host));
4317
4353
  const serveSecure = (secure, capability) => {
4318
4354
  tunnelTokens.set(secure, capability);
4355
+ if (ledger.retiring()) {
4356
+ const deadline = setTimeout(() => {
4357
+ secure.destroy();
4358
+ }, config.limits.headDeadlineMs);
4359
+ deadline.unref();
4360
+ lateSessionDeadlines.set(secure, deadline);
4361
+ }
4319
4362
  httpSession.serve(secure);
4320
4363
  };
4321
4364
  const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(host), serveSecure);
4322
4365
  return { host, serveSecure, httpSession, tlsAcceptor };
4323
4366
  });
4324
- const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
4325
- const listener = await effects.listenLoopback(preferredPort, (socket) => {
4367
+ const listener = await effects.listenLoopback(source, (socket) => {
4326
4368
  handleConnect(socket, { config, effects, sessions, ledger });
4327
4369
  });
4328
4370
  const apiSession = sessions.find((session) => session.host === config.routedHost);
@@ -4335,7 +4377,7 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
4335
4377
  }
4336
4378
  session.serveSecure(secure, config.transparentCapability ?? "");
4337
4379
  });
4338
- const transparent = config.transparentPort === void 0 || apiSession === void 0 ? void 0 : await effects.listenLoopback(config.transparentPort, (socket) => {
4380
+ const transparent = config.transparentPort === void 0 || apiSession === void 0 ? void 0 : await effects.listenLoopback({ preferredPort: config.transparentPort }, (socket) => {
4339
4381
  sniAcceptor.accept(socket);
4340
4382
  });
4341
4383
  const closeSurface = async () => {
@@ -4350,6 +4392,7 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
4350
4392
  };
4351
4393
  return {
4352
4394
  port: listener.port,
4395
+ listening: listener.listening,
4353
4396
  ...transparent === void 0 ? {} : { transparentPort: transparent.port },
4354
4397
  openTunnels: ledger.openTunnels,
4355
4398
  drain: async () => {
@@ -4366,7 +4409,9 @@ function createConnectionLedger(limits, isLiveCapability2) {
4366
4409
  const authenticated = /* @__PURE__ */ new Map();
4367
4410
  let tunnels = 0;
4368
4411
  const blind = /* @__PURE__ */ new Set();
4369
- let onNoBlindTunnels;
4412
+ const live = /* @__PURE__ */ new Set();
4413
+ let retiring = false;
4414
+ let onNoConnections;
4370
4415
  const leavePending = (socket) => {
4371
4416
  const deadline = pending.get(socket);
4372
4417
  if (deadline !== void 0) {
@@ -4398,20 +4443,19 @@ function createConnectionLedger(limits, isLiveCapability2) {
4398
4443
  refuse(socket, REFUSAL.requestTimeout);
4399
4444
  }, limits.headDeadlineMs)
4400
4445
  );
4446
+ live.add(socket);
4401
4447
  socket.once("close", () => {
4402
4448
  leavePending(socket);
4449
+ live.delete(socket);
4450
+ if (live.size === 0) {
4451
+ onNoConnections?.();
4452
+ }
4403
4453
  });
4404
4454
  },
4405
4455
  headReceived: leavePending,
4406
4456
  openTunnels: () => tunnels,
4407
4457
  retire: async () => {
4408
- for (const socket of pending.keys()) {
4409
- socket.destroy();
4410
- }
4411
- for (const deadline of pending.values()) {
4412
- clearTimeout(deadline);
4413
- }
4414
- pending.clear();
4458
+ retiring = true;
4415
4459
  for (const sockets of authenticated.values()) {
4416
4460
  for (const socket of sockets) {
4417
4461
  if (!blind.has(socket)) {
@@ -4419,12 +4463,13 @@ function createConnectionLedger(limits, isLiveCapability2) {
4419
4463
  }
4420
4464
  }
4421
4465
  }
4422
- if (blind.size > 0) {
4466
+ if (live.size > 0) {
4423
4467
  await new Promise((resolve) => {
4424
- onNoBlindTunnels = resolve;
4468
+ onNoConnections = resolve;
4425
4469
  });
4426
4470
  }
4427
4471
  },
4472
+ retiring: () => retiring,
4428
4473
  establish: (socket, capability, kind) => {
4429
4474
  if (tunnels >= limits.maxTunnels) {
4430
4475
  return false;
@@ -4439,9 +4484,6 @@ function createConnectionLedger(limits, isLiveCapability2) {
4439
4484
  socket.once("close", () => {
4440
4485
  tunnels -= 1;
4441
4486
  blind.delete(socket);
4442
- if (blind.size === 0) {
4443
- onNoBlindTunnels?.();
4444
- }
4445
4487
  sockets.delete(socket);
4446
4488
  if (sockets.size === 0 && authenticated.get(capability) === sockets) {
4447
4489
  authenticated.delete(capability);
@@ -4651,7 +4693,7 @@ var init_package = __esm({
4651
4693
  "package.json"() {
4652
4694
  package_default = {
4653
4695
  name: "claude-use",
4654
- version: "11.62.3",
4696
+ version: "11.63.0",
4655
4697
  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.",
4656
4698
  license: "MIT",
4657
4699
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -10179,7 +10221,8 @@ var init_replacement = __esm({
10179
10221
  // src/frontdoor/ensure.ts
10180
10222
  function ensureFrontDoor(params) {
10181
10223
  const { paths, ports } = params;
10182
- const deadline = ports.now() + FRONTDOOR_START_TIMEOUT_MS;
10224
+ const startedAt = ports.now();
10225
+ let deadline = startedAt + FRONTDOOR_START_TIMEOUT_MS;
10183
10226
  let spawned = false;
10184
10227
  let replaced = false;
10185
10228
  const distrusted = /* @__PURE__ */ new Set();
@@ -10219,6 +10262,19 @@ function ensureFrontDoor(params) {
10219
10262
  ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
10220
10263
  }
10221
10264
  };
10265
+ const handOverAndAwait = (supervisorPid, doorProtocol, reason, request4) => {
10266
+ recordReplacement(supervisorPid, doorProtocol, reason, "SIGUSR2");
10267
+ request4(supervisorPid);
10268
+ const waitEnds = ports.now() + FRONTDOOR_START_TIMEOUT_MS + FRONTDOOR_EXIT_GRACE_MS;
10269
+ deadline += FRONTDOOR_START_TIMEOUT_MS + FRONTDOOR_EXIT_GRACE_MS;
10270
+ while (ports.isRunning(supervisorPid) && readFrontDoorState(ports.fs, paths.frontdoorStateFile)?.supervisorPid === supervisorPid) {
10271
+ if (ports.now() >= waitEnds) {
10272
+ stopAndAwaitExit(supervisorPid, doorProtocol, reason, `the front door (pid ${String(supervisorPid)}) did not act on a request to hand its listeners over, and did not exit when asked to`);
10273
+ return;
10274
+ }
10275
+ ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
10276
+ }
10277
+ };
10222
10278
  for (; ; ) {
10223
10279
  const state = readFrontDoorState(ports.fs, paths.frontdoorStateFile);
10224
10280
  const supervisorPid = state?.supervisorPid;
@@ -10232,12 +10288,16 @@ function ensureFrontDoor(params) {
10232
10288
  const verdict = verifyWithRetry(state.port);
10233
10289
  const doorProtocol = state.protocol ?? 0;
10234
10290
  if (verdict.ok && !replaced && !spawned && (params.replace !== void 0 || doorProtocol < FRONT_DOOR_PROTOCOL)) {
10235
- stopAndAwaitExit(
10236
- supervisorPid,
10237
- doorProtocol,
10238
- params.replace ?? "protocol-older",
10239
- `the front door (pid ${String(supervisorPid)}, protocol ${String(doorProtocol)}; this launcher speaks protocol ${String(FRONT_DOOR_PROTOCOL)}) was asked to be replaced and did not exit`
10240
- );
10291
+ if (params.replace !== void 0 && doorProtocol >= FRONT_DOOR_HANDOVER_PROTOCOL && ports.requestHandover !== void 0 && ports.isFrontDoorSupervisor(supervisorPid)) {
10292
+ handOverAndAwait(supervisorPid, doorProtocol, params.replace, ports.requestHandover);
10293
+ } else {
10294
+ stopAndAwaitExit(
10295
+ supervisorPid,
10296
+ doorProtocol,
10297
+ params.replace ?? "protocol-older",
10298
+ `the front door (pid ${String(supervisorPid)}, protocol ${String(doorProtocol)}; this launcher speaks protocol ${String(FRONT_DOOR_PROTOCOL)}) was asked to be replaced and did not exit`
10299
+ );
10300
+ }
10241
10301
  replaced = true;
10242
10302
  continue;
10243
10303
  }
@@ -10289,7 +10349,7 @@ function ensureFrontDoor(params) {
10289
10349
  if (ports.now() >= deadline) {
10290
10350
  const lastError = state?.lastError;
10291
10351
  throw new FrontDoorStartError(
10292
- `the front door did not become ready within ${String(FRONTDOOR_START_TIMEOUT_MS)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (lastRejection === void 0 ? "" : ` (${lastRejection})`) + (busyDoor === void 0 ? "" : `. It was not replaced because ${String(busyDoor.sessions)} live session(s) are using it and would lose their connections; run \`agent-shim frontdoor restart\` to replace it deliberately`) + `. Daemon log: ${paths.frontdoorLogPath}`
10352
+ `the front door did not become ready within ${String(deadline - startedAt)}ms` + (lastError === void 0 ? "" : ` (last error: ${lastError})`) + (lastRejection === void 0 ? "" : ` (${lastRejection})`) + (busyDoor === void 0 ? "" : `. It was not replaced because ${String(busyDoor.sessions)} live session(s) are using it and would lose their connections; run \`agent-shim frontdoor restart\` to replace it deliberately`) + `. Daemon log: ${paths.frontdoorLogPath}`
10293
10353
  );
10294
10354
  }
10295
10355
  ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
@@ -11935,6 +11995,12 @@ function realEnsurePorts(paths, spawnDaemon) {
11935
11995
  killSupervisor: (pid) => {
11936
11996
  process.kill(pid, "SIGKILL");
11937
11997
  },
11998
+ // Windows has no user signals (Node refuses to send one), so a replacement there keeps the stop-and-start path.
11999
+ ...process.platform === "win32" ? {} : {
12000
+ requestHandover: (pid) => {
12001
+ process.kill(pid, "SIGUSR2");
12002
+ }
12003
+ },
11938
12004
  // Read fresh for each probe: a replacement supervisor may have regenerated an unparseable CA, and the probe must trust exactly what the serving door's leaf chains to.
11939
12005
  verifyListener: (port) => probeFrontDoorSync(port, import_node_fs13.default.readFileSync(paths.frontdoorCaCertFile, "utf8"))
11940
12006
  };
@@ -14749,7 +14815,7 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
14749
14815
  function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
14750
14816
  const plainAgent = new ExemptHttpAgent(ports);
14751
14817
  const tlsAgent = new ExemptTlsAgent(ports);
14752
- const listenOnce = async (port, onSocket) => await new Promise((resolve, reject) => {
14818
+ const listenOnce = async (target, onSocket) => await new Promise((resolve, reject) => {
14753
14819
  const accepted = /* @__PURE__ */ new Set();
14754
14820
  const server = net2.createServer((socket) => {
14755
14821
  accepted.add(socket);
@@ -14759,7 +14825,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
14759
14825
  onSocket(socket);
14760
14826
  });
14761
14827
  server.once("error", reject);
14762
- server.listen(port, "127.0.0.1", () => {
14828
+ const onListening = () => {
14763
14829
  const address = server.address();
14764
14830
  const bound = typeof address === "object" && address !== null ? address.port : 0;
14765
14831
  if (bound === 0) {
@@ -14768,6 +14834,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
14768
14834
  }
14769
14835
  resolve({
14770
14836
  port: bound,
14837
+ listening: server,
14771
14838
  // The listening socket is released by `close` at once; the connections already accepted are untouched and keep the server's `close` callback pending until they end.
14772
14839
  stopAccepting: () => {
14773
14840
  server.close();
@@ -14783,10 +14850,19 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
14783
14850
  });
14784
14851
  }
14785
14852
  });
14786
- });
14853
+ };
14854
+ if (typeof target === "number") {
14855
+ server.listen(target, "127.0.0.1", onListening);
14856
+ } else {
14857
+ server.listen(target, onListening);
14858
+ }
14787
14859
  });
14788
14860
  return {
14789
- listenLoopback: async (preferredPort, onSocket) => {
14861
+ listenLoopback: async (source, onSocket) => {
14862
+ if ("inherit" in source) {
14863
+ return await listenOnce(await source.inherit(), onSocket);
14864
+ }
14865
+ const { preferredPort } = source;
14790
14866
  if (preferredPort !== void 0) {
14791
14867
  try {
14792
14868
  return await listenOnce(preferredPort, onSocket);