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.cjs
CHANGED
|
@@ -5333,10 +5333,113 @@ function createRcCredentialStore(fs12, dir) {
|
|
|
5333
5333
|
// src/frontdoor/rcApi.ts
|
|
5334
5334
|
var import_client = require("@orpc/client");
|
|
5335
5335
|
var import_fetch = require("@orpc/client/fetch");
|
|
5336
|
+
var import_openapi = require("@orpc/openapi");
|
|
5337
|
+
var import_node = require("@orpc/openapi/node");
|
|
5336
5338
|
var import_server2 = require("@orpc/server");
|
|
5337
|
-
var
|
|
5339
|
+
var import_node2 = require("@orpc/server/node");
|
|
5338
5340
|
var import_undici = require("undici");
|
|
5339
5341
|
|
|
5342
|
+
// package.json
|
|
5343
|
+
var package_default = {
|
|
5344
|
+
name: "agent-shim",
|
|
5345
|
+
version: "8.30.0",
|
|
5346
|
+
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.",
|
|
5347
|
+
license: "MIT",
|
|
5348
|
+
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
5349
|
+
repository: {
|
|
5350
|
+
type: "git",
|
|
5351
|
+
url: "git+https://github.com/ExaDev/agent-shim.git"
|
|
5352
|
+
},
|
|
5353
|
+
homepage: "https://github.com/ExaDev/agent-shim#readme",
|
|
5354
|
+
bugs: "https://github.com/ExaDev/agent-shim/issues",
|
|
5355
|
+
keywords: [
|
|
5356
|
+
"claude-code",
|
|
5357
|
+
"claude",
|
|
5358
|
+
"cli"
|
|
5359
|
+
],
|
|
5360
|
+
packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|
|
5361
|
+
type: "module",
|
|
5362
|
+
engines: {
|
|
5363
|
+
node: "^22.18 || >=24"
|
|
5364
|
+
},
|
|
5365
|
+
bin: {
|
|
5366
|
+
"agent-shim": "dist/cli.cjs",
|
|
5367
|
+
"claude-use": "dist/cli.cjs"
|
|
5368
|
+
},
|
|
5369
|
+
files: [
|
|
5370
|
+
"dist/cli.cjs",
|
|
5371
|
+
"dist/index.mjs",
|
|
5372
|
+
"dist/index.cjs",
|
|
5373
|
+
"dist/types"
|
|
5374
|
+
],
|
|
5375
|
+
scripts: {
|
|
5376
|
+
prepare: "husky && node scripts/build.mts --bundle-only",
|
|
5377
|
+
typecheck: "turbo run _typecheck",
|
|
5378
|
+
_typecheck: "tsc --noEmit",
|
|
5379
|
+
lint: "turbo run _lint",
|
|
5380
|
+
_lint: "eslint . --cache --cache-location .eslintcache --max-warnings 0",
|
|
5381
|
+
test: "turbo run _test",
|
|
5382
|
+
_test: "vitest run",
|
|
5383
|
+
"test:coverage": "turbo run _test:coverage",
|
|
5384
|
+
"_test:coverage": "vitest run --coverage",
|
|
5385
|
+
knip: "turbo run _knip",
|
|
5386
|
+
_knip: "knip --cache",
|
|
5387
|
+
build: "turbo run _build",
|
|
5388
|
+
_build: "node scripts/build.mts",
|
|
5389
|
+
"build:bundle": "node scripts/build.mts --bundle-only",
|
|
5390
|
+
prepublishOnly: "pnpm build:bundle",
|
|
5391
|
+
schema: "node scripts/gen-schema.mts"
|
|
5392
|
+
},
|
|
5393
|
+
dependencies: {
|
|
5394
|
+
"@clack/prompts": "^1.8.0",
|
|
5395
|
+
"@orpc/client": "1.15.4",
|
|
5396
|
+
"@orpc/openapi": "1.15.4",
|
|
5397
|
+
"@orpc/server": "1.15.4",
|
|
5398
|
+
commander: "^15.0.0",
|
|
5399
|
+
cosmiconfig: "^10.0.1",
|
|
5400
|
+
picomatch: "^4.0.7",
|
|
5401
|
+
undici: "7.29.1",
|
|
5402
|
+
zod: "^4.6.1"
|
|
5403
|
+
},
|
|
5404
|
+
devDependencies: {
|
|
5405
|
+
"@commitlint/cli": "^21.2.2",
|
|
5406
|
+
"@commitlint/config-conventional": "^21.2.2",
|
|
5407
|
+
"@exadev/eslint-config": "2.12.1",
|
|
5408
|
+
"@semantic-release/changelog": "^7.0.0",
|
|
5409
|
+
"@semantic-release/git": "^11.0.1",
|
|
5410
|
+
"@semantic-release/npm": "^13.1.5",
|
|
5411
|
+
"@types/node": "^26.5.1",
|
|
5412
|
+
"@types/picomatch": "^4.0.3",
|
|
5413
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
5414
|
+
"conventional-changelog-conventionalcommits": "^10.4.0",
|
|
5415
|
+
esbuild: "^0.28.2",
|
|
5416
|
+
eslint: "^10.10.0",
|
|
5417
|
+
globals: "^17.12.0",
|
|
5418
|
+
husky: "^9.1.7",
|
|
5419
|
+
jiti: "^2.7.0",
|
|
5420
|
+
knip: "^6.35.1",
|
|
5421
|
+
"lint-staged": "^17.5.0",
|
|
5422
|
+
rollup: "4.64.0",
|
|
5423
|
+
"rollup-plugin-dts": "6.5.1",
|
|
5424
|
+
"semantic-release": "^25.0.9",
|
|
5425
|
+
turbo: "^2.11.5",
|
|
5426
|
+
typescript: "^6.0.3",
|
|
5427
|
+
"typescript-eslint": "^8.70.0",
|
|
5428
|
+
vitest: "^4.1.11"
|
|
5429
|
+
},
|
|
5430
|
+
main: "dist/index.cjs",
|
|
5431
|
+
module: "dist/index.mjs",
|
|
5432
|
+
types: "dist/types/index.d.ts",
|
|
5433
|
+
exports: {
|
|
5434
|
+
".": {
|
|
5435
|
+
types: "./dist/types/index.d.ts",
|
|
5436
|
+
import: "./dist/index.mjs",
|
|
5437
|
+
require: "./dist/index.cjs"
|
|
5438
|
+
},
|
|
5439
|
+
"./package.json": "./package.json"
|
|
5440
|
+
}
|
|
5441
|
+
};
|
|
5442
|
+
|
|
5340
5443
|
// src/frontdoor/rcSchemas.ts
|
|
5341
5444
|
var import_zod4 = require("zod");
|
|
5342
5445
|
var RcPermissionModeSchema = import_zod4.z.enum(RC_PERMISSION_MODES);
|
|
@@ -5498,18 +5601,23 @@ var RcAnswerOutputSchema = import_zod4.z.strictObject({
|
|
|
5498
5601
|
|
|
5499
5602
|
// src/frontdoor/rcApi.ts
|
|
5500
5603
|
var RC_ORPC_PATH_PREFIX = "/__agent-shim/orpc";
|
|
5604
|
+
var RC_OPENAPI_DOC_PATH = "/openapi.json";
|
|
5501
5605
|
var RC_SUBSCRIBER_BUFFER_EVENTS = 100;
|
|
5606
|
+
function doorApiBearer(headers) {
|
|
5607
|
+
const presented = headers.authorization;
|
|
5608
|
+
const bearerPrefix = "bearer ".length;
|
|
5609
|
+
return typeof presented === "string" && presented.slice(0, bearerPrefix).toLowerCase() === "bearer " ? presented.slice(bearerPrefix) : void 0;
|
|
5610
|
+
}
|
|
5502
5611
|
function doorApiAuth(expectedToken) {
|
|
5503
5612
|
return import_server2.os.$context().use(({ context, next }) => {
|
|
5504
|
-
const
|
|
5505
|
-
const bearerPrefix = "bearer ".length;
|
|
5506
|
-
const token = typeof presented === "string" && presented.slice(0, bearerPrefix).toLowerCase() === "bearer " ? presented.slice(bearerPrefix) : void 0;
|
|
5613
|
+
const token = doorApiBearer(context.headers);
|
|
5507
5614
|
if (token === void 0 || !isLiveCapability(token, [expectedToken])) {
|
|
5508
5615
|
throw new import_client.ORPCError("UNAUTHORIZED", { message: "the front door's typed API demands this generation's control token as a Bearer credential" });
|
|
5509
5616
|
}
|
|
5510
5617
|
return next();
|
|
5511
5618
|
});
|
|
5512
5619
|
}
|
|
5620
|
+
var RC_API_TAG = "remote-control";
|
|
5513
5621
|
function createRcApiRouter(deps) {
|
|
5514
5622
|
const authed = doorApiAuth(deps.expectedToken);
|
|
5515
5623
|
const delivered = (sessionId, result) => {
|
|
@@ -5529,41 +5637,41 @@ function createRcApiRouter(deps) {
|
|
|
5529
5637
|
};
|
|
5530
5638
|
return {
|
|
5531
5639
|
rc: {
|
|
5532
|
-
list: authed.output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
|
|
5533
|
-
status: authed.input(RcSessionQuerySchema).output(RcStatusOutputSchema).handler(({ input }) => {
|
|
5640
|
+
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() })),
|
|
5641
|
+
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 }) => {
|
|
5534
5642
|
const statuses = deps.statusOf(input.session);
|
|
5535
5643
|
if (input.session !== void 0 && !statuses.some((entry) => entry.id === input.session)) {
|
|
5536
5644
|
throw new import_client.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
|
|
5537
5645
|
}
|
|
5538
5646
|
return { statuses };
|
|
5539
5647
|
}),
|
|
5540
|
-
pending: authed.input(RcSessionQuerySchema).output(RcPendingOutputSchema).handler(({ input }) => {
|
|
5648
|
+
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 }) => {
|
|
5541
5649
|
const pending = deps.pendingOf(input.session);
|
|
5542
5650
|
if (input.session !== void 0 && deps.statusOf(input.session).length === 0) {
|
|
5543
5651
|
throw new import_client.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
|
|
5544
5652
|
}
|
|
5545
5653
|
return { pending };
|
|
5546
5654
|
}),
|
|
5547
|
-
send: authed.input(RcSendInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.inject(input.session, input.text)) })),
|
|
5548
|
-
answer: authed.input(RcAnswerInputSchema).output(RcAnswerOutputSchema).handler(async ({ input }) => {
|
|
5655
|
+
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)) })),
|
|
5656
|
+
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 }) => {
|
|
5549
5657
|
const decision = { approve: input.approve, message: input.approve || input.text === void 0 ? void 0 : input.text };
|
|
5550
5658
|
return { session: input.session, request: input.request, sequenceNums: delivered(input.session, await deps.answer(input.session, input.request, decision)) };
|
|
5551
5659
|
}),
|
|
5552
|
-
interrupt: authed.input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
|
|
5553
|
-
setModel: authed.input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
|
|
5554
|
-
setPermissionMode: authed.input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
|
|
5555
|
-
endSession: authed.input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
|
|
5556
|
-
getUsage: authed.input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
|
|
5557
|
-
getContextUsage: authed.input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
|
|
5558
|
-
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 } })) })),
|
|
5559
|
-
fileSuggestions: authed.input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
|
|
5560
|
-
keepAlive: authed.input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
|
|
5561
|
-
mcpStatus: authed.input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
|
|
5562
|
-
mcpReconnect: authed.input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
|
|
5563
|
-
mcpAuthenticate: authed.input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
|
|
5564
|
-
mcpOAuthCallbackUrl: authed.input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
|
|
5565
|
-
teleport: authed.input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.teleport(input.session, input.marker)) })),
|
|
5566
|
-
subscribe: authed.input(RcSessionQuerySchema).output((0, import_server2.eventIterator)(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
|
|
5660
|
+
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)) })),
|
|
5661
|
+
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)) })),
|
|
5662
|
+
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)) })),
|
|
5663
|
+
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)) })),
|
|
5664
|
+
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)) })),
|
|
5665
|
+
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)) })),
|
|
5666
|
+
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 } })) })),
|
|
5667
|
+
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)) })),
|
|
5668
|
+
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)) })),
|
|
5669
|
+
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)) })),
|
|
5670
|
+
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)) })),
|
|
5671
|
+
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)) })),
|
|
5672
|
+
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)) })),
|
|
5673
|
+
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)) })),
|
|
5674
|
+
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((0, import_server2.eventIterator)(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
|
|
5567
5675
|
const queue = [];
|
|
5568
5676
|
let wake;
|
|
5569
5677
|
const detach = deps.fanout.subscribe(input.session, (event) => {
|
|
@@ -5600,15 +5708,44 @@ function createRcApiRouter(deps) {
|
|
|
5600
5708
|
}
|
|
5601
5709
|
};
|
|
5602
5710
|
}
|
|
5603
|
-
function doorApiNodeHandlerOf(router) {
|
|
5604
|
-
const
|
|
5711
|
+
function doorApiNodeHandlerOf(router, expectedToken) {
|
|
5712
|
+
const plugins = [new import_node2.BodyLimitPlugin({ maxBodySize: CONTROL_BODY_CAP_BYTES })];
|
|
5713
|
+
const rpcHandler = new import_node2.RPCHandler(router, { plugins });
|
|
5714
|
+
const restHandler = new import_node.OpenAPIHandler(router, { plugins });
|
|
5715
|
+
let document;
|
|
5716
|
+
const documentOf = async () => document ??= new import_openapi.OpenAPIGenerator().generate(router, { info: { title: "agent-shim front door API", version: package_default.version } });
|
|
5605
5717
|
return {
|
|
5606
5718
|
pathPrefix: RC_ORPC_PATH_PREFIX,
|
|
5607
|
-
handle: async (request4, response) =>
|
|
5719
|
+
handle: async (request4, response) => {
|
|
5720
|
+
if (request4.method === "GET" && request4.url === `${RC_ORPC_PATH_PREFIX}${RC_OPENAPI_DOC_PATH}`) {
|
|
5721
|
+
const token = doorApiBearer(request4.headers);
|
|
5722
|
+
if (token === void 0 || !isLiveCapability(token, [expectedToken])) {
|
|
5723
|
+
const refusal = new import_client.ORPCError("UNAUTHORIZED", { message: "the front door's OpenAPI document demands this generation's control token as a Bearer credential" });
|
|
5724
|
+
response.writeHead(HTTP_STATUS.unauthorized, { "content-type": "application/json" });
|
|
5725
|
+
response.end(JSON.stringify(refusal.toJSON()));
|
|
5726
|
+
return { matched: true };
|
|
5727
|
+
}
|
|
5728
|
+
try {
|
|
5729
|
+
const doc = await documentOf();
|
|
5730
|
+
response.writeHead(HTTP_STATUS.ok, { "content-type": "application/json" });
|
|
5731
|
+
response.end(JSON.stringify(doc));
|
|
5732
|
+
} catch (error) {
|
|
5733
|
+
const refusal = new import_client.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)}` });
|
|
5734
|
+
response.writeHead(HTTP_STATUS.internalServerError, { "content-type": "application/json" });
|
|
5735
|
+
response.end(JSON.stringify(refusal.toJSON()));
|
|
5736
|
+
}
|
|
5737
|
+
return { matched: true };
|
|
5738
|
+
}
|
|
5739
|
+
const rest = await restHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
|
|
5740
|
+
if (rest.matched) {
|
|
5741
|
+
return rest;
|
|
5742
|
+
}
|
|
5743
|
+
return await rpcHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
|
|
5744
|
+
}
|
|
5608
5745
|
};
|
|
5609
5746
|
}
|
|
5610
5747
|
function createRcApiNodeHandler(deps) {
|
|
5611
|
-
return doorApiNodeHandlerOf(createRcApiRouter(deps));
|
|
5748
|
+
return doorApiNodeHandlerOf(createRcApiRouter(deps), deps.expectedToken);
|
|
5612
5749
|
}
|
|
5613
5750
|
function frontDoorApiLink(port, ca, token) {
|
|
5614
5751
|
const dispatcher = new import_undici.Agent({ connect: { ca } });
|
|
@@ -10043,6 +10180,10 @@ var CheckRunInputSchema = import_zod19.z.strictObject({
|
|
|
10043
10180
|
path: import_zod19.z.string().min(1),
|
|
10044
10181
|
identity: import_zod19.z.string().min(1).optional()
|
|
10045
10182
|
}).refine((input) => import_node_path27.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
10183
|
+
var PoolPickInputSchema = import_zod19.z.strictObject({
|
|
10184
|
+
pool: import_zod19.z.string().min(1),
|
|
10185
|
+
path: import_zod19.z.string().min(1)
|
|
10186
|
+
}).refine((input) => import_node_path27.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
|
|
10046
10187
|
var DoctorFindingSchema = import_zod19.z.strictObject({
|
|
10047
10188
|
section: import_zod19.z.enum(DOCTOR_SECTIONS),
|
|
10048
10189
|
subject: import_zod19.z.string().optional(),
|
|
@@ -10080,11 +10221,12 @@ var LaunchLifecycleEventSchema = import_zod20.z.strictObject({
|
|
|
10080
10221
|
});
|
|
10081
10222
|
|
|
10082
10223
|
// src/frontdoor/eventsApi.ts
|
|
10224
|
+
var EVENTS_API_TAG = "events";
|
|
10083
10225
|
function createEventsApiRouter(deps) {
|
|
10084
10226
|
const authed = doorApiAuth(deps.expectedToken);
|
|
10085
10227
|
return {
|
|
10086
10228
|
events: {
|
|
10087
|
-
subscribe: authed.input(DoorEventSourceQuerySchema).output((0, import_server3.eventIterator)(DoorEventSchema)).handler(async function* ({ input, signal }) {
|
|
10229
|
+
subscribe: authed.route({ method: "GET", path: "/rest/events", summary: "Stream the door's every event source (SSE)", tags: [EVENTS_API_TAG] }).input(DoorEventSourceQuerySchema).output((0, import_server3.eventIterator)(DoorEventSchema)).handler(async function* ({ input, signal }) {
|
|
10088
10230
|
if (input.sources !== void 0) {
|
|
10089
10231
|
const live = deps.events.sources();
|
|
10090
10232
|
const unknown = input.sources.filter((source) => !live.includes(source));
|
|
@@ -10117,12 +10259,17 @@ function createEventsApiRouter(deps) {
|
|
|
10117
10259
|
}
|
|
10118
10260
|
|
|
10119
10261
|
// src/frontdoor/controlApi.ts
|
|
10262
|
+
var USAGE_API_TAG = "usage";
|
|
10263
|
+
var FRONTDOOR_API_TAG = "frontdoor";
|
|
10264
|
+
var CHECK_API_TAG = "check";
|
|
10265
|
+
var DOCTOR_API_TAG = "doctor";
|
|
10266
|
+
var POOL_API_TAG = "pool";
|
|
10120
10267
|
function createControlApiRouter(deps) {
|
|
10121
10268
|
const authed = doorApiAuth(deps.expectedToken);
|
|
10122
10269
|
return {
|
|
10123
10270
|
usage: {
|
|
10124
|
-
list: authed.output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
|
|
10125
|
-
effectiveWindow: authed.input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
|
|
10271
|
+
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() })),
|
|
10272
|
+
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 }) => {
|
|
10126
10273
|
const snapshot = deps.usageSnapshotOf(input.identity);
|
|
10127
10274
|
if (snapshot === void 0) {
|
|
10128
10275
|
throw new import_client3.ORPCError("NOT_FOUND", { message: `identity ${input.identity} has no usage snapshot yet, so no quota window has been observed for it` });
|
|
@@ -10139,7 +10286,7 @@ function createControlApiRouter(deps) {
|
|
|
10139
10286
|
...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
|
|
10140
10287
|
};
|
|
10141
10288
|
}),
|
|
10142
|
-
live: authed.input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
|
|
10289
|
+
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 }) => {
|
|
10143
10290
|
const sessions = deps.liveRateLimits(input.session);
|
|
10144
10291
|
if (input.session !== void 0 && sessions.length === 0) {
|
|
10145
10292
|
if (deps.list().some((session) => session.id === input.session)) {
|
|
@@ -10151,15 +10298,27 @@ function createControlApiRouter(deps) {
|
|
|
10151
10298
|
})
|
|
10152
10299
|
},
|
|
10153
10300
|
frontdoor: {
|
|
10154
|
-
status: authed.output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
|
|
10155
|
-
sessions: authed.output(FrontDoorSessionsOutputSchema).handler(() => ({ sessions: deps.frontDoorStatus().sessions }))
|
|
10301
|
+
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()),
|
|
10302
|
+
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 }))
|
|
10156
10303
|
},
|
|
10157
10304
|
check: {
|
|
10158
10305
|
// 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.
|
|
10159
|
-
run: authed.input(CheckRunInputSchema).output(CheckReportJsonSchema).handler(({ input }) => checkReportToJson(deps.checkReport(input.path, input.identity)))
|
|
10306
|
+
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)))
|
|
10160
10307
|
},
|
|
10161
10308
|
doctor: {
|
|
10162
|
-
run: authed.output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
|
|
10309
|
+
run: authed.route({ method: "GET", path: "/rest/doctor", summary: "Run the doctor report", tags: [DOCTOR_API_TAG] }).output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
|
|
10310
|
+
},
|
|
10311
|
+
pool: {
|
|
10312
|
+
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 }) => {
|
|
10313
|
+
const report = deps.poolPick(input.pool, input.path);
|
|
10314
|
+
if (report === void 0) {
|
|
10315
|
+
const live = deps.poolNames();
|
|
10316
|
+
throw new import_client3.ORPCError("NOT_FOUND", {
|
|
10317
|
+
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(", ")}`
|
|
10318
|
+
});
|
|
10319
|
+
}
|
|
10320
|
+
return report;
|
|
10321
|
+
})
|
|
10163
10322
|
}
|
|
10164
10323
|
};
|
|
10165
10324
|
}
|
|
@@ -10167,7 +10326,7 @@ function createDoorApiRouter(deps) {
|
|
|
10167
10326
|
return { ...createRcApiRouter(deps), ...createControlApiRouter(deps), ...createEventsApiRouter(deps) };
|
|
10168
10327
|
}
|
|
10169
10328
|
function createDoorApiNodeHandler(deps) {
|
|
10170
|
-
return doorApiNodeHandlerOf(createDoorApiRouter(deps));
|
|
10329
|
+
return doorApiNodeHandlerOf(createDoorApiRouter(deps), deps.expectedToken);
|
|
10171
10330
|
}
|
|
10172
10331
|
function frontDoorApiClient(port, ca, token) {
|
|
10173
10332
|
return (0, import_client3.createORPCClient)(frontDoorApiLink(port, ca, token));
|
|
@@ -12253,106 +12412,6 @@ function removeDirectoryRule(paths, rulePath) {
|
|
|
12253
12412
|
var import_node_crypto10 = require("node:crypto");
|
|
12254
12413
|
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
12255
12414
|
|
|
12256
|
-
// package.json
|
|
12257
|
-
var package_default = {
|
|
12258
|
-
name: "agent-shim",
|
|
12259
|
-
version: "8.28.0",
|
|
12260
|
-
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.",
|
|
12261
|
-
license: "MIT",
|
|
12262
|
-
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
12263
|
-
repository: {
|
|
12264
|
-
type: "git",
|
|
12265
|
-
url: "git+https://github.com/ExaDev/agent-shim.git"
|
|
12266
|
-
},
|
|
12267
|
-
homepage: "https://github.com/ExaDev/agent-shim#readme",
|
|
12268
|
-
bugs: "https://github.com/ExaDev/agent-shim/issues",
|
|
12269
|
-
keywords: [
|
|
12270
|
-
"claude-code",
|
|
12271
|
-
"claude",
|
|
12272
|
-
"cli"
|
|
12273
|
-
],
|
|
12274
|
-
packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|
|
12275
|
-
type: "module",
|
|
12276
|
-
engines: {
|
|
12277
|
-
node: "^22.18 || >=24"
|
|
12278
|
-
},
|
|
12279
|
-
bin: {
|
|
12280
|
-
"agent-shim": "dist/cli.cjs",
|
|
12281
|
-
"claude-use": "dist/cli.cjs"
|
|
12282
|
-
},
|
|
12283
|
-
files: [
|
|
12284
|
-
"dist/cli.cjs",
|
|
12285
|
-
"dist/index.mjs",
|
|
12286
|
-
"dist/index.cjs",
|
|
12287
|
-
"dist/types"
|
|
12288
|
-
],
|
|
12289
|
-
scripts: {
|
|
12290
|
-
prepare: "husky && node scripts/build.mts --bundle-only",
|
|
12291
|
-
typecheck: "turbo run _typecheck",
|
|
12292
|
-
_typecheck: "tsc --noEmit",
|
|
12293
|
-
lint: "turbo run _lint",
|
|
12294
|
-
_lint: "eslint . --cache --cache-location .eslintcache --max-warnings 0",
|
|
12295
|
-
test: "turbo run _test",
|
|
12296
|
-
_test: "vitest run",
|
|
12297
|
-
"test:coverage": "turbo run _test:coverage",
|
|
12298
|
-
"_test:coverage": "vitest run --coverage",
|
|
12299
|
-
knip: "turbo run _knip",
|
|
12300
|
-
_knip: "knip --cache",
|
|
12301
|
-
build: "turbo run _build",
|
|
12302
|
-
_build: "node scripts/build.mts",
|
|
12303
|
-
"build:bundle": "node scripts/build.mts --bundle-only",
|
|
12304
|
-
prepublishOnly: "pnpm build:bundle",
|
|
12305
|
-
schema: "node scripts/gen-schema.mts"
|
|
12306
|
-
},
|
|
12307
|
-
dependencies: {
|
|
12308
|
-
"@clack/prompts": "^1.8.0",
|
|
12309
|
-
"@orpc/client": "1.15.4",
|
|
12310
|
-
"@orpc/server": "1.15.4",
|
|
12311
|
-
commander: "^15.0.0",
|
|
12312
|
-
cosmiconfig: "^10.0.1",
|
|
12313
|
-
picomatch: "^4.0.7",
|
|
12314
|
-
undici: "7.29.1",
|
|
12315
|
-
zod: "^4.6.1"
|
|
12316
|
-
},
|
|
12317
|
-
devDependencies: {
|
|
12318
|
-
"@commitlint/cli": "^21.2.2",
|
|
12319
|
-
"@commitlint/config-conventional": "^21.2.2",
|
|
12320
|
-
"@exadev/eslint-config": "2.12.1",
|
|
12321
|
-
"@semantic-release/changelog": "^7.0.0",
|
|
12322
|
-
"@semantic-release/git": "^11.0.1",
|
|
12323
|
-
"@semantic-release/npm": "^13.1.5",
|
|
12324
|
-
"@types/node": "^26.5.1",
|
|
12325
|
-
"@types/picomatch": "^4.0.3",
|
|
12326
|
-
"@vitest/coverage-v8": "^4.1.11",
|
|
12327
|
-
"conventional-changelog-conventionalcommits": "^10.4.0",
|
|
12328
|
-
esbuild: "^0.28.2",
|
|
12329
|
-
eslint: "^10.10.0",
|
|
12330
|
-
globals: "^17.12.0",
|
|
12331
|
-
husky: "^9.1.7",
|
|
12332
|
-
jiti: "^2.7.0",
|
|
12333
|
-
knip: "^6.35.1",
|
|
12334
|
-
"lint-staged": "^17.5.0",
|
|
12335
|
-
rollup: "4.64.0",
|
|
12336
|
-
"rollup-plugin-dts": "6.5.1",
|
|
12337
|
-
"semantic-release": "^25.0.9",
|
|
12338
|
-
turbo: "^2.11.5",
|
|
12339
|
-
typescript: "^6.0.3",
|
|
12340
|
-
"typescript-eslint": "^8.70.0",
|
|
12341
|
-
vitest: "^4.1.11"
|
|
12342
|
-
},
|
|
12343
|
-
main: "dist/index.cjs",
|
|
12344
|
-
module: "dist/index.mjs",
|
|
12345
|
-
types: "dist/types/index.d.ts",
|
|
12346
|
-
exports: {
|
|
12347
|
-
".": {
|
|
12348
|
-
types: "./dist/types/index.d.ts",
|
|
12349
|
-
import: "./dist/index.mjs",
|
|
12350
|
-
require: "./dist/index.cjs"
|
|
12351
|
-
},
|
|
12352
|
-
"./package.json": "./package.json"
|
|
12353
|
-
}
|
|
12354
|
-
};
|
|
12355
|
-
|
|
12356
12415
|
// src/launcher/argv.ts
|
|
12357
12416
|
var ConflictingIdentityError = class extends UsageError {
|
|
12358
12417
|
constructor(positional, flag) {
|