agent-shim 8.17.1 → 8.19.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 +1 -1
- package/dist/cli.cjs +64 -39
- package/dist/index.cjs +13 -31
- package/dist/index.mjs +13 -31
- package/dist/types/index.d.ts +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ Sharing composes through a cascade (shipped defaults, then a user-global overrid
|
|
|
73
73
|
|
|
74
74
|
`claude` refuses to launch while `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN` or a `CLAUDE_CODE_USE_BEDROCK`/`VERTEX`/`FOUNDRY` variable is set in the environment, because those outrank every identity's stored credential and would make all identities authenticate as the same account. Opt in deliberately with `AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL=1` for one launch or `agent-shim identity set <name> --allow-ambient-credential`.
|
|
75
75
|
|
|
76
|
-
Providers and identities take their token from one `credential` block: an ordered list of sources (`env`, `file`, `command`, and the `op` and `keychain` presets, plus a `literal` placeholder for a local proxy), tried in turn, and a target (`bearer`, `apiKey`, or `oauthToken` for an identity).
|
|
76
|
+
Providers and identities take their token from one `credential` block: an ordered list of sources (`env`, `file`, `command`, and the `op` and `keychain` presets, plus a `literal` placeholder for a local proxy), tried in turn, and a target (`bearer`, `apiKey`, or `oauthToken` for an identity). An identity's token reaches the child's environment only; a provider's never reaches the child at all (the front door attaches it at the provider's route, which is also what lets provider inference and Remote Control share one session). `check`, `doctor` and `--json` report the source kind and target, never the value.
|
|
77
77
|
|
|
78
78
|
The full mechanics, including the credential block, the merge algorithm, conditional sharing rules (age, size, git branch, environment), the ambient-credential launch guard, and how `~/.claude/projects/` history is pattern-matched, are in [docs/configuration-model.md](docs/configuration-model.md). Worked examples are in [docs/examples.md](docs/examples.md).
|
|
79
79
|
|
package/dist/cli.cjs
CHANGED
|
@@ -55589,7 +55589,7 @@ function ensureHeadroom(params) {
|
|
|
55589
55589
|
|
|
55590
55590
|
// src/frontdoor/state.ts
|
|
55591
55591
|
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
55592
|
-
var FRONT_DOOR_PROTOCOL =
|
|
55592
|
+
var FRONT_DOOR_PROTOCOL = 3;
|
|
55593
55593
|
var FrontDoorSessionSchema = external_exports.strictObject({ pid: external_exports.number().int().positive(), startedAt: external_exports.number(), token: external_exports.string().min(1) });
|
|
55594
55594
|
var FrontDoorStateSchema = external_exports.strictObject({
|
|
55595
55595
|
/**
|
|
@@ -61749,7 +61749,7 @@ function registerIdentityCommand(program2, deps) {
|
|
|
61749
61749
|
// package.json
|
|
61750
61750
|
var package_default = {
|
|
61751
61751
|
name: "agent-shim",
|
|
61752
|
-
version: "8.
|
|
61752
|
+
version: "8.19.0",
|
|
61753
61753
|
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.",
|
|
61754
61754
|
license: "MIT",
|
|
61755
61755
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -62124,6 +62124,7 @@ var INTERNAL_HEADER_NAMES = [
|
|
|
62124
62124
|
"x-agent-shim-session",
|
|
62125
62125
|
"x-agent-shim-headroom",
|
|
62126
62126
|
"x-agent-shim-auth",
|
|
62127
|
+
"x-agent-shim-provider",
|
|
62127
62128
|
"x-agent-shim-hop",
|
|
62128
62129
|
"x-agent-shim-hop-id",
|
|
62129
62130
|
"x-headroom-project-id",
|
|
@@ -62131,6 +62132,7 @@ var INTERNAL_HEADER_NAMES = [
|
|
|
62131
62132
|
];
|
|
62132
62133
|
var IDENTITY_HEADER = "x-agent-shim-identity";
|
|
62133
62134
|
var SESSION_HEADER = "x-agent-shim-session";
|
|
62135
|
+
var PROVIDER_HEADER = "x-agent-shim-provider";
|
|
62134
62136
|
var HEADROOM_FLAG_HEADER = "x-agent-shim-headroom";
|
|
62135
62137
|
var PROJECT_ID_HEADER = "x-headroom-project-id";
|
|
62136
62138
|
var HEADROOM_BASE_URL_HEADER = "x-headroom-base-url";
|
|
@@ -62166,6 +62168,7 @@ function identifyRequest(headers) {
|
|
|
62166
62168
|
session: {
|
|
62167
62169
|
identity: internalHeaderValue(headers, IDENTITY_HEADER),
|
|
62168
62170
|
sessionId: internalHeaderValue(headers, SESSION_HEADER),
|
|
62171
|
+
provider: internalHeaderValue(headers, PROVIDER_HEADER),
|
|
62169
62172
|
headroom: internalHeaderValue(headers, HEADROOM_FLAG_HEADER) === "1",
|
|
62170
62173
|
projectId: internalHeaderValue(headers, PROJECT_ID_HEADER)
|
|
62171
62174
|
},
|
|
@@ -62173,9 +62176,6 @@ function identifyRequest(headers) {
|
|
|
62173
62176
|
};
|
|
62174
62177
|
}
|
|
62175
62178
|
var PROVIDER_PATH_PREFIX = "/providers/";
|
|
62176
|
-
function providerBaseUrl(port, provider) {
|
|
62177
|
-
return `https://127.0.0.1:${String(port)}${PROVIDER_PATH_PREFIX}${encodeURIComponent(provider)}`;
|
|
62178
|
-
}
|
|
62179
62179
|
function directOrigin(port) {
|
|
62180
62180
|
return `http://127.0.0.1:${String(port)}`;
|
|
62181
62181
|
}
|
|
@@ -65050,7 +65050,7 @@ function admitHop(hopSecret, custody) {
|
|
|
65050
65050
|
return { ok: false, message: "agent-shim front door: the direct listener serves only this door's own headroom hop" };
|
|
65051
65051
|
}
|
|
65052
65052
|
const hopId = singleValue(request7.headers[HOP_ID_HEADER]);
|
|
65053
|
-
const provider = parseProviderPath(new URL(request7.url, "http://127.0.0.1").pathname)?.provider;
|
|
65053
|
+
const provider = parseProviderPath(new URL(request7.url, "http://127.0.0.1").pathname)?.provider ?? internalHeaderValue(request7.headers, PROVIDER_HEADER);
|
|
65054
65054
|
const credentials = hopId === void 0 || provider === void 0 ? void 0 : custody.redeem(hopId, provider);
|
|
65055
65055
|
if (credentials === void 0) {
|
|
65056
65056
|
return { ok: false, message: "agent-shim front door: this request names no live headroom hop for its provider" };
|
|
@@ -67820,7 +67820,7 @@ function pushProvider(push, entry, cacheEnv, signIn) {
|
|
|
67820
67820
|
const cache = cacheClause(cacheEnv, `provider ${entry.name}`, validated2.data.credential);
|
|
67821
67821
|
push("provider", cache.unreadable ? "fail" : "pass", `${entry.name} is valid (${describeProviderEndpoint(validated2.data)}, credential ${describeCredential(validated2.data.credential)})${cache.text}.`, entry.name);
|
|
67822
67822
|
if (validated2.data.env?.ENABLE_TOOL_SEARCH === void 0) {
|
|
67823
|
-
push("provider", "warn", `${entry.name} does not set ENABLE_TOOL_SEARCH: a session on this provider
|
|
67823
|
+
push("provider", "warn", `${entry.name} does not set ENABLE_TOOL_SEARCH: a session on this provider keeps Claude Code's own API as its base URL, so it defers MCP tool loading and sends tool_reference payloads the upstream backend must understand. Set ENABLE_TOOL_SEARCH=false in the provider's env block to load tools upfront instead, when the backend does not support them.`, entry.name);
|
|
67824
67824
|
}
|
|
67825
67825
|
if (signIn !== void 0 && isCodexProvider(validated2.data) && validated2.data.codex?.login === "chatgpt-sign-in") {
|
|
67826
67826
|
const problem = signInProblem(signIn);
|
|
@@ -72125,7 +72125,7 @@ async function applyHeadroomHop(request7, response, upstream, deps) {
|
|
|
72125
72125
|
let headers = forwardableHeaders(request7.headers);
|
|
72126
72126
|
let hopId;
|
|
72127
72127
|
if (upstream !== void 0) {
|
|
72128
|
-
const provider = parseProviderPath(new URL(request7.url, "http://127.0.0.1").pathname)?.provider;
|
|
72128
|
+
const provider = parseProviderPath(new URL(request7.url, "http://127.0.0.1").pathname)?.provider ?? request7.session.provider;
|
|
72129
72129
|
if (provider === void 0) {
|
|
72130
72130
|
throw new Error(`headroom hop for ${request7.url} names an upstream but no provider`);
|
|
72131
72131
|
}
|
|
@@ -72135,6 +72135,9 @@ async function applyHeadroomHop(request7, response, upstream, deps) {
|
|
|
72135
72135
|
headers[HOP_ID_HEADER] = hopId;
|
|
72136
72136
|
headers[HEADROOM_BASE_URL_HEADER] = upstream;
|
|
72137
72137
|
}
|
|
72138
|
+
if (request7.session.provider !== void 0) {
|
|
72139
|
+
headers[PROVIDER_HEADER] = request7.session.provider;
|
|
72140
|
+
}
|
|
72138
72141
|
if (request7.session.projectId !== void 0) {
|
|
72139
72142
|
headers[PROJECT_ID_HEADER] = request7.session.projectId;
|
|
72140
72143
|
}
|
|
@@ -73289,6 +73292,9 @@ function createProviderRouteResolver(deps) {
|
|
|
73289
73292
|
if (deps.rcSelfHostRoute !== void 0 && isRcSelfHostPath(path44)) {
|
|
73290
73293
|
return { ok: true, route: deps.rcSelfHostRoute };
|
|
73291
73294
|
}
|
|
73295
|
+
if (request7.session.provider !== void 0 && path44.startsWith("/v1/") && !isRcSelfHostPath(path44)) {
|
|
73296
|
+
return resolve({ ...request7, url: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(request7.session.provider)}${request7.url}` });
|
|
73297
|
+
}
|
|
73292
73298
|
return path44.startsWith("/v1/") ? { ok: true, route: oauthRoute } : { ok: false, status: HTTP_STATUS.notFound, message: `no such endpoint: ${path44}` };
|
|
73293
73299
|
}
|
|
73294
73300
|
const { provider } = scoped;
|
|
@@ -73318,15 +73324,40 @@ function createProviderRouteResolver(deps) {
|
|
|
73318
73324
|
const httpProvider = definition;
|
|
73319
73325
|
return {
|
|
73320
73326
|
ok: true,
|
|
73321
|
-
route:
|
|
73322
|
-
|
|
73323
|
-
|
|
73324
|
-
|
|
73325
|
-
|
|
73327
|
+
route: attachingProviderCredential(
|
|
73328
|
+
passthroughFor(`http:${provider}`, {
|
|
73329
|
+
baseUrl: httpProvider.baseUrl,
|
|
73330
|
+
stripPrefix: `${PROVIDER_PATH_PREFIX}${encodeURIComponent(provider)}`,
|
|
73331
|
+
headroomUpstream: directOrigin(deps.directPort())
|
|
73332
|
+
}),
|
|
73333
|
+
{ provider, credential: httpProvider.credential, env: deps.env, port: deps.credentials }
|
|
73334
|
+
)
|
|
73326
73335
|
};
|
|
73327
73336
|
};
|
|
73328
73337
|
return async (request7) => await Promise.resolve(resolve(request7));
|
|
73329
73338
|
}
|
|
73339
|
+
function providerCredentialHeaders(credential) {
|
|
73340
|
+
return credential.target === "apiKey" ? { "x-api-key": credential.token } : { authorization: `Bearer ${credential.token}` };
|
|
73341
|
+
}
|
|
73342
|
+
function attachingProviderCredential(route, deps) {
|
|
73343
|
+
return {
|
|
73344
|
+
name: route.name,
|
|
73345
|
+
headroomEligible: route.headroomEligible,
|
|
73346
|
+
headroomUpstream: route.headroomUpstream,
|
|
73347
|
+
serve: async (request7, response) => {
|
|
73348
|
+
const resolution = resolveCredential({ credential: deps.credential, env: deps.env, port: deps.port, subject: `provider ${deps.provider}` });
|
|
73349
|
+
if (!resolution.ok) {
|
|
73350
|
+
response.start(HTTP_STATUS.badGateway, { "Content-Type": "application/json" });
|
|
73351
|
+
await response.write(
|
|
73352
|
+
JSON.stringify({ type: "error", error: { type: "api_error", message: `provider ${deps.provider} has no usable credential for the front door to attach: ${resolution.message}` } })
|
|
73353
|
+
);
|
|
73354
|
+
response.end();
|
|
73355
|
+
return;
|
|
73356
|
+
}
|
|
73357
|
+
await route.serve({ ...request7, headers: restoreCredentials(request7.headers, providerCredentialHeaders(resolution.credential)) }, response);
|
|
73358
|
+
}
|
|
73359
|
+
};
|
|
73360
|
+
}
|
|
73330
73361
|
|
|
73331
73362
|
// src/frontdoor/rcCredentialStore.ts
|
|
73332
73363
|
var import_node_path34 = __toESM(require("node:path"), 1);
|
|
@@ -75239,7 +75270,16 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
75239
75270
|
});
|
|
75240
75271
|
const rcControlToken = (0, import_node_crypto14.randomUUID)();
|
|
75241
75272
|
const resolveRoute = rcObservingResolver(
|
|
75242
|
-
createProviderRouteResolver({
|
|
75273
|
+
createProviderRouteResolver({
|
|
75274
|
+
fs: realFsPort,
|
|
75275
|
+
providersDir: paths.providersDir,
|
|
75276
|
+
codexPorts,
|
|
75277
|
+
directPort: () => directPort,
|
|
75278
|
+
// The same port (cache included) the launcher resolves a launch's provider with, so the credential the door attaches at the route and the one the launcher handed the child are the same resolution of the same block.
|
|
75279
|
+
env: process.env,
|
|
75280
|
+
credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
|
|
75281
|
+
...rcSelfHostSurface === void 0 ? {} : { rcSelfHostRoute: rcSelfHostSurface.route }
|
|
75282
|
+
}),
|
|
75243
75283
|
rcTracker,
|
|
75244
75284
|
rcHub
|
|
75245
75285
|
);
|
|
@@ -77468,15 +77508,6 @@ function buildFlagArgs(flags) {
|
|
|
77468
77508
|
function buildArgv(params) {
|
|
77469
77509
|
return [...params.toolFlags, ...params.extraFlags, ...params.passthrough];
|
|
77470
77510
|
}
|
|
77471
|
-
var LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
|
|
77472
|
-
function isLoopbackUrl(baseUrl) {
|
|
77473
|
-
const host = new URL(baseUrl).hostname.replace(/^\[|\]$/g, "");
|
|
77474
|
-
return LOOPBACK_HOSTS.some((loopback) => loopback === host);
|
|
77475
|
-
}
|
|
77476
|
-
function withLoopbackHosts(existing) {
|
|
77477
|
-
const listed = (existing ?? "").split(",").map((entry) => entry.trim()).filter((entry) => entry !== "");
|
|
77478
|
-
return [...listed, ...LOOPBACK_HOSTS.filter((host) => !listed.includes(host))].join(",");
|
|
77479
|
-
}
|
|
77480
77511
|
function buildEnv(params) {
|
|
77481
77512
|
const env = { ...params.baseEnv };
|
|
77482
77513
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
@@ -77487,19 +77518,18 @@ function buildEnv(params) {
|
|
|
77487
77518
|
if (params.provider !== void 0) {
|
|
77488
77519
|
const providerEnv = params.provider.definition.env ?? {};
|
|
77489
77520
|
providerCustomHeaders = providerEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
77490
|
-
env.ANTHROPIC_BASE_URL =
|
|
77491
|
-
if (isLoopbackUrl(params.provider.baseUrl)) {
|
|
77492
|
-
env.NO_PROXY = withLoopbackHosts(params.baseEnv.NO_PROXY);
|
|
77493
|
-
env.no_proxy = withLoopbackHosts(params.baseEnv.no_proxy);
|
|
77494
|
-
}
|
|
77521
|
+
env.ANTHROPIC_BASE_URL = void 0;
|
|
77495
77522
|
env.AGENT_SHIM_PROVIDER = params.provider.definition.displayName;
|
|
77496
77523
|
for (const [key, value2] of Object.entries(providerEnv)) {
|
|
77497
77524
|
env[key] = value2;
|
|
77498
77525
|
}
|
|
77499
77526
|
}
|
|
77500
|
-
|
|
77501
|
-
|
|
77502
|
-
|
|
77527
|
+
if (params.provider !== void 0) {
|
|
77528
|
+
env.ANTHROPIC_AUTH_TOKEN = void 0;
|
|
77529
|
+
env.ANTHROPIC_API_KEY = void 0;
|
|
77530
|
+
env.CLAUDE_CODE_OAUTH_TOKEN = void 0;
|
|
77531
|
+
} else if (params.identityCredential !== void 0) {
|
|
77532
|
+
for (const [variable, value2] of Object.entries(credentialVariables(params.identityCredential.target, params.identityCredential.token))) {
|
|
77503
77533
|
env[variable] = value2;
|
|
77504
77534
|
}
|
|
77505
77535
|
}
|
|
@@ -77513,6 +77543,7 @@ function buildEnv(params) {
|
|
|
77513
77543
|
...params.resolvedIdentityName === void 0 ? [] : [{ name: IDENTITY_HEADER, value: params.resolvedIdentityName }],
|
|
77514
77544
|
{ name: SESSION_HEADER, value: params.sessionId },
|
|
77515
77545
|
{ name: AUTH_HEADER, value: params.frontdoor.sessionToken },
|
|
77546
|
+
...params.provider === void 0 ? [] : [{ name: PROVIDER_HEADER, value: params.provider.name }],
|
|
77516
77547
|
...params.headroom === void 0 ? [] : [
|
|
77517
77548
|
{ name: HEADROOM_FLAG_HEADER, value: "1" },
|
|
77518
77549
|
{ name: PROJECT_ID_HEADER, value: params.headroom.projectId }
|
|
@@ -77520,9 +77551,7 @@ function buildEnv(params) {
|
|
|
77520
77551
|
]
|
|
77521
77552
|
);
|
|
77522
77553
|
env.NODE_EXTRA_CA_CERTS = params.frontdoor.trustBundlePath;
|
|
77523
|
-
|
|
77524
|
-
env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
|
|
77525
|
-
}
|
|
77554
|
+
env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
|
|
77526
77555
|
}
|
|
77527
77556
|
return env;
|
|
77528
77557
|
}
|
|
@@ -77797,10 +77826,6 @@ function prepareLaunch(params) {
|
|
|
77797
77826
|
if (frontDoor?.trustWarning !== void 0) {
|
|
77798
77827
|
log.warn(frontDoor.trustWarning);
|
|
77799
77828
|
}
|
|
77800
|
-
let routedProvider;
|
|
77801
|
-
if (resolvedProvider !== void 0 && frontDoor !== void 0) {
|
|
77802
|
-
routedProvider = { ...resolvedProvider, baseUrl: providerBaseUrl(frontDoor.port, resolvedProvider.name) };
|
|
77803
|
-
}
|
|
77804
77829
|
let headroom;
|
|
77805
77830
|
const headroomPort = params.headroom;
|
|
77806
77831
|
if (resolvedFlags.headroom && headroomPort !== void 0) {
|
|
@@ -77824,7 +77849,7 @@ function prepareLaunch(params) {
|
|
|
77824
77849
|
configDirEscapeHatch: configDirEscapeHatchApplies,
|
|
77825
77850
|
resolvedIdentityName: identityDecision.name,
|
|
77826
77851
|
identitiesDir: paths.identitiesDir,
|
|
77827
|
-
...
|
|
77852
|
+
...resolvedProvider === void 0 ? {} : { provider: resolvedProvider },
|
|
77828
77853
|
...identityCredential === void 0 ? {} : { identityCredential },
|
|
77829
77854
|
...frontDoor === void 0 ? {} : { frontdoor: frontDoor },
|
|
77830
77855
|
...headroom === void 0 ? {} : { headroom },
|
package/dist/index.cjs
CHANGED
|
@@ -2852,18 +2852,15 @@ function isLiveCapability(presented, live) {
|
|
|
2852
2852
|
// src/frontdoor/route.ts
|
|
2853
2853
|
var IDENTITY_HEADER = "x-agent-shim-identity";
|
|
2854
2854
|
var SESSION_HEADER = "x-agent-shim-session";
|
|
2855
|
+
var PROVIDER_HEADER = "x-agent-shim-provider";
|
|
2855
2856
|
var HEADROOM_FLAG_HEADER = "x-agent-shim-headroom";
|
|
2856
2857
|
var PROJECT_ID_HEADER = "x-headroom-project-id";
|
|
2857
2858
|
var AUTH_HEADER = "x-agent-shim-auth";
|
|
2858
|
-
var PROVIDER_PATH_PREFIX = "/providers/";
|
|
2859
|
-
function providerBaseUrl(port, provider) {
|
|
2860
|
-
return `https://127.0.0.1:${String(port)}${PROVIDER_PATH_PREFIX}${encodeURIComponent(provider)}`;
|
|
2861
|
-
}
|
|
2862
2859
|
|
|
2863
2860
|
// src/frontdoor/state.ts
|
|
2864
2861
|
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
2865
2862
|
var import_zod3 = require("zod");
|
|
2866
|
-
var FRONT_DOOR_PROTOCOL =
|
|
2863
|
+
var FRONT_DOOR_PROTOCOL = 3;
|
|
2867
2864
|
var FrontDoorSessionSchema = import_zod3.z.strictObject({ pid: import_zod3.z.number().int().positive(), startedAt: import_zod3.z.number(), token: import_zod3.z.string().min(1) });
|
|
2868
2865
|
var FrontDoorStateSchema = import_zod3.z.strictObject({
|
|
2869
2866
|
/**
|
|
@@ -9118,7 +9115,7 @@ function pushProvider(push, entry, cacheEnv, signIn) {
|
|
|
9118
9115
|
const cache = cacheClause(cacheEnv, `provider ${entry.name}`, validated2.data.credential);
|
|
9119
9116
|
push("provider", cache.unreadable ? "fail" : "pass", `${entry.name} is valid (${describeProviderEndpoint(validated2.data)}, credential ${describeCredential(validated2.data.credential)})${cache.text}.`, entry.name);
|
|
9120
9117
|
if (validated2.data.env?.ENABLE_TOOL_SEARCH === void 0) {
|
|
9121
|
-
push("provider", "warn", `${entry.name} does not set ENABLE_TOOL_SEARCH: a session on this provider
|
|
9118
|
+
push("provider", "warn", `${entry.name} does not set ENABLE_TOOL_SEARCH: a session on this provider keeps Claude Code's own API as its base URL, so it defers MCP tool loading and sends tool_reference payloads the upstream backend must understand. Set ENABLE_TOOL_SEARCH=false in the provider's env block to load tools upfront instead, when the backend does not support them.`, entry.name);
|
|
9122
9119
|
}
|
|
9123
9120
|
if (signIn !== void 0 && isCodexProvider(validated2.data) && validated2.data.codex?.login === "chatgpt-sign-in") {
|
|
9124
9121
|
const problem = signInProblem(signIn);
|
|
@@ -11339,15 +11336,6 @@ function buildFlagArgs(flags) {
|
|
|
11339
11336
|
function buildArgv(params) {
|
|
11340
11337
|
return [...params.toolFlags, ...params.extraFlags, ...params.passthrough];
|
|
11341
11338
|
}
|
|
11342
|
-
var LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
|
|
11343
|
-
function isLoopbackUrl(baseUrl) {
|
|
11344
|
-
const host = new URL(baseUrl).hostname.replace(/^\[|\]$/g, "");
|
|
11345
|
-
return LOOPBACK_HOSTS.some((loopback) => loopback === host);
|
|
11346
|
-
}
|
|
11347
|
-
function withLoopbackHosts(existing) {
|
|
11348
|
-
const listed = (existing ?? "").split(",").map((entry) => entry.trim()).filter((entry) => entry !== "");
|
|
11349
|
-
return [...listed, ...LOOPBACK_HOSTS.filter((host) => !listed.includes(host))].join(",");
|
|
11350
|
-
}
|
|
11351
11339
|
function buildEnv(params) {
|
|
11352
11340
|
const env = { ...params.baseEnv };
|
|
11353
11341
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
@@ -11358,19 +11346,18 @@ function buildEnv(params) {
|
|
|
11358
11346
|
if (params.provider !== void 0) {
|
|
11359
11347
|
const providerEnv = params.provider.definition.env ?? {};
|
|
11360
11348
|
providerCustomHeaders = providerEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
11361
|
-
env.ANTHROPIC_BASE_URL =
|
|
11362
|
-
if (isLoopbackUrl(params.provider.baseUrl)) {
|
|
11363
|
-
env.NO_PROXY = withLoopbackHosts(params.baseEnv.NO_PROXY);
|
|
11364
|
-
env.no_proxy = withLoopbackHosts(params.baseEnv.no_proxy);
|
|
11365
|
-
}
|
|
11349
|
+
env.ANTHROPIC_BASE_URL = void 0;
|
|
11366
11350
|
env.AGENT_SHIM_PROVIDER = params.provider.definition.displayName;
|
|
11367
11351
|
for (const [key, value] of Object.entries(providerEnv)) {
|
|
11368
11352
|
env[key] = value;
|
|
11369
11353
|
}
|
|
11370
11354
|
}
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11355
|
+
if (params.provider !== void 0) {
|
|
11356
|
+
env.ANTHROPIC_AUTH_TOKEN = void 0;
|
|
11357
|
+
env.ANTHROPIC_API_KEY = void 0;
|
|
11358
|
+
env.CLAUDE_CODE_OAUTH_TOKEN = void 0;
|
|
11359
|
+
} else if (params.identityCredential !== void 0) {
|
|
11360
|
+
for (const [variable, value] of Object.entries(credentialVariables(params.identityCredential.target, params.identityCredential.token))) {
|
|
11374
11361
|
env[variable] = value;
|
|
11375
11362
|
}
|
|
11376
11363
|
}
|
|
@@ -11384,6 +11371,7 @@ function buildEnv(params) {
|
|
|
11384
11371
|
...params.resolvedIdentityName === void 0 ? [] : [{ name: IDENTITY_HEADER, value: params.resolvedIdentityName }],
|
|
11385
11372
|
{ name: SESSION_HEADER, value: params.sessionId },
|
|
11386
11373
|
{ name: AUTH_HEADER, value: params.frontdoor.sessionToken },
|
|
11374
|
+
...params.provider === void 0 ? [] : [{ name: PROVIDER_HEADER, value: params.provider.name }],
|
|
11387
11375
|
...params.headroom === void 0 ? [] : [
|
|
11388
11376
|
{ name: HEADROOM_FLAG_HEADER, value: "1" },
|
|
11389
11377
|
{ name: PROJECT_ID_HEADER, value: params.headroom.projectId }
|
|
@@ -11391,9 +11379,7 @@ function buildEnv(params) {
|
|
|
11391
11379
|
]
|
|
11392
11380
|
);
|
|
11393
11381
|
env.NODE_EXTRA_CA_CERTS = params.frontdoor.trustBundlePath;
|
|
11394
|
-
|
|
11395
|
-
env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
|
|
11396
|
-
}
|
|
11382
|
+
env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
|
|
11397
11383
|
}
|
|
11398
11384
|
return env;
|
|
11399
11385
|
}
|
|
@@ -11668,10 +11654,6 @@ function prepareLaunch(params) {
|
|
|
11668
11654
|
if (frontDoor?.trustWarning !== void 0) {
|
|
11669
11655
|
log.warn(frontDoor.trustWarning);
|
|
11670
11656
|
}
|
|
11671
|
-
let routedProvider;
|
|
11672
|
-
if (resolvedProvider !== void 0 && frontDoor !== void 0) {
|
|
11673
|
-
routedProvider = { ...resolvedProvider, baseUrl: providerBaseUrl(frontDoor.port, resolvedProvider.name) };
|
|
11674
|
-
}
|
|
11675
11657
|
let headroom;
|
|
11676
11658
|
const headroomPort = params.headroom;
|
|
11677
11659
|
if (resolvedFlags.headroom && headroomPort !== void 0) {
|
|
@@ -11695,7 +11677,7 @@ function prepareLaunch(params) {
|
|
|
11695
11677
|
configDirEscapeHatch: configDirEscapeHatchApplies,
|
|
11696
11678
|
resolvedIdentityName: identityDecision.name,
|
|
11697
11679
|
identitiesDir: paths.identitiesDir,
|
|
11698
|
-
...
|
|
11680
|
+
...resolvedProvider === void 0 ? {} : { provider: resolvedProvider },
|
|
11699
11681
|
...identityCredential === void 0 ? {} : { identityCredential },
|
|
11700
11682
|
...frontDoor === void 0 ? {} : { frontdoor: frontDoor },
|
|
11701
11683
|
...headroom === void 0 ? {} : { headroom },
|
package/dist/index.mjs
CHANGED
|
@@ -2588,18 +2588,15 @@ function isLiveCapability(presented, live) {
|
|
|
2588
2588
|
// src/frontdoor/route.ts
|
|
2589
2589
|
var IDENTITY_HEADER = "x-agent-shim-identity";
|
|
2590
2590
|
var SESSION_HEADER = "x-agent-shim-session";
|
|
2591
|
+
var PROVIDER_HEADER = "x-agent-shim-provider";
|
|
2591
2592
|
var HEADROOM_FLAG_HEADER = "x-agent-shim-headroom";
|
|
2592
2593
|
var PROJECT_ID_HEADER = "x-headroom-project-id";
|
|
2593
2594
|
var AUTH_HEADER = "x-agent-shim-auth";
|
|
2594
|
-
var PROVIDER_PATH_PREFIX = "/providers/";
|
|
2595
|
-
function providerBaseUrl(port, provider) {
|
|
2596
|
-
return `https://127.0.0.1:${String(port)}${PROVIDER_PATH_PREFIX}${encodeURIComponent(provider)}`;
|
|
2597
|
-
}
|
|
2598
2595
|
|
|
2599
2596
|
// src/frontdoor/state.ts
|
|
2600
2597
|
import path8 from "node:path";
|
|
2601
2598
|
import { z as z3 } from "zod";
|
|
2602
|
-
var FRONT_DOOR_PROTOCOL =
|
|
2599
|
+
var FRONT_DOOR_PROTOCOL = 3;
|
|
2603
2600
|
var FrontDoorSessionSchema = z3.strictObject({ pid: z3.number().int().positive(), startedAt: z3.number(), token: z3.string().min(1) });
|
|
2604
2601
|
var FrontDoorStateSchema = z3.strictObject({
|
|
2605
2602
|
/**
|
|
@@ -8854,7 +8851,7 @@ function pushProvider(push, entry, cacheEnv, signIn) {
|
|
|
8854
8851
|
const cache = cacheClause(cacheEnv, `provider ${entry.name}`, validated2.data.credential);
|
|
8855
8852
|
push("provider", cache.unreadable ? "fail" : "pass", `${entry.name} is valid (${describeProviderEndpoint(validated2.data)}, credential ${describeCredential(validated2.data.credential)})${cache.text}.`, entry.name);
|
|
8856
8853
|
if (validated2.data.env?.ENABLE_TOOL_SEARCH === void 0) {
|
|
8857
|
-
push("provider", "warn", `${entry.name} does not set ENABLE_TOOL_SEARCH: a session on this provider
|
|
8854
|
+
push("provider", "warn", `${entry.name} does not set ENABLE_TOOL_SEARCH: a session on this provider keeps Claude Code's own API as its base URL, so it defers MCP tool loading and sends tool_reference payloads the upstream backend must understand. Set ENABLE_TOOL_SEARCH=false in the provider's env block to load tools upfront instead, when the backend does not support them.`, entry.name);
|
|
8858
8855
|
}
|
|
8859
8856
|
if (signIn !== void 0 && isCodexProvider(validated2.data) && validated2.data.codex?.login === "chatgpt-sign-in") {
|
|
8860
8857
|
const problem = signInProblem(signIn);
|
|
@@ -11075,15 +11072,6 @@ function buildFlagArgs(flags) {
|
|
|
11075
11072
|
function buildArgv(params) {
|
|
11076
11073
|
return [...params.toolFlags, ...params.extraFlags, ...params.passthrough];
|
|
11077
11074
|
}
|
|
11078
|
-
var LOOPBACK_HOSTS = ["127.0.0.1", "localhost", "::1"];
|
|
11079
|
-
function isLoopbackUrl(baseUrl) {
|
|
11080
|
-
const host = new URL(baseUrl).hostname.replace(/^\[|\]$/g, "");
|
|
11081
|
-
return LOOPBACK_HOSTS.some((loopback) => loopback === host);
|
|
11082
|
-
}
|
|
11083
|
-
function withLoopbackHosts(existing) {
|
|
11084
|
-
const listed = (existing ?? "").split(",").map((entry) => entry.trim()).filter((entry) => entry !== "");
|
|
11085
|
-
return [...listed, ...LOOPBACK_HOSTS.filter((host) => !listed.includes(host))].join(",");
|
|
11086
|
-
}
|
|
11087
11075
|
function buildEnv(params) {
|
|
11088
11076
|
const env = { ...params.baseEnv };
|
|
11089
11077
|
const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
@@ -11094,19 +11082,18 @@ function buildEnv(params) {
|
|
|
11094
11082
|
if (params.provider !== void 0) {
|
|
11095
11083
|
const providerEnv = params.provider.definition.env ?? {};
|
|
11096
11084
|
providerCustomHeaders = providerEnv.ANTHROPIC_CUSTOM_HEADERS;
|
|
11097
|
-
env.ANTHROPIC_BASE_URL =
|
|
11098
|
-
if (isLoopbackUrl(params.provider.baseUrl)) {
|
|
11099
|
-
env.NO_PROXY = withLoopbackHosts(params.baseEnv.NO_PROXY);
|
|
11100
|
-
env.no_proxy = withLoopbackHosts(params.baseEnv.no_proxy);
|
|
11101
|
-
}
|
|
11085
|
+
env.ANTHROPIC_BASE_URL = void 0;
|
|
11102
11086
|
env.AGENT_SHIM_PROVIDER = params.provider.definition.displayName;
|
|
11103
11087
|
for (const [key, value] of Object.entries(providerEnv)) {
|
|
11104
11088
|
env[key] = value;
|
|
11105
11089
|
}
|
|
11106
11090
|
}
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11091
|
+
if (params.provider !== void 0) {
|
|
11092
|
+
env.ANTHROPIC_AUTH_TOKEN = void 0;
|
|
11093
|
+
env.ANTHROPIC_API_KEY = void 0;
|
|
11094
|
+
env.CLAUDE_CODE_OAUTH_TOKEN = void 0;
|
|
11095
|
+
} else if (params.identityCredential !== void 0) {
|
|
11096
|
+
for (const [variable, value] of Object.entries(credentialVariables(params.identityCredential.target, params.identityCredential.token))) {
|
|
11110
11097
|
env[variable] = value;
|
|
11111
11098
|
}
|
|
11112
11099
|
}
|
|
@@ -11120,6 +11107,7 @@ function buildEnv(params) {
|
|
|
11120
11107
|
...params.resolvedIdentityName === void 0 ? [] : [{ name: IDENTITY_HEADER, value: params.resolvedIdentityName }],
|
|
11121
11108
|
{ name: SESSION_HEADER, value: params.sessionId },
|
|
11122
11109
|
{ name: AUTH_HEADER, value: params.frontdoor.sessionToken },
|
|
11110
|
+
...params.provider === void 0 ? [] : [{ name: PROVIDER_HEADER, value: params.provider.name }],
|
|
11123
11111
|
...params.headroom === void 0 ? [] : [
|
|
11124
11112
|
{ name: HEADROOM_FLAG_HEADER, value: "1" },
|
|
11125
11113
|
{ name: PROJECT_ID_HEADER, value: params.headroom.projectId }
|
|
@@ -11127,9 +11115,7 @@ function buildEnv(params) {
|
|
|
11127
11115
|
]
|
|
11128
11116
|
);
|
|
11129
11117
|
env.NODE_EXTRA_CA_CERTS = params.frontdoor.trustBundlePath;
|
|
11130
|
-
|
|
11131
|
-
env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
|
|
11132
|
-
}
|
|
11118
|
+
env.HTTPS_PROXY = connectProxyUrl(params.frontdoor.connectPort, params.frontdoor.sessionToken);
|
|
11133
11119
|
}
|
|
11134
11120
|
return env;
|
|
11135
11121
|
}
|
|
@@ -11404,10 +11390,6 @@ function prepareLaunch(params) {
|
|
|
11404
11390
|
if (frontDoor?.trustWarning !== void 0) {
|
|
11405
11391
|
log.warn(frontDoor.trustWarning);
|
|
11406
11392
|
}
|
|
11407
|
-
let routedProvider;
|
|
11408
|
-
if (resolvedProvider !== void 0 && frontDoor !== void 0) {
|
|
11409
|
-
routedProvider = { ...resolvedProvider, baseUrl: providerBaseUrl(frontDoor.port, resolvedProvider.name) };
|
|
11410
|
-
}
|
|
11411
11393
|
let headroom;
|
|
11412
11394
|
const headroomPort = params.headroom;
|
|
11413
11395
|
if (resolvedFlags.headroom && headroomPort !== void 0) {
|
|
@@ -11431,7 +11413,7 @@ function prepareLaunch(params) {
|
|
|
11431
11413
|
configDirEscapeHatch: configDirEscapeHatchApplies,
|
|
11432
11414
|
resolvedIdentityName: identityDecision.name,
|
|
11433
11415
|
identitiesDir: paths.identitiesDir,
|
|
11434
|
-
...
|
|
11416
|
+
...resolvedProvider === void 0 ? {} : { provider: resolvedProvider },
|
|
11435
11417
|
...identityCredential === void 0 ? {} : { identityCredential },
|
|
11436
11418
|
...frontDoor === void 0 ? {} : { frontdoor: frontDoor },
|
|
11437
11419
|
...headroom === void 0 ? {} : { headroom },
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1687,6 +1687,8 @@ interface SessionIdentity {
|
|
|
1687
1687
|
readonly identity: string | undefined;
|
|
1688
1688
|
/** The per-launch session id, when the launcher injected one. */
|
|
1689
1689
|
readonly sessionId: string | undefined;
|
|
1690
|
+
/** The provider this launch selected, when it selected one: the door routes the session's API traffic to that provider whatever host the child believes it is dialling. */
|
|
1691
|
+
readonly provider: string | undefined;
|
|
1690
1692
|
/** Whether this launch resolved headroom on, so its requests must pass through the headroom hop before their route. */
|
|
1691
1693
|
readonly headroom: boolean;
|
|
1692
1694
|
/** The project identity headroom scopes memory to, re-set on the headroom hop and sent nowhere else. */
|
|
@@ -2832,7 +2834,7 @@ interface EvaluateAmbientCredentialGuardParams {
|
|
|
2832
2834
|
/** The active identity's name, for the message's persistent-opt-in command. Undefined when no identity is known. */
|
|
2833
2835
|
readonly identityName?: string;
|
|
2834
2836
|
/**
|
|
2835
|
-
* True when this launch routes through an API provider. The guard inspects the PARENT environment, before `buildEnv` runs; a provider launch has
|
|
2837
|
+
* True when this launch routes through an API provider. The guard inspects the PARENT environment, before `buildEnv` runs; a provider launch has every credential variable removed by `buildEnv` itself (the door attaches the provider's credential at its route, so the child presents nothing), so an ambient credential in the parent environment never reaches the child and there is nothing left for this guard to protect against. Everything else about the guard (including `IdentitySchema.allowAmbientCredential`) is unchanged by this flag.
|
|
2836
2838
|
*/
|
|
2837
2839
|
readonly providerSelected?: boolean;
|
|
2838
2840
|
/** The launching identity's own credential, when its credential block resolved: see `detectAmbientCredential`. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-shim",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.19.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>",
|