agent-shim 8.5.6 → 8.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/README.md +3 -0
- package/dist/cli.cjs +2368 -2109
- package/dist/index.cjs +448 -225
- package/dist/index.mjs +439 -224
- package/dist/types/index.d.ts +85 -7
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -75,6 +75,7 @@ __export(index_exports, {
|
|
|
75
75
|
ProviderSchema: () => ProviderSchema,
|
|
76
76
|
RC_IDLE_EXPIRY_MS: () => RC_IDLE_EXPIRY_MS,
|
|
77
77
|
RC_PENDING_DEADLINE_MS: () => RC_PENDING_DEADLINE_MS,
|
|
78
|
+
RC_PERMISSION_MODES: () => RC_PERMISSION_MODES,
|
|
78
79
|
RC_REQUEST_PARSE_CAP_BYTES: () => RC_REQUEST_PARSE_CAP_BYTES,
|
|
79
80
|
RC_SESSIONS_PATH_PREFIX: () => RC_SESSIONS_PATH_PREFIX,
|
|
80
81
|
ROUTED_PATH_PREFIX: () => ROUTED_PATH_PREFIX,
|
|
@@ -91,6 +92,9 @@ __export(index_exports, {
|
|
|
91
92
|
buildLayoutPaths: () => buildLayoutPaths,
|
|
92
93
|
buildRcControlResponsePayload: () => buildRcControlResponsePayload,
|
|
93
94
|
buildRcEventWriteBody: () => buildRcEventWriteBody,
|
|
95
|
+
buildRcInterruptPayload: () => buildRcInterruptPayload,
|
|
96
|
+
buildRcSetModelPayload: () => buildRcSetModelPayload,
|
|
97
|
+
buildRcSetPermissionModePayload: () => buildRcSetPermissionModePayload,
|
|
94
98
|
buildRcUserMessagePayload: () => buildRcUserMessagePayload,
|
|
95
99
|
carryOver: () => carryOver,
|
|
96
100
|
checkReportHasWarnings: () => checkReportHasWarnings,
|
|
@@ -115,8 +119,10 @@ __export(index_exports, {
|
|
|
115
119
|
generateCa: () => generateCa,
|
|
116
120
|
identityExists: () => identityExists,
|
|
117
121
|
injectRcUserMessage: () => injectRcUserMessage,
|
|
122
|
+
interruptRcSession: () => interruptRcSession,
|
|
118
123
|
isIdentityDirectoryName: () => isIdentityDirectoryName,
|
|
119
124
|
isInterceptedHost: () => isInterceptedHost,
|
|
125
|
+
isRcPermissionMode: () => isRcPermissionMode,
|
|
120
126
|
listDirectoryRules: () => listDirectoryRules,
|
|
121
127
|
listIdentities: () => listIdentities,
|
|
122
128
|
listProfiles: () => listProfiles,
|
|
@@ -172,6 +178,8 @@ __export(index_exports, {
|
|
|
172
178
|
setProfileEntries: () => setProfileEntries,
|
|
173
179
|
setProfileLaunchFlags: () => setProfileLaunchFlags,
|
|
174
180
|
setProfileMetadata: () => setProfileMetadata,
|
|
181
|
+
setRcSessionModel: () => setRcSessionModel,
|
|
182
|
+
setRcSessionPermissionMode: () => setRcSessionPermissionMode,
|
|
175
183
|
snapshotPath: () => snapshotPath,
|
|
176
184
|
startConnectServer: () => startConnectServer,
|
|
177
185
|
topLevelNames: () => topLevelNames,
|
|
@@ -4070,6 +4078,19 @@ function buildRcControlResponsePayload(requestId, decision) {
|
|
|
4070
4078
|
const result = decision.approve ? { behavior: "allow" } : { behavior: "deny", message: decision.message ?? "" };
|
|
4071
4079
|
return { type: "control_response", response: { subtype: "success", request_id: requestId, response: result } };
|
|
4072
4080
|
}
|
|
4081
|
+
var RC_PERMISSION_MODES = ["default", "acceptEdits", "bypassPermissions", "plan", "dontAsk", "auto"];
|
|
4082
|
+
function isRcPermissionMode(value) {
|
|
4083
|
+
return RC_PERMISSION_MODES.some((mode) => mode === value);
|
|
4084
|
+
}
|
|
4085
|
+
function buildRcInterruptPayload(requestId) {
|
|
4086
|
+
return { type: "control_request", request_id: requestId, request: { subtype: "interrupt" } };
|
|
4087
|
+
}
|
|
4088
|
+
function buildRcSetModelPayload(requestId, model) {
|
|
4089
|
+
return { type: "control_request", request_id: requestId, request: { subtype: "set_model", model } };
|
|
4090
|
+
}
|
|
4091
|
+
function buildRcSetPermissionModePayload(requestId, mode) {
|
|
4092
|
+
return { type: "control_request", request_id: requestId, request: { subtype: "set_permission_mode", mode } };
|
|
4093
|
+
}
|
|
4073
4094
|
async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
4074
4095
|
const credential = deps.credentialOf(sessionId);
|
|
4075
4096
|
if (credential === void 0) {
|
|
@@ -4094,9 +4115,64 @@ async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
|
4094
4115
|
}
|
|
4095
4116
|
return result;
|
|
4096
4117
|
}
|
|
4118
|
+
async function interruptRcSession(deps, sessionId) {
|
|
4119
|
+
const credential = deps.credentialOf(sessionId);
|
|
4120
|
+
if (credential === void 0) {
|
|
4121
|
+
return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
|
|
4122
|
+
}
|
|
4123
|
+
if (credential.authorization === void 0) {
|
|
4124
|
+
return noOAuthCredentialResult(sessionId);
|
|
4125
|
+
}
|
|
4126
|
+
const body = JSON.stringify(buildRcEventWriteBody(buildRcInterruptPayload(deps.newUuid())));
|
|
4127
|
+
let answer;
|
|
4128
|
+
try {
|
|
4129
|
+
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
4130
|
+
} catch (error) {
|
|
4131
|
+
return { ok: false, message: `the door could not reach the API host to interrupt session ${sessionId}: ${error instanceof Error ? error.message : String(error)}` };
|
|
4132
|
+
}
|
|
4133
|
+
return rcEventWriteResultFromAnswer(answer);
|
|
4134
|
+
}
|
|
4135
|
+
async function setRcSessionModel(deps, sessionId, model) {
|
|
4136
|
+
if (model === "") {
|
|
4137
|
+
return { ok: false, message: "a set-model write needs a non-empty model id: the SDK's own field treats an omitted or null value as a reset to the session default, which this operation never sends, and an empty string is neither" };
|
|
4138
|
+
}
|
|
4139
|
+
const credential = deps.credentialOf(sessionId);
|
|
4140
|
+
if (credential === void 0) {
|
|
4141
|
+
return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
|
|
4142
|
+
}
|
|
4143
|
+
if (credential.authorization === void 0) {
|
|
4144
|
+
return noOAuthCredentialResult(sessionId);
|
|
4145
|
+
}
|
|
4146
|
+
const body = JSON.stringify(buildRcEventWriteBody(buildRcSetModelPayload(deps.newUuid(), model)));
|
|
4147
|
+
let answer;
|
|
4148
|
+
try {
|
|
4149
|
+
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
4150
|
+
} catch (error) {
|
|
4151
|
+
return { ok: false, message: `the door could not reach the API host to set the model on session ${sessionId}: ${error instanceof Error ? error.message : String(error)}` };
|
|
4152
|
+
}
|
|
4153
|
+
return rcEventWriteResultFromAnswer(answer);
|
|
4154
|
+
}
|
|
4155
|
+
async function setRcSessionPermissionMode(deps, sessionId, mode) {
|
|
4156
|
+
const credential = deps.credentialOf(sessionId);
|
|
4157
|
+
if (credential === void 0) {
|
|
4158
|
+
return { ok: false, message: `the front door has not observed Remote Control session ${sessionId}: it may never have passed through this door, or it ended or expired (an entry lives only a bounded idle period past its last observed traffic)` };
|
|
4159
|
+
}
|
|
4160
|
+
if (credential.authorization === void 0) {
|
|
4161
|
+
return noOAuthCredentialResult(sessionId);
|
|
4162
|
+
}
|
|
4163
|
+
const body = JSON.stringify(buildRcEventWriteBody(buildRcSetPermissionModePayload(deps.newUuid(), mode)));
|
|
4164
|
+
let answer;
|
|
4165
|
+
try {
|
|
4166
|
+
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
4167
|
+
} catch (error) {
|
|
4168
|
+
return { ok: false, message: `the door could not reach the API host to set the permission mode on session ${sessionId}: ${error instanceof Error ? error.message : String(error)}` };
|
|
4169
|
+
}
|
|
4170
|
+
return rcEventWriteResultFromAnswer(answer);
|
|
4171
|
+
}
|
|
4097
4172
|
|
|
4098
4173
|
// src/frontdoor/rcControl.ts
|
|
4099
4174
|
var https2 = __toESM(require("node:https"), 1);
|
|
4175
|
+
var RC_PERMISSION_MODE_LIST = RC_PERMISSION_MODES.join(", ");
|
|
4100
4176
|
var CONTROL_PATH_PREFIX = "/__agent-shim/rc";
|
|
4101
4177
|
var CONTROL_BODY_CAP_BYTES = 10485760;
|
|
4102
4178
|
function answerJson(response, status, body) {
|
|
@@ -4131,6 +4207,9 @@ function createRcControlHandler(deps) {
|
|
|
4131
4207
|
const pendingPath = `${CONTROL_PATH_PREFIX}/pending`;
|
|
4132
4208
|
const injectPath = `${CONTROL_PATH_PREFIX}/inject`;
|
|
4133
4209
|
const answerPath = `${CONTROL_PATH_PREFIX}/answer`;
|
|
4210
|
+
const interruptPath = `${CONTROL_PATH_PREFIX}/interrupt`;
|
|
4211
|
+
const setModelPath = `${CONTROL_PATH_PREFIX}/set-model`;
|
|
4212
|
+
const setPermissionModePath = `${CONTROL_PATH_PREFIX}/set-permission-mode`;
|
|
4134
4213
|
return (request4, response) => {
|
|
4135
4214
|
const presented = request4.headers.authorization;
|
|
4136
4215
|
const bearerPrefix = "bearer ".length;
|
|
@@ -4215,6 +4294,78 @@ function createRcControlHandler(deps) {
|
|
|
4215
4294
|
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4216
4295
|
return;
|
|
4217
4296
|
}
|
|
4297
|
+
if (url.pathname === interruptPath) {
|
|
4298
|
+
if (request4.method !== "POST") {
|
|
4299
|
+
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: "the interrupt operation is a POST" });
|
|
4300
|
+
return;
|
|
4301
|
+
}
|
|
4302
|
+
let parsed;
|
|
4303
|
+
try {
|
|
4304
|
+
parsed = JSON.parse(await readBody(request4));
|
|
4305
|
+
} catch {
|
|
4306
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the interrupt body is not readable JSON within the control body cap" });
|
|
4307
|
+
return;
|
|
4308
|
+
}
|
|
4309
|
+
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || typeof parsed.session !== "string" || parsed.session === "") {
|
|
4310
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the interrupt body must be JSON naming a non-empty session id" });
|
|
4311
|
+
return;
|
|
4312
|
+
}
|
|
4313
|
+
const result = await deps.interrupt(parsed.session);
|
|
4314
|
+
if (result.ok) {
|
|
4315
|
+
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, sequenceNums: result.sequenceNums });
|
|
4316
|
+
return;
|
|
4317
|
+
}
|
|
4318
|
+
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4319
|
+
return;
|
|
4320
|
+
}
|
|
4321
|
+
if (url.pathname === setModelPath) {
|
|
4322
|
+
if (request4.method !== "POST") {
|
|
4323
|
+
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: "the set-model operation is a POST" });
|
|
4324
|
+
return;
|
|
4325
|
+
}
|
|
4326
|
+
let parsed;
|
|
4327
|
+
try {
|
|
4328
|
+
parsed = JSON.parse(await readBody(request4));
|
|
4329
|
+
} catch {
|
|
4330
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-model body is not readable JSON within the control body cap" });
|
|
4331
|
+
return;
|
|
4332
|
+
}
|
|
4333
|
+
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || !("model" in parsed) || typeof parsed.session !== "string" || typeof parsed.model !== "string" || parsed.session === "" || parsed.model === "") {
|
|
4334
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-model body must be JSON naming a non-empty session id and model id" });
|
|
4335
|
+
return;
|
|
4336
|
+
}
|
|
4337
|
+
const result = await deps.setModel(parsed.session, parsed.model);
|
|
4338
|
+
if (result.ok) {
|
|
4339
|
+
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, model: parsed.model, sequenceNums: result.sequenceNums });
|
|
4340
|
+
return;
|
|
4341
|
+
}
|
|
4342
|
+
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4343
|
+
return;
|
|
4344
|
+
}
|
|
4345
|
+
if (url.pathname === setPermissionModePath) {
|
|
4346
|
+
if (request4.method !== "POST") {
|
|
4347
|
+
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: "the set-permission-mode operation is a POST" });
|
|
4348
|
+
return;
|
|
4349
|
+
}
|
|
4350
|
+
let parsed;
|
|
4351
|
+
try {
|
|
4352
|
+
parsed = JSON.parse(await readBody(request4));
|
|
4353
|
+
} catch {
|
|
4354
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-permission-mode body is not readable JSON within the control body cap" });
|
|
4355
|
+
return;
|
|
4356
|
+
}
|
|
4357
|
+
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || !("mode" in parsed) || typeof parsed.session !== "string" || parsed.session === "" || !isRcPermissionMode(parsed.mode)) {
|
|
4358
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: `the set-permission-mode body must be JSON naming a non-empty session id and a mode the SDK's own type permits (${RC_PERMISSION_MODE_LIST})` });
|
|
4359
|
+
return;
|
|
4360
|
+
}
|
|
4361
|
+
const result = await deps.setPermissionMode(parsed.session, parsed.mode);
|
|
4362
|
+
if (result.ok) {
|
|
4363
|
+
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, mode: parsed.mode, sequenceNums: result.sequenceNums });
|
|
4364
|
+
return;
|
|
4365
|
+
}
|
|
4366
|
+
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4367
|
+
return;
|
|
4368
|
+
}
|
|
4218
4369
|
answerJson(response, HTTP_STATUS.notFound, { error: `no such control route: ${url.pathname}` });
|
|
4219
4370
|
};
|
|
4220
4371
|
handle().catch((error) => {
|
|
@@ -4429,7 +4580,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
4429
4580
|
`${CONTROL_PATH_PREFIX}/answer`,
|
|
4430
4581
|
JSON.stringify({ session: sessionId, request: requestId, approve: decision.approve, ...decision.approve || decision.message === void 0 ? {} : { text: decision.message } }),
|
|
4431
4582
|
(status, message) => `answering control request ${requestId} on ${sessionId} failed (HTTP ${String(status)}): ${message}`
|
|
4432
|
-
)
|
|
4583
|
+
),
|
|
4584
|
+
interruptSession: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/interrupt`, JSON.stringify({ session: sessionId }), (status, message) => `interrupting ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4585
|
+
setModel: async (sessionId, model) => await writeOf(`${CONTROL_PATH_PREFIX}/set-model`, JSON.stringify({ session: sessionId, model }), (status, message) => `setting the model on ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4586
|
+
setPermissionMode: async (sessionId, mode) => await writeOf(`${CONTROL_PATH_PREFIX}/set-permission-mode`, JSON.stringify({ session: sessionId, mode }), (status, message) => `setting the permission mode on ${sessionId} failed (HTTP ${String(status)}): ${message}`)
|
|
4433
4587
|
};
|
|
4434
4588
|
}
|
|
4435
4589
|
|
|
@@ -5872,6 +6026,56 @@ var import_node_path16 = __toESM(require("node:path"), 1);
|
|
|
5872
6026
|
|
|
5873
6027
|
// src/credentialCache.ts
|
|
5874
6028
|
var import_zod7 = require("zod");
|
|
6029
|
+
|
|
6030
|
+
// src/usage/preflight.ts
|
|
6031
|
+
var MS_PER_SECOND2 = 1e3;
|
|
6032
|
+
var SECONDS_PER_MINUTE = 60;
|
|
6033
|
+
var MINUTES_PER_HOUR = 60;
|
|
6034
|
+
var HOURS_PER_DAY = 24;
|
|
6035
|
+
var WARNING_STATUSES = /* @__PURE__ */ new Set(["allowed_warning", "rejected"]);
|
|
6036
|
+
function formatAge(ms) {
|
|
6037
|
+
const minutes = Math.floor(ms / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
|
|
6038
|
+
if (minutes < MINUTES_PER_HOUR) {
|
|
6039
|
+
return `${String(Math.max(minutes, 0))}m`;
|
|
6040
|
+
}
|
|
6041
|
+
const hours = Math.floor(minutes / MINUTES_PER_HOUR);
|
|
6042
|
+
return hours < HOURS_PER_DAY ? `${String(hours)}h` : `${String(Math.floor(hours / HOURS_PER_DAY))}d`;
|
|
6043
|
+
}
|
|
6044
|
+
function effectiveWindow(window, nowMs) {
|
|
6045
|
+
const resetsAtMs = window.resetsAt === void 0 ? void 0 : Date.parse(window.resetsAt);
|
|
6046
|
+
if (resetsAtMs !== void 0 && resetsAtMs <= nowMs) {
|
|
6047
|
+
return { reset: true, utilization: 0 };
|
|
6048
|
+
}
|
|
6049
|
+
return {
|
|
6050
|
+
reset: false,
|
|
6051
|
+
...window.utilization === void 0 ? {} : { utilization: window.utilization },
|
|
6052
|
+
...resetsAtMs === void 0 ? {} : { resetsAtMs },
|
|
6053
|
+
...window.status === void 0 ? {} : { status: window.status }
|
|
6054
|
+
};
|
|
6055
|
+
}
|
|
6056
|
+
function quotaWarnings(snapshot, provider, nowMs) {
|
|
6057
|
+
const rateLimit = snapshot?.providers[provider]?.rateLimit;
|
|
6058
|
+
const unified = rateLimit?.unified;
|
|
6059
|
+
if (snapshot === void 0 || rateLimit === void 0 || unified === void 0) {
|
|
6060
|
+
return [];
|
|
6061
|
+
}
|
|
6062
|
+
const age = formatAge(nowMs - Date.parse(rateLimit.observedAt));
|
|
6063
|
+
const windows = [
|
|
6064
|
+
{ name: "five-hour", window: unified.fiveHour },
|
|
6065
|
+
{ name: "seven-day", window: unified.sevenDay }
|
|
6066
|
+
];
|
|
6067
|
+
return windows.flatMap(({ name, window }) => {
|
|
6068
|
+
const effective = window === void 0 ? void 0 : effectiveWindow(window, nowMs);
|
|
6069
|
+
if (window === void 0 || effective?.status === void 0 || !WARNING_STATUSES.has(effective.status)) {
|
|
6070
|
+
return [];
|
|
6071
|
+
}
|
|
6072
|
+
const reset = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
|
|
6073
|
+
const verdict = effective.status === "rejected" ? "exhausted" : "nearly used";
|
|
6074
|
+
return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age} ago)`];
|
|
6075
|
+
});
|
|
6076
|
+
}
|
|
6077
|
+
|
|
6078
|
+
// src/credentialCache.ts
|
|
5875
6079
|
var MS_PER_UNIT = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
|
|
5876
6080
|
var CachedCredentialSchema = import_zod7.z.strictObject({
|
|
5877
6081
|
token: import_zod7.z.string().min(1),
|
|
@@ -5898,6 +6102,45 @@ function isFresh(entry, cache, now) {
|
|
|
5898
6102
|
}
|
|
5899
6103
|
return limit === void 0 || now - entry.fetchedAt < limit;
|
|
5900
6104
|
}
|
|
6105
|
+
function cacheAgeMs(entry, now) {
|
|
6106
|
+
return Math.max(0, now - entry.fetchedAt);
|
|
6107
|
+
}
|
|
6108
|
+
function describeCachedCredential(params) {
|
|
6109
|
+
const store = effectiveStore(params.cache, params.platform);
|
|
6110
|
+
let entry;
|
|
6111
|
+
try {
|
|
6112
|
+
entry = params.port.read(store, params.owner);
|
|
6113
|
+
} catch (error) {
|
|
6114
|
+
return { store, status: "unreadable", reason: error instanceof Error ? error.message : String(error) };
|
|
6115
|
+
}
|
|
6116
|
+
if (entry === void 0) {
|
|
6117
|
+
return { store, status: "empty" };
|
|
6118
|
+
}
|
|
6119
|
+
const limit = ttlMs(params.cache);
|
|
6120
|
+
const ageMs = cacheAgeMs(entry, params.nowMs);
|
|
6121
|
+
return {
|
|
6122
|
+
store,
|
|
6123
|
+
status: isFresh(entry, params.cache, params.nowMs) ? "fresh" : "expired",
|
|
6124
|
+
ageMs,
|
|
6125
|
+
...limit === void 0 ? {} : { expiresInMs: limit - ageMs }
|
|
6126
|
+
};
|
|
6127
|
+
}
|
|
6128
|
+
function formatCachedCredentialState(state) {
|
|
6129
|
+
if (state.status === "empty") {
|
|
6130
|
+
return `no cached entry in the ${state.store} store yet`;
|
|
6131
|
+
}
|
|
6132
|
+
if (state.status === "unreadable") {
|
|
6133
|
+
return `the ${state.store} store cannot be read here: ${state.reason}`;
|
|
6134
|
+
}
|
|
6135
|
+
if (state.status === "expired" && (state.expiresInMs === void 0 || state.expiresInMs > 0)) {
|
|
6136
|
+
return "cached with a timestamp in the future, treated as expired";
|
|
6137
|
+
}
|
|
6138
|
+
const age = `cached ${formatAge(state.ageMs)} ago`;
|
|
6139
|
+
if (state.expiresInMs === void 0) {
|
|
6140
|
+
return `${age}, no expiry`;
|
|
6141
|
+
}
|
|
6142
|
+
return state.status === "fresh" ? `${age}, expires in ${formatAge(state.expiresInMs)}` : `${age}, expired ${formatAge(-state.expiresInMs)} ago`;
|
|
6143
|
+
}
|
|
5901
6144
|
|
|
5902
6145
|
// src/credential.ts
|
|
5903
6146
|
var CREDENTIAL_UNAVAILABLE_EXIT = 64;
|
|
@@ -6513,54 +6756,6 @@ function readDirectorySelections(loaded) {
|
|
|
6513
6756
|
return { ...identity === void 0 ? {} : { identity }, ...configProfile === void 0 ? {} : { configProfile } };
|
|
6514
6757
|
}
|
|
6515
6758
|
|
|
6516
|
-
// src/usage/preflight.ts
|
|
6517
|
-
var MS_PER_SECOND2 = 1e3;
|
|
6518
|
-
var SECONDS_PER_MINUTE = 60;
|
|
6519
|
-
var MINUTES_PER_HOUR = 60;
|
|
6520
|
-
var HOURS_PER_DAY = 24;
|
|
6521
|
-
var WARNING_STATUSES = /* @__PURE__ */ new Set(["allowed_warning", "rejected"]);
|
|
6522
|
-
function formatAge(ms) {
|
|
6523
|
-
const minutes = Math.floor(ms / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
|
|
6524
|
-
if (minutes < MINUTES_PER_HOUR) {
|
|
6525
|
-
return `${String(Math.max(minutes, 0))}m`;
|
|
6526
|
-
}
|
|
6527
|
-
const hours = Math.floor(minutes / MINUTES_PER_HOUR);
|
|
6528
|
-
return hours < HOURS_PER_DAY ? `${String(hours)}h` : `${String(Math.floor(hours / HOURS_PER_DAY))}d`;
|
|
6529
|
-
}
|
|
6530
|
-
function effectiveWindow(window, nowMs) {
|
|
6531
|
-
const resetsAtMs = window.resetsAt === void 0 ? void 0 : Date.parse(window.resetsAt);
|
|
6532
|
-
if (resetsAtMs !== void 0 && resetsAtMs <= nowMs) {
|
|
6533
|
-
return { reset: true, utilization: 0 };
|
|
6534
|
-
}
|
|
6535
|
-
return {
|
|
6536
|
-
reset: false,
|
|
6537
|
-
...window.utilization === void 0 ? {} : { utilization: window.utilization },
|
|
6538
|
-
...resetsAtMs === void 0 ? {} : { resetsAtMs },
|
|
6539
|
-
...window.status === void 0 ? {} : { status: window.status }
|
|
6540
|
-
};
|
|
6541
|
-
}
|
|
6542
|
-
function quotaWarnings(snapshot, provider, nowMs) {
|
|
6543
|
-
const rateLimit = snapshot?.providers[provider]?.rateLimit;
|
|
6544
|
-
const unified = rateLimit?.unified;
|
|
6545
|
-
if (snapshot === void 0 || rateLimit === void 0 || unified === void 0) {
|
|
6546
|
-
return [];
|
|
6547
|
-
}
|
|
6548
|
-
const age = formatAge(nowMs - Date.parse(rateLimit.observedAt));
|
|
6549
|
-
const windows = [
|
|
6550
|
-
{ name: "five-hour", window: unified.fiveHour },
|
|
6551
|
-
{ name: "seven-day", window: unified.sevenDay }
|
|
6552
|
-
];
|
|
6553
|
-
return windows.flatMap(({ name, window }) => {
|
|
6554
|
-
const effective = window === void 0 ? void 0 : effectiveWindow(window, nowMs);
|
|
6555
|
-
if (window === void 0 || effective?.status === void 0 || !WARNING_STATUSES.has(effective.status)) {
|
|
6556
|
-
return [];
|
|
6557
|
-
}
|
|
6558
|
-
const reset = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
|
|
6559
|
-
const verdict = effective.status === "rejected" ? "exhausted" : "nearly used";
|
|
6560
|
-
return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age} ago)`];
|
|
6561
|
-
});
|
|
6562
|
-
}
|
|
6563
|
-
|
|
6564
6759
|
// src/usage/poolPick.ts
|
|
6565
6760
|
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
6566
6761
|
var import_zod9 = require("zod");
|
|
@@ -6956,19 +7151,97 @@ function collectPoolPick(params) {
|
|
|
6956
7151
|
};
|
|
6957
7152
|
}
|
|
6958
7153
|
|
|
6959
|
-
// src/
|
|
7154
|
+
// src/realCredentialCache.ts
|
|
6960
7155
|
var import_node_child_process = require("node:child_process");
|
|
6961
|
-
var import_node_crypto9 = require("node:crypto");
|
|
6962
7156
|
var import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
7157
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
7158
|
+
var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
7159
|
+
var CACHE_DIR_MODE = 448;
|
|
7160
|
+
var CACHE_FILE_MODE = 384;
|
|
7161
|
+
function cacheFileNameFor(owner) {
|
|
7162
|
+
return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
|
|
7163
|
+
}
|
|
7164
|
+
function parseEntry(raw) {
|
|
7165
|
+
let json;
|
|
7166
|
+
try {
|
|
7167
|
+
json = JSON.parse(raw);
|
|
7168
|
+
} catch {
|
|
7169
|
+
return void 0;
|
|
7170
|
+
}
|
|
7171
|
+
const parsed = CachedCredentialSchema.safeParse(json);
|
|
7172
|
+
return parsed.success ? parsed.data : void 0;
|
|
7173
|
+
}
|
|
7174
|
+
function requireKeychain() {
|
|
7175
|
+
if (process.platform !== "darwin") {
|
|
7176
|
+
throw new Error("the keychain credential store needs macOS; use --credential-cache-store file");
|
|
7177
|
+
}
|
|
7178
|
+
}
|
|
7179
|
+
function security(args, stdin) {
|
|
7180
|
+
const result = (0, import_node_child_process.spawnSync)("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
|
|
7181
|
+
return { status: result.status, stdout: result.stdout };
|
|
7182
|
+
}
|
|
7183
|
+
function createRealCredentialCache(root) {
|
|
7184
|
+
const dir = import_node_path20.default.join(root, "credential-cache");
|
|
7185
|
+
const filePath = (owner) => import_node_path20.default.join(dir, cacheFileNameFor(owner));
|
|
7186
|
+
return {
|
|
7187
|
+
read(store, owner) {
|
|
7188
|
+
if (store === "file") {
|
|
7189
|
+
try {
|
|
7190
|
+
return parseEntry(import_node_fs6.default.readFileSync(filePath(owner), "utf8"));
|
|
7191
|
+
} catch {
|
|
7192
|
+
return void 0;
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
requireKeychain();
|
|
7196
|
+
const result = security(["find-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner, "-w"]);
|
|
7197
|
+
return result.status === 0 ? parseEntry(Buffer.from(result.stdout.trim(), "base64").toString("utf8")) : void 0;
|
|
7198
|
+
},
|
|
7199
|
+
write(store, owner, entry) {
|
|
7200
|
+
const serialised = JSON.stringify(entry);
|
|
7201
|
+
if (store === "file") {
|
|
7202
|
+
import_node_fs6.default.mkdirSync(dir, { recursive: true, mode: CACHE_DIR_MODE });
|
|
7203
|
+
import_node_fs6.default.chmodSync(dir, CACHE_DIR_MODE);
|
|
7204
|
+
const target = filePath(owner);
|
|
7205
|
+
const temp = `${target}.${String(process.pid)}.tmp`;
|
|
7206
|
+
import_node_fs6.default.writeFileSync(temp, serialised, { mode: CACHE_FILE_MODE });
|
|
7207
|
+
import_node_fs6.default.renameSync(temp, target);
|
|
7208
|
+
return;
|
|
7209
|
+
}
|
|
7210
|
+
requireKeychain();
|
|
7211
|
+
const encoded = Buffer.from(serialised, "utf8").toString("base64");
|
|
7212
|
+
const result = security(["-i"], `add-generic-password -U -s ${KEYCHAIN_CACHE_SERVICE} -a ${JSON.stringify(owner)} -w ${encoded}
|
|
7213
|
+
`);
|
|
7214
|
+
if (result.status !== 0) {
|
|
7215
|
+
throw new Error(`could not write the keychain credential cache for ${owner}`);
|
|
7216
|
+
}
|
|
7217
|
+
},
|
|
7218
|
+
remove(store, owner) {
|
|
7219
|
+
if (store === "file") {
|
|
7220
|
+
import_node_fs6.default.rmSync(filePath(owner), { force: true });
|
|
7221
|
+
return;
|
|
7222
|
+
}
|
|
7223
|
+
requireKeychain();
|
|
7224
|
+
security(["delete-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner]);
|
|
7225
|
+
}
|
|
7226
|
+
};
|
|
7227
|
+
}
|
|
7228
|
+
function realCredentialCacheEnv(paths) {
|
|
7229
|
+
return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
|
|
7230
|
+
}
|
|
7231
|
+
|
|
7232
|
+
// src/realPorts.ts
|
|
7233
|
+
var import_node_child_process2 = require("node:child_process");
|
|
7234
|
+
var import_node_crypto9 = require("node:crypto");
|
|
7235
|
+
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
6963
7236
|
var import_node_os3 = __toESM(require("node:os"), 1);
|
|
6964
|
-
var
|
|
7237
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
6965
7238
|
var import_node_sea = require("node:sea");
|
|
6966
7239
|
|
|
6967
7240
|
// src/versionDiscovery.ts
|
|
6968
7241
|
var import_node_os2 = __toESM(require("node:os"), 1);
|
|
6969
|
-
var
|
|
7242
|
+
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
6970
7243
|
function defaultVersionsDir() {
|
|
6971
|
-
return
|
|
7244
|
+
return import_node_path21.default.join(import_node_os2.default.homedir(), ".local", "share", "claude", "versions");
|
|
6972
7245
|
}
|
|
6973
7246
|
var NUMERIC_DOTTED_VERSION_RE = /^\d+(?:\.\d+)*$/;
|
|
6974
7247
|
function isNumericDottedVersion(name) {
|
|
@@ -7010,7 +7283,7 @@ function discoverClaudeBinary(options) {
|
|
|
7010
7283
|
const highestVersion = pickHighestVersion(entries);
|
|
7011
7284
|
if (highestVersion !== void 0) {
|
|
7012
7285
|
return {
|
|
7013
|
-
path:
|
|
7286
|
+
path: import_node_path21.default.join(versionsDir, highestVersion),
|
|
7014
7287
|
source: "versions-dir",
|
|
7015
7288
|
version: highestVersion
|
|
7016
7289
|
};
|
|
@@ -7033,7 +7306,7 @@ function isEnoent3(error) {
|
|
|
7033
7306
|
var realFsPort = {
|
|
7034
7307
|
readFileUtf8(filePath) {
|
|
7035
7308
|
try {
|
|
7036
|
-
return
|
|
7309
|
+
return import_node_fs7.default.readFileSync(filePath, "utf8");
|
|
7037
7310
|
} catch (error) {
|
|
7038
7311
|
if (isEnoent3(error)) {
|
|
7039
7312
|
return void 0;
|
|
@@ -7044,7 +7317,7 @@ var realFsPort = {
|
|
|
7044
7317
|
readConfigFile: cosmiconfigReader(),
|
|
7045
7318
|
readdir(dirPath) {
|
|
7046
7319
|
try {
|
|
7047
|
-
return
|
|
7320
|
+
return import_node_fs7.default.readdirSync(dirPath);
|
|
7048
7321
|
} catch (error) {
|
|
7049
7322
|
if (isEnoent3(error)) {
|
|
7050
7323
|
return [];
|
|
@@ -7063,7 +7336,7 @@ var realFarmFs = {
|
|
|
7063
7336
|
lstat(filePath) {
|
|
7064
7337
|
let stat;
|
|
7065
7338
|
try {
|
|
7066
|
-
stat =
|
|
7339
|
+
stat = import_node_fs7.default.lstatSync(filePath);
|
|
7067
7340
|
} catch (error) {
|
|
7068
7341
|
if (isEnoent3(error)) {
|
|
7069
7342
|
return void 0;
|
|
@@ -7075,7 +7348,7 @@ var realFarmFs = {
|
|
|
7075
7348
|
},
|
|
7076
7349
|
readdir(dirPath) {
|
|
7077
7350
|
try {
|
|
7078
|
-
return
|
|
7351
|
+
return import_node_fs7.default.readdirSync(dirPath);
|
|
7079
7352
|
} catch (error) {
|
|
7080
7353
|
if (isEnoent3(error) || isErrorWithCode(error, "ENOTDIR")) {
|
|
7081
7354
|
return [];
|
|
@@ -7084,23 +7357,23 @@ var realFarmFs = {
|
|
|
7084
7357
|
}
|
|
7085
7358
|
},
|
|
7086
7359
|
mkdirp(dirPath) {
|
|
7087
|
-
|
|
7360
|
+
import_node_fs7.default.mkdirSync(dirPath, { recursive: true });
|
|
7088
7361
|
},
|
|
7089
7362
|
symlink(target, linkPath) {
|
|
7090
|
-
|
|
7363
|
+
import_node_fs7.default.symlinkSync(target, linkPath);
|
|
7091
7364
|
},
|
|
7092
7365
|
rename(from, to) {
|
|
7093
|
-
|
|
7366
|
+
import_node_fs7.default.renameSync(from, to);
|
|
7094
7367
|
},
|
|
7095
7368
|
removeRecursive(targetPath) {
|
|
7096
|
-
|
|
7369
|
+
import_node_fs7.default.rmSync(targetPath, { recursive: true, force: true });
|
|
7097
7370
|
},
|
|
7098
7371
|
copyRecursive(from, to) {
|
|
7099
|
-
|
|
7372
|
+
import_node_fs7.default.cpSync(from, to, { recursive: true, force: true, verbatimSymlinks: true });
|
|
7100
7373
|
},
|
|
7101
7374
|
readFileUtf8(filePath) {
|
|
7102
7375
|
try {
|
|
7103
|
-
return
|
|
7376
|
+
return import_node_fs7.default.readFileSync(filePath, "utf8");
|
|
7104
7377
|
} catch (error) {
|
|
7105
7378
|
if (isEnoent3(error)) {
|
|
7106
7379
|
return void 0;
|
|
@@ -7109,36 +7382,36 @@ var realFarmFs = {
|
|
|
7109
7382
|
}
|
|
7110
7383
|
},
|
|
7111
7384
|
writeFileUtf8(filePath, contents) {
|
|
7112
|
-
|
|
7385
|
+
import_node_fs7.default.writeFileSync(filePath, contents, "utf8");
|
|
7113
7386
|
},
|
|
7114
7387
|
mkdirPrivate(dirPath) {
|
|
7115
|
-
|
|
7116
|
-
|
|
7388
|
+
import_node_fs7.default.mkdirSync(dirPath, { recursive: true, mode: OWNER_ONLY_DIR_MODE });
|
|
7389
|
+
import_node_fs7.default.chmodSync(dirPath, OWNER_ONLY_DIR_MODE);
|
|
7117
7390
|
},
|
|
7118
7391
|
writeFilePrivate(filePath, contents) {
|
|
7119
7392
|
const temp = `${filePath}.${String(process.pid)}.tmp`;
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7393
|
+
import_node_fs7.default.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
|
|
7394
|
+
import_node_fs7.default.chmodSync(temp, OWNER_ONLY_FILE_MODE);
|
|
7395
|
+
import_node_fs7.default.renameSync(temp, filePath);
|
|
7123
7396
|
},
|
|
7124
7397
|
appendFilePrivate(filePath, contents) {
|
|
7125
|
-
const descriptor =
|
|
7398
|
+
const descriptor = import_node_fs7.default.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
|
|
7126
7399
|
try {
|
|
7127
|
-
if ((
|
|
7128
|
-
|
|
7400
|
+
if ((import_node_fs7.default.fstatSync(descriptor).mode & PERMISSION_BITS2) !== OWNER_ONLY_FILE_MODE) {
|
|
7401
|
+
import_node_fs7.default.fchmodSync(descriptor, OWNER_ONLY_FILE_MODE);
|
|
7129
7402
|
}
|
|
7130
7403
|
const bytes = Buffer.from(contents, "utf8");
|
|
7131
7404
|
let written = 0;
|
|
7132
7405
|
while (written < bytes.length) {
|
|
7133
|
-
written +=
|
|
7406
|
+
written += import_node_fs7.default.writeSync(descriptor, bytes, written, bytes.length - written);
|
|
7134
7407
|
}
|
|
7135
7408
|
} finally {
|
|
7136
|
-
|
|
7409
|
+
import_node_fs7.default.closeSync(descriptor);
|
|
7137
7410
|
}
|
|
7138
7411
|
},
|
|
7139
7412
|
writeFileExclusive(filePath, contents) {
|
|
7140
7413
|
try {
|
|
7141
|
-
|
|
7414
|
+
import_node_fs7.default.writeFileSync(filePath, contents, { encoding: "utf8", flag: "wx" });
|
|
7142
7415
|
return true;
|
|
7143
7416
|
} catch (error) {
|
|
7144
7417
|
if (isErrorWithCode(error, "EEXIST")) {
|
|
@@ -7149,7 +7422,7 @@ var realFarmFs = {
|
|
|
7149
7422
|
},
|
|
7150
7423
|
hashFile(filePath) {
|
|
7151
7424
|
try {
|
|
7152
|
-
return (0, import_node_crypto9.createHash)("sha256").update(
|
|
7425
|
+
return (0, import_node_crypto9.createHash)("sha256").update(import_node_fs7.default.readFileSync(filePath)).digest("hex");
|
|
7153
7426
|
} catch (error) {
|
|
7154
7427
|
if (isEnoent3(error) || isErrorWithCode(error, "EISDIR")) {
|
|
7155
7428
|
return void 0;
|
|
@@ -7171,7 +7444,7 @@ function realIsProcessAlive(pid) {
|
|
|
7171
7444
|
}
|
|
7172
7445
|
}
|
|
7173
7446
|
function realIsProcessZombie(pid) {
|
|
7174
|
-
const result = (0,
|
|
7447
|
+
const result = (0, import_node_child_process2.spawnSync)("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
|
|
7175
7448
|
return result.status === 0 && result.stdout.trim().startsWith("Z");
|
|
7176
7449
|
}
|
|
7177
7450
|
function realIsProcessRunning(pid) {
|
|
@@ -7179,17 +7452,17 @@ function realIsProcessRunning(pid) {
|
|
|
7179
7452
|
}
|
|
7180
7453
|
var realRunPort = {
|
|
7181
7454
|
run(command, args) {
|
|
7182
|
-
const result = (0,
|
|
7455
|
+
const result = (0, import_node_child_process2.spawnSync)(command, [...args], { encoding: "utf8" });
|
|
7183
7456
|
return { status: result.status, stdout: result.stdout, stderr: result.stderr };
|
|
7184
7457
|
}
|
|
7185
7458
|
};
|
|
7186
7459
|
function expandHome2(filePath) {
|
|
7187
|
-
return filePath.startsWith("~/") ?
|
|
7460
|
+
return filePath.startsWith("~/") ? import_node_path22.default.join(import_node_os3.default.homedir(), filePath.slice(1)) : filePath;
|
|
7188
7461
|
}
|
|
7189
7462
|
var MACOS_GUI_SESSION_MANAGER = "Aqua";
|
|
7190
7463
|
function hasDesktopSession() {
|
|
7191
7464
|
if (process.platform === "darwin") {
|
|
7192
|
-
const result = (0,
|
|
7465
|
+
const result = (0, import_node_child_process2.spawnSync)("launchctl", ["managername"], { encoding: "utf8" });
|
|
7193
7466
|
return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
|
|
7194
7467
|
}
|
|
7195
7468
|
if (process.platform === "win32") {
|
|
@@ -7203,8 +7476,8 @@ var realCredentialPort = {
|
|
|
7203
7476
|
let content;
|
|
7204
7477
|
let stat;
|
|
7205
7478
|
try {
|
|
7206
|
-
stat =
|
|
7207
|
-
content =
|
|
7479
|
+
stat = import_node_fs7.default.statSync(resolved);
|
|
7480
|
+
content = import_node_fs7.default.readFileSync(resolved, "utf8");
|
|
7208
7481
|
} catch (error) {
|
|
7209
7482
|
if (isEnoent3(error)) {
|
|
7210
7483
|
return { found: false };
|
|
@@ -7215,7 +7488,7 @@ var realCredentialPort = {
|
|
|
7215
7488
|
},
|
|
7216
7489
|
runCommand(argv, options) {
|
|
7217
7490
|
const [command, ...args] = argv;
|
|
7218
|
-
const result = (0,
|
|
7491
|
+
const result = (0, import_node_child_process2.spawnSync)(command, args, {
|
|
7219
7492
|
encoding: "utf8",
|
|
7220
7493
|
timeout: options.timeoutMs,
|
|
7221
7494
|
stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
|
|
@@ -7257,17 +7530,17 @@ function spawnDaemonThrough(executable) {
|
|
|
7257
7530
|
return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
|
|
7258
7531
|
}
|
|
7259
7532
|
function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
7260
|
-
|
|
7261
|
-
const logFd =
|
|
7533
|
+
import_node_fs7.default.mkdirSync(import_node_path22.default.dirname(logPath), { recursive: true });
|
|
7534
|
+
const logFd = import_node_fs7.default.openSync(logPath, "a");
|
|
7262
7535
|
try {
|
|
7263
|
-
const child = (0,
|
|
7536
|
+
const child = (0, import_node_child_process2.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
7264
7537
|
child.unref();
|
|
7265
7538
|
if (child.pid === void 0) {
|
|
7266
7539
|
throw new Error(`spawning ${subcommand} returned no pid`);
|
|
7267
7540
|
}
|
|
7268
7541
|
return child.pid;
|
|
7269
7542
|
} finally {
|
|
7270
|
-
|
|
7543
|
+
import_node_fs7.default.closeSync(logFd);
|
|
7271
7544
|
}
|
|
7272
7545
|
}
|
|
7273
7546
|
function spawnHeadroomSupervisor(paths, spawnDaemon) {
|
|
@@ -7285,7 +7558,7 @@ var realHeadroomSocketTrust = {
|
|
|
7285
7558
|
lstat: (target) => {
|
|
7286
7559
|
let stat;
|
|
7287
7560
|
try {
|
|
7288
|
-
stat =
|
|
7561
|
+
stat = import_node_fs7.default.lstatSync(target);
|
|
7289
7562
|
} catch (error) {
|
|
7290
7563
|
if (isEnoent3(error)) {
|
|
7291
7564
|
return void 0;
|
|
@@ -7331,7 +7604,7 @@ var EXECUTE_BITS_MASK = 73;
|
|
|
7331
7604
|
function listVersionsDir(dir) {
|
|
7332
7605
|
let entries;
|
|
7333
7606
|
try {
|
|
7334
|
-
entries =
|
|
7607
|
+
entries = import_node_fs7.default.readdirSync(dir, { withFileTypes: true });
|
|
7335
7608
|
} catch (error) {
|
|
7336
7609
|
if (isEnoent3(error)) {
|
|
7337
7610
|
return [];
|
|
@@ -7339,8 +7612,8 @@ function listVersionsDir(dir) {
|
|
|
7339
7612
|
throw error;
|
|
7340
7613
|
}
|
|
7341
7614
|
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
7342
|
-
const fullPath =
|
|
7343
|
-
const stat =
|
|
7615
|
+
const fullPath = import_node_path22.default.join(dir, entry.name);
|
|
7616
|
+
const stat = import_node_fs7.default.statSync(fullPath);
|
|
7344
7617
|
return {
|
|
7345
7618
|
name: entry.name,
|
|
7346
7619
|
isFile: true,
|
|
@@ -7354,7 +7627,7 @@ function windowsPathExtensions(pathext) {
|
|
|
7354
7627
|
return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
|
|
7355
7628
|
}
|
|
7356
7629
|
function resolveExecutableCandidate(dir, name, env) {
|
|
7357
|
-
const candidate =
|
|
7630
|
+
const candidate = import_node_path22.default.join(dir, name);
|
|
7358
7631
|
if (env.platform === "win32") {
|
|
7359
7632
|
const extensions = windowsPathExtensions(env.pathext);
|
|
7360
7633
|
const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
|
|
@@ -7374,7 +7647,7 @@ function resolveExecutableCandidate(dir, name, env) {
|
|
|
7374
7647
|
}
|
|
7375
7648
|
function realStatFileMode(candidate) {
|
|
7376
7649
|
try {
|
|
7377
|
-
const stat =
|
|
7650
|
+
const stat = import_node_fs7.default.statSync(candidate);
|
|
7378
7651
|
return stat.isFile() ? stat.mode : void 0;
|
|
7379
7652
|
} catch (error) {
|
|
7380
7653
|
if (isEnoent3(error)) {
|
|
@@ -7403,13 +7676,13 @@ function resolveOwnExecutablePath(env) {
|
|
|
7403
7676
|
if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
|
|
7404
7677
|
return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
|
|
7405
7678
|
}
|
|
7406
|
-
const candidate = env.argv1 === void 0 ? env.execPath :
|
|
7407
|
-
const candidateDir =
|
|
7408
|
-
const candidateDirOnPath = env.pathDirs.some((dir) =>
|
|
7679
|
+
const candidate = env.argv1 === void 0 ? env.execPath : import_node_path22.default.resolve(env.cwd, env.argv1);
|
|
7680
|
+
const candidateDir = import_node_path22.default.dirname(candidate);
|
|
7681
|
+
const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path22.default.resolve(dir) === candidateDir);
|
|
7409
7682
|
if (candidateDirOnPath) {
|
|
7410
7683
|
return candidate;
|
|
7411
7684
|
}
|
|
7412
|
-
const viaPath = searchPathForExecutable(env.pathDirs,
|
|
7685
|
+
const viaPath = searchPathForExecutable(env.pathDirs, import_node_path22.default.basename(candidate), env.findExecutableInDir);
|
|
7413
7686
|
return viaPath ?? candidate;
|
|
7414
7687
|
}
|
|
7415
7688
|
function realOwnExecutablePath() {
|
|
@@ -7417,7 +7690,7 @@ function realOwnExecutablePath() {
|
|
|
7417
7690
|
argv1: process.argv[1],
|
|
7418
7691
|
execPath: process.execPath,
|
|
7419
7692
|
cwd: process.cwd(),
|
|
7420
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
7693
|
+
pathDirs: (process.env.PATH ?? "").split(import_node_path22.default.delimiter).filter((dir) => dir !== ""),
|
|
7421
7694
|
findExecutableInDir
|
|
7422
7695
|
});
|
|
7423
7696
|
}
|
|
@@ -7430,14 +7703,14 @@ function realContentSourcePath() {
|
|
|
7430
7703
|
function realResolveClaudeBinary(isOwnBinary) {
|
|
7431
7704
|
return () => discoverClaudeBinary({
|
|
7432
7705
|
listVersionsDir,
|
|
7433
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
7706
|
+
pathDirs: (process.env.PATH ?? "").split(import_node_path22.default.delimiter).filter((dir) => dir !== ""),
|
|
7434
7707
|
findExecutableInDir,
|
|
7435
7708
|
isOwnBinary
|
|
7436
7709
|
});
|
|
7437
7710
|
}
|
|
7438
7711
|
|
|
7439
7712
|
// src/checkReport.ts
|
|
7440
|
-
var
|
|
7713
|
+
var import_node_path23 = __toESM(require("node:path"), 1);
|
|
7441
7714
|
var import_zod10 = require("zod");
|
|
7442
7715
|
|
|
7443
7716
|
// src/cli/bool.ts
|
|
@@ -7607,14 +7880,23 @@ function inspectSettingsExposure(params) {
|
|
|
7607
7880
|
}
|
|
7608
7881
|
return reports;
|
|
7609
7882
|
}
|
|
7610
|
-
function
|
|
7883
|
+
function cachedState(cacheEnv, owner, block) {
|
|
7884
|
+
if (cacheEnv === void 0 || block.cache === void 0) {
|
|
7885
|
+
return void 0;
|
|
7886
|
+
}
|
|
7887
|
+
return describeCachedCredential({ port: cacheEnv.port, platform: cacheEnv.platform, owner, cache: block.cache, nowMs: cacheEnv.now() });
|
|
7888
|
+
}
|
|
7889
|
+
function buildCredentialReport(provider, identity, identityName, cacheEnv) {
|
|
7611
7890
|
const identityCredential = identity?.credential === void 0 ? void 0 : summariseCredential(identity.credential);
|
|
7891
|
+
const identityCached = identity?.credential === void 0 || identityName === void 0 ? void 0 : cachedState(cacheEnv, `identity ${identityName}`, identity.credential);
|
|
7892
|
+
const providerCached = provider?.definition === void 0 ? void 0 : cachedState(cacheEnv, `provider ${provider.name}`, provider.definition.credential);
|
|
7612
7893
|
return {
|
|
7613
7894
|
applies: provider !== void 0 ? "provider" : identityCredential !== void 0 ? "identity" : "stored-login",
|
|
7614
7895
|
...provider === void 0 ? {} : {
|
|
7615
|
-
provider: provider.problem === void 0 ? { name: provider.name, credential: summariseCredential(provider.definition.credential) } : { name: provider.name, problem: provider.problem }
|
|
7896
|
+
provider: provider.problem === void 0 ? { name: provider.name, credential: summariseCredential(provider.definition.credential), ...providerCached === void 0 ? {} : { cached: providerCached } } : { name: provider.name, problem: provider.problem }
|
|
7616
7897
|
},
|
|
7617
|
-
...identityCredential === void 0 ? {} : { identity: identityCredential }
|
|
7898
|
+
...identityCredential === void 0 ? {} : { identity: identityCredential },
|
|
7899
|
+
...identityCached === void 0 ? {} : { identityCached }
|
|
7618
7900
|
};
|
|
7619
7901
|
}
|
|
7620
7902
|
function runCheck(params) {
|
|
@@ -7653,7 +7935,7 @@ function runCheck(params) {
|
|
|
7653
7935
|
ambientCredential,
|
|
7654
7936
|
...keychain === void 0 ? {} : { keychain },
|
|
7655
7937
|
settingsExposure,
|
|
7656
|
-
credential: buildCredentialReport(params.provider, params.identity)
|
|
7938
|
+
credential: buildCredentialReport(params.provider, params.identity, params.identityName, params.credentialCache)
|
|
7657
7939
|
};
|
|
7658
7940
|
}
|
|
7659
7941
|
function formatCheckReport(report) {
|
|
@@ -7691,12 +7973,12 @@ function formatCheckReport(report) {
|
|
|
7691
7973
|
const { credential } = report;
|
|
7692
7974
|
if (credential.provider !== void 0) {
|
|
7693
7975
|
lines.push(
|
|
7694
|
-
` Provider ${credential.provider.name}: ${credential.provider.credential === void 0 ? `unusable: ${credential.provider.problem ?? ""}` : formatCredentialSummary(credential.provider.credential)}`
|
|
7976
|
+
` Provider ${credential.provider.name}: ${credential.provider.credential === void 0 ? `unusable: ${credential.provider.problem ?? ""}` : formatCredentialSummary(credential.provider.credential)}${credential.provider.cached === void 0 ? "" : `; ${formatCachedCredentialState(credential.provider.cached)}`}`
|
|
7695
7977
|
);
|
|
7696
7978
|
}
|
|
7697
7979
|
if (credential.identity !== void 0) {
|
|
7698
7980
|
lines.push(
|
|
7699
|
-
` Identity ${report.identityName ?? "(none)"}: ${formatCredentialSummary(credential.identity)}${credential.applies === "provider" ? " (not used: the provider's credential applies)" : ""}`
|
|
7981
|
+
` Identity ${report.identityName ?? "(none)"}: ${formatCredentialSummary(credential.identity)}${credential.identityCached === void 0 ? "" : `; ${formatCachedCredentialState(credential.identityCached)}`}${credential.applies === "provider" ? " (not used: the provider's credential applies)" : ""}`
|
|
7700
7982
|
);
|
|
7701
7983
|
}
|
|
7702
7984
|
if (credential.applies === "stored-login") {
|
|
@@ -7805,10 +8087,10 @@ function collectCheckReport(params) {
|
|
|
7805
8087
|
}).input;
|
|
7806
8088
|
const providerName = cascadeProviderName(cascade);
|
|
7807
8089
|
const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
|
|
7808
|
-
const farmRoot = identityDecision.name === void 0 ? void 0 :
|
|
8090
|
+
const farmRoot = identityDecision.name === void 0 ? void 0 : import_node_path23.default.join(paths.identitiesDir, identityDecision.name);
|
|
7809
8091
|
const settingsFiles = {
|
|
7810
|
-
"settings.json": realFsPort.readFileUtf8(
|
|
7811
|
-
"settings.local.json": realFsPort.readFileUtf8(
|
|
8092
|
+
"settings.json": realFsPort.readFileUtf8(import_node_path23.default.join(claudeHome, "settings.json")),
|
|
8093
|
+
"settings.local.json": realFsPort.readFileUtf8(import_node_path23.default.join(claudeHome, "settings.local.json"))
|
|
7812
8094
|
};
|
|
7813
8095
|
const report = runCheck({
|
|
7814
8096
|
cwd,
|
|
@@ -7829,6 +8111,7 @@ function collectCheckReport(params) {
|
|
|
7829
8111
|
...loadedIdentity === void 0 ? {} : { identity: loadedIdentity.config },
|
|
7830
8112
|
settingsFiles,
|
|
7831
8113
|
run: realRunPort,
|
|
8114
|
+
credentialCache: realCredentialCacheEnv(paths),
|
|
7832
8115
|
...farmRoot === void 0 ? {} : { farmRoot },
|
|
7833
8116
|
platform: process.platform,
|
|
7834
8117
|
...provider === void 0 ? {} : { provider }
|
|
@@ -7837,8 +8120,8 @@ function collectCheckReport(params) {
|
|
|
7837
8120
|
}
|
|
7838
8121
|
|
|
7839
8122
|
// src/claudeShim.ts
|
|
7840
|
-
var
|
|
7841
|
-
var
|
|
8123
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
8124
|
+
var import_node_path24 = __toESM(require("node:path"), 1);
|
|
7842
8125
|
var import_zod11 = require("zod");
|
|
7843
8126
|
var ClaudeShimStateSchema = import_zod11.z.strictObject({
|
|
7844
8127
|
targetPath: import_zod11.z.string().min(1),
|
|
@@ -7850,10 +8133,10 @@ function commandFilename(ownExecutablePath, commandName) {
|
|
|
7850
8133
|
}
|
|
7851
8134
|
function resolveOwnBinaryCheck(paths, contentSourcePath) {
|
|
7852
8135
|
const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
7853
|
-
const recordedTarget = state === void 0 ? void 0 :
|
|
8136
|
+
const recordedTarget = state === void 0 ? void 0 : import_node_path24.default.resolve(state.targetPath);
|
|
7854
8137
|
let ownStat;
|
|
7855
8138
|
return (candidate) => {
|
|
7856
|
-
if (recordedTarget !== void 0 &&
|
|
8139
|
+
if (recordedTarget !== void 0 && import_node_path24.default.resolve(candidate) === recordedTarget) {
|
|
7857
8140
|
return true;
|
|
7858
8141
|
}
|
|
7859
8142
|
ownStat ??= statOrUndefined(contentSourcePath);
|
|
@@ -7867,7 +8150,7 @@ function isEnoent4(error) {
|
|
|
7867
8150
|
}
|
|
7868
8151
|
function statOrUndefined(target) {
|
|
7869
8152
|
try {
|
|
7870
|
-
return
|
|
8153
|
+
return import_node_fs8.default.statSync(target);
|
|
7871
8154
|
} catch (error) {
|
|
7872
8155
|
if (isEnoent4(error)) {
|
|
7873
8156
|
return void 0;
|
|
@@ -7875,22 +8158,22 @@ function statOrUndefined(target) {
|
|
|
7875
8158
|
throw error;
|
|
7876
8159
|
}
|
|
7877
8160
|
}
|
|
7878
|
-
var nodeLinkFs = { link:
|
|
8161
|
+
var nodeLinkFs = { link: import_node_fs8.default.linkSync, copyFile: import_node_fs8.default.copyFileSync, chmod: import_node_fs8.default.chmodSync };
|
|
7879
8162
|
function findPathShadow(params) {
|
|
7880
|
-
const resolvedTargetDir =
|
|
8163
|
+
const resolvedTargetDir = import_node_path24.default.resolve(params.targetDir);
|
|
7881
8164
|
for (const dir of params.pathDirs) {
|
|
7882
8165
|
const found = params.findExecutableInDir(dir, params.targetFilename);
|
|
7883
8166
|
if (found === void 0) {
|
|
7884
8167
|
continue;
|
|
7885
8168
|
}
|
|
7886
|
-
return
|
|
8169
|
+
return import_node_path24.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
|
|
7887
8170
|
}
|
|
7888
|
-
return params.pathDirs.some((dir) =>
|
|
8171
|
+
return params.pathDirs.some((dir) => import_node_path24.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
|
|
7889
8172
|
}
|
|
7890
8173
|
|
|
7891
8174
|
// src/doctorReport.ts
|
|
7892
|
-
var
|
|
7893
|
-
var
|
|
8175
|
+
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
8176
|
+
var import_node_path25 = __toESM(require("node:path"), 1);
|
|
7894
8177
|
function refinePathShadow(status, ownExecutablePath, realpath) {
|
|
7895
8178
|
if (status.status !== "shadowed") {
|
|
7896
8179
|
return status;
|
|
@@ -7914,7 +8197,7 @@ function validateJson(schema, input) {
|
|
|
7914
8197
|
return { ok: true, data: result.data };
|
|
7915
8198
|
}
|
|
7916
8199
|
function pushPathResolution(push, resolution) {
|
|
7917
|
-
const ownDir =
|
|
8200
|
+
const ownDir = import_node_path25.default.dirname(resolution.ownExecutablePath);
|
|
7918
8201
|
switch (resolution.agentShim.status) {
|
|
7919
8202
|
case "ok":
|
|
7920
8203
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -7956,7 +8239,14 @@ function pushPathResolution(push, resolution) {
|
|
|
7956
8239
|
break;
|
|
7957
8240
|
}
|
|
7958
8241
|
}
|
|
7959
|
-
function
|
|
8242
|
+
function cacheClause(cacheEnv, owner, block) {
|
|
8243
|
+
if (cacheEnv === void 0 || block.cache === void 0) {
|
|
8244
|
+
return { text: "", unreadable: false };
|
|
8245
|
+
}
|
|
8246
|
+
const state = describeCachedCredential({ port: cacheEnv.port, platform: cacheEnv.platform, owner, cache: block.cache, nowMs: cacheEnv.now() });
|
|
8247
|
+
return { text: `; ${formatCachedCredentialState(state)}`, unreadable: state.status === "unreadable" };
|
|
8248
|
+
}
|
|
8249
|
+
function pushProvider(push, entry, cacheEnv) {
|
|
7960
8250
|
if (entry.raw === void 0) {
|
|
7961
8251
|
push("provider", "fail", `${entry.path} is missing.`, entry.name);
|
|
7962
8252
|
return;
|
|
@@ -7978,18 +8268,19 @@ function pushProvider(push, entry) {
|
|
|
7978
8268
|
push("provider", "fail", new ConfigValidationError(entry.path, validated.error.issues).message, entry.name);
|
|
7979
8269
|
return;
|
|
7980
8270
|
}
|
|
7981
|
-
|
|
8271
|
+
const cache = cacheClause(cacheEnv, `provider ${entry.name}`, validated.data.credential);
|
|
8272
|
+
push("provider", cache.unreadable ? "fail" : "pass", `${entry.name} is valid (${describeProviderEndpoint(validated.data)}, credential ${describeCredential(validated.data.credential)})${cache.text}.`, entry.name);
|
|
7982
8273
|
}
|
|
7983
8274
|
function pushLegacyName(push, params) {
|
|
7984
8275
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
7985
|
-
if (legacyVariables.length === 0 &&
|
|
8276
|
+
if (legacyVariables.length === 0 && import_node_path25.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
7986
8277
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
7987
8278
|
return;
|
|
7988
8279
|
}
|
|
7989
8280
|
for (const name of legacyVariables) {
|
|
7990
8281
|
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);
|
|
7991
8282
|
}
|
|
7992
|
-
if (
|
|
8283
|
+
if (import_node_path25.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
7993
8284
|
push(
|
|
7994
8285
|
"legacy-name",
|
|
7995
8286
|
"warn",
|
|
@@ -8071,10 +8362,11 @@ function runDoctor(params) {
|
|
|
8071
8362
|
);
|
|
8072
8363
|
} else {
|
|
8073
8364
|
const credential = validated.data.credential;
|
|
8365
|
+
const cache = credential === void 0 ? { text: "", unreadable: false } : cacheClause(params.credentialCache, `identity ${entry.name}`, credential);
|
|
8074
8366
|
push(
|
|
8075
8367
|
"identity",
|
|
8076
|
-
"pass",
|
|
8077
|
-
`${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}.`,
|
|
8368
|
+
cache.unreadable ? "fail" : "pass",
|
|
8369
|
+
`${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}${cache.text}.`,
|
|
8078
8370
|
entry.name
|
|
8079
8371
|
);
|
|
8080
8372
|
}
|
|
@@ -8094,7 +8386,7 @@ function runDoctor(params) {
|
|
|
8094
8386
|
return poolName === void 0 ? validIdentityNames.has(selector) : poolName in pools;
|
|
8095
8387
|
};
|
|
8096
8388
|
for (const entry of params.providers) {
|
|
8097
|
-
pushProvider(push, entry);
|
|
8389
|
+
pushProvider(push, entry, params.credentialCache);
|
|
8098
8390
|
}
|
|
8099
8391
|
if (params.platform !== "darwin" || params.run === void 0) {
|
|
8100
8392
|
push("keychain", "pass", "Skipped (not macOS).");
|
|
@@ -8288,27 +8580,27 @@ function formatDoctorReport(report) {
|
|
|
8288
8580
|
}
|
|
8289
8581
|
function realpathOrSelf(target) {
|
|
8290
8582
|
try {
|
|
8291
|
-
return
|
|
8583
|
+
return import_node_fs9.default.realpathSync(target);
|
|
8292
8584
|
} catch {
|
|
8293
8585
|
return target;
|
|
8294
8586
|
}
|
|
8295
8587
|
}
|
|
8296
8588
|
function collectDoctorReport(params) {
|
|
8297
8589
|
const { paths } = params;
|
|
8298
|
-
const identityNames =
|
|
8590
|
+
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() : [];
|
|
8299
8591
|
const identities = identityNames.map((name) => {
|
|
8300
|
-
const farmRoot =
|
|
8301
|
-
const identityPath =
|
|
8592
|
+
const farmRoot = import_node_path25.default.join(paths.identitiesDir, name);
|
|
8593
|
+
const identityPath = import_node_path25.default.join(farmRoot, "identity.json");
|
|
8302
8594
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
|
|
8303
8595
|
});
|
|
8304
|
-
const profileNames =
|
|
8596
|
+
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() : [];
|
|
8305
8597
|
const configProfiles = profileNames.map((name) => {
|
|
8306
|
-
const profilePath =
|
|
8598
|
+
const profilePath = import_node_path25.default.join(paths.configProfilesDir, `${name}.json`);
|
|
8307
8599
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
8308
8600
|
});
|
|
8309
|
-
const providerNames =
|
|
8601
|
+
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() : [];
|
|
8310
8602
|
const providers = providerNames.map((name) => {
|
|
8311
|
-
const providerPath =
|
|
8603
|
+
const providerPath = import_node_path25.default.join(paths.providersDir, `${name}.json`);
|
|
8312
8604
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
8313
8605
|
});
|
|
8314
8606
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -8320,12 +8612,12 @@ function collectDoctorReport(params) {
|
|
|
8320
8612
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
8321
8613
|
}
|
|
8322
8614
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
8323
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
8615
|
+
const pathDirs = (params.env.PATH ?? "").split(import_node_path25.default.delimiter).filter((dir) => dir !== "");
|
|
8324
8616
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
8325
8617
|
findPathShadow({
|
|
8326
8618
|
pathDirs,
|
|
8327
|
-
targetDir:
|
|
8328
|
-
targetFilename:
|
|
8619
|
+
targetDir: import_node_path25.default.dirname(shimState.targetPath),
|
|
8620
|
+
targetFilename: import_node_path25.default.basename(shimState.targetPath),
|
|
8329
8621
|
findExecutableInDir
|
|
8330
8622
|
}),
|
|
8331
8623
|
shimState.targetPath,
|
|
@@ -8333,6 +8625,7 @@ function collectDoctorReport(params) {
|
|
|
8333
8625
|
);
|
|
8334
8626
|
const report = runDoctor({
|
|
8335
8627
|
env: params.env,
|
|
8628
|
+
credentialCache: realCredentialCacheEnv(paths),
|
|
8336
8629
|
identities,
|
|
8337
8630
|
configProfiles,
|
|
8338
8631
|
providers,
|
|
@@ -8341,14 +8634,14 @@ function collectDoctorReport(params) {
|
|
|
8341
8634
|
categoriesLocal: { path: paths.categoriesLocalFile, raw: realFsPort.readFileUtf8(paths.categoriesLocalFile) },
|
|
8342
8635
|
activeIdentity: { path: paths.activeIdentityFile, raw: realFsPort.readFileUtf8(paths.activeIdentityFile) },
|
|
8343
8636
|
binaryDiscovery,
|
|
8344
|
-
claudeShim: { state: shimState, targetExists: shimState !== void 0 &&
|
|
8637
|
+
claudeShim: { state: shimState, targetExists: shimState !== void 0 && import_node_fs9.default.existsSync(shimState.targetPath) },
|
|
8345
8638
|
rootPath: paths.root,
|
|
8346
8639
|
pathResolution: {
|
|
8347
8640
|
ownExecutablePath,
|
|
8348
8641
|
agentShim: refinePathShadow(
|
|
8349
8642
|
findPathShadow({
|
|
8350
8643
|
pathDirs,
|
|
8351
|
-
targetDir:
|
|
8644
|
+
targetDir: import_node_path25.default.dirname(ownExecutablePath),
|
|
8352
8645
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
8353
8646
|
findExecutableInDir
|
|
8354
8647
|
}),
|
|
@@ -8369,7 +8662,7 @@ function collectDoctorReport(params) {
|
|
|
8369
8662
|
|
|
8370
8663
|
// src/launcher.ts
|
|
8371
8664
|
var import_node_crypto10 = require("node:crypto");
|
|
8372
|
-
var
|
|
8665
|
+
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
8373
8666
|
|
|
8374
8667
|
// src/launcher/argv.ts
|
|
8375
8668
|
var ConflictingIdentityError = class extends UsageError {
|
|
@@ -8621,7 +8914,7 @@ function buildCliOverride(params) {
|
|
|
8621
8914
|
}
|
|
8622
8915
|
|
|
8623
8916
|
// src/launcher/flags.ts
|
|
8624
|
-
var
|
|
8917
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
8625
8918
|
|
|
8626
8919
|
// src/headroom/headers.ts
|
|
8627
8920
|
function mergeAnthropicCustomHeaders(existing, additions) {
|
|
@@ -8691,7 +8984,7 @@ function buildEnv(params) {
|
|
|
8691
8984
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
8692
8985
|
let providerCustomHeaders;
|
|
8693
8986
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
8694
|
-
env.CLAUDE_CONFIG_DIR =
|
|
8987
|
+
env.CLAUDE_CONFIG_DIR = import_node_path26.default.join(params.identitiesDir, params.resolvedIdentityName);
|
|
8695
8988
|
}
|
|
8696
8989
|
if (params.provider !== void 0) {
|
|
8697
8990
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -8852,7 +9145,7 @@ function prepareLaunch(params) {
|
|
|
8852
9145
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
8853
9146
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
8854
9147
|
});
|
|
8855
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
9148
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path27.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
8856
9149
|
log.error(
|
|
8857
9150
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
8858
9151
|
);
|
|
@@ -9025,84 +9318,6 @@ function prepareLaunch(params) {
|
|
|
9025
9318
|
var import_node_os5 = __toESM(require("node:os"), 1);
|
|
9026
9319
|
var import_node_crypto12 = require("node:crypto");
|
|
9027
9320
|
|
|
9028
|
-
// src/realCredentialCache.ts
|
|
9029
|
-
var import_node_child_process2 = require("node:child_process");
|
|
9030
|
-
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
9031
|
-
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
9032
|
-
var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
9033
|
-
var CACHE_DIR_MODE = 448;
|
|
9034
|
-
var CACHE_FILE_MODE = 384;
|
|
9035
|
-
function cacheFileNameFor(owner) {
|
|
9036
|
-
return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
|
|
9037
|
-
}
|
|
9038
|
-
function parseEntry(raw) {
|
|
9039
|
-
let json;
|
|
9040
|
-
try {
|
|
9041
|
-
json = JSON.parse(raw);
|
|
9042
|
-
} catch {
|
|
9043
|
-
return void 0;
|
|
9044
|
-
}
|
|
9045
|
-
const parsed = CachedCredentialSchema.safeParse(json);
|
|
9046
|
-
return parsed.success ? parsed.data : void 0;
|
|
9047
|
-
}
|
|
9048
|
-
function requireKeychain() {
|
|
9049
|
-
if (process.platform !== "darwin") {
|
|
9050
|
-
throw new Error("the keychain credential store needs macOS; use --credential-cache-store file");
|
|
9051
|
-
}
|
|
9052
|
-
}
|
|
9053
|
-
function security(args, stdin) {
|
|
9054
|
-
const result = (0, import_node_child_process2.spawnSync)("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
|
|
9055
|
-
return { status: result.status, stdout: result.stdout };
|
|
9056
|
-
}
|
|
9057
|
-
function createRealCredentialCache(root) {
|
|
9058
|
-
const dir = import_node_path27.default.join(root, "credential-cache");
|
|
9059
|
-
const filePath = (owner) => import_node_path27.default.join(dir, cacheFileNameFor(owner));
|
|
9060
|
-
return {
|
|
9061
|
-
read(store, owner) {
|
|
9062
|
-
if (store === "file") {
|
|
9063
|
-
try {
|
|
9064
|
-
return parseEntry(import_node_fs9.default.readFileSync(filePath(owner), "utf8"));
|
|
9065
|
-
} catch {
|
|
9066
|
-
return void 0;
|
|
9067
|
-
}
|
|
9068
|
-
}
|
|
9069
|
-
requireKeychain();
|
|
9070
|
-
const result = security(["find-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner, "-w"]);
|
|
9071
|
-
return result.status === 0 ? parseEntry(Buffer.from(result.stdout.trim(), "base64").toString("utf8")) : void 0;
|
|
9072
|
-
},
|
|
9073
|
-
write(store, owner, entry) {
|
|
9074
|
-
const serialised = JSON.stringify(entry);
|
|
9075
|
-
if (store === "file") {
|
|
9076
|
-
import_node_fs9.default.mkdirSync(dir, { recursive: true, mode: CACHE_DIR_MODE });
|
|
9077
|
-
import_node_fs9.default.chmodSync(dir, CACHE_DIR_MODE);
|
|
9078
|
-
const target = filePath(owner);
|
|
9079
|
-
const temp = `${target}.${String(process.pid)}.tmp`;
|
|
9080
|
-
import_node_fs9.default.writeFileSync(temp, serialised, { mode: CACHE_FILE_MODE });
|
|
9081
|
-
import_node_fs9.default.renameSync(temp, target);
|
|
9082
|
-
return;
|
|
9083
|
-
}
|
|
9084
|
-
requireKeychain();
|
|
9085
|
-
const encoded = Buffer.from(serialised, "utf8").toString("base64");
|
|
9086
|
-
const result = security(["-i"], `add-generic-password -U -s ${KEYCHAIN_CACHE_SERVICE} -a ${JSON.stringify(owner)} -w ${encoded}
|
|
9087
|
-
`);
|
|
9088
|
-
if (result.status !== 0) {
|
|
9089
|
-
throw new Error(`could not write the keychain credential cache for ${owner}`);
|
|
9090
|
-
}
|
|
9091
|
-
},
|
|
9092
|
-
remove(store, owner) {
|
|
9093
|
-
if (store === "file") {
|
|
9094
|
-
import_node_fs9.default.rmSync(filePath(owner), { force: true });
|
|
9095
|
-
return;
|
|
9096
|
-
}
|
|
9097
|
-
requireKeychain();
|
|
9098
|
-
security(["delete-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner]);
|
|
9099
|
-
}
|
|
9100
|
-
};
|
|
9101
|
-
}
|
|
9102
|
-
function realCredentialCacheEnv(paths) {
|
|
9103
|
-
return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
|
|
9104
|
-
}
|
|
9105
|
-
|
|
9106
9321
|
// src/frontdoor/realFrontDoorPort.ts
|
|
9107
9322
|
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
9108
9323
|
|
|
@@ -9379,6 +9594,7 @@ function prepareClaudeLaunch(options) {
|
|
|
9379
9594
|
ProviderSchema,
|
|
9380
9595
|
RC_IDLE_EXPIRY_MS,
|
|
9381
9596
|
RC_PENDING_DEADLINE_MS,
|
|
9597
|
+
RC_PERMISSION_MODES,
|
|
9382
9598
|
RC_REQUEST_PARSE_CAP_BYTES,
|
|
9383
9599
|
RC_SESSIONS_PATH_PREFIX,
|
|
9384
9600
|
ROUTED_PATH_PREFIX,
|
|
@@ -9395,6 +9611,9 @@ function prepareClaudeLaunch(options) {
|
|
|
9395
9611
|
buildLayoutPaths,
|
|
9396
9612
|
buildRcControlResponsePayload,
|
|
9397
9613
|
buildRcEventWriteBody,
|
|
9614
|
+
buildRcInterruptPayload,
|
|
9615
|
+
buildRcSetModelPayload,
|
|
9616
|
+
buildRcSetPermissionModePayload,
|
|
9398
9617
|
buildRcUserMessagePayload,
|
|
9399
9618
|
carryOver,
|
|
9400
9619
|
checkReportHasWarnings,
|
|
@@ -9419,8 +9638,10 @@ function prepareClaudeLaunch(options) {
|
|
|
9419
9638
|
generateCa,
|
|
9420
9639
|
identityExists,
|
|
9421
9640
|
injectRcUserMessage,
|
|
9641
|
+
interruptRcSession,
|
|
9422
9642
|
isIdentityDirectoryName,
|
|
9423
9643
|
isInterceptedHost,
|
|
9644
|
+
isRcPermissionMode,
|
|
9424
9645
|
listDirectoryRules,
|
|
9425
9646
|
listIdentities,
|
|
9426
9647
|
listProfiles,
|
|
@@ -9476,6 +9697,8 @@ function prepareClaudeLaunch(options) {
|
|
|
9476
9697
|
setProfileEntries,
|
|
9477
9698
|
setProfileLaunchFlags,
|
|
9478
9699
|
setProfileMetadata,
|
|
9700
|
+
setRcSessionModel,
|
|
9701
|
+
setRcSessionPermissionMode,
|
|
9479
9702
|
snapshotPath,
|
|
9480
9703
|
startConnectServer,
|
|
9481
9704
|
topLevelNames,
|