agent-shim 8.28.0 → 8.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1691 -51
- package/dist/index.cjs +196 -137
- package/dist/index.mjs +195 -136
- package/dist/types/index.d.ts +85 -2
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -5028,10 +5028,113 @@ function createRcCredentialStore(fs12, dir) {
|
|
|
5028
5028
|
// src/frontdoor/rcApi.ts
|
|
5029
5029
|
import { createORPCClient, ORPCError } from "@orpc/client";
|
|
5030
5030
|
import { RPCLink } from "@orpc/client/fetch";
|
|
5031
|
+
import { OpenAPIGenerator } from "@orpc/openapi";
|
|
5032
|
+
import { OpenAPIHandler } from "@orpc/openapi/node";
|
|
5031
5033
|
import { eventIterator, os as os2, withEventMeta } from "@orpc/server";
|
|
5032
5034
|
import { BodyLimitPlugin, RPCHandler } from "@orpc/server/node";
|
|
5033
5035
|
import { Agent as Agent3, fetch as undiciFetch } from "undici";
|
|
5034
5036
|
|
|
5037
|
+
// package.json
|
|
5038
|
+
var package_default = {
|
|
5039
|
+
name: "agent-shim",
|
|
5040
|
+
version: "8.30.0",
|
|
5041
|
+
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.",
|
|
5042
|
+
license: "MIT",
|
|
5043
|
+
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
5044
|
+
repository: {
|
|
5045
|
+
type: "git",
|
|
5046
|
+
url: "git+https://github.com/ExaDev/agent-shim.git"
|
|
5047
|
+
},
|
|
5048
|
+
homepage: "https://github.com/ExaDev/agent-shim#readme",
|
|
5049
|
+
bugs: "https://github.com/ExaDev/agent-shim/issues",
|
|
5050
|
+
keywords: [
|
|
5051
|
+
"claude-code",
|
|
5052
|
+
"claude",
|
|
5053
|
+
"cli"
|
|
5054
|
+
],
|
|
5055
|
+
packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|
|
5056
|
+
type: "module",
|
|
5057
|
+
engines: {
|
|
5058
|
+
node: "^22.18 || >=24"
|
|
5059
|
+
},
|
|
5060
|
+
bin: {
|
|
5061
|
+
"agent-shim": "dist/cli.cjs",
|
|
5062
|
+
"claude-use": "dist/cli.cjs"
|
|
5063
|
+
},
|
|
5064
|
+
files: [
|
|
5065
|
+
"dist/cli.cjs",
|
|
5066
|
+
"dist/index.mjs",
|
|
5067
|
+
"dist/index.cjs",
|
|
5068
|
+
"dist/types"
|
|
5069
|
+
],
|
|
5070
|
+
scripts: {
|
|
5071
|
+
prepare: "husky && node scripts/build.mts --bundle-only",
|
|
5072
|
+
typecheck: "turbo run _typecheck",
|
|
5073
|
+
_typecheck: "tsc --noEmit",
|
|
5074
|
+
lint: "turbo run _lint",
|
|
5075
|
+
_lint: "eslint . --cache --cache-location .eslintcache --max-warnings 0",
|
|
5076
|
+
test: "turbo run _test",
|
|
5077
|
+
_test: "vitest run",
|
|
5078
|
+
"test:coverage": "turbo run _test:coverage",
|
|
5079
|
+
"_test:coverage": "vitest run --coverage",
|
|
5080
|
+
knip: "turbo run _knip",
|
|
5081
|
+
_knip: "knip --cache",
|
|
5082
|
+
build: "turbo run _build",
|
|
5083
|
+
_build: "node scripts/build.mts",
|
|
5084
|
+
"build:bundle": "node scripts/build.mts --bundle-only",
|
|
5085
|
+
prepublishOnly: "pnpm build:bundle",
|
|
5086
|
+
schema: "node scripts/gen-schema.mts"
|
|
5087
|
+
},
|
|
5088
|
+
dependencies: {
|
|
5089
|
+
"@clack/prompts": "^1.8.0",
|
|
5090
|
+
"@orpc/client": "1.15.4",
|
|
5091
|
+
"@orpc/openapi": "1.15.4",
|
|
5092
|
+
"@orpc/server": "1.15.4",
|
|
5093
|
+
commander: "^15.0.0",
|
|
5094
|
+
cosmiconfig: "^10.0.1",
|
|
5095
|
+
picomatch: "^4.0.7",
|
|
5096
|
+
undici: "7.29.1",
|
|
5097
|
+
zod: "^4.6.1"
|
|
5098
|
+
},
|
|
5099
|
+
devDependencies: {
|
|
5100
|
+
"@commitlint/cli": "^21.2.2",
|
|
5101
|
+
"@commitlint/config-conventional": "^21.2.2",
|
|
5102
|
+
"@exadev/eslint-config": "2.12.1",
|
|
5103
|
+
"@semantic-release/changelog": "^7.0.0",
|
|
5104
|
+
"@semantic-release/git": "^11.0.1",
|
|
5105
|
+
"@semantic-release/npm": "^13.1.5",
|
|
5106
|
+
"@types/node": "^26.5.1",
|
|
5107
|
+
"@types/picomatch": "^4.0.3",
|
|
5108
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
5109
|
+
"conventional-changelog-conventionalcommits": "^10.4.0",
|
|
5110
|
+
esbuild: "^0.28.2",
|
|
5111
|
+
eslint: "^10.10.0",
|
|
5112
|
+
globals: "^17.12.0",
|
|
5113
|
+
husky: "^9.1.7",
|
|
5114
|
+
jiti: "^2.7.0",
|
|
5115
|
+
knip: "^6.35.1",
|
|
5116
|
+
"lint-staged": "^17.5.0",
|
|
5117
|
+
rollup: "4.64.0",
|
|
5118
|
+
"rollup-plugin-dts": "6.5.1",
|
|
5119
|
+
"semantic-release": "^25.0.9",
|
|
5120
|
+
turbo: "^2.11.5",
|
|
5121
|
+
typescript: "^6.0.3",
|
|
5122
|
+
"typescript-eslint": "^8.70.0",
|
|
5123
|
+
vitest: "^4.1.11"
|
|
5124
|
+
},
|
|
5125
|
+
main: "dist/index.cjs",
|
|
5126
|
+
module: "dist/index.mjs",
|
|
5127
|
+
types: "dist/types/index.d.ts",
|
|
5128
|
+
exports: {
|
|
5129
|
+
".": {
|
|
5130
|
+
types: "./dist/types/index.d.ts",
|
|
5131
|
+
import: "./dist/index.mjs",
|
|
5132
|
+
require: "./dist/index.cjs"
|
|
5133
|
+
},
|
|
5134
|
+
"./package.json": "./package.json"
|
|
5135
|
+
}
|
|
5136
|
+
};
|
|
5137
|
+
|
|
5035
5138
|
// src/frontdoor/rcSchemas.ts
|
|
5036
5139
|
import { z as z4 } from "zod";
|
|
5037
5140
|
var RcPermissionModeSchema = z4.enum(RC_PERMISSION_MODES);
|
|
@@ -5193,18 +5296,23 @@ var RcAnswerOutputSchema = z4.strictObject({
|
|
|
5193
5296
|
|
|
5194
5297
|
// src/frontdoor/rcApi.ts
|
|
5195
5298
|
var RC_ORPC_PATH_PREFIX = "/__agent-shim/orpc";
|
|
5299
|
+
var RC_OPENAPI_DOC_PATH = "/openapi.json";
|
|
5196
5300
|
var RC_SUBSCRIBER_BUFFER_EVENTS = 100;
|
|
5301
|
+
function doorApiBearer(headers) {
|
|
5302
|
+
const presented = headers.authorization;
|
|
5303
|
+
const bearerPrefix = "bearer ".length;
|
|
5304
|
+
return typeof presented === "string" && presented.slice(0, bearerPrefix).toLowerCase() === "bearer " ? presented.slice(bearerPrefix) : void 0;
|
|
5305
|
+
}
|
|
5197
5306
|
function doorApiAuth(expectedToken) {
|
|
5198
5307
|
return os2.$context().use(({ context, next }) => {
|
|
5199
|
-
const
|
|
5200
|
-
const bearerPrefix = "bearer ".length;
|
|
5201
|
-
const token = typeof presented === "string" && presented.slice(0, bearerPrefix).toLowerCase() === "bearer " ? presented.slice(bearerPrefix) : void 0;
|
|
5308
|
+
const token = doorApiBearer(context.headers);
|
|
5202
5309
|
if (token === void 0 || !isLiveCapability(token, [expectedToken])) {
|
|
5203
5310
|
throw new ORPCError("UNAUTHORIZED", { message: "the front door's typed API demands this generation's control token as a Bearer credential" });
|
|
5204
5311
|
}
|
|
5205
5312
|
return next();
|
|
5206
5313
|
});
|
|
5207
5314
|
}
|
|
5315
|
+
var RC_API_TAG = "remote-control";
|
|
5208
5316
|
function createRcApiRouter(deps) {
|
|
5209
5317
|
const authed = doorApiAuth(deps.expectedToken);
|
|
5210
5318
|
const delivered = (sessionId, result) => {
|
|
@@ -5224,41 +5332,41 @@ function createRcApiRouter(deps) {
|
|
|
5224
5332
|
};
|
|
5225
5333
|
return {
|
|
5226
5334
|
rc: {
|
|
5227
|
-
list: authed.output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
|
|
5228
|
-
status: authed.input(RcSessionQuerySchema).output(RcStatusOutputSchema).handler(({ input }) => {
|
|
5335
|
+
list: authed.route({ method: "GET", path: "/rest/rc/sessions", summary: "List the observed Remote Control sessions", tags: [RC_API_TAG] }).output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
|
|
5336
|
+
status: authed.route({ method: "GET", path: "/rest/rc/status", summary: "Read session status, one session's when named", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output(RcStatusOutputSchema).handler(({ input }) => {
|
|
5229
5337
|
const statuses = deps.statusOf(input.session);
|
|
5230
5338
|
if (input.session !== void 0 && !statuses.some((entry) => entry.id === input.session)) {
|
|
5231
5339
|
throw new ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
|
|
5232
5340
|
}
|
|
5233
5341
|
return { statuses };
|
|
5234
5342
|
}),
|
|
5235
|
-
pending: authed.input(RcSessionQuerySchema).output(RcPendingOutputSchema).handler(({ input }) => {
|
|
5343
|
+
pending: authed.route({ method: "GET", path: "/rest/rc/pending", summary: "Read the control requests awaiting an answer", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output(RcPendingOutputSchema).handler(({ input }) => {
|
|
5236
5344
|
const pending = deps.pendingOf(input.session);
|
|
5237
5345
|
if (input.session !== void 0 && deps.statusOf(input.session).length === 0) {
|
|
5238
5346
|
throw new ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
|
|
5239
5347
|
}
|
|
5240
5348
|
return { pending };
|
|
5241
5349
|
}),
|
|
5242
|
-
send: authed.input(RcSendInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.inject(input.session, input.text)) })),
|
|
5243
|
-
answer: authed.input(RcAnswerInputSchema).output(RcAnswerOutputSchema).handler(async ({ input }) => {
|
|
5350
|
+
send: authed.route({ method: "POST", path: "/rest/rc/send", summary: "Send one message into a session", tags: [RC_API_TAG] }).input(RcSendInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.inject(input.session, input.text)) })),
|
|
5351
|
+
answer: authed.route({ method: "POST", path: "/rest/rc/answer", summary: "Answer one pending control request", tags: [RC_API_TAG] }).input(RcAnswerInputSchema).output(RcAnswerOutputSchema).handler(async ({ input }) => {
|
|
5244
5352
|
const decision = { approve: input.approve, message: input.approve || input.text === void 0 ? void 0 : input.text };
|
|
5245
5353
|
return { session: input.session, request: input.request, sequenceNums: delivered(input.session, await deps.answer(input.session, input.request, decision)) };
|
|
5246
5354
|
}),
|
|
5247
|
-
interrupt: authed.input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
|
|
5248
|
-
setModel: authed.input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
|
|
5249
|
-
setPermissionMode: authed.input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
|
|
5250
|
-
endSession: authed.input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
|
|
5251
|
-
getUsage: authed.input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
|
|
5252
|
-
getContextUsage: authed.input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
|
|
5253
|
-
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 } })) })),
|
|
5254
|
-
fileSuggestions: authed.input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
|
|
5255
|
-
keepAlive: authed.input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
|
|
5256
|
-
mcpStatus: authed.input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
|
|
5257
|
-
mcpReconnect: authed.input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
|
|
5258
|
-
mcpAuthenticate: authed.input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
|
|
5259
|
-
mcpOAuthCallbackUrl: authed.input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
|
|
5260
|
-
teleport: authed.input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.teleport(input.session, input.marker)) })),
|
|
5261
|
-
subscribe: authed.input(RcSessionQuerySchema).output(eventIterator(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
|
|
5355
|
+
interrupt: authed.route({ method: "POST", path: "/rest/rc/interrupt", summary: "Interrupt a session's running turn", tags: [RC_API_TAG] }).input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
|
|
5356
|
+
setModel: authed.route({ method: "POST", path: "/rest/rc/set-model", summary: "Switch a session's model", tags: [RC_API_TAG] }).input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
|
|
5357
|
+
setPermissionMode: authed.route({ method: "POST", path: "/rest/rc/set-permission-mode", summary: "Switch a session's permission mode", tags: [RC_API_TAG] }).input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
|
|
5358
|
+
endSession: authed.route({ method: "POST", path: "/rest/rc/end-session", summary: "End a session", tags: [RC_API_TAG] }).input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
|
|
5359
|
+
getUsage: authed.route({ method: "POST", path: "/rest/rc/get-usage", summary: "Ask a session for its usage snapshot", tags: [RC_API_TAG] }).input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
|
|
5360
|
+
getContextUsage: authed.route({ method: "POST", path: "/rest/rc/get-context-usage", summary: "Ask a session for its context usage", tags: [RC_API_TAG] }).input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
|
|
5361
|
+
readFile: authed.route({ method: "POST", path: "/rest/rc/read-file", summary: "Ask a session to read one file", tags: [RC_API_TAG] }).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 } })) })),
|
|
5362
|
+
fileSuggestions: authed.route({ method: "POST", path: "/rest/rc/file-suggestions", summary: "Ask a session for file-path suggestions", tags: [RC_API_TAG] }).input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
|
|
5363
|
+
keepAlive: authed.route({ method: "POST", path: "/rest/rc/keep-alive", summary: "Keep a session's bridge alive", tags: [RC_API_TAG] }).input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
|
|
5364
|
+
mcpStatus: authed.route({ method: "POST", path: "/rest/rc/mcp-status", summary: "Ask a session for its MCP servers' status", tags: [RC_API_TAG] }).input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
|
|
5365
|
+
mcpReconnect: authed.route({ method: "POST", path: "/rest/rc/mcp-reconnect", summary: "Ask a session to reconnect one MCP server", tags: [RC_API_TAG] }).input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
|
|
5366
|
+
mcpAuthenticate: authed.route({ method: "POST", path: "/rest/rc/mcp-authenticate", summary: "Start OAuth for one MCP server on a session", tags: [RC_API_TAG] }).input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
|
|
5367
|
+
mcpOAuthCallbackUrl: authed.route({ method: "POST", path: "/rest/rc/mcp-oauth-callback-url", summary: "Hand a completed MCP OAuth callback to a session", tags: [RC_API_TAG] }).input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
|
|
5368
|
+
teleport: authed.route({ method: "POST", path: "/rest/rc/teleport", summary: "Teleport a session to a conversation marker", tags: [RC_API_TAG] }).input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.teleport(input.session, input.marker)) })),
|
|
5369
|
+
subscribe: authed.route({ method: "GET", path: "/rest/rc/events", summary: "Stream a session's Remote Control events (SSE)", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output(eventIterator(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
|
|
5262
5370
|
const queue = [];
|
|
5263
5371
|
let wake;
|
|
5264
5372
|
const detach = deps.fanout.subscribe(input.session, (event) => {
|
|
@@ -5295,15 +5403,44 @@ function createRcApiRouter(deps) {
|
|
|
5295
5403
|
}
|
|
5296
5404
|
};
|
|
5297
5405
|
}
|
|
5298
|
-
function doorApiNodeHandlerOf(router) {
|
|
5299
|
-
const
|
|
5406
|
+
function doorApiNodeHandlerOf(router, expectedToken) {
|
|
5407
|
+
const plugins = [new BodyLimitPlugin({ maxBodySize: CONTROL_BODY_CAP_BYTES })];
|
|
5408
|
+
const rpcHandler = new RPCHandler(router, { plugins });
|
|
5409
|
+
const restHandler = new OpenAPIHandler(router, { plugins });
|
|
5410
|
+
let document;
|
|
5411
|
+
const documentOf = async () => document ??= new OpenAPIGenerator().generate(router, { info: { title: "agent-shim front door API", version: package_default.version } });
|
|
5300
5412
|
return {
|
|
5301
5413
|
pathPrefix: RC_ORPC_PATH_PREFIX,
|
|
5302
|
-
handle: async (request4, response) =>
|
|
5414
|
+
handle: async (request4, response) => {
|
|
5415
|
+
if (request4.method === "GET" && request4.url === `${RC_ORPC_PATH_PREFIX}${RC_OPENAPI_DOC_PATH}`) {
|
|
5416
|
+
const token = doorApiBearer(request4.headers);
|
|
5417
|
+
if (token === void 0 || !isLiveCapability(token, [expectedToken])) {
|
|
5418
|
+
const refusal = new ORPCError("UNAUTHORIZED", { message: "the front door's OpenAPI document demands this generation's control token as a Bearer credential" });
|
|
5419
|
+
response.writeHead(HTTP_STATUS.unauthorized, { "content-type": "application/json" });
|
|
5420
|
+
response.end(JSON.stringify(refusal.toJSON()));
|
|
5421
|
+
return { matched: true };
|
|
5422
|
+
}
|
|
5423
|
+
try {
|
|
5424
|
+
const doc = await documentOf();
|
|
5425
|
+
response.writeHead(HTTP_STATUS.ok, { "content-type": "application/json" });
|
|
5426
|
+
response.end(JSON.stringify(doc));
|
|
5427
|
+
} catch (error) {
|
|
5428
|
+
const refusal = new ORPCError("INTERNAL_SERVER_ERROR", { message: `the OpenAPI document could not be generated from the door's own router: ${error instanceof Error ? error.message : String(error)}` });
|
|
5429
|
+
response.writeHead(HTTP_STATUS.internalServerError, { "content-type": "application/json" });
|
|
5430
|
+
response.end(JSON.stringify(refusal.toJSON()));
|
|
5431
|
+
}
|
|
5432
|
+
return { matched: true };
|
|
5433
|
+
}
|
|
5434
|
+
const rest = await restHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
|
|
5435
|
+
if (rest.matched) {
|
|
5436
|
+
return rest;
|
|
5437
|
+
}
|
|
5438
|
+
return await rpcHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
|
|
5439
|
+
}
|
|
5303
5440
|
};
|
|
5304
5441
|
}
|
|
5305
5442
|
function createRcApiNodeHandler(deps) {
|
|
5306
|
-
return doorApiNodeHandlerOf(createRcApiRouter(deps));
|
|
5443
|
+
return doorApiNodeHandlerOf(createRcApiRouter(deps), deps.expectedToken);
|
|
5307
5444
|
}
|
|
5308
5445
|
function frontDoorApiLink(port, ca, token) {
|
|
5309
5446
|
const dispatcher = new Agent3({ connect: { ca } });
|
|
@@ -9738,6 +9875,10 @@ var CheckRunInputSchema = z19.strictObject({
|
|
|
9738
9875
|
path: z19.string().min(1),
|
|
9739
9876
|
identity: z19.string().min(1).optional()
|
|
9740
9877
|
}).refine((input) => path27.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
9878
|
+
var PoolPickInputSchema = z19.strictObject({
|
|
9879
|
+
pool: z19.string().min(1),
|
|
9880
|
+
path: z19.string().min(1)
|
|
9881
|
+
}).refine((input) => path27.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
9741
9882
|
var DoctorFindingSchema = z19.strictObject({
|
|
9742
9883
|
section: z19.enum(DOCTOR_SECTIONS),
|
|
9743
9884
|
subject: z19.string().optional(),
|
|
@@ -9775,11 +9916,12 @@ var LaunchLifecycleEventSchema = z20.strictObject({
|
|
|
9775
9916
|
});
|
|
9776
9917
|
|
|
9777
9918
|
// src/frontdoor/eventsApi.ts
|
|
9919
|
+
var EVENTS_API_TAG = "events";
|
|
9778
9920
|
function createEventsApiRouter(deps) {
|
|
9779
9921
|
const authed = doorApiAuth(deps.expectedToken);
|
|
9780
9922
|
return {
|
|
9781
9923
|
events: {
|
|
9782
|
-
subscribe: authed.input(DoorEventSourceQuerySchema).output(eventIterator2(DoorEventSchema)).handler(async function* ({ input, signal }) {
|
|
9924
|
+
subscribe: authed.route({ method: "GET", path: "/rest/events", summary: "Stream the door's every event source (SSE)", tags: [EVENTS_API_TAG] }).input(DoorEventSourceQuerySchema).output(eventIterator2(DoorEventSchema)).handler(async function* ({ input, signal }) {
|
|
9783
9925
|
if (input.sources !== void 0) {
|
|
9784
9926
|
const live = deps.events.sources();
|
|
9785
9927
|
const unknown = input.sources.filter((source) => !live.includes(source));
|
|
@@ -9812,12 +9954,17 @@ function createEventsApiRouter(deps) {
|
|
|
9812
9954
|
}
|
|
9813
9955
|
|
|
9814
9956
|
// src/frontdoor/controlApi.ts
|
|
9957
|
+
var USAGE_API_TAG = "usage";
|
|
9958
|
+
var FRONTDOOR_API_TAG = "frontdoor";
|
|
9959
|
+
var CHECK_API_TAG = "check";
|
|
9960
|
+
var DOCTOR_API_TAG = "doctor";
|
|
9961
|
+
var POOL_API_TAG = "pool";
|
|
9815
9962
|
function createControlApiRouter(deps) {
|
|
9816
9963
|
const authed = doorApiAuth(deps.expectedToken);
|
|
9817
9964
|
return {
|
|
9818
9965
|
usage: {
|
|
9819
|
-
list: authed.output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
|
|
9820
|
-
effectiveWindow: authed.input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
|
|
9966
|
+
list: authed.route({ method: "GET", path: "/rest/usage/snapshots", summary: "List every identity's usage snapshot", tags: [USAGE_API_TAG] }).output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
|
|
9967
|
+
effectiveWindow: authed.route({ method: "GET", path: "/rest/usage/windows", summary: "Read one identity's effective quota windows", tags: [USAGE_API_TAG] }).input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
|
|
9821
9968
|
const snapshot = deps.usageSnapshotOf(input.identity);
|
|
9822
9969
|
if (snapshot === void 0) {
|
|
9823
9970
|
throw new ORPCError3("NOT_FOUND", { message: `identity ${input.identity} has no usage snapshot yet, so no quota window has been observed for it` });
|
|
@@ -9834,7 +9981,7 @@ function createControlApiRouter(deps) {
|
|
|
9834
9981
|
...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
|
|
9835
9982
|
};
|
|
9836
9983
|
}),
|
|
9837
|
-
live: authed.input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
|
|
9984
|
+
live: authed.route({ method: "GET", path: "/rest/usage/live", summary: "Read the live rate-limit observations the event backbone files", tags: [USAGE_API_TAG] }).input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
|
|
9838
9985
|
const sessions = deps.liveRateLimits(input.session);
|
|
9839
9986
|
if (input.session !== void 0 && sessions.length === 0) {
|
|
9840
9987
|
if (deps.list().some((session) => session.id === input.session)) {
|
|
@@ -9846,15 +9993,27 @@ function createControlApiRouter(deps) {
|
|
|
9846
9993
|
})
|
|
9847
9994
|
},
|
|
9848
9995
|
frontdoor: {
|
|
9849
|
-
status: authed.output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
|
|
9850
|
-
sessions: authed.output(FrontDoorSessionsOutputSchema).handler(() => ({ sessions: deps.frontDoorStatus().sessions }))
|
|
9996
|
+
status: authed.route({ method: "GET", path: "/rest/frontdoor/status", summary: "Read the front door's status", tags: [FRONTDOOR_API_TAG] }).output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
|
|
9997
|
+
sessions: authed.route({ method: "GET", path: "/rest/frontdoor/sessions", summary: "Read the front door's session registry", tags: [FRONTDOOR_API_TAG] }).output(FrontDoorSessionsOutputSchema).handler(() => ({ sessions: deps.frontDoorStatus().sessions }))
|
|
9851
9998
|
},
|
|
9852
9999
|
check: {
|
|
9853
10000
|
// The report's own JSON shape is the contract (the same one `check --json` prints and `checkReportSchema.ts` defines), so the procedure returns exactly that conversion.
|
|
9854
|
-
run: authed.input(CheckRunInputSchema).output(CheckReportJsonSchema).handler(({ input }) => checkReportToJson(deps.checkReport(input.path, input.identity)))
|
|
10001
|
+
run: authed.route({ method: "GET", path: "/rest/check", summary: "Run the check report for one directory", tags: [CHECK_API_TAG] }).input(CheckRunInputSchema).output(CheckReportJsonSchema).handler(({ input }) => checkReportToJson(deps.checkReport(input.path, input.identity)))
|
|
9855
10002
|
},
|
|
9856
10003
|
doctor: {
|
|
9857
|
-
run: authed.output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
|
|
10004
|
+
run: authed.route({ method: "GET", path: "/rest/doctor", summary: "Run the doctor report", tags: [DOCTOR_API_TAG] }).output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
|
|
10005
|
+
},
|
|
10006
|
+
pool: {
|
|
10007
|
+
pick: authed.route({ method: "GET", path: "/rest/pool/pick", summary: "Rank one pool exactly as a launch from a directory would right now", tags: [POOL_API_TAG] }).input(PoolPickInputSchema).output(PoolPickReportSchema).handler(({ input }) => {
|
|
10008
|
+
const report = deps.poolPick(input.pool, input.path);
|
|
10009
|
+
if (report === void 0) {
|
|
10010
|
+
const live = deps.poolNames();
|
|
10011
|
+
throw new ORPCError3("NOT_FOUND", {
|
|
10012
|
+
message: live.length === 0 ? `no pools are configured, so none is named ${input.pool}` : `no pool is named ${input.pool}; the live pools are ${live.map((name) => `"${name}"`).join(", ")}`
|
|
10013
|
+
});
|
|
10014
|
+
}
|
|
10015
|
+
return report;
|
|
10016
|
+
})
|
|
9858
10017
|
}
|
|
9859
10018
|
};
|
|
9860
10019
|
}
|
|
@@ -9862,7 +10021,7 @@ function createDoorApiRouter(deps) {
|
|
|
9862
10021
|
return { ...createRcApiRouter(deps), ...createControlApiRouter(deps), ...createEventsApiRouter(deps) };
|
|
9863
10022
|
}
|
|
9864
10023
|
function createDoorApiNodeHandler(deps) {
|
|
9865
|
-
return doorApiNodeHandlerOf(createDoorApiRouter(deps));
|
|
10024
|
+
return doorApiNodeHandlerOf(createDoorApiRouter(deps), deps.expectedToken);
|
|
9866
10025
|
}
|
|
9867
10026
|
function frontDoorApiClient(port, ca, token) {
|
|
9868
10027
|
return createORPCClient2(frontDoorApiLink(port, ca, token));
|
|
@@ -11948,106 +12107,6 @@ function removeDirectoryRule(paths, rulePath) {
|
|
|
11948
12107
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
11949
12108
|
import path30 from "node:path";
|
|
11950
12109
|
|
|
11951
|
-
// package.json
|
|
11952
|
-
var package_default = {
|
|
11953
|
-
name: "agent-shim",
|
|
11954
|
-
version: "8.28.0",
|
|
11955
|
-
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.",
|
|
11956
|
-
license: "MIT",
|
|
11957
|
-
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
11958
|
-
repository: {
|
|
11959
|
-
type: "git",
|
|
11960
|
-
url: "git+https://github.com/ExaDev/agent-shim.git"
|
|
11961
|
-
},
|
|
11962
|
-
homepage: "https://github.com/ExaDev/agent-shim#readme",
|
|
11963
|
-
bugs: "https://github.com/ExaDev/agent-shim/issues",
|
|
11964
|
-
keywords: [
|
|
11965
|
-
"claude-code",
|
|
11966
|
-
"claude",
|
|
11967
|
-
"cli"
|
|
11968
|
-
],
|
|
11969
|
-
packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|
|
11970
|
-
type: "module",
|
|
11971
|
-
engines: {
|
|
11972
|
-
node: "^22.18 || >=24"
|
|
11973
|
-
},
|
|
11974
|
-
bin: {
|
|
11975
|
-
"agent-shim": "dist/cli.cjs",
|
|
11976
|
-
"claude-use": "dist/cli.cjs"
|
|
11977
|
-
},
|
|
11978
|
-
files: [
|
|
11979
|
-
"dist/cli.cjs",
|
|
11980
|
-
"dist/index.mjs",
|
|
11981
|
-
"dist/index.cjs",
|
|
11982
|
-
"dist/types"
|
|
11983
|
-
],
|
|
11984
|
-
scripts: {
|
|
11985
|
-
prepare: "husky && node scripts/build.mts --bundle-only",
|
|
11986
|
-
typecheck: "turbo run _typecheck",
|
|
11987
|
-
_typecheck: "tsc --noEmit",
|
|
11988
|
-
lint: "turbo run _lint",
|
|
11989
|
-
_lint: "eslint . --cache --cache-location .eslintcache --max-warnings 0",
|
|
11990
|
-
test: "turbo run _test",
|
|
11991
|
-
_test: "vitest run",
|
|
11992
|
-
"test:coverage": "turbo run _test:coverage",
|
|
11993
|
-
"_test:coverage": "vitest run --coverage",
|
|
11994
|
-
knip: "turbo run _knip",
|
|
11995
|
-
_knip: "knip --cache",
|
|
11996
|
-
build: "turbo run _build",
|
|
11997
|
-
_build: "node scripts/build.mts",
|
|
11998
|
-
"build:bundle": "node scripts/build.mts --bundle-only",
|
|
11999
|
-
prepublishOnly: "pnpm build:bundle",
|
|
12000
|
-
schema: "node scripts/gen-schema.mts"
|
|
12001
|
-
},
|
|
12002
|
-
dependencies: {
|
|
12003
|
-
"@clack/prompts": "^1.8.0",
|
|
12004
|
-
"@orpc/client": "1.15.4",
|
|
12005
|
-
"@orpc/server": "1.15.4",
|
|
12006
|
-
commander: "^15.0.0",
|
|
12007
|
-
cosmiconfig: "^10.0.1",
|
|
12008
|
-
picomatch: "^4.0.7",
|
|
12009
|
-
undici: "7.29.1",
|
|
12010
|
-
zod: "^4.6.1"
|
|
12011
|
-
},
|
|
12012
|
-
devDependencies: {
|
|
12013
|
-
"@commitlint/cli": "^21.2.2",
|
|
12014
|
-
"@commitlint/config-conventional": "^21.2.2",
|
|
12015
|
-
"@exadev/eslint-config": "2.12.1",
|
|
12016
|
-
"@semantic-release/changelog": "^7.0.0",
|
|
12017
|
-
"@semantic-release/git": "^11.0.1",
|
|
12018
|
-
"@semantic-release/npm": "^13.1.5",
|
|
12019
|
-
"@types/node": "^26.5.1",
|
|
12020
|
-
"@types/picomatch": "^4.0.3",
|
|
12021
|
-
"@vitest/coverage-v8": "^4.1.11",
|
|
12022
|
-
"conventional-changelog-conventionalcommits": "^10.4.0",
|
|
12023
|
-
esbuild: "^0.28.2",
|
|
12024
|
-
eslint: "^10.10.0",
|
|
12025
|
-
globals: "^17.12.0",
|
|
12026
|
-
husky: "^9.1.7",
|
|
12027
|
-
jiti: "^2.7.0",
|
|
12028
|
-
knip: "^6.35.1",
|
|
12029
|
-
"lint-staged": "^17.5.0",
|
|
12030
|
-
rollup: "4.64.0",
|
|
12031
|
-
"rollup-plugin-dts": "6.5.1",
|
|
12032
|
-
"semantic-release": "^25.0.9",
|
|
12033
|
-
turbo: "^2.11.5",
|
|
12034
|
-
typescript: "^6.0.3",
|
|
12035
|
-
"typescript-eslint": "^8.70.0",
|
|
12036
|
-
vitest: "^4.1.11"
|
|
12037
|
-
},
|
|
12038
|
-
main: "dist/index.cjs",
|
|
12039
|
-
module: "dist/index.mjs",
|
|
12040
|
-
types: "dist/types/index.d.ts",
|
|
12041
|
-
exports: {
|
|
12042
|
-
".": {
|
|
12043
|
-
types: "./dist/types/index.d.ts",
|
|
12044
|
-
import: "./dist/index.mjs",
|
|
12045
|
-
require: "./dist/index.cjs"
|
|
12046
|
-
},
|
|
12047
|
-
"./package.json": "./package.json"
|
|
12048
|
-
}
|
|
12049
|
-
};
|
|
12050
|
-
|
|
12051
12110
|
// src/launcher/argv.ts
|
|
12052
12111
|
var ConflictingIdentityError = class extends UsageError {
|
|
12053
12112
|
constructor(positional, flag) {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2503,6 +2503,8 @@ interface PrePipelineApi {
|
|
|
2503
2503
|
* Mounted on the provider listener beside the bespoke namespace, authenticated by the same per-generation owner-only control token as a Bearer credential: a fresh random value per door start, written owner-only under the front door's state directory, and checked in constant time like every other capability the door accepts. `rc.subscribe` streams the client attachment's fan-out: every event the door's held stream produced, SSE-framed by oRPC's event iterator, each carrying its sequence number as the SSE event id so a consumer's own reconnect can resume exactly as the door's does.
|
|
2504
2504
|
*
|
|
2505
2505
|
* This module also owns the mount's router-agnostic plumbing, which the control-plane routers (`controlApi.ts`) serve on the same prefix under the same token: the control-token middleware (`doorApiAuth`), the node-handler builder (`doorApiNodeHandlerOf`) and the TLS-pinned client link (`frontDoorApiLink`).
|
|
2506
|
+
*
|
|
2507
|
+
* Every procedure is route-annotated (method, path, summary, tags) under the mount's one REST namespace (`/rest/...`), so the mount serves the same operations twice over: as the oRPC RPC protocol the typed clients and the web client speak, and as plain REST for consumers with no TypeScript client (curl, scripts, other languages), with the OpenAPI document of the whole surface at `RC_OPENAPI_DOC_PATH` under the same token. The two share one router, one token middleware and one Zod schema source, so nothing can drift between them; an annotated (method, path) pair is served REST-shaped and everything else falls through to the RPC handler, and no RPC procedure path begins with `/rest`, so neither address space can ever capture the other.
|
|
2506
2508
|
*/
|
|
2507
2509
|
/** The one path prefix the typed API is mounted under, answered before the routed pipeline like the bespoke control routes are. */
|
|
2508
2510
|
declare const RC_ORPC_PATH_PREFIX = "/__agent-shim/orpc";
|
|
@@ -2751,9 +2753,9 @@ declare function createRcApiRouter(deps: RcApiDeps): {
|
|
|
2751
2753
|
/** The typed API's router, as the CLI-side client's own type is derived from it. */
|
|
2752
2754
|
type RcApiRouter = ReturnType<typeof createRcApiRouter>;
|
|
2753
2755
|
/**
|
|
2754
|
-
* Builds the node handler that serves one router of the door's typed API under the mount's one prefix: the pre-pipeline surface the provider listener hands every request under `RC_ORPC_PATH_PREFIX`, answering with `matched: false` for a path under the prefix that names no procedure (which the listener itself answers as a 404). Request bodies are bounded by the same protocol cap the bespoke routes apply. Every router the mount serves (Remote Control and the control plane) goes through this one builder, so the prefix, the context and the cap are stated once.
|
|
2756
|
+
* Builds the node handler that serves one router of the door's typed API under the mount's one prefix, twice over: the OpenAPI handler answers every route-annotated (method, path) pair as plain REST (every annotation under `/rest`, which no RPC procedure path begins with, so the RPC protocol's own POSTs always fall through untouched), and everything else falls to the RPC handler, which answers the oRPC protocol the typed clients and the web client speak. The OpenAPI document of the annotated routes is served at `RC_OPENAPI_DOC_PATH`, behind the same per-generation control token the procedures demand, so a consumer with no TypeScript client reads the whole surface from the mount itself. The pre-pipeline surface the provider listener hands every request under `RC_ORPC_PATH_PREFIX`, answering with `matched: false` for a path under the prefix that names no route and no procedure (which the listener itself answers as a 404). Request bodies are bounded by the same protocol cap the bespoke routes apply, on both handlers. Every router the mount serves (Remote Control and the control plane) goes through this one builder, so the prefix, the context and the cap are stated once.
|
|
2755
2757
|
*/
|
|
2756
|
-
declare function doorApiNodeHandlerOf(router: AnyRouter): PrePipelineApi;
|
|
2758
|
+
declare function doorApiNodeHandlerOf(router: AnyRouter, expectedToken: string): PrePipelineApi;
|
|
2757
2759
|
/**
|
|
2758
2760
|
* Builds the typed API's node handler for the Remote Control router alone: the pre-pipeline surface the provider listener hands every request under `RC_ORPC_PATH_PREFIX`.
|
|
2759
2761
|
*/
|
|
@@ -3913,6 +3915,7 @@ declare function formatFrontDoorStatus(status: FrontDoorStatus, caCertPath: stri
|
|
|
3913
3915
|
* - `usage.*` reads the per-identity usage snapshots the door's own middleware writes, reads a provider's quota windows the way every in-process consumer does (`effectiveWindow`: a window past its reset is empty and carries no status), and reads the live rate-limit observations the event backbone files off the Remote Control client stream (`live`: per-session latest state, exactly as fresh as the last turn a session completed, never a timer's derivation of it).
|
|
3914
3916
|
* - `frontdoor.*` returns what `agent-shim frontdoor status` returns: the supervisor state, its liveness, the session registry's launches and the headroom hop.
|
|
3915
3917
|
* - `check.run` and `doctor.run` return the reports `agent-shim check` and `agent-shim doctor` print, as data, `check.run` parameterised by an absolute directory path.
|
|
3918
|
+
* - `pool.pick` returns what `agent-shim pool pick` prints, the ranked pick for one pool exactly as a launch from the named absolute directory would make it right now, so a programmatic consumer can ask which identity to use without reading the door host's files.
|
|
3916
3919
|
*
|
|
3917
3920
|
* Read-only by design: identity, configuration-profile, provider, pool and directory-rule management stay CLI-side, and adding writes over this mount is a decision of its own rather than a gap here. `createDoorApiNodeHandler` mounts these routers and the door-wide `events.subscribe` router beside the Remote Control router on the one prefix the provider listener already serves, so a consumer dials one address with one token for the whole door.
|
|
3918
3921
|
*/
|
|
@@ -3938,6 +3941,10 @@ interface ControlApiDeps {
|
|
|
3938
3941
|
readonly checkReport: (path: string, identity?: string) => CheckReport;
|
|
3939
3942
|
/** The doctor report, as `collectDoctorReport` collects it. */
|
|
3940
3943
|
readonly doctorReport: () => DoctorReport;
|
|
3944
|
+
/** The ranked pick for one pool as a launch from one absolute directory would make it right now, exactly `pool pick`'s own product; undefined when the pool table names no such pool. */
|
|
3945
|
+
readonly poolPick: (pool: string, directory: string) => PoolPickReport | undefined;
|
|
3946
|
+
/** The pool table's live names, so an unknown pool is refused naming the real ones rather than answered as an empty ranking. */
|
|
3947
|
+
readonly poolNames: () => readonly string[];
|
|
3941
3948
|
}
|
|
3942
3949
|
/** Builds the control-plane routers: one procedure per read, every one behind the control-token middleware. */
|
|
3943
3950
|
declare function createControlApiRouter(deps: ControlApiDeps): {
|
|
@@ -4461,6 +4468,44 @@ declare function createControlApiRouter(deps: ControlApiDeps): {
|
|
|
4461
4468
|
}, zod_v4_core.$strict>>>;
|
|
4462
4469
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4463
4470
|
};
|
|
4471
|
+
pool: {
|
|
4472
|
+
pick: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
4473
|
+
pool: zod.ZodString;
|
|
4474
|
+
path: zod.ZodString;
|
|
4475
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4476
|
+
pool: zod.ZodString;
|
|
4477
|
+
directory: zod.ZodString;
|
|
4478
|
+
pick: zod.ZodOptional<zod.ZodString>;
|
|
4479
|
+
candidates: zod.ZodArray<zod.ZodObject<{
|
|
4480
|
+
identity: zod.ZodString;
|
|
4481
|
+
class: zod.ZodEnum<{
|
|
4482
|
+
unknown: "unknown";
|
|
4483
|
+
scored: "scored";
|
|
4484
|
+
"pay-per-use": "pay-per-use";
|
|
4485
|
+
ineligible: "ineligible";
|
|
4486
|
+
}>;
|
|
4487
|
+
score: zod.ZodOptional<zod.ZodNumber>;
|
|
4488
|
+
feasible: zod.ZodBoolean;
|
|
4489
|
+
blockedUntil: zod.ZodOptional<zod.ZodISODateTime>;
|
|
4490
|
+
plan: zod.ZodUnion<readonly [zod.ZodObject<{
|
|
4491
|
+
kind: zod.ZodLiteral<"subscription">;
|
|
4492
|
+
capacity: zod.ZodNumber;
|
|
4493
|
+
recognised: zod.ZodBoolean;
|
|
4494
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
4495
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
4496
|
+
kind: zod.ZodLiteral<"pay-per-use">;
|
|
4497
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
4498
|
+
}, zod_v4_core.$strict>]>;
|
|
4499
|
+
reasons: zod.ZodArray<zod.ZodString>;
|
|
4500
|
+
}, zod_v4_core.$strict>>;
|
|
4501
|
+
missing: zod.ZodArray<zod.ZodString>;
|
|
4502
|
+
earliestReturn: zod.ZodOptional<zod.ZodObject<{
|
|
4503
|
+
identity: zod.ZodString;
|
|
4504
|
+
at: zod.ZodISODateTime;
|
|
4505
|
+
}, zod_v4_core.$strict>>;
|
|
4506
|
+
stickyProblem: zod.ZodOptional<zod.ZodString>;
|
|
4507
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4508
|
+
};
|
|
4464
4509
|
};
|
|
4465
4510
|
/** The control-plane routers, as the merged mount's and the client's own types are derived from them. */
|
|
4466
4511
|
type ControlApiRouter = ReturnType<typeof createControlApiRouter>;
|
|
@@ -4996,6 +5041,44 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
|
|
|
4996
5041
|
}, zod_v4_core.$strict>>>;
|
|
4997
5042
|
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
4998
5043
|
};
|
|
5044
|
+
pool: {
|
|
5045
|
+
pick: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, zod.ZodObject<{
|
|
5046
|
+
pool: zod.ZodString;
|
|
5047
|
+
path: zod.ZodString;
|
|
5048
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
5049
|
+
pool: zod.ZodString;
|
|
5050
|
+
directory: zod.ZodString;
|
|
5051
|
+
pick: zod.ZodOptional<zod.ZodString>;
|
|
5052
|
+
candidates: zod.ZodArray<zod.ZodObject<{
|
|
5053
|
+
identity: zod.ZodString;
|
|
5054
|
+
class: zod.ZodEnum<{
|
|
5055
|
+
unknown: "unknown";
|
|
5056
|
+
scored: "scored";
|
|
5057
|
+
"pay-per-use": "pay-per-use";
|
|
5058
|
+
ineligible: "ineligible";
|
|
5059
|
+
}>;
|
|
5060
|
+
score: zod.ZodOptional<zod.ZodNumber>;
|
|
5061
|
+
feasible: zod.ZodBoolean;
|
|
5062
|
+
blockedUntil: zod.ZodOptional<zod.ZodISODateTime>;
|
|
5063
|
+
plan: zod.ZodUnion<readonly [zod.ZodObject<{
|
|
5064
|
+
kind: zod.ZodLiteral<"subscription">;
|
|
5065
|
+
capacity: zod.ZodNumber;
|
|
5066
|
+
recognised: zod.ZodBoolean;
|
|
5067
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
5068
|
+
}, zod_v4_core.$strict>, zod.ZodObject<{
|
|
5069
|
+
kind: zod.ZodLiteral<"pay-per-use">;
|
|
5070
|
+
tier: zod.ZodOptional<zod.ZodString>;
|
|
5071
|
+
}, zod_v4_core.$strict>]>;
|
|
5072
|
+
reasons: zod.ZodArray<zod.ZodString>;
|
|
5073
|
+
}, zod_v4_core.$strict>>;
|
|
5074
|
+
missing: zod.ZodArray<zod.ZodString>;
|
|
5075
|
+
earliestReturn: zod.ZodOptional<zod.ZodObject<{
|
|
5076
|
+
identity: zod.ZodString;
|
|
5077
|
+
at: zod.ZodISODateTime;
|
|
5078
|
+
}, zod_v4_core.$strict>>;
|
|
5079
|
+
stickyProblem: zod.ZodOptional<zod.ZodString>;
|
|
5080
|
+
}, zod_v4_core.$strict>, Record<never, never>, Record<never, never>>;
|
|
5081
|
+
};
|
|
4999
5082
|
rc: {
|
|
5000
5083
|
list: _orpc_server.DecoratedProcedure<_orpc_server.MergedInitialContext<DoorApiContext & Record<never, never>, DoorApiContext, DoorApiContext>, any, Schema<unknown, unknown>, zod.ZodObject<{
|
|
5001
5084
|
sessions: zod.ZodReadonly<zod.ZodArray<zod.ZodObject<{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-shim",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.30.0",
|
|
4
4
|
"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.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@clack/prompts": "^1.8.0",
|
|
53
53
|
"@orpc/client": "1.15.4",
|
|
54
|
+
"@orpc/openapi": "1.15.4",
|
|
54
55
|
"@orpc/server": "1.15.4",
|
|
55
56
|
"commander": "^15.0.0",
|
|
56
57
|
"cosmiconfig": "^10.0.1",
|