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/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/realPorts.ts
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 import_node_path21 = __toESM(require("node:path"), 1);
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 import_node_path20 = __toESM(require("node:path"), 1);
7242
+ var import_node_path21 = __toESM(require("node:path"), 1);
6970
7243
  function defaultVersionsDir() {
6971
- return import_node_path20.default.join(import_node_os2.default.homedir(), ".local", "share", "claude", "versions");
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: import_node_path20.default.join(versionsDir, highestVersion),
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 import_node_fs6.default.readFileSync(filePath, "utf8");
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 import_node_fs6.default.readdirSync(dirPath);
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 = import_node_fs6.default.lstatSync(filePath);
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 import_node_fs6.default.readdirSync(dirPath);
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
- import_node_fs6.default.mkdirSync(dirPath, { recursive: true });
7360
+ import_node_fs7.default.mkdirSync(dirPath, { recursive: true });
7088
7361
  },
7089
7362
  symlink(target, linkPath) {
7090
- import_node_fs6.default.symlinkSync(target, linkPath);
7363
+ import_node_fs7.default.symlinkSync(target, linkPath);
7091
7364
  },
7092
7365
  rename(from, to) {
7093
- import_node_fs6.default.renameSync(from, to);
7366
+ import_node_fs7.default.renameSync(from, to);
7094
7367
  },
7095
7368
  removeRecursive(targetPath) {
7096
- import_node_fs6.default.rmSync(targetPath, { recursive: true, force: true });
7369
+ import_node_fs7.default.rmSync(targetPath, { recursive: true, force: true });
7097
7370
  },
7098
7371
  copyRecursive(from, to) {
7099
- import_node_fs6.default.cpSync(from, to, { recursive: true, force: true, verbatimSymlinks: true });
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 import_node_fs6.default.readFileSync(filePath, "utf8");
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
- import_node_fs6.default.writeFileSync(filePath, contents, "utf8");
7385
+ import_node_fs7.default.writeFileSync(filePath, contents, "utf8");
7113
7386
  },
7114
7387
  mkdirPrivate(dirPath) {
7115
- import_node_fs6.default.mkdirSync(dirPath, { recursive: true, mode: OWNER_ONLY_DIR_MODE });
7116
- import_node_fs6.default.chmodSync(dirPath, OWNER_ONLY_DIR_MODE);
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
- import_node_fs6.default.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
7121
- import_node_fs6.default.chmodSync(temp, OWNER_ONLY_FILE_MODE);
7122
- import_node_fs6.default.renameSync(temp, filePath);
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 = import_node_fs6.default.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
7398
+ const descriptor = import_node_fs7.default.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
7126
7399
  try {
7127
- if ((import_node_fs6.default.fstatSync(descriptor).mode & PERMISSION_BITS2) !== OWNER_ONLY_FILE_MODE) {
7128
- import_node_fs6.default.fchmodSync(descriptor, OWNER_ONLY_FILE_MODE);
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 += import_node_fs6.default.writeSync(descriptor, bytes, written, bytes.length - written);
7406
+ written += import_node_fs7.default.writeSync(descriptor, bytes, written, bytes.length - written);
7134
7407
  }
7135
7408
  } finally {
7136
- import_node_fs6.default.closeSync(descriptor);
7409
+ import_node_fs7.default.closeSync(descriptor);
7137
7410
  }
7138
7411
  },
