claude-use 9.7.1 → 9.8.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 +427 -370
- package/dist/index.cjs +120 -77
- package/dist/index.mjs +116 -73
- package/dist/types/index.d.ts +7 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2663,7 +2663,7 @@ var init_package = __esm({
|
|
|
2663
2663
|
"package.json"() {
|
|
2664
2664
|
package_default = {
|
|
2665
2665
|
name: "claude-use",
|
|
2666
|
-
version: "9.
|
|
2666
|
+
version: "9.8.0",
|
|
2667
2667
|
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.",
|
|
2668
2668
|
license: "MIT",
|
|
2669
2669
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -6567,7 +6567,7 @@ function buildEnv(params) {
|
|
|
6567
6567
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
6568
6568
|
let providerCustomHeaders;
|
|
6569
6569
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
6570
|
-
env.CLAUDE_CONFIG_DIR =
|
|
6570
|
+
env.CLAUDE_CONFIG_DIR = import_node_path33.default.join(params.identitiesDir, params.resolvedIdentityName);
|
|
6571
6571
|
}
|
|
6572
6572
|
if (params.provider !== void 0) {
|
|
6573
6573
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -6611,11 +6611,11 @@ function buildEnv(params) {
|
|
|
6611
6611
|
}
|
|
6612
6612
|
return env;
|
|
6613
6613
|
}
|
|
6614
|
-
var
|
|
6614
|
+
var import_node_path33, LOOPBACK_HOSTS;
|
|
6615
6615
|
var init_flags = __esm({
|
|
6616
6616
|
"src/launcher/flags.ts"() {
|
|
6617
6617
|
"use strict";
|
|
6618
|
-
|
|
6618
|
+
import_node_path33 = __toESM(require("node:path"), 1);
|
|
6619
6619
|
init_envBool();
|
|
6620
6620
|
init_credential();
|
|
6621
6621
|
init_headers();
|
|
@@ -6938,7 +6938,7 @@ function decideLaunch(params, readOnly) {
|
|
|
6938
6938
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
6939
6939
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
6940
6940
|
});
|
|
6941
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
6941
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path34.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
6942
6942
|
log.error(
|
|
6943
6943
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
6944
6944
|
);
|
|
@@ -7017,10 +7017,16 @@ function decideLaunch(params, readOnly) {
|
|
|
7017
7017
|
const assembled = assembleCascade(launchCascade);
|
|
7018
7018
|
const flattened = flattenLayers(assembled.layers, { home: params.farm.home });
|
|
7019
7019
|
cascadeLaunch = flattened.launch;
|
|
7020
|
-
if (readOnly) {
|
|
7020
|
+
if (readOnly || farmContext === void 0) {
|
|
7021
7021
|
for (const diagnostic of [...assembled.diagnostics, ...flattened.diagnostics]) {
|
|
7022
|
-
if (diagnostic.severity
|
|
7023
|
-
|
|
7022
|
+
if (diagnostic.severity === "info") {
|
|
7023
|
+
continue;
|
|
7024
|
+
}
|
|
7025
|
+
const message = `agent-shim: ${diagnostic.code}: ${diagnostic.message}`;
|
|
7026
|
+
if (diagnostic.severity === "error" && !readOnly) {
|
|
7027
|
+
log.error(message);
|
|
7028
|
+
} else {
|
|
7029
|
+
log.warn(message);
|
|
7024
7030
|
}
|
|
7025
7031
|
}
|
|
7026
7032
|
}
|
|
@@ -7044,7 +7050,7 @@ function decideLaunch(params, readOnly) {
|
|
|
7044
7050
|
extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
|
|
7045
7051
|
passthrough: parsedArgv.rest
|
|
7046
7052
|
});
|
|
7047
|
-
const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR :
|
|
7053
|
+
const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : import_node_path34.default.join(paths.identitiesDir, identityDecision.name);
|
|
7048
7054
|
const decision = {
|
|
7049
7055
|
identitySource: identityDecision.source,
|
|
7050
7056
|
configDirEscapeHatch: identityDecision.configDirEscapeHatch,
|
|
@@ -7085,7 +7091,7 @@ function prepareLaunch(params) {
|
|
|
7085
7091
|
);
|
|
7086
7092
|
const updateCheck = runLaunchUpdateCheck({
|
|
7087
7093
|
mode: params.updateMode ?? "off",
|
|
7088
|
-
checkPath:
|
|
7094
|
+
checkPath: import_node_path34.default.join(paths.root, "update.check"),
|
|
7089
7095
|
currentVersion: package_default.version,
|
|
7090
7096
|
port: params.update
|
|
7091
7097
|
});
|
|
@@ -7216,12 +7222,12 @@ function runLaunchPlan(plan, spawn2) {
|
|
|
7216
7222
|
function runLauncher(params) {
|
|
7217
7223
|
params.proc.exit(runLaunchPlan(prepareLaunch(params), params.spawn));
|
|
7218
7224
|
}
|
|
7219
|
-
var import_node_crypto10,
|
|
7225
|
+
var import_node_crypto10, import_node_path34;
|
|
7220
7226
|
var init_launcher = __esm({
|
|
7221
7227
|
"src/launcher.ts"() {
|
|
7222
7228
|
"use strict";
|
|
7223
7229
|
import_node_crypto10 = require("node:crypto");
|
|
7224
|
-
|
|
7230
|
+
import_node_path34 = __toESM(require("node:path"), 1);
|
|
7225
7231
|
init_package();
|
|
7226
7232
|
init_envBool();
|
|
7227
7233
|
init_argv();
|
|
@@ -7252,13 +7258,13 @@ function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string"
|
|
|
7252
7258
|
if (distDir === void 0) {
|
|
7253
7259
|
throw new OwnCliPathUnknownError();
|
|
7254
7260
|
}
|
|
7255
|
-
return
|
|
7261
|
+
return import_node_path35.default.join(distDir, OWN_CLI_FILE_NAME);
|
|
7256
7262
|
}
|
|
7257
|
-
var
|
|
7263
|
+
var import_node_path35, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
|
|
7258
7264
|
var init_ownCli = __esm({
|
|
7259
7265
|
"src/ownCli.ts"() {
|
|
7260
7266
|
"use strict";
|
|
7261
|
-
|
|
7267
|
+
import_node_path35 = __toESM(require("node:path"), 1);
|
|
7262
7268
|
init_cliError();
|
|
7263
7269
|
OWN_CLI_FILE_NAME = "cli.cjs";
|
|
7264
7270
|
OwnCliPathUnknownError = class extends CliError {
|
|
@@ -7343,7 +7349,7 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
|
|
|
7343
7349
|
// src/frontdoor/trust.ts
|
|
7344
7350
|
function resolveTrustBundle(params) {
|
|
7345
7351
|
const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
|
|
7346
|
-
if (inherited === void 0 || inherited === "" ||
|
|
7352
|
+
if (inherited === void 0 || inherited === "" || import_node_path36.default.resolve(inherited) === import_node_path36.default.resolve(caCertFile)) {
|
|
7347
7353
|
return { path: caCertFile };
|
|
7348
7354
|
}
|
|
7349
7355
|
const caPem = fs12.readFileUtf8(caCertFile);
|
|
@@ -7361,19 +7367,19 @@ function resolveTrustBundle(params) {
|
|
|
7361
7367
|
}
|
|
7362
7368
|
const combined = `${inheritedPem.trimEnd()}
|
|
7363
7369
|
${caPem}`;
|
|
7364
|
-
const bundle =
|
|
7370
|
+
const bundle = import_node_path36.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
7365
7371
|
if (!fs12.exists(bundle)) {
|
|
7366
7372
|
fs12.mkdirp(bundlesDir);
|
|
7367
7373
|
fs12.writeFileAtomic(bundle, combined);
|
|
7368
7374
|
}
|
|
7369
7375
|
return { path: bundle };
|
|
7370
7376
|
}
|
|
7371
|
-
var import_node_crypto11,
|
|
7377
|
+
var import_node_crypto11, import_node_path36, BUNDLE_NAME_HEX_DIGITS;
|
|
7372
7378
|
var init_trust = __esm({
|
|
7373
7379
|
"src/frontdoor/trust.ts"() {
|
|
7374
7380
|
"use strict";
|
|
7375
7381
|
import_node_crypto11 = require("node:crypto");
|
|
7376
|
-
|
|
7382
|
+
import_node_path36 = __toESM(require("node:path"), 1);
|
|
7377
7383
|
BUNDLE_NAME_HEX_DIGITS = 16;
|
|
7378
7384
|
}
|
|
7379
7385
|
});
|
|
@@ -8717,8 +8723,8 @@ function parseConnectTarget(authority) {
|
|
|
8717
8723
|
function isInterceptedHost(host, interceptHosts) {
|
|
8718
8724
|
return interceptHosts.includes(host);
|
|
8719
8725
|
}
|
|
8720
|
-
function servedByPipeline(
|
|
8721
|
-
return
|
|
8726
|
+
function servedByPipeline(path37) {
|
|
8727
|
+
return path37?.startsWith(ROUTED_PATH_PREFIX) === true;
|
|
8722
8728
|
}
|
|
8723
8729
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
8724
8730
|
"connection",
|
|
@@ -9253,11 +9259,11 @@ function createRcSessionTracker(deps) {
|
|
|
9253
9259
|
};
|
|
9254
9260
|
const observeExchange = (request4) => {
|
|
9255
9261
|
const method = (request4.method ?? "").toUpperCase();
|
|
9256
|
-
const
|
|
9257
|
-
if (!
|
|
9262
|
+
const path37 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
|
|
9263
|
+
if (!path37.startsWith(RC_SESSIONS_PATH_PREFIX)) {
|
|
9258
9264
|
return void 0;
|
|
9259
9265
|
}
|
|
9260
|
-
const tail =
|
|
9266
|
+
const tail = path37.slice(RC_SESSIONS_PATH_PREFIX.length);
|
|
9261
9267
|
const facts = {
|
|
9262
9268
|
oauthAuthorization: oauthAuthorizationOf(request4.headers),
|
|
9263
9269
|
anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
|
|
@@ -9639,8 +9645,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
|
|
|
9639
9645
|
function isRcReadFileEncoding(value) {
|
|
9640
9646
|
return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
|
|
9641
9647
|
}
|
|
9642
|
-
function buildRcReadFilePayload(requestId,
|
|
9643
|
-
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path:
|
|
9648
|
+
function buildRcReadFilePayload(requestId, path37, options) {
|
|
9649
|
+
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path37, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
|
|
9644
9650
|
}
|
|
9645
9651
|
function buildRcFileSuggestionsPayload(requestId, query) {
|
|
9646
9652
|
return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
|
|
@@ -9742,15 +9748,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
|
|
|
9742
9748
|
const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
|
|
9743
9749
|
return result.ok ? { ...result, requestId } : result;
|
|
9744
9750
|
}
|
|
9745
|
-
async function readRcSessionFile(deps, sessionId,
|
|
9746
|
-
if (
|
|
9751
|
+
async function readRcSessionFile(deps, sessionId, path37, options) {
|
|
9752
|
+
if (path37 === "") {
|
|
9747
9753
|
return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
|
|
9748
9754
|
}
|
|
9749
9755
|
if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
|
|
9750
9756
|
return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
|
|
9751
9757
|
}
|
|
9752
9758
|
const requestId = deps.newUuid();
|
|
9753
|
-
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId,
|
|
9759
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path37, options), `read ${path37} from session ${sessionId}`);
|
|
9754
9760
|
return result.ok ? { ...result, requestId } : result;
|
|
9755
9761
|
}
|
|
9756
9762
|
async function suggestRcSessionFiles(deps, sessionId, query) {
|
|
@@ -9919,11 +9925,11 @@ function createRcControlHandler(deps) {
|
|
|
9919
9925
|
path: "read-file",
|
|
9920
9926
|
read: (body) => {
|
|
9921
9927
|
const session = bodyString(body, "session");
|
|
9922
|
-
const
|
|
9928
|
+
const path37 = bodyString(body, "path");
|
|
9923
9929
|
const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
|
|
9924
9930
|
const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
|
|
9925
|
-
const refused2 = session === void 0 ||
|
|
9926
|
-
return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session,
|
|
9931
|
+
const refused2 = session === void 0 || path37 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
|
|
9932
|
+
return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path37, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
|
|
9927
9933
|
}
|
|
9928
9934
|
},
|
|
9929
9935
|
{
|
|
@@ -10233,9 +10239,9 @@ function requestIdOfBody(body) {
|
|
|
10233
10239
|
}
|
|
10234
10240
|
function frontDoorRcControl(transport, token) {
|
|
10235
10241
|
const headers = { authorization: `Bearer ${token}` };
|
|
10236
|
-
const listAnswerOf = async (
|
|
10242
|
+
const listAnswerOf = async (path37, what) => {
|
|
10237
10243
|
try {
|
|
10238
|
-
return await transport.request({ method: "GET", path:
|
|
10244
|
+
return await transport.request({ method: "GET", path: path37, headers });
|
|
10239
10245
|
} catch (error) {
|
|
10240
10246
|
throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
10241
10247
|
}
|
|
@@ -10307,10 +10313,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
10307
10313
|
}
|
|
10308
10314
|
return pending;
|
|
10309
10315
|
};
|
|
10310
|
-
const writeOf = async (
|
|
10316
|
+
const writeOf = async (path37, body, describeFailure) => {
|
|
10311
10317
|
let answer;
|
|
10312
10318
|
try {
|
|
10313
|
-
answer = await transport.request({ method: "POST", path:
|
|
10319
|
+
answer = await transport.request({ method: "POST", path: path37, headers: { ...headers, "content-type": "application/json" }, body });
|
|
10314
10320
|
} catch (error) {
|
|
10315
10321
|
return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
|
|
10316
10322
|
}
|
|
@@ -10341,10 +10347,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
10341
10347
|
endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
10342
10348
|
getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
10343
10349
|
getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
10344
|
-
readFile: async (sessionId,
|
|
10350
|
+
readFile: async (sessionId, path37, options) => await writeOf(
|
|
10345
10351
|
`${CONTROL_PATH_PREFIX}/read-file`,
|
|
10346
|
-
JSON.stringify({ session: sessionId, path:
|
|
10347
|
-
(status, message) => `reading ${
|
|
10352
|
+
JSON.stringify({ session: sessionId, path: path37, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
|
|
10353
|
+
(status, message) => `reading ${path37} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
|
|
10348
10354
|
),
|
|
10349
10355
|
fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
10350
10356
|
keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
|
|
@@ -10503,12 +10509,12 @@ function tlsFacts(options) {
|
|
|
10503
10509
|
}
|
|
10504
10510
|
function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
10505
10511
|
const agent = new ExemptTlsAgent();
|
|
10506
|
-
const post = async (
|
|
10512
|
+
const post = async (path37, headers, body) => await new Promise((resolve, reject) => {
|
|
10507
10513
|
const options = {
|
|
10508
10514
|
host: target.host,
|
|
10509
10515
|
port: target.port,
|
|
10510
10516
|
method: "POST",
|
|
10511
|
-
path:
|
|
10517
|
+
path: path37,
|
|
10512
10518
|
// The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
|
|
10513
10519
|
headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
|
|
10514
10520
|
agent
|
|
@@ -10573,12 +10579,12 @@ function lateRcStreamDial(resolve) {
|
|
|
10573
10579
|
}
|
|
10574
10580
|
function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
|
|
10575
10581
|
const agent = new ExemptTlsAgent();
|
|
10576
|
-
const request4 = async (method,
|
|
10582
|
+
const request4 = async (method, path37, headers, body, signal) => await new Promise((resolve, reject) => {
|
|
10577
10583
|
const options = {
|
|
10578
10584
|
host: target.host,
|
|
10579
10585
|
port: target.port,
|
|
10580
10586
|
method,
|
|
10581
|
-
path:
|
|
10587
|
+
path: path37,
|
|
10582
10588
|
// The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
|
|
10583
10589
|
headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
|
|
10584
10590
|
agent,
|
|
@@ -10620,9 +10626,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
|
|
|
10620
10626
|
return { status, body: await readAll(response) };
|
|
10621
10627
|
},
|
|
10622
10628
|
openStream: async (sessionId, headers, resume, signal) => {
|
|
10623
|
-
const
|
|
10629
|
+
const path37 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
|
|
10624
10630
|
const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
|
|
10625
|
-
const { status, response } = await request4("GET",
|
|
10631
|
+
const { status, response } = await request4("GET", path37, streamHeaders, void 0, signal);
|
|
10626
10632
|
if (!isSuccessful2(status)) {
|
|
10627
10633
|
await readAll(response);
|
|
10628
10634
|
return { status, chunks: NO_CHUNKS };
|
|
@@ -11537,19 +11543,19 @@ function writePools(paths, pools) {
|
|
|
11537
11543
|
applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
|
|
11538
11544
|
}
|
|
11539
11545
|
function poolCycleOf(pools, name) {
|
|
11540
|
-
const walk = (current,
|
|
11546
|
+
const walk = (current, path37) => {
|
|
11541
11547
|
for (const entry of pools[current]?.identities ?? []) {
|
|
11542
11548
|
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
11543
11549
|
if (nested === void 0) {
|
|
11544
11550
|
continue;
|
|
11545
11551
|
}
|
|
11546
11552
|
if (nested === name) {
|
|
11547
|
-
return [...
|
|
11553
|
+
return [...path37, nested];
|
|
11548
11554
|
}
|
|
11549
|
-
if (
|
|
11555
|
+
if (path37.includes(nested)) {
|
|
11550
11556
|
continue;
|
|
11551
11557
|
}
|
|
11552
|
-
const found = walk(nested, [...
|
|
11558
|
+
const found = walk(nested, [...path37, nested]);
|
|
11553
11559
|
if (found !== void 0) {
|
|
11554
11560
|
return found;
|
|
11555
11561
|
}
|
|
@@ -12222,7 +12228,7 @@ init_middleware();
|
|
|
12222
12228
|
init_preflight();
|
|
12223
12229
|
|
|
12224
12230
|
// src/frontdoor/controlSchemas.ts
|
|
12225
|
-
var
|
|
12231
|
+
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
12226
12232
|
var import_zod19 = require("zod");
|
|
12227
12233
|
|
|
12228
12234
|
// src/doctorReport.ts
|
|
@@ -12393,7 +12399,29 @@ function removeIdentity(paths, name) {
|
|
|
12393
12399
|
// src/doctorReport.ts
|
|
12394
12400
|
init_realPorts();
|
|
12395
12401
|
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
12402
|
+
var import_node_path29 = __toESM(require("node:path"), 1);
|
|
12403
|
+
|
|
12404
|
+
// src/usage/signIn.ts
|
|
12396
12405
|
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
12406
|
+
var CREDENTIALS_FILE = ".credentials.json";
|
|
12407
|
+
function keychainHasItem(run, account) {
|
|
12408
|
+
return run.run("security", ["find-generic-password", "-a", account]).status === 0;
|
|
12409
|
+
}
|
|
12410
|
+
function decideSignIn(facts) {
|
|
12411
|
+
if (facts.hasCredentialBlock) {
|
|
12412
|
+
return { state: "token", detail: "supplies its own credential through a credential block, so a stored login is not what a launch uses" };
|
|
12413
|
+
}
|
|
12414
|
+
if (facts.keychainItem === true) {
|
|
12415
|
+
return { state: "signed-in", detail: "a login is stored in the macOS Keychain" };
|
|
12416
|
+
}
|
|
12417
|
+
if (facts.credentialsFile) {
|
|
12418
|
+
return { state: "signed-in", detail: `a login is stored in ${CREDENTIALS_FILE}` };
|
|
12419
|
+
}
|
|
12420
|
+
return { state: "signed-out", detail: facts.platform === "darwin" ? `no Keychain item and no ${CREDENTIALS_FILE}` : `no ${CREDENTIALS_FILE}` };
|
|
12421
|
+
}
|
|
12422
|
+
function credentialsFilePath(farmRoot) {
|
|
12423
|
+
return import_node_path28.default.join(farmRoot, CREDENTIALS_FILE);
|
|
12424
|
+
}
|
|
12397
12425
|
|
|
12398
12426
|
// src/codex/siwcStore.ts
|
|
12399
12427
|
var import_zod18 = require("zod");
|
|
@@ -12494,6 +12522,7 @@ var DOCTOR_SECTIONS = [
|
|
|
12494
12522
|
"legacy-name",
|
|
12495
12523
|
"config-profile",
|
|
12496
12524
|
"identity",
|
|
12525
|
+
"sign-in",
|
|
12497
12526
|
"pool",
|
|
12498
12527
|
"provider",
|
|
12499
12528
|
"keychain",
|
|
@@ -12536,7 +12565,7 @@ function tcpPortEraRecord(raw) {
|
|
|
12536
12565
|
return (has("port") || has("lastPort")) && !has("socketPath");
|
|
12537
12566
|
}
|
|
12538
12567
|
function pushPathResolution(push, resolution) {
|
|
12539
|
-
const ownDir =
|
|
12568
|
+
const ownDir = import_node_path29.default.dirname(resolution.ownExecutablePath);
|
|
12540
12569
|
switch (resolution.agentShim.status) {
|
|
12541
12570
|
case "ok":
|
|
12542
12571
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -12635,14 +12664,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
|
|
|
12635
12664
|
}
|
|
12636
12665
|
function pushLegacyName(push, params) {
|
|
12637
12666
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
12638
|
-
if (legacyVariables.length === 0 &&
|
|
12667
|
+
if (legacyVariables.length === 0 && import_node_path29.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
12639
12668
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
12640
12669
|
return;
|
|
12641
12670
|
}
|
|
12642
12671
|
for (const name of legacyVariables) {
|
|
12643
12672
|
push("legacy-name", "warn", `${name} is the former name of ${name.replace(LEGACY_ENV_PREFIX, ENV_PREFIX)}. Rename it; the old name still works but is only a fallback.`, name);
|
|
12644
12673
|
}
|
|
12645
|
-
if (
|
|
12674
|
+
if (import_node_path29.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
12646
12675
|
push(
|
|
12647
12676
|
"legacy-name",
|
|
12648
12677
|
"warn",
|
|
@@ -12739,6 +12768,18 @@ function runDoctor(params) {
|
|
|
12739
12768
|
`${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}${cache.text}.`,
|
|
12740
12769
|
entry.name
|
|
12741
12770
|
);
|
|
12771
|
+
const signIn = decideSignIn({
|
|
12772
|
+
hasCredentialBlock: credential !== void 0,
|
|
12773
|
+
keychainItem: params.platform === "darwin" && params.run !== void 0 ? keychainHasItem(params.run, entry.farmRoot) : void 0,
|
|
12774
|
+
credentialsFile: entry.credentialsFilePresent,
|
|
12775
|
+
platform: params.platform
|
|
12776
|
+
});
|
|
12777
|
+
push(
|
|
12778
|
+
"sign-in",
|
|
12779
|
+
signIn.state === "signed-out" ? "warn" : "pass",
|
|
12780
|
+
signIn.state === "signed-out" ? `${entry.name} is signed out (${signIn.detail}). Run \`agent-shim run @${entry.name}\` and sign in.` : `${entry.name} ${signIn.state === "token" ? "uses a credential block" : "is signed in"} (${signIn.detail}).`,
|
|
12781
|
+
entry.name
|
|
12782
|
+
);
|
|
12742
12783
|
}
|
|
12743
12784
|
}
|
|
12744
12785
|
const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
|
|
@@ -12784,7 +12825,7 @@ function runDoctor(params) {
|
|
|
12784
12825
|
} else {
|
|
12785
12826
|
for (const entry of params.identities) {
|
|
12786
12827
|
const result = lookupKeychainService(params.run, entry.farmRoot);
|
|
12787
|
-
push("keychain", result.found ?
|
|
12828
|
+
push("keychain", "pass", result.found ? result.note : `${result.note} The sign-in section reports whether a login is stored elsewhere.`, entry.name);
|
|
12788
12829
|
}
|
|
12789
12830
|
}
|
|
12790
12831
|
if (params.directoryRules.raw === void 0) {
|
|
@@ -12919,6 +12960,7 @@ var SECTION_TITLES = {
|
|
|
12919
12960
|
"legacy-name": "Former `claude-use` name",
|
|
12920
12961
|
"config-profile": "Configuration profiles",
|
|
12921
12962
|
identity: "Identities",
|
|
12963
|
+
"sign-in": "Sign-in",
|
|
12922
12964
|
pool: "Pools",
|
|
12923
12965
|
provider: "Providers",
|
|
12924
12966
|
keychain: "macOS Keychain",
|
|
@@ -12935,6 +12977,7 @@ var SECTION_ORDER = [
|
|
|
12935
12977
|
"path-resolution",
|
|
12936
12978
|
"config-profile",
|
|
12937
12979
|
"identity",
|
|
12980
|
+
"sign-in",
|
|
12938
12981
|
"pool",
|
|
12939
12982
|
"provider",
|
|
12940
12983
|
"keychain",
|
|
@@ -12984,18 +13027,18 @@ function collectDoctorReport(params) {
|
|
|
12984
13027
|
const { paths } = params;
|
|
12985
13028
|
const identityNames = import_node_fs9.default.existsSync(paths.identitiesDir) ? import_node_fs9.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
12986
13029
|
const identities = identityNames.map((name) => {
|
|
12987
|
-
const farmRoot =
|
|
12988
|
-
const identityPath =
|
|
12989
|
-
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
|
|
13030
|
+
const farmRoot = import_node_path29.default.join(paths.identitiesDir, name);
|
|
13031
|
+
const identityPath = import_node_path29.default.join(farmRoot, "identity.json");
|
|
13032
|
+
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot, credentialsFilePresent: import_node_fs9.default.existsSync(credentialsFilePath(farmRoot)) };
|
|
12990
13033
|
});
|
|
12991
13034
|
const profileNames = import_node_fs9.default.existsSync(paths.configProfilesDir) ? import_node_fs9.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
12992
13035
|
const configProfiles = profileNames.map((name) => {
|
|
12993
|
-
const profilePath =
|
|
13036
|
+
const profilePath = import_node_path29.default.join(paths.configProfilesDir, `${name}.json`);
|
|
12994
13037
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
12995
13038
|
});
|
|
12996
13039
|
const providerNames = import_node_fs9.default.existsSync(paths.providersDir) ? import_node_fs9.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
12997
13040
|
const providers = providerNames.map((name) => {
|
|
12998
|
-
const providerPath =
|
|
13041
|
+
const providerPath = import_node_path29.default.join(paths.providersDir, `${name}.json`);
|
|
12999
13042
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
13000
13043
|
});
|
|
13001
13044
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -13007,12 +13050,12 @@ function collectDoctorReport(params) {
|
|
|
13007
13050
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
13008
13051
|
}
|
|
13009
13052
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
13010
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
13053
|
+
const pathDirs = (params.env.PATH ?? "").split(import_node_path29.default.delimiter).filter((dir) => dir !== "");
|
|
13011
13054
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
13012
13055
|
findPathShadow({
|
|
13013
13056
|
pathDirs,
|
|
13014
|
-
targetDir:
|
|
13015
|
-
targetFilename:
|
|
13057
|
+
targetDir: import_node_path29.default.dirname(shimState.targetPath),
|
|
13058
|
+
targetFilename: import_node_path29.default.basename(shimState.targetPath),
|
|
13016
13059
|
findExecutableInDir
|
|
13017
13060
|
}),
|
|
13018
13061
|
shimState.targetPath,
|
|
@@ -13038,7 +13081,7 @@ function collectDoctorReport(params) {
|
|
|
13038
13081
|
agentShim: refinePathShadow(
|
|
13039
13082
|
findPathShadow({
|
|
13040
13083
|
pathDirs,
|
|
13041
|
-
targetDir:
|
|
13084
|
+
targetDir: import_node_path29.default.dirname(ownExecutablePath),
|
|
13042
13085
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
13043
13086
|
findExecutableInDir
|
|
13044
13087
|
}),
|
|
@@ -13112,11 +13155,11 @@ var FrontDoorSessionsOutputSchema = import_zod19.z.strictObject({ sessions: impo
|
|
|
13112
13155
|
var CheckRunInputSchema = import_zod19.z.strictObject({
|
|
13113
13156
|
path: import_zod19.z.string().min(1),
|
|
13114
13157
|
identity: import_zod19.z.string().min(1).optional()
|
|
13115
|
-
}).refine((input) =>
|
|
13158
|
+
}).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
13116
13159
|
var PoolPickInputSchema = import_zod19.z.strictObject({
|
|
13117
13160
|
pool: import_zod19.z.string().min(1),
|
|
13118
13161
|
path: import_zod19.z.string().min(1)
|
|
13119
|
-
}).refine((input) =>
|
|
13162
|
+
}).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
13120
13163
|
var DoctorFindingSchema = import_zod19.z.strictObject({
|
|
13121
13164
|
section: import_zod19.z.enum(DOCTOR_SECTIONS),
|
|
13122
13165
|
subject: import_zod19.z.string().optional(),
|
|
@@ -13492,7 +13535,7 @@ function profileValue(name, paths) {
|
|
|
13492
13535
|
function createConfigApiRouter(deps) {
|
|
13493
13536
|
const authed = doorApiAuth(deps.expectedToken);
|
|
13494
13537
|
const { paths } = deps;
|
|
13495
|
-
const route = (
|
|
13538
|
+
const route = (path37, summary) => authed.meta((0, import_openapi3.openapi)({ method: "POST", path: path37, summary, tags: [CONFIG_API_TAG] }));
|
|
13496
13539
|
return {
|
|
13497
13540
|
config: {
|
|
13498
13541
|
identity: {
|
|
@@ -13851,7 +13894,7 @@ var import_openapi6 = require("@orpc/openapi");
|
|
|
13851
13894
|
init_cliError();
|
|
13852
13895
|
|
|
13853
13896
|
// src/frontdoor/launchSchemas.ts
|
|
13854
|
-
var
|
|
13897
|
+
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
13855
13898
|
var import_zod22 = require("zod");
|
|
13856
13899
|
init_claudeVersion();
|
|
13857
13900
|
init_identity();
|
|
@@ -13861,7 +13904,7 @@ var LaunchResolveInputSchema = import_zod22.z.strictObject({
|
|
|
13861
13904
|
argv: import_zod22.z.readonly(import_zod22.z.array(import_zod22.z.string())).optional(),
|
|
13862
13905
|
/** The launch's inherited environment. Absent means an empty one: the door's own environment is never a substitute for the caller's, so a caller that wants `AGENT_SHIM_*` switches or a `CLAUDE_CONFIG_DIR` considered names them here. Values are read, never reported. */
|
|
13863
13906
|
env: import_zod22.z.record(import_zod22.z.string(), import_zod22.z.string()).optional()
|
|
13864
|
-
}).refine((input) =>
|
|
13907
|
+
}).refine((input) => import_node_path31.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
13865
13908
|
var LaunchPoolDecisionSchema = import_zod22.z.strictObject({
|
|
13866
13909
|
name: import_zod22.z.string(),
|
|
13867
13910
|
reasons: import_zod22.z.readonly(import_zod22.z.array(import_zod22.z.string())),
|
|
@@ -15956,9 +15999,9 @@ data: ${JSON.stringify(envelope)}
|
|
|
15956
15999
|
}
|
|
15957
16000
|
|
|
15958
16001
|
// src/frontdoor/rcSelfHostMint.ts
|
|
15959
|
-
var
|
|
16002
|
+
var import_node_path32 = __toESM(require("node:path"), 1);
|
|
15960
16003
|
init_account();
|
|
15961
|
-
var
|
|
16004
|
+
var CREDENTIALS_FILE2 = ".credentials.json";
|
|
15962
16005
|
var CLAUDE_JSON2 = ".claude.json";
|
|
15963
16006
|
var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
|
|
15964
16007
|
var RC_SELF_HOST_RECORD_FILE = "credential.json";
|
|
@@ -15981,7 +16024,7 @@ function readJsonObject(fs12, file) {
|
|
|
15981
16024
|
return isRecord11(parsed) ? parsed : void 0;
|
|
15982
16025
|
}
|
|
15983
16026
|
function readRcSelfHostRecord(fs12, frontdoorDir) {
|
|
15984
|
-
const parsed = readJsonObject(fs12,
|
|
16027
|
+
const parsed = readJsonObject(fs12, import_node_path32.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
|
|
15985
16028
|
if (parsed === void 0) {
|
|
15986
16029
|
return void 0;
|
|
15987
16030
|
}
|
|
@@ -15995,11 +16038,11 @@ function mintRcSelfHostCredential(deps) {
|
|
|
15995
16038
|
if (!isIdentityName(deps.identity)) {
|
|
15996
16039
|
throw new Error(`"${deps.identity}" is not a valid identity name.`);
|
|
15997
16040
|
}
|
|
15998
|
-
const identityDir =
|
|
15999
|
-
const credentialsFile =
|
|
16000
|
-
const claudeJsonFile =
|
|
16001
|
-
const recordDir =
|
|
16002
|
-
const recordFile =
|
|
16041
|
+
const identityDir = import_node_path32.default.join(deps.identitiesDir, deps.identity);
|
|
16042
|
+
const credentialsFile = import_node_path32.default.join(identityDir, CREDENTIALS_FILE2);
|
|
16043
|
+
const claudeJsonFile = import_node_path32.default.join(identityDir, CLAUDE_JSON2);
|
|
16044
|
+
const recordDir = import_node_path32.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
|
|
16045
|
+
const recordFile = import_node_path32.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
|
|
16003
16046
|
const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
|
|
16004
16047
|
const existingCredentials = readJsonObject(deps.fs, credentialsFile);
|
|
16005
16048
|
const existingOauth = isRecord11(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
|
|
@@ -16015,7 +16058,7 @@ function mintRcSelfHostCredential(deps) {
|
|
|
16015
16058
|
const organizationUuid = deps.newUuid();
|
|
16016
16059
|
const accountUuid = deps.newUuid();
|
|
16017
16060
|
const mintedAt = new Date(deps.now()).toISOString();
|
|
16018
|
-
deps.fs.mkdirPrivate(
|
|
16061
|
+
deps.fs.mkdirPrivate(import_node_path32.default.dirname(credentialsFile));
|
|
16019
16062
|
deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
|
|
16020
16063
|
`);
|
|
16021
16064
|
const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
|