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.mjs
CHANGED
|
@@ -3886,6 +3886,19 @@ function buildRcControlResponsePayload(requestId, decision) {
|
|
|
3886
3886
|
const result = decision.approve ? { behavior: "allow" } : { behavior: "deny", message: decision.message ?? "" };
|
|
3887
3887
|
return { type: "control_response", response: { subtype: "success", request_id: requestId, response: result } };
|
|
3888
3888
|
}
|
|
3889
|
+
var RC_PERMISSION_MODES = ["default", "acceptEdits", "bypassPermissions", "plan", "dontAsk", "auto"];
|
|
3890
|
+
function isRcPermissionMode(value) {
|
|
3891
|
+
return RC_PERMISSION_MODES.some((mode) => mode === value);
|
|
3892
|
+
}
|
|
3893
|
+
function buildRcInterruptPayload(requestId) {
|
|
3894
|
+
return { type: "control_request", request_id: requestId, request: { subtype: "interrupt" } };
|
|
3895
|
+
}
|
|
3896
|
+
function buildRcSetModelPayload(requestId, model) {
|
|
3897
|
+
return { type: "control_request", request_id: requestId, request: { subtype: "set_model", model } };
|
|
3898
|
+
}
|
|
3899
|
+
function buildRcSetPermissionModePayload(requestId, mode) {
|
|
3900
|
+
return { type: "control_request", request_id: requestId, request: { subtype: "set_permission_mode", mode } };
|
|
3901
|
+
}
|
|
3889
3902
|
async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
3890
3903
|
const credential = deps.credentialOf(sessionId);
|
|
3891
3904
|
if (credential === void 0) {
|
|
@@ -3910,9 +3923,64 @@ async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
|
3910
3923
|
}
|
|
3911
3924
|
return result;
|
|
3912
3925
|
}
|
|
3926
|
+
async function interruptRcSession(deps, sessionId) {
|
|
3927
|
+
const credential = deps.credentialOf(sessionId);
|
|
3928
|
+
if (credential === void 0) {
|
|
3929
|
+
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)` };
|
|
3930
|
+
}
|
|
3931
|
+
if (credential.authorization === void 0) {
|
|
3932
|
+
return noOAuthCredentialResult(sessionId);
|
|
3933
|
+
}
|
|
3934
|
+
const body = JSON.stringify(buildRcEventWriteBody(buildRcInterruptPayload(deps.newUuid())));
|
|
3935
|
+
let answer;
|
|
3936
|
+
try {
|
|
3937
|
+
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
3938
|
+
} catch (error) {
|
|
3939
|
+
return { ok: false, message: `the door could not reach the API host to interrupt session ${sessionId}: ${error instanceof Error ? error.message : String(error)}` };
|
|
3940
|
+
}
|
|
3941
|
+
return rcEventWriteResultFromAnswer(answer);
|
|
3942
|
+
}
|
|
3943
|
+
async function setRcSessionModel(deps, sessionId, model) {
|
|
3944
|
+
if (model === "") {
|
|
3945
|
+
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" };
|
|
3946
|
+
}
|
|
3947
|
+
const credential = deps.credentialOf(sessionId);
|
|
3948
|
+
if (credential === void 0) {
|
|
3949
|
+
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)` };
|
|
3950
|
+
}
|
|
3951
|
+
if (credential.authorization === void 0) {
|
|
3952
|
+
return noOAuthCredentialResult(sessionId);
|
|
3953
|
+
}
|
|
3954
|
+
const body = JSON.stringify(buildRcEventWriteBody(buildRcSetModelPayload(deps.newUuid(), model)));
|
|
3955
|
+
let answer;
|
|
3956
|
+
try {
|
|
3957
|
+
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
3958
|
+
} catch (error) {
|
|
3959
|
+
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)}` };
|
|
3960
|
+
}
|
|
3961
|
+
return rcEventWriteResultFromAnswer(answer);
|
|
3962
|
+
}
|
|
3963
|
+
async function setRcSessionPermissionMode(deps, sessionId, mode) {
|
|
3964
|
+
const credential = deps.credentialOf(sessionId);
|
|
3965
|
+
if (credential === void 0) {
|
|
3966
|
+
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)` };
|
|
3967
|
+
}
|
|
3968
|
+
if (credential.authorization === void 0) {
|
|
3969
|
+
return noOAuthCredentialResult(sessionId);
|
|
3970
|
+
}
|
|
3971
|
+
const body = JSON.stringify(buildRcEventWriteBody(buildRcSetPermissionModePayload(deps.newUuid(), mode)));
|
|
3972
|
+
let answer;
|
|
3973
|
+
try {
|
|
3974
|
+
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
3975
|
+
} catch (error) {
|
|
3976
|
+
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)}` };
|
|
3977
|
+
}
|
|
3978
|
+
return rcEventWriteResultFromAnswer(answer);
|
|
3979
|
+
}
|
|
3913
3980
|
|
|
3914
3981
|
// src/frontdoor/rcControl.ts
|
|
3915
3982
|
import * as https2 from "node:https";
|
|
3983
|
+
var RC_PERMISSION_MODE_LIST = RC_PERMISSION_MODES.join(", ");
|
|
3916
3984
|
var CONTROL_PATH_PREFIX = "/__agent-shim/rc";
|
|
3917
3985
|
var CONTROL_BODY_CAP_BYTES = 10485760;
|
|
3918
3986
|
function answerJson(response, status, body) {
|
|
@@ -3947,6 +4015,9 @@ function createRcControlHandler(deps) {
|
|
|
3947
4015
|
const pendingPath = `${CONTROL_PATH_PREFIX}/pending`;
|
|
3948
4016
|
const injectPath = `${CONTROL_PATH_PREFIX}/inject`;
|
|
3949
4017
|
const answerPath = `${CONTROL_PATH_PREFIX}/answer`;
|
|
4018
|
+
const interruptPath = `${CONTROL_PATH_PREFIX}/interrupt`;
|
|
4019
|
+
const setModelPath = `${CONTROL_PATH_PREFIX}/set-model`;
|
|
4020
|
+
const setPermissionModePath = `${CONTROL_PATH_PREFIX}/set-permission-mode`;
|
|
3950
4021
|
return (request4, response) => {
|
|
3951
4022
|
const presented = request4.headers.authorization;
|
|
3952
4023
|
const bearerPrefix = "bearer ".length;
|
|
@@ -4031,6 +4102,78 @@ function createRcControlHandler(deps) {
|
|
|
4031
4102
|
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4032
4103
|
return;
|
|
4033
4104
|
}
|
|
4105
|
+
if (url.pathname === interruptPath) {
|
|
4106
|
+
if (request4.method !== "POST") {
|
|
4107
|
+
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: "the interrupt operation is a POST" });
|
|
4108
|
+
return;
|
|
4109
|
+
}
|
|
4110
|
+
let parsed;
|
|
4111
|
+
try {
|
|
4112
|
+
parsed = JSON.parse(await readBody(request4));
|
|
4113
|
+
} catch {
|
|
4114
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the interrupt body is not readable JSON within the control body cap" });
|
|
4115
|
+
return;
|
|
4116
|
+
}
|
|
4117
|
+
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || typeof parsed.session !== "string" || parsed.session === "") {
|
|
4118
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the interrupt body must be JSON naming a non-empty session id" });
|
|
4119
|
+
return;
|
|
4120
|
+
}
|
|
4121
|
+
const result = await deps.interrupt(parsed.session);
|
|
4122
|
+
if (result.ok) {
|
|
4123
|
+
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, sequenceNums: result.sequenceNums });
|
|
4124
|
+
return;
|
|
4125
|
+
}
|
|
4126
|
+
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4127
|
+
return;
|
|
4128
|
+
}
|
|
4129
|
+
if (url.pathname === setModelPath) {
|
|
4130
|
+
if (request4.method !== "POST") {
|
|
4131
|
+
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: "the set-model operation is a POST" });
|
|
4132
|
+
return;
|
|
4133
|
+
}
|
|
4134
|
+
let parsed;
|
|
4135
|
+
try {
|
|
4136
|
+
parsed = JSON.parse(await readBody(request4));
|
|
4137
|
+
} catch {
|
|
4138
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-model body is not readable JSON within the control body cap" });
|
|
4139
|
+
return;
|
|
4140
|
+
}
|
|
4141
|
+
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || !("model" in parsed) || typeof parsed.session !== "string" || typeof parsed.model !== "string" || parsed.session === "" || parsed.model === "") {
|
|
4142
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-model body must be JSON naming a non-empty session id and model id" });
|
|
4143
|
+
return;
|
|
4144
|
+
}
|
|
4145
|
+
const result = await deps.setModel(parsed.session, parsed.model);
|
|
4146
|
+
if (result.ok) {
|
|
4147
|
+
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, model: parsed.model, sequenceNums: result.sequenceNums });
|
|
4148
|
+
return;
|
|
4149
|
+
}
|
|
4150
|
+
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4151
|
+
return;
|
|
4152
|
+
}
|
|
4153
|
+
if (url.pathname === setPermissionModePath) {
|
|
4154
|
+
if (request4.method !== "POST") {
|
|
4155
|
+
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: "the set-permission-mode operation is a POST" });
|
|
4156
|
+
return;
|
|
4157
|
+
}
|
|
4158
|
+
let parsed;
|
|
4159
|
+
try {
|
|
4160
|
+
parsed = JSON.parse(await readBody(request4));
|
|
4161
|
+
} catch {
|
|
4162
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-permission-mode body is not readable JSON within the control body cap" });
|
|
4163
|
+
return;
|
|
4164
|
+
}
|
|
4165
|
+
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || !("mode" in parsed) || typeof parsed.session !== "string" || parsed.session === "" || !isRcPermissionMode(parsed.mode)) {
|
|
4166
|
+
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})` });
|
|
4167
|
+
return;
|
|
4168
|
+
}
|
|
4169
|
+
const result = await deps.setPermissionMode(parsed.session, parsed.mode);
|
|
4170
|
+
if (result.ok) {
|
|
4171
|
+
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, mode: parsed.mode, sequenceNums: result.sequenceNums });
|
|
4172
|
+
return;
|
|
4173
|
+
}
|
|
4174
|
+
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4034
4177
|
answerJson(response, HTTP_STATUS.notFound, { error: `no such control route: ${url.pathname}` });
|
|
4035
4178
|
};
|
|
4036
4179
|
handle().catch((error) => {
|
|
@@ -4245,7 +4388,10 @@ function frontDoorRcControl(transport, token) {
|
|
|
4245
4388
|
`${CONTROL_PATH_PREFIX}/answer`,
|
|
4246
4389
|
JSON.stringify({ session: sessionId, request: requestId, approve: decision.approve, ...decision.approve || decision.message === void 0 ? {} : { text: decision.message } }),
|
|
4247
4390
|
(status, message) => `answering control request ${requestId} on ${sessionId} failed (HTTP ${String(status)}): ${message}`
|
|
4248
|
-
)
|
|
4391
|
+
),
|
|
4392
|
+
interruptSession: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/interrupt`, JSON.stringify({ session: sessionId }), (status, message) => `interrupting ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4393
|
+
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}`),
|
|
4394
|
+
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}`)
|
|
4249
4395
|
};
|
|
4250
4396
|
}
|
|
4251
4397
|
|
|
@@ -5688,6 +5834,56 @@ import path16 from "node:path";
|
|
|
5688
5834
|
|
|
5689
5835
|
// src/credentialCache.ts
|
|
5690
5836
|
import { z as z7 } from "zod";
|
|
5837
|
+
|
|
5838
|
+
// src/usage/preflight.ts
|
|
5839
|
+
var MS_PER_SECOND2 = 1e3;
|
|
5840
|
+
var SECONDS_PER_MINUTE = 60;
|
|
5841
|
+
var MINUTES_PER_HOUR = 60;
|
|
5842
|
+
var HOURS_PER_DAY = 24;
|
|
5843
|
+
var WARNING_STATUSES = /* @__PURE__ */ new Set(["allowed_warning", "rejected"]);
|
|
5844
|
+
function formatAge(ms) {
|
|
5845
|
+
const minutes = Math.floor(ms / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
|
|
5846
|
+
if (minutes < MINUTES_PER_HOUR) {
|
|
5847
|
+
return `${String(Math.max(minutes, 0))}m`;
|
|
5848
|
+
}
|
|
5849
|
+
const hours = Math.floor(minutes / MINUTES_PER_HOUR);
|
|
5850
|
+
return hours < HOURS_PER_DAY ? `${String(hours)}h` : `${String(Math.floor(hours / HOURS_PER_DAY))}d`;
|
|
5851
|
+
}
|
|
5852
|
+
function effectiveWindow(window, nowMs) {
|
|
5853
|
+
const resetsAtMs = window.resetsAt === void 0 ? void 0 : Date.parse(window.resetsAt);
|
|
5854
|
+
if (resetsAtMs !== void 0 && resetsAtMs <= nowMs) {
|
|
5855
|
+
return { reset: true, utilization: 0 };
|
|
5856
|
+
}
|
|
5857
|
+
return {
|
|
5858
|
+
reset: false,
|
|
5859
|
+
...window.utilization === void 0 ? {} : { utilization: window.utilization },
|
|
5860
|
+
...resetsAtMs === void 0 ? {} : { resetsAtMs },
|
|
5861
|
+
...window.status === void 0 ? {} : { status: window.status }
|
|
5862
|
+
};
|
|
5863
|
+
}
|
|
5864
|
+
function quotaWarnings(snapshot, provider, nowMs) {
|
|
5865
|
+
const rateLimit = snapshot?.providers[provider]?.rateLimit;
|
|
5866
|
+
const unified = rateLimit?.unified;
|
|
5867
|
+
if (snapshot === void 0 || rateLimit === void 0 || unified === void 0) {
|
|
5868
|
+
return [];
|
|
5869
|
+
}
|
|
5870
|
+
const age = formatAge(nowMs - Date.parse(rateLimit.observedAt));
|
|
5871
|
+
const windows = [
|
|
5872
|
+
{ name: "five-hour", window: unified.fiveHour },
|
|
5873
|
+
{ name: "seven-day", window: unified.sevenDay }
|
|
5874
|
+
];
|
|
5875
|
+
return windows.flatMap(({ name, window }) => {
|
|
5876
|
+
const effective = window === void 0 ? void 0 : effectiveWindow(window, nowMs);
|
|
5877
|
+
if (window === void 0 || effective?.status === void 0 || !WARNING_STATUSES.has(effective.status)) {
|
|
5878
|
+
return [];
|
|
5879
|
+
}
|
|
5880
|
+
const reset = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
|
|
5881
|
+
const verdict = effective.status === "rejected" ? "exhausted" : "nearly used";
|
|
5882
|
+
return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age} ago)`];
|
|
5883
|
+
});
|
|
5884
|
+
}
|
|
5885
|
+
|
|
5886
|
+
// src/credentialCache.ts
|
|
5691
5887
|
var MS_PER_UNIT = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
|
|
5692
5888
|
var CachedCredentialSchema = z7.strictObject({
|
|
5693
5889
|
token: z7.string().min(1),
|
|
@@ -5714,6 +5910,45 @@ function isFresh(entry, cache, now) {
|
|
|
5714
5910
|
}
|
|
5715
5911
|
return limit === void 0 || now - entry.fetchedAt < limit;
|
|
5716
5912
|
}
|
|
5913
|
+
function cacheAgeMs(entry, now) {
|
|
5914
|
+
return Math.max(0, now - entry.fetchedAt);
|
|
5915
|
+
}
|
|
5916
|
+
function describeCachedCredential(params) {
|
|
5917
|
+
const store = effectiveStore(params.cache, params.platform);
|
|
5918
|
+
let entry;
|
|
5919
|
+
try {
|
|
5920
|
+
entry = params.port.read(store, params.owner);
|
|
5921
|
+
} catch (error) {
|
|
5922
|
+
return { store, status: "unreadable", reason: error instanceof Error ? error.message : String(error) };
|
|
5923
|
+
}
|
|
5924
|
+
if (entry === void 0) {
|
|
5925
|
+
return { store, status: "empty" };
|
|
5926
|
+
}
|
|
5927
|
+
const limit = ttlMs(params.cache);
|
|
5928
|
+
const ageMs = cacheAgeMs(entry, params.nowMs);
|
|
5929
|
+
return {
|
|
5930
|
+
store,
|
|
5931
|
+
status: isFresh(entry, params.cache, params.nowMs) ? "fresh" : "expired",
|
|
5932
|
+
ageMs,
|
|
5933
|
+
...limit === void 0 ? {} : { expiresInMs: limit - ageMs }
|
|
5934
|
+
};
|
|
5935
|
+
}
|
|
5936
|
+
function formatCachedCredentialState(state) {
|
|
5937
|
+
if (state.status === "empty") {
|
|
5938
|
+
return `no cached entry in the ${state.store} store yet`;
|
|
5939
|
+
}
|
|
5940
|
+
if (state.status === "unreadable") {
|
|
5941
|
+
return `the ${state.store} store cannot be read here: ${state.reason}`;
|
|
5942
|
+
}
|
|
5943
|
+
if (state.status === "expired" && (state.expiresInMs === void 0 || state.expiresInMs > 0)) {
|
|
5944
|
+
return "cached with a timestamp in the future, treated as expired";
|
|
5945
|
+
}
|
|
5946
|
+
const age = `cached ${formatAge(state.ageMs)} ago`;
|
|
5947
|
+
if (state.expiresInMs === void 0) {
|
|
5948
|
+
return `${age}, no expiry`;
|
|
5949
|
+
}
|
|
5950
|
+
return state.status === "fresh" ? `${age}, expires in ${formatAge(state.expiresInMs)}` : `${age}, expired ${formatAge(-state.expiresInMs)} ago`;
|
|
5951
|
+
}
|
|
5717
5952
|
|
|
5718
5953
|
// src/credential.ts
|
|
5719
5954
|
var CREDENTIAL_UNAVAILABLE_EXIT = 64;
|
|
@@ -6329,54 +6564,6 @@ function readDirectorySelections(loaded) {
|
|
|
6329
6564
|
return { ...identity === void 0 ? {} : { identity }, ...configProfile === void 0 ? {} : { configProfile } };
|
|
6330
6565
|
}
|
|
6331
6566
|
|
|
6332
|
-
// src/usage/preflight.ts
|
|
6333
|
-
var MS_PER_SECOND2 = 1e3;
|
|
6334
|
-
var SECONDS_PER_MINUTE = 60;
|
|
6335
|
-
var MINUTES_PER_HOUR = 60;
|
|
6336
|
-
var HOURS_PER_DAY = 24;
|
|
6337
|
-
var WARNING_STATUSES = /* @__PURE__ */ new Set(["allowed_warning", "rejected"]);
|
|
6338
|
-
function formatAge(ms) {
|
|
6339
|
-
const minutes = Math.floor(ms / (MS_PER_SECOND2 * SECONDS_PER_MINUTE));
|
|
6340
|
-
if (minutes < MINUTES_PER_HOUR) {
|
|
6341
|
-
return `${String(Math.max(minutes, 0))}m`;
|
|
6342
|
-
}
|
|
6343
|
-
const hours = Math.floor(minutes / MINUTES_PER_HOUR);
|
|
6344
|
-
return hours < HOURS_PER_DAY ? `${String(hours)}h` : `${String(Math.floor(hours / HOURS_PER_DAY))}d`;
|
|
6345
|
-
}
|
|
6346
|
-
function effectiveWindow(window, nowMs) {
|
|
6347
|
-
const resetsAtMs = window.resetsAt === void 0 ? void 0 : Date.parse(window.resetsAt);
|
|
6348
|
-
if (resetsAtMs !== void 0 && resetsAtMs <= nowMs) {
|
|
6349
|
-
return { reset: true, utilization: 0 };
|
|
6350
|
-
}
|
|
6351
|
-
return {
|
|
6352
|
-
reset: false,
|
|
6353
|
-
...window.utilization === void 0 ? {} : { utilization: window.utilization },
|
|
6354
|
-
...resetsAtMs === void 0 ? {} : { resetsAtMs },
|
|
6355
|
-
...window.status === void 0 ? {} : { status: window.status }
|
|
6356
|
-
};
|
|
6357
|
-
}
|
|
6358
|
-
function quotaWarnings(snapshot, provider, nowMs) {
|
|
6359
|
-
const rateLimit = snapshot?.providers[provider]?.rateLimit;
|
|
6360
|
-
const unified = rateLimit?.unified;
|
|
6361
|
-
if (snapshot === void 0 || rateLimit === void 0 || unified === void 0) {
|
|
6362
|
-
return [];
|
|
6363
|
-
}
|
|
6364
|
-
const age = formatAge(nowMs - Date.parse(rateLimit.observedAt));
|
|
6365
|
-
const windows = [
|
|
6366
|
-
{ name: "five-hour", window: unified.fiveHour },
|
|
6367
|
-
{ name: "seven-day", window: unified.sevenDay }
|
|
6368
|
-
];
|
|
6369
|
-
return windows.flatMap(({ name, window }) => {
|
|
6370
|
-
const effective = window === void 0 ? void 0 : effectiveWindow(window, nowMs);
|
|
6371
|
-
if (window === void 0 || effective?.status === void 0 || !WARNING_STATUSES.has(effective.status)) {
|
|
6372
|
-
return [];
|
|
6373
|
-
}
|
|
6374
|
-
const reset = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
|
|
6375
|
-
const verdict = effective.status === "rejected" ? "exhausted" : "nearly used";
|
|
6376
|
-
return [`agent-shim: identity ${snapshot.identity}: the ${name} quota is ${verdict}${reset} (last seen ${age} ago)`];
|
|
6377
|
-
});
|
|
6378
|
-
}
|
|
6379
|
-
|
|
6380
6567
|
// src/usage/poolPick.ts
|
|
6381
6568
|
import path19 from "node:path";
|
|
6382
6569
|
import { z as z9 } from "zod";
|
|
@@ -6772,19 +6959,97 @@ function collectPoolPick(params) {
|
|
|
6772
6959
|
};
|
|
6773
6960
|
}
|
|
6774
6961
|
|
|
6962
|
+
// src/realCredentialCache.ts
|
|
6963
|
+
import { spawnSync } from "node:child_process";
|
|
6964
|
+
import fs7 from "node:fs";
|
|
6965
|
+
import path20 from "node:path";
|
|
6966
|
+
var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
6967
|
+
var CACHE_DIR_MODE = 448;
|
|
6968
|
+
var CACHE_FILE_MODE = 384;
|
|
6969
|
+
function cacheFileNameFor(owner) {
|
|
6970
|
+
return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
|
|
6971
|
+
}
|
|
6972
|
+
function parseEntry(raw) {
|
|
6973
|
+
let json;
|
|
6974
|
+
try {
|
|
6975
|
+
json = JSON.parse(raw);
|
|
6976
|
+
} catch {
|
|
6977
|
+
return void 0;
|
|
6978
|
+
}
|
|
6979
|
+
const parsed = CachedCredentialSchema.safeParse(json);
|
|
6980
|
+
return parsed.success ? parsed.data : void 0;
|
|
6981
|
+
}
|
|
6982
|
+
function requireKeychain() {
|
|
6983
|
+
if (process.platform !== "darwin") {
|
|
6984
|
+
throw new Error("the keychain credential store needs macOS; use --credential-cache-store file");
|
|
6985
|
+
}
|
|
6986
|
+
}
|
|
6987
|
+
function security(args, stdin) {
|
|
6988
|
+
const result = spawnSync("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
|
|
6989
|
+
return { status: result.status, stdout: result.stdout };
|
|
6990
|
+
}
|
|
6991
|
+
function createRealCredentialCache(root) {
|
|
6992
|
+
const dir = path20.join(root, "credential-cache");
|
|
6993
|
+
const filePath = (owner) => path20.join(dir, cacheFileNameFor(owner));
|
|
6994
|
+
return {
|
|
6995
|
+
read(store, owner) {
|
|
6996
|
+
if (store === "file") {
|
|
6997
|
+
try {
|
|
6998
|
+
return parseEntry(fs7.readFileSync(filePath(owner), "utf8"));
|
|
6999
|
+
} catch {
|
|
7000
|
+
return void 0;
|
|
7001
|
+
}
|
|
7002
|
+
}
|
|
7003
|
+
requireKeychain();
|
|
7004
|
+
const result = security(["find-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner, "-w"]);
|
|
7005
|
+
return result.status === 0 ? parseEntry(Buffer.from(result.stdout.trim(), "base64").toString("utf8")) : void 0;
|
|
7006
|
+
},
|
|
7007
|
+
write(store, owner, entry) {
|
|
7008
|
+
const serialised = JSON.stringify(entry);
|
|
7009
|
+
if (store === "file") {
|
|
7010
|
+
fs7.mkdirSync(dir, { recursive: true, mode: CACHE_DIR_MODE });
|
|
7011
|
+
fs7.chmodSync(dir, CACHE_DIR_MODE);
|
|
7012
|
+
const target = filePath(owner);
|
|
7013
|
+
const temp = `${target}.${String(process.pid)}.tmp`;
|
|
7014
|
+
fs7.writeFileSync(temp, serialised, { mode: CACHE_FILE_MODE });
|
|
7015
|
+
fs7.renameSync(temp, target);
|
|
7016
|
+
return;
|
|
7017
|
+
}
|
|
7018
|
+
requireKeychain();
|
|
7019
|
+
const encoded = Buffer.from(serialised, "utf8").toString("base64");
|
|
7020
|
+
const result = security(["-i"], `add-generic-password -U -s ${KEYCHAIN_CACHE_SERVICE} -a ${JSON.stringify(owner)} -w ${encoded}
|
|
7021
|
+
`);
|
|
7022
|
+
if (result.status !== 0) {
|
|
7023
|
+
throw new Error(`could not write the keychain credential cache for ${owner}`);
|
|
7024
|
+
}
|
|
7025
|
+
},
|
|
7026
|
+
remove(store, owner) {
|
|
7027
|
+
if (store === "file") {
|
|
7028
|
+
fs7.rmSync(filePath(owner), { force: true });
|
|
7029
|
+
return;
|
|
7030
|
+
}
|
|
7031
|
+
requireKeychain();
|
|
7032
|
+
security(["delete-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner]);
|
|
7033
|
+
}
|
|
7034
|
+
};
|
|
7035
|
+
}
|
|
7036
|
+
function realCredentialCacheEnv(paths) {
|
|
7037
|
+
return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
|
|
7038
|
+
}
|
|
7039
|
+
|
|
6775
7040
|
// src/realPorts.ts
|
|
6776
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
7041
|
+
import { spawn, spawnSync as spawnSync2 } from "node:child_process";
|
|
6777
7042
|
import { createHash as createHash5 } from "node:crypto";
|
|
6778
|
-
import
|
|
7043
|
+
import fs8 from "node:fs";
|
|
6779
7044
|
import os3 from "node:os";
|
|
6780
|
-
import
|
|
7045
|
+
import path22 from "node:path";
|
|
6781
7046
|
import { isSea } from "node:sea";
|
|
6782
7047
|
|
|
6783
7048
|
// src/versionDiscovery.ts
|
|
6784
7049
|
import os2 from "node:os";
|
|
6785
|
-
import
|
|
7050
|
+
import path21 from "node:path";
|
|
6786
7051
|
function defaultVersionsDir() {
|
|
6787
|
-
return
|
|
7052
|
+
return path21.join(os2.homedir(), ".local", "share", "claude", "versions");
|
|
6788
7053
|
}
|
|
6789
7054
|
var NUMERIC_DOTTED_VERSION_RE = /^\d+(?:\.\d+)*$/;
|
|
6790
7055
|
function isNumericDottedVersion(name) {
|
|
@@ -6826,7 +7091,7 @@ function discoverClaudeBinary(options) {
|
|
|
6826
7091
|
const highestVersion = pickHighestVersion(entries);
|
|
6827
7092
|
if (highestVersion !== void 0) {
|
|
6828
7093
|
return {
|
|
6829
|
-
path:
|
|
7094
|
+
path: path21.join(versionsDir, highestVersion),
|
|
6830
7095
|
source: "versions-dir",
|
|
6831
7096
|
version: highestVersion
|
|
6832
7097
|
};
|
|
@@ -6849,7 +7114,7 @@ function isEnoent3(error) {
|
|
|
6849
7114
|
var realFsPort = {
|
|
6850
7115
|
readFileUtf8(filePath) {
|
|
6851
7116
|
try {
|
|
6852
|
-
return
|
|
7117
|
+
return fs8.readFileSync(filePath, "utf8");
|
|
6853
7118
|
} catch (error) {
|
|
6854
7119
|
if (isEnoent3(error)) {
|
|
6855
7120
|
return void 0;
|
|
@@ -6860,7 +7125,7 @@ var realFsPort = {
|
|
|
6860
7125
|
readConfigFile: cosmiconfigReader(),
|
|
6861
7126
|
readdir(dirPath) {
|
|
6862
7127
|
try {
|
|
6863
|
-
return
|
|
7128
|
+
return fs8.readdirSync(dirPath);
|
|
6864
7129
|
} catch (error) {
|
|
6865
7130
|
if (isEnoent3(error)) {
|
|
6866
7131
|
return [];
|
|
@@ -6879,7 +7144,7 @@ var realFarmFs = {
|
|
|
6879
7144
|
lstat(filePath) {
|
|
6880
7145
|
let stat;
|
|
6881
7146
|
try {
|
|
6882
|
-
stat =
|
|
7147
|
+
stat = fs8.lstatSync(filePath);
|
|
6883
7148
|
} catch (error) {
|
|
6884
7149
|
if (isEnoent3(error)) {
|
|
6885
7150
|
return void 0;
|
|
@@ -6891,7 +7156,7 @@ var realFarmFs = {
|
|
|
6891
7156
|
},
|
|
6892
7157
|
readdir(dirPath) {
|
|
6893
7158
|
try {
|
|
6894
|
-
return
|
|
7159
|
+
return fs8.readdirSync(dirPath);
|
|
6895
7160
|
} catch (error) {
|
|
6896
7161
|
if (isEnoent3(error) || isErrorWithCode(error, "ENOTDIR")) {
|
|
6897
7162
|
return [];
|
|
@@ -6900,23 +7165,23 @@ var realFarmFs = {
|
|
|
6900
7165
|
}
|
|
6901
7166
|
},
|
|
6902
7167
|
mkdirp(dirPath) {
|
|
6903
|
-
|
|
7168
|
+
fs8.mkdirSync(dirPath, { recursive: true });
|
|
6904
7169
|
},
|
|
6905
7170
|
symlink(target, linkPath) {
|
|
6906
|
-
|
|
7171
|
+
fs8.symlinkSync(target, linkPath);
|
|
6907
7172
|
},
|
|
6908
7173
|
rename(from, to) {
|
|
6909
|
-
|
|
7174
|
+
fs8.renameSync(from, to);
|
|
6910
7175
|
},
|
|
6911
7176
|
removeRecursive(targetPath) {
|
|
6912
|
-
|
|
7177
|
+
fs8.rmSync(targetPath, { recursive: true, force: true });
|
|
6913
7178
|
},
|
|
6914
7179
|
copyRecursive(from, to) {
|
|
6915
|
-
|
|
7180
|
+
fs8.cpSync(from, to, { recursive: true, force: true, verbatimSymlinks: true });
|
|
6916
7181
|
},
|
|
6917
7182
|
readFileUtf8(filePath) {
|
|
6918
7183
|
try {
|
|
6919
|
-
return
|
|
7184
|
+
return fs8.readFileSync(filePath, "utf8");
|
|
6920
7185
|
} catch (error) {
|
|
6921
7186
|
if (isEnoent3(error)) {
|
|
6922
7187
|
return void 0;
|
|
@@ -6925,36 +7190,36 @@ var realFarmFs = {
|
|
|
6925
7190
|
}
|
|
6926
7191
|
},
|
|
6927
7192
|
writeFileUtf8(filePath, contents) {
|
|
6928
|
-
|
|
7193
|
+
fs8.writeFileSync(filePath, contents, "utf8");
|
|
6929
7194
|
},
|
|
6930
7195
|
mkdirPrivate(dirPath) {
|
|
6931
|
-
|
|
6932
|
-
|
|
7196
|
+
fs8.mkdirSync(dirPath, { recursive: true, mode: OWNER_ONLY_DIR_MODE });
|
|
7197
|
+
fs8.chmodSync(dirPath, OWNER_ONLY_DIR_MODE);
|
|
6933
7198
|
},
|
|
6934
7199
|
writeFilePrivate(filePath, contents) {
|
|
6935
7200
|
const temp = `${filePath}.${String(process.pid)}.tmp`;
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
7201
|
+
fs8.writeFileSync(temp, contents, { encoding: "utf8", mode: OWNER_ONLY_FILE_MODE });
|
|
7202
|
+
fs8.chmodSync(temp, OWNER_ONLY_FILE_MODE);
|
|
7203
|
+
fs8.renameSync(temp, filePath);
|
|
6939
7204
|
},
|
|
6940
7205
|
appendFilePrivate(filePath, contents) {
|
|
6941
|
-
const descriptor =
|
|
7206
|
+
const descriptor = fs8.openSync(filePath, "a", OWNER_ONLY_FILE_MODE);
|
|
6942
7207
|
try {
|
|
6943
|
-
if ((
|
|
6944
|
-
|
|
7208
|
+
if ((fs8.fstatSync(descriptor).mode & PERMISSION_BITS2) !== OWNER_ONLY_FILE_MODE) {
|
|
7209
|
+
fs8.fchmodSync(descriptor, OWNER_ONLY_FILE_MODE);
|
|
6945
7210
|
}
|
|
6946
7211
|
const bytes = Buffer.from(contents, "utf8");
|
|
6947
7212
|
let written = 0;
|
|
6948
7213
|
while (written < bytes.length) {
|
|
6949
|
-
written +=
|
|
7214
|
+
written += fs8.writeSync(descriptor, bytes, written, bytes.length - written);
|
|
6950
7215
|
}
|
|
6951
7216
|
} finally {
|
|
6952
|
-
|
|
7217
|
+
fs8.closeSync(descriptor);
|
|
6953
7218
|
}
|
|
6954
7219
|
},
|
|
6955
7220
|
writeFileExclusive(filePath, contents) {
|
|
6956
7221
|
try {
|
|
6957
|
-
|
|
7222
|
+
fs8.writeFileSync(filePath, contents, { encoding: "utf8", flag: "wx" });
|
|
6958
7223
|
return true;
|
|
6959
7224
|
} catch (error) {
|
|
6960
7225
|
if (isErrorWithCode(error, "EEXIST")) {
|
|
@@ -6965,7 +7230,7 @@ var realFarmFs = {
|
|
|
6965
7230
|
},
|
|
6966
7231
|
hashFile(filePath) {
|
|
6967
7232
|
try {
|
|
6968
|
-
return createHash5("sha256").update(
|
|
7233
|
+
return createHash5("sha256").update(fs8.readFileSync(filePath)).digest("hex");
|
|
6969
7234
|
} catch (error) {
|
|
6970
7235
|
if (isEnoent3(error) || isErrorWithCode(error, "EISDIR")) {
|
|
6971
7236
|
return void 0;
|
|
@@ -6987,7 +7252,7 @@ function realIsProcessAlive(pid) {
|
|
|
6987
7252
|
}
|
|
6988
7253
|
}
|
|
6989
7254
|
function realIsProcessZombie(pid) {
|
|
6990
|
-
const result =
|
|
7255
|
+
const result = spawnSync2("ps", ["-o", "stat=", "-p", String(pid)], { encoding: "utf8" });
|
|
6991
7256
|
return result.status === 0 && result.stdout.trim().startsWith("Z");
|
|
6992
7257
|
}
|
|
6993
7258
|
function realIsProcessRunning(pid) {
|
|
@@ -6995,17 +7260,17 @@ function realIsProcessRunning(pid) {
|
|
|
6995
7260
|
}
|
|
6996
7261
|
var realRunPort = {
|
|
6997
7262
|
run(command, args) {
|
|
6998
|
-
const result =
|
|
7263
|
+
const result = spawnSync2(command, [...args], { encoding: "utf8" });
|
|
6999
7264
|
return { status: result.status, stdout: result.stdout, stderr: result.stderr };
|
|
7000
7265
|
}
|
|
7001
7266
|
};
|
|
7002
7267
|
function expandHome2(filePath) {
|
|
7003
|
-
return filePath.startsWith("~/") ?
|
|
7268
|
+
return filePath.startsWith("~/") ? path22.join(os3.homedir(), filePath.slice(1)) : filePath;
|
|
7004
7269
|
}
|
|
7005
7270
|
var MACOS_GUI_SESSION_MANAGER = "Aqua";
|
|
7006
7271
|
function hasDesktopSession() {
|
|
7007
7272
|
if (process.platform === "darwin") {
|
|
7008
|
-
const result =
|
|
7273
|
+
const result = spawnSync2("launchctl", ["managername"], { encoding: "utf8" });
|
|
7009
7274
|
return result.status === 0 && result.stdout.trim() === MACOS_GUI_SESSION_MANAGER;
|
|
7010
7275
|
}
|
|
7011
7276
|
if (process.platform === "win32") {
|
|
@@ -7019,8 +7284,8 @@ var realCredentialPort = {
|
|
|
7019
7284
|
let content;
|
|
7020
7285
|
let stat;
|
|
7021
7286
|
try {
|
|
7022
|
-
stat =
|
|
7023
|
-
content =
|
|
7287
|
+
stat = fs8.statSync(resolved);
|
|
7288
|
+
content = fs8.readFileSync(resolved, "utf8");
|
|
7024
7289
|
} catch (error) {
|
|
7025
7290
|
if (isEnoent3(error)) {
|
|
7026
7291
|
return { found: false };
|
|
@@ -7031,7 +7296,7 @@ var realCredentialPort = {
|
|
|
7031
7296
|
},
|
|
7032
7297
|
runCommand(argv, options) {
|
|
7033
7298
|
const [command, ...args] = argv;
|
|
7034
|
-
const result =
|
|
7299
|
+
const result = spawnSync2(command, args, {
|
|
7035
7300
|
encoding: "utf8",
|
|
7036
7301
|
timeout: options.timeoutMs,
|
|
7037
7302
|
stdio: options.interactive ? ["inherit", "pipe", "inherit"] : ["ignore", "pipe", "pipe"]
|
|
@@ -7073,8 +7338,8 @@ function spawnDaemonThrough(executable) {
|
|
|
7073
7338
|
return (paths, subcommand, logPath) => spawnDetachedDaemon({ command: executable, args: [subcommand] }, paths, subcommand, logPath);
|
|
7074
7339
|
}
|
|
7075
7340
|
function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
7076
|
-
|
|
7077
|
-
const logFd =
|
|
7341
|
+
fs8.mkdirSync(path22.dirname(logPath), { recursive: true });
|
|
7342
|
+
const logFd = fs8.openSync(logPath, "a");
|
|
7078
7343
|
try {
|
|
7079
7344
|
const child = spawn(invocation.command, invocation.args, detachedDaemonSpawnOptions(logFd, { ...process.env, AGENT_SHIM_HOME: paths.root }));
|
|
7080
7345
|
child.unref();
|
|
@@ -7083,7 +7348,7 @@ function spawnDetachedDaemon(invocation, paths, subcommand, logPath) {
|
|
|
7083
7348
|
}
|
|
7084
7349
|
return child.pid;
|
|
7085
7350
|
} finally {
|
|
7086
|
-
|
|
7351
|
+
fs8.closeSync(logFd);
|
|
7087
7352
|
}
|
|
7088
7353
|
}
|
|
7089
7354
|
function spawnHeadroomSupervisor(paths, spawnDaemon) {
|
|
@@ -7101,7 +7366,7 @@ var realHeadroomSocketTrust = {
|
|
|
7101
7366
|
lstat: (target) => {
|
|
7102
7367
|
let stat;
|
|
7103
7368
|
try {
|
|
7104
|
-
stat =
|
|
7369
|
+
stat = fs8.lstatSync(target);
|
|
7105
7370
|
} catch (error) {
|
|
7106
7371
|
if (isEnoent3(error)) {
|
|
7107
7372
|
return void 0;
|
|
@@ -7147,7 +7412,7 @@ var EXECUTE_BITS_MASK = 73;
|
|
|
7147
7412
|
function listVersionsDir(dir) {
|
|
7148
7413
|
let entries;
|
|
7149
7414
|
try {
|
|
7150
|
-
entries =
|
|
7415
|
+
entries = fs8.readdirSync(dir, { withFileTypes: true });
|
|
7151
7416
|
} catch (error) {
|
|
7152
7417
|
if (isEnoent3(error)) {
|
|
7153
7418
|
return [];
|
|
@@ -7155,8 +7420,8 @@ function listVersionsDir(dir) {
|
|
|
7155
7420
|
throw error;
|
|
7156
7421
|
}
|
|
7157
7422
|
return entries.filter((entry) => entry.isFile()).map((entry) => {
|
|
7158
|
-
const fullPath =
|
|
7159
|
-
const stat =
|
|
7423
|
+
const fullPath = path22.join(dir, entry.name);
|
|
7424
|
+
const stat = fs8.statSync(fullPath);
|
|
7160
7425
|
return {
|
|
7161
7426
|
name: entry.name,
|
|
7162
7427
|
isFile: true,
|
|
@@ -7170,7 +7435,7 @@ function windowsPathExtensions(pathext) {
|
|
|
7170
7435
|
return (pathext ?? WINDOWS_DEFAULT_PATHEXT).split(";").map((ext) => ext.trim()).filter((ext) => ext.length > 0);
|
|
7171
7436
|
}
|
|
7172
7437
|
function resolveExecutableCandidate(dir, name, env) {
|
|
7173
|
-
const candidate =
|
|
7438
|
+
const candidate = path22.join(dir, name);
|
|
7174
7439
|
if (env.platform === "win32") {
|
|
7175
7440
|
const extensions = windowsPathExtensions(env.pathext);
|
|
7176
7441
|
const alreadyHasRecognisedExtension = extensions.some((ext) => candidate.toLowerCase().endsWith(ext.toLowerCase()));
|
|
@@ -7190,7 +7455,7 @@ function resolveExecutableCandidate(dir, name, env) {
|
|
|
7190
7455
|
}
|
|
7191
7456
|
function realStatFileMode(candidate) {
|
|
7192
7457
|
try {
|
|
7193
|
-
const stat =
|
|
7458
|
+
const stat = fs8.statSync(candidate);
|
|
7194
7459
|
return stat.isFile() ? stat.mode : void 0;
|
|
7195
7460
|
} catch (error) {
|
|
7196
7461
|
if (isEnoent3(error)) {
|
|
@@ -7219,13 +7484,13 @@ function resolveOwnExecutablePath(env) {
|
|
|
7219
7484
|
if (env.argv1 !== void 0 && !env.argv1.includes("/") && !env.argv1.includes("\\")) {
|
|
7220
7485
|
return searchPathForExecutable(env.pathDirs, env.argv1, env.findExecutableInDir) ?? env.execPath;
|
|
7221
7486
|
}
|
|
7222
|
-
const candidate = env.argv1 === void 0 ? env.execPath :
|
|
7223
|
-
const candidateDir =
|
|
7224
|
-
const candidateDirOnPath = env.pathDirs.some((dir) =>
|
|
7487
|
+
const candidate = env.argv1 === void 0 ? env.execPath : path22.resolve(env.cwd, env.argv1);
|
|
7488
|
+
const candidateDir = path22.dirname(candidate);
|
|
7489
|
+
const candidateDirOnPath = env.pathDirs.some((dir) => path22.resolve(dir) === candidateDir);
|
|
7225
7490
|
if (candidateDirOnPath) {
|
|
7226
7491
|
return candidate;
|
|
7227
7492
|
}
|
|
7228
|
-
const viaPath = searchPathForExecutable(env.pathDirs,
|
|
7493
|
+
const viaPath = searchPathForExecutable(env.pathDirs, path22.basename(candidate), env.findExecutableInDir);
|
|
7229
7494
|
return viaPath ?? candidate;
|
|
7230
7495
|
}
|
|
7231
7496
|
function realOwnExecutablePath() {
|
|
@@ -7233,7 +7498,7 @@ function realOwnExecutablePath() {
|
|
|
7233
7498
|
argv1: process.argv[1],
|
|
7234
7499
|
execPath: process.execPath,
|
|
7235
7500
|
cwd: process.cwd(),
|
|
7236
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
7501
|
+
pathDirs: (process.env.PATH ?? "").split(path22.delimiter).filter((dir) => dir !== ""),
|
|
7237
7502
|
findExecutableInDir
|
|
7238
7503
|
});
|
|
7239
7504
|
}
|
|
@@ -7246,14 +7511,14 @@ function realContentSourcePath() {
|
|
|
7246
7511
|
function realResolveClaudeBinary(isOwnBinary) {
|
|
7247
7512
|
return () => discoverClaudeBinary({
|
|
7248
7513
|
listVersionsDir,
|
|
7249
|
-
pathDirs: (process.env.PATH ?? "").split(
|
|
7514
|
+
pathDirs: (process.env.PATH ?? "").split(path22.delimiter).filter((dir) => dir !== ""),
|
|
7250
7515
|
findExecutableInDir,
|
|
7251
7516
|
isOwnBinary
|
|
7252
7517
|
});
|
|
7253
7518
|
}
|
|
7254
7519
|
|
|
7255
7520
|
// src/checkReport.ts
|
|
7256
|
-
import
|
|
7521
|
+
import path23 from "node:path";
|
|
7257
7522
|
import { z as z10 } from "zod";
|
|
7258
7523
|
|
|
7259
7524
|
// src/cli/bool.ts
|
|
@@ -7423,14 +7688,23 @@ function inspectSettingsExposure(params) {
|
|
|
7423
7688
|
}
|
|
7424
7689
|
return reports;
|
|
7425
7690
|
}
|
|
7426
|
-
function
|
|
7691
|
+
function cachedState(cacheEnv, owner, block) {
|
|
7692
|
+
if (cacheEnv === void 0 || block.cache === void 0) {
|
|
7693
|
+
return void 0;
|
|
7694
|
+
}
|
|
7695
|
+
return describeCachedCredential({ port: cacheEnv.port, platform: cacheEnv.platform, owner, cache: block.cache, nowMs: cacheEnv.now() });
|
|
7696
|
+
}
|
|
7697
|
+
function buildCredentialReport(provider, identity, identityName, cacheEnv) {
|
|
7427
7698
|
const identityCredential = identity?.credential === void 0 ? void 0 : summariseCredential(identity.credential);
|
|
7699
|
+
const identityCached = identity?.credential === void 0 || identityName === void 0 ? void 0 : cachedState(cacheEnv, `identity ${identityName}`, identity.credential);
|
|
7700
|
+
const providerCached = provider?.definition === void 0 ? void 0 : cachedState(cacheEnv, `provider ${provider.name}`, provider.definition.credential);
|
|
7428
7701
|
return {
|
|
7429
7702
|
applies: provider !== void 0 ? "provider" : identityCredential !== void 0 ? "identity" : "stored-login",
|
|
7430
7703
|
...provider === void 0 ? {} : {
|
|
7431
|
-
provider: provider.problem === void 0 ? { name: provider.name, credential: summariseCredential(provider.definition.credential) } : { name: provider.name, problem: provider.problem }
|
|
7704
|
+
provider: provider.problem === void 0 ? { name: provider.name, credential: summariseCredential(provider.definition.credential), ...providerCached === void 0 ? {} : { cached: providerCached } } : { name: provider.name, problem: provider.problem }
|
|
7432
7705
|
},
|
|
7433
|
-
...identityCredential === void 0 ? {} : { identity: identityCredential }
|
|
7706
|
+
...identityCredential === void 0 ? {} : { identity: identityCredential },
|
|
7707
|
+
...identityCached === void 0 ? {} : { identityCached }
|
|
7434
7708
|
};
|
|
7435
7709
|
}
|
|
7436
7710
|
function runCheck(params) {
|
|
@@ -7469,7 +7743,7 @@ function runCheck(params) {
|
|
|
7469
7743
|
ambientCredential,
|
|
7470
7744
|
...keychain === void 0 ? {} : { keychain },
|
|
7471
7745
|
settingsExposure,
|
|
7472
|
-
credential: buildCredentialReport(params.provider, params.identity)
|
|
7746
|
+
credential: buildCredentialReport(params.provider, params.identity, params.identityName, params.credentialCache)
|
|
7473
7747
|
};
|
|
7474
7748
|
}
|
|
7475
7749
|
function formatCheckReport(report) {
|
|
@@ -7507,12 +7781,12 @@ function formatCheckReport(report) {
|
|
|
7507
7781
|
const { credential } = report;
|
|
7508
7782
|
if (credential.provider !== void 0) {
|
|
7509
7783
|
lines.push(
|
|
7510
|
-
` Provider ${credential.provider.name}: ${credential.provider.credential === void 0 ? `unusable: ${credential.provider.problem ?? ""}` : formatCredentialSummary(credential.provider.credential)}`
|
|
7784
|
+
` 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)}`}`
|
|
7511
7785
|
);
|
|
7512
7786
|
}
|
|
7513
7787
|
if (credential.identity !== void 0) {
|
|
7514
7788
|
lines.push(
|
|
7515
|
-
` Identity ${report.identityName ?? "(none)"}: ${formatCredentialSummary(credential.identity)}${credential.applies === "provider" ? " (not used: the provider's credential applies)" : ""}`
|
|
7789
|
+
` Identity ${report.identityName ?? "(none)"}: ${formatCredentialSummary(credential.identity)}${credential.identityCached === void 0 ? "" : `; ${formatCachedCredentialState(credential.identityCached)}`}${credential.applies === "provider" ? " (not used: the provider's credential applies)" : ""}`
|
|
7516
7790
|
);
|
|
7517
7791
|
}
|
|
7518
7792
|
if (credential.applies === "stored-login") {
|
|
@@ -7621,10 +7895,10 @@ function collectCheckReport(params) {
|
|
|
7621
7895
|
}).input;
|
|
7622
7896
|
const providerName = cascadeProviderName(cascade);
|
|
7623
7897
|
const provider = providerName === void 0 ? void 0 : loadCheckProvider(paths, providerName);
|
|
7624
|
-
const farmRoot = identityDecision.name === void 0 ? void 0 :
|
|
7898
|
+
const farmRoot = identityDecision.name === void 0 ? void 0 : path23.join(paths.identitiesDir, identityDecision.name);
|
|
7625
7899
|
const settingsFiles = {
|
|
7626
|
-
"settings.json": realFsPort.readFileUtf8(
|
|
7627
|
-
"settings.local.json": realFsPort.readFileUtf8(
|
|
7900
|
+
"settings.json": realFsPort.readFileUtf8(path23.join(claudeHome, "settings.json")),
|
|
7901
|
+
"settings.local.json": realFsPort.readFileUtf8(path23.join(claudeHome, "settings.local.json"))
|
|
7628
7902
|
};
|
|
7629
7903
|
const report = runCheck({
|
|
7630
7904
|
cwd,
|
|
@@ -7645,6 +7919,7 @@ function collectCheckReport(params) {
|
|
|
7645
7919
|
...loadedIdentity === void 0 ? {} : { identity: loadedIdentity.config },
|
|
7646
7920
|
settingsFiles,
|
|
7647
7921
|
run: realRunPort,
|
|
7922
|
+
credentialCache: realCredentialCacheEnv(paths),
|
|
7648
7923
|
...farmRoot === void 0 ? {} : { farmRoot },
|
|
7649
7924
|
platform: process.platform,
|
|
7650
7925
|
...provider === void 0 ? {} : { provider }
|
|
@@ -7653,8 +7928,8 @@ function collectCheckReport(params) {
|
|
|
7653
7928
|
}
|
|
7654
7929
|
|
|
7655
7930
|
// src/claudeShim.ts
|
|
7656
|
-
import
|
|
7657
|
-
import
|
|
7931
|
+
import fs9 from "node:fs";
|
|
7932
|
+
import path24 from "node:path";
|
|
7658
7933
|
import { z as z11 } from "zod";
|
|
7659
7934
|
var ClaudeShimStateSchema = z11.strictObject({
|
|
7660
7935
|
targetPath: z11.string().min(1),
|
|
@@ -7666,10 +7941,10 @@ function commandFilename(ownExecutablePath, commandName) {
|
|
|
7666
7941
|
}
|
|
7667
7942
|
function resolveOwnBinaryCheck(paths, contentSourcePath) {
|
|
7668
7943
|
const state = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
7669
|
-
const recordedTarget = state === void 0 ? void 0 :
|
|
7944
|
+
const recordedTarget = state === void 0 ? void 0 : path24.resolve(state.targetPath);
|
|
7670
7945
|
let ownStat;
|
|
7671
7946
|
return (candidate) => {
|
|
7672
|
-
if (recordedTarget !== void 0 &&
|
|
7947
|
+
if (recordedTarget !== void 0 && path24.resolve(candidate) === recordedTarget) {
|
|
7673
7948
|
return true;
|
|
7674
7949
|
}
|
|
7675
7950
|
ownStat ??= statOrUndefined(contentSourcePath);
|
|
@@ -7683,7 +7958,7 @@ function isEnoent4(error) {
|
|
|
7683
7958
|
}
|
|
7684
7959
|
function statOrUndefined(target) {
|
|
7685
7960
|
try {
|
|
7686
|
-
return
|
|
7961
|
+
return fs9.statSync(target);
|
|
7687
7962
|
} catch (error) {
|
|
7688
7963
|
if (isEnoent4(error)) {
|
|
7689
7964
|
return void 0;
|
|
@@ -7691,22 +7966,22 @@ function statOrUndefined(target) {
|
|
|
7691
7966
|
throw error;
|
|
7692
7967
|
}
|
|
7693
7968
|
}
|
|
7694
|
-
var nodeLinkFs = { link:
|
|
7969
|
+
var nodeLinkFs = { link: fs9.linkSync, copyFile: fs9.copyFileSync, chmod: fs9.chmodSync };
|
|
7695
7970
|
function findPathShadow(params) {
|
|
7696
|
-
const resolvedTargetDir =
|
|
7971
|
+
const resolvedTargetDir = path24.resolve(params.targetDir);
|
|
7697
7972
|
for (const dir of params.pathDirs) {
|
|
7698
7973
|
const found = params.findExecutableInDir(dir, params.targetFilename);
|
|
7699
7974
|
if (found === void 0) {
|
|
7700
7975
|
continue;
|
|
7701
7976
|
}
|
|
7702
|
-
return
|
|
7977
|
+
return path24.resolve(dir) === resolvedTargetDir ? { status: "ok" } : { status: "shadowed", by: found };
|
|
7703
7978
|
}
|
|
7704
|
-
return params.pathDirs.some((dir) =>
|
|
7979
|
+
return params.pathDirs.some((dir) => path24.resolve(dir) === resolvedTargetDir) ? { status: "ok" } : { status: "not-on-path" };
|
|
7705
7980
|
}
|
|
7706
7981
|
|
|
7707
7982
|
// src/doctorReport.ts
|
|
7708
|
-
import
|
|
7709
|
-
import
|
|
7983
|
+
import fs10 from "node:fs";
|
|
7984
|
+
import path25 from "node:path";
|
|
7710
7985
|
function refinePathShadow(status, ownExecutablePath, realpath) {
|
|
7711
7986
|
if (status.status !== "shadowed") {
|
|
7712
7987
|
return status;
|
|
@@ -7730,7 +8005,7 @@ function validateJson(schema, input) {
|
|
|
7730
8005
|
return { ok: true, data: result.data };
|
|
7731
8006
|
}
|
|
7732
8007
|
function pushPathResolution(push, resolution) {
|
|
7733
|
-
const ownDir =
|
|
8008
|
+
const ownDir = path25.dirname(resolution.ownExecutablePath);
|
|
7734
8009
|
switch (resolution.agentShim.status) {
|
|
7735
8010
|
case "ok":
|
|
7736
8011
|
push("path-resolution", "pass", `\`agent-shim\` on PATH resolves to this running executable, ${resolution.ownExecutablePath}.`, "agent-shim");
|
|
@@ -7772,7 +8047,14 @@ function pushPathResolution(push, resolution) {
|
|
|
7772
8047
|
break;
|
|
7773
8048
|
}
|
|
7774
8049
|
}
|
|
7775
|
-
function
|
|
8050
|
+
function cacheClause(cacheEnv, owner, block) {
|
|
8051
|
+
if (cacheEnv === void 0 || block.cache === void 0) {
|
|
8052
|
+
return { text: "", unreadable: false };
|
|
8053
|
+
}
|
|
8054
|
+
const state = describeCachedCredential({ port: cacheEnv.port, platform: cacheEnv.platform, owner, cache: block.cache, nowMs: cacheEnv.now() });
|
|
8055
|
+
return { text: `; ${formatCachedCredentialState(state)}`, unreadable: state.status === "unreadable" };
|
|
8056
|
+
}
|
|
8057
|
+
function pushProvider(push, entry, cacheEnv) {
|
|
7776
8058
|
if (entry.raw === void 0) {
|
|
7777
8059
|
push("provider", "fail", `${entry.path} is missing.`, entry.name);
|
|
7778
8060
|
return;
|
|
@@ -7794,18 +8076,19 @@ function pushProvider(push, entry) {
|
|
|
7794
8076
|
push("provider", "fail", new ConfigValidationError(entry.path, validated.error.issues).message, entry.name);
|
|
7795
8077
|
return;
|
|
7796
8078
|
}
|
|
7797
|
-
|
|
8079
|
+
const cache = cacheClause(cacheEnv, `provider ${entry.name}`, validated.data.credential);
|
|
8080
|
+
push("provider", cache.unreadable ? "fail" : "pass", `${entry.name} is valid (${describeProviderEndpoint(validated.data)}, credential ${describeCredential(validated.data.credential)})${cache.text}.`, entry.name);
|
|
7798
8081
|
}
|
|
7799
8082
|
function pushLegacyName(push, params) {
|
|
7800
8083
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
7801
|
-
if (legacyVariables.length === 0 &&
|
|
8084
|
+
if (legacyVariables.length === 0 && path25.basename(params.rootPath) !== LEGACY_HOME_DIRNAME) {
|
|
7802
8085
|
push("legacy-name", "pass", "Nothing here still uses the former `claude-use` name.");
|
|
7803
8086
|
return;
|
|
7804
8087
|
}
|
|
7805
8088
|
for (const name of legacyVariables) {
|
|
7806
8089
|
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);
|
|
7807
8090
|
}
|
|
7808
|
-
if (
|
|
8091
|
+
if (path25.basename(params.rootPath) === LEGACY_HOME_DIRNAME) {
|
|
7809
8092
|
push(
|
|
7810
8093
|
"legacy-name",
|
|
7811
8094
|
"warn",
|
|
@@ -7887,10 +8170,11 @@ function runDoctor(params) {
|
|
|
7887
8170
|
);
|
|
7888
8171
|
} else {
|
|
7889
8172
|
const credential = validated.data.credential;
|
|
8173
|
+
const cache = credential === void 0 ? { text: "", unreadable: false } : cacheClause(params.credentialCache, `identity ${entry.name}`, credential);
|
|
7890
8174
|
push(
|
|
7891
8175
|
"identity",
|
|
7892
|
-
"pass",
|
|
7893
|
-
`${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}.`,
|
|
8176
|
+
cache.unreadable ? "fail" : "pass",
|
|
8177
|
+
`${entry.name} is valid and authenticates with ${credential === void 0 ? "its stored login" : `credential ${describeCredential(credential)}`}${cache.text}.`,
|
|
7894
8178
|
entry.name
|
|
7895
8179
|
);
|
|
7896
8180
|
}
|
|
@@ -7910,7 +8194,7 @@ function runDoctor(params) {
|
|
|
7910
8194
|
return poolName === void 0 ? validIdentityNames.has(selector) : poolName in pools;
|
|
7911
8195
|
};
|
|
7912
8196
|
for (const entry of params.providers) {
|
|
7913
|
-
pushProvider(push, entry);
|
|
8197
|
+
pushProvider(push, entry, params.credentialCache);
|
|
7914
8198
|
}
|
|
7915
8199
|
if (params.platform !== "darwin" || params.run === void 0) {
|
|
7916
8200
|
push("keychain", "pass", "Skipped (not macOS).");
|
|
@@ -8104,27 +8388,27 @@ function formatDoctorReport(report) {
|
|
|
8104
8388
|
}
|
|
8105
8389
|
function realpathOrSelf(target) {
|
|
8106
8390
|
try {
|
|
8107
|
-
return
|
|
8391
|
+
return fs10.realpathSync(target);
|
|
8108
8392
|
} catch {
|
|
8109
8393
|
return target;
|
|
8110
8394
|
}
|
|
8111
8395
|
}
|
|
8112
8396
|
function collectDoctorReport(params) {
|
|
8113
8397
|
const { paths } = params;
|
|
8114
|
-
const identityNames =
|
|
8398
|
+
const identityNames = fs10.existsSync(paths.identitiesDir) ? fs10.readdirSync(paths.identitiesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isIdentityDirectoryName(entry.name)).map((entry) => entry.name).sort() : [];
|
|
8115
8399
|
const identities = identityNames.map((name) => {
|
|
8116
|
-
const farmRoot =
|
|
8117
|
-
const identityPath =
|
|
8400
|
+
const farmRoot = path25.join(paths.identitiesDir, name);
|
|
8401
|
+
const identityPath = path25.join(farmRoot, "identity.json");
|
|
8118
8402
|
return { name, path: identityPath, raw: realFsPort.readFileUtf8(identityPath), farmRoot };
|
|
8119
8403
|
});
|
|
8120
|
-
const profileNames =
|
|
8404
|
+
const profileNames = fs10.existsSync(paths.configProfilesDir) ? fs10.readdirSync(paths.configProfilesDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
8121
8405
|
const configProfiles = profileNames.map((name) => {
|
|
8122
|
-
const profilePath =
|
|
8406
|
+
const profilePath = path25.join(paths.configProfilesDir, `${name}.json`);
|
|
8123
8407
|
return { name, path: profilePath, raw: realFsPort.readFileUtf8(profilePath) };
|
|
8124
8408
|
});
|
|
8125
|
-
const providerNames =
|
|
8409
|
+
const providerNames = fs10.existsSync(paths.providersDir) ? fs10.readdirSync(paths.providersDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name.slice(0, -".json".length)).sort() : [];
|
|
8126
8410
|
const providers = providerNames.map((name) => {
|
|
8127
|
-
const providerPath =
|
|
8411
|
+
const providerPath = path25.join(paths.providersDir, `${name}.json`);
|
|
8128
8412
|
return { name, path: providerPath, raw: realFsPort.readFileUtf8(providerPath) };
|
|
8129
8413
|
});
|
|
8130
8414
|
const ownExecutablePath = realOwnExecutablePath();
|
|
@@ -8136,12 +8420,12 @@ function collectDoctorReport(params) {
|
|
|
8136
8420
|
binaryDiscovery = { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
8137
8421
|
}
|
|
8138
8422
|
const shimState = readJson(paths.claudeShimFile, ClaudeShimStateSchema);
|
|
8139
|
-
const pathDirs = (params.env.PATH ?? "").split(
|
|
8423
|
+
const pathDirs = (params.env.PATH ?? "").split(path25.delimiter).filter((dir) => dir !== "");
|
|
8140
8424
|
const claudeShimShadow = shimState === void 0 ? void 0 : refinePathShadow(
|
|
8141
8425
|
findPathShadow({
|
|
8142
8426
|
pathDirs,
|
|
8143
|
-
targetDir:
|
|
8144
|
-
targetFilename:
|
|
8427
|
+
targetDir: path25.dirname(shimState.targetPath),
|
|
8428
|
+
targetFilename: path25.basename(shimState.targetPath),
|
|
8145
8429
|
findExecutableInDir
|
|
8146
8430
|
}),
|
|
8147
8431
|
shimState.targetPath,
|
|
@@ -8149,6 +8433,7 @@ function collectDoctorReport(params) {
|
|
|
8149
8433
|
);
|
|
8150
8434
|
const report = runDoctor({
|
|
8151
8435
|
env: params.env,
|
|
8436
|
+
credentialCache: realCredentialCacheEnv(paths),
|
|
8152
8437
|
identities,
|
|
8153
8438
|
configProfiles,
|
|
8154
8439
|
providers,
|
|
@@ -8157,14 +8442,14 @@ function collectDoctorReport(params) {
|
|
|
8157
8442
|
categoriesLocal: { path: paths.categoriesLocalFile, raw: realFsPort.readFileUtf8(paths.categoriesLocalFile) },
|
|
8158
8443
|
activeIdentity: { path: paths.activeIdentityFile, raw: realFsPort.readFileUtf8(paths.activeIdentityFile) },
|
|
8159
8444
|
binaryDiscovery,
|
|
8160
|
-
claudeShim: { state: shimState, targetExists: shimState !== void 0 &&
|
|
8445
|
+
claudeShim: { state: shimState, targetExists: shimState !== void 0 && fs10.existsSync(shimState.targetPath) },
|
|
8161
8446
|
rootPath: paths.root,
|
|
8162
8447
|
pathResolution: {
|
|
8163
8448
|
ownExecutablePath,
|
|
8164
8449
|
agentShim: refinePathShadow(
|
|
8165
8450
|
findPathShadow({
|
|
8166
8451
|
pathDirs,
|
|
8167
|
-
targetDir:
|
|
8452
|
+
targetDir: path25.dirname(ownExecutablePath),
|
|
8168
8453
|
targetFilename: commandFilename(ownExecutablePath, "agent-shim"),
|
|
8169
8454
|
findExecutableInDir
|
|
8170
8455
|
}),
|
|
@@ -8185,7 +8470,7 @@ function collectDoctorReport(params) {
|
|
|
8185
8470
|
|
|
8186
8471
|
// src/launcher.ts
|
|
8187
8472
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
8188
|
-
import
|
|
8473
|
+
import path27 from "node:path";
|
|
8189
8474
|
|
|
8190
8475
|
// src/launcher/argv.ts
|
|
8191
8476
|
var ConflictingIdentityError = class extends UsageError {
|
|
@@ -8437,7 +8722,7 @@ function buildCliOverride(params) {
|
|
|
8437
8722
|
}
|
|
8438
8723
|
|
|
8439
8724
|
// src/launcher/flags.ts
|
|
8440
|
-
import
|
|
8725
|
+
import path26 from "node:path";
|
|
8441
8726
|
|
|
8442
8727
|
// src/headroom/headers.ts
|
|
8443
8728
|
function mergeAnthropicCustomHeaders(existing, additions) {
|
|
@@ -8507,7 +8792,7 @@ function buildEnv(params) {
|
|
|
8507
8792
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
8508
8793
|
let providerCustomHeaders;
|
|
8509
8794
|
if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
|
|
8510
|
-
env.CLAUDE_CONFIG_DIR =
|
|
8795
|
+
env.CLAUDE_CONFIG_DIR = path26.join(params.identitiesDir, params.resolvedIdentityName);
|
|
8511
8796
|
}
|
|
8512
8797
|
if (params.provider !== void 0) {
|
|
8513
8798
|
const providerEnv = params.provider.definition.env ?? {};
|
|
@@ -8668,7 +8953,7 @@ function prepareLaunch(params) {
|
|
|
8668
8953
|
identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
|
|
8669
8954
|
globalDefaultConfigProfile: params.globalDefaultConfigProfile
|
|
8670
8955
|
});
|
|
8671
|
-
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(
|
|
8956
|
+
if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path27.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
|
|
8672
8957
|
log.error(
|
|
8673
8958
|
`agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
|
|
8674
8959
|
);
|
|
@@ -8841,84 +9126,6 @@ function prepareLaunch(params) {
|
|
|
8841
9126
|
import os5 from "node:os";
|
|
8842
9127
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
8843
9128
|
|
|
8844
|
-
// src/realCredentialCache.ts
|
|
8845
|
-
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
8846
|
-
import fs10 from "node:fs";
|
|
8847
|
-
import path27 from "node:path";
|
|
8848
|
-
var KEYCHAIN_CACHE_SERVICE = "agent-shim-credential-cache";
|
|
8849
|
-
var CACHE_DIR_MODE = 448;
|
|
8850
|
-
var CACHE_FILE_MODE = 384;
|
|
8851
|
-
function cacheFileNameFor(owner) {
|
|
8852
|
-
return `${owner.replace(/[^A-Za-z0-9._-]/g, "_")}.json`;
|
|
8853
|
-
}
|
|
8854
|
-
function parseEntry(raw) {
|
|
8855
|
-
let json;
|
|
8856
|
-
try {
|
|
8857
|
-
json = JSON.parse(raw);
|
|
8858
|
-
} catch {
|
|
8859
|
-
return void 0;
|
|
8860
|
-
}
|
|
8861
|
-
const parsed = CachedCredentialSchema.safeParse(json);
|
|
8862
|
-
return parsed.success ? parsed.data : void 0;
|
|
8863
|
-
}
|
|
8864
|
-
function requireKeychain() {
|
|
8865
|
-
if (process.platform !== "darwin") {
|
|
8866
|
-
throw new Error("the keychain credential store needs macOS; use --credential-cache-store file");
|
|
8867
|
-
}
|
|
8868
|
-
}
|
|
8869
|
-
function security(args, stdin) {
|
|
8870
|
-
const result = spawnSync2("security", args, { encoding: "utf8", ...stdin === void 0 ? {} : { input: stdin }, stdio: ["pipe", "pipe", "ignore"] });
|
|
8871
|
-
return { status: result.status, stdout: result.stdout };
|
|
8872
|
-
}
|
|
8873
|
-
function createRealCredentialCache(root) {
|
|
8874
|
-
const dir = path27.join(root, "credential-cache");
|
|
8875
|
-
const filePath = (owner) => path27.join(dir, cacheFileNameFor(owner));
|
|
8876
|
-
return {
|
|
8877
|
-
read(store, owner) {
|
|
8878
|
-
if (store === "file") {
|
|
8879
|
-
try {
|
|
8880
|
-
return parseEntry(fs10.readFileSync(filePath(owner), "utf8"));
|
|
8881
|
-
} catch {
|
|
8882
|
-
return void 0;
|
|
8883
|
-
}
|
|
8884
|
-
}
|
|
8885
|
-
requireKeychain();
|
|
8886
|
-
const result = security(["find-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner, "-w"]);
|
|
8887
|
-
return result.status === 0 ? parseEntry(Buffer.from(result.stdout.trim(), "base64").toString("utf8")) : void 0;
|
|
8888
|
-
},
|
|
8889
|
-
write(store, owner, entry) {
|
|
8890
|
-
const serialised = JSON.stringify(entry);
|
|
8891
|
-
if (store === "file") {
|
|
8892
|
-
fs10.mkdirSync(dir, { recursive: true, mode: CACHE_DIR_MODE });
|
|
8893
|
-
fs10.chmodSync(dir, CACHE_DIR_MODE);
|
|
8894
|
-
const target = filePath(owner);
|
|
8895
|
-
const temp = `${target}.${String(process.pid)}.tmp`;
|
|
8896
|
-
fs10.writeFileSync(temp, serialised, { mode: CACHE_FILE_MODE });
|
|
8897
|
-
fs10.renameSync(temp, target);
|
|
8898
|
-
return;
|
|
8899
|
-
}
|
|
8900
|
-
requireKeychain();
|
|
8901
|
-
const encoded = Buffer.from(serialised, "utf8").toString("base64");
|
|
8902
|
-
const result = security(["-i"], `add-generic-password -U -s ${KEYCHAIN_CACHE_SERVICE} -a ${JSON.stringify(owner)} -w ${encoded}
|
|
8903
|
-
`);
|
|
8904
|
-
if (result.status !== 0) {
|
|
8905
|
-
throw new Error(`could not write the keychain credential cache for ${owner}`);
|
|
8906
|
-
}
|
|
8907
|
-
},
|
|
8908
|
-
remove(store, owner) {
|
|
8909
|
-
if (store === "file") {
|
|
8910
|
-
fs10.rmSync(filePath(owner), { force: true });
|
|
8911
|
-
return;
|
|
8912
|
-
}
|
|
8913
|
-
requireKeychain();
|
|
8914
|
-
security(["delete-generic-password", "-s", KEYCHAIN_CACHE_SERVICE, "-a", owner]);
|
|
8915
|
-
}
|
|
8916
|
-
};
|
|
8917
|
-
}
|
|
8918
|
-
function realCredentialCacheEnv(paths) {
|
|
8919
|
-
return { port: createRealCredentialCache(paths.root), platform: process.platform, now: () => Date.now() };
|
|
8920
|
-
}
|
|
8921
|
-
|
|
8922
9129
|
// src/frontdoor/realFrontDoorPort.ts
|
|
8923
9130
|
import fs11 from "node:fs";
|
|
8924
9131
|
|
|
@@ -9194,6 +9401,7 @@ export {
|
|
|
9194
9401
|
ProviderSchema,
|
|
9195
9402
|
RC_IDLE_EXPIRY_MS,
|
|
9196
9403
|
RC_PENDING_DEADLINE_MS,
|
|
9404
|
+
RC_PERMISSION_MODES,
|
|
9197
9405
|
RC_REQUEST_PARSE_CAP_BYTES,
|
|
9198
9406
|
RC_SESSIONS_PATH_PREFIX,
|
|
9199
9407
|
ROUTED_PATH_PREFIX,
|
|
@@ -9210,6 +9418,9 @@ export {
|
|
|
9210
9418
|
buildLayoutPaths,
|
|
9211
9419
|
buildRcControlResponsePayload,
|
|
9212
9420
|
buildRcEventWriteBody,
|
|
9421
|
+
buildRcInterruptPayload,
|
|
9422
|
+
buildRcSetModelPayload,
|
|
9423
|
+
buildRcSetPermissionModePayload,
|
|
9213
9424
|
buildRcUserMessagePayload,
|
|
9214
9425
|
carryOver,
|
|
9215
9426
|
checkReportHasWarnings,
|
|
@@ -9234,8 +9445,10 @@ export {
|
|
|
9234
9445
|
generateCa,
|
|
9235
9446
|
identityExists,
|
|
9236
9447
|
injectRcUserMessage,
|
|
9448
|
+
interruptRcSession,
|
|
9237
9449
|
isIdentityDirectoryName,
|
|
9238
9450
|
isInterceptedHost,
|
|
9451
|
+
isRcPermissionMode,
|
|
9239
9452
|
listDirectoryRules,
|
|
9240
9453
|
listIdentities,
|
|
9241
9454
|
listProfiles,
|
|
@@ -9291,6 +9504,8 @@ export {
|
|
|
9291
9504
|
setProfileEntries,
|
|
9292
9505
|
setProfileLaunchFlags,
|
|
9293
9506
|
setProfileMetadata,
|
|
9507
|
+
setRcSessionModel,
|
|
9508
|
+
setRcSessionPermissionMode,
|
|
9294
9509
|
snapshotPath,
|
|
9295
9510
|
startConnectServer,
|
|
9296
9511
|
topLevelNames,
|