agent-shim 8.15.0 → 8.17.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 +5 -2
- package/dist/cli.cjs +1406 -217
- package/dist/index.cjs +376 -46
- package/dist/index.mjs +365 -45
- package/dist/types/index.d.ts +174 -30
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -14464,7 +14464,7 @@ var require_client = __commonJS({
|
|
|
14464
14464
|
"use strict";
|
|
14465
14465
|
var assert2 = require("node:assert");
|
|
14466
14466
|
var net3 = require("node:net");
|
|
14467
|
-
var
|
|
14467
|
+
var http7 = require("node:http");
|
|
14468
14468
|
var util = require_util2();
|
|
14469
14469
|
var { ClientStats } = require_stats();
|
|
14470
14470
|
var { channels } = require_diagnostics();
|
|
@@ -14522,7 +14522,7 @@ var require_client = __commonJS({
|
|
|
14522
14522
|
var connectH1 = require_client_h1();
|
|
14523
14523
|
var connectH2 = require_client_h2();
|
|
14524
14524
|
var kClosedResolve = /* @__PURE__ */ Symbol("kClosedResolve");
|
|
14525
|
-
var getDefaultNodeMaxHeaderSize =
|
|
14525
|
+
var getDefaultNodeMaxHeaderSize = http7 && http7.maxHeaderSize && Number.isInteger(http7.maxHeaderSize) && http7.maxHeaderSize > 0 ? () => http7.maxHeaderSize : () => {
|
|
14526
14526
|
throw new InvalidArgumentError2("http module not available or http.maxHeaderSize invalid");
|
|
14527
14527
|
};
|
|
14528
14528
|
var noop = () => {
|
|
@@ -55242,6 +55242,8 @@ var ProviderEnvSchema = external_exports.record(external_exports.string().min(1)
|
|
|
55242
55242
|
var PROVIDER_KINDS = ["http", "codex"];
|
|
55243
55243
|
var CODEX_TIERS = ["fable", "opus", "sonnet", "haiku"];
|
|
55244
55244
|
var CODEX_EFFORTS = ["none", "low", "medium", "high"];
|
|
55245
|
+
var CODEX_LOGINS = ["codex-cli", "chatgpt-sign-in"];
|
|
55246
|
+
var CODEX_DEFAULT_LOGIN = "codex-cli";
|
|
55245
55247
|
var CODEX_DEFAULT_MODEL = "gpt-5.6-sol";
|
|
55246
55248
|
var CODEX_DEFAULT_TIER_MODELS = Object.freeze({
|
|
55247
55249
|
fable: "gpt-5.6-sol",
|
|
@@ -55261,7 +55263,9 @@ var CodexProviderConfigSchema = external_exports.strictObject({
|
|
|
55261
55263
|
haiku: external_exports.string().min(1).optional()
|
|
55262
55264
|
}).optional(),
|
|
55263
55265
|
/** The reasoning effort used when the request's own `output_config.effort` is not one the backend accepts. */
|
|
55264
|
-
effort: external_exports.enum(CODEX_EFFORTS).optional()
|
|
55266
|
+
effort: external_exports.enum(CODEX_EFFORTS).optional(),
|
|
55267
|
+
/** Which login the upstream call is made with; see `CODEX_LOGINS`. */
|
|
55268
|
+
login: external_exports.enum(CODEX_LOGINS).optional()
|
|
55265
55269
|
});
|
|
55266
55270
|
var HttpProviderSchema = external_exports.strictObject({
|
|
55267
55271
|
$schema: external_exports.string().optional(),
|
|
@@ -60278,6 +60282,7 @@ function buildLayoutPaths(root) {
|
|
|
60278
60282
|
frontdoorCaCertFile: import_node_path19.default.join(root, "frontdoor", "ca", "ca.pem"),
|
|
60279
60283
|
frontdoorCaKeyFile: import_node_path19.default.join(root, "frontdoor", "ca", "ca.key"),
|
|
60280
60284
|
frontdoorCaBundlesDir: import_node_path19.default.join(root, "frontdoor", "ca", "bundles"),
|
|
60285
|
+
chatgptSignInFile: import_node_path19.default.join(root, "codex", "chatgpt-sign-in.json"),
|
|
60281
60286
|
frontdoorStateFile: import_node_path19.default.join(root, "frontdoor", "state.json"),
|
|
60282
60287
|
frontdoorLockFile: import_node_path19.default.join(root, "frontdoor", "start.lock"),
|
|
60283
60288
|
frontdoorControlTokenFile: import_node_path19.default.join(root, "frontdoor", "control-token"),
|
|
@@ -61744,7 +61749,7 @@ function registerIdentityCommand(program2, deps) {
|
|
|
61744
61749
|
// package.json
|
|
61745
61750
|
var package_default = {
|
|
61746
61751
|
name: "agent-shim",
|
|
61747
|
-
version: "8.
|
|
61752
|
+
version: "8.17.0",
|
|
61748
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.",
|
|
61749
61754
|
license: "MIT",
|
|
61750
61755
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -63484,7 +63489,7 @@ var ProviderKindMismatchError = class extends UsageError {
|
|
|
63484
63489
|
}
|
|
63485
63490
|
};
|
|
63486
63491
|
function isEmptyCodexConfig(config2) {
|
|
63487
|
-
return config2 === void 0 || config2.defaultModel === void 0 && config2.effort === void 0 && (config2.models === void 0 || Object.keys(config2.models).length === 0);
|
|
63492
|
+
return config2 === void 0 || config2.defaultModel === void 0 && config2.effort === void 0 && config2.login === void 0 && (config2.models === void 0 || Object.keys(config2.models).length === 0);
|
|
63488
63493
|
}
|
|
63489
63494
|
function addProvider(paths, name, input2) {
|
|
63490
63495
|
if (providerExists(paths, name)) {
|
|
@@ -64121,7 +64126,7 @@ function registerCheckCommand(program2, deps) {
|
|
|
64121
64126
|
}
|
|
64122
64127
|
|
|
64123
64128
|
// src/codex/commands.ts
|
|
64124
|
-
var
|
|
64129
|
+
var import_node_crypto9 = require("node:crypto");
|
|
64125
64130
|
var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
64126
64131
|
var import_node_os6 = __toESM(require("node:os"), 1);
|
|
64127
64132
|
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
@@ -64272,8 +64277,273 @@ function createCodexAuthStore(authPath, ports) {
|
|
|
64272
64277
|
};
|
|
64273
64278
|
}
|
|
64274
64279
|
|
|
64275
|
-
// src/codex/
|
|
64280
|
+
// src/codex/siwc.ts
|
|
64276
64281
|
var import_node_crypto6 = require("node:crypto");
|
|
64282
|
+
var SIWC_AUTHORIZE_URL = "https://auth.openai.com/api/accounts/authorize";
|
|
64283
|
+
var SIWC_TOKEN_URL = "https://auth.openai.com/api/accounts/oauth/token";
|
|
64284
|
+
var SIWC_REVOKE_URL = "https://auth.openai.com/api/accounts/oauth/revoke";
|
|
64285
|
+
var SIWC_ISSUER = "https://auth.openai.com";
|
|
64286
|
+
var SIWC_JWKS_URL = "https://auth.openai.com/.well-known/jwks.json";
|
|
64287
|
+
var SIWC_DYNAMIC_CLIENT_ID = "dynamic_agent_client";
|
|
64288
|
+
var SIWC_RESOURCE = "https://api.openai.com/v1";
|
|
64289
|
+
var SIWC_RESPONSES_URL = `${SIWC_RESOURCE}/responses`;
|
|
64290
|
+
var SIWC_SCOPES = ["openid", "profile", "email", "offline_access", "resource.invoke", "chatgpt.tokens.use.direct"];
|
|
64291
|
+
var SIWC_PLAN_SCOPE = "chatgpt.tokens.use.direct";
|
|
64292
|
+
var SIWC_CALLBACK_PORT = 1455;
|
|
64293
|
+
var SIWC_CALLBACK_PATH = "/auth/callback";
|
|
64294
|
+
var SIWC_RANDOM_BYTES = 32;
|
|
64295
|
+
var MS_PER_SECOND4 = 1e3;
|
|
64296
|
+
var ID_TOKEN_ALGORITHM = "RS256";
|
|
64297
|
+
var SiwcError = class extends Error {
|
|
64298
|
+
constructor(message) {
|
|
64299
|
+
super(message);
|
|
64300
|
+
this.name = "SiwcError";
|
|
64301
|
+
}
|
|
64302
|
+
};
|
|
64303
|
+
var SiwcInvalidGrantError = class extends SiwcError {
|
|
64304
|
+
constructor(message) {
|
|
64305
|
+
super(message);
|
|
64306
|
+
this.name = "SiwcInvalidGrantError";
|
|
64307
|
+
}
|
|
64308
|
+
};
|
|
64309
|
+
function base64Url(bytes) {
|
|
64310
|
+
return Buffer.from(bytes).toString("base64url");
|
|
64311
|
+
}
|
|
64312
|
+
function newPkce(randomBytes4) {
|
|
64313
|
+
const verifier = base64Url(randomBytes4(SIWC_RANDOM_BYTES));
|
|
64314
|
+
return { verifier, challenge: (0, import_node_crypto6.createHash)("sha256").update(verifier).digest("base64url") };
|
|
64315
|
+
}
|
|
64316
|
+
function newOpaqueValue(randomBytes4) {
|
|
64317
|
+
return base64Url(randomBytes4(SIWC_RANDOM_BYTES));
|
|
64318
|
+
}
|
|
64319
|
+
function buildAuthorizeUrl(request7) {
|
|
64320
|
+
const url2 = new URL(SIWC_AUTHORIZE_URL);
|
|
64321
|
+
const params = url2.searchParams;
|
|
64322
|
+
params.set("client_id", request7.clientId ?? SIWC_DYNAMIC_CLIENT_ID);
|
|
64323
|
+
if (request7.clientId === void 0) {
|
|
64324
|
+
params.set("agent_name_hint", request7.agentName);
|
|
64325
|
+
}
|
|
64326
|
+
if (request7.returning !== void 0) {
|
|
64327
|
+
params.set("id_token_hint", request7.returning.idToken);
|
|
64328
|
+
if (request7.returning.loginHint !== void 0) {
|
|
64329
|
+
params.set("login_hint", request7.returning.loginHint);
|
|
64330
|
+
}
|
|
64331
|
+
}
|
|
64332
|
+
params.set("response_type", "code");
|
|
64333
|
+
params.set("redirect_uri", request7.redirectUri);
|
|
64334
|
+
params.set("scope", SIWC_SCOPES.join(" "));
|
|
64335
|
+
params.set("resource", SIWC_RESOURCE);
|
|
64336
|
+
params.set("state", request7.state);
|
|
64337
|
+
params.set("nonce", request7.nonce);
|
|
64338
|
+
params.set("code_challenge_method", "S256");
|
|
64339
|
+
params.set("code_challenge", request7.challenge);
|
|
64340
|
+
return url2.toString();
|
|
64341
|
+
}
|
|
64342
|
+
function parseCallback(url2, expectedState) {
|
|
64343
|
+
const params = url2.searchParams;
|
|
64344
|
+
const error62 = params.get("error");
|
|
64345
|
+
if (error62 !== null) {
|
|
64346
|
+
throw new SiwcError(`the sign-in was refused: ${error62}${params.has("error_description") ? ` (${params.get("error_description") ?? ""})` : ""}`);
|
|
64347
|
+
}
|
|
64348
|
+
if (params.get("state") !== expectedState) {
|
|
64349
|
+
throw new SiwcError("the sign-in callback's state did not match the request, so it was discarded");
|
|
64350
|
+
}
|
|
64351
|
+
const code = params.get("code");
|
|
64352
|
+
if (code === null || code === "") {
|
|
64353
|
+
throw new SiwcError("the sign-in callback carried no authorization code");
|
|
64354
|
+
}
|
|
64355
|
+
const scope = params.get("scope");
|
|
64356
|
+
return { code, clientId: params.get("client_id") ?? void 0, scopes: scope === null ? [] : scope.split(" ").filter((part) => part !== "") };
|
|
64357
|
+
}
|
|
64358
|
+
var TokenResponseSchema = external_exports.looseObject({
|
|
64359
|
+
access_token: external_exports.string().min(1),
|
|
64360
|
+
refresh_token: external_exports.string().min(1).optional(),
|
|
64361
|
+
id_token: external_exports.string().min(1).optional(),
|
|
64362
|
+
expires_in: external_exports.number().positive(),
|
|
64363
|
+
scope: external_exports.string().optional()
|
|
64364
|
+
});
|
|
64365
|
+
var ERROR_BODY_CHARS = 300;
|
|
64366
|
+
var TOKEN_CALL_TIMEOUT_MS = 3e4;
|
|
64367
|
+
async function postToken(ports, form, what) {
|
|
64368
|
+
const response = await ports.fetch(SIWC_TOKEN_URL, {
|
|
64369
|
+
method: "POST",
|
|
64370
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
64371
|
+
body: new URLSearchParams({ ...form, resource: SIWC_RESOURCE }).toString(),
|
|
64372
|
+
signal: AbortSignal.timeout(TOKEN_CALL_TIMEOUT_MS)
|
|
64373
|
+
});
|
|
64374
|
+
if (!response.ok) {
|
|
64375
|
+
const detail = (await response.text()).slice(0, ERROR_BODY_CHARS);
|
|
64376
|
+
const message = `the ${what} failed with HTTP ${String(response.status)}: ${detail}`;
|
|
64377
|
+
throw /"error"\s*:\s*"invalid_grant"/.test(detail) ? new SiwcInvalidGrantError(message) : new SiwcError(message);
|
|
64378
|
+
}
|
|
64379
|
+
const parsed = TokenResponseSchema.safeParse(await response.json());
|
|
64380
|
+
if (!parsed.success) {
|
|
64381
|
+
throw new SiwcError(`the ${what} answered without an access token and a lifetime`);
|
|
64382
|
+
}
|
|
64383
|
+
return parsed.data;
|
|
64384
|
+
}
|
|
64385
|
+
function grantTokens(ports, answer) {
|
|
64386
|
+
return {
|
|
64387
|
+
accessToken: answer.access_token,
|
|
64388
|
+
refreshToken: answer.refresh_token,
|
|
64389
|
+
idToken: answer.id_token,
|
|
64390
|
+
scopes: answer.scope === void 0 ? void 0 : answer.scope.split(" ").filter((part) => part !== ""),
|
|
64391
|
+
expiresAt: ports.now().getTime() + answer.expires_in * MS_PER_SECOND4
|
|
64392
|
+
};
|
|
64393
|
+
}
|
|
64394
|
+
async function exchangeCode(ports, request7) {
|
|
64395
|
+
return grantTokens(
|
|
64396
|
+
ports,
|
|
64397
|
+
await postToken(ports, { grant_type: "authorization_code", client_id: request7.clientId, code: request7.code, code_verifier: request7.verifier, redirect_uri: request7.redirectUri }, "authorisation code exchange")
|
|
64398
|
+
);
|
|
64399
|
+
}
|
|
64400
|
+
async function refreshTokens(ports, request7) {
|
|
64401
|
+
return grantTokens(ports, await postToken(ports, { grant_type: "refresh_token", client_id: request7.clientId, refresh_token: request7.refreshToken }, "token refresh"));
|
|
64402
|
+
}
|
|
64403
|
+
var JwtHeaderSchema = external_exports.looseObject({ alg: external_exports.string(), kid: external_exports.string().optional() });
|
|
64404
|
+
var IdTokenClaimsSchema = external_exports.looseObject({
|
|
64405
|
+
iss: external_exports.string(),
|
|
64406
|
+
sub: external_exports.string().min(1),
|
|
64407
|
+
aud: external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]),
|
|
64408
|
+
exp: external_exports.number(),
|
|
64409
|
+
nonce: external_exports.string().optional(),
|
|
64410
|
+
email: external_exports.string().optional()
|
|
64411
|
+
});
|
|
64412
|
+
var JwksSchema = external_exports.object({ keys: external_exports.array(external_exports.looseObject({ kid: external_exports.string().optional(), kty: external_exports.string() })) });
|
|
64413
|
+
function decodeSegment(segment) {
|
|
64414
|
+
if (segment === void 0) {
|
|
64415
|
+
throw new SiwcError("the ID token is not a three-part JWT");
|
|
64416
|
+
}
|
|
64417
|
+
try {
|
|
64418
|
+
const parsed = JSON.parse(Buffer.from(segment, "base64url").toString("utf8"));
|
|
64419
|
+
return parsed;
|
|
64420
|
+
} catch {
|
|
64421
|
+
throw new SiwcError("the ID token has an unreadable segment");
|
|
64422
|
+
}
|
|
64423
|
+
}
|
|
64424
|
+
async function verifyIdToken(ports, idToken, expected) {
|
|
64425
|
+
const [headerSegment, payloadSegment, signatureSegment, ...rest] = idToken.split(".");
|
|
64426
|
+
if (rest.length > 0 || headerSegment === void 0 || payloadSegment === void 0 || signatureSegment === void 0) {
|
|
64427
|
+
throw new SiwcError("the ID token is not a three-part JWT");
|
|
64428
|
+
}
|
|
64429
|
+
const header = JwtHeaderSchema.parse(decodeSegment(headerSegment));
|
|
64430
|
+
if (header.alg !== ID_TOKEN_ALGORITHM) {
|
|
64431
|
+
throw new SiwcError(`the ID token is signed with ${header.alg}, and only ${ID_TOKEN_ALGORITHM} is accepted`);
|
|
64432
|
+
}
|
|
64433
|
+
const response = await ports.fetch(SIWC_JWKS_URL, { method: "GET", headers: {}, signal: AbortSignal.timeout(TOKEN_CALL_TIMEOUT_MS) });
|
|
64434
|
+
if (!response.ok) {
|
|
64435
|
+
throw new SiwcError(`the issuer's key set could not be fetched (HTTP ${String(response.status)})`);
|
|
64436
|
+
}
|
|
64437
|
+
const jwk = JwksSchema.parse(await response.json()).keys.find((key) => key.kty === "RSA" && (header.kid === void 0 || key.kid === header.kid));
|
|
64438
|
+
if (jwk === void 0) {
|
|
64439
|
+
throw new SiwcError("the issuer's key set has no key for the ID token's signature");
|
|
64440
|
+
}
|
|
64441
|
+
const signed = Buffer.from(`${headerSegment}.${payloadSegment}`);
|
|
64442
|
+
if (!(0, import_node_crypto6.verify)("sha256", signed, (0, import_node_crypto6.createPublicKey)({ key: jwk, format: "jwk" }), Buffer.from(signatureSegment, "base64url"))) {
|
|
64443
|
+
throw new SiwcError("the ID token's signature did not verify");
|
|
64444
|
+
}
|
|
64445
|
+
const claims = IdTokenClaimsSchema.parse(decodeSegment(payloadSegment));
|
|
64446
|
+
if (claims.iss !== SIWC_ISSUER) {
|
|
64447
|
+
throw new SiwcError(`the ID token was issued by ${claims.iss}, not ${SIWC_ISSUER}`);
|
|
64448
|
+
}
|
|
64449
|
+
if (!(Array.isArray(claims.aud) ? claims.aud : [claims.aud]).includes(expected.clientId)) {
|
|
64450
|
+
throw new SiwcError("the ID token was issued for a different client");
|
|
64451
|
+
}
|
|
64452
|
+
if (claims.exp * MS_PER_SECOND4 <= ports.now().getTime()) {
|
|
64453
|
+
throw new SiwcError("the ID token has already expired");
|
|
64454
|
+
}
|
|
64455
|
+
if (expected.nonce !== void 0 && claims.nonce !== expected.nonce) {
|
|
64456
|
+
throw new SiwcError("the ID token's nonce did not match the request");
|
|
64457
|
+
}
|
|
64458
|
+
return { sub: claims.sub, email: claims.email };
|
|
64459
|
+
}
|
|
64460
|
+
|
|
64461
|
+
// src/codex/siwcLogin.ts
|
|
64462
|
+
var SIWC_AGENT_NAME = "agent-shim";
|
|
64463
|
+
var SIWC_LOGIN_TIMEOUT_MS = 3e5;
|
|
64464
|
+
async function runSiwcLogin(ports, options) {
|
|
64465
|
+
const existing = ports.store.read();
|
|
64466
|
+
const returning = existing?.grant;
|
|
64467
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
64468
|
+
const clientId = ports.store.read()?.registeredClientId ?? returning?.clientId;
|
|
64469
|
+
try {
|
|
64470
|
+
return await authorizeOnce(ports, options, clientId, attempt === 0 ? returning : void 0);
|
|
64471
|
+
} catch (error62) {
|
|
64472
|
+
if (!(error62 instanceof SiwcInvalidGrantError) || attempt > 0) {
|
|
64473
|
+
throw error62;
|
|
64474
|
+
}
|
|
64475
|
+
ports.print("OpenAI did not accept the first code, which is expected once after registering: authorising again with the registration it issued.");
|
|
64476
|
+
}
|
|
64477
|
+
}
|
|
64478
|
+
}
|
|
64479
|
+
async function authorizeOnce(ports, options, savedClientId, returning) {
|
|
64480
|
+
const pkce = newPkce(ports.siwc.randomBytes);
|
|
64481
|
+
const state = newOpaqueValue(ports.siwc.randomBytes);
|
|
64482
|
+
const nonce = newOpaqueValue(ports.siwc.randomBytes);
|
|
64483
|
+
const redirectUri = `http://127.0.0.1:${String(SIWC_CALLBACK_PORT)}${SIWC_CALLBACK_PATH}`;
|
|
64484
|
+
const url2 = buildAuthorizeUrl({
|
|
64485
|
+
clientId: savedClientId,
|
|
64486
|
+
agentName: SIWC_AGENT_NAME,
|
|
64487
|
+
redirectUri,
|
|
64488
|
+
state,
|
|
64489
|
+
nonce,
|
|
64490
|
+
challenge: pkce.challenge,
|
|
64491
|
+
...returning === void 0 ? {} : { returning: { idToken: returning.idToken, loginHint: returning.email } }
|
|
64492
|
+
});
|
|
64493
|
+
const listener = await ports.listen(SIWC_CALLBACK_PORT, state);
|
|
64494
|
+
try {
|
|
64495
|
+
ports.print(`Sign in at: ${url2}`);
|
|
64496
|
+
if (options.open) {
|
|
64497
|
+
ports.openBrowser(url2);
|
|
64498
|
+
}
|
|
64499
|
+
const callback = parseCallback(await listener.waitForCallback(AbortSignal.timeout(SIWC_LOGIN_TIMEOUT_MS)), state);
|
|
64500
|
+
const clientId = callback.clientId ?? savedClientId;
|
|
64501
|
+
if (clientId === void 0) {
|
|
64502
|
+
throw new SiwcError("the sign-in callback carried no client id and none was stored from an earlier sign-in");
|
|
64503
|
+
}
|
|
64504
|
+
const grantBefore = ports.store.read()?.grant;
|
|
64505
|
+
ports.store.write({ registeredClientId: clientId, ...grantBefore === void 0 ? {} : { grant: grantBefore } });
|
|
64506
|
+
const tokens = await exchangeCode(ports.siwc, { clientId, code: callback.code, verifier: pkce.verifier, redirectUri });
|
|
64507
|
+
if (tokens.refreshToken === void 0 || tokens.idToken === void 0) {
|
|
64508
|
+
throw new SiwcError("the token endpoint did not return a refresh token and an ID token, so the sign-in cannot be kept");
|
|
64509
|
+
}
|
|
64510
|
+
const scopes = tokens.scopes ?? callback.scopes;
|
|
64511
|
+
if (!scopes.includes(SIWC_PLAN_SCOPE)) {
|
|
64512
|
+
throw new SiwcError("the sign-in was not granted permission to use your ChatGPT plan: run the login again and allow it");
|
|
64513
|
+
}
|
|
64514
|
+
const identity = await verifyIdToken(ports.siwc, tokens.idToken, { clientId, nonce });
|
|
64515
|
+
ports.store.write({
|
|
64516
|
+
registeredClientId: clientId,
|
|
64517
|
+
grant: { clientId, sub: identity.sub, ...identity.email === void 0 ? {} : { email: identity.email }, idToken: tokens.idToken, accessToken: tokens.accessToken, refreshToken: tokens.refreshToken, scopes, expiresAt: tokens.expiresAt }
|
|
64518
|
+
});
|
|
64519
|
+
return { email: identity.email, sub: identity.sub };
|
|
64520
|
+
} finally {
|
|
64521
|
+
listener.close();
|
|
64522
|
+
}
|
|
64523
|
+
}
|
|
64524
|
+
var REVOKE_TIMEOUT_MS = 3e4;
|
|
64525
|
+
async function runSiwcLogout(ports) {
|
|
64526
|
+
const file2 = ports.store.read();
|
|
64527
|
+
if (file2?.grant === void 0) {
|
|
64528
|
+
return { hadGrant: false, revoked: false };
|
|
64529
|
+
}
|
|
64530
|
+
const revoked = await ports.siwc.fetch(SIWC_REVOKE_URL, {
|
|
64531
|
+
method: "POST",
|
|
64532
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
64533
|
+
body: new URLSearchParams({ token: file2.grant.refreshToken, token_type_hint: "refresh_token", client_id: file2.grant.clientId }).toString(),
|
|
64534
|
+
signal: AbortSignal.timeout(REVOKE_TIMEOUT_MS)
|
|
64535
|
+
}).then(
|
|
64536
|
+
(response) => response.ok,
|
|
64537
|
+
() => false
|
|
64538
|
+
);
|
|
64539
|
+
ports.store.write({ registeredClientId: file2.grant.clientId });
|
|
64540
|
+
return { hadGrant: true, revoked };
|
|
64541
|
+
}
|
|
64542
|
+
|
|
64543
|
+
// src/codex/siwcPorts.ts
|
|
64544
|
+
var import_node_child_process4 = require("node:child_process");
|
|
64545
|
+
var import_node_crypto7 = require("node:crypto");
|
|
64546
|
+
var import_node_http = __toESM(require("node:http"), 1);
|
|
64277
64547
|
|
|
64278
64548
|
// src/codex/http.ts
|
|
64279
64549
|
var HTTP_STATUS = {
|
|
@@ -64291,7 +64561,157 @@ var HTTP_STATUS = {
|
|
|
64291
64561
|
badGateway: 502
|
|
64292
64562
|
};
|
|
64293
64563
|
|
|
64564
|
+
// src/codex/siwcPorts.ts
|
|
64565
|
+
function realSiwcPorts(fetch3) {
|
|
64566
|
+
return { fetch: fetch3, randomBytes: (size) => (0, import_node_crypto7.randomBytes)(size), now: () => /* @__PURE__ */ new Date() };
|
|
64567
|
+
}
|
|
64568
|
+
var CALLBACK_PAGE = "<!doctype html><meta charset=utf-8><title>Signed in</title><p>You can close this tab and return to the terminal.</p>";
|
|
64569
|
+
async function listenForCallback(port, state) {
|
|
64570
|
+
let deliver;
|
|
64571
|
+
const arrived = new Promise((resolve) => {
|
|
64572
|
+
deliver = resolve;
|
|
64573
|
+
});
|
|
64574
|
+
const server = import_node_http.default.createServer((request7, response) => {
|
|
64575
|
+
const url2 = new URL(request7.url ?? "/", `http://127.0.0.1:${String(port)}`);
|
|
64576
|
+
if (request7.method !== "GET" || url2.pathname !== SIWC_CALLBACK_PATH || url2.searchParams.getAll("state").length !== 1 || url2.searchParams.get("state") !== state) {
|
|
64577
|
+
response.writeHead(HTTP_STATUS.notFound).end("Not found");
|
|
64578
|
+
return;
|
|
64579
|
+
}
|
|
64580
|
+
response.writeHead(HTTP_STATUS.ok, { "Content-Type": "text/html; charset=utf-8" });
|
|
64581
|
+
response.end(CALLBACK_PAGE);
|
|
64582
|
+
deliver?.(url2);
|
|
64583
|
+
});
|
|
64584
|
+
await new Promise((resolve, reject) => {
|
|
64585
|
+
server.once("error", (error62) => {
|
|
64586
|
+
reject(error62.code === "EADDRINUSE" ? new Error(`port ${String(port)} is in use (another sign-in, such as \`codex login\`, may be running): finish or stop it and try again`) : error62);
|
|
64587
|
+
});
|
|
64588
|
+
server.listen(port, "127.0.0.1", () => {
|
|
64589
|
+
resolve();
|
|
64590
|
+
});
|
|
64591
|
+
});
|
|
64592
|
+
return {
|
|
64593
|
+
waitForCallback: async (signal) => await Promise.race([
|
|
64594
|
+
arrived,
|
|
64595
|
+
new Promise((_resolve, reject) => {
|
|
64596
|
+
signal.addEventListener("abort", () => {
|
|
64597
|
+
reject(new Error("timed out waiting for the browser sign-in to finish"));
|
|
64598
|
+
});
|
|
64599
|
+
})
|
|
64600
|
+
]),
|
|
64601
|
+
close: () => {
|
|
64602
|
+
server.close();
|
|
64603
|
+
server.closeAllConnections();
|
|
64604
|
+
}
|
|
64605
|
+
};
|
|
64606
|
+
}
|
|
64607
|
+
function openInBrowser(url2) {
|
|
64608
|
+
const command = process.platform === "darwin" ? { file: "open", args: [url2] } : process.platform === "win32" ? { file: "cmd", args: ["/c", "start", "", url2] } : { file: "xdg-open", args: [url2] };
|
|
64609
|
+
(0, import_node_child_process4.spawn)(command.file, command.args, { detached: true, stdio: "ignore" }).unref();
|
|
64610
|
+
}
|
|
64611
|
+
|
|
64612
|
+
// src/codex/siwcStore.ts
|
|
64613
|
+
var SiwcGrantSchema = external_exports.strictObject({
|
|
64614
|
+
clientId: external_exports.string().min(1),
|
|
64615
|
+
sub: external_exports.string().min(1),
|
|
64616
|
+
email: external_exports.string().optional(),
|
|
64617
|
+
idToken: external_exports.string().min(1),
|
|
64618
|
+
accessToken: external_exports.string().min(1),
|
|
64619
|
+
refreshToken: external_exports.string().min(1),
|
|
64620
|
+
scopes: external_exports.array(external_exports.string()).readonly(),
|
|
64621
|
+
/** When the access token stops working, in milliseconds since the epoch. */
|
|
64622
|
+
expiresAt: external_exports.number()
|
|
64623
|
+
});
|
|
64624
|
+
var SiwcFileSchema = external_exports.strictObject({ registeredClientId: external_exports.string().min(1).optional(), grant: SiwcGrantSchema.optional() });
|
|
64625
|
+
var SIWC_REFRESH_MARGIN_MS = 6e4;
|
|
64626
|
+
function parseSiwcFile(raw, filePath) {
|
|
64627
|
+
let json2;
|
|
64628
|
+
try {
|
|
64629
|
+
json2 = JSON.parse(raw);
|
|
64630
|
+
} catch {
|
|
64631
|
+
throw new CodexAuthError(`${filePath} is not valid JSON: run \`agent-shim codex login\` again`);
|
|
64632
|
+
}
|
|
64633
|
+
const parsed = SiwcFileSchema.safeParse(json2);
|
|
64634
|
+
if (!parsed.success) {
|
|
64635
|
+
throw new CodexAuthError(`${filePath} is not a Sign in with ChatGPT file: run \`agent-shim codex login\` again`);
|
|
64636
|
+
}
|
|
64637
|
+
return parsed.data;
|
|
64638
|
+
}
|
|
64639
|
+
function grantFrom(previous, tokens) {
|
|
64640
|
+
return {
|
|
64641
|
+
...previous,
|
|
64642
|
+
accessToken: tokens.accessToken,
|
|
64643
|
+
refreshToken: tokens.refreshToken ?? previous.refreshToken,
|
|
64644
|
+
idToken: tokens.idToken ?? previous.idToken,
|
|
64645
|
+
scopes: tokens.scopes ?? previous.scopes,
|
|
64646
|
+
expiresAt: tokens.expiresAt
|
|
64647
|
+
};
|
|
64648
|
+
}
|
|
64649
|
+
function createSiwcStore(filePath, ports) {
|
|
64650
|
+
let cached2;
|
|
64651
|
+
let inFlight;
|
|
64652
|
+
const read = () => {
|
|
64653
|
+
const raw = ports.fs.read(filePath);
|
|
64654
|
+
return raw === void 0 ? void 0 : parseSiwcFile(raw, filePath);
|
|
64655
|
+
};
|
|
64656
|
+
const write = (file2) => {
|
|
64657
|
+
const temp = `${filePath}.${ports.tempSuffix}.tmp`;
|
|
64658
|
+
ports.fs.writePrivate(temp, `${JSON.stringify(file2, null, 2)}
|
|
64659
|
+
`);
|
|
64660
|
+
ports.fs.rename(temp, filePath);
|
|
64661
|
+
cached2 = file2.grant;
|
|
64662
|
+
};
|
|
64663
|
+
const loadSignedIn = () => {
|
|
64664
|
+
const file2 = read();
|
|
64665
|
+
if (file2?.grant === void 0) {
|
|
64666
|
+
throw new CodexAuthError(`no Sign in with ChatGPT login at ${filePath}: run \`agent-shim codex login\` first`);
|
|
64667
|
+
}
|
|
64668
|
+
if (!file2.grant.scopes.includes(SIWC_PLAN_SCOPE)) {
|
|
64669
|
+
throw new CodexAuthError(`the Sign in with ChatGPT login at ${filePath} was not granted permission to use your ChatGPT plan: run \`agent-shim codex login\` again and allow it`);
|
|
64670
|
+
}
|
|
64671
|
+
return { file: file2, grant: file2.grant };
|
|
64672
|
+
};
|
|
64673
|
+
const credentialsOf2 = (grant) => ({ accessToken: grant.accessToken, accountId: void 0 });
|
|
64674
|
+
const doRefresh = async (rejected) => {
|
|
64675
|
+
const { file: file2, grant } = loadSignedIn();
|
|
64676
|
+
if (rejected !== void 0 && grant.accessToken !== rejected) {
|
|
64677
|
+
cached2 = grant;
|
|
64678
|
+
return credentialsOf2(grant);
|
|
64679
|
+
}
|
|
64680
|
+
let tokens;
|
|
64681
|
+
try {
|
|
64682
|
+
tokens = await refreshTokens(ports.siwc, { clientId: grant.clientId, refreshToken: grant.refreshToken });
|
|
64683
|
+
} catch (error62) {
|
|
64684
|
+
if (error62 instanceof SiwcError) {
|
|
64685
|
+
throw new CodexAuthError(`${error62.message}: run \`agent-shim codex login\` again if the login was revoked`);
|
|
64686
|
+
}
|
|
64687
|
+
throw error62;
|
|
64688
|
+
}
|
|
64689
|
+
const next = grantFrom(grant, tokens);
|
|
64690
|
+
write({ ...file2, grant: next });
|
|
64691
|
+
return credentialsOf2(next);
|
|
64692
|
+
};
|
|
64693
|
+
const refreshOnce = async (rejected) => await (inFlight ??= doRefresh(rejected).finally(() => {
|
|
64694
|
+
inFlight = void 0;
|
|
64695
|
+
}));
|
|
64696
|
+
return {
|
|
64697
|
+
read,
|
|
64698
|
+
write,
|
|
64699
|
+
auth: {
|
|
64700
|
+
current: async () => {
|
|
64701
|
+
const grant = cached2 ?? loadSignedIn().grant;
|
|
64702
|
+
cached2 = grant;
|
|
64703
|
+
if (grant.expiresAt - SIWC_REFRESH_MARGIN_MS <= ports.siwc.now().getTime()) {
|
|
64704
|
+
return await refreshOnce(void 0);
|
|
64705
|
+
}
|
|
64706
|
+
return credentialsOf2(grant);
|
|
64707
|
+
},
|
|
64708
|
+
refresh: async (rejected) => await refreshOnce(rejected)
|
|
64709
|
+
}
|
|
64710
|
+
};
|
|
64711
|
+
}
|
|
64712
|
+
|
|
64294
64713
|
// src/codex/upstream.ts
|
|
64714
|
+
var import_node_crypto8 = require("node:crypto");
|
|
64295
64715
|
var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
64296
64716
|
var CODEX_UPSTREAM_TIMEOUT_MS = 3e5;
|
|
64297
64717
|
var CODEX_HEADERS_TIMEOUT_MS = 15e3;
|
|
@@ -64327,12 +64747,17 @@ function sessionIdFor(userId, randomId) {
|
|
|
64327
64747
|
if (userId === void 0 || userId === "") {
|
|
64328
64748
|
return randomId();
|
|
64329
64749
|
}
|
|
64330
|
-
const hex3 = (0,
|
|
64750
|
+
const hex3 = (0, import_node_crypto8.createHash)("sha256").update(`agent-shim codex session
|
|
64331
64751
|
${userId}`).digest("hex");
|
|
64332
64752
|
let next = 0;
|
|
64333
64753
|
return UUID_TEMPLATE.replace(/x/g, () => hex3.charAt(next++));
|
|
64334
64754
|
}
|
|
64335
|
-
|
|
64755
|
+
var CODEX_BACKEND_TARGET = { url: CODEX_RESPONSES_URL, headers: codexBackendHeaders };
|
|
64756
|
+
var RESPONSES_API_TARGET = {
|
|
64757
|
+
url: SIWC_RESPONSES_URL,
|
|
64758
|
+
headers: (credentials) => ({ "Content-Type": "application/json", Accept: "text/event-stream", Authorization: `Bearer ${credentials.accessToken}` })
|
|
64759
|
+
};
|
|
64760
|
+
function codexBackendHeaders(credentials, sessionId) {
|
|
64336
64761
|
return {
|
|
64337
64762
|
"Content-Type": "application/json",
|
|
64338
64763
|
Accept: "text/event-stream",
|
|
@@ -64344,11 +64769,11 @@ function headersFor(credentials, sessionId) {
|
|
|
64344
64769
|
};
|
|
64345
64770
|
}
|
|
64346
64771
|
async function callCodex(ports, request7, sessionId, signal) {
|
|
64347
|
-
const
|
|
64772
|
+
const target = ports.target ?? CODEX_BACKEND_TARGET;
|
|
64348
64773
|
const body = JSON.stringify(request7);
|
|
64349
|
-
const send = async (credentials2) => await fetchUntilHeaders(ports.fetch, ports.timers,
|
|
64774
|
+
const send = async (credentials2) => await fetchUntilHeaders(ports.fetch, ports.timers, target.url, {
|
|
64350
64775
|
method: "POST",
|
|
64351
|
-
headers:
|
|
64776
|
+
headers: target.headers(credentials2, sessionId),
|
|
64352
64777
|
body,
|
|
64353
64778
|
signal: AbortSignal.any([signal, AbortSignal.timeout(CODEX_UPSTREAM_TIMEOUT_MS)])
|
|
64354
64779
|
});
|
|
@@ -64384,6 +64809,7 @@ var realCodexAuthFs = {
|
|
|
64384
64809
|
}
|
|
64385
64810
|
},
|
|
64386
64811
|
writePrivate: (filePath, contents) => {
|
|
64812
|
+
import_node_fs11.default.mkdirSync(import_node_path31.default.dirname(filePath), { recursive: true });
|
|
64387
64813
|
import_node_fs11.default.writeFileSync(filePath, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
|
|
64388
64814
|
import_node_fs11.default.chmodSync(filePath, PRIVATE_FILE_MODE);
|
|
64389
64815
|
},
|
|
@@ -64403,17 +64829,22 @@ function writeUsageSnapshot(log, snapshot) {
|
|
|
64403
64829
|
log(`usage snapshot write failed: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
64404
64830
|
}
|
|
64405
64831
|
}
|
|
64406
|
-
function createCodexRoutePorts(log) {
|
|
64832
|
+
function createCodexRoutePorts(log, signInFile) {
|
|
64407
64833
|
const agent = createUpstreamAgent();
|
|
64408
64834
|
const upstreamFetch = createUpstreamFetch(agent);
|
|
64835
|
+
const tempSuffix = `${String(process.pid)}.${(0, import_node_crypto9.randomUUID)()}`;
|
|
64409
64836
|
const auth = createCodexAuthStore(import_node_path31.default.join(codexHome(process.env, import_node_os6.default.homedir()), "auth.json"), {
|
|
64410
64837
|
fs: realCodexAuthFs,
|
|
64411
64838
|
fetch: upstreamFetch,
|
|
64412
64839
|
now: () => /* @__PURE__ */ new Date(),
|
|
64413
|
-
tempSuffix
|
|
64840
|
+
tempSuffix
|
|
64414
64841
|
});
|
|
64842
|
+
const signIn = createSiwcStore(signInFile, { fs: realCodexAuthFs, siwc: realSiwcPorts(upstreamFetch), tempSuffix });
|
|
64415
64843
|
return {
|
|
64416
|
-
|
|
64844
|
+
upstreams: {
|
|
64845
|
+
"codex-cli": { fetch: upstreamFetch, auth, timers: realTimers, randomId: import_node_crypto9.randomUUID },
|
|
64846
|
+
"chatgpt-sign-in": { fetch: upstreamFetch, auth: signIn.auth, timers: realTimers, randomId: import_node_crypto9.randomUUID, target: RESPONSES_API_TARGET }
|
|
64847
|
+
},
|
|
64417
64848
|
writeUsageSnapshot: (snapshot) => {
|
|
64418
64849
|
writeUsageSnapshot(log, snapshot);
|
|
64419
64850
|
},
|
|
@@ -64421,6 +64852,18 @@ function createCodexRoutePorts(log) {
|
|
|
64421
64852
|
log
|
|
64422
64853
|
};
|
|
64423
64854
|
}
|
|
64855
|
+
function readSignInStatus(fsPort, filePath) {
|
|
64856
|
+
const raw = fsPort.readFileUtf8(filePath);
|
|
64857
|
+
if (raw === void 0) {
|
|
64858
|
+
return { state: "none" };
|
|
64859
|
+
}
|
|
64860
|
+
try {
|
|
64861
|
+
const file2 = parseSiwcFile(raw, filePath);
|
|
64862
|
+
return file2.grant === void 0 ? { state: "none" } : { state: "signed-in", email: file2.grant.email, planScope: file2.grant.scopes.includes(SIWC_PLAN_SCOPE), accessTokenExpiresAt: file2.grant.expiresAt };
|
|
64863
|
+
} catch (error62) {
|
|
64864
|
+
return { state: "unreadable", message: error62 instanceof Error ? error62.message : String(error62) };
|
|
64865
|
+
}
|
|
64866
|
+
}
|
|
64424
64867
|
function codexProviderNames(fsPort, providersDir) {
|
|
64425
64868
|
return readAllProviders(fsPort, providersDir).filter((entry) => isCodexProvider(entry.provider)).map((entry) => entry.name).sort();
|
|
64426
64869
|
}
|
|
@@ -64431,12 +64874,22 @@ function collectCodexStatus(fsPort, paths, isRunning) {
|
|
|
64431
64874
|
supervisorAlive: state.supervisorPid !== void 0 && isRunning(state.supervisorPid),
|
|
64432
64875
|
sessions: listFrontDoorSessions(fsPort, paths.frontdoorSessionsDir).map((session) => ({ ...session, alive: isRunning(session.pid) })),
|
|
64433
64876
|
codexProviders: codexProviderNames(fsPort, paths.providersDir),
|
|
64877
|
+
signIn: readSignInStatus(fsPort, paths.chatgptSignInFile),
|
|
64434
64878
|
usageSnapshotPath: codexUsageSnapshotPath(),
|
|
64435
64879
|
usageSnapshotExists: fsPort.readFileUtf8(codexUsageSnapshotPath()) !== void 0,
|
|
64436
64880
|
logPath: paths.frontdoorLogPath,
|
|
64437
64881
|
logExists: fsPort.readFileUtf8(paths.frontdoorLogPath) !== void 0
|
|
64438
64882
|
};
|
|
64439
64883
|
}
|
|
64884
|
+
function formatSignIn(signIn) {
|
|
64885
|
+
if (signIn.state === "none") {
|
|
64886
|
+
return "chatgpt sign-in: not signed in (run `agent-shim codex login`)";
|
|
64887
|
+
}
|
|
64888
|
+
if (signIn.state === "unreadable") {
|
|
64889
|
+
return `chatgpt sign-in: ${signIn.message}`;
|
|
64890
|
+
}
|
|
64891
|
+
return `chatgpt sign-in: signed in${signIn.email === void 0 ? "" : ` as ${signIn.email}`}${signIn.planScope ? "" : ", WITHOUT permission to use your ChatGPT plan (run `agent-shim codex login` again and allow it)"}`;
|
|
64892
|
+
}
|
|
64440
64893
|
function formatCodexStatus(status) {
|
|
64441
64894
|
const lines = [];
|
|
64442
64895
|
lines.push(
|
|
@@ -64457,10 +64910,24 @@ function formatCodexStatus(status) {
|
|
|
64457
64910
|
if (status.frontDoor.lastError !== void 0) {
|
|
64458
64911
|
lines.push(`last error: ${status.frontDoor.lastError}`);
|
|
64459
64912
|
}
|
|
64913
|
+
lines.push(formatSignIn(status.signIn));
|
|
64460
64914
|
lines.push(`usage snapshot: ${status.usageSnapshotPath}${status.usageSnapshotExists ? "" : " (not created yet)"}`);
|
|
64461
64915
|
lines.push(`daemon log: ${status.logPath}${status.logExists ? "" : " (not created yet)"}`);
|
|
64462
64916
|
return lines;
|
|
64463
64917
|
}
|
|
64918
|
+
function realSiwcLoginPorts(paths) {
|
|
64919
|
+
const siwc = realSiwcPorts(createUpstreamFetch(createUpstreamAgent()));
|
|
64920
|
+
const store = createSiwcStore(paths.chatgptSignInFile, { fs: realCodexAuthFs, siwc, tempSuffix: `${String(process.pid)}.${(0, import_node_crypto9.randomUUID)()}` });
|
|
64921
|
+
return {
|
|
64922
|
+
store,
|
|
64923
|
+
siwc,
|
|
64924
|
+
listen: listenForCallback,
|
|
64925
|
+
openBrowser: openInBrowser,
|
|
64926
|
+
print: (line) => {
|
|
64927
|
+
console.log(line);
|
|
64928
|
+
}
|
|
64929
|
+
};
|
|
64930
|
+
}
|
|
64464
64931
|
function registerCodexCommand(program2, deps) {
|
|
64465
64932
|
const { paths } = deps;
|
|
64466
64933
|
const codex = withExamples(program2.command("codex").description("Inspect the codex translation the front-door daemon serves for codex providers."), ["agent-shim codex status"]);
|
|
@@ -64477,10 +64944,38 @@ function registerCodexCommand(program2, deps) {
|
|
|
64477
64944
|
}),
|
|
64478
64945
|
["agent-shim codex status", "agent-shim codex status --json"]
|
|
64479
64946
|
);
|
|
64947
|
+
withExamples(
|
|
64948
|
+
codex.command("login").description("Sign in with ChatGPT so a codex provider with `codex.login` set to `chatgpt-sign-in` can spend your ChatGPT plan on OpenAI's public Responses API. Opens your browser.").option("--no-open", "Print the sign-in address instead of opening the browser.").option("--json", "Print the result as JSON.").action(async (options) => {
|
|
64949
|
+
const ports = realSiwcLoginPorts(paths);
|
|
64950
|
+
const result = await runSiwcLogin(options.json === true ? { ...ports, print: () => void 0 } : ports, { open: options.open });
|
|
64951
|
+
if (options.json === true) {
|
|
64952
|
+
printJson({ action: "login", email: result.email ?? null, sub: result.sub });
|
|
64953
|
+
return;
|
|
64954
|
+
}
|
|
64955
|
+
console.log(`Signed in${result.email === void 0 ? "" : ` as ${result.email}`}. Set "codex": { "login": "chatgpt-sign-in" } on a codex provider to use it.`);
|
|
64956
|
+
}),
|
|
64957
|
+
["agent-shim codex login", "agent-shim codex login --no-open"]
|
|
64958
|
+
);
|
|
64959
|
+
withExamples(
|
|
64960
|
+
codex.command("logout").description("Revoke the Sign in with ChatGPT login and remove it from this machine.").option("--json", "Print the result as JSON.").action(async (options) => {
|
|
64961
|
+
const ports = realSiwcLoginPorts(paths);
|
|
64962
|
+
const result = await runSiwcLogout(ports);
|
|
64963
|
+
if (options.json === true) {
|
|
64964
|
+
printJson({ action: "logout", ...result });
|
|
64965
|
+
return;
|
|
64966
|
+
}
|
|
64967
|
+
if (!result.hadGrant) {
|
|
64968
|
+
console.log("Not signed in.");
|
|
64969
|
+
return;
|
|
64970
|
+
}
|
|
64971
|
+
console.log(result.revoked ? "Signed out and revoked the login at OpenAI." : "Signed out here, but OpenAI could not be told to revoke the login: revoke it in ChatGPT settings.");
|
|
64972
|
+
}),
|
|
64973
|
+
["agent-shim codex logout"]
|
|
64974
|
+
);
|
|
64480
64975
|
}
|
|
64481
64976
|
|
|
64482
64977
|
// src/frontdoor/commands.ts
|
|
64483
|
-
var
|
|
64978
|
+
var import_node_crypto14 = require("node:crypto");
|
|
64484
64979
|
var import_node_path36 = __toESM(require("node:path"), 1);
|
|
64485
64980
|
var import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
64486
64981
|
|
|
@@ -64585,7 +65080,7 @@ function createDoorPipelines(deps) {
|
|
|
64585
65080
|
}
|
|
64586
65081
|
|
|
64587
65082
|
// src/frontdoor/capability.ts
|
|
64588
|
-
var
|
|
65083
|
+
var import_node_crypto10 = require("node:crypto");
|
|
64589
65084
|
var CONNECT_PROXY_USER = "agent-shim";
|
|
64590
65085
|
var CONNECT_PROXY_REALM = "agent-shim front door";
|
|
64591
65086
|
var BASIC_SCHEME = "basic";
|
|
@@ -64607,13 +65102,13 @@ function capabilityFromProxyAuthorization(value2) {
|
|
|
64607
65102
|
return password === "" ? void 0 : password;
|
|
64608
65103
|
}
|
|
64609
65104
|
function digest(token) {
|
|
64610
|
-
return (0,
|
|
65105
|
+
return (0, import_node_crypto10.createHash)("sha256").update(token, "utf8").digest();
|
|
64611
65106
|
}
|
|
64612
65107
|
function isLiveCapability(presented, live) {
|
|
64613
65108
|
const presentedDigest = digest(presented);
|
|
64614
65109
|
let matched = false;
|
|
64615
65110
|
for (const token of live) {
|
|
64616
|
-
const equal = (0,
|
|
65111
|
+
const equal = (0, import_node_crypto10.timingSafeEqual)(presentedDigest, digest(token));
|
|
64617
65112
|
matched = equal || matched;
|
|
64618
65113
|
}
|
|
64619
65114
|
return matched;
|
|
@@ -64757,11 +65252,11 @@ function createFileCapture(file2, now = () => /* @__PURE__ */ new Date()) {
|
|
|
64757
65252
|
}
|
|
64758
65253
|
|
|
64759
65254
|
// src/frontdoor/connect.ts
|
|
64760
|
-
var
|
|
65255
|
+
var import_node_crypto12 = require("node:crypto");
|
|
64761
65256
|
var fs13 = __toESM(require("node:fs"), 1);
|
|
64762
65257
|
|
|
64763
65258
|
// src/frontdoor/x509.ts
|
|
64764
|
-
var
|
|
65259
|
+
var import_node_crypto11 = require("node:crypto");
|
|
64765
65260
|
var import_node_net = __toESM(require("node:net"), 1);
|
|
64766
65261
|
var TAG_BOOLEAN = 1;
|
|
64767
65262
|
var TAG_INTEGER = 2;
|
|
@@ -64797,7 +65292,7 @@ var HIGH_BIT = 128;
|
|
|
64797
65292
|
var BASE_128_PAYLOAD_MASK = 127;
|
|
64798
65293
|
var FIRST_ARC_WEIGHT = 40;
|
|
64799
65294
|
var SHORT_FORM_MAX_LENGTH = 127;
|
|
64800
|
-
var
|
|
65295
|
+
var MS_PER_SECOND5 = 1e3;
|
|
64801
65296
|
var UTC_TIME_LAST_YEAR = 2049;
|
|
64802
65297
|
var YEAR_DIGITS = 4;
|
|
64803
65298
|
var TWO_DIGIT_YEAR_DIGITS = 2;
|
|
@@ -64856,7 +65351,7 @@ function wholeBitString(content) {
|
|
|
64856
65351
|
return tlv(TAG_BIT_STRING, Buffer.concat([Buffer.from([0]), content]));
|
|
64857
65352
|
}
|
|
64858
65353
|
function time3(instant) {
|
|
64859
|
-
const iso = new Date(Math.floor(instant.getTime() /
|
|
65354
|
+
const iso = new Date(Math.floor(instant.getTime() / MS_PER_SECOND5) * MS_PER_SECOND5).toISOString();
|
|
64860
65355
|
const compact = `${iso.replace(/[-:T]/g, "").slice(0, COMPACT_TIME_DIGITS)}Z`;
|
|
64861
65356
|
if (instant.getUTCFullYear() > UTC_TIME_LAST_YEAR) {
|
|
64862
65357
|
return tlv(TAG_GENERALIZED_TIME, Buffer.from(compact, "ascii"));
|
|
@@ -64913,7 +65408,7 @@ function ipBytes(address) {
|
|
|
64913
65408
|
return bytes;
|
|
64914
65409
|
}
|
|
64915
65410
|
function keyIdentifier(publicKey) {
|
|
64916
|
-
return (0,
|
|
65411
|
+
return (0, import_node_crypto11.createHash)("sha1").update(publicKey.export({ type: "pkcs1", format: "der" })).digest();
|
|
64917
65412
|
}
|
|
64918
65413
|
function readElement(buffer, offset) {
|
|
64919
65414
|
const tag = buffer[offset];
|
|
@@ -64959,7 +65454,7 @@ ${body.join("\n")}
|
|
|
64959
65454
|
`;
|
|
64960
65455
|
}
|
|
64961
65456
|
function randomSerial() {
|
|
64962
|
-
const bytes = (0,
|
|
65457
|
+
const bytes = (0, import_node_crypto11.randomBytes)(SERIAL_NUMBER_BYTES);
|
|
64963
65458
|
bytes[0] = (bytes[0] ?? 0) & BASE_128_PAYLOAD_MASK | HIGH_BIT >> 1;
|
|
64964
65459
|
return bytes;
|
|
64965
65460
|
}
|
|
@@ -64974,7 +65469,7 @@ function assemble(spec) {
|
|
|
64974
65469
|
spec.subjectPublicKey.export({ type: "spki", format: "der" }),
|
|
64975
65470
|
tlv(TAG_EXTENSIONS, sequence(...spec.extensions))
|
|
64976
65471
|
);
|
|
64977
|
-
const signature = (0,
|
|
65472
|
+
const signature = (0, import_node_crypto11.sign)("sha256", tbs, spec.signingKey);
|
|
64978
65473
|
return sequence(tbs, SIGNATURE_ALGORITHM, wholeBitString(signature));
|
|
64979
65474
|
}
|
|
64980
65475
|
function subjectKeyIdentifierExtension(publicKey) {
|
|
@@ -64984,7 +65479,7 @@ function basicConstraintsExtension(isCa) {
|
|
|
64984
65479
|
return extension(OID_BASIC_CONSTRAINTS, true, sequence(...isCa ? [boolean4(true)] : []));
|
|
64985
65480
|
}
|
|
64986
65481
|
function rsaKeyPair() {
|
|
64987
|
-
return (0,
|
|
65482
|
+
return (0, import_node_crypto11.generateKeyPairSync)("rsa", { modulusLength: RSA_MODULUS_BITS });
|
|
64988
65483
|
}
|
|
64989
65484
|
function keyPem(privateKey) {
|
|
64990
65485
|
return privateKey.export({ type: "pkcs8", format: "pem" });
|
|
@@ -65008,8 +65503,8 @@ function issueLeafCertificate(ca, names, notBefore, notAfter) {
|
|
|
65008
65503
|
if (commonName === void 0) {
|
|
65009
65504
|
throw new Error("a leaf certificate needs at least one name");
|
|
65010
65505
|
}
|
|
65011
|
-
const caCertificate = new
|
|
65012
|
-
const caPrivateKey = (0,
|
|
65506
|
+
const caCertificate = new import_node_crypto11.X509Certificate(ca.certPem);
|
|
65507
|
+
const caPrivateKey = (0, import_node_crypto11.createPrivateKey)(ca.keyPem);
|
|
65013
65508
|
const { publicKey, privateKey } = rsaKeyPair();
|
|
65014
65509
|
const generalNames = names.map((name) => import_node_net.default.isIP(name) === 0 ? tlv(TAG_GENERAL_NAME_DNS, Buffer.from(name, "ascii")) : tlv(TAG_GENERAL_NAME_IP, ipBytes(name)));
|
|
65015
65510
|
const der = assemble({
|
|
@@ -65106,22 +65601,22 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
65106
65601
|
};
|
|
65107
65602
|
writeFrontDoorState(fs19, paths.frontdoorStateFile, { supervisorPid: ports.ownPid, ...sticky() });
|
|
65108
65603
|
const previousSticky = lastPort;
|
|
65109
|
-
let
|
|
65604
|
+
let http7;
|
|
65110
65605
|
try {
|
|
65111
|
-
|
|
65606
|
+
http7 = await ports.startProviderListener(lastPort);
|
|
65112
65607
|
} catch (error62) {
|
|
65113
65608
|
return fail(`could not start the provider listener: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
65114
65609
|
}
|
|
65115
|
-
if (previousSticky !== void 0 &&
|
|
65116
|
-
ports.log(`agent-shim frontdoor supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(
|
|
65610
|
+
if (previousSticky !== void 0 && http7.port !== previousSticky) {
|
|
65611
|
+
ports.log(`agent-shim frontdoor supervisor: sticky port ${String(previousSticky)} was occupied; moving to ${String(http7.port)} (sessions launched against the old port are stale until they relaunch)`);
|
|
65117
65612
|
}
|
|
65118
|
-
lastPort =
|
|
65613
|
+
lastPort = http7.port;
|
|
65119
65614
|
const previousStickyConnect = lastConnectPort;
|
|
65120
65615
|
let connect3;
|
|
65121
65616
|
try {
|
|
65122
65617
|
connect3 = await ports.startConnectListener(lastConnectPort);
|
|
65123
65618
|
} catch (error62) {
|
|
65124
|
-
await
|
|
65619
|
+
await http7.close();
|
|
65125
65620
|
return fail(`could not start the CONNECT surface: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
65126
65621
|
}
|
|
65127
65622
|
if (previousStickyConnect !== void 0 && connect3.port !== previousStickyConnect) {
|
|
@@ -65134,16 +65629,16 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
65134
65629
|
direct = await ports.startDirectListener(lastDirectPort);
|
|
65135
65630
|
} catch (error62) {
|
|
65136
65631
|
await connect3.close();
|
|
65137
|
-
await
|
|
65632
|
+
await http7.close();
|
|
65138
65633
|
return fail(`could not start the direct listener: ${error62 instanceof Error ? error62.message : String(error62)}`);
|
|
65139
65634
|
}
|
|
65140
65635
|
if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
|
|
65141
65636
|
ports.log(`agent-shim frontdoor supervisor: sticky direct port ${String(previousStickyDirect)} was occupied; moving to ${String(direct.port)} (headroom must be restarted to admit the new address)`);
|
|
65142
65637
|
}
|
|
65143
65638
|
lastDirectPort = direct.port;
|
|
65144
|
-
writeFrontDoorState(fs19, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port:
|
|
65639
|
+
writeFrontDoorState(fs19, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http7.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
|
|
65145
65640
|
fs19.removeRecursive(paths.frontdoorLockFile);
|
|
65146
|
-
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(
|
|
65641
|
+
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http7.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
|
|
65147
65642
|
let idleSince;
|
|
65148
65643
|
let ticks = 0;
|
|
65149
65644
|
for (; ; ) {
|
|
@@ -65151,14 +65646,17 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
65151
65646
|
return FRONTDOOR_SUPERVISOR_STILL_RUNNING;
|
|
65152
65647
|
}
|
|
65153
65648
|
ticks += 1;
|
|
65154
|
-
|
|
65155
|
-
|
|
65649
|
+
const listed = listFrontDoorSessions(fs19, paths.frontdoorSessionsDir);
|
|
65650
|
+
const pruned = pruneDeadFrontDoorSessions(fs19, paths.frontdoorSessionsDir, ports.isRunning);
|
|
65651
|
+
ports.observeLaunchRegistry(listed, pruned);
|
|
65652
|
+
const prunedPids = new Set(pruned);
|
|
65653
|
+
if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
|
|
65156
65654
|
idleSince ??= ports.now();
|
|
65157
65655
|
if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE2) {
|
|
65158
65656
|
ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
|
|
65159
65657
|
await direct.close();
|
|
65160
65658
|
await connect3.close();
|
|
65161
|
-
await
|
|
65659
|
+
await http7.close();
|
|
65162
65660
|
ports.closeRcStreamHub();
|
|
65163
65661
|
writeFrontDoorState(fs19, paths.frontdoorStateFile, sticky());
|
|
65164
65662
|
return 0;
|
|
@@ -65274,8 +65772,8 @@ function ensureCa(store, generate) {
|
|
|
65274
65772
|
}
|
|
65275
65773
|
function caParses(ca) {
|
|
65276
65774
|
try {
|
|
65277
|
-
new
|
|
65278
|
-
(0,
|
|
65775
|
+
new import_node_crypto12.X509Certificate(ca.certPem);
|
|
65776
|
+
(0, import_node_crypto12.createPrivateKey)(ca.keyPem);
|
|
65279
65777
|
return true;
|
|
65280
65778
|
} catch {
|
|
65281
65779
|
return false;
|
|
@@ -65563,13 +66061,13 @@ function realConnectCertStore(paths) {
|
|
|
65563
66061
|
|
|
65564
66062
|
// src/frontdoor/connectEffects.ts
|
|
65565
66063
|
var import_node_dns = __toESM(require("node:dns"), 1);
|
|
65566
|
-
var
|
|
66064
|
+
var http3 = __toESM(require("node:http"), 1);
|
|
65567
66065
|
var https3 = __toESM(require("node:https"), 1);
|
|
65568
66066
|
var net2 = __toESM(require("node:net"), 1);
|
|
65569
66067
|
var tls = __toESM(require("node:tls"), 1);
|
|
65570
66068
|
|
|
65571
66069
|
// src/frontdoor/server.ts
|
|
65572
|
-
var
|
|
66070
|
+
var import_node_http2 = __toESM(require("node:http"), 1);
|
|
65573
66071
|
var import_node_https = __toESM(require("node:https"), 1);
|
|
65574
66072
|
|
|
65575
66073
|
// src/frontdoor/rcControl.ts
|
|
@@ -66595,7 +67093,7 @@ function frontDoorRcControl(transport, token) {
|
|
|
66595
67093
|
var HEALTH_TIMEOUT_MS = 2e3;
|
|
66596
67094
|
var HEALTH_START_BUDGET_MS = 5e3;
|
|
66597
67095
|
var HEALTH_RETRY_MS = 50;
|
|
66598
|
-
function createFrontDoorServer(pipeline, log, tls2, control,
|
|
67096
|
+
function createFrontDoorServer(pipeline, log, tls2, control, apis) {
|
|
66599
67097
|
const handler = (request7, response) => {
|
|
66600
67098
|
if (request7.method === "GET" && request7.url === "/healthz") {
|
|
66601
67099
|
response.writeHead(HTTP_STATUS.ok, { "Content-Type": "text/plain" });
|
|
@@ -66606,7 +67104,8 @@ function createFrontDoorServer(pipeline, log, tls2, control, api) {
|
|
|
66606
67104
|
control(request7, response);
|
|
66607
67105
|
return;
|
|
66608
67106
|
}
|
|
66609
|
-
|
|
67107
|
+
const api = apis?.find((candidate) => (request7.url ?? "/").startsWith(candidate.pathPrefix));
|
|
67108
|
+
if (api !== void 0) {
|
|
66610
67109
|
api.handle(request7, response).then((result) => {
|
|
66611
67110
|
if (!result.matched && !response.headersSent) {
|
|
66612
67111
|
response.writeHead(HTTP_STATUS.notFound, { "Content-Type": "application/json" });
|
|
@@ -66646,7 +67145,7 @@ function createFrontDoorServer(pipeline, log, tls2, control, api) {
|
|
|
66646
67145
|
});
|
|
66647
67146
|
};
|
|
66648
67147
|
if (tls2 === void 0) {
|
|
66649
|
-
return
|
|
67148
|
+
return import_node_http2.default.createServer(handler);
|
|
66650
67149
|
}
|
|
66651
67150
|
const server = import_node_https.default.createServer({ key: tls2.keyPem, cert: tls2.certPem }, handler);
|
|
66652
67151
|
server.on("tlsClientError", (_error, socket) => {
|
|
@@ -66661,7 +67160,7 @@ async function frontDoorHealthy(port, ca) {
|
|
|
66661
67160
|
resolve(response.statusCode === HTTP_STATUS.ok);
|
|
66662
67161
|
};
|
|
66663
67162
|
const options = { host: "127.0.0.1", port, path: "/healthz", agent: false, timeout: HEALTH_TIMEOUT_MS };
|
|
66664
|
-
const request7 = ca === void 0 ?
|
|
67163
|
+
const request7 = ca === void 0 ? import_node_http2.default.get(options, onResponse) : import_node_https.default.get({ ...options, ca: [ca] }, onResponse);
|
|
66665
67164
|
request7.on("timeout", () => {
|
|
66666
67165
|
request7.destroy();
|
|
66667
67166
|
});
|
|
@@ -66816,7 +67315,7 @@ async function reservedDial(target, ports) {
|
|
|
66816
67315
|
function requestServername(options, fallback) {
|
|
66817
67316
|
return "servername" in options && typeof options.servername === "string" && options.servername !== "" ? options.servername : fallback;
|
|
66818
67317
|
}
|
|
66819
|
-
var ExemptHttpAgent = class extends
|
|
67318
|
+
var ExemptHttpAgent = class extends http3.Agent {
|
|
66820
67319
|
constructor(ports = DOOR_SOURCE_PORTS) {
|
|
66821
67320
|
super();
|
|
66822
67321
|
this.ports = ports;
|
|
@@ -67087,7 +67586,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
|
67087
67586
|
};
|
|
67088
67587
|
},
|
|
67089
67588
|
createHttpSession: (handler, onUpgrade) => {
|
|
67090
|
-
const server =
|
|
67589
|
+
const server = http3.createServer(handler);
|
|
67091
67590
|
server.on("clientError", (_error, socket) => {
|
|
67092
67591
|
socket.destroy();
|
|
67093
67592
|
});
|
|
@@ -67157,7 +67656,7 @@ function realConnectEffects(ports = DOOR_SOURCE_PORTS) {
|
|
|
67157
67656
|
}
|
|
67158
67657
|
upstreamResponse.pipe(response);
|
|
67159
67658
|
};
|
|
67160
|
-
const upstream = target.tls ? https3.request(options, onUpstreamResponse) :
|
|
67659
|
+
const upstream = target.tls ? https3.request(options, onUpstreamResponse) : http3.request(options, onUpstreamResponse);
|
|
67161
67660
|
upstream.on("error", (error62) => {
|
|
67162
67661
|
if (response.headersSent) {
|
|
67163
67662
|
response.destroy(error62);
|
|
@@ -67282,7 +67781,21 @@ function cacheClause(cacheEnv, owner, block2) {
|
|
|
67282
67781
|
const state = describeCachedCredential({ port: cacheEnv.port, platform: cacheEnv.platform, owner, cache: block2.cache, nowMs: cacheEnv.now() });
|
|
67283
67782
|
return { text: `; ${formatCachedCredentialState(state)}`, unreadable: state.status === "unreadable" };
|
|
67284
67783
|
}
|
|
67285
|
-
function
|
|
67784
|
+
function signInProblem(signIn) {
|
|
67785
|
+
if (signIn.raw === void 0) {
|
|
67786
|
+
return "nobody is signed in: run `agent-shim codex login`.";
|
|
67787
|
+
}
|
|
67788
|
+
try {
|
|
67789
|
+
const grant = parseSiwcFile(signIn.raw, signIn.path).grant;
|
|
67790
|
+
if (grant === void 0) {
|
|
67791
|
+
return "nobody is signed in: run `agent-shim codex login`.";
|
|
67792
|
+
}
|
|
67793
|
+
return grant.scopes.includes(SIWC_PLAN_SCOPE) ? void 0 : "the login was not given permission to use your ChatGPT plan: run `agent-shim codex login` again and allow it.";
|
|
67794
|
+
} catch (error62) {
|
|
67795
|
+
return error62 instanceof Error ? error62.message : String(error62);
|
|
67796
|
+
}
|
|
67797
|
+
}
|
|
67798
|
+
function pushProvider(push, entry, cacheEnv, signIn) {
|
|
67286
67799
|
if (entry.raw === void 0) {
|
|
67287
67800
|
push("provider", "fail", `${entry.path} is missing.`, entry.name);
|
|
67288
67801
|
return;
|
|
@@ -67309,6 +67822,12 @@ function pushProvider(push, entry, cacheEnv) {
|
|
|
67309
67822
|
if (validated2.data.env?.ENABLE_TOOL_SEARCH === void 0) {
|
|
67310
67823
|
push("provider", "warn", `${entry.name} does not set ENABLE_TOOL_SEARCH: a session on this provider loads MCP tools upfront rather than deferring them, because its base URL is the front door, which Claude Code treats as a non-first-party host. Set ENABLE_TOOL_SEARCH in the provider's env block to restore deferred loading, when the upstream backend supports the tool_reference payloads it sends.`, entry.name);
|
|
67311
67824
|
}
|
|
67825
|
+
if (signIn !== void 0 && isCodexProvider(validated2.data) && validated2.data.codex?.login === "chatgpt-sign-in") {
|
|
67826
|
+
const problem = signInProblem(signIn);
|
|
67827
|
+
if (problem !== void 0) {
|
|
67828
|
+
push("provider", "warn", `${entry.name} uses the Sign in with ChatGPT login, but ${problem}`, entry.name);
|
|
67829
|
+
}
|
|
67830
|
+
}
|
|
67312
67831
|
}
|
|
67313
67832
|
function pushLegacyName(push, params) {
|
|
67314
67833
|
const legacyVariables = Object.keys(params.env).filter((name) => name.startsWith(LEGACY_ENV_PREFIX) && params.env[name] !== void 0).sort();
|
|
@@ -67433,7 +67952,7 @@ function runDoctor(params) {
|
|
|
67433
67952
|
return poolName === void 0 ? validIdentityNames.has(selector) : poolName in pools;
|
|
67434
67953
|
};
|
|
67435
67954
|
for (const entry of params.providers) {
|
|
67436
|
-
pushProvider(push, entry, params.credentialCache);
|
|
67955
|
+
pushProvider(push, entry, params.credentialCache, params.chatgptSignIn);
|
|
67437
67956
|
}
|
|
67438
67957
|
if (params.platform !== "darwin" || params.run === void 0) {
|
|
67439
67958
|
push("keychain", "pass", "Skipped (not macOS).");
|
|
@@ -67675,6 +68194,7 @@ function collectDoctorReport(params) {
|
|
|
67675
68194
|
const report = runDoctor({
|
|
67676
68195
|
env: params.env,
|
|
67677
68196
|
credentialCache: realCredentialCacheEnv(paths),
|
|
68197
|
+
chatgptSignIn: { path: paths.chatgptSignInFile, raw: realFsPort.readFileUtf8(paths.chatgptSignInFile) },
|
|
67678
68198
|
installedClaudeVersions: realInstalledClaudeVersions(),
|
|
67679
68199
|
identities,
|
|
67680
68200
|
configProfiles,
|
|
@@ -68870,6 +69390,56 @@ var DoctorRunOutputSchema = external_exports.strictObject({
|
|
|
68870
69390
|
findings: external_exports.readonly(external_exports.array(DoctorFindingSchema))
|
|
68871
69391
|
});
|
|
68872
69392
|
|
|
69393
|
+
// node_modules/.pnpm/@orpc+contract@1.15.4/node_modules/@orpc/contract/dist/shared/contract.D_dZrO__.mjs
|
|
69394
|
+
var ValidationError = class extends Error {
|
|
69395
|
+
issues;
|
|
69396
|
+
data;
|
|
69397
|
+
constructor(options) {
|
|
69398
|
+
super(options.message, options);
|
|
69399
|
+
this.issues = options.issues;
|
|
69400
|
+
this.data = options.data;
|
|
69401
|
+
}
|
|
69402
|
+
};
|
|
69403
|
+
function mergeErrorMap(errorMap1, errorMap2) {
|
|
69404
|
+
return { ...errorMap1, ...errorMap2 };
|
|
69405
|
+
}
|
|
69406
|
+
async function validateORPCError(map3, error62) {
|
|
69407
|
+
const { code, status, message, data, cause, defined } = error62;
|
|
69408
|
+
const config2 = map3?.[error62.code];
|
|
69409
|
+
if (!config2 || fallbackORPCErrorStatus(error62.code, config2.status) !== error62.status) {
|
|
69410
|
+
return defined ? new ORPCError(code, { defined: false, status, message, data, cause }) : error62;
|
|
69411
|
+
}
|
|
69412
|
+
if (!config2.data) {
|
|
69413
|
+
return defined ? error62 : new ORPCError(code, { defined: true, status, message, data, cause });
|
|
69414
|
+
}
|
|
69415
|
+
const validated2 = await config2.data["~standard"].validate(error62.data);
|
|
69416
|
+
if (validated2.issues) {
|
|
69417
|
+
return defined ? new ORPCError(code, { defined: false, status, message, data, cause }) : error62;
|
|
69418
|
+
}
|
|
69419
|
+
return new ORPCError(code, { defined: true, status, message, data: validated2.value, cause });
|
|
69420
|
+
}
|
|
69421
|
+
var ContractProcedure = class {
|
|
69422
|
+
/**
|
|
69423
|
+
* This property holds the defined options for the contract procedure.
|
|
69424
|
+
*/
|
|
69425
|
+
"~orpc";
|
|
69426
|
+
constructor(def) {
|
|
69427
|
+
if (def.route?.successStatus && isORPCErrorStatus(def.route.successStatus)) {
|
|
69428
|
+
throw new Error("[ContractProcedure] Invalid successStatus.");
|
|
69429
|
+
}
|
|
69430
|
+
if (Object.values(def.errorMap).some((val) => val && val.status && !isORPCErrorStatus(val.status))) {
|
|
69431
|
+
throw new Error("[ContractProcedure] Invalid error status code.");
|
|
69432
|
+
}
|
|
69433
|
+
this["~orpc"] = def;
|
|
69434
|
+
}
|
|
69435
|
+
};
|
|
69436
|
+
function isContractProcedure(item) {
|
|
69437
|
+
if (item instanceof ContractProcedure) {
|
|
69438
|
+
return true;
|
|
69439
|
+
}
|
|
69440
|
+
return (typeof item === "object" || typeof item === "function") && item !== null && "~orpc" in item && typeof item["~orpc"] === "object" && item["~orpc"] !== null && "errorMap" in item["~orpc"] && "route" in item["~orpc"] && "meta" in item["~orpc"];
|
|
69441
|
+
}
|
|
69442
|
+
|
|
68873
69443
|
// node_modules/.pnpm/@orpc+standard-server-fetch@1.15.4/node_modules/@orpc/standard-server-fetch/dist/index.mjs
|
|
68874
69444
|
function toEventIterator(stream, options = {}) {
|
|
68875
69445
|
const eventStream = stream?.pipeThrough(new TextDecoderStream()).pipeThrough(new EventDecoderStream());
|
|
@@ -69581,93 +70151,6 @@ var StandardRPCLink = class extends StandardLink {
|
|
|
69581
70151
|
}
|
|
69582
70152
|
};
|
|
69583
70153
|
|
|
69584
|
-
// node_modules/.pnpm/@orpc+client@1.15.4/node_modules/@orpc/client/dist/adapters/fetch/index.mjs
|
|
69585
|
-
var CompositeLinkFetchPlugin = class extends CompositeStandardLinkPlugin {
|
|
69586
|
-
initRuntimeAdapter(options) {
|
|
69587
|
-
for (const plugin of this.plugins) {
|
|
69588
|
-
plugin.initRuntimeAdapter?.(options);
|
|
69589
|
-
}
|
|
69590
|
-
}
|
|
69591
|
-
};
|
|
69592
|
-
var LinkFetchClient = class {
|
|
69593
|
-
fetch;
|
|
69594
|
-
toFetchRequestOptions;
|
|
69595
|
-
adapterInterceptors;
|
|
69596
|
-
constructor(options) {
|
|
69597
|
-
const plugin = new CompositeLinkFetchPlugin(options.plugins);
|
|
69598
|
-
plugin.initRuntimeAdapter(options);
|
|
69599
|
-
this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
69600
|
-
this.toFetchRequestOptions = options;
|
|
69601
|
-
this.adapterInterceptors = toArray(options.adapterInterceptors);
|
|
69602
|
-
}
|
|
69603
|
-
async call(standardRequest, options, path44, input2) {
|
|
69604
|
-
const request7 = toFetchRequest(standardRequest, this.toFetchRequestOptions);
|
|
69605
|
-
const fetchResponse = await intercept(
|
|
69606
|
-
this.adapterInterceptors,
|
|
69607
|
-
{ ...options, request: request7, path: path44, input: input2, init: { redirect: "manual" } },
|
|
69608
|
-
({ request: request22, path: path210, input: input22, init, ...options2 }) => this.fetch(request22, init, options2, path210, input22)
|
|
69609
|
-
);
|
|
69610
|
-
const lazyResponse = toStandardLazyResponse(fetchResponse, { signal: request7.signal });
|
|
69611
|
-
return lazyResponse;
|
|
69612
|
-
}
|
|
69613
|
-
};
|
|
69614
|
-
var RPCLink = class extends StandardRPCLink {
|
|
69615
|
-
constructor(options) {
|
|
69616
|
-
const linkClient = new LinkFetchClient(options);
|
|
69617
|
-
super(linkClient, options);
|
|
69618
|
-
}
|
|
69619
|
-
};
|
|
69620
|
-
|
|
69621
|
-
// node_modules/.pnpm/@orpc+contract@1.15.4/node_modules/@orpc/contract/dist/shared/contract.D_dZrO__.mjs
|
|
69622
|
-
var ValidationError = class extends Error {
|
|
69623
|
-
issues;
|
|
69624
|
-
data;
|
|
69625
|
-
constructor(options) {
|
|
69626
|
-
super(options.message, options);
|
|
69627
|
-
this.issues = options.issues;
|
|
69628
|
-
this.data = options.data;
|
|
69629
|
-
}
|
|
69630
|
-
};
|
|
69631
|
-
function mergeErrorMap(errorMap1, errorMap2) {
|
|
69632
|
-
return { ...errorMap1, ...errorMap2 };
|
|
69633
|
-
}
|
|
69634
|
-
async function validateORPCError(map3, error62) {
|
|
69635
|
-
const { code, status, message, data, cause, defined } = error62;
|
|
69636
|
-
const config2 = map3?.[error62.code];
|
|
69637
|
-
if (!config2 || fallbackORPCErrorStatus(error62.code, config2.status) !== error62.status) {
|
|
69638
|
-
return defined ? new ORPCError(code, { defined: false, status, message, data, cause }) : error62;
|
|
69639
|
-
}
|
|
69640
|
-
if (!config2.data) {
|
|
69641
|
-
return defined ? error62 : new ORPCError(code, { defined: true, status, message, data, cause });
|
|
69642
|
-
}
|
|
69643
|
-
const validated2 = await config2.data["~standard"].validate(error62.data);
|
|
69644
|
-
if (validated2.issues) {
|
|
69645
|
-
return defined ? new ORPCError(code, { defined: false, status, message, data, cause }) : error62;
|
|
69646
|
-
}
|
|
69647
|
-
return new ORPCError(code, { defined: true, status, message, data: validated2.value, cause });
|
|
69648
|
-
}
|
|
69649
|
-
var ContractProcedure = class {
|
|
69650
|
-
/**
|
|
69651
|
-
* This property holds the defined options for the contract procedure.
|
|
69652
|
-
*/
|
|
69653
|
-
"~orpc";
|
|
69654
|
-
constructor(def) {
|
|
69655
|
-
if (def.route?.successStatus && isORPCErrorStatus(def.route.successStatus)) {
|
|
69656
|
-
throw new Error("[ContractProcedure] Invalid successStatus.");
|
|
69657
|
-
}
|
|
69658
|
-
if (Object.values(def.errorMap).some((val) => val && val.status && !isORPCErrorStatus(val.status))) {
|
|
69659
|
-
throw new Error("[ContractProcedure] Invalid error status code.");
|
|
69660
|
-
}
|
|
69661
|
-
this["~orpc"] = def;
|
|
69662
|
-
}
|
|
69663
|
-
};
|
|
69664
|
-
function isContractProcedure(item) {
|
|
69665
|
-
if (item instanceof ContractProcedure) {
|
|
69666
|
-
return true;
|
|
69667
|
-
}
|
|
69668
|
-
return (typeof item === "object" || typeof item === "function") && item !== null && "~orpc" in item && typeof item["~orpc"] === "object" && item["~orpc"] !== null && "errorMap" in item["~orpc"] && "route" in item["~orpc"] && "meta" in item["~orpc"];
|
|
69669
|
-
}
|
|
69670
|
-
|
|
69671
70154
|
// node_modules/.pnpm/@orpc+contract@1.15.4/node_modules/@orpc/contract/dist/index.mjs
|
|
69672
70155
|
function mergeMeta(meta1, meta22) {
|
|
69673
70156
|
return { ...meta1, ...meta22 };
|
|
@@ -70612,6 +71095,43 @@ var os7 = new Builder({
|
|
|
70612
71095
|
dedupeLeadingMiddlewares: true
|
|
70613
71096
|
});
|
|
70614
71097
|
|
|
71098
|
+
// node_modules/.pnpm/@orpc+client@1.15.4/node_modules/@orpc/client/dist/adapters/fetch/index.mjs
|
|
71099
|
+
var CompositeLinkFetchPlugin = class extends CompositeStandardLinkPlugin {
|
|
71100
|
+
initRuntimeAdapter(options) {
|
|
71101
|
+
for (const plugin of this.plugins) {
|
|
71102
|
+
plugin.initRuntimeAdapter?.(options);
|
|
71103
|
+
}
|
|
71104
|
+
}
|
|
71105
|
+
};
|
|
71106
|
+
var LinkFetchClient = class {
|
|
71107
|
+
fetch;
|
|
71108
|
+
toFetchRequestOptions;
|
|
71109
|
+
adapterInterceptors;
|
|
71110
|
+
constructor(options) {
|
|
71111
|
+
const plugin = new CompositeLinkFetchPlugin(options.plugins);
|
|
71112
|
+
plugin.initRuntimeAdapter(options);
|
|
71113
|
+
this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
71114
|
+
this.toFetchRequestOptions = options;
|
|
71115
|
+
this.adapterInterceptors = toArray(options.adapterInterceptors);
|
|
71116
|
+
}
|
|
71117
|
+
async call(standardRequest, options, path44, input2) {
|
|
71118
|
+
const request7 = toFetchRequest(standardRequest, this.toFetchRequestOptions);
|
|
71119
|
+
const fetchResponse = await intercept(
|
|
71120
|
+
this.adapterInterceptors,
|
|
71121
|
+
{ ...options, request: request7, path: path44, input: input2, init: { redirect: "manual" } },
|
|
71122
|
+
({ request: request22, path: path210, input: input22, init, ...options2 }) => this.fetch(request22, init, options2, path210, input22)
|
|
71123
|
+
);
|
|
71124
|
+
const lazyResponse = toStandardLazyResponse(fetchResponse, { signal: request7.signal });
|
|
71125
|
+
return lazyResponse;
|
|
71126
|
+
}
|
|
71127
|
+
};
|
|
71128
|
+
var RPCLink = class extends StandardRPCLink {
|
|
71129
|
+
constructor(options) {
|
|
71130
|
+
const linkClient = new LinkFetchClient(options);
|
|
71131
|
+
super(linkClient, options);
|
|
71132
|
+
}
|
|
71133
|
+
};
|
|
71134
|
+
|
|
70615
71135
|
// node_modules/.pnpm/@orpc+standard-server-node@1.15.4/node_modules/@orpc/standard-server-node/dist/index.mjs
|
|
70616
71136
|
var import_node_buffer = require("node:buffer");
|
|
70617
71137
|
var import_node_stream = require("node:stream");
|
|
@@ -71335,6 +71855,62 @@ function frontDoorRcApiClient(port, ca, token) {
|
|
|
71335
71855
|
return createORPCClient(frontDoorApiLink(port, ca, token));
|
|
71336
71856
|
}
|
|
71337
71857
|
|
|
71858
|
+
// src/frontdoor/eventSchemas.ts
|
|
71859
|
+
var DOOR_EVENT_SOURCE_RC = "rc";
|
|
71860
|
+
var LAUNCH_EVENT_SOURCE = "launch";
|
|
71861
|
+
var DoorEventSchema = external_exports.strictObject({
|
|
71862
|
+
source: external_exports.string().min(1),
|
|
71863
|
+
/** A positive integer because the backbone's counters start at one and only ever increase. */
|
|
71864
|
+
sequence: external_exports.number().int().positive(),
|
|
71865
|
+
payload: external_exports.unknown()
|
|
71866
|
+
});
|
|
71867
|
+
var DoorEventSourceQuerySchema = external_exports.strictObject({
|
|
71868
|
+
sources: external_exports.array(external_exports.string().min(1)).min(1).optional()
|
|
71869
|
+
});
|
|
71870
|
+
var LaunchLifecycleEventSchema = external_exports.strictObject({
|
|
71871
|
+
kind: external_exports.enum(["registered", "pruned", "ended"]),
|
|
71872
|
+
pid: external_exports.number().int().positive(),
|
|
71873
|
+
startedAt: external_exports.number(),
|
|
71874
|
+
observedAt: external_exports.number()
|
|
71875
|
+
});
|
|
71876
|
+
|
|
71877
|
+
// src/frontdoor/eventsApi.ts
|
|
71878
|
+
function createEventsApiRouter(deps) {
|
|
71879
|
+
const authed = doorApiAuth(deps.expectedToken);
|
|
71880
|
+
return {
|
|
71881
|
+
events: {
|
|
71882
|
+
subscribe: authed.input(DoorEventSourceQuerySchema).output(eventIterator(DoorEventSchema)).handler(async function* ({ input: input2, signal }) {
|
|
71883
|
+
if (input2.sources !== void 0) {
|
|
71884
|
+
const live = deps.events.sources();
|
|
71885
|
+
const unknown2 = input2.sources.filter((source) => !live.includes(source));
|
|
71886
|
+
if (unknown2.length > 0) {
|
|
71887
|
+
throw new ORPCError("NOT_FOUND", { message: `the door publishes no event source named ${unknown2.map((source) => `"${source}"`).join(", ")}; the live sources are ${live.map((source) => `"${source}"`).join(", ")}` });
|
|
71888
|
+
}
|
|
71889
|
+
}
|
|
71890
|
+
const stream = deps.events.stream(input2.sources);
|
|
71891
|
+
const ended = new Promise((resolve) => {
|
|
71892
|
+
signal?.addEventListener("abort", () => {
|
|
71893
|
+
resolve();
|
|
71894
|
+
}, { once: true });
|
|
71895
|
+
});
|
|
71896
|
+
try {
|
|
71897
|
+
for (; ; ) {
|
|
71898
|
+
signal?.throwIfAborted();
|
|
71899
|
+
const next = await Promise.race([stream.next(), ended.then(() => ({ value: void 0, done: true }))]);
|
|
71900
|
+
if (next.done === true) {
|
|
71901
|
+
signal?.throwIfAborted();
|
|
71902
|
+
return;
|
|
71903
|
+
}
|
|
71904
|
+
yield withEventMeta(next.value, { id: String(next.value.sequence) });
|
|
71905
|
+
}
|
|
71906
|
+
} finally {
|
|
71907
|
+
stream.close();
|
|
71908
|
+
}
|
|
71909
|
+
})
|
|
71910
|
+
}
|
|
71911
|
+
};
|
|
71912
|
+
}
|
|
71913
|
+
|
|
71338
71914
|
// src/frontdoor/controlApi.ts
|
|
71339
71915
|
function createControlApiRouter(deps) {
|
|
71340
71916
|
const authed = doorApiAuth(deps.expectedToken);
|
|
@@ -71373,14 +71949,156 @@ function createControlApiRouter(deps) {
|
|
|
71373
71949
|
};
|
|
71374
71950
|
}
|
|
71375
71951
|
function createDoorApiRouter(deps) {
|
|
71376
|
-
return { ...createRcApiRouter(deps), ...createControlApiRouter(deps) };
|
|
71952
|
+
return { ...createRcApiRouter(deps), ...createControlApiRouter(deps), ...createEventsApiRouter(deps) };
|
|
71377
71953
|
}
|
|
71378
71954
|
function createDoorApiNodeHandler(deps) {
|
|
71379
71955
|
return doorApiNodeHandlerOf(createDoorApiRouter(deps));
|
|
71380
71956
|
}
|
|
71381
71957
|
|
|
71958
|
+
// src/frontdoor/eventHub.ts
|
|
71959
|
+
var DOOR_EVENT_BUFFER_EVENTS = 100;
|
|
71960
|
+
function createDoorEventHub() {
|
|
71961
|
+
const sequences = /* @__PURE__ */ new Map();
|
|
71962
|
+
const registered = /* @__PURE__ */ new Set();
|
|
71963
|
+
const every = /* @__PURE__ */ new Set();
|
|
71964
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
71965
|
+
const deliver = (event) => {
|
|
71966
|
+
for (const listener of every) {
|
|
71967
|
+
listener(event);
|
|
71968
|
+
}
|
|
71969
|
+
for (const listener of bySource.get(event.source) ?? []) {
|
|
71970
|
+
listener(event);
|
|
71971
|
+
}
|
|
71972
|
+
};
|
|
71973
|
+
const publish = (source, payload) => {
|
|
71974
|
+
const sequence2 = (sequences.get(source) ?? 0) + 1;
|
|
71975
|
+
sequences.set(source, sequence2);
|
|
71976
|
+
deliver({ source, sequence: sequence2, payload });
|
|
71977
|
+
};
|
|
71978
|
+
const addListener = (sources, listener) => {
|
|
71979
|
+
if (sources === void 0) {
|
|
71980
|
+
every.add(listener);
|
|
71981
|
+
return () => {
|
|
71982
|
+
every.delete(listener);
|
|
71983
|
+
};
|
|
71984
|
+
}
|
|
71985
|
+
const listenersFor = (source) => {
|
|
71986
|
+
const listeners = bySource.get(source) ?? /* @__PURE__ */ new Set();
|
|
71987
|
+
bySource.set(source, listeners);
|
|
71988
|
+
return listeners;
|
|
71989
|
+
};
|
|
71990
|
+
const detachers = sources.map((source) => {
|
|
71991
|
+
const listeners = listenersFor(source);
|
|
71992
|
+
listeners.add(listener);
|
|
71993
|
+
return () => {
|
|
71994
|
+
listeners.delete(listener);
|
|
71995
|
+
if (listeners.size === 0) {
|
|
71996
|
+
bySource.delete(source);
|
|
71997
|
+
}
|
|
71998
|
+
};
|
|
71999
|
+
});
|
|
72000
|
+
return () => {
|
|
72001
|
+
for (const detach of detachers) {
|
|
72002
|
+
detach();
|
|
72003
|
+
}
|
|
72004
|
+
};
|
|
72005
|
+
};
|
|
72006
|
+
return {
|
|
72007
|
+
publisher: (source) => {
|
|
72008
|
+
registered.add(source);
|
|
72009
|
+
return {
|
|
72010
|
+
source,
|
|
72011
|
+
publish: (payload) => {
|
|
72012
|
+
publish(source, payload);
|
|
72013
|
+
}
|
|
72014
|
+
};
|
|
72015
|
+
},
|
|
72016
|
+
subscribe: addListener,
|
|
72017
|
+
stream: (sources) => {
|
|
72018
|
+
const queue = [];
|
|
72019
|
+
let wake;
|
|
72020
|
+
let closed = false;
|
|
72021
|
+
const detach = addListener(sources, (event) => {
|
|
72022
|
+
if (queue.length >= DOOR_EVENT_BUFFER_EVENTS) {
|
|
72023
|
+
queue.shift();
|
|
72024
|
+
}
|
|
72025
|
+
queue.push(event);
|
|
72026
|
+
wake?.();
|
|
72027
|
+
});
|
|
72028
|
+
return {
|
|
72029
|
+
next: async () => {
|
|
72030
|
+
for (; ; ) {
|
|
72031
|
+
const event = queue.shift();
|
|
72032
|
+
if (event !== void 0) {
|
|
72033
|
+
return { value: event, done: false };
|
|
72034
|
+
}
|
|
72035
|
+
if (closed) {
|
|
72036
|
+
return { value: void 0, done: true };
|
|
72037
|
+
}
|
|
72038
|
+
await new Promise((resolve) => {
|
|
72039
|
+
wake = resolve;
|
|
72040
|
+
});
|
|
72041
|
+
}
|
|
72042
|
+
},
|
|
72043
|
+
close: () => {
|
|
72044
|
+
closed = true;
|
|
72045
|
+
detach();
|
|
72046
|
+
wake?.();
|
|
72047
|
+
}
|
|
72048
|
+
};
|
|
72049
|
+
},
|
|
72050
|
+
sources: () => [...registered].sort()
|
|
72051
|
+
};
|
|
72052
|
+
}
|
|
72053
|
+
function rcFanoutOnDoorHub(fanout, hub) {
|
|
72054
|
+
const publisher = hub.publisher(DOOR_EVENT_SOURCE_RC);
|
|
72055
|
+
return {
|
|
72056
|
+
publish: (event) => {
|
|
72057
|
+
fanout.publish(event);
|
|
72058
|
+
publisher.publish(event);
|
|
72059
|
+
},
|
|
72060
|
+
subscribe: (session, listener) => fanout.subscribe(session, listener)
|
|
72061
|
+
};
|
|
72062
|
+
}
|
|
72063
|
+
|
|
72064
|
+
// src/frontdoor/launchEvents.ts
|
|
72065
|
+
function createLaunchEventPublisher(hub, now) {
|
|
72066
|
+
const publisher = hub.publisher(LAUNCH_EVENT_SOURCE);
|
|
72067
|
+
let known;
|
|
72068
|
+
return {
|
|
72069
|
+
observe: (sessions, pruned) => {
|
|
72070
|
+
const previous = known;
|
|
72071
|
+
const listed = new Map(sessions.map((session) => [session.pid, session]));
|
|
72072
|
+
const prunedSet = new Set(pruned);
|
|
72073
|
+
known = new Map([...listed].filter(([pid]) => !prunedSet.has(pid)));
|
|
72074
|
+
if (previous === void 0) {
|
|
72075
|
+
return;
|
|
72076
|
+
}
|
|
72077
|
+
const emit = (kind, pid, startedAt) => {
|
|
72078
|
+
publisher.publish({ kind, pid, startedAt, observedAt: now() });
|
|
72079
|
+
};
|
|
72080
|
+
for (const pid of pruned) {
|
|
72081
|
+
const session = listed.get(pid);
|
|
72082
|
+
if (session !== void 0) {
|
|
72083
|
+
emit("pruned", pid, session.startedAt);
|
|
72084
|
+
}
|
|
72085
|
+
}
|
|
72086
|
+
for (const [pid, session] of previous) {
|
|
72087
|
+
if (!listed.has(pid) && !prunedSet.has(pid)) {
|
|
72088
|
+
emit("ended", pid, session.startedAt);
|
|
72089
|
+
}
|
|
72090
|
+
}
|
|
72091
|
+
for (const [pid, session] of listed) {
|
|
72092
|
+
if (!previous.has(pid) && !prunedSet.has(pid)) {
|
|
72093
|
+
emit("registered", pid, session.startedAt);
|
|
72094
|
+
}
|
|
72095
|
+
}
|
|
72096
|
+
}
|
|
72097
|
+
};
|
|
72098
|
+
}
|
|
72099
|
+
|
|
71382
72100
|
// src/frontdoor/headroomHop.ts
|
|
71383
|
-
var
|
|
72101
|
+
var http4 = __toESM(require("node:http"), 1);
|
|
71384
72102
|
var HTTP_BAD_GATEWAY2 = HTTP_STATUS.badGateway;
|
|
71385
72103
|
function responseHeaders(headers) {
|
|
71386
72104
|
const result = {};
|
|
@@ -71434,7 +72152,7 @@ async function answerBadGateway(response, message) {
|
|
|
71434
72152
|
await response.write(JSON.stringify({ type: "error", error: { type: "api_error", message } }));
|
|
71435
72153
|
response.end();
|
|
71436
72154
|
}
|
|
71437
|
-
var HOP_AGENT = new
|
|
72155
|
+
var HOP_AGENT = new http4.Agent({ keepAlive: false });
|
|
71438
72156
|
async function forwardThroughHeadroom(request7, response, target) {
|
|
71439
72157
|
const { socketPath, headers } = target;
|
|
71440
72158
|
await new Promise((resolve) => {
|
|
@@ -71462,7 +72180,7 @@ async function forwardThroughHeadroom(request7, response, target) {
|
|
|
71462
72180
|
};
|
|
71463
72181
|
void stream();
|
|
71464
72182
|
};
|
|
71465
|
-
const hop =
|
|
72183
|
+
const hop = http4.request({ socketPath, method: request7.method, path: request7.url, headers, agent: HOP_AGENT }, onUpstreamResponse);
|
|
71466
72184
|
hop.on("error", (error62) => {
|
|
71467
72185
|
const phase = response.headersSent ? "mid-stream" : "before the response started";
|
|
71468
72186
|
const code = "code" in error62 && typeof error62.code === "string" ? ` ${error62.code}` : "";
|
|
@@ -71651,7 +72369,7 @@ async function serveRouted(request7, deps) {
|
|
|
71651
72369
|
}
|
|
71652
72370
|
|
|
71653
72371
|
// src/codex/translate.ts
|
|
71654
|
-
var
|
|
72372
|
+
var import_node_crypto13 = require("node:crypto");
|
|
71655
72373
|
|
|
71656
72374
|
// src/codex/anthropic.ts
|
|
71657
72375
|
var TextBlockSchema = external_exports.looseObject({ type: external_exports.literal("text"), text: external_exports.string() });
|
|
@@ -71730,7 +72448,8 @@ function resolveCodexConfig(config2) {
|
|
|
71730
72448
|
sonnet: overrides?.sonnet ?? CODEX_DEFAULT_TIER_MODELS.sonnet,
|
|
71731
72449
|
haiku: overrides?.haiku ?? CODEX_DEFAULT_TIER_MODELS.haiku
|
|
71732
72450
|
},
|
|
71733
|
-
effort: config2?.effort ?? CODEX_DEFAULT_EFFORT
|
|
72451
|
+
effort: config2?.effort ?? CODEX_DEFAULT_EFFORT,
|
|
72452
|
+
login: config2?.login ?? CODEX_DEFAULT_LOGIN
|
|
71734
72453
|
};
|
|
71735
72454
|
}
|
|
71736
72455
|
function mapModel(requested, config2) {
|
|
@@ -71763,7 +72482,7 @@ function shortToolName(name, names) {
|
|
|
71763
72482
|
if (name.length <= CODEX_TOOL_NAME_LIMIT) {
|
|
71764
72483
|
return name;
|
|
71765
72484
|
}
|
|
71766
|
-
const hash2 = (0,
|
|
72485
|
+
const hash2 = (0, import_node_crypto13.createHash)("sha256").update(name).digest("hex").slice(0, TOOL_NAME_HASH_CHARS);
|
|
71767
72486
|
const shortened = `${name.slice(0, CODEX_TOOL_NAME_LIMIT - TOOL_NAME_HASH_CHARS - 1)}_${hash2}`;
|
|
71768
72487
|
names.set(shortened, name);
|
|
71769
72488
|
return shortened;
|
|
@@ -72039,17 +72758,17 @@ function unifiedQuotaHeaders(upstream, rejected, quotaError) {
|
|
|
72039
72758
|
}
|
|
72040
72759
|
return headers;
|
|
72041
72760
|
}
|
|
72042
|
-
var
|
|
72761
|
+
var MS_PER_SECOND6 = 1e3;
|
|
72043
72762
|
function buildUsageSnapshot(upstream, quotaError, nowMs) {
|
|
72044
72763
|
const used7 = upstream.get("x-codex-primary-used-percent") ?? (quotaError === void 0 ? null : EXHAUSTED_PERCENT);
|
|
72045
72764
|
const reset7 = upstream.get("x-codex-primary-reset-at") ?? (quotaError?.resets_at === void 0 ? null : String(quotaError.resets_at));
|
|
72046
|
-
const sevenDay = used7 !== null && reset7 !== null ? { used_percentage: Number(used7), resets_at: new Date(Number(reset7) *
|
|
72765
|
+
const sevenDay = used7 !== null && reset7 !== null ? { used_percentage: Number(used7), resets_at: new Date(Number(reset7) * MS_PER_SECOND6).toISOString() } : void 0;
|
|
72047
72766
|
let fiveHour;
|
|
72048
72767
|
if (Number(upstream.get("x-codex-secondary-window-minutes")) > 0) {
|
|
72049
72768
|
const used5 = upstream.get("x-codex-secondary-used-percent");
|
|
72050
72769
|
const reset5 = upstream.get("x-codex-secondary-reset-at");
|
|
72051
72770
|
if (used5 !== null && reset5 !== null) {
|
|
72052
|
-
fiveHour = { used_percentage: Number(used5), resets_at: new Date(Number(reset5) *
|
|
72771
|
+
fiveHour = { used_percentage: Number(used5), resets_at: new Date(Number(reset5) * MS_PER_SECOND6).toISOString() };
|
|
72053
72772
|
}
|
|
72054
72773
|
}
|
|
72055
72774
|
if (sevenDay === void 0 && fiveHour === void 0) {
|
|
@@ -72266,12 +72985,13 @@ function createCodexRoute(ports) {
|
|
|
72266
72985
|
}
|
|
72267
72986
|
const body = parsed.data;
|
|
72268
72987
|
const requestedModel = body.model ?? "";
|
|
72988
|
+
const upstreamPorts = ports.upstreams[config2.login];
|
|
72269
72989
|
const { request: upstreamRequest, toolNames } = translateRequest(body, config2);
|
|
72270
72990
|
const started = ports.now();
|
|
72271
72991
|
const elapsed = () => `${String(ports.now() - started)}ms`;
|
|
72272
72992
|
let upstream;
|
|
72273
72993
|
try {
|
|
72274
|
-
upstream = await callCodex(
|
|
72994
|
+
upstream = await callCodex(upstreamPorts, upstreamRequest, sessionIdFor(body.metadata?.user_id, upstreamPorts.randomId), request7.signal);
|
|
72275
72995
|
} catch (error62) {
|
|
72276
72996
|
if (request7.signal.aborted) {
|
|
72277
72997
|
return errorResponse(HTTP_STATUS.clientClosedRequest, "client disconnected");
|
|
@@ -72304,7 +73024,7 @@ function createCodexRoute(ports) {
|
|
|
72304
73024
|
});
|
|
72305
73025
|
}
|
|
72306
73026
|
snapshot(void 0);
|
|
72307
|
-
const relay = createRelay({ requestedModel, toolNames, fallbackId: () => `msg_${
|
|
73027
|
+
const relay = createRelay({ requestedModel, toolNames, fallbackId: () => `msg_${upstreamPorts.randomId()}` });
|
|
72308
73028
|
const upstreamBody = upstream.body;
|
|
72309
73029
|
const quota = { ...quotaHeaders(upstream.headers), ...unifiedQuotaHeaders(upstream.headers, false, void 0) };
|
|
72310
73030
|
const logCompleted = (message, usage) => {
|
|
@@ -72469,7 +73189,7 @@ function createCodexRouteMount(ports, upstreamBase, provider) {
|
|
|
72469
73189
|
}
|
|
72470
73190
|
|
|
72471
73191
|
// src/frontdoor/passthrough.ts
|
|
72472
|
-
var
|
|
73192
|
+
var http5 = __toESM(require("node:http"), 1);
|
|
72473
73193
|
var https4 = __toESM(require("node:https"), 1);
|
|
72474
73194
|
function responseHeaders2(headers) {
|
|
72475
73195
|
const result = {};
|
|
@@ -72523,7 +73243,7 @@ function createPassthroughRoute(name, target) {
|
|
|
72523
73243
|
};
|
|
72524
73244
|
void stream();
|
|
72525
73245
|
};
|
|
72526
|
-
const forward = tls2 ? https4.request(options, onUpstreamResponse) :
|
|
73246
|
+
const forward = tls2 ? https4.request(options, onUpstreamResponse) : http5.request(options, onUpstreamResponse);
|
|
72527
73247
|
forward.on("error", (error62) => {
|
|
72528
73248
|
if (!response.headersSent) {
|
|
72529
73249
|
response.start(HTTP_STATUS.badGateway, { "Content-Type": "application/json" });
|
|
@@ -72689,6 +73409,465 @@ function createRcCredentialStore(fs19, dir) {
|
|
|
72689
73409
|
};
|
|
72690
73410
|
}
|
|
72691
73411
|
|
|
73412
|
+
// src/frontdoor/rcClientPage.ts
|
|
73413
|
+
var RC_CLIENT_PATH = "/__agent-shim/client";
|
|
73414
|
+
var RC_CLIENT_PAGE_SCRIPT = `'use strict';
|
|
73415
|
+
// The door's typed API as this page speaks it: the oRPC RPC protocol over plain fetch, which is one POST per procedure with a {"json": input} body and a {"json": output} answer, so no client library is needed. These helpers are plain top-level functions (not boot-scoped) so the page's tests can evaluate this script outside a browser and drive them against a mounted listener.
|
|
73416
|
+
var API_PREFIX = '/__agent-shim/orpc';
|
|
73417
|
+
var TOKEN_KEY = 'agent-shim-rc-token';
|
|
73418
|
+
var token = null;
|
|
73419
|
+
|
|
73420
|
+
function apiBase() { return window.location.origin + API_PREFIX; }
|
|
73421
|
+
|
|
73422
|
+
// Calls one procedure: resolves the output's own value, rejects with the door's error message when it answered one.
|
|
73423
|
+
async function rpc(path, input) {
|
|
73424
|
+
var response = await fetch(apiBase() + '/' + path, {
|
|
73425
|
+
method: 'POST',
|
|
73426
|
+
headers: { 'content-type': 'application/json', authorization: 'Bearer ' + token },
|
|
73427
|
+
body: JSON.stringify({ json: input === undefined ? {} : input }),
|
|
73428
|
+
});
|
|
73429
|
+
var envelope = await response.json().catch(function () { return {}; });
|
|
73430
|
+
if (!response.ok) {
|
|
73431
|
+
var message = envelope && envelope.json && envelope.json.message ? envelope.json.message : ('HTTP ' + response.status);
|
|
73432
|
+
var error = new Error(message);
|
|
73433
|
+
error.status = response.status;
|
|
73434
|
+
throw error;
|
|
73435
|
+
}
|
|
73436
|
+
return envelope.json;
|
|
73437
|
+
}
|
|
73438
|
+
|
|
73439
|
+
// Parses every complete SSE frame out of the buffered text, returning the frames and the unparsed remainder. Comment frames (the door's keepalive opens with one) carry no event name and are dropped.
|
|
73440
|
+
function parseSseFrames(buffer) {
|
|
73441
|
+
var frames = [];
|
|
73442
|
+
var rest = buffer;
|
|
73443
|
+
for (;;) {
|
|
73444
|
+
var boundary = rest.indexOf('\\n\\n');
|
|
73445
|
+
if (boundary === -1) { break; }
|
|
73446
|
+
var raw = rest.slice(0, boundary);
|
|
73447
|
+
rest = rest.slice(boundary + 2);
|
|
73448
|
+
var frame = { event: 'message', id: '', data: '' };
|
|
73449
|
+
var lines = raw.split('\\n');
|
|
73450
|
+
for (var i = 0; i < lines.length; i++) {
|
|
73451
|
+
var line = lines[i];
|
|
73452
|
+
if (line === '' || line.charAt(0) === ':') { continue; }
|
|
73453
|
+
var colon = line.indexOf(':');
|
|
73454
|
+
var field = colon === -1 ? line : line.slice(0, colon);
|
|
73455
|
+
var value = colon === -1 ? '' : line.slice(colon + 1);
|
|
73456
|
+
if (value.charAt(0) === ' ') { value = value.slice(1); }
|
|
73457
|
+
if (field === 'event') { frame.event = value; }
|
|
73458
|
+
if (field === 'id') { frame.id = value; }
|
|
73459
|
+
if (field === 'data') { frame.data += (frame.data === '' ? '' : '\\n') + value; }
|
|
73460
|
+
}
|
|
73461
|
+
if (frame.data !== '') { frames.push(frame); }
|
|
73462
|
+
}
|
|
73463
|
+
return { frames: frames, rest: rest };
|
|
73464
|
+
}
|
|
73465
|
+
|
|
73466
|
+
// Whether one source-tagged event continues the per-source sequence the tracker holds: the count of events the stream dropped when it does not, zero when it does. The tracker keeps the high-water mark, so a number the door re-sends after a reconnect is a duplicate, not a step back, and never reports a negative gap. The backbone holds no replay, so a gap is reported, never hidden.
|
|
73467
|
+
function sequenceGap(tracker, event) {
|
|
73468
|
+
var previous = tracker[event.source];
|
|
73469
|
+
if (event.sequence > (previous === undefined ? 0 : previous)) { tracker[event.source] = event.sequence; }
|
|
73470
|
+
if (previous === undefined || event.sequence <= previous) { return 0; }
|
|
73471
|
+
return event.sequence - previous - 1;
|
|
73472
|
+
}
|
|
73473
|
+
|
|
73474
|
+
function shortId(id) { return id.length > 14 ? id.slice(0, 8) + '..' + id.slice(-4) : id; }
|
|
73475
|
+
|
|
73476
|
+
// A bounded sketch of any payload, the feed's fallback rendering: one JSON line, cut with a marker rather than silently.
|
|
73477
|
+
function sketch(value, cap) {
|
|
73478
|
+
var text;
|
|
73479
|
+
try { text = JSON.stringify(value); } catch (e) { text = String(value); }
|
|
73480
|
+
if (text === undefined) { text = 'undefined'; }
|
|
73481
|
+
return text.length > cap ? text.slice(0, cap) + '...' : text;
|
|
73482
|
+
}
|
|
73483
|
+
|
|
73484
|
+
// The headline text of one Remote Control stream event: the assistant and user payloads that carry a content array of text blocks render as their prose, everything else as its type plus a sketch.
|
|
73485
|
+
function rcLine(event) {
|
|
73486
|
+
var envelope = event.envelope;
|
|
73487
|
+
var payload = envelope.payload;
|
|
73488
|
+
var headline = '';
|
|
73489
|
+
if (payload !== undefined && payload !== null && typeof payload === 'object' && Array.isArray(payload.content)) {
|
|
73490
|
+
var parts = [];
|
|
73491
|
+
for (var i = 0; i < payload.content.length; i++) {
|
|
73492
|
+
var block = payload.content[i];
|
|
73493
|
+
if (block !== null && typeof block === 'object' && block.type === 'text' && typeof block.text === 'string') { parts.push(block.text); }
|
|
73494
|
+
}
|
|
73495
|
+
if (parts.length > 0) { headline = parts.join(' '); }
|
|
73496
|
+
}
|
|
73497
|
+
if (headline === '') {
|
|
73498
|
+
headline = envelope.event_type;
|
|
73499
|
+
if (payload !== undefined) { headline += ' ' + sketch(payload, 240); }
|
|
73500
|
+
}
|
|
73501
|
+
return new Date().toLocaleTimeString() + ' ' + shortId(event.session) + ' ' + envelope.event_type + ' ' + headline;
|
|
73502
|
+
}
|
|
73503
|
+
|
|
73504
|
+
function el(tag, className, text) {
|
|
73505
|
+
var node = document.createElement(tag);
|
|
73506
|
+
if (className) { node.className = className; }
|
|
73507
|
+
if (text !== undefined) { node.textContent = text; }
|
|
73508
|
+
return node;
|
|
73509
|
+
}
|
|
73510
|
+
|
|
73511
|
+
var ui = null;
|
|
73512
|
+
|
|
73513
|
+
function renderEvent(event, gap) {
|
|
73514
|
+
if (ui === null) { return; }
|
|
73515
|
+
var list = ui.eventList;
|
|
73516
|
+
if (gap > 0) {
|
|
73517
|
+
list.appendChild(el('div', 'event gap', 'dropped events: ' + String(gap) + ' on source ' + event.source + ' (the stream holds no replay)'));
|
|
73518
|
+
}
|
|
73519
|
+
var line;
|
|
73520
|
+
if (event.source === 'rc') {
|
|
73521
|
+
line = rcLine(event.payload);
|
|
73522
|
+
} else {
|
|
73523
|
+
line = new Date().toLocaleTimeString() + ' [' + event.source + '] ' + sketch(event.payload, 240);
|
|
73524
|
+
}
|
|
73525
|
+
list.appendChild(el('div', 'event', line));
|
|
73526
|
+
while (list.childElementCount > 500) { list.removeChild(list.firstChild); }
|
|
73527
|
+
list.scrollTop = list.scrollHeight;
|
|
73528
|
+
}
|
|
73529
|
+
|
|
73530
|
+
function renderSessions(statuses) {
|
|
73531
|
+
if (ui === null) { return; }
|
|
73532
|
+
var list = ui.sessionList;
|
|
73533
|
+
list.textContent = '';
|
|
73534
|
+
if (statuses.length === 0) {
|
|
73535
|
+
list.appendChild(el('div', 'event dim', 'no Remote Control sessions observed'));
|
|
73536
|
+
return;
|
|
73537
|
+
}
|
|
73538
|
+
for (var i = 0; i < statuses.length; i++) {
|
|
73539
|
+
var status = statuses[i];
|
|
73540
|
+
var worker = status.workerState === undefined ? 'worker unknown' : 'worker ' + status.workerState.value;
|
|
73541
|
+
var row = el('div', 'session' + (status.id === ui.selected ? ' selected' : ''));
|
|
73542
|
+
row.appendChild(el('div', null, shortId(status.id)));
|
|
73543
|
+
row.appendChild(el('div', 'dim', worker + (status.pending.length === 0 ? '' : ', ' + String(status.pending.length) + ' pending') + ', seen ' + new Date(status.lastSeenAt).toLocaleTimeString()));
|
|
73544
|
+
row.addEventListener('click', selectSession(status.id));
|
|
73545
|
+
list.appendChild(row);
|
|
73546
|
+
}
|
|
73547
|
+
}
|
|
73548
|
+
|
|
73549
|
+
function selectSession(id) {
|
|
73550
|
+
return function () {
|
|
73551
|
+
if (ui === null) { return; }
|
|
73552
|
+
ui.selected = ui.selected === id ? null : id;
|
|
73553
|
+
ui.promptTarget.textContent = ui.selected === null ? 'no session selected' : 'to ' + ui.selected;
|
|
73554
|
+
refreshSessions();
|
|
73555
|
+
refreshPending();
|
|
73556
|
+
};
|
|
73557
|
+
}
|
|
73558
|
+
|
|
73559
|
+
function renderPending(pending) {
|
|
73560
|
+
if (ui === null) { return; }
|
|
73561
|
+
var list = ui.pendingList;
|
|
73562
|
+
list.textContent = '';
|
|
73563
|
+
if (pending.length === 0) {
|
|
73564
|
+
list.appendChild(el('div', 'event dim', 'no control requests awaiting an answer'));
|
|
73565
|
+
return;
|
|
73566
|
+
}
|
|
73567
|
+
for (var i = 0; i < pending.length; i++) {
|
|
73568
|
+
var request = pending[i];
|
|
73569
|
+
var card = el('div', 'card');
|
|
73570
|
+
card.appendChild(el('div', null, request.type + ' ' + (request.summary === '' ? shortId(request.requestId) : request.summary)));
|
|
73571
|
+
card.appendChild(el('div', 'dim', shortId(request.sessionId) + ' ' + shortId(request.requestId) + ' observed ' + new Date(request.observedAt).toLocaleTimeString()));
|
|
73572
|
+
var row = el('div', 'row');
|
|
73573
|
+
var denial = el('input');
|
|
73574
|
+
denial.type = 'text';
|
|
73575
|
+
denial.placeholder = 'denial message (optional)';
|
|
73576
|
+
var approve = el('button', null, 'Approve');
|
|
73577
|
+
var deny = el('button', 'secondary', 'Deny');
|
|
73578
|
+
approve.addEventListener('click', answerRequest(request, true, denial));
|
|
73579
|
+
deny.addEventListener('click', answerRequest(request, false, denial));
|
|
73580
|
+
row.appendChild(denial);
|
|
73581
|
+
row.appendChild(approve);
|
|
73582
|
+
row.appendChild(deny);
|
|
73583
|
+
card.appendChild(row);
|
|
73584
|
+
list.appendChild(card);
|
|
73585
|
+
}
|
|
73586
|
+
}
|
|
73587
|
+
|
|
73588
|
+
function answerRequest(request, approve, denialInput) {
|
|
73589
|
+
return function () {
|
|
73590
|
+
var input = { session: request.sessionId, request: request.requestId, approve: approve };
|
|
73591
|
+
if (!approve && denialInput.value !== '') { input.text = denialInput.value; }
|
|
73592
|
+
rpc('rc/answer', input).then(function () {
|
|
73593
|
+
renderEvent({ source: 'page', sequence: 0, payload: { note: (approve ? 'approved' : 'denied') + ' ' + request.requestId } }, 0);
|
|
73594
|
+
refreshPending();
|
|
73595
|
+
}, function (error) { window.alert('answer failed: ' + error.message); });
|
|
73596
|
+
};
|
|
73597
|
+
}
|
|
73598
|
+
|
|
73599
|
+
function sendPrompt() {
|
|
73600
|
+
if (ui === null || ui.selected === null) { window.alert('select a session first'); return; }
|
|
73601
|
+
var text = ui.prompt.value;
|
|
73602
|
+
if (text === '') { return; }
|
|
73603
|
+
ui.send.disabled = true;
|
|
73604
|
+
rpc('rc/send', { session: ui.selected, text: text }).then(function (result) {
|
|
73605
|
+
ui.prompt.value = '';
|
|
73606
|
+
renderEvent({ source: 'page', sequence: 0, payload: { note: 'sent, sequence_num ' + result.sequenceNums.join(', ') } }, 0);
|
|
73607
|
+
}, function (error) { window.alert('send failed: ' + error.message); }).then(function () { ui.send.disabled = false; });
|
|
73608
|
+
}
|
|
73609
|
+
|
|
73610
|
+
function refreshSessions() {
|
|
73611
|
+
rpc('rc/status', {}).then(function (result) { renderSessions(result.statuses); }, authOrReport('rc/status'));
|
|
73612
|
+
}
|
|
73613
|
+
|
|
73614
|
+
function refreshPending() {
|
|
73615
|
+
rpc('rc/pending', ui !== null && ui.selected !== null ? { session: ui.selected } : {}).then(function (result) { renderPending(result.pending); }, authOrReport('rc/pending'));
|
|
73616
|
+
}
|
|
73617
|
+
|
|
73618
|
+
// The one error path every call shares: a 401 means this token is not this generation's, so the page says so and asks for it again; anything else is reported in the feed.
|
|
73619
|
+
function authOrReport(what) {
|
|
73620
|
+
return function (error) {
|
|
73621
|
+
if (error.status === 401) {
|
|
73622
|
+
handleUnauthorized();
|
|
73623
|
+
return;
|
|
73624
|
+
}
|
|
73625
|
+
renderEvent({ source: 'page', sequence: 0, payload: { note: what + ' failed: ' + error.message } }, 0);
|
|
73626
|
+
};
|
|
73627
|
+
}
|
|
73628
|
+
|
|
73629
|
+
function handleUnauthorized() {
|
|
73630
|
+
window.sessionStorage.removeItem(TOKEN_KEY);
|
|
73631
|
+
if (feedAbort !== null) { feedAbort.abort(); }
|
|
73632
|
+
streamState('');
|
|
73633
|
+
showTokenForm('this door refused the token: it names a different door generation, paste the current one');
|
|
73634
|
+
}
|
|
73635
|
+
|
|
73636
|
+
function streamState(text) { if (ui !== null) { ui.streamState.textContent = text; } }
|
|
73637
|
+
|
|
73638
|
+
var feedAbort = null;
|
|
73639
|
+
|
|
73640
|
+
// Subscribes to the door's backbone and renders what it yields, reconnecting on any drop. The stream holds no replay, so a reconnect starts at the live head and the per-source sequence numbers surface whatever the gap swallowed.
|
|
73641
|
+
async function runFeed() {
|
|
73642
|
+
var tracker = {};
|
|
73643
|
+
for (;;) {
|
|
73644
|
+
if (feedAbort !== null) { feedAbort.abort(); }
|
|
73645
|
+
feedAbort = new AbortController();
|
|
73646
|
+
var filter = document.getElementById('source-filter').value;
|
|
73647
|
+
var input = filter === '' ? {} : { sources: [filter] };
|
|
73648
|
+
try {
|
|
73649
|
+
streamState('stream: connecting');
|
|
73650
|
+
var response = await fetch(apiBase() + '/events/subscribe', {
|
|
73651
|
+
method: 'POST',
|
|
73652
|
+
headers: { 'content-type': 'application/json', authorization: 'Bearer ' + token },
|
|
73653
|
+
body: JSON.stringify({ json: input }),
|
|
73654
|
+
signal: feedAbort.signal,
|
|
73655
|
+
});
|
|
73656
|
+
if (response.status === 401) { handleUnauthorized(); return; }
|
|
73657
|
+
if (!response.ok || response.body === null) { throw new Error('HTTP ' + String(response.status)); }
|
|
73658
|
+
streamState('stream: live');
|
|
73659
|
+
var reader = response.body.getReader();
|
|
73660
|
+
var decoder = new TextDecoder();
|
|
73661
|
+
var buffer = '';
|
|
73662
|
+
for (;;) {
|
|
73663
|
+
var chunk = await reader.read();
|
|
73664
|
+
if (chunk.done) { break; }
|
|
73665
|
+
buffer += decoder.decode(chunk.value, { stream: true });
|
|
73666
|
+
var parsed = parseSseFrames(buffer);
|
|
73667
|
+
buffer = parsed.rest;
|
|
73668
|
+
for (var i = 0; i < parsed.frames.length; i++) {
|
|
73669
|
+
var frame = parsed.frames[i];
|
|
73670
|
+
if (frame.event !== 'message') { continue; }
|
|
73671
|
+
var event;
|
|
73672
|
+
try { event = JSON.parse(frame.data).json; } catch (e) { continue; }
|
|
73673
|
+
if (event === undefined || event.source === undefined) { continue; }
|
|
73674
|
+
renderEvent(event, sequenceGap(tracker, event));
|
|
73675
|
+
}
|
|
73676
|
+
}
|
|
73677
|
+
} catch (error) {
|
|
73678
|
+
if (feedAbort !== null && feedAbort.signal.aborted) { return; }
|
|
73679
|
+
}
|
|
73680
|
+
streamState('stream: dropped, reconnecting');
|
|
73681
|
+
await new Promise(function (resolve) { window.setTimeout(resolve, 1000); });
|
|
73682
|
+
}
|
|
73683
|
+
}
|
|
73684
|
+
|
|
73685
|
+
function showTokenForm(message) {
|
|
73686
|
+
if (feedAbort !== null) { feedAbort.abort(); }
|
|
73687
|
+
if (ui !== null) { ui.main.classList.add('hidden'); }
|
|
73688
|
+
var form = document.getElementById('token-form');
|
|
73689
|
+
form.classList.remove('hidden');
|
|
73690
|
+
document.getElementById('token-error').textContent = message === undefined ? '' : message;
|
|
73691
|
+
document.getElementById('token-input').focus();
|
|
73692
|
+
}
|
|
73693
|
+
|
|
73694
|
+
function startPage(heldToken) {
|
|
73695
|
+
token = heldToken;
|
|
73696
|
+
ui = {
|
|
73697
|
+
main: document.getElementById('main'),
|
|
73698
|
+
eventList: document.getElementById('event-list'),
|
|
73699
|
+
sessionList: document.getElementById('session-list'),
|
|
73700
|
+
pendingList: document.getElementById('pending-list'),
|
|
73701
|
+
prompt: document.getElementById('prompt'),
|
|
73702
|
+
promptTarget: document.getElementById('prompt-target'),
|
|
73703
|
+
send: document.getElementById('send'),
|
|
73704
|
+
streamState: document.getElementById('stream-state'),
|
|
73705
|
+
selected: null,
|
|
73706
|
+
};
|
|
73707
|
+
document.getElementById('token-form').classList.add('hidden');
|
|
73708
|
+
ui.main.classList.remove('hidden');
|
|
73709
|
+
document.getElementById('refresh').addEventListener('click', function () { refreshSessions(); refreshPending(); });
|
|
73710
|
+
document.getElementById('send').addEventListener('click', sendPrompt);
|
|
73711
|
+
document.getElementById('source-filter').addEventListener('change', function () { runFeed(); });
|
|
73712
|
+
ui.prompt.addEventListener('keydown', function (event) {
|
|
73713
|
+
if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) { sendPrompt(); }
|
|
73714
|
+
});
|
|
73715
|
+
refreshSessions();
|
|
73716
|
+
refreshPending();
|
|
73717
|
+
window.setInterval(function () { refreshSessions(); refreshPending(); }, 4000);
|
|
73718
|
+
runFeed();
|
|
73719
|
+
}
|
|
73720
|
+
|
|
73721
|
+
function boot() {
|
|
73722
|
+
var held = null;
|
|
73723
|
+
var query = new URLSearchParams(window.location.search);
|
|
73724
|
+
var fromQuery = query.get('token');
|
|
73725
|
+
if (fromQuery !== null && fromQuery !== '') {
|
|
73726
|
+
window.sessionStorage.setItem(TOKEN_KEY, fromQuery);
|
|
73727
|
+
// The token leaves the address bar the moment the page holds it, so a refresh or a shared screen shows the clean URL; sessionStorage keeps the tab working.
|
|
73728
|
+
window.history.replaceState(null, '', window.location.pathname);
|
|
73729
|
+
held = fromQuery;
|
|
73730
|
+
} else {
|
|
73731
|
+
held = window.sessionStorage.getItem(TOKEN_KEY);
|
|
73732
|
+
}
|
|
73733
|
+
document.getElementById('token-save').addEventListener('click', function () {
|
|
73734
|
+
var value = document.getElementById('token-input').value.trim();
|
|
73735
|
+
if (value === '') { return; }
|
|
73736
|
+
window.sessionStorage.setItem(TOKEN_KEY, value);
|
|
73737
|
+
startPage(value);
|
|
73738
|
+
});
|
|
73739
|
+
document.getElementById('token-input').addEventListener('keydown', function (event) {
|
|
73740
|
+
if (event.key === 'Enter') { document.getElementById('token-save').click(); }
|
|
73741
|
+
});
|
|
73742
|
+
if (held !== null && held !== '') { startPage(held); }
|
|
73743
|
+
}
|
|
73744
|
+
|
|
73745
|
+
if (typeof document !== 'undefined' && document.getElementById('event-list') !== null) {
|
|
73746
|
+
window.addEventListener('DOMContentLoaded', boot);
|
|
73747
|
+
}
|
|
73748
|
+
`;
|
|
73749
|
+
var RC_CLIENT_PAGE_HTML = `<!doctype html>
|
|
73750
|
+
<html lang="en">
|
|
73751
|
+
<head>
|
|
73752
|
+
<meta charset="utf-8">
|
|
73753
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
73754
|
+
<title>agent-shim Remote Control</title>
|
|
73755
|
+
<style>
|
|
73756
|
+
:root { color-scheme: dark; }
|
|
73757
|
+
* { box-sizing: border-box; }
|
|
73758
|
+
body { margin: 0; background: #101418; color: #d7dde3; font: 14px/1.45 ui-monospace, Menlo, Consolas, monospace; }
|
|
73759
|
+
header { display: flex; gap: 12px; align-items: baseline; padding: 10px 16px; background: #171d24; border-bottom: 1px solid #2a333d; }
|
|
73760
|
+
header h1 { font-size: 15px; margin: 0; font-weight: 600; }
|
|
73761
|
+
header .state { color: #8b98a5; }
|
|
73762
|
+
main { display: flex; gap: 1px; background: #2a333d; min-height: calc(100vh - 39px); }
|
|
73763
|
+
section { background: #101418; padding: 12px 16px; overflow-y: auto; }
|
|
73764
|
+
#sessions { flex: 0 0 320px; border-right: 1px solid #2a333d; }
|
|
73765
|
+
#right { flex: 1; display: flex; flex-direction: column; min-width: 0; }
|
|
73766
|
+
#feed { flex: 1; }
|
|
73767
|
+
#controls { border-top: 1px solid #2a333d; }
|
|
73768
|
+
h2 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: #8b98a5; margin: 8px 0 8px; font-weight: 600; }
|
|
73769
|
+
.session { padding: 6px 8px; border: 1px solid transparent; border-radius: 4px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
73770
|
+
.session:hover { background: #171d24; }
|
|
73771
|
+
.session.selected { border-color: #3d6ea5; background: #17222e; }
|
|
73772
|
+
.session .dim { color: #8b98a5; }
|
|
73773
|
+
.event { padding: 2px 0; white-space: pre-wrap; word-break: break-word; }
|
|
73774
|
+
.event .dim { color: #8b98a5; }
|
|
73775
|
+
.event.gap { color: #d29922; }
|
|
73776
|
+
.event.error { color: #e5534b; }
|
|
73777
|
+
textarea, input[type=text], select { background: #171d24; color: #d7dde3; border: 1px solid #2a333d; border-radius: 4px; padding: 6px 8px; font: inherit; width: 100%; }
|
|
73778
|
+
textarea { resize: vertical; min-height: 44px; }
|
|
73779
|
+
button { background: #1f4a7a; color: #d7dde3; border: 1px solid #3d6ea5; border-radius: 4px; padding: 5px 12px; font: inherit; cursor: pointer; }
|
|
73780
|
+
button.secondary { background: #2a333d; border-color: #3a444f; }
|
|
73781
|
+
button:disabled { opacity: 0.5; cursor: default; }
|
|
73782
|
+
.row { display: flex; gap: 8px; margin: 6px 0; align-items: center; }
|
|
73783
|
+
.card { border: 1px solid #3d6ea5; border-radius: 4px; padding: 8px; margin: 6px 0; background: #17222e; }
|
|
73784
|
+
.card .dim { color: #8b98a5; }
|
|
73785
|
+
#token-form { max-width: 480px; margin: 48px auto; }
|
|
73786
|
+
#token-form p { color: #8b98a5; }
|
|
73787
|
+
.hidden { display: none !important; }
|
|
73788
|
+
</style>
|
|
73789
|
+
</head>
|
|
73790
|
+
<body data-agent-shim-rc-client>
|
|
73791
|
+
<header>
|
|
73792
|
+
<h1>agent-shim Remote Control</h1>
|
|
73793
|
+
<span class="state" id="door-state">not connected</span>
|
|
73794
|
+
<span class="state" id="stream-state"></span>
|
|
73795
|
+
</header>
|
|
73796
|
+
<div id="token-form">
|
|
73797
|
+
<h2>This door's control token</h2>
|
|
73798
|
+
<p>The page is served behind the door's per-generation control token. Paste this door generation's token (the owner-only value the door writes beside its state) to use the page; it stays in this tab only.</p>
|
|
73799
|
+
<div class="row"><input type="text" id="token-input" placeholder="control token" autocomplete="off"><button id="token-save">Use</button></div>
|
|
73800
|
+
<p id="token-error" class="event error"></p>
|
|
73801
|
+
</div>
|
|
73802
|
+
<main class="hidden" id="main">
|
|
73803
|
+
<section id="sessions">
|
|
73804
|
+
<h2>Sessions <button class="secondary" id="refresh">Refresh</button></h2>
|
|
73805
|
+
<div id="session-list"></div>
|
|
73806
|
+
</section>
|
|
73807
|
+
<section id="right">
|
|
73808
|
+
<div id="feed">
|
|
73809
|
+
<h2>Feed <select id="source-filter"><option value="">all sources</option><option value="rc">Remote Control only</option></select></h2>
|
|
73810
|
+
<div id="event-list"></div>
|
|
73811
|
+
</div>
|
|
73812
|
+
<div id="controls">
|
|
73813
|
+
<h2>Pending approvals</h2>
|
|
73814
|
+
<div id="pending-list"></div>
|
|
73815
|
+
<h2>Send a prompt</h2>
|
|
73816
|
+
<div class="row"><textarea id="prompt" placeholder="Prompt for the selected session"></textarea></div>
|
|
73817
|
+
<div class="row"><span class="dim" id="prompt-target">no session selected</span><span style="flex:1"></span><button id="send">Send</button></div>
|
|
73818
|
+
</div>
|
|
73819
|
+
</section>
|
|
73820
|
+
</main>
|
|
73821
|
+
<script>
|
|
73822
|
+
${RC_CLIENT_PAGE_SCRIPT}
|
|
73823
|
+
</script>
|
|
73824
|
+
</body>
|
|
73825
|
+
</html>
|
|
73826
|
+
`;
|
|
73827
|
+
function pageTokenOf(request7, url2) {
|
|
73828
|
+
const presented = request7.headers.authorization;
|
|
73829
|
+
const bearerPrefix = "bearer ".length;
|
|
73830
|
+
const header = typeof presented === "string" && presented.slice(0, bearerPrefix).toLowerCase() === "bearer " ? presented.slice(bearerPrefix) : void 0;
|
|
73831
|
+
const query = url2.searchParams.get("token") ?? void 0;
|
|
73832
|
+
return header ?? query;
|
|
73833
|
+
}
|
|
73834
|
+
function serveRcClientPage(expectedToken, request7, response) {
|
|
73835
|
+
const url2 = new URL(request7.url ?? "/", "https://door.invalid");
|
|
73836
|
+
if (url2.pathname !== RC_CLIENT_PATH && url2.pathname !== `${RC_CLIENT_PATH}/`) {
|
|
73837
|
+
response.writeHead(HTTP_STATUS.notFound, { "Content-Type": "text/plain" });
|
|
73838
|
+
response.end("no such page under the door's client prefix");
|
|
73839
|
+
return;
|
|
73840
|
+
}
|
|
73841
|
+
if (request7.method !== "GET" && request7.method !== "HEAD") {
|
|
73842
|
+
response.writeHead(HTTP_STATUS.methodNotAllowed, { Allow: "GET, HEAD", "Content-Type": "text/plain" });
|
|
73843
|
+
response.end("the door's web client page is read-only");
|
|
73844
|
+
return;
|
|
73845
|
+
}
|
|
73846
|
+
const token = pageTokenOf(request7, url2);
|
|
73847
|
+
if (token === void 0 || !isLiveCapability(token, [expectedToken])) {
|
|
73848
|
+
response.writeHead(HTTP_STATUS.unauthorized, { "Content-Type": "application/json" });
|
|
73849
|
+
response.end(JSON.stringify({ error: "the door's web client demands this generation's control token, as a Bearer credential or the token query parameter" }));
|
|
73850
|
+
return;
|
|
73851
|
+
}
|
|
73852
|
+
response.writeHead(HTTP_STATUS.ok, {
|
|
73853
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
73854
|
+
"Cache-Control": "no-store",
|
|
73855
|
+
"Referrer-Policy": "no-referrer",
|
|
73856
|
+
"Content-Security-Policy": "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'"
|
|
73857
|
+
});
|
|
73858
|
+
response.end(request7.method === "HEAD" ? void 0 : RC_CLIENT_PAGE_HTML);
|
|
73859
|
+
}
|
|
73860
|
+
function createRcClientPage(expectedToken) {
|
|
73861
|
+
return {
|
|
73862
|
+
pathPrefix: RC_CLIENT_PATH,
|
|
73863
|
+
handle: async (request7, response) => {
|
|
73864
|
+
serveRcClientPage(expectedToken, request7, response);
|
|
73865
|
+
await Promise.resolve();
|
|
73866
|
+
return { matched: true };
|
|
73867
|
+
}
|
|
73868
|
+
};
|
|
73869
|
+
}
|
|
73870
|
+
|
|
72692
73871
|
// src/frontdoor/rcSelfHost.ts
|
|
72693
73872
|
var RC_SELF_HOST_ENV = "AGENT_SHIM_FRONTDOOR_RC_SELF_HOST";
|
|
72694
73873
|
function rcSelfHostFromEnv(env) {
|
|
@@ -72701,7 +73880,7 @@ var RC_SESSION_ID_PREFIX2 = "cse_";
|
|
|
72701
73880
|
var RC_SELF_HOST_API_BASE_URL = "https://api.anthropic.com";
|
|
72702
73881
|
var RC_SELF_HOST_OAUTH_HOST = "platform.claude.com";
|
|
72703
73882
|
var HTTP_CONFLICT = 409;
|
|
72704
|
-
var
|
|
73883
|
+
var MS_PER_SECOND7 = 1e3;
|
|
72705
73884
|
var HTTP_SERVICE_UNAVAILABLE = 503;
|
|
72706
73885
|
var RC_SELF_HOST_WORKER_JWT_TTL_SECONDS = 46800;
|
|
72707
73886
|
var RC_SELF_HOST_OAUTH_TOKEN_TTL_SECONDS = 3600;
|
|
@@ -72776,7 +73955,7 @@ function parseJsonObject2(body) {
|
|
|
72776
73955
|
function mintWorkerJwt(randomToken, issuedAt) {
|
|
72777
73956
|
const encode3 = (value2) => Buffer.from(JSON.stringify(value2), "utf8").toString("base64url");
|
|
72778
73957
|
const header = encode3({ alg: "HS256", typ: "JWT" });
|
|
72779
|
-
const payload = encode3({ exp: Math.floor((issuedAt + RC_SELF_HOST_WORKER_JWT_TTL_SECONDS *
|
|
73958
|
+
const payload = encode3({ exp: Math.floor((issuedAt + RC_SELF_HOST_WORKER_JWT_TTL_SECONDS * MS_PER_SECOND7) / MS_PER_SECOND7), iat: Math.floor(issuedAt / MS_PER_SECOND7) });
|
|
72780
73959
|
return `${header}.${payload}.${Buffer.from(randomToken(), "utf8").toString("base64url")}`;
|
|
72781
73960
|
}
|
|
72782
73961
|
function growthBookFeatures() {
|
|
@@ -73227,7 +74406,7 @@ data: ${JSON.stringify(envelope)}
|
|
|
73227
74406
|
}
|
|
73228
74407
|
if (method === "POST" && pathname.startsWith("/api/eval/")) {
|
|
73229
74408
|
await readBody3(request7, CONTROL_BODY_CAP_BYTES);
|
|
73230
|
-
answerServerJson(response, HTTP_STATUS.ok, { features: growthBookFeatures(), dateUpdated: Math.floor(deps.now() /
|
|
74409
|
+
answerServerJson(response, HTTP_STATUS.ok, { features: growthBookFeatures(), dateUpdated: Math.floor(deps.now() / MS_PER_SECOND7) });
|
|
73231
74410
|
return true;
|
|
73232
74411
|
}
|
|
73233
74412
|
if (method === "GET" && pathname === "/api/oauth/profile") {
|
|
@@ -73715,7 +74894,7 @@ var ProviderQuotaError = class extends Error {
|
|
|
73715
74894
|
this.name = "ProviderQuotaError";
|
|
73716
74895
|
}
|
|
73717
74896
|
};
|
|
73718
|
-
var
|
|
74897
|
+
var MS_PER_SECOND8 = 1e3;
|
|
73719
74898
|
var SECONDS_PER_HOUR = 3600;
|
|
73720
74899
|
var HOURS_PER_DAY3 = 24;
|
|
73721
74900
|
var DAYS_PER_MONTH = 30;
|
|
@@ -73727,8 +74906,8 @@ var ZAI_QUOTA_URL = `https://${ZAI_HOST}/api/monitor/usage/quota/limit`;
|
|
|
73727
74906
|
var ZAI_UNIT_HOURS = 3;
|
|
73728
74907
|
var ZAI_UNIT_MONTHS = 5;
|
|
73729
74908
|
var ZAI_UNIT_MS = /* @__PURE__ */ new Map([
|
|
73730
|
-
[ZAI_UNIT_HOURS, SECONDS_PER_HOUR *
|
|
73731
|
-
[ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY3 * SECONDS_PER_HOUR *
|
|
74909
|
+
[ZAI_UNIT_HOURS, SECONDS_PER_HOUR * MS_PER_SECOND8],
|
|
74910
|
+
[ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND8]
|
|
73732
74911
|
]);
|
|
73733
74912
|
var ZAI_MEASURES = { TOKENS_LIMIT: "tokens", TIME_LIMIT: "tool-calls" };
|
|
73734
74913
|
var ZaiLimitSchema = external_exports.object({
|
|
@@ -73761,8 +74940,8 @@ function zaiWindow(limit) {
|
|
|
73761
74940
|
var zaiQuotaAdapter = {
|
|
73762
74941
|
source: ZAI_SOURCE,
|
|
73763
74942
|
matches: (baseUrl) => URL.canParse(baseUrl) && new URL(baseUrl).hostname === ZAI_HOST,
|
|
73764
|
-
fetch: async (apiKey,
|
|
73765
|
-
const response = await
|
|
74943
|
+
fetch: async (apiKey, http7, signal, nowMs) => {
|
|
74944
|
+
const response = await http7(ZAI_QUOTA_URL, { authorization: apiKey, accept: "application/json" }, signal);
|
|
73766
74945
|
if (response.status !== HTTP_OK) {
|
|
73767
74946
|
throw new ProviderQuotaError(ZAI_SOURCE, `answered HTTP ${String(response.status)}`);
|
|
73768
74947
|
}
|
|
@@ -73792,7 +74971,7 @@ var OPENROUTER_HOST = "openrouter.ai";
|
|
|
73792
74971
|
var OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
|
|
73793
74972
|
var OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
|
|
73794
74973
|
var HTTP_FORBIDDEN = 403;
|
|
73795
|
-
var MS_PER_DAY2 = HOURS_PER_DAY3 * SECONDS_PER_HOUR *
|
|
74974
|
+
var MS_PER_DAY2 = HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND8;
|
|
73796
74975
|
var OpenRouterKeySchema = external_exports.object({
|
|
73797
74976
|
data: external_exports.object({
|
|
73798
74977
|
limit: external_exports.number().nonnegative().nullable(),
|
|
@@ -73803,8 +74982,8 @@ var OpenRouterKeySchema = external_exports.object({
|
|
|
73803
74982
|
})
|
|
73804
74983
|
});
|
|
73805
74984
|
var OpenRouterCreditsSchema = external_exports.object({ data: external_exports.object({ total_credits: external_exports.number().nonnegative(), total_usage: external_exports.number().nonnegative() }) });
|
|
73806
|
-
async function openRouterGet(url2, schema, apiKey,
|
|
73807
|
-
const response = await
|
|
74985
|
+
async function openRouterGet(url2, schema, apiKey, http7, signal) {
|
|
74986
|
+
const response = await http7(url2, { authorization: `Bearer ${apiKey}`, accept: "application/json" }, signal);
|
|
73808
74987
|
if (response.status === HTTP_FORBIDDEN) {
|
|
73809
74988
|
return "forbidden";
|
|
73810
74989
|
}
|
|
@@ -73829,12 +75008,12 @@ function nextUtcMidnight(nowMs) {
|
|
|
73829
75008
|
var openRouterQuotaAdapter = {
|
|
73830
75009
|
source: OPENROUTER_SOURCE,
|
|
73831
75010
|
matches: (baseUrl) => URL.canParse(baseUrl) && new URL(baseUrl).hostname === OPENROUTER_HOST,
|
|
73832
|
-
fetch: async (apiKey,
|
|
73833
|
-
const key = await openRouterGet(OPENROUTER_KEY_URL, OpenRouterKeySchema, apiKey,
|
|
75011
|
+
fetch: async (apiKey, http7, signal, nowMs) => {
|
|
75012
|
+
const key = await openRouterGet(OPENROUTER_KEY_URL, OpenRouterKeySchema, apiKey, http7, signal);
|
|
73834
75013
|
if (key === "forbidden") {
|
|
73835
75014
|
throw new ProviderQuotaError(OPENROUTER_SOURCE, "/api/v1/key refused the key (HTTP 403)");
|
|
73836
75015
|
}
|
|
73837
|
-
const credits = await openRouterGet(OPENROUTER_CREDITS_URL, OpenRouterCreditsSchema, apiKey,
|
|
75016
|
+
const credits = await openRouterGet(OPENROUTER_CREDITS_URL, OpenRouterCreditsSchema, apiKey, http7, signal);
|
|
73838
75017
|
const { limit, limit_remaining: limitRemaining, limit_reset: limitReset, free_model_daily_requests: free, is_free_tier: isFreeTier } = key.data;
|
|
73839
75018
|
const windows = [];
|
|
73840
75019
|
if (limit !== null && limit > 0) {
|
|
@@ -74010,7 +75189,7 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74010
75189
|
};
|
|
74011
75190
|
let directPort = 0;
|
|
74012
75191
|
const rcSelfHost = rcSelfHostFromEnv(process.env);
|
|
74013
|
-
const codexPorts = createCodexRoutePorts(log);
|
|
75192
|
+
const codexPorts = createCodexRoutePorts(log, paths.chatgptSignInFile);
|
|
74014
75193
|
let ca;
|
|
74015
75194
|
const loadCa = () => {
|
|
74016
75195
|
ca ??= ensureCa(realConnectCertStore(paths), () => generateCa(/* @__PURE__ */ new Date()));
|
|
@@ -74027,14 +75206,15 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74027
75206
|
};
|
|
74028
75207
|
const rcSelfHostSurface = rcSelfHost ? createRcSelfHostSurface({
|
|
74029
75208
|
now: () => Date.now(),
|
|
74030
|
-
newUuid:
|
|
74031
|
-
randomToken: () => (0,
|
|
75209
|
+
newUuid: import_node_crypto14.randomUUID,
|
|
75210
|
+
randomToken: () => (0, import_node_crypto14.randomBytes)(MINTED_TOKEN_RANDOM_BYTES).toString("base64url"),
|
|
74032
75211
|
credentialRecord: () => readRcSelfHostRecord(realFarmFs, paths.frontdoorDir),
|
|
74033
75212
|
log
|
|
74034
75213
|
}) : void 0;
|
|
74035
75214
|
const rcCredentialStore = createRcCredentialStore(realFarmFs, paths.frontdoorRcCredentialsDir);
|
|
74036
75215
|
const rcTracker = createRcSessionTracker({ now: () => Date.now(), idleMs: RC_IDLE_EXPIRY_MS, credentialStore: rcCredentialStore });
|
|
74037
|
-
const
|
|
75216
|
+
const doorEvents = createDoorEventHub();
|
|
75217
|
+
const rcFanout = rcFanoutOnDoorHub(createRcEventFanout(), doorEvents);
|
|
74038
75218
|
const rcHub = createRcStreamHub({
|
|
74039
75219
|
now: () => Date.now(),
|
|
74040
75220
|
credentialOf: rcTracker.credentialOf,
|
|
@@ -74045,7 +75225,7 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74045
75225
|
saveSequenceNum: rcCredentialStore.writeCursor,
|
|
74046
75226
|
dial: rcSelfHost ? lateRcStreamDial(rcSelfHostDialTarget) : realRcStreamDial(),
|
|
74047
75227
|
fanout: rcFanout,
|
|
74048
|
-
newClientId:
|
|
75228
|
+
newClientId: import_node_crypto14.randomUUID,
|
|
74049
75229
|
backoffMs: RC_STREAM_BACKOFF_MS,
|
|
74050
75230
|
sleep: async (ms) => {
|
|
74051
75231
|
await new Promise((resolve) => {
|
|
@@ -74056,7 +75236,7 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74056
75236
|
appendLog(paths, `frontdoor ${String(process.pid)}: ${line}`);
|
|
74057
75237
|
}
|
|
74058
75238
|
});
|
|
74059
|
-
const rcControlToken = (0,
|
|
75239
|
+
const rcControlToken = (0, import_node_crypto14.randomUUID)();
|
|
74060
75240
|
const resolveRoute = rcObservingResolver(
|
|
74061
75241
|
createProviderRouteResolver({ fs: realFsPort, providersDir: paths.providersDir, codexPorts, directPort: () => directPort, ...rcSelfHostSurface === void 0 ? {} : { rcSelfHostRoute: rcSelfHostSurface.route } }),
|
|
74062
75242
|
rcTracker,
|
|
@@ -74087,8 +75267,8 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74087
75267
|
now: () => Date.now(),
|
|
74088
75268
|
headroomSocket: () => headroomSocketTarget(realFarmFs, realHeadroomSocketTrust, paths),
|
|
74089
75269
|
// The per-generation capability the direct listener demands: held only in this process's memory, so a loopback process that discovers the direct port still cannot use it.
|
|
74090
|
-
hopSecret: (0,
|
|
74091
|
-
custody: createCredentialCustody(() => (0,
|
|
75270
|
+
hopSecret: (0, import_node_crypto14.randomUUID)(),
|
|
75271
|
+
custody: createCredentialCustody(() => (0, import_node_crypto14.randomUUID)()),
|
|
74092
75272
|
log
|
|
74093
75273
|
});
|
|
74094
75274
|
const onListenerError = (name) => (error62) => {
|
|
@@ -74109,9 +75289,9 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74109
75289
|
startProviderListener: async (preferredPort) => {
|
|
74110
75290
|
const authority = loadCa();
|
|
74111
75291
|
const rcDial = rcSelfHost ? lateRcEventDial(rcSelfHostDialTarget) : realRcEventDial();
|
|
74112
|
-
const rcInject = async (sessionId, text2) => await injectRcUserMessage({ credentialOf: rcTracker.credentialOf, noteSequenceNums: rcTracker.noteSequenceNums, dial: rcDial, newUuid:
|
|
75292
|
+
const rcInject = async (sessionId, text2) => await injectRcUserMessage({ credentialOf: rcTracker.credentialOf, noteSequenceNums: rcTracker.noteSequenceNums, dial: rcDial, newUuid: import_node_crypto14.randomUUID }, sessionId, text2);
|
|
74113
75293
|
const rcAnswer = async (sessionId, requestId, decision) => await answerRcControlRequest({ credentialOf: rcTracker.credentialOf, pendingOf: (id) => rcTracker.pendingOf(id), completePending: rcTracker.completePending, noteSequenceNums: rcTracker.noteSequenceNums, dial: rcDial }, sessionId, requestId, decision);
|
|
74114
|
-
const rcControlRequestDeps = { credentialOf: rcTracker.credentialOf, noteSequenceNums: rcTracker.noteSequenceNums, dial: rcDial, newUuid:
|
|
75294
|
+
const rcControlRequestDeps = { credentialOf: rcTracker.credentialOf, noteSequenceNums: rcTracker.noteSequenceNums, dial: rcDial, newUuid: import_node_crypto14.randomUUID };
|
|
74115
75295
|
const rcInterrupt = async (sessionId) => await interruptRcSession(rcControlRequestDeps, sessionId);
|
|
74116
75296
|
const rcSetModel = async (sessionId, model) => await setRcSessionModel(rcControlRequestDeps, sessionId, model);
|
|
74117
75297
|
const rcSetPermissionMode = async (sessionId, mode) => await setRcSessionPermissionMode(rcControlRequestDeps, sessionId, mode);
|
|
@@ -74133,19 +75313,24 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74133
75313
|
log,
|
|
74134
75314
|
mintLeaf(authority, LOOPBACK_LEAF_NAMES, /* @__PURE__ */ new Date()),
|
|
74135
75315
|
createRcControlHandler({ expectedToken: rcControlToken, list: rcTracker.list, statusOf: rcTracker.statusOf, pendingOf: rcTracker.pendingOf, inject: rcInject, answer: rcAnswer, interrupt: rcInterrupt, setModel: rcSetModel, setPermissionMode: rcSetPermissionMode }),
|
|
74136
|
-
|
|
74137
|
-
|
|
74138
|
-
|
|
74139
|
-
|
|
74140
|
-
|
|
74141
|
-
|
|
74142
|
-
|
|
74143
|
-
|
|
74144
|
-
|
|
74145
|
-
|
|
74146
|
-
|
|
74147
|
-
|
|
74148
|
-
|
|
75316
|
+
[
|
|
75317
|
+
createDoorApiNodeHandler({
|
|
75318
|
+
expectedToken: rcControlToken,
|
|
75319
|
+
list: rcTracker.list,
|
|
75320
|
+
statusOf: rcTracker.statusOf,
|
|
75321
|
+
pendingOf: rcTracker.pendingOf,
|
|
75322
|
+
inject: rcInject,
|
|
75323
|
+
answer: rcAnswer,
|
|
75324
|
+
interrupt: rcInterrupt,
|
|
75325
|
+
setModel: rcSetModel,
|
|
75326
|
+
setPermissionMode: rcSetPermissionMode,
|
|
75327
|
+
fanout: rcFanout,
|
|
75328
|
+
...controlDeps,
|
|
75329
|
+
events: doorEvents
|
|
75330
|
+
}),
|
|
75331
|
+
// The self-hosted web client rides the same listener under the same per-generation token as the typed API it speaks: no extra process, no new trust surface.
|
|
75332
|
+
createRcClientPage(rcControlToken)
|
|
75333
|
+
]
|
|
74149
75334
|
);
|
|
74150
75335
|
const handle = await listenFrontDoor(server, { ...preferredPort === void 0 ? {} : { preferredPort }, ca: authority.certPem, onError: onListenerError("provider") });
|
|
74151
75336
|
return {
|
|
@@ -74158,7 +75343,7 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74158
75343
|
},
|
|
74159
75344
|
startConnectListener: async (preferredPort) => {
|
|
74160
75345
|
const wantedTransparentPort = process.env.AGENT_SHIM_TRANSPARENT_SURFACE === void 0 ? void 0 : Number(process.env.AGENT_SHIM_TRANSPARENT_SURFACE);
|
|
74161
|
-
const transparentCapability = wantedTransparentPort === void 0 || Number.isNaN(wantedTransparentPort) ? void 0 : (0,
|
|
75346
|
+
const transparentCapability = wantedTransparentPort === void 0 || Number.isNaN(wantedTransparentPort) ? void 0 : (0, import_node_crypto14.randomUUID)();
|
|
74162
75347
|
if (transparentCapability !== void 0) {
|
|
74163
75348
|
writeFrontDoorSession(realFarmFs, paths.frontdoorSessionsDir, { pid: process.pid, startedAt: Date.now(), token: transparentCapability });
|
|
74164
75349
|
}
|
|
@@ -74231,6 +75416,8 @@ function realFrontDoorSupervisorPorts(paths) {
|
|
|
74231
75416
|
return { port: handle.port, close: handle.close };
|
|
74232
75417
|
},
|
|
74233
75418
|
closeRcStreamHub: rcHub.close,
|
|
75419
|
+
// The launch lifecycle publisher over the same backbone the typed API serves: the tick's registry facts go in here, and the door's own register, prune and end moments come out as source-tagged events.
|
|
75420
|
+
observeLaunchRegistry: createLaunchEventPublisher(doorEvents, () => Date.now()).observe,
|
|
74234
75421
|
log: (line) => {
|
|
74235
75422
|
appendLog(paths, line);
|
|
74236
75423
|
}
|
|
@@ -74501,8 +75688,8 @@ function registerFrontDoorCommand(program2, deps) {
|
|
|
74501
75688
|
identitiesDir: paths.identitiesDir,
|
|
74502
75689
|
frontdoorDir: paths.frontdoorDir,
|
|
74503
75690
|
identity,
|
|
74504
|
-
newUuid:
|
|
74505
|
-
randomToken: () => (0,
|
|
75691
|
+
newUuid: import_node_crypto14.randomUUID,
|
|
75692
|
+
randomToken: () => (0, import_node_crypto14.randomBytes)(MINTED_TOKEN_RANDOM_BYTES).toString("base64url"),
|
|
74506
75693
|
force: options.force === true,
|
|
74507
75694
|
now: () => Date.now()
|
|
74508
75695
|
});
|
|
@@ -74816,7 +76003,7 @@ function registerCompletionCommand(program2) {
|
|
|
74816
76003
|
}
|
|
74817
76004
|
|
|
74818
76005
|
// src/credentialCommand.ts
|
|
74819
|
-
var
|
|
76006
|
+
var import_node_child_process5 = require("node:child_process");
|
|
74820
76007
|
|
|
74821
76008
|
// src/identityToken.ts
|
|
74822
76009
|
var import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
@@ -74868,7 +76055,7 @@ function realCommandPorts(deps) {
|
|
|
74868
76055
|
cache: createRealCredentialCache(deps.paths.root),
|
|
74869
76056
|
platform: process.platform,
|
|
74870
76057
|
now: () => Date.now(),
|
|
74871
|
-
ssh: (host, remoteCommand, input2) => (0,
|
|
76058
|
+
ssh: (host, remoteCommand, input2) => (0, import_node_child_process5.spawnSync)("ssh", ["--", host, remoteCommand], { input: input2, stdio: ["pipe", "inherit", "inherit"] }).status
|
|
74872
76059
|
};
|
|
74873
76060
|
}
|
|
74874
76061
|
var REMOTE_ROOT_SCRIPT = 'root="${AGENT_SHIM_HOME:-${CLAUDE_USE_HOME:-}}"; if [ -z "$root" ]; then if [ ! -d "$HOME/.agent-shim" ] && [ -d "$HOME/.claude-use" ]; then root="$HOME/.claude-use"; else root="$HOME/.agent-shim"; fi; fi';
|
|
@@ -74999,15 +76186,15 @@ function registerDoctorCommand(program2, deps) {
|
|
|
74999
76186
|
|
|
75000
76187
|
// src/headroom/commands.ts
|
|
75001
76188
|
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
75002
|
-
var
|
|
76189
|
+
var import_node_http3 = __toESM(require("node:http"), 1);
|
|
75003
76190
|
var import_node_path39 = __toESM(require("node:path"), 1);
|
|
75004
|
-
var
|
|
76191
|
+
var import_node_child_process6 = require("node:child_process");
|
|
75005
76192
|
|
|
75006
76193
|
// src/frontdoor/realFrontDoorPort.ts
|
|
75007
76194
|
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
75008
76195
|
|
|
75009
76196
|
// src/frontdoor/ensure.ts
|
|
75010
|
-
var
|
|
76197
|
+
var import_node_crypto15 = require("node:crypto");
|
|
75011
76198
|
var FRONTDOOR_START_TIMEOUT_MS = 3e4;
|
|
75012
76199
|
var FRONTDOOR_LAUNCHER_POLL_MS = 100;
|
|
75013
76200
|
var FrontDoorStartError = class extends CliError {
|
|
@@ -75041,7 +76228,7 @@ function ensureFrontDoor(params) {
|
|
|
75041
76228
|
continue;
|
|
75042
76229
|
}
|
|
75043
76230
|
if (verdict.ok) {
|
|
75044
|
-
const token = (0,
|
|
76231
|
+
const token = (0, import_node_crypto15.randomUUID)();
|
|
75045
76232
|
writeFrontDoorSession(ports.fs, paths.frontdoorSessionsDir, { pid: params.launcherPid, startedAt: ports.now(), token });
|
|
75046
76233
|
return { port: state.port, connectPort: state.connectPort, token };
|
|
75047
76234
|
}
|
|
@@ -75145,7 +76332,7 @@ function probeFrontDoorSync(port, caPem) {
|
|
|
75145
76332
|
}
|
|
75146
76333
|
|
|
75147
76334
|
// src/frontdoor/trust.ts
|
|
75148
|
-
var
|
|
76335
|
+
var import_node_crypto16 = require("node:crypto");
|
|
75149
76336
|
var import_node_path38 = __toESM(require("node:path"), 1);
|
|
75150
76337
|
var BUNDLE_NAME_HEX_DIGITS = 16;
|
|
75151
76338
|
function resolveTrustBundle(params) {
|
|
@@ -75168,7 +76355,7 @@ function resolveTrustBundle(params) {
|
|
|
75168
76355
|
}
|
|
75169
76356
|
const combined = `${inheritedPem.trimEnd()}
|
|
75170
76357
|
${caPem}`;
|
|
75171
|
-
const bundle = import_node_path38.default.join(bundlesDir, `${(0,
|
|
76358
|
+
const bundle = import_node_path38.default.join(bundlesDir, `${(0, import_node_crypto16.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
|
|
75172
76359
|
if (!fs19.exists(bundle)) {
|
|
75173
76360
|
fs19.mkdirp(bundlesDir);
|
|
75174
76361
|
fs19.writeFileAtomic(bundle, combined);
|
|
@@ -75308,7 +76495,7 @@ function headroomProxyArgs(socketPath, settings2) {
|
|
|
75308
76495
|
}
|
|
75309
76496
|
async function readyOverSocket(socketPath) {
|
|
75310
76497
|
return await new Promise((resolve) => {
|
|
75311
|
-
const probe =
|
|
76498
|
+
const probe = import_node_http3.default.get({ socketPath, path: "/readyz", timeout: READY_FETCH_TIMEOUT_MS }, (response) => {
|
|
75312
76499
|
response.resume();
|
|
75313
76500
|
resolve(response.statusCode === HTTP_STATUS.ok);
|
|
75314
76501
|
});
|
|
@@ -75322,7 +76509,7 @@ async function readyOverSocket(socketPath) {
|
|
|
75322
76509
|
}
|
|
75323
76510
|
var HEADROOM_TOOL_NAME = "headroom-ai";
|
|
75324
76511
|
function readInstalledHeadroomCommit() {
|
|
75325
|
-
const toolDir = (0,
|
|
76512
|
+
const toolDir = (0, import_node_child_process6.spawnSync)("uv", ["tool", "dir"], { encoding: "utf8" });
|
|
75326
76513
|
if (toolDir.status !== 0) {
|
|
75327
76514
|
return void 0;
|
|
75328
76515
|
}
|
|
@@ -75362,7 +76549,7 @@ function realSupervisorPorts(paths) {
|
|
|
75362
76549
|
}
|
|
75363
76550
|
const logFd = import_node_fs16.default.openSync(paths.headroomLogPath, "a");
|
|
75364
76551
|
try {
|
|
75365
|
-
const child = (0,
|
|
76552
|
+
const child = (0, import_node_child_process6.spawn)("headroom", headroomProxyArgs(socketPath, settings2), {
|
|
75366
76553
|
detached: true,
|
|
75367
76554
|
stdio: ["ignore", logFd, logFd],
|
|
75368
76555
|
env: headroomSpawnEnv(process.env, allowlist, settings2, trust?.path)
|
|
@@ -75402,7 +76589,7 @@ function realSupervisorPorts(paths) {
|
|
|
75402
76589
|
},
|
|
75403
76590
|
ready: readyOverSocket,
|
|
75404
76591
|
install: (spec) => {
|
|
75405
|
-
const result = (0,
|
|
76592
|
+
const result = (0, import_node_child_process6.spawnSync)("uv", ["tool", "install", spec], { encoding: "utf8" });
|
|
75406
76593
|
if (result.error !== void 0) {
|
|
75407
76594
|
return { ok: false, error: `uv is not installed or not on PATH (${result.error.message})` };
|
|
75408
76595
|
}
|
|
@@ -75415,7 +76602,7 @@ function realSupervisorPorts(paths) {
|
|
|
75415
76602
|
return result.status === 0 ? { ok: true } : { ok: false, error: `uv tool install exited ${String(result.status)}` };
|
|
75416
76603
|
},
|
|
75417
76604
|
headroomVersion: () => {
|
|
75418
|
-
const result = (0,
|
|
76605
|
+
const result = (0, import_node_child_process6.spawnSync)("headroom", ["--version"], { encoding: "utf8" });
|
|
75419
76606
|
return result.status === 0 ? result.stdout.trim() : void 0;
|
|
75420
76607
|
},
|
|
75421
76608
|
installedCommit: readInstalledHeadroomCommit,
|
|
@@ -75598,13 +76785,14 @@ function toProviderView(name, provider) {
|
|
|
75598
76785
|
};
|
|
75599
76786
|
}
|
|
75600
76787
|
function codexConfigFromOptions(options) {
|
|
75601
|
-
if (options.codexDefaultModel === void 0 && options.codexModel === void 0 && options.codexEffort === void 0) {
|
|
76788
|
+
if (options.codexDefaultModel === void 0 && options.codexModel === void 0 && options.codexEffort === void 0 && options.codexLogin === void 0) {
|
|
75602
76789
|
return void 0;
|
|
75603
76790
|
}
|
|
75604
76791
|
const candidate = {
|
|
75605
76792
|
...options.codexDefaultModel === void 0 ? {} : { defaultModel: options.codexDefaultModel },
|
|
75606
76793
|
...options.codexModel === void 0 ? {} : { models: options.codexModel },
|
|
75607
|
-
...options.codexEffort === void 0 ? {} : { effort: options.codexEffort }
|
|
76794
|
+
...options.codexEffort === void 0 ? {} : { effort: options.codexEffort },
|
|
76795
|
+
...options.codexLogin === void 0 ? {} : { login: options.codexLogin }
|
|
75608
76796
|
};
|
|
75609
76797
|
const parsed = CodexProviderConfigSchema.safeParse(candidate);
|
|
75610
76798
|
if (!parsed.success) {
|
|
@@ -75627,7 +76815,7 @@ function registerProviderCommand(program2, deps) {
|
|
|
75627
76815
|
new Option("--credential-target <target>", "Where the token goes: bearer sets ANTHROPIC_AUTH_TOKEN (default), apiKey sets ANTHROPIC_API_KEY.").choices(
|
|
75628
76816
|
PROVIDER_CREDENTIAL_TARGETS
|
|
75629
76817
|
)
|
|
75630
|
-
).option("--env <KEY=VALUE>", "Extra environment entry for the child (repeatable).", collectStringPair).option("--codex-default-model <model>", "Codex providers: the codex model a request maps to when no tier matches.").option("--codex-model <tier=model>", "Codex providers: the codex model one tier (fable, opus, sonnet or haiku) maps to (repeatable).", collectStringPair).addOption(new Option("--codex-effort <effort>", "Codex providers: the reasoning effort when a request asks for none the backend accepts.").choices(CODEX_EFFORTS)).option("--json", "Print the result as JSON.").action((name, options) => {
|
|
76818
|
+
).option("--env <KEY=VALUE>", "Extra environment entry for the child (repeatable).", collectStringPair).option("--codex-default-model <model>", "Codex providers: the codex model a request maps to when no tier matches.").option("--codex-model <tier=model>", "Codex providers: the codex model one tier (fable, opus, sonnet or haiku) maps to (repeatable).", collectStringPair).addOption(new Option("--codex-effort <effort>", "Codex providers: the reasoning effort when a request asks for none the backend accepts.").choices(CODEX_EFFORTS)).addOption(new Option("--codex-login <login>", "Codex providers: which login the upstream call uses, the Codex CLI's own login or a Sign in with ChatGPT grant from `agent-shim codex login`.").choices(CODEX_LOGINS)).option("--json", "Print the result as JSON.").action((name, options) => {
|
|
75631
76819
|
const codex = codexConfigFromOptions(options);
|
|
75632
76820
|
const created = addProvider(paths, name, {
|
|
75633
76821
|
...options.kind === void 0 ? {} : { kind: options.kind },
|
|
@@ -75659,14 +76847,14 @@ function registerProviderCommand(program2, deps) {
|
|
|
75659
76847
|
new Option("--credential-target <target>", "Where the token goes: bearer sets ANTHROPIC_AUTH_TOKEN, apiKey sets ANTHROPIC_API_KEY.").choices(
|
|
75660
76848
|
PROVIDER_CREDENTIAL_TARGETS
|
|
75661
76849
|
)
|
|
75662
|
-
).option("--env <KEY=VALUE>", "Add or replace an environment entry for the child (repeatable).", collectStringPair).option("--unset-env <KEY>", "Remove an environment entry (repeatable).", collectRepeated).option("--codex-default-model <model>", "Codex providers: replace the model a request maps to when no tier matches.").option("--codex-model <tier=model>", "Codex providers: set the codex model one tier maps to (repeatable; other tiers are kept).", collectStringPair).addOption(new Option("--codex-effort <effort>", "Codex providers: replace the default reasoning effort.").choices(CODEX_EFFORTS));
|
|
76850
|
+
).option("--env <KEY=VALUE>", "Add or replace an environment entry for the child (repeatable).", collectStringPair).option("--unset-env <KEY>", "Remove an environment entry (repeatable).", collectRepeated).option("--codex-default-model <model>", "Codex providers: replace the model a request maps to when no tier matches.").option("--codex-model <tier=model>", "Codex providers: set the codex model one tier maps to (repeatable; other tiers are kept).", collectStringPair).addOption(new Option("--codex-effort <effort>", "Codex providers: replace the default reasoning effort.").choices(CODEX_EFFORTS)).addOption(new Option("--codex-login <login>", "Codex providers: replace which login the upstream call uses.").choices(CODEX_LOGINS));
|
|
75663
76851
|
addCredentialCacheOptions(providerSet);
|
|
75664
76852
|
withExamples(
|
|
75665
76853
|
providerSet.option("--json", "Print the result as JSON.").action((name, allOptions) => {
|
|
75666
76854
|
const { json: json2, ...options } = allOptions;
|
|
75667
76855
|
if (Object.entries(allOptions).every(([key, value2]) => key === "json" || value2 === void 0)) {
|
|
75668
76856
|
throw new UsageError(
|
|
75669
|
-
"Nothing to change: pass --display-name, --base-url, --credential, --credential-target, a --credential-cache option, --env, --unset-env, --codex-default-model, --codex-model or --codex-
|
|
76857
|
+
"Nothing to change: pass --display-name, --base-url, --credential, --credential-target, a --credential-cache option, --env, --unset-env, --codex-default-model, --codex-model, --codex-effort or --codex-login."
|
|
75670
76858
|
);
|
|
75671
76859
|
}
|
|
75672
76860
|
const codex = codexConfigFromOptions(options);
|
|
@@ -75727,6 +76915,7 @@ function registerProviderCommand(program2, deps) {
|
|
|
75727
76915
|
const config2 = resolveCodexConfig(found.codex);
|
|
75728
76916
|
console.log(`Codex models: ${CODEX_TIERS.map((tier) => `${tier}=${config2.models[tier]}`).join(", ")}, otherwise ${config2.defaultModel}`);
|
|
75729
76917
|
console.log(`Codex effort: ${config2.effort}`);
|
|
76918
|
+
console.log(`Codex login: ${config2.login}`);
|
|
75730
76919
|
} else {
|
|
75731
76920
|
console.log(`Base URL: ${found.baseUrl}`);
|
|
75732
76921
|
}
|
|
@@ -76134,10 +77323,10 @@ function buildProgram(deps) {
|
|
|
76134
77323
|
|
|
76135
77324
|
// src/launchWiring.ts
|
|
76136
77325
|
var import_node_os8 = __toESM(require("node:os"), 1);
|
|
76137
|
-
var
|
|
77326
|
+
var import_node_crypto18 = require("node:crypto");
|
|
76138
77327
|
|
|
76139
77328
|
// src/launcher.ts
|
|
76140
|
-
var
|
|
77329
|
+
var import_node_crypto17 = require("node:crypto");
|
|
76141
77330
|
var import_node_path41 = __toESM(require("node:path"), 1);
|
|
76142
77331
|
|
|
76143
77332
|
// src/launcher/cliOverride.ts
|
|
@@ -76638,7 +77827,7 @@ function prepareLaunch(params) {
|
|
|
76638
77827
|
...identityCredential === void 0 ? {} : { identityCredential },
|
|
76639
77828
|
...frontDoor === void 0 ? {} : { frontdoor: frontDoor },
|
|
76640
77829
|
...headroom === void 0 ? {} : { headroom },
|
|
76641
|
-
sessionId: (0,
|
|
77830
|
+
sessionId: (0, import_node_crypto17.randomUUID)()
|
|
76642
77831
|
});
|
|
76643
77832
|
const releases = [...headroom === void 0 || headroomPort === void 0 ? [] : [headroomPort.release], ...frontDoorRelease === void 0 ? [] : [frontDoorRelease]];
|
|
76644
77833
|
const release = () => {
|
|
@@ -76683,7 +77872,7 @@ function buildFarmRuntime(paths, cwd) {
|
|
|
76683
77872
|
...cliOverride === void 0 ? {} : { cliOverride }
|
|
76684
77873
|
}).input,
|
|
76685
77874
|
now: () => Date.now(),
|
|
76686
|
-
uniqueSuffix: `${String(process.pid)}.${(0,
|
|
77875
|
+
uniqueSuffix: `${String(process.pid)}.${(0, import_node_crypto18.randomUUID)()}`,
|
|
76687
77876
|
// Zombie-aware on purpose: a previous launcher that crashed out of a resync without releasing the lock may sit unreaped, still answering signal 0 as alive, and must read as a dead holder so this launch takes the lock over instead of timing out.
|
|
76688
77877
|
lock: { pid: process.pid, isRunning: realIsProcessRunning, sleep: realSleepSync }
|
|
76689
77878
|
},
|