claude-use 11.62.3 → 11.64.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 +2215 -1051
- package/dist/index.cjs +134 -47
- package/dist/index.mjs +134 -47
- package/dist/types/index.d.ts +1395 -39
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -328,7 +328,7 @@ var init_statusline = __esm({
|
|
|
328
328
|
init_graphemes();
|
|
329
329
|
init_languages();
|
|
330
330
|
STATUSLINE_HEADER_SEGMENTS = ["model", "provider", "route", "account", "identity", "headroom", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "dailyCost", "sessionName", "duration", "speed"];
|
|
331
|
-
STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment", "sessionTime", "promptCache", "compactions", "tokens"];
|
|
331
|
+
STATUSLINE_ROWS = ["context", "quota", "addedDirs", "gitFiles", "memory", "environment", "sessionTime", "promptCache", "compactions", "tokens", "tools", "skills", "mcp", "agents", "todos"];
|
|
332
332
|
STATUSLINE_SESSION_TIME_PARTS = ["started", "lastReply"];
|
|
333
333
|
PROMPT_CACHE_TTL_SECONDS = { fiveMinutes: 300, oneHour: 3600 };
|
|
334
334
|
STATUSLINE_COLOUR_NAMES = [
|
|
@@ -359,13 +359,13 @@ var init_statusline = __esm({
|
|
|
359
359
|
PRESET_BUNDLES = {
|
|
360
360
|
standard: { layout: { header: DEFAULT_HEADER_SEGMENTS, rows: DEFAULT_ROWS }, git: GIT_WITH_DIRTY_MARKER, jj: JJ_OFF, usage: { resetLabel: false }, context: { breakdown: "never" } },
|
|
361
361
|
full: {
|
|
362
|
-
layout: { header: ["model", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "sessionName", "duration"], rows: ["context", "quota", "addedDirs", "memory", "environment", "promptCache", "compactions", "tokens"] },
|
|
362
|
+
layout: { header: ["model", "project", "vcs", "effort", "advisor", "version", "outputStyle", "cost", "sessionName", "duration"], rows: ["context", "quota", "addedDirs", "memory", "environment", "tools", "skills", "mcp", "agents", "todos", "promptCache", "compactions", "tokens"] },
|
|
363
363
|
git: GIT_WITH_DIRTY_MARKER,
|
|
364
364
|
jj: { enabled: true, showDirty: true, showConflicts: true },
|
|
365
365
|
usage: { resetLabel: true },
|
|
366
366
|
context: { breakdown: "critical" }
|
|
367
367
|
},
|
|
368
|
-
essential: { layout: { header: ["model", "project", "vcs", "duration"], rows: ["context", "addedDirs"] }, git: GIT_WITH_DIRTY_MARKER, jj: JJ_OFF, usage: { resetLabel: true }, context: { breakdown: "never" } },
|
|
368
|
+
essential: { layout: { header: ["model", "project", "vcs", "duration"], rows: ["context", "addedDirs", "tools", "agents", "todos"] }, git: GIT_WITH_DIRTY_MARKER, jj: JJ_OFF, usage: { resetLabel: true }, context: { breakdown: "never" } },
|
|
369
369
|
minimal: { layout: { header: ["model", "project", "vcs"], rows: ["context", "addedDirs"] }, git: GIT_WITH_DIRTY_MARKER, jj: JJ_OFF, usage: { resetLabel: true }, context: { breakdown: "never" } }
|
|
370
370
|
};
|
|
371
371
|
STATUSLINE_PATH_LEVELS = ["1", "2", "3", "full"];
|
|
@@ -481,6 +481,10 @@ var init_statusline = __esm({
|
|
|
481
481
|
promptCache: {
|
|
482
482
|
ttlSeconds: import_zod2.z.number().int().min(1).describe("How long the prompt cache lives, in seconds, when the transcript has not yet shown which tier the session writes (five minutes or one hour); the tier the transcript shows takes over once it does.")
|
|
483
483
|
},
|
|
484
|
+
tools: {
|
|
485
|
+
nameMaxLength: import_zod2.z.number().int().min(0).describe("The most terminal columns of a tool's name the tools row draws, cut with an ellipsis. With a limit set, a tool of an MCP server is shown by its own name, without the server's, whether or not it needs cutting. 0 draws every name whole, an MCP tool's with its server."),
|
|
486
|
+
maxVisible: import_zod2.z.number().int().min(0).describe("The most kinds of finished tool call the tools row names, the most-used first, with the rest counted as +N more. 0 names every kind.")
|
|
487
|
+
},
|
|
484
488
|
colours: {
|
|
485
489
|
context: colourValue.describe("The colour of the context bar and its figures below the warning threshold."),
|
|
486
490
|
usage: colourValue.describe("The colour of the quota bars and their figures below the warning threshold."),
|
|
@@ -492,7 +496,9 @@ var init_statusline = __esm({
|
|
|
492
496
|
empty: colourValue.describe("The colour of the unused part of a bar."),
|
|
493
497
|
project: colourValue.describe("The colour of the project path segment."),
|
|
494
498
|
git: colourValue.describe("The colour of the version control segment's wrapper text (`git:(` and `)`)."),
|
|
495
|
-
gitBranch: colourValue.describe("The colour of the branch or bookmark and its ahead, behind and dirty markers.")
|
|
499
|
+
gitBranch: colourValue.describe("The colour of the branch or bookmark and its ahead, behind and dirty markers."),
|
|
500
|
+
activity: colourValue.describe("The colour of the names of the tools, skills and MCP servers the tools, skills and mcp rows draw. Their running markers take colours.warning and their finished markers colours.context."),
|
|
501
|
+
agent: colourValue.describe("The colour of an agent's type in the agents row.")
|
|
496
502
|
},
|
|
497
503
|
project: {
|
|
498
504
|
pathLevels: import_zod2.z.enum(STATUSLINE_PATH_LEVELS).describe("How many trailing directories of the working directory the project segment shows: 1, 2 or 3, or full for the whole absolute path."),
|
|
@@ -519,7 +525,7 @@ var init_statusline = __esm({
|
|
|
519
525
|
LANGUAGE_ALIASES = { zh: "zh-Hans", "zh-TW": "zh-Hant" };
|
|
520
526
|
TOP_LEVEL = {
|
|
521
527
|
language: import_zod2.z.enum(STATUSLINE_LANGUAGES).describe(LANGUAGE_DESCRIPTION),
|
|
522
|
-
preset: import_zod2.z.enum(STATUSLINE_PRESETS).describe("A named bundle of settings (layout.header, layout.rows, git.enabled, git.showDirty, git.showAheadBehind, git.showLineDiff, jj.enabled, jj.showDirty, jj.showConflicts, usage.resetLabel and context.breakdown) that this layer sets beneath the keys it names itself and above everything the shallower layers set: standard is the statusline's own; full, essential and minimal are claude-hud's presets. Each draws the model, project and version control segments and the context row; full adds the effort, advisor, version, output style, cost, session name and duration segments and the quota, added directories, memory, environment, prompt cache, compactions and session tokens rows, with the token breakdown at high use, essential adds the duration
|
|
528
|
+
preset: import_zod2.z.enum(STATUSLINE_PRESETS).describe("A named bundle of settings (layout.header, layout.rows, git.enabled, git.showDirty, git.showAheadBehind, git.showLineDiff, jj.enabled, jj.showDirty, jj.showConflicts, usage.resetLabel and context.breakdown) that this layer sets beneath the keys it names itself and above everything the shallower layers set: standard is the statusline's own; full, essential and minimal are claude-hud's presets. Each draws the model, project and version control segments and the context row; full adds the effort, advisor, version, output style, cost, session name and duration segments and the quota, added directories, memory, environment, tools, skills, mcp, agents, todos, prompt cache, compactions and session tokens rows, with the token breakdown at high use, essential adds the duration, the added directories row and the tools, agents and todos rows, and minimal adds the added directories row alone.")
|
|
523
529
|
};
|
|
524
530
|
StatuslineSchema = import_zod2.z.strictObject({
|
|
525
531
|
language: import_zod2.z.enum(LANGUAGE_TAGS).transform(canonicalLanguage).describe(LANGUAGE_DESCRIPTION).optional(),
|
|
@@ -540,6 +546,7 @@ var init_statusline = __esm({
|
|
|
540
546
|
environment: import_zod2.z.strictObject(SHAPES.environment).partial().optional(),
|
|
541
547
|
sessionTime: import_zod2.z.strictObject(SHAPES.sessionTime).partial().optional(),
|
|
542
548
|
promptCache: import_zod2.z.strictObject(SHAPES.promptCache).partial().optional(),
|
|
549
|
+
tools: import_zod2.z.strictObject(SHAPES.tools).partial().optional(),
|
|
543
550
|
colours: import_zod2.z.strictObject(SHAPES.colours).partial().optional(),
|
|
544
551
|
project: import_zod2.z.strictObject(SHAPES.project).partial().optional(),
|
|
545
552
|
git: import_zod2.z.strictObject(SHAPES.git).partial().optional(),
|
|
@@ -564,6 +571,7 @@ var init_statusline = __esm({
|
|
|
564
571
|
environment: import_zod2.z.strictObject(SHAPES.environment),
|
|
565
572
|
sessionTime: import_zod2.z.strictObject(SHAPES.sessionTime),
|
|
566
573
|
promptCache: import_zod2.z.strictObject(SHAPES.promptCache),
|
|
574
|
+
tools: import_zod2.z.strictObject(SHAPES.tools),
|
|
567
575
|
colours: import_zod2.z.strictObject(SHAPES.colours),
|
|
568
576
|
project: import_zod2.z.strictObject(SHAPES.project),
|
|
569
577
|
git: import_zod2.z.strictObject(SHAPES.git),
|
|
@@ -588,6 +596,7 @@ var init_statusline = __esm({
|
|
|
588
596
|
environment: { threshold: 0 },
|
|
589
597
|
sessionTime: { parts: [...STATUSLINE_SESSION_TIME_PARTS] },
|
|
590
598
|
promptCache: { ttlSeconds: PROMPT_CACHE_TTL_SECONDS.fiveMinutes },
|
|
599
|
+
tools: { nameMaxLength: 0, maxVisible: 4 },
|
|
591
600
|
colours: {
|
|
592
601
|
context: "green",
|
|
593
602
|
usage: "green",
|
|
@@ -599,7 +608,9 @@ var init_statusline = __esm({
|
|
|
599
608
|
empty: "brightBlack",
|
|
600
609
|
project: "yellow",
|
|
601
610
|
git: "magenta",
|
|
602
|
-
gitBranch: "cyan"
|
|
611
|
+
gitBranch: "cyan",
|
|
612
|
+
activity: "cyan",
|
|
613
|
+
agent: "magenta"
|
|
603
614
|
},
|
|
604
615
|
project: { pathLevels: "1", addedDirsLayout: "inline" },
|
|
605
616
|
git: { enabled: true, showDirty: true, showAheadBehind: false, showLineDiff: false, branchOverflow: "truncate", pushWarnAt: 0, pushCriticalAt: 0 },
|
|
@@ -3923,14 +3934,15 @@ function pruneDeadFrontDoorSessions(fs14, sessionsDir, listed, isRunning) {
|
|
|
3923
3934
|
}
|
|
3924
3935
|
return removed;
|
|
3925
3936
|
}
|
|
3926
|
-
var import_node_path9, import_zod5, FRONT_DOOR_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
|
|
3937
|
+
var import_node_path9, import_zod5, FRONT_DOOR_PROTOCOL, FRONT_DOOR_HANDOVER_PROTOCOL, FrontDoorSessionSchema, FrontDoorStateSchema, MAX_TCP_PORT, FrontDoorDirectRecordSchema, RECORD_TEMPORARY_FILE;
|
|
3927
3938
|
var init_state = __esm({
|
|
3928
3939
|
"src/frontdoor/state.ts"() {
|
|
3929
3940
|
"use strict";
|
|
3930
3941
|
import_node_path9 = __toESM(require("node:path"), 1);
|
|
3931
3942
|
import_zod5 = require("zod");
|
|
3932
3943
|
init_schema();
|
|
3933
|
-
FRONT_DOOR_PROTOCOL =
|
|
3944
|
+
FRONT_DOOR_PROTOCOL = 6;
|
|
3945
|
+
FRONT_DOOR_HANDOVER_PROTOCOL = 6;
|
|
3934
3946
|
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
3947
|
FrontDoorStateSchema = import_zod5.z.strictObject({
|
|
3936
3948
|
/**
|
|
@@ -4026,18 +4038,24 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
|
|
|
4026
4038
|
...lastConnectPort === void 0 ? {} : { lastConnectPort },
|
|
4027
4039
|
...lastDirectPort === void 0 ? {} : { lastDirectPort }
|
|
4028
4040
|
});
|
|
4041
|
+
const { predecessor } = ports;
|
|
4042
|
+
const sourceOf = (listener, preferredPort) => predecessor === void 0 ? { preferredPort } : { inherit: async () => await predecessor.take(listener) };
|
|
4029
4043
|
const fail = (message) => {
|
|
4030
4044
|
ports.closeRcStreamHub();
|
|
4031
|
-
|
|
4032
|
-
|
|
4045
|
+
if (predecessor === void 0) {
|
|
4046
|
+
writeFrontDoorState(fs14, paths.frontdoorStateFile, { lastError: message, ...sticky() });
|
|
4047
|
+
fs14.removeRecursive(paths.frontdoorLockFile);
|
|
4048
|
+
}
|
|
4033
4049
|
ports.log(`agent-shim frontdoor supervisor: ${message}`);
|
|
4034
4050
|
return 1;
|
|
4035
4051
|
};
|
|
4036
|
-
|
|
4052
|
+
if (predecessor === void 0) {
|
|
4053
|
+
writeFrontDoorState(fs14, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
|
|
4054
|
+
}
|
|
4037
4055
|
const previousSticky = lastPort;
|
|
4038
4056
|
let http3;
|
|
4039
4057
|
try {
|
|
4040
|
-
http3 = await ports.startProviderListener(lastPort);
|
|
4058
|
+
http3 = await ports.startProviderListener(sourceOf("provider", lastPort));
|
|
4041
4059
|
} catch (error) {
|
|
4042
4060
|
ports.doorHealth.listenerFailed("provider", error instanceof Error ? error.message : String(error));
|
|
4043
4061
|
return fail(`could not start the provider listener: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -4049,7 +4067,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
|
|
|
4049
4067
|
const previousStickyConnect = lastConnectPort;
|
|
4050
4068
|
let connect3;
|
|
4051
4069
|
try {
|
|
4052
|
-
connect3 = await ports.startConnectListener(lastConnectPort);
|
|
4070
|
+
connect3 = await ports.startConnectListener(sourceOf("connect", lastConnectPort));
|
|
4053
4071
|
} catch (error) {
|
|
4054
4072
|
await http3.close();
|
|
4055
4073
|
ports.doorHealth.listenerFailed("connect", error instanceof Error ? error.message : String(error));
|
|
@@ -4062,7 +4080,7 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
|
|
|
4062
4080
|
const previousStickyDirect = lastDirectPort;
|
|
4063
4081
|
let direct;
|
|
4064
4082
|
try {
|
|
4065
|
-
direct = await ports.startDirectListener(lastDirectPort);
|
|
4083
|
+
direct = await ports.startDirectListener(sourceOf("direct", lastDirectPort));
|
|
4066
4084
|
} catch (error) {
|
|
4067
4085
|
await connect3.close();
|
|
4068
4086
|
await http3.close();
|
|
@@ -4076,8 +4094,12 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
|
|
|
4076
4094
|
writeFrontDoorDirectRecord(fs14, paths.frontdoorDirectRecordsDir, { pid: ports.ownPid, directPort: direct.port });
|
|
4077
4095
|
writeFrontDoorState(fs14, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
|
|
4078
4096
|
ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
|
|
4079
|
-
|
|
4080
|
-
|
|
4097
|
+
if (predecessor === void 0) {
|
|
4098
|
+
fs14.removeRecursive(paths.frontdoorLockFile);
|
|
4099
|
+
} else {
|
|
4100
|
+
predecessor.serving();
|
|
4101
|
+
}
|
|
4102
|
+
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
4103
|
const watchdog = ports.startWatchdog?.();
|
|
4082
4104
|
let idleSince;
|
|
4083
4105
|
let ticks = 0;
|
|
@@ -4097,14 +4119,16 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
|
|
|
4097
4119
|
resolve();
|
|
4098
4120
|
};
|
|
4099
4121
|
ports.retire?.addEventListener("abort", wake, { once: true });
|
|
4122
|
+
ports.handover?.requested.addEventListener("abort", wake, { once: true });
|
|
4100
4123
|
void ports.sleep(FRONTDOOR_POLL_MS).then(() => {
|
|
4101
4124
|
ports.retire?.removeEventListener("abort", wake);
|
|
4125
|
+
ports.handover?.requested.removeEventListener("abort", wake);
|
|
4102
4126
|
resolve();
|
|
4103
4127
|
});
|
|
4104
4128
|
});
|
|
4105
4129
|
};
|
|
4106
4130
|
const retireByDrain = async () => {
|
|
4107
|
-
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}:
|
|
4131
|
+
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: releasing the front door's addresses and finishing the connections it carries`);
|
|
4108
4132
|
watchdog?.stop();
|
|
4109
4133
|
ports.stopBackgroundWork?.();
|
|
4110
4134
|
const drained = [direct.drain(), connect3.drain(), http3.drain()];
|
|
@@ -4119,6 +4143,17 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
|
|
|
4119
4143
|
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: the connections this door carried have ended; exiting`);
|
|
4120
4144
|
return 0;
|
|
4121
4145
|
};
|
|
4146
|
+
const handOverThenDrain = async (run) => {
|
|
4147
|
+
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`);
|
|
4148
|
+
const outcome = await run({ provider: http3.listening, connect: connect3.listening, direct: direct.listening });
|
|
4149
|
+
if (outcome.ok) {
|
|
4150
|
+
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: successor ${String(outcome.successorPid)} serves the front door's listeners`);
|
|
4151
|
+
ports.doorHealth.superseded(outcome.successorPid);
|
|
4152
|
+
} else {
|
|
4153
|
+
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`);
|
|
4154
|
+
}
|
|
4155
|
+
return await retireByDrain();
|
|
4156
|
+
};
|
|
4122
4157
|
const closeServing = async () => {
|
|
4123
4158
|
watchdog?.stop();
|
|
4124
4159
|
await direct.close();
|
|
@@ -4136,8 +4171,12 @@ async function serveFrontDoor(idleShutdownMinutes, ports, options) {
|
|
|
4136
4171
|
};
|
|
4137
4172
|
for (; ; ) {
|
|
4138
4173
|
if (ports.retire?.aborted === true) {
|
|
4174
|
+
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: asked to exit`);
|
|
4139
4175
|
return await retireByDrain();
|
|
4140
4176
|
}
|
|
4177
|
+
if (ports.handover?.requested.aborted === true && supersededBy === void 0) {
|
|
4178
|
+
return await handOverThenDrain(ports.handover.run);
|
|
4179
|
+
}
|
|
4141
4180
|
if (options.tickLimit !== void 0 && ticks >= options.tickLimit) {
|
|
4142
4181
|
watchdog?.stop();
|
|
4143
4182
|
return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
|
|
@@ -4274,8 +4313,10 @@ function caParses(ca) {
|
|
|
4274
4313
|
return false;
|
|
4275
4314
|
}
|
|
4276
4315
|
}
|
|
4277
|
-
async function startConnectServer(config, effects,
|
|
4316
|
+
async function startConnectServer(config, effects, source) {
|
|
4278
4317
|
const tunnelTokens = /* @__PURE__ */ new WeakMap();
|
|
4318
|
+
const ledger = createConnectionLedger(config.limits, config.isLiveCapability);
|
|
4319
|
+
const lateSessionDeadlines = /* @__PURE__ */ new WeakMap();
|
|
4279
4320
|
const onUpgrade = (host) => (request4, socket, head) => {
|
|
4280
4321
|
config.capture?.upgrade(request4);
|
|
4281
4322
|
if (head.length > 0) {
|
|
@@ -4297,6 +4338,12 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
4297
4338
|
return { host, serveSecure: serveSecure2, tlsAcceptor: tlsAcceptor2 };
|
|
4298
4339
|
}
|
|
4299
4340
|
const handleHostRequest = async (request4, response) => {
|
|
4341
|
+
if (ledger.retiring()) {
|
|
4342
|
+
clearTimeout(lateSessionDeadlines.get(request4.socket));
|
|
4343
|
+
response.once("close", () => {
|
|
4344
|
+
request4.socket.end();
|
|
4345
|
+
});
|
|
4346
|
+
}
|
|
4300
4347
|
if (config.localSurface !== void 0 && await config.localSurface.serve(host, request4, response)) {
|
|
4301
4348
|
return;
|
|
4302
4349
|
}
|
|
@@ -4316,13 +4363,19 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
4316
4363
|
const httpSession = effects.createHttpSession(handler, onUpgrade(host));
|
|
4317
4364
|
const serveSecure = (secure, capability) => {
|
|
4318
4365
|
tunnelTokens.set(secure, capability);
|
|
4366
|
+
if (ledger.retiring()) {
|
|
4367
|
+
const deadline = setTimeout(() => {
|
|
4368
|
+
secure.destroy();
|
|
4369
|
+
}, config.limits.headDeadlineMs);
|
|
4370
|
+
deadline.unref();
|
|
4371
|
+
lateSessionDeadlines.set(secure, deadline);
|
|
4372
|
+
}
|
|
4319
4373
|
httpSession.serve(secure);
|
|
4320
4374
|
};
|
|
4321
4375
|
const tlsAcceptor = effects.createTlsAcceptor(config.leafFor(host), serveSecure);
|
|
4322
4376
|
return { host, serveSecure, httpSession, tlsAcceptor };
|
|
4323
4377
|
});
|
|
4324
|
-
const
|
|
4325
|
-
const listener = await effects.listenLoopback(preferredPort, (socket) => {
|
|
4378
|
+
const listener = await effects.listenLoopback(source, (socket) => {
|
|
4326
4379
|
handleConnect(socket, { config, effects, sessions, ledger });
|
|
4327
4380
|
});
|
|
4328
4381
|
const apiSession = sessions.find((session) => session.host === config.routedHost);
|
|
@@ -4335,7 +4388,7 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
4335
4388
|
}
|
|
4336
4389
|
session.serveSecure(secure, config.transparentCapability ?? "");
|
|
4337
4390
|
});
|
|
4338
|
-
const transparent = config.transparentPort === void 0 || apiSession === void 0 ? void 0 : await effects.listenLoopback(config.transparentPort, (socket) => {
|
|
4391
|
+
const transparent = config.transparentPort === void 0 || apiSession === void 0 ? void 0 : await effects.listenLoopback({ preferredPort: config.transparentPort }, (socket) => {
|
|
4339
4392
|
sniAcceptor.accept(socket);
|
|
4340
4393
|
});
|
|
4341
4394
|
const closeSurface = async () => {
|
|
@@ -4350,6 +4403,7 @@ ${request4.rawHeaders.reduce((accumulated, value, index) => index % 2 === 0 ? `$
|
|
|
4350
4403
|
};
|
|
4351
4404
|
return {
|
|
4352
4405
|
port: listener.port,
|
|
4406
|
+
listening: listener.listening,
|
|
4353
4407
|
...transparent === void 0 ? {} : { transparentPort: transparent.port },
|
|
4354
4408
|
openTunnels: ledger.openTunnels,
|
|
4355
4409
|
drain: async () => {
|
|
@@ -4366,7 +4420,9 @@ function createConnectionLedger(limits, isLiveCapability2) {
|
|
|
4366
4420
|
const authenticated = /* @__PURE__ */ new Map();
|
|
4367
4421
|
let tunnels = 0;
|
|
4368
4422
|
const blind = /* @__PURE__ */ new Set();
|
|
4369
|
-
|
|
4423
|
+
const live = /* @__PURE__ */ new Set();
|
|
4424
|
+
let retiring = false;
|
|
4425
|
+
let onNoConnections;
|
|
4370
4426
|
const leavePending = (socket) => {
|
|
4371
4427
|
const deadline = pending.get(socket);
|
|
4372
4428
|
if (deadline !== void 0) {
|
|
@@ -4398,20 +4454,19 @@ function createConnectionLedger(limits, isLiveCapability2) {
|
|
|
4398
4454
|
refuse(socket, REFUSAL.requestTimeout);
|
|
4399
4455
|
}, limits.headDeadlineMs)
|
|
4400
4456
|
);
|
|
4457
|
+
live.add(socket);
|
|
4401
4458
|
socket.once("close", () => {
|
|
4402
4459
|
leavePending(socket);
|
|
4460
|
+
live.delete(socket);
|
|
4461
|
+
if (live.size === 0) {
|
|
4462
|
+
onNoConnections?.();
|
|
4463
|
+
}
|
|
4403
4464
|
});
|
|
4404
4465
|
},
|
|
4405
4466
|
headReceived: leavePending,
|
|
4406
4467
|
openTunnels: () => tunnels,
|
|
4407
4468
|
retire: async () => {
|
|
4408
|
-
|
|
4409
|
-
socket.destroy();
|
|
4410
|
-
}
|
|
4411
|
-
for (const deadline of pending.values()) {
|
|
4412
|
-
clearTimeout(deadline);
|
|
4413
|
-
}
|
|
4414
|
-
pending.clear();
|
|
4469
|
+
retiring = true;
|
|
4415
4470
|
for (const sockets of authenticated.values()) {
|
|
4416
4471
|
for (const socket of sockets) {
|
|
4417
4472
|
if (!blind.has(socket)) {
|
|
@@ -4419,12 +4474,13 @@ function createConnectionLedger(limits, isLiveCapability2) {
|
|
|
4419
4474
|
}
|
|
4420
4475
|
}
|
|
4421
4476
|
}
|
|
4422
|
-
if (
|
|
4477
|
+
if (live.size > 0) {
|
|
4423
4478
|
await new Promise((resolve) => {
|
|
4424
|
-
|
|
4479
|
+
onNoConnections = resolve;
|
|
4425
4480
|
});
|
|
4426
4481
|
}
|
|
4427
4482
|
},
|
|
4483
|
+
retiring: () => retiring,
|
|
4428
4484
|
establish: (socket, capability, kind) => {
|
|
4429
4485
|
if (tunnels >= limits.maxTunnels) {
|
|
4430
4486
|
return false;
|
|
@@ -4439,9 +4495,6 @@ function createConnectionLedger(limits, isLiveCapability2) {
|
|
|
4439
4495
|
socket.once("close", () => {
|
|
4440
4496
|
tunnels -= 1;
|
|
4441
4497
|
blind.delete(socket);
|
|
4442
|
-
if (blind.size === 0) {
|
|
4443
|
-
onNoBlindTunnels?.();
|
|
4444
|
-
}
|
|
4445
4498
|
sockets.delete(socket);
|
|
4446
4499
|
if (sockets.size === 0 && authenticated.get(capability) === sockets) {
|
|
4447
4500
|
authenticated.delete(capability);
|
|
@@ -4651,7 +4704,7 @@ var init_package = __esm({
|
|
|
4651
4704
|
"package.json"() {
|
|
4652
4705
|
package_default = {
|
|
4653
4706
|
name: "claude-use",
|
|
4654
|
-
version: "11.
|
|
4707
|
+
version: "11.64.0",
|
|
4655
4708
|
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
4709
|
license: "MIT",
|
|
4657
4710
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -10179,7 +10232,8 @@ var init_replacement = __esm({
|
|
|
10179
10232
|
// src/frontdoor/ensure.ts
|
|
10180
10233
|
function ensureFrontDoor(params) {
|
|
10181
10234
|
const { paths, ports } = params;
|
|
10182
|
-
const
|
|
10235
|
+
const startedAt = ports.now();
|
|
10236
|
+
let deadline = startedAt + FRONTDOOR_START_TIMEOUT_MS;
|
|
10183
10237
|
let spawned = false;
|
|
10184
10238
|
let replaced = false;
|
|
10185
10239
|
const distrusted = /* @__PURE__ */ new Set();
|
|
@@ -10219,6 +10273,19 @@ function ensureFrontDoor(params) {
|
|
|
10219
10273
|
ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
|
|
10220
10274
|
}
|
|
10221
10275
|
};
|
|
10276
|
+
const handOverAndAwait = (supervisorPid, doorProtocol, reason, request4) => {
|
|
10277
|
+
recordReplacement(supervisorPid, doorProtocol, reason, "SIGUSR2");
|
|
10278
|
+
request4(supervisorPid);
|
|
10279
|
+
const waitEnds = ports.now() + FRONTDOOR_START_TIMEOUT_MS + FRONTDOOR_EXIT_GRACE_MS;
|
|
10280
|
+
deadline += FRONTDOOR_START_TIMEOUT_MS + FRONTDOOR_EXIT_GRACE_MS;
|
|
10281
|
+
while (ports.isRunning(supervisorPid) && readFrontDoorState(ports.fs, paths.frontdoorStateFile)?.supervisorPid === supervisorPid) {
|
|
10282
|
+
if (ports.now() >= waitEnds) {
|
|
10283
|
+
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`);
|
|
10284
|
+
return;
|
|
10285
|
+
}
|
|
10286
|
+
ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
|
|
10287
|
+
}
|
|
10288
|
+
};
|
|
10222
10289
|
for (; ; ) {
|
|
10223
10290
|
const state = readFrontDoorState(ports.fs, paths.frontdoorStateFile);
|
|
10224
10291
|
const supervisorPid = state?.supervisorPid;
|
|
@@ -10232,12 +10299,16 @@ function ensureFrontDoor(params) {
|
|
|
10232
10299
|
const verdict = verifyWithRetry(state.port);
|
|
10233
10300
|
const doorProtocol = state.protocol ?? 0;
|
|
10234
10301
|
if (verdict.ok && !replaced && !spawned && (params.replace !== void 0 || doorProtocol < FRONT_DOOR_PROTOCOL)) {
|
|
10235
|
-
|
|
10236
|
-
supervisorPid,
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10302
|
+
if (params.replace !== void 0 && doorProtocol >= FRONT_DOOR_HANDOVER_PROTOCOL && ports.requestHandover !== void 0 && ports.isFrontDoorSupervisor(supervisorPid)) {
|
|
10303
|
+
handOverAndAwait(supervisorPid, doorProtocol, params.replace, ports.requestHandover);
|
|
10304
|
+
} else {
|
|
10305
|
+
stopAndAwaitExit(
|
|
10306
|
+
supervisorPid,
|
|
10307
|
+
doorProtocol,
|
|
10308
|
+
params.replace ?? "protocol-older",
|
|
10309
|
+
`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`
|
|
10310
|
+
);
|
|
10311
|
+
}
|
|
10241
10312
|
replaced = true;
|
|
10242
10313
|
continue;
|
|
10243
10314
|
}
|
|
@@ -10289,7 +10360,7 @@ function ensureFrontDoor(params) {
|
|
|
10289
10360
|
if (ports.now() >= deadline) {
|
|
10290
10361
|
const lastError = state?.lastError;
|
|
10291
10362
|
throw new FrontDoorStartError(
|
|
10292
|
-
`the front door did not become ready within ${String(
|
|
10363
|
+
`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
10364
|
);
|
|
10294
10365
|
}
|
|
10295
10366
|
ports.sleep(FRONTDOOR_LAUNCHER_POLL_MS);
|
|
@@ -11935,6 +12006,12 @@ function realEnsurePorts(paths, spawnDaemon) {
|
|
|
11935
12006
|
killSupervisor: (pid) => {
|
|
11936
12007
|
process.kill(pid, "SIGKILL");
|
|
11937
12008
|
},
|
|
12009
|
+
// Windows has no user signals (Node refuses to send one), so a replacement there keeps the stop-and-start path.
|
|
12010
|
+
...process.platform === "win32" ? {} : {
|
|
12011
|
+
requestHandover: (pid) => {
|
|
12012
|
+
process.kill(pid, "SIGUSR2");
|
|
12013
|
+
}
|
|
12014
|
+
},
|
|
11938
12015
|
// 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
12016
|
verifyListener: (port) => probeFrontDoorSync(port, import_node_fs13.default.readFileSync(paths.frontdoorCaCertFile, "utf8"))
|
|
11940
12017
|
};
|
|
@@ -14749,7 +14826,7 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
14749
14826
|
function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
14750
14827
|
const plainAgent = new ExemptHttpAgent(ports);
|
|
14751
14828
|
const tlsAgent = new ExemptTlsAgent(ports);
|
|
14752
|
-
const listenOnce = async (
|
|
14829
|
+
const listenOnce = async (target, onSocket) => await new Promise((resolve, reject) => {
|
|
14753
14830
|
const accepted = /* @__PURE__ */ new Set();
|
|
14754
14831
|
const server = net2.createServer((socket) => {
|
|
14755
14832
|
accepted.add(socket);
|
|
@@ -14759,7 +14836,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
|
14759
14836
|
onSocket(socket);
|
|
14760
14837
|
});
|
|
14761
14838
|
server.once("error", reject);
|
|
14762
|
-
|
|
14839
|
+
const onListening = () => {
|
|
14763
14840
|
const address = server.address();
|
|
14764
14841
|
const bound = typeof address === "object" && address !== null ? address.port : 0;
|
|
14765
14842
|
if (bound === 0) {
|
|
@@ -14768,6 +14845,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
|
14768
14845
|
}
|
|
14769
14846
|
resolve({
|
|
14770
14847
|
port: bound,
|
|
14848
|
+
listening: server,
|
|
14771
14849
|
// 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
14850
|
stopAccepting: () => {
|
|
14773
14851
|
server.close();
|
|
@@ -14783,10 +14861,19 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
|
14783
14861
|
});
|
|
14784
14862
|
}
|
|
14785
14863
|
});
|
|
14786
|
-
}
|
|
14864
|
+
};
|
|
14865
|
+
if (typeof target === "number") {
|
|
14866
|
+
server.listen(target, "127.0.0.1", onListening);
|
|
14867
|
+
} else {
|
|
14868
|
+
server.listen(target, onListening);
|
|
14869
|
+
}
|
|
14787
14870
|
});
|
|
14788
14871
|
return {
|
|
14789
|
-
listenLoopback: async (
|
|
14872
|
+
listenLoopback: async (source, onSocket) => {
|
|
14873
|
+
if ("inherit" in source) {
|
|
14874
|
+
return await listenOnce(await source.inherit(), onSocket);
|
|
14875
|
+
}
|
|
14876
|
+
const { preferredPort } = source;
|
|
14790
14877
|
if (preferredPort !== void 0) {
|
|
14791
14878
|
try {
|
|
14792
14879
|
return await listenOnce(preferredPort, onSocket);
|