agent-shim 8.22.0 → 8.24.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 +11 -1
- package/dist/cli.cjs +2293 -1821
- package/dist/index.cjs +622 -101
- package/dist/index.mjs +597 -101
- package/dist/types/index.d.ts +416 -22
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -93,10 +93,12 @@ __export(index_exports, {
|
|
|
93
93
|
ProviderKindMismatchError: () => ProviderKindMismatchError,
|
|
94
94
|
ProviderNotFoundError: () => ProviderNotFoundError,
|
|
95
95
|
ProviderSchema: () => ProviderSchema,
|
|
96
|
+
RC_CONTEXT_USAGE_DETAILS: () => RC_CONTEXT_USAGE_DETAILS,
|
|
96
97
|
RC_IDLE_EXPIRY_MS: () => RC_IDLE_EXPIRY_MS,
|
|
97
98
|
RC_ORPC_PATH_PREFIX: () => RC_ORPC_PATH_PREFIX,
|
|
98
99
|
RC_PENDING_DEADLINE_MS: () => RC_PENDING_DEADLINE_MS,
|
|
99
100
|
RC_PERMISSION_MODES: () => RC_PERMISSION_MODES,
|
|
101
|
+
RC_READ_FILE_ENCODINGS: () => RC_READ_FILE_ENCODINGS,
|
|
100
102
|
RC_REQUEST_PARSE_CAP_BYTES: () => RC_REQUEST_PARSE_CAP_BYTES,
|
|
101
103
|
RC_SELF_HOST_ENV: () => RC_SELF_HOST_ENV,
|
|
102
104
|
RC_SELF_HOST_KEEPALIVE_MS: () => RC_SELF_HOST_KEEPALIVE_MS,
|
|
@@ -127,11 +129,23 @@ __export(index_exports, {
|
|
|
127
129
|
addPool: () => addPool,
|
|
128
130
|
addProvider: () => addProvider,
|
|
129
131
|
answerRcControlRequest: () => answerRcControlRequest,
|
|
132
|
+
authenticateRcSessionMcpServer: () => authenticateRcSessionMcpServer,
|
|
130
133
|
buildEntryFacts: () => buildEntryFacts,
|
|
131
134
|
buildLayoutPaths: () => buildLayoutPaths,
|
|
135
|
+
buildRcControlRequestPayload: () => buildRcControlRequestPayload,
|
|
132
136
|
buildRcControlResponsePayload: () => buildRcControlResponsePayload,
|
|
137
|
+
buildRcEndSessionPayload: () => buildRcEndSessionPayload,
|
|
133
138
|
buildRcEventWriteBody: () => buildRcEventWriteBody,
|
|
139
|
+
buildRcFileSuggestionsPayload: () => buildRcFileSuggestionsPayload,
|
|
140
|
+
buildRcGetContextUsagePayload: () => buildRcGetContextUsagePayload,
|
|
141
|
+
buildRcGetUsagePayload: () => buildRcGetUsagePayload,
|
|
134
142
|
buildRcInterruptPayload: () => buildRcInterruptPayload,
|
|
143
|
+
buildRcKeepAlivePayload: () => buildRcKeepAlivePayload,
|
|
144
|
+
buildRcMcpAuthenticatePayload: () => buildRcMcpAuthenticatePayload,
|
|
145
|
+
buildRcMcpOAuthCallbackUrlPayload: () => buildRcMcpOAuthCallbackUrlPayload,
|
|
146
|
+
buildRcMcpReconnectPayload: () => buildRcMcpReconnectPayload,
|
|
147
|
+
buildRcMcpStatusPayload: () => buildRcMcpStatusPayload,
|
|
148
|
+
buildRcReadFilePayload: () => buildRcReadFilePayload,
|
|
135
149
|
buildRcSetModelPayload: () => buildRcSetModelPayload,
|
|
136
150
|
buildRcSetPermissionModePayload: () => buildRcSetPermissionModePayload,
|
|
137
151
|
buildRcUserMessagePayload: () => buildRcUserMessagePayload,
|
|
@@ -164,6 +178,7 @@ __export(index_exports, {
|
|
|
164
178
|
doorApiAuth: () => doorApiAuth,
|
|
165
179
|
doorApiNodeHandlerOf: () => doorApiNodeHandlerOf,
|
|
166
180
|
effectiveWindow: () => effectiveWindow,
|
|
181
|
+
endRcSession: () => endRcSession,
|
|
167
182
|
ensureCa: () => ensureCa,
|
|
168
183
|
ensureFrontDoor: () => ensureFrontDoor,
|
|
169
184
|
ensureHeadroom: () => ensureHeadroom,
|
|
@@ -180,6 +195,9 @@ __export(index_exports, {
|
|
|
180
195
|
frontDoorRcApiClient: () => frontDoorRcApiClient,
|
|
181
196
|
frontDoorRcControl: () => frontDoorRcControl,
|
|
182
197
|
generateCa: () => generateCa,
|
|
198
|
+
getRcSessionContextUsage: () => getRcSessionContextUsage,
|
|
199
|
+
getRcSessionMcpStatus: () => getRcSessionMcpStatus,
|
|
200
|
+
getRcSessionUsage: () => getRcSessionUsage,
|
|
183
201
|
headroomSocketTarget: () => headroomSocketTarget,
|
|
184
202
|
identityExists: () => identityExists,
|
|
185
203
|
injectRcUserMessage: () => injectRcUserMessage,
|
|
@@ -187,7 +205,9 @@ __export(index_exports, {
|
|
|
187
205
|
isIdentityDirectoryName: () => isIdentityDirectoryName,
|
|
188
206
|
isInterceptedHost: () => isInterceptedHost,
|
|
189
207
|
isPrivateAddress: () => isPrivateAddress,
|
|
208
|
+
isRcContextUsageDetail: () => isRcContextUsageDetail,
|
|
190
209
|
isRcPermissionMode: () => isRcPermissionMode,
|
|
210
|
+
isRcReadFileEncoding: () => isRcReadFileEncoding,
|
|
191
211
|
lateRcEventDial: () => lateRcEventDial,
|
|
192
212
|
lateRcStreamDial: () => lateRcStreamDial,
|
|
193
213
|
listDirectoryRules: () => listDirectoryRules,
|
|
@@ -221,6 +241,7 @@ __export(index_exports, {
|
|
|
221
241
|
readProfile: () => readProfile,
|
|
222
242
|
readProvider: () => readProvider,
|
|
223
243
|
readRcSelfHostRecord: () => readRcSelfHostRecord,
|
|
244
|
+
readRcSessionFile: () => readRcSessionFile,
|
|
224
245
|
readUsageSnapshot: () => readUsageSnapshot,
|
|
225
246
|
realConnectCertStore: () => realConnectCertStore,
|
|
226
247
|
realConnectEffects: () => realConnectEffects,
|
|
@@ -228,6 +249,7 @@ __export(index_exports, {
|
|
|
228
249
|
realRcEventDial: () => realRcEventDial,
|
|
229
250
|
realRcStreamDial: () => realRcStreamDial,
|
|
230
251
|
realRcWebFetch: () => realRcWebFetch,
|
|
252
|
+
reconnectRcSessionMcpServer: () => reconnectRcSessionMcpServer,
|
|
231
253
|
recoverFarm: () => recoverFarm,
|
|
232
254
|
recoveryDiagnostics: () => recoveryDiagnostics,
|
|
233
255
|
removeDirectoryRule: () => removeDirectoryRule,
|
|
@@ -247,6 +269,7 @@ __export(index_exports, {
|
|
|
247
269
|
runFrontDoorSupervisor: () => runFrontDoorSupervisor,
|
|
248
270
|
runLauncher: () => runLauncher,
|
|
249
271
|
runSupervisor: () => runSupervisor,
|
|
272
|
+
sendRcKeepAlive: () => sendRcKeepAlive,
|
|
250
273
|
servedByPipeline: () => servedByPipeline,
|
|
251
274
|
setAllowAmbientCredential: () => setAllowAmbientCredential,
|
|
252
275
|
setDefaultConfigProfile: () => setDefaultConfigProfile,
|
|
@@ -262,6 +285,8 @@ __export(index_exports, {
|
|
|
262
285
|
snapshotPath: () => snapshotPath,
|
|
263
286
|
spawnClaude: () => spawnClaude,
|
|
264
287
|
startConnectServer: () => startConnectServer,
|
|
288
|
+
submitRcSessionMcpOAuthCallbackUrl: () => submitRcSessionMcpOAuthCallbackUrl,
|
|
289
|
+
suggestRcSessionFiles: () => suggestRcSessionFiles,
|
|
265
290
|
topLevelNames: () => topLevelNames,
|
|
266
291
|
updateDirectoryRule: () => updateDirectoryRule,
|
|
267
292
|
updateProvider: () => updateProvider,
|
|
@@ -640,6 +665,11 @@ var FrontDoorGlobalConfigSchema = import_zod.z.strictObject({
|
|
|
640
665
|
/** How long the front door may sit with no registered sessions before it closes and exits. Defaults to FRONTDOOR_DEFAULT_IDLE_SHUTDOWN_MINUTES. */
|
|
641
666
|
idleShutdownMinutes: import_zod.z.number().int().positive().optional()
|
|
642
667
|
});
|
|
668
|
+
var UPDATE_MODES = ["off", "notify", "auto"];
|
|
669
|
+
var UpdateGlobalConfigSchema = import_zod.z.strictObject({
|
|
670
|
+
/** What a launch does about a newer release of agent-shim itself; see `UPDATE_MODES`. Absent means `off`. */
|
|
671
|
+
mode: import_zod.z.enum(UPDATE_MODES).optional()
|
|
672
|
+
});
|
|
643
673
|
var GlobalConfigSchema = import_zod.z.strictObject({
|
|
644
674
|
$schema: import_zod.z.string().optional(),
|
|
645
675
|
defaultConfigProfile: import_zod.z.string().min(1).optional(),
|
|
@@ -649,6 +679,7 @@ var GlobalConfigSchema = import_zod.z.strictObject({
|
|
|
649
679
|
launch: LaunchSchema.optional(),
|
|
650
680
|
headroom: HeadroomGlobalConfigSchema.optional(),
|
|
651
681
|
frontdoor: FrontDoorGlobalConfigSchema.optional(),
|
|
682
|
+
update: UpdateGlobalConfigSchema.optional(),
|
|
652
683
|
pools: import_zod.z.record(PoolNameSchema, PoolSchema).optional()
|
|
653
684
|
});
|
|
654
685
|
var IdentitySchema = import_zod.z.strictObject({
|
|
@@ -3896,6 +3927,8 @@ function rcObserverAsPassthrough(observer) {
|
|
|
3896
3927
|
}
|
|
3897
3928
|
};
|
|
3898
3929
|
}
|
|
3930
|
+
|
|
3931
|
+
// src/frontdoor/rcWrites.ts
|
|
3899
3932
|
function buildRcUserMessagePayload(uuid, sessionId, text) {
|
|
3900
3933
|
return {
|
|
3901
3934
|
type: "user",
|
|
@@ -3996,14 +4029,55 @@ var RC_PERMISSION_MODES = ["default", "acceptEdits", "bypassPermissions", "plan"
|
|
|
3996
4029
|
function isRcPermissionMode(value) {
|
|
3997
4030
|
return RC_PERMISSION_MODES.some((mode) => mode === value);
|
|
3998
4031
|
}
|
|
4032
|
+
function buildRcControlRequestPayload(requestId, request4) {
|
|
4033
|
+
return { type: "control_request", request_id: requestId, request: request4 };
|
|
4034
|
+
}
|
|
3999
4035
|
function buildRcInterruptPayload(requestId) {
|
|
4000
|
-
return
|
|
4036
|
+
return buildRcControlRequestPayload(requestId, { subtype: "interrupt" });
|
|
4001
4037
|
}
|
|
4002
4038
|
function buildRcSetModelPayload(requestId, model) {
|
|
4003
|
-
return
|
|
4039
|
+
return buildRcControlRequestPayload(requestId, { subtype: "set_model", model });
|
|
4004
4040
|
}
|
|
4005
4041
|
function buildRcSetPermissionModePayload(requestId, mode) {
|
|
4006
|
-
return
|
|
4042
|
+
return buildRcControlRequestPayload(requestId, { subtype: "set_permission_mode", mode });
|
|
4043
|
+
}
|
|
4044
|
+
function buildRcEndSessionPayload(requestId, reason) {
|
|
4045
|
+
return buildRcControlRequestPayload(requestId, { subtype: "end_session", ...reason === void 0 ? {} : { reason } });
|
|
4046
|
+
}
|
|
4047
|
+
function buildRcGetUsagePayload(requestId, skipBehaviors) {
|
|
4048
|
+
return buildRcControlRequestPayload(requestId, { subtype: "get_usage", ...skipBehaviors === true ? { skip_behaviors: true } : {} });
|
|
4049
|
+
}
|
|
4050
|
+
var RC_CONTEXT_USAGE_DETAILS = ["summary", "full"];
|
|
4051
|
+
function isRcContextUsageDetail(value) {
|
|
4052
|
+
return RC_CONTEXT_USAGE_DETAILS.some((detail) => detail === value);
|
|
4053
|
+
}
|
|
4054
|
+
function buildRcGetContextUsagePayload(requestId, detail) {
|
|
4055
|
+
return buildRcControlRequestPayload(requestId, { subtype: "get_context_usage", ...detail === void 0 ? {} : { detail } });
|
|
4056
|
+
}
|
|
4057
|
+
var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
|
|
4058
|
+
function isRcReadFileEncoding(value) {
|
|
4059
|
+
return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
|
|
4060
|
+
}
|
|
4061
|
+
function buildRcReadFilePayload(requestId, path32, options) {
|
|
4062
|
+
return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path32, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
|
|
4063
|
+
}
|
|
4064
|
+
function buildRcFileSuggestionsPayload(requestId, query) {
|
|
4065
|
+
return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
|
|
4066
|
+
}
|
|
4067
|
+
function buildRcMcpStatusPayload(requestId) {
|
|
4068
|
+
return buildRcControlRequestPayload(requestId, { subtype: "mcp_status" });
|
|
4069
|
+
}
|
|
4070
|
+
function buildRcMcpReconnectPayload(requestId, serverName) {
|
|
4071
|
+
return buildRcControlRequestPayload(requestId, { subtype: "mcp_reconnect", serverName });
|
|
4072
|
+
}
|
|
4073
|
+
function buildRcMcpAuthenticatePayload(requestId, serverName, redirectUri) {
|
|
4074
|
+
return buildRcControlRequestPayload(requestId, { subtype: "mcp_authenticate", serverName, redirectUri });
|
|
4075
|
+
}
|
|
4076
|
+
function buildRcMcpOAuthCallbackUrlPayload(requestId, serverName, callbackUrl) {
|
|
4077
|
+
return buildRcControlRequestPayload(requestId, { subtype: "mcp_oauth_callback_url", serverName, callbackUrl });
|
|
4078
|
+
}
|
|
4079
|
+
function buildRcKeepAlivePayload() {
|
|
4080
|
+
return { type: "keep_alive" };
|
|
4007
4081
|
}
|
|
4008
4082
|
async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
4009
4083
|
const credential = deps.credentialOf(sessionId);
|
|
@@ -4030,7 +4104,7 @@ async function answerRcControlRequest(deps, sessionId, requestId, decision) {
|
|
|
4030
4104
|
}
|
|
4031
4105
|
return result;
|
|
4032
4106
|
}
|
|
4033
|
-
async function
|
|
4107
|
+
async function deliverRcClientPayload(deps, sessionId, payload, action) {
|
|
4034
4108
|
const credential = deps.credentialOf(sessionId);
|
|
4035
4109
|
if (credential === void 0) {
|
|
4036
4110
|
return { ok: false, message: rcSessionNotObservedMessage(sessionId) };
|
|
@@ -4038,12 +4112,12 @@ async function interruptRcSession(deps, sessionId) {
|
|
|
4038
4112
|
if (credential.authorization === void 0) {
|
|
4039
4113
|
return noOAuthCredentialResult(sessionId);
|
|
4040
4114
|
}
|
|
4041
|
-
const body = JSON.stringify(buildRcEventWriteBody(
|
|
4115
|
+
const body = JSON.stringify(buildRcEventWriteBody(payload));
|
|
4042
4116
|
let answer;
|
|
4043
4117
|
try {
|
|
4044
4118
|
answer = await deps.dial.writeEvents(sessionId, rcWriteHeaders(credential), body);
|
|
4045
4119
|
} catch (error) {
|
|
4046
|
-
return { ok: false, message: `the door could not reach the API host to
|
|
4120
|
+
return { ok: false, message: `the door could not reach the API host to ${action}: ${error instanceof Error ? error.message : String(error)}` };
|
|
4047
4121
|
}
|
|
4048
4122
|
const result = rcEventWriteResultFromAnswer(answer);
|
|
4049
4123
|
if (result.ok) {
|
|
@@ -4051,50 +4125,89 @@ async function interruptRcSession(deps, sessionId) {
|
|
|
4051
4125
|
}
|
|
4052
4126
|
return result;
|
|
4053
4127
|
}
|
|
4128
|
+
async function interruptRcSession(deps, sessionId) {
|
|
4129
|
+
const requestId = deps.newUuid();
|
|
4130
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcInterruptPayload(requestId), `interrupt session ${sessionId}`);
|
|
4131
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4132
|
+
}
|
|
4054
4133
|
async function setRcSessionModel(deps, sessionId, model) {
|
|
4055
4134
|
if (model === "") {
|
|
4056
4135
|
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" };
|
|
4057
4136
|
}
|
|
4058
|
-
const
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4137
|
+
const requestId = deps.newUuid();
|
|
4138
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcSetModelPayload(requestId, model), `set the model on session ${sessionId}`);
|
|
4139
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4140
|
+
}
|
|
4141
|
+
async function setRcSessionPermissionMode(deps, sessionId, mode) {
|
|
4142
|
+
const requestId = deps.newUuid();
|
|
4143
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcSetPermissionModePayload(requestId, mode), `set the permission mode on session ${sessionId}`);
|
|
4144
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4145
|
+
}
|
|
4146
|
+
async function endRcSession(deps, sessionId, reason) {
|
|
4147
|
+
if (reason === "") {
|
|
4148
|
+
return { ok: false, message: "an end-session write needs either no reason or a non-empty one: the worker reads an absent reason as its own unspecified form, and an empty string is neither" };
|
|
4064
4149
|
}
|
|
4065
|
-
const
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4150
|
+
const requestId = deps.newUuid();
|
|
4151
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcEndSessionPayload(requestId, reason), `end session ${sessionId}`);
|
|
4152
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4153
|
+
}
|
|
4154
|
+
async function getRcSessionUsage(deps, sessionId, skipBehaviors) {
|
|
4155
|
+
const requestId = deps.newUuid();
|
|
4156
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcGetUsagePayload(requestId, skipBehaviors), `request the usage of session ${sessionId}`);
|
|
4157
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4158
|
+
}
|
|
4159
|
+
async function getRcSessionContextUsage(deps, sessionId, detail) {
|
|
4160
|
+
const requestId = deps.newUuid();
|
|
4161
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
|
|
4162
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4163
|
+
}
|
|
4164
|
+
async function readRcSessionFile(deps, sessionId, path32, options) {
|
|
4165
|
+
if (path32 === "") {
|
|
4166
|
+
return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
|
|
4071
4167
|
}
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
deps.noteSequenceNums(sessionId, result.sequenceNums);
|
|
4168
|
+
if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
|
|
4169
|
+
return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
|
|
4075
4170
|
}
|
|
4076
|
-
|
|
4171
|
+
const requestId = deps.newUuid();
|
|
4172
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path32, options), `read ${path32} from session ${sessionId}`);
|
|
4173
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4077
4174
|
}
|
|
4078
|
-
async function
|
|
4079
|
-
const
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4175
|
+
async function suggestRcSessionFiles(deps, sessionId, query) {
|
|
4176
|
+
const requestId = deps.newUuid();
|
|
4177
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcFileSuggestionsPayload(requestId, query), `request file suggestions from session ${sessionId}`);
|
|
4178
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4179
|
+
}
|
|
4180
|
+
async function getRcSessionMcpStatus(deps, sessionId) {
|
|
4181
|
+
const requestId = deps.newUuid();
|
|
4182
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcMcpStatusPayload(requestId), `request the MCP status of session ${sessionId}`);
|
|
4183
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4184
|
+
}
|
|
4185
|
+
async function reconnectRcSessionMcpServer(deps, sessionId, serverName) {
|
|
4186
|
+
if (serverName === "") {
|
|
4187
|
+
return { ok: false, message: "an mcp-reconnect write needs a non-empty server name: the SDK's own field names the server as mcp_status reports it, and an empty string names none" };
|
|
4085
4188
|
}
|
|
4086
|
-
const
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4189
|
+
const requestId = deps.newUuid();
|
|
4190
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcMcpReconnectPayload(requestId, serverName), `reconnect MCP server ${serverName} on session ${sessionId}`);
|
|
4191
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4192
|
+
}
|
|
4193
|
+
async function authenticateRcSessionMcpServer(deps, sessionId, serverName, redirectUri) {
|
|
4194
|
+
if (serverName === "" || redirectUri === "") {
|
|
4195
|
+
return { ok: false, message: "an mcp-authenticate write needs a non-empty server name and redirect URI: the CLI's own request names the server and where its OAuth flow redirects back to, and an empty string names neither" };
|
|
4092
4196
|
}
|
|
4093
|
-
const
|
|
4094
|
-
|
|
4095
|
-
|
|
4197
|
+
const requestId = deps.newUuid();
|
|
4198
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcMcpAuthenticatePayload(requestId, serverName, redirectUri), `authenticate MCP server ${serverName} on session ${sessionId}`);
|
|
4199
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4200
|
+
}
|
|
4201
|
+
async function submitRcSessionMcpOAuthCallbackUrl(deps, sessionId, serverName, callbackUrl) {
|
|
4202
|
+
if (serverName === "" || callbackUrl === "") {
|
|
4203
|
+
return { ok: false, message: "an mcp-oauth-callback-url write needs a non-empty server name and callback URL: the CLI's own request names the server and the URL its OAuth flow landed on, and an empty string names neither" };
|
|
4096
4204
|
}
|
|
4097
|
-
|
|
4205
|
+
const requestId = deps.newUuid();
|
|
4206
|
+
const result = await deliverRcClientPayload(deps, sessionId, buildRcMcpOAuthCallbackUrlPayload(requestId, serverName, callbackUrl), `hand MCP server ${serverName}'s OAuth callback to session ${sessionId}`);
|
|
4207
|
+
return result.ok ? { ...result, requestId } : result;
|
|
4208
|
+
}
|
|
4209
|
+
async function sendRcKeepAlive(deps, sessionId) {
|
|
4210
|
+
return await deliverRcClientPayload(deps, sessionId, buildRcKeepAlivePayload(), `keep session ${sessionId} alive`);
|
|
4098
4211
|
}
|
|
4099
4212
|
|
|
4100
4213
|
// src/frontdoor/rcControl.ts
|
|
@@ -4106,6 +4219,25 @@ function answerJson(response, status, body) {
|
|
|
4106
4219
|
response.writeHead(status, { "content-type": "application/json", "content-length": String(Buffer.byteLength(text, "utf8")) });
|
|
4107
4220
|
response.end(text);
|
|
4108
4221
|
}
|
|
4222
|
+
function isJsonObject(value) {
|
|
4223
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4224
|
+
}
|
|
4225
|
+
function bodyString(body, field) {
|
|
4226
|
+
const value = body[field];
|
|
4227
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
4228
|
+
}
|
|
4229
|
+
function bodyStringAllowingEmpty(body, field) {
|
|
4230
|
+
const value = body[field];
|
|
4231
|
+
return typeof value === "string" ? value : void 0;
|
|
4232
|
+
}
|
|
4233
|
+
function bodyBoolean(body, field) {
|
|
4234
|
+
const value = body[field];
|
|
4235
|
+
return typeof value === "boolean" ? value : void 0;
|
|
4236
|
+
}
|
|
4237
|
+
function bodyPositiveInteger(body, field) {
|
|
4238
|
+
const value = body[field];
|
|
4239
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
4240
|
+
}
|
|
4109
4241
|
async function readBody(request4) {
|
|
4110
4242
|
return await new Promise((resolve, reject) => {
|
|
4111
4243
|
const chunks = [];
|
|
@@ -4133,9 +4265,127 @@ function createRcControlHandler(deps) {
|
|
|
4133
4265
|
const pendingPath = `${CONTROL_PATH_PREFIX}/pending`;
|
|
4134
4266
|
const injectPath = `${CONTROL_PATH_PREFIX}/inject`;
|
|
4135
4267
|
const answerPath = `${CONTROL_PATH_PREFIX}/answer`;
|
|
4136
|
-
const
|
|
4137
|
-
|
|
4138
|
-
|
|
4268
|
+
const controlWrites = [
|
|
4269
|
+
{
|
|
4270
|
+
name: "interrupt",
|
|
4271
|
+
path: "interrupt",
|
|
4272
|
+
read: (body) => {
|
|
4273
|
+
const session = bodyString(body, "session");
|
|
4274
|
+
return session === void 0 ? { error: "the interrupt body must be JSON naming a non-empty session id" } : { session, run: async () => await deps.interrupt(session) };
|
|
4275
|
+
}
|
|
4276
|
+
},
|
|
4277
|
+
{
|
|
4278
|
+
name: "set-model",
|
|
4279
|
+
path: "set-model",
|
|
4280
|
+
read: (body) => {
|
|
4281
|
+
const session = bodyString(body, "session");
|
|
4282
|
+
const model = bodyString(body, "model");
|
|
4283
|
+
return session === void 0 || model === void 0 ? { error: "the set-model body must be JSON naming a non-empty session id and model id" } : { session, run: async () => await deps.setModel(session, model) };
|
|
4284
|
+
}
|
|
4285
|
+
},
|
|
4286
|
+
{
|
|
4287
|
+
name: "set-permission-mode",
|
|
4288
|
+
path: "set-permission-mode",
|
|
4289
|
+
read: (body) => {
|
|
4290
|
+
const session = bodyString(body, "session");
|
|
4291
|
+
const mode = body.mode;
|
|
4292
|
+
return session === void 0 || !isRcPermissionMode(mode) ? { 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})` } : { session, run: async () => await deps.setPermissionMode(session, mode) };
|
|
4293
|
+
}
|
|
4294
|
+
},
|
|
4295
|
+
{
|
|
4296
|
+
name: "end-session",
|
|
4297
|
+
path: "end-session",
|
|
4298
|
+
read: (body) => {
|
|
4299
|
+
const session = bodyString(body, "session");
|
|
4300
|
+
const reason = "reason" in body ? bodyString(body, "reason") : void 0;
|
|
4301
|
+
return session === void 0 || "reason" in body && reason === void 0 ? { error: "the end-session body must be JSON naming a non-empty session id, and a reason only as a non-empty string or absent" } : { session, run: async () => await deps.endSession(session, reason) };
|
|
4302
|
+
}
|
|
4303
|
+
},
|
|
4304
|
+
{
|
|
4305
|
+
name: "get-usage",
|
|
4306
|
+
path: "get-usage",
|
|
4307
|
+
read: (body) => {
|
|
4308
|
+
const session = bodyString(body, "session");
|
|
4309
|
+
const skipBehaviors = "skipBehaviors" in body ? bodyBoolean(body, "skipBehaviors") : void 0;
|
|
4310
|
+
return session === void 0 || "skipBehaviors" in body && skipBehaviors === void 0 ? { error: "the get-usage body must be JSON naming a non-empty session id, and skipBehaviors only as a boolean or absent" } : { session, run: async () => await deps.getUsage(session, skipBehaviors) };
|
|
4311
|
+
}
|
|
4312
|
+
},
|
|
4313
|
+
{
|
|
4314
|
+
name: "get-context-usage",
|
|
4315
|
+
path: "get-context-usage",
|
|
4316
|
+
read: (body) => {
|
|
4317
|
+
const session = bodyString(body, "session");
|
|
4318
|
+
const detail = "detail" in body && isRcContextUsageDetail(body.detail) ? body.detail : void 0;
|
|
4319
|
+
return session === void 0 || "detail" in body && detail === void 0 ? { error: `the get-context-usage body must be JSON naming a non-empty session id, and a detail level the SDK's own type permits (${RC_CONTEXT_USAGE_DETAILS.join(", ")}) or none` } : { session, run: async () => await deps.getContextUsage(session, detail) };
|
|
4320
|
+
}
|
|
4321
|
+
},
|
|
4322
|
+
{
|
|
4323
|
+
name: "read-file",
|
|
4324
|
+
path: "read-file",
|
|
4325
|
+
read: (body) => {
|
|
4326
|
+
const session = bodyString(body, "session");
|
|
4327
|
+
const path32 = bodyString(body, "path");
|
|
4328
|
+
const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
|
|
4329
|
+
const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
|
|
4330
|
+
const refused2 = session === void 0 || path32 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
|
|
4331
|
+
return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path32, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
|
|
4332
|
+
}
|
|
4333
|
+
},
|
|
4334
|
+
{
|
|
4335
|
+
name: "file-suggestions",
|
|
4336
|
+
path: "file-suggestions",
|
|
4337
|
+
read: (body) => {
|
|
4338
|
+
const session = bodyString(body, "session");
|
|
4339
|
+
const query = bodyStringAllowingEmpty(body, "query");
|
|
4340
|
+
return session === void 0 || query === void 0 ? { error: "the file-suggestions body must be JSON naming a non-empty session id and a query string, which may be empty" } : { session, run: async () => await deps.fileSuggestions(session, query) };
|
|
4341
|
+
}
|
|
4342
|
+
},
|
|
4343
|
+
{
|
|
4344
|
+
name: "keep-alive",
|
|
4345
|
+
path: "keep-alive",
|
|
4346
|
+
read: (body) => {
|
|
4347
|
+
const session = bodyString(body, "session");
|
|
4348
|
+
return session === void 0 ? { error: "the keep-alive body must be JSON naming a non-empty session id" } : { session, run: async () => await deps.keepAlive(session) };
|
|
4349
|
+
}
|
|
4350
|
+
},
|
|
4351
|
+
{
|
|
4352
|
+
name: "mcp-status",
|
|
4353
|
+
path: "mcp-status",
|
|
4354
|
+
read: (body) => {
|
|
4355
|
+
const session = bodyString(body, "session");
|
|
4356
|
+
return session === void 0 ? { error: "the mcp-status body must be JSON naming a non-empty session id" } : { session, run: async () => await deps.mcpStatus(session) };
|
|
4357
|
+
}
|
|
4358
|
+
},
|
|
4359
|
+
{
|
|
4360
|
+
name: "mcp-reconnect",
|
|
4361
|
+
path: "mcp-reconnect",
|
|
4362
|
+
read: (body) => {
|
|
4363
|
+
const session = bodyString(body, "session");
|
|
4364
|
+
const serverName = bodyString(body, "serverName");
|
|
4365
|
+
return session === void 0 || serverName === void 0 ? { error: "the mcp-reconnect body must be JSON naming a non-empty session id and server name" } : { session, run: async () => await deps.mcpReconnect(session, serverName) };
|
|
4366
|
+
}
|
|
4367
|
+
},
|
|
4368
|
+
{
|
|
4369
|
+
name: "mcp-authenticate",
|
|
4370
|
+
path: "mcp-authenticate",
|
|
4371
|
+
read: (body) => {
|
|
4372
|
+
const session = bodyString(body, "session");
|
|
4373
|
+
const serverName = bodyString(body, "serverName");
|
|
4374
|
+
const redirectUri = bodyString(body, "redirectUri");
|
|
4375
|
+
return session === void 0 || serverName === void 0 || redirectUri === void 0 ? { error: "the mcp-authenticate body must be JSON naming a non-empty session id, server name, and redirect URI" } : { session, run: async () => await deps.mcpAuthenticate(session, serverName, redirectUri) };
|
|
4376
|
+
}
|
|
4377
|
+
},
|
|
4378
|
+
{
|
|
4379
|
+
name: "mcp-oauth-callback-url",
|
|
4380
|
+
path: "mcp-oauth-callback-url",
|
|
4381
|
+
read: (body) => {
|
|
4382
|
+
const session = bodyString(body, "session");
|
|
4383
|
+
const serverName = bodyString(body, "serverName");
|
|
4384
|
+
const callbackUrl = bodyString(body, "callbackUrl");
|
|
4385
|
+
return session === void 0 || serverName === void 0 || callbackUrl === void 0 ? { error: "the mcp-oauth-callback-url body must be JSON naming a non-empty session id, server name, and callback URL" } : { session, run: async () => await deps.mcpOAuthCallbackUrl(session, serverName, callbackUrl) };
|
|
4386
|
+
}
|
|
4387
|
+
}
|
|
4388
|
+
];
|
|
4139
4389
|
return (request4, response) => {
|
|
4140
4390
|
const presented = request4.headers.authorization;
|
|
4141
4391
|
const bearerPrefix = "bearer ".length;
|
|
@@ -4220,73 +4470,33 @@ function createRcControlHandler(deps) {
|
|
|
4220
4470
|
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4221
4471
|
return;
|
|
4222
4472
|
}
|
|
4223
|
-
|
|
4224
|
-
if (
|
|
4225
|
-
|
|
4226
|
-
return;
|
|
4227
|
-
}
|
|
4228
|
-
let parsed;
|
|
4229
|
-
try {
|
|
4230
|
-
parsed = JSON.parse(await readBody(request4));
|
|
4231
|
-
} catch {
|
|
4232
|
-
answerJson(response, HTTP_STATUS.badRequest, { error: "the interrupt body is not readable JSON within the control body cap" });
|
|
4233
|
-
return;
|
|
4234
|
-
}
|
|
4235
|
-
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || typeof parsed.session !== "string" || parsed.session === "") {
|
|
4236
|
-
answerJson(response, HTTP_STATUS.badRequest, { error: "the interrupt body must be JSON naming a non-empty session id" });
|
|
4237
|
-
return;
|
|
4238
|
-
}
|
|
4239
|
-
const result = await deps.interrupt(parsed.session);
|
|
4240
|
-
if (result.ok) {
|
|
4241
|
-
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, sequenceNums: result.sequenceNums });
|
|
4242
|
-
return;
|
|
4473
|
+
for (const route of controlWrites) {
|
|
4474
|
+
if (url.pathname !== `${CONTROL_PATH_PREFIX}/${route.path}`) {
|
|
4475
|
+
continue;
|
|
4243
4476
|
}
|
|
4244
|
-
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4245
|
-
return;
|
|
4246
|
-
}
|
|
4247
|
-
if (url.pathname === setModelPath) {
|
|
4248
4477
|
if (request4.method !== "POST") {
|
|
4249
|
-
answerJson(response, HTTP_STATUS.methodNotAllowed, { error:
|
|
4478
|
+
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: `the ${route.name} operation is a POST` });
|
|
4250
4479
|
return;
|
|
4251
4480
|
}
|
|
4252
4481
|
let parsed;
|
|
4253
4482
|
try {
|
|
4254
4483
|
parsed = JSON.parse(await readBody(request4));
|
|
4255
4484
|
} catch {
|
|
4256
|
-
answerJson(response, HTTP_STATUS.badRequest, { error:
|
|
4257
|
-
return;
|
|
4258
|
-
}
|
|
4259
|
-
if (typeof parsed !== "object" || parsed === null || !("session" in parsed) || !("model" in parsed) || typeof parsed.session !== "string" || typeof parsed.model !== "string" || parsed.session === "" || parsed.model === "") {
|
|
4260
|
-
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-model body must be JSON naming a non-empty session id and model id" });
|
|
4485
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: `the ${route.name} body is not readable JSON within the control body cap` });
|
|
4261
4486
|
return;
|
|
4262
4487
|
}
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
answerJson(response, HTTP_STATUS.ok, { session: parsed.session, model: parsed.model, sequenceNums: result.sequenceNums });
|
|
4266
|
-
return;
|
|
4267
|
-
}
|
|
4268
|
-
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
4269
|
-
return;
|
|
4270
|
-
}
|
|
4271
|
-
if (url.pathname === setPermissionModePath) {
|
|
4272
|
-
if (request4.method !== "POST") {
|
|
4273
|
-
answerJson(response, HTTP_STATUS.methodNotAllowed, { error: "the set-permission-mode operation is a POST" });
|
|
4488
|
+
if (!isJsonObject(parsed)) {
|
|
4489
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: `the ${route.name} body must be a JSON object` });
|
|
4274
4490
|
return;
|
|
4275
4491
|
}
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
} catch {
|
|
4280
|
-
answerJson(response, HTTP_STATUS.badRequest, { error: "the set-permission-mode body is not readable JSON within the control body cap" });
|
|
4492
|
+
const read = route.read(parsed);
|
|
4493
|
+
if ("error" in read) {
|
|
4494
|
+
answerJson(response, HTTP_STATUS.badRequest, { error: read.error });
|
|
4281
4495
|
return;
|
|
4282
4496
|
}
|
|
4283
|
-
|
|
4284
|
-
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})` });
|
|
4285
|
-
return;
|
|
4286
|
-
}
|
|
4287
|
-
const result = await deps.setPermissionMode(parsed.session, parsed.mode);
|
|
4497
|
+
const result = await read.run();
|
|
4288
4498
|
if (result.ok) {
|
|
4289
|
-
answerJson(response, HTTP_STATUS.ok, { session:
|
|
4499
|
+
answerJson(response, HTTP_STATUS.ok, { session: read.session, ...result.requestId === void 0 ? {} : { request: result.requestId }, sequenceNums: result.sequenceNums });
|
|
4290
4500
|
return;
|
|
4291
4501
|
}
|
|
4292
4502
|
answerJson(response, HTTP_STATUS.badGateway, { error: result.message });
|
|
@@ -4404,6 +4614,19 @@ function sequenceNumsOfBody(body) {
|
|
|
4404
4614
|
}
|
|
4405
4615
|
return sequenceNums;
|
|
4406
4616
|
}
|
|
4617
|
+
function requestIdOfBody(body) {
|
|
4618
|
+
let parsed;
|
|
4619
|
+
try {
|
|
4620
|
+
parsed = JSON.parse(body);
|
|
4621
|
+
} catch {
|
|
4622
|
+
return void 0;
|
|
4623
|
+
}
|
|
4624
|
+
if (typeof parsed !== "object" || parsed === null || !("request" in parsed)) {
|
|
4625
|
+
return void 0;
|
|
4626
|
+
}
|
|
4627
|
+
const value = parsed.request;
|
|
4628
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
4629
|
+
}
|
|
4407
4630
|
function frontDoorRcControl(transport, token) {
|
|
4408
4631
|
const headers = { authorization: `Bearer ${token}` };
|
|
4409
4632
|
const listAnswerOf = async (path32, what) => {
|
|
@@ -4492,7 +4715,8 @@ function frontDoorRcControl(transport, token) {
|
|
|
4492
4715
|
if (sequenceNums === void 0) {
|
|
4493
4716
|
return { ok: false, message: `the door accepted the event but its answer named no sequence numbers: ${answer.body}` };
|
|
4494
4717
|
}
|
|
4495
|
-
|
|
4718
|
+
const requestId = requestIdOfBody(answer.body);
|
|
4719
|
+
return requestId === void 0 ? { ok: true, sequenceNums } : { ok: true, sequenceNums, requestId };
|
|
4496
4720
|
}
|
|
4497
4721
|
return { ok: false, message: describeFailure(answer.status, controlErrorOf(answer.body) ?? answer.body) };
|
|
4498
4722
|
};
|
|
@@ -4509,7 +4733,21 @@ function frontDoorRcControl(transport, token) {
|
|
|
4509
4733
|
),
|
|
4510
4734
|
interruptSession: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/interrupt`, JSON.stringify({ session: sessionId }), (status, message) => `interrupting ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4511
4735
|
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}`),
|
|
4512
|
-
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}`)
|
|
4736
|
+
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}`),
|
|
4737
|
+
endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4738
|
+
getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4739
|
+
getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4740
|
+
readFile: async (sessionId, path32, options) => await writeOf(
|
|
4741
|
+
`${CONTROL_PATH_PREFIX}/read-file`,
|
|
4742
|
+
JSON.stringify({ session: sessionId, path: path32, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
|
|
4743
|
+
(status, message) => `reading ${path32} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
|
|
4744
|
+
),
|
|
4745
|
+
fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4746
|
+
keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
|
|
4747
|
+
mcpStatus: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-status`, JSON.stringify({ session: sessionId }), (status, message) => `requesting the MCP status of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4748
|
+
mcpReconnect: async (sessionId, serverName) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-reconnect`, JSON.stringify({ session: sessionId, serverName }), (status, message) => `reconnecting MCP server ${serverName} on ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4749
|
+
mcpAuthenticate: async (sessionId, serverName, redirectUri) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-authenticate`, JSON.stringify({ session: sessionId, serverName, redirectUri }), (status, message) => `authenticating MCP server ${serverName} on ${sessionId} failed (HTTP ${String(status)}): ${message}`),
|
|
4750
|
+
mcpOAuthCallbackUrl: async (sessionId, serverName, callbackUrl) => await writeOf(`${CONTROL_PATH_PREFIX}/mcp-oauth-callback-url`, JSON.stringify({ session: sessionId, serverName, callbackUrl }), (status, message) => `handing MCP server ${serverName}'s OAuth callback to ${sessionId} failed (HTTP ${String(status)}): ${message}`)
|
|
4513
4751
|
};
|
|
4514
4752
|
}
|
|
4515
4753
|
|
|
@@ -5131,6 +5369,48 @@ var RcSetPermissionModeInputSchema = import_zod4.z.strictObject({
|
|
|
5131
5369
|
session: import_zod4.z.string().min(1),
|
|
5132
5370
|
mode: RcPermissionModeSchema
|
|
5133
5371
|
});
|
|
5372
|
+
var RcEndSessionInputSchema = import_zod4.z.strictObject({
|
|
5373
|
+
session: import_zod4.z.string().min(1),
|
|
5374
|
+
reason: import_zod4.z.string().min(1).optional()
|
|
5375
|
+
});
|
|
5376
|
+
var RcGetUsageInputSchema = import_zod4.z.strictObject({
|
|
5377
|
+
session: import_zod4.z.string().min(1),
|
|
5378
|
+
skipBehaviors: import_zod4.z.boolean().optional()
|
|
5379
|
+
});
|
|
5380
|
+
var RcGetContextUsageInputSchema = import_zod4.z.strictObject({
|
|
5381
|
+
session: import_zod4.z.string().min(1),
|
|
5382
|
+
detail: import_zod4.z.enum(RC_CONTEXT_USAGE_DETAILS).optional()
|
|
5383
|
+
});
|
|
5384
|
+
var RcReadFileInputSchema = import_zod4.z.strictObject({
|
|
5385
|
+
session: import_zod4.z.string().min(1),
|
|
5386
|
+
path: import_zod4.z.string().min(1),
|
|
5387
|
+
maxBytes: import_zod4.z.number().int().positive().optional(),
|
|
5388
|
+
encoding: import_zod4.z.enum(RC_READ_FILE_ENCODINGS).optional()
|
|
5389
|
+
});
|
|
5390
|
+
var RcFileSuggestionsInputSchema = import_zod4.z.strictObject({
|
|
5391
|
+
session: import_zod4.z.string().min(1),
|
|
5392
|
+
query: import_zod4.z.string()
|
|
5393
|
+
});
|
|
5394
|
+
var RcKeepAliveInputSchema = import_zod4.z.strictObject({
|
|
5395
|
+
session: import_zod4.z.string().min(1)
|
|
5396
|
+
});
|
|
5397
|
+
var RcMcpStatusInputSchema = import_zod4.z.strictObject({
|
|
5398
|
+
session: import_zod4.z.string().min(1)
|
|
5399
|
+
});
|
|
5400
|
+
var RcMcpReconnectInputSchema = import_zod4.z.strictObject({
|
|
5401
|
+
session: import_zod4.z.string().min(1),
|
|
5402
|
+
serverName: import_zod4.z.string().min(1)
|
|
5403
|
+
});
|
|
5404
|
+
var RcMcpAuthenticateInputSchema = import_zod4.z.strictObject({
|
|
5405
|
+
session: import_zod4.z.string().min(1),
|
|
5406
|
+
serverName: import_zod4.z.string().min(1),
|
|
5407
|
+
redirectUri: import_zod4.z.string().min(1)
|
|
5408
|
+
});
|
|
5409
|
+
var RcMcpOAuthCallbackUrlInputSchema = import_zod4.z.strictObject({
|
|
5410
|
+
session: import_zod4.z.string().min(1),
|
|
5411
|
+
serverName: import_zod4.z.string().min(1),
|
|
5412
|
+
callbackUrl: import_zod4.z.string().min(1)
|
|
5413
|
+
});
|
|
5134
5414
|
var RcListOutputSchema = import_zod4.z.strictObject({ sessions: import_zod4.z.readonly(import_zod4.z.array(RcSessionSummarySchema)) });
|
|
5135
5415
|
var RcStatusOutputSchema = import_zod4.z.strictObject({ statuses: import_zod4.z.readonly(import_zod4.z.array(RcSessionStatusSchema)) });
|
|
5136
5416
|
var RcPendingOutputSchema = import_zod4.z.strictObject({ pending: import_zod4.z.readonly(import_zod4.z.array(RcPendingRequestSummarySchema)) });
|
|
@@ -5138,6 +5418,11 @@ var RcWriteOutputSchema = import_zod4.z.strictObject({
|
|
|
5138
5418
|
session: import_zod4.z.string(),
|
|
5139
5419
|
sequenceNums: import_zod4.z.readonly(import_zod4.z.array(import_zod4.z.number()))
|
|
5140
5420
|
});
|
|
5421
|
+
var RcControlWriteOutputSchema = import_zod4.z.strictObject({
|
|
5422
|
+
session: import_zod4.z.string(),
|
|
5423
|
+
request: import_zod4.z.string(),
|
|
5424
|
+
sequenceNums: import_zod4.z.readonly(import_zod4.z.array(import_zod4.z.number()))
|
|
5425
|
+
});
|
|
5141
5426
|
var RcAnswerOutputSchema = import_zod4.z.strictObject({
|
|
5142
5427
|
session: import_zod4.z.string(),
|
|
5143
5428
|
request: import_zod4.z.string(),
|
|
@@ -5166,6 +5451,15 @@ function createRcApiRouter(deps) {
|
|
|
5166
5451
|
}
|
|
5167
5452
|
return result.sequenceNums;
|
|
5168
5453
|
};
|
|
5454
|
+
const deliveredControl = (sessionId, result) => {
|
|
5455
|
+
if (!result.ok) {
|
|
5456
|
+
throw new import_client.ORPCError("BAD_GATEWAY", { message: result.message });
|
|
5457
|
+
}
|
|
5458
|
+
if (result.requestId === void 0) {
|
|
5459
|
+
throw new import_client.ORPCError("INTERNAL_SERVER_ERROR", { message: "the control request was delivered but the door cannot name the request id it minted, so the worker's answer cannot be matched" });
|
|
5460
|
+
}
|
|
5461
|
+
return { request: result.requestId, sequenceNums: result.sequenceNums };
|
|
5462
|
+
};
|
|
5169
5463
|
return {
|
|
5170
5464
|
rc: {
|
|
5171
5465
|
list: authed.output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
|
|
@@ -5188,9 +5482,19 @@ function createRcApiRouter(deps) {
|
|
|
5188
5482
|
const decision = { approve: input.approve, message: input.approve || input.text === void 0 ? void 0 : input.text };
|
|
5189
5483
|
return { session: input.session, request: input.request, sequenceNums: delivered(input.session, await deps.answer(input.session, input.request, decision)) };
|
|
5190
5484
|
}),
|
|
5191
|
-
interrupt: authed.input(RcInterruptInputSchema).output(
|
|
5192
|
-
setModel: authed.input(RcSetModelInputSchema).output(
|
|
5193
|
-
setPermissionMode: authed.input(RcSetPermissionModeInputSchema).output(
|
|
5485
|
+
interrupt: authed.input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
|
|
5486
|
+
setModel: authed.input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
|
|
5487
|
+
setPermissionMode: authed.input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
|
|
5488
|
+
endSession: authed.input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
|
|
5489
|
+
getUsage: authed.input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
|
|
5490
|
+
getContextUsage: authed.input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
|
|
5491
|
+
readFile: authed.input(RcReadFileInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.readFile(input.session, input.path, { ...input.maxBytes === void 0 ? {} : { maxBytes: input.maxBytes }, ...input.encoding === void 0 ? {} : { encoding: input.encoding } })) })),
|
|
5492
|
+
fileSuggestions: authed.input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
|
|
5493
|
+
keepAlive: authed.input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
|
|
5494
|
+
mcpStatus: authed.input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
|
|
5495
|
+
mcpReconnect: authed.input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
|
|
5496
|
+
mcpAuthenticate: authed.input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
|
|
5497
|
+
mcpOAuthCallbackUrl: authed.input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
|
|
5194
5498
|
subscribe: authed.input(RcSessionQuerySchema).output((0, import_server2.eventIterator)(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
|
|
5195
5499
|
const queue = [];
|
|
5196
5500
|
let wake;
|
|
@@ -11457,6 +11761,106 @@ function removeDirectoryRule(paths, rulePath) {
|
|
|
11457
11761
|
var import_node_crypto10 = require("node:crypto");
|
|
11458
11762
|
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
11459
11763
|
|
|
11764
|
+
// package.json
|
|
11765
|
+
var package_default = {
|
|
11766
|
+
name: "agent-shim",
|
|
11767
|
+
version: "8.24.0",
|
|
11768
|
+
description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
11769
|
+
license: "MIT",
|
|
11770
|
+
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
11771
|
+
repository: {
|
|
11772
|
+
type: "git",
|
|
11773
|
+
url: "git+https://github.com/ExaDev/agent-shim.git"
|
|
11774
|
+
},
|
|
11775
|
+
homepage: "https://github.com/ExaDev/agent-shim#readme",
|
|
11776
|
+
bugs: "https://github.com/ExaDev/agent-shim/issues",
|
|
11777
|
+
keywords: [
|
|
11778
|
+
"claude-code",
|
|
11779
|
+
"claude",
|
|
11780
|
+
"cli"
|
|
11781
|
+
],
|
|
11782
|
+
packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|
|
11783
|
+
type: "module",
|
|
11784
|
+
engines: {
|
|
11785
|
+
node: "^22.18 || >=24"
|
|
11786
|
+
},
|
|
11787
|
+
bin: {
|
|
11788
|
+
"agent-shim": "dist/cli.cjs",
|
|
11789
|
+
"claude-use": "dist/cli.cjs"
|
|
11790
|
+
},
|
|
11791
|
+
files: [
|
|
11792
|
+
"dist/cli.cjs",
|
|
11793
|
+
"dist/index.mjs",
|
|
11794
|
+
"dist/index.cjs",
|
|
11795
|
+
"dist/types"
|
|
11796
|
+
],
|
|
11797
|
+
scripts: {
|
|
11798
|
+
prepare: "husky && node scripts/build.mts --bundle-only",
|
|
11799
|
+
typecheck: "turbo run _typecheck",
|
|
11800
|
+
_typecheck: "tsc --noEmit",
|
|
11801
|
+
lint: "turbo run _lint",
|
|
11802
|
+
_lint: "eslint . --cache --cache-location .eslintcache --max-warnings 0",
|
|
11803
|
+
test: "turbo run _test",
|
|
11804
|
+
_test: "vitest run",
|
|
11805
|
+
"test:coverage": "turbo run _test:coverage",
|
|
11806
|
+
"_test:coverage": "vitest run --coverage",
|
|
11807
|
+
knip: "turbo run _knip",
|
|
11808
|
+
_knip: "knip --cache",
|
|
11809
|
+
build: "turbo run _build",
|
|
11810
|
+
_build: "node scripts/build.mts",
|
|
11811
|
+
"build:bundle": "node scripts/build.mts --bundle-only",
|
|
11812
|
+
prepublishOnly: "pnpm build:bundle",
|
|
11813
|
+
schema: "node scripts/gen-schema.mts"
|
|
11814
|
+
},
|
|
11815
|
+
dependencies: {
|
|
11816
|
+
"@clack/prompts": "^1.8.0",
|
|
11817
|
+
"@orpc/client": "1.15.4",
|
|
11818
|
+
"@orpc/server": "1.15.4",
|
|
11819
|
+
commander: "^15.0.0",
|
|
11820
|
+
cosmiconfig: "^10.0.1",
|
|
11821
|
+
picomatch: "^4.0.7",
|
|
11822
|
+
undici: "7.29.1",
|
|
11823
|
+
zod: "^4.6.1"
|
|
11824
|
+
},
|
|
11825
|
+
devDependencies: {
|
|
11826
|
+
"@commitlint/cli": "^21.2.2",
|
|
11827
|
+
"@commitlint/config-conventional": "^21.2.2",
|
|
11828
|
+
"@exadev/eslint-config": "2.12.1",
|
|
11829
|
+
"@semantic-release/changelog": "^7.0.0",
|
|
11830
|
+
"@semantic-release/git": "^11.0.1",
|
|
11831
|
+
"@semantic-release/npm": "^13.1.5",
|
|
11832
|
+
"@types/node": "^26.5.1",
|
|
11833
|
+
"@types/picomatch": "^4.0.3",
|
|
11834
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
11835
|
+
"conventional-changelog-conventionalcommits": "^10.4.0",
|
|
11836
|
+
esbuild: "^0.28.2",
|
|
11837
|
+
eslint: "^10.10.0",
|
|
11838
|
+
globals: "^17.12.0",
|
|
11839
|
+
husky: "^9.1.7",
|
|
11840
|
+
jiti: "^2.7.0",
|
|
11841
|
+
knip: "^6.35.1",
|
|
11842
|
+
"lint-staged": "^17.5.0",
|
|
11843
|
+
rollup: "4.64.0",
|
|
11844
|
+
"rollup-plugin-dts": "6.5.1",
|
|
11845
|
+
"semantic-release": "^25.0.9",
|
|
11846
|
+
turbo: "^2.11.5",
|
|
11847
|
+
typescript: "^6.0.3",
|
|
11848
|
+
"typescript-eslint": "^8.70.0",
|
|
11849
|
+
vitest: "^4.1.11"
|
|
11850
|
+
},
|
|
11851
|
+
main: "dist/index.cjs",
|
|
11852
|
+
module: "dist/index.mjs",
|
|
11853
|
+
types: "dist/types/index.d.ts",
|
|
11854
|
+
exports: {
|
|
11855
|
+
".": {
|
|
11856
|
+
types: "./dist/types/index.d.ts",
|
|
11857
|
+
import: "./dist/index.mjs",
|
|
11858
|
+
require: "./dist/index.cjs"
|
|
11859
|
+
},
|
|
11860
|
+
"./package.json": "./package.json"
|
|
11861
|
+
}
|
|
11862
|
+
};
|
|
11863
|
+
|
|
11460
11864
|
// src/launcher/argv.ts
|
|
11461
11865
|
var ConflictingIdentityError = class extends UsageError {
|
|
11462
11866
|
constructor(positional, flag) {
|
|
@@ -11929,6 +12333,88 @@ function spawnClaude(params) {
|
|
|
11929
12333
|
return params.proc.exit(exitCodeFor(result));
|
|
11930
12334
|
}
|
|
11931
12335
|
|
|
12336
|
+
// src/update/update.ts
|
|
12337
|
+
var LATEST_RELEASE_URL = "https://github.com/ExaDev/agent-shim/releases/latest";
|
|
12338
|
+
function compareVersions3(left, right) {
|
|
12339
|
+
const parse = (version) => {
|
|
12340
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
|
|
12341
|
+
if (match === null) {
|
|
12342
|
+
throw new Error(`not a plain release version: ${version}`);
|
|
12343
|
+
}
|
|
12344
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
12345
|
+
};
|
|
12346
|
+
const leftParts = parse(left);
|
|
12347
|
+
const rightParts = parse(right);
|
|
12348
|
+
return leftParts.map((part, index) => part - (rightParts[index] ?? 0)).find((difference) => difference !== 0) ?? 0;
|
|
12349
|
+
}
|
|
12350
|
+
function releaseTagFromUrl(url) {
|
|
12351
|
+
const segment = url.split("?")[0]?.split("/").at(-1);
|
|
12352
|
+
const candidate = segment?.startsWith("v") === true ? segment.slice(1) : void 0;
|
|
12353
|
+
return candidate !== void 0 && /^\d+\.\d+\.\d+$/.test(candidate) ? candidate : void 0;
|
|
12354
|
+
}
|
|
12355
|
+
|
|
12356
|
+
// src/update/launchHook.ts
|
|
12357
|
+
var UPDATE_CHECK_COOLDOWN_MS = 864e5;
|
|
12358
|
+
function resolveUpdateMode(globalConfig) {
|
|
12359
|
+
return globalConfig?.update?.mode ?? "off";
|
|
12360
|
+
}
|
|
12361
|
+
function updateCheckDue(contents, nowMs, cooldownMs = UPDATE_CHECK_COOLDOWN_MS) {
|
|
12362
|
+
if (contents === void 0) {
|
|
12363
|
+
return true;
|
|
12364
|
+
}
|
|
12365
|
+
const checkedAt = Date.parse(contents.trim());
|
|
12366
|
+
if (Number.isNaN(checkedAt)) {
|
|
12367
|
+
return true;
|
|
12368
|
+
}
|
|
12369
|
+
const age = nowMs - checkedAt;
|
|
12370
|
+
return age < 0 || age >= cooldownMs;
|
|
12371
|
+
}
|
|
12372
|
+
var NOOP_HANDLE = { markChildStarted: () => void 0 };
|
|
12373
|
+
function updateNotifyLine(currentVersion, latest) {
|
|
12374
|
+
return `agent-shim: update available: ${currentVersion} -> ${latest} (run \`agent-shim update\` to install it)`;
|
|
12375
|
+
}
|
|
12376
|
+
function runLaunchUpdateCheck(params) {
|
|
12377
|
+
const { mode, checkPath, currentVersion, port } = params;
|
|
12378
|
+
if (mode === "off" || port === void 0) {
|
|
12379
|
+
return NOOP_HANDLE;
|
|
12380
|
+
}
|
|
12381
|
+
let childStarted = false;
|
|
12382
|
+
try {
|
|
12383
|
+
if (!updateCheckDue(port.readStamp(checkPath), port.now())) {
|
|
12384
|
+
return NOOP_HANDLE;
|
|
12385
|
+
}
|
|
12386
|
+
port.writeStamp(checkPath, new Date(port.now()).toISOString());
|
|
12387
|
+
} catch {
|
|
12388
|
+
return NOOP_HANDLE;
|
|
12389
|
+
}
|
|
12390
|
+
const answer = (url) => {
|
|
12391
|
+
try {
|
|
12392
|
+
const latest = releaseTagFromUrl(url);
|
|
12393
|
+
if (latest === void 0 || compareVersions3(latest, currentVersion) <= 0) {
|
|
12394
|
+
return;
|
|
12395
|
+
}
|
|
12396
|
+
if (mode === "auto") {
|
|
12397
|
+
port.spawnDetached(["update"]);
|
|
12398
|
+
}
|
|
12399
|
+
if (!childStarted) {
|
|
12400
|
+
port.writeErr(updateNotifyLine(currentVersion, latest));
|
|
12401
|
+
}
|
|
12402
|
+
} catch {
|
|
12403
|
+
}
|
|
12404
|
+
};
|
|
12405
|
+
port.effectiveUrl(LATEST_RELEASE_URL).then(
|
|
12406
|
+
(url) => {
|
|
12407
|
+
answer(url);
|
|
12408
|
+
},
|
|
12409
|
+
() => void 0
|
|
12410
|
+
);
|
|
12411
|
+
return {
|
|
12412
|
+
markChildStarted: () => {
|
|
12413
|
+
childStarted = true;
|
|
12414
|
+
}
|
|
12415
|
+
};
|
|
12416
|
+
}
|
|
12417
|
+
|
|
11932
12418
|
// src/launcher.ts
|
|
11933
12419
|
function resolveIdentityCredential(identity, credential, env, port) {
|
|
11934
12420
|
if (port === void 0) {
|
|
@@ -12094,6 +12580,12 @@ function prepareLaunch(params) {
|
|
|
12094
12580
|
log.info(
|
|
12095
12581
|
`agent-shim: identity ${identityDecision.name ?? "(none)"} (${identityDecision.source}${poolExplanation === void 0 ? "" : `, ${poolExplanation}`}), config profile ${configProfileDecision.name ?? "(none)"} (${configProfileDecision.source})` + (resolvedProvider === void 0 ? "" : `, provider ${resolvedProvider.name} (credential ${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)})`) + (identityCredential === void 0 ? "" : `, identity credential ${identityCredential.target} from ${describeSource(identityCredential.source)}`)
|
|
12096
12582
|
);
|
|
12583
|
+
const updateCheck = runLaunchUpdateCheck({
|
|
12584
|
+
mode: params.updateMode ?? "off",
|
|
12585
|
+
checkPath: import_node_path30.default.join(paths.root, "update.check"),
|
|
12586
|
+
currentVersion: package_default.version,
|
|
12587
|
+
port: params.update
|
|
12588
|
+
});
|
|
12097
12589
|
let cascadeLaunch;
|
|
12098
12590
|
if (farmContext !== void 0) {
|
|
12099
12591
|
const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = farmContext;
|
|
@@ -12199,11 +12691,12 @@ function prepareLaunch(params) {
|
|
|
12199
12691
|
registered();
|
|
12200
12692
|
}
|
|
12201
12693
|
};
|
|
12202
|
-
return { bin: discovered.path, args: finalArgv, env: finalEnv, release };
|
|
12694
|
+
return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted };
|
|
12203
12695
|
}
|
|
12204
12696
|
function runLauncher(params) {
|
|
12205
12697
|
const plan = prepareLaunch(params);
|
|
12206
12698
|
try {
|
|
12699
|
+
plan.markChildStarted();
|
|
12207
12700
|
spawnClaude({ bin: plan.bin, args: plan.args, env: plan.env, spawn: params.spawn, proc: params.proc, beforeExit: plan.release });
|
|
12208
12701
|
} finally {
|
|
12209
12702
|
plan.release();
|
|
@@ -12366,6 +12859,7 @@ function buildFarmRuntime(paths, cwd) {
|
|
|
12366
12859
|
const loaded = loadCascadeInput({ paths, home, cwd, read });
|
|
12367
12860
|
const selections = readDirectorySelections(loaded);
|
|
12368
12861
|
const git = resolveGitBranch(realRunPort, cwd);
|
|
12862
|
+
const updateMode = resolveUpdateMode(loaded.globalConfig);
|
|
12369
12863
|
return {
|
|
12370
12864
|
runtime: {
|
|
12371
12865
|
fs: realFarmFs,
|
|
@@ -12391,7 +12885,8 @@ function buildFarmRuntime(paths, cwd) {
|
|
|
12391
12885
|
...selections.identity === void 0 ? {} : { directoryIdentity: selections.identity },
|
|
12392
12886
|
...selections.configProfile === void 0 ? {} : { directoryConfigProfile: selections.configProfile },
|
|
12393
12887
|
...loaded.globalConfig?.defaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: loaded.globalConfig.defaultConfigProfile },
|
|
12394
|
-
...loaded.globalConfig?.pools === void 0 ? {} : { pools: loaded.globalConfig.pools }
|
|
12888
|
+
...loaded.globalConfig?.pools === void 0 ? {} : { pools: loaded.globalConfig.pools },
|
|
12889
|
+
...updateMode === "off" ? {} : { updateMode }
|
|
12395
12890
|
};
|
|
12396
12891
|
}
|
|
12397
12892
|
function realClaudeBinaryResolver(paths) {
|
|
@@ -12413,6 +12908,7 @@ function realPrepareLaunchParams(paths, options) {
|
|
|
12413
12908
|
...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
|
|
12414
12909
|
...farm.globalDefaultConfigProfile === void 0 ? {} : { globalDefaultConfigProfile: farm.globalDefaultConfigProfile },
|
|
12415
12910
|
...farm.pools === void 0 ? {} : { pools: farm.pools },
|
|
12911
|
+
...farm.updateMode === void 0 ? {} : { updateMode: farm.updateMode },
|
|
12416
12912
|
...options.allowMissingConfigProfile === void 0 ? {} : { allowMissingConfigProfile: options.allowMissingConfigProfile }
|
|
12417
12913
|
};
|
|
12418
12914
|
}
|
|
@@ -12511,10 +13007,12 @@ function prepareClaudeLaunch(options) {
|
|
|
12511
13007
|
ProviderKindMismatchError,
|
|
12512
13008
|
ProviderNotFoundError,
|
|
12513
13009
|
ProviderSchema,
|
|
13010
|
+
RC_CONTEXT_USAGE_DETAILS,
|
|
12514
13011
|
RC_IDLE_EXPIRY_MS,
|
|
12515
13012
|
RC_ORPC_PATH_PREFIX,
|
|
12516
13013
|
RC_PENDING_DEADLINE_MS,
|
|
12517
13014
|
RC_PERMISSION_MODES,
|
|
13015
|
+
RC_READ_FILE_ENCODINGS,
|
|
12518
13016
|
RC_REQUEST_PARSE_CAP_BYTES,
|
|
12519
13017
|
RC_SELF_HOST_ENV,
|
|
12520
13018
|
RC_SELF_HOST_KEEPALIVE_MS,
|
|
@@ -12545,11 +13043,23 @@ function prepareClaudeLaunch(options) {
|
|
|
12545
13043
|
addPool,
|
|
12546
13044
|
addProvider,
|
|
12547
13045
|
answerRcControlRequest,
|
|
13046
|
+
authenticateRcSessionMcpServer,
|
|
12548
13047
|
buildEntryFacts,
|
|
12549
13048
|
buildLayoutPaths,
|
|
13049
|
+
buildRcControlRequestPayload,
|
|
12550
13050
|
buildRcControlResponsePayload,
|
|
13051
|
+
buildRcEndSessionPayload,
|
|
12551
13052
|
buildRcEventWriteBody,
|
|
13053
|
+
buildRcFileSuggestionsPayload,
|
|
13054
|
+
buildRcGetContextUsagePayload,
|
|
13055
|
+
buildRcGetUsagePayload,
|
|
12552
13056
|
buildRcInterruptPayload,
|
|
13057
|
+
buildRcKeepAlivePayload,
|
|
13058
|
+
buildRcMcpAuthenticatePayload,
|
|
13059
|
+
buildRcMcpOAuthCallbackUrlPayload,
|
|
13060
|
+
buildRcMcpReconnectPayload,
|
|
13061
|
+
buildRcMcpStatusPayload,
|
|
13062
|
+
buildRcReadFilePayload,
|
|
12553
13063
|
buildRcSetModelPayload,
|
|
12554
13064
|
buildRcSetPermissionModePayload,
|
|
12555
13065
|
buildRcUserMessagePayload,
|
|
@@ -12582,6 +13092,7 @@ function prepareClaudeLaunch(options) {
|
|
|
12582
13092
|
doorApiAuth,
|
|
12583
13093
|
doorApiNodeHandlerOf,
|
|
12584
13094
|
effectiveWindow,
|
|
13095
|
+
endRcSession,
|
|
12585
13096
|
ensureCa,
|
|
12586
13097
|
ensureFrontDoor,
|
|
12587
13098
|
ensureHeadroom,
|
|
@@ -12598,6 +13109,9 @@ function prepareClaudeLaunch(options) {
|
|
|
12598
13109
|
frontDoorRcApiClient,
|
|
12599
13110
|
frontDoorRcControl,
|
|
12600
13111
|
generateCa,
|
|
13112
|
+
getRcSessionContextUsage,
|
|
13113
|
+
getRcSessionMcpStatus,
|
|
13114
|
+
getRcSessionUsage,
|
|
12601
13115
|
headroomSocketTarget,
|
|
12602
13116
|
identityExists,
|
|
12603
13117
|
injectRcUserMessage,
|
|
@@ -12605,7 +13119,9 @@ function prepareClaudeLaunch(options) {
|
|
|
12605
13119
|
isIdentityDirectoryName,
|
|
12606
13120
|
isInterceptedHost,
|
|
12607
13121
|
isPrivateAddress,
|
|
13122
|
+
isRcContextUsageDetail,
|
|
12608
13123
|
isRcPermissionMode,
|
|
13124
|
+
isRcReadFileEncoding,
|
|
12609
13125
|
lateRcEventDial,
|
|
12610
13126
|
lateRcStreamDial,
|
|
12611
13127
|
listDirectoryRules,
|
|
@@ -12639,6 +13155,7 @@ function prepareClaudeLaunch(options) {
|
|
|
12639
13155
|
readProfile,
|
|
12640
13156
|
readProvider,
|
|
12641
13157
|
readRcSelfHostRecord,
|
|
13158
|
+
readRcSessionFile,
|
|
12642
13159
|
readUsageSnapshot,
|
|
12643
13160
|
realConnectCertStore,
|
|
12644
13161
|
realConnectEffects,
|
|
@@ -12646,6 +13163,7 @@ function prepareClaudeLaunch(options) {
|
|
|
12646
13163
|
realRcEventDial,
|
|
12647
13164
|
realRcStreamDial,
|
|
12648
13165
|
realRcWebFetch,
|
|
13166
|
+
reconnectRcSessionMcpServer,
|
|
12649
13167
|
recoverFarm,
|
|
12650
13168
|
recoveryDiagnostics,
|
|
12651
13169
|
removeDirectoryRule,
|
|
@@ -12665,6 +13183,7 @@ function prepareClaudeLaunch(options) {
|
|
|
12665
13183
|
runFrontDoorSupervisor,
|
|
12666
13184
|
runLauncher,
|
|
12667
13185
|
runSupervisor,
|
|
13186
|
+
sendRcKeepAlive,
|
|
12668
13187
|
servedByPipeline,
|
|
12669
13188
|
setAllowAmbientCredential,
|
|
12670
13189
|
setDefaultConfigProfile,
|
|
@@ -12680,6 +13199,8 @@ function prepareClaudeLaunch(options) {
|
|
|
12680
13199
|
snapshotPath,
|
|
12681
13200
|
spawnClaude,
|
|
12682
13201
|
startConnectServer,
|
|
13202
|
+
submitRcSessionMcpOAuthCallbackUrl,
|
|
13203
|
+
suggestRcSessionFiles,
|
|
12683
13204
|
topLevelNames,
|
|
12684
13205
|
updateDirectoryRule,
|
|
12685
13206
|
updateProvider,
|