7139
7412
  writeFileExclusive(filePath, contents) {
7140
7413
  try {
7141
- import_node_fs6.default.writeFileSync(filePath, contents, { encoding: "utf8", flag: "wx" });
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(import_node_fs6.default.readFileSync(filePath)).digest("hex");
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, import_node_child_process.spawnSync)("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
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, import_node_child_process.spawnSync)(command, [...args], { encoding: "utf8" });
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("~/") ? import_node_path21.default.join(import_node_os3.default.homedir(), filePath.slice(1)) : filePath;
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, import_node_child_process.spawnSync)("launchctl", ["managername"], { encoding: "utf8" });
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 = import_node_fs6.default.statSync(resolved);
7207
- content = import_node_fs6.default.readFileSync(resolved, "utf8");
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, import_node_child_process.spawnSync)(command, args, {
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
- import_node_fs6.default.mkdirSync(import_node_path21.default.dirname(logPath), { recursive: true });
7261
- const logFd = import_node_fs6.default.openSync(logPath, "a");
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, import_node_child_process.spawn)(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
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
- import_node_fs6.default.closeSync(logFd);
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 = import_node_fs6.default.lstatSync(target);
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 = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
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 = import_node_path21.default.join(dir, entry.name);
7343
- const stat = import_node_fs6.default.statSync(fullPath);
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 = import_node_path21.default.join(dir, name);
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 = import_node_fs6.default.statSync(candidate);
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 : import_node_path21.default.resolve(env.cwd, env.argv1);
7407
- const candidateDir = import_node_path21.default.dirname(candidate);
7408
- const candidateDirOnPath = env.pathDirs.some((dir) => import_node_path21.default.resolve(dir) === candidateDir);
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, import_node_path21.default.basename(candidate), env.findExecutableInDir);
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(import_node_path21.default.delimiter).filter((dir) => dir !== ""),
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(import_node_path21.default.delimiter).filter((dir) => dir !== ""),
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 import_node_path22 = __toESM(require("node:path"), 1);
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 buildCredentialReport(provider, identity) {
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 : import_node_path22.default.join(paths.identitiesDir, identityDecision.name);
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(import_node_path22.default.join(claudeHome, "settings.json")),
7811
- "settings.local.json": realFsPort.readFileUtf8(import_node_path22.default.join(claudeHome, "settings.local.json"))
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 import_node_fs7 = __toESM(require("node:fs"), 1);
7841
- var import_node_path23 = __toESM(require("node:path"), 1);
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 : import_node_path23.default.resolve(state.targetPath);
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 && import_node_path23.default.resolve(candidate) === recordedTarget) {
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 import_node_fs7.default.statSync(target);
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: import_node_fs7.default.linkSync, copyFile: import_node_fs7.default.copyFileSync, chmod: import_node_fs7.default.chmodSync };
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 = import_node_path23.default.resolve(params.targetDir);
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 import_node_path23.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
8169
+ return import_node_path24.default.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
7887
8170
  }
7888
- return params.pathDirs.some((dir) => import_node_path23.default.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
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 import_node_fs8 = __toESM(require("node:fs"), 1);
7893
- var import_node_path24 = __toESM(require("node:path"), 1);
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 = import_node_path24.default.dirname(resolution.ownExecutablePath);
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 pushProvider(push, entry) {
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
- push("provider", "pass", `${entry.name} is valid (${describeProviderEndpoint(validated.data)}, credential ${describeCredential(validated.data.credential)}).`, entry.name);
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 && import_node_path24.default.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
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 (import_node_path24.default.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
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 import_node_fs8.default.realpathSync(target);
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 = import_node_fs8.default.existsSync(paths.identitiesDir) ? import_node_fs8.default.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
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 = import_node_path24.default.join(paths.identitiesDir, name);
8301
- const identityPath = import_node_path24.default.join(farmRoot, "identity.json");
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 = import_node_fs8.default.existsSync(paths.configProfilesDir) ? import_node_fs8.default.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
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 = import_node_path24.default.join(paths.configProfilesDir, `${name}.json`);
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 = import_node_fs8.default.existsSync(paths.providersDir) ? import_node_fs8.default.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
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 = import_node_path24.default.join(paths.providersDir, `${name}.json`);
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(import_node_path24.default.delimiter).filter((dir) => dir !== "");
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: import_node_path24.default.dirname(shimState.targetPath),
8328
- targetFilename: import_node_path24.default.basename(shimState.targetPath),
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 && import_node_fs8.default.existsSync(shimState.targetPath) },
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: import_node_path24.default.dirname(ownExecutablePath),
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 import_node_path26 = __toESM(require("node:path"), 1);
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 import_node_path25 = __toESM(require("node:path"), 1);
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 = import_node_path25.default.join(params.identitiesDir, params.resolvedIdentityName);
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(import_node_path26.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
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,