@iam-brain/opencode-codex-auth 0.1.7 → 0.1.9
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 +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/codex-native.d.ts +6 -2
- package/dist/lib/codex-native.d.ts.map +1 -1
- package/dist/lib/codex-native.js +147 -35
- package/dist/lib/codex-native.js.map +1 -1
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +40 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/fetch-orchestrator.d.ts +5 -0
- package/dist/lib/fetch-orchestrator.d.ts.map +1 -1
- package/dist/lib/fetch-orchestrator.js +20 -2
- package/dist/lib/fetch-orchestrator.js.map +1 -1
- package/dist/lib/installer-cli.d.ts.map +1 -1
- package/dist/lib/installer-cli.js +5 -1
- package/dist/lib/installer-cli.js.map +1 -1
- package/dist/lib/oauth-pages.d.ts +1 -1
- package/dist/lib/oauth-pages.d.ts.map +1 -1
- package/dist/lib/oauth-pages.js +3 -5
- package/dist/lib/oauth-pages.js.map +1 -1
- package/dist/lib/paths.d.ts +8 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +29 -2
- package/dist/lib/paths.js.map +1 -1
- package/dist/lib/personality-skill.d.ts +17 -0
- package/dist/lib/personality-skill.d.ts.map +1 -0
- package/dist/lib/personality-skill.js +136 -0
- package/dist/lib/personality-skill.js.map +1 -0
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +64 -73
- package/dist/lib/rotation.js.map +1 -1
- package/dist/lib/session-affinity.d.ts +26 -0
- package/dist/lib/session-affinity.d.ts.map +1 -0
- package/dist/lib/session-affinity.js +181 -0
- package/dist/lib/session-affinity.js.map +1 -0
- package/package.json +1 -1
- package/schemas/codex-config.schema.json +7 -0
package/README.md
CHANGED
|
@@ -54,12 +54,14 @@ The installer does two things:
|
|
|
54
54
|
- `Codex Compact.md.disabled`
|
|
55
55
|
3. Creates `~/.config/opencode/codex-config.json` with defaults when missing.
|
|
56
56
|
4. Synchronizes `~/.config/opencode/commands/create-personality.md` for `/create-personality` (created/updated as needed).
|
|
57
|
+
5. Synchronizes `~/.config/opencode/skills/personality-builder/SKILL.md` (plus references) for skill-driven personality workflows.
|
|
57
58
|
|
|
58
59
|
At plugin startup, files are reconciled against runtime mode:
|
|
59
60
|
|
|
60
61
|
- `mode: "collab"` -> `.md.disabled` files are activated to `.md`
|
|
61
62
|
- `mode: "native"` or `mode: "codex"` -> Codex agents are disabled to `.md.disabled`
|
|
62
63
|
- `/create-personality` command template is synchronized to the latest managed version.
|
|
64
|
+
- `personality-builder` skill template bundle is synchronized to the latest managed version.
|
|
63
65
|
|
|
64
66
|
To install only the agent templates (no `opencode.json` edits):
|
|
65
67
|
|
|
@@ -102,6 +104,8 @@ Create guided custom personalities with:
|
|
|
102
104
|
|
|
103
105
|
- Provider auth marker: `~/.local/share/opencode/auth.json`
|
|
104
106
|
- Plugin multi-account store: `~/.config/opencode/codex-accounts.json`
|
|
107
|
+
- Session affinity cache: `~/.config/opencode/cache/codex-session-affinity.json`
|
|
108
|
+
- Quota snapshot cache: `~/.config/opencode/cache/codex-snapshots.json`
|
|
105
109
|
|
|
106
110
|
Legacy sources can be imported explicitly from the auth menu:
|
|
107
111
|
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAyCjD,eAAO,MAAM,qBAAqB,EAAE,MA6LnC,CAAA;AAED,eAAe,qBAAqB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin";
|
|
2
2
|
import { listAccountsForTools, removeAccountByIndex, switchAccountByIndex, toggleAccountEnabledByIndex } from "./lib/accounts-tools";
|
|
3
3
|
import { CodexAuthPlugin, refreshAccessToken } from "./lib/codex-native";
|
|
4
|
-
import { ensureDefaultConfigFile, getCompatInputSanitizerEnabled, getCustomSettings, getDebugEnabled, getHeaderSnapshotsEnabled, getMode, getPidOffsetEnabled, getPersonality, getProactiveRefreshBufferMs, getProactiveRefreshEnabled, getSpoofMode, getQuietMode, loadConfigFile, resolveConfig } from "./lib/config";
|
|
4
|
+
import { ensureDefaultConfigFile, getCompatInputSanitizerEnabled, getCustomSettings, getDebugEnabled, getHeaderTransformDebugEnabled, getHeaderSnapshotsEnabled, getMode, getRotationStrategy, getPidOffsetEnabled, getPersonality, getProactiveRefreshBufferMs, getProactiveRefreshEnabled, getSpoofMode, getQuietMode, loadConfigFile, resolveConfig } from "./lib/config";
|
|
5
5
|
import { createLogger } from "./lib/logger";
|
|
6
6
|
import { reconcileOrchestratorAgentsState } from "./lib/orchestrator-agents";
|
|
7
7
|
import { generatePersonaSpec } from "./lib/persona-tool";
|
|
8
8
|
import { createPersonalityFile } from "./lib/personality-create";
|
|
9
9
|
import { installCreatePersonalityCommand } from "./lib/personality-command";
|
|
10
|
+
import { installPersonalityBuilderSkill } from "./lib/personality-skill";
|
|
10
11
|
import { runOneProactiveRefreshTick } from "./lib/proactive-refresh";
|
|
11
12
|
import { toolOutputForStatus } from "./lib/codex-status-tool";
|
|
12
13
|
import { requireOpenAIMultiOauthAuth, saveAuthStorage } from "./lib/storage";
|
|
@@ -19,6 +20,7 @@ export const OpenAIMultiAuthPlugin = async (input) => {
|
|
|
19
20
|
}
|
|
20
21
|
await ensureDefaultConfigFile({ env: process.env }).catch(() => { });
|
|
21
22
|
await installCreatePersonalityCommand({ force: true }).catch(() => { });
|
|
23
|
+
await installPersonalityBuilderSkill({ force: true }).catch(() => { });
|
|
22
24
|
const cfg = resolveConfig({
|
|
23
25
|
env: process.env,
|
|
24
26
|
file: loadConfigFile({ env: process.env })
|
|
@@ -66,9 +68,11 @@ export const OpenAIMultiAuthPlugin = async (input) => {
|
|
|
66
68
|
mode: runtimeMode,
|
|
67
69
|
quietMode: getQuietMode(cfg),
|
|
68
70
|
pidOffsetEnabled: getPidOffsetEnabled(cfg),
|
|
71
|
+
rotationStrategy: getRotationStrategy(cfg),
|
|
69
72
|
spoofMode: getSpoofMode(cfg),
|
|
70
73
|
compatInputSanitizer: getCompatInputSanitizerEnabled(cfg),
|
|
71
74
|
headerSnapshots: getHeaderSnapshotsEnabled(cfg),
|
|
75
|
+
headerTransformDebug: getHeaderTransformDebugEnabled(cfg),
|
|
72
76
|
customSettings: getCustomSettings(cfg)
|
|
73
77
|
});
|
|
74
78
|
const z = tool.schema;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAE1C,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,2BAA2B,EAC5B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EACL,uBAAuB,EACvB,8BAA8B,EAC9B,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,OAAO,EACP,mBAAmB,EACnB,cAAc,EACd,2BAA2B,EAC3B,0BAA0B,EAC1B,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,aAAa,EACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAA;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAA;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEtD,IAAI,SAA2C,CAAA;AAE/C,MAAM,CAAC,MAAM,qBAAqB,GAAW,KAAK,EAAE,KAAK,EAAE,EAAE;IAC3D,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,IAAI,EAAE,CAAA;QAChB,SAAS,GAAG,SAAS,CAAA;IACvB,CAAC;IAED,MAAM,uBAAuB,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACnE,MAAM,+BAA+B,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Hooks, PluginInput } from "@opencode-ai/plugin";
|
|
2
2
|
import { type IdTokenClaims } from "./claims";
|
|
3
3
|
import type { Logger } from "./logger";
|
|
4
|
-
import type { AccountRecord, OpenAIAuthMode, OpenAIOAuthDomain } from "./types";
|
|
4
|
+
import type { AccountRecord, OpenAIAuthMode, OpenAIOAuthDomain, RotationStrategy } from "./types";
|
|
5
5
|
import type { CodexSpoofMode, CustomSettings, PersonalityOption, PluginRuntimeMode } from "./config";
|
|
6
6
|
type BrowserOpenInvocation = {
|
|
7
7
|
command: string;
|
|
@@ -39,6 +39,7 @@ export declare const __testOnly: {
|
|
|
39
39
|
resolveHookAgentName: typeof resolveHookAgentName;
|
|
40
40
|
resolveCollaborationModeKind: typeof resolveCollaborationModeKind;
|
|
41
41
|
resolveSubagentHeaderValue: typeof resolveSubagentHeaderValue;
|
|
42
|
+
isOAuthDebugEnabled: typeof isOAuthDebugEnabled;
|
|
42
43
|
stopOAuthServer: typeof stopOAuthServer;
|
|
43
44
|
};
|
|
44
45
|
export declare function refreshAccessToken(refreshToken: string): Promise<TokenResponse>;
|
|
@@ -48,10 +49,11 @@ declare function composeCodexSuccessRedirectUrl(tokens: TokenResponse, options?:
|
|
|
48
49
|
}): string;
|
|
49
50
|
declare function buildOAuthSuccessHtml(mode?: CodexSpoofMode): string;
|
|
50
51
|
declare function buildOAuthErrorHtml(error: string): string;
|
|
52
|
+
declare function isOAuthDebugEnabled(): boolean;
|
|
51
53
|
declare function stopOAuthServer(): void;
|
|
52
54
|
declare function modeForRuntimeMode(runtimeMode: PluginRuntimeMode): OpenAIAuthMode;
|
|
53
55
|
export declare function upsertAccount(openai: OpenAIOAuthDomain, incoming: AccountRecord): AccountRecord;
|
|
54
|
-
type CodexOriginator = "codex_cli_rs" | "codex_exec";
|
|
56
|
+
type CodexOriginator = "opencode" | "codex_cli_rs" | "codex_exec";
|
|
55
57
|
declare function buildCodexUserAgent(originator: CodexOriginator): string;
|
|
56
58
|
declare function resolveRequestUserAgent(spoofMode: CodexSpoofMode, originator: CodexOriginator): string;
|
|
57
59
|
type CodexCollaborationModeKind = "plan" | "code" | "execute" | "pair_programming";
|
|
@@ -65,9 +67,11 @@ export type CodexAuthPluginOptions = {
|
|
|
65
67
|
mode?: PluginRuntimeMode;
|
|
66
68
|
quietMode?: boolean;
|
|
67
69
|
pidOffsetEnabled?: boolean;
|
|
70
|
+
rotationStrategy?: RotationStrategy;
|
|
68
71
|
spoofMode?: CodexSpoofMode;
|
|
69
72
|
compatInputSanitizer?: boolean;
|
|
70
73
|
headerSnapshots?: boolean;
|
|
74
|
+
headerTransformDebug?: boolean;
|
|
71
75
|
};
|
|
72
76
|
export declare function CodexAuthPlugin(input: PluginInput, opts?: CodexAuthPluginOptions): Promise<Hooks>;
|
|
73
77
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-native.d.ts","sourceRoot":"","sources":["../../lib/codex-native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAS7D,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,UAAU,CAAA;AAuBjB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,KAAK,EAEV,aAAa,EAEb,cAAc,EACd,iBAAiB,
|
|
1
|
+
{"version":3,"file":"codex-native.d.ts","sourceRoot":"","sources":["../../lib/codex-native.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/codex-native.js
CHANGED
|
@@ -9,7 +9,7 @@ import { CodexStatus } from "./codex-status";
|
|
|
9
9
|
import { saveSnapshots } from "./codex-status-storage";
|
|
10
10
|
import { PluginFatalError, formatWaitTime, isPluginFatalError, toSyntheticErrorResponse } from "./fatal-errors";
|
|
11
11
|
import { buildIdentityKey, ensureIdentityKey, normalizeEmail, normalizePlan } from "./identity";
|
|
12
|
-
import { defaultSnapshotsPath } from "./paths";
|
|
12
|
+
import { defaultSessionAffinityPath, defaultSnapshotsPath } from "./paths";
|
|
13
13
|
import { createStickySessionState, selectAccount } from "./rotation";
|
|
14
14
|
import { ensureOpenAIOAuthDomain, getOpenAIOAuthDomain, importLegacyInstallData, listOpenAIOAuthDomains, loadAuthStorage, saveAuthStorage, setAccountCooldown, shouldOfferLegacyTransfer } from "./storage";
|
|
15
15
|
import { toolOutputForStatus } from "./codex-status-tool";
|
|
@@ -22,10 +22,15 @@ import { sanitizeRequestPayloadForCompat } from "./compat-sanitizer";
|
|
|
22
22
|
import { fetchQuotaSnapshotFromBackend } from "./codex-quota-fetch";
|
|
23
23
|
import { createRequestSnapshots } from "./request-snapshots";
|
|
24
24
|
import { CODEX_OAUTH_SUCCESS_HTML } from "./oauth-pages";
|
|
25
|
+
import { createSessionExistsFn, loadSessionAffinity, pruneSessionAffinitySnapshot, readSessionAffinitySnapshot, saveSessionAffinity, writeSessionAffinitySnapshot } from "./session-affinity";
|
|
25
26
|
const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
26
27
|
const ISSUER = "https://auth.openai.com";
|
|
27
28
|
const CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
28
29
|
const OAUTH_PORT = 1455;
|
|
30
|
+
const OAUTH_LOOPBACK_HOST = "localhost";
|
|
31
|
+
const OAUTH_CALLBACK_ORIGIN = `http://${OAUTH_LOOPBACK_HOST}:${OAUTH_PORT}`;
|
|
32
|
+
const OAUTH_CALLBACK_PATH = "/auth/callback";
|
|
33
|
+
const OAUTH_CALLBACK_URI = `${OAUTH_CALLBACK_ORIGIN}${OAUTH_CALLBACK_PATH}`;
|
|
29
34
|
const OAUTH_DUMMY_KEY = "oauth_dummy_key";
|
|
30
35
|
const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000;
|
|
31
36
|
const AUTH_REFRESH_FAILURE_COOLDOWN_MS = 30_000;
|
|
@@ -192,6 +197,7 @@ export const __testOnly = {
|
|
|
192
197
|
resolveHookAgentName,
|
|
193
198
|
resolveCollaborationModeKind,
|
|
194
199
|
resolveSubagentHeaderValue,
|
|
200
|
+
isOAuthDebugEnabled,
|
|
195
201
|
stopOAuthServer
|
|
196
202
|
};
|
|
197
203
|
async function exchangeCodeForTokens(code, redirectUri, pkce) {
|
|
@@ -275,7 +281,6 @@ function composeCodexSuccessRedirectUrl(tokens, options = {}) {
|
|
|
275
281
|
getClaimBoolean(idClaims, "is_org_owner");
|
|
276
282
|
const platformUrl = issuer === ISSUER ? "https://platform.openai.com" : "https://platform.api.openai.org";
|
|
277
283
|
const params = new URLSearchParams({
|
|
278
|
-
id_token: tokens.id_token ?? "",
|
|
279
284
|
needs_setup: String(needsSetup),
|
|
280
285
|
org_id: getClaimString(idClaims, "organization_id"),
|
|
281
286
|
project_id: getClaimString(idClaims, "project_id"),
|
|
@@ -373,7 +378,8 @@ let oauthServer;
|
|
|
373
378
|
let pendingOAuth;
|
|
374
379
|
let oauthServerCloseTimer;
|
|
375
380
|
function isOAuthDebugEnabled() {
|
|
376
|
-
|
|
381
|
+
const raw = process.env.CODEX_AUTH_DEBUG?.trim().toLowerCase();
|
|
382
|
+
return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
|
|
377
383
|
}
|
|
378
384
|
function emitOAuthDebug(event, meta = {}) {
|
|
379
385
|
if (!isOAuthDebugEnabled())
|
|
@@ -405,24 +411,51 @@ function clearOAuthServerCloseTimer() {
|
|
|
405
411
|
clearTimeout(oauthServerCloseTimer);
|
|
406
412
|
oauthServerCloseTimer = undefined;
|
|
407
413
|
}
|
|
414
|
+
function isLoopbackRemoteAddress(remoteAddress) {
|
|
415
|
+
if (!remoteAddress)
|
|
416
|
+
return false;
|
|
417
|
+
const normalized = remoteAddress.split("%")[0]?.toLowerCase();
|
|
418
|
+
return normalized === "127.0.0.1" || normalized === "::1" || normalized === "::ffff:127.0.0.1";
|
|
419
|
+
}
|
|
420
|
+
function setOAuthResponseHeaders(res, options) {
|
|
421
|
+
res.setHeader("Cache-Control", "no-store");
|
|
422
|
+
res.setHeader("Pragma", "no-cache");
|
|
423
|
+
res.setHeader("Referrer-Policy", "no-referrer");
|
|
424
|
+
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
425
|
+
if (options?.contentType) {
|
|
426
|
+
res.setHeader("Content-Type", options.contentType);
|
|
427
|
+
}
|
|
428
|
+
if (options?.isHtml) {
|
|
429
|
+
res.setHeader("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'; frame-ancestors 'none'");
|
|
430
|
+
}
|
|
431
|
+
}
|
|
408
432
|
async function startOAuthServer() {
|
|
409
433
|
clearOAuthServerCloseTimer();
|
|
410
434
|
if (oauthServer) {
|
|
411
435
|
emitOAuthDebug("server_reuse", { port: OAUTH_PORT });
|
|
412
|
-
return { redirectUri:
|
|
436
|
+
return { redirectUri: OAUTH_CALLBACK_URI };
|
|
413
437
|
}
|
|
414
438
|
emitOAuthDebug("server_starting", { port: OAUTH_PORT });
|
|
415
439
|
oauthServer = http.createServer((req, res) => {
|
|
416
440
|
try {
|
|
417
|
-
|
|
418
|
-
|
|
441
|
+
if (!isLoopbackRemoteAddress(req.socket.remoteAddress)) {
|
|
442
|
+
emitOAuthDebug("callback_rejected_non_loopback", {
|
|
443
|
+
remoteAddress: req.socket.remoteAddress
|
|
444
|
+
});
|
|
445
|
+
res.statusCode = 403;
|
|
446
|
+
setOAuthResponseHeaders(res, { contentType: "text/plain; charset=utf-8" });
|
|
447
|
+
res.end("Forbidden");
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
const url = new URL(req.url ?? "/", OAUTH_CALLBACK_ORIGIN);
|
|
419
451
|
const sendHtml = (status, html) => {
|
|
420
452
|
res.statusCode = status;
|
|
421
|
-
res
|
|
453
|
+
setOAuthResponseHeaders(res, { contentType: "text/html; charset=utf-8", isHtml: true });
|
|
422
454
|
res.end(html);
|
|
423
455
|
};
|
|
424
456
|
const redirect = (location) => {
|
|
425
457
|
res.statusCode = 302;
|
|
458
|
+
setOAuthResponseHeaders(res, { contentType: "text/plain; charset=utf-8" });
|
|
426
459
|
res.setHeader("Location", location);
|
|
427
460
|
res.end();
|
|
428
461
|
};
|
|
@@ -463,7 +496,7 @@ async function startOAuthServer() {
|
|
|
463
496
|
const current = pendingOAuth;
|
|
464
497
|
pendingOAuth = undefined;
|
|
465
498
|
emitOAuthDebug("token_exchange_start", { authMode: current.authMode });
|
|
466
|
-
exchangeCodeForTokens(code,
|
|
499
|
+
exchangeCodeForTokens(code, OAUTH_CALLBACK_URI, current.pkce)
|
|
467
500
|
.then((tokens) => {
|
|
468
501
|
current.resolve(tokens);
|
|
469
502
|
emitOAuthDebug("token_exchange_success", { authMode: current.authMode });
|
|
@@ -495,21 +528,24 @@ async function startOAuthServer() {
|
|
|
495
528
|
pendingOAuth?.reject(new Error("Login cancelled"));
|
|
496
529
|
pendingOAuth = undefined;
|
|
497
530
|
res.statusCode = 200;
|
|
531
|
+
setOAuthResponseHeaders(res, { contentType: "text/plain; charset=utf-8" });
|
|
498
532
|
res.end("Login cancelled");
|
|
499
533
|
return;
|
|
500
534
|
}
|
|
501
535
|
res.statusCode = 404;
|
|
536
|
+
setOAuthResponseHeaders(res, { contentType: "text/plain; charset=utf-8" });
|
|
502
537
|
res.end("Not found");
|
|
503
538
|
}
|
|
504
539
|
catch (error) {
|
|
505
540
|
res.statusCode = 500;
|
|
541
|
+
setOAuthResponseHeaders(res, { contentType: "text/plain; charset=utf-8" });
|
|
506
542
|
res.end(`Server error: ${error.message}`);
|
|
507
543
|
}
|
|
508
544
|
});
|
|
509
545
|
try {
|
|
510
546
|
await new Promise((resolve, reject) => {
|
|
511
547
|
oauthServer?.once("error", reject);
|
|
512
|
-
oauthServer?.listen(OAUTH_PORT, () => resolve());
|
|
548
|
+
oauthServer?.listen(OAUTH_PORT, OAUTH_LOOPBACK_HOST, () => resolve());
|
|
513
549
|
});
|
|
514
550
|
emitOAuthDebug("server_started", { port: OAUTH_PORT });
|
|
515
551
|
}
|
|
@@ -527,7 +563,7 @@ async function startOAuthServer() {
|
|
|
527
563
|
}
|
|
528
564
|
throw error;
|
|
529
565
|
}
|
|
530
|
-
return { redirectUri:
|
|
566
|
+
return { redirectUri: OAUTH_CALLBACK_URI };
|
|
531
567
|
}
|
|
532
568
|
function stopOAuthServer() {
|
|
533
569
|
clearOAuthServerCloseTimer();
|
|
@@ -680,7 +716,8 @@ function rewriteUrl(requestInput) {
|
|
|
680
716
|
return parsed;
|
|
681
717
|
}
|
|
682
718
|
function opencodeUserAgent() {
|
|
683
|
-
|
|
719
|
+
const version = resolvePluginVersion();
|
|
720
|
+
return `opencode/${version} (${os.platform()} ${os.release()}; ${os.arch()})`;
|
|
684
721
|
}
|
|
685
722
|
let cachedPluginVersion;
|
|
686
723
|
let cachedMacProductVersion;
|
|
@@ -858,6 +895,8 @@ function resolveCodexPlatformSignature(platform = process.platform) {
|
|
|
858
895
|
return `${platform} ${os.release()}; ${architecture}`;
|
|
859
896
|
}
|
|
860
897
|
function buildCodexUserAgent(originator) {
|
|
898
|
+
if (originator === "opencode")
|
|
899
|
+
return opencodeUserAgent();
|
|
861
900
|
const buildVersion = resolvePluginVersion();
|
|
862
901
|
const terminalToken = resolveTerminalUserAgentToken();
|
|
863
902
|
const prefix = `${originator}/${buildVersion} (${resolveCodexPlatformSignature()}) ${terminalToken}`;
|
|
@@ -1017,7 +1056,7 @@ function isTuiWorkerInvocation(argv) {
|
|
|
1017
1056
|
}
|
|
1018
1057
|
function resolveCodexOriginator(spoofMode, argv = process.argv) {
|
|
1019
1058
|
if (spoofMode !== "codex")
|
|
1020
|
-
return "
|
|
1059
|
+
return "opencode";
|
|
1021
1060
|
const normalizedArgv = argv.map((entry) => String(entry));
|
|
1022
1061
|
if (isTuiWorkerInvocation(normalizedArgv))
|
|
1023
1062
|
return "codex_cli_rs";
|
|
@@ -1152,7 +1191,7 @@ function hydrateAccountIdentityFromAccessClaims(account) {
|
|
|
1152
1191
|
ensureAccountAuthTypes(account);
|
|
1153
1192
|
ensureIdentityKey(account);
|
|
1154
1193
|
}
|
|
1155
|
-
async function selectCatalogAuthCandidate(authMode, pidOffsetEnabled) {
|
|
1194
|
+
async function selectCatalogAuthCandidate(authMode, pidOffsetEnabled, rotationStrategy) {
|
|
1156
1195
|
try {
|
|
1157
1196
|
const auth = await loadAuthStorage();
|
|
1158
1197
|
const domain = getOpenAIOAuthDomain(auth, authMode);
|
|
@@ -1161,7 +1200,7 @@ async function selectCatalogAuthCandidate(authMode, pidOffsetEnabled) {
|
|
|
1161
1200
|
}
|
|
1162
1201
|
const selected = selectAccount({
|
|
1163
1202
|
accounts: domain.accounts,
|
|
1164
|
-
strategy: domain.strategy,
|
|
1203
|
+
strategy: rotationStrategy ?? domain.strategy,
|
|
1165
1204
|
activeIdentityKey: domain.activeIdentityKey,
|
|
1166
1205
|
now: Date.now(),
|
|
1167
1206
|
stickyPidOffset: pidOffsetEnabled
|
|
@@ -1461,7 +1500,7 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
1461
1500
|
};
|
|
1462
1501
|
};
|
|
1463
1502
|
const requestSnapshots = createRequestSnapshots({
|
|
1464
|
-
enabled: opts.headerSnapshots === true,
|
|
1503
|
+
enabled: opts.headerSnapshots === true || opts.headerTransformDebug === true,
|
|
1465
1504
|
log: opts.log
|
|
1466
1505
|
});
|
|
1467
1506
|
const showToast = async (message, variant = "info", quietMode = false) => {
|
|
@@ -1757,7 +1796,37 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
1757
1796
|
}
|
|
1758
1797
|
if (!hasOAuth)
|
|
1759
1798
|
return {};
|
|
1760
|
-
const
|
|
1799
|
+
const sessionAffinityPath = defaultSessionAffinityPath();
|
|
1800
|
+
const loadedSessionAffinity = await loadSessionAffinity(sessionAffinityPath).catch(() => ({ version: 1 }));
|
|
1801
|
+
const initialSessionAffinity = readSessionAffinitySnapshot(loadedSessionAffinity, authMode);
|
|
1802
|
+
const sessionExists = createSessionExistsFn(process.env);
|
|
1803
|
+
await pruneSessionAffinitySnapshot(initialSessionAffinity, sessionExists).catch(() => 0);
|
|
1804
|
+
const orchestratorState = createFetchOrchestratorState();
|
|
1805
|
+
orchestratorState.seenSessionKeys = initialSessionAffinity.seenSessionKeys;
|
|
1806
|
+
const stickySessionState = createStickySessionState();
|
|
1807
|
+
stickySessionState.bySessionKey = initialSessionAffinity.stickyBySessionKey;
|
|
1808
|
+
const hybridSessionState = createStickySessionState();
|
|
1809
|
+
hybridSessionState.bySessionKey = initialSessionAffinity.hybridBySessionKey;
|
|
1810
|
+
let sessionAffinityPersistQueue = Promise.resolve();
|
|
1811
|
+
const persistSessionAffinityState = () => {
|
|
1812
|
+
sessionAffinityPersistQueue = sessionAffinityPersistQueue
|
|
1813
|
+
.then(async () => {
|
|
1814
|
+
await pruneSessionAffinitySnapshot({
|
|
1815
|
+
seenSessionKeys: orchestratorState.seenSessionKeys,
|
|
1816
|
+
stickyBySessionKey: stickySessionState.bySessionKey,
|
|
1817
|
+
hybridBySessionKey: hybridSessionState.bySessionKey
|
|
1818
|
+
}, sessionExists);
|
|
1819
|
+
await saveSessionAffinity(async (current) => writeSessionAffinitySnapshot(current, authMode, {
|
|
1820
|
+
seenSessionKeys: orchestratorState.seenSessionKeys,
|
|
1821
|
+
stickyBySessionKey: stickySessionState.bySessionKey,
|
|
1822
|
+
hybridBySessionKey: hybridSessionState.bySessionKey
|
|
1823
|
+
}), sessionAffinityPath);
|
|
1824
|
+
})
|
|
1825
|
+
.catch(() => {
|
|
1826
|
+
// best-effort persistence
|
|
1827
|
+
});
|
|
1828
|
+
};
|
|
1829
|
+
const catalogAuth = await selectCatalogAuthCandidate(authMode, opts.pidOffsetEnabled === true, opts.rotationStrategy);
|
|
1761
1830
|
const catalogModels = await getCodexModelCatalog({
|
|
1762
1831
|
accessToken: catalogAuth.accessToken,
|
|
1763
1832
|
accountId: catalogAuth.accountId,
|
|
@@ -1770,23 +1839,47 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
1770
1839
|
fallbackModels: STATIC_FALLBACK_MODELS,
|
|
1771
1840
|
personality: opts.personality
|
|
1772
1841
|
});
|
|
1773
|
-
const orchestratorState = createFetchOrchestratorState();
|
|
1774
|
-
const stickySessionState = createStickySessionState();
|
|
1775
1842
|
return {
|
|
1776
1843
|
apiKey: OAUTH_DUMMY_KEY,
|
|
1777
1844
|
async fetch(requestInput, init) {
|
|
1778
1845
|
const baseRequest = new Request(requestInput, init);
|
|
1846
|
+
const inboundCollaborationModeKind = baseRequest.headers.get(INTERNAL_COLLABORATION_MODE_HEADER) ?? undefined;
|
|
1847
|
+
if (opts.headerTransformDebug === true) {
|
|
1848
|
+
await requestSnapshots.captureRequest("before-header-transform", baseRequest, {
|
|
1849
|
+
spoofMode,
|
|
1850
|
+
...(inboundCollaborationModeKind
|
|
1851
|
+
? { collaborationModeKind: inboundCollaborationModeKind }
|
|
1852
|
+
: {})
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1779
1855
|
const outbound = new Request(rewriteUrl(baseRequest), baseRequest);
|
|
1780
1856
|
const inboundOriginator = outbound.headers.get("originator")?.trim();
|
|
1781
|
-
const outboundOriginator = inboundOriginator === "
|
|
1857
|
+
const outboundOriginator = inboundOriginator === "opencode" ||
|
|
1858
|
+
inboundOriginator === "codex_exec" ||
|
|
1859
|
+
inboundOriginator === "codex_cli_rs"
|
|
1782
1860
|
? inboundOriginator
|
|
1783
1861
|
: resolveCodexOriginator(spoofMode);
|
|
1784
1862
|
outbound.headers.set("originator", outboundOriginator);
|
|
1785
|
-
outbound.headers.
|
|
1863
|
+
const inboundUserAgent = outbound.headers.get("user-agent")?.trim();
|
|
1864
|
+
if (spoofMode === "native" && inboundUserAgent) {
|
|
1865
|
+
outbound.headers.set("user-agent", inboundUserAgent);
|
|
1866
|
+
}
|
|
1867
|
+
else {
|
|
1868
|
+
outbound.headers.set("user-agent", resolveRequestUserAgent(spoofMode, outboundOriginator));
|
|
1869
|
+
}
|
|
1786
1870
|
const collaborationModeKind = outbound.headers.get(INTERNAL_COLLABORATION_MODE_HEADER);
|
|
1787
1871
|
if (collaborationModeKind) {
|
|
1788
1872
|
outbound.headers.delete(INTERNAL_COLLABORATION_MODE_HEADER);
|
|
1789
1873
|
}
|
|
1874
|
+
const subagentHeader = outbound.headers.get("x-openai-subagent")?.trim();
|
|
1875
|
+
const isSubagentRequest = Boolean(subagentHeader);
|
|
1876
|
+
if (opts.headerTransformDebug === true) {
|
|
1877
|
+
await requestSnapshots.captureRequest("after-header-transform", outbound, {
|
|
1878
|
+
spoofMode,
|
|
1879
|
+
...(collaborationModeKind ? { collaborationModeKind } : {}),
|
|
1880
|
+
...(isSubagentRequest ? { subagent: subagentHeader } : {})
|
|
1881
|
+
});
|
|
1882
|
+
}
|
|
1790
1883
|
let selectedIdentityKey;
|
|
1791
1884
|
await requestSnapshots.captureRequest("before-auth", outbound, {
|
|
1792
1885
|
spoofMode,
|
|
@@ -1801,6 +1894,11 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
1801
1894
|
let email;
|
|
1802
1895
|
let plan;
|
|
1803
1896
|
try {
|
|
1897
|
+
if (isSubagentRequest && context?.sessionKey) {
|
|
1898
|
+
orchestratorState.seenSessionKeys.delete(context.sessionKey);
|
|
1899
|
+
stickySessionState.bySessionKey.delete(context.sessionKey);
|
|
1900
|
+
hybridSessionState.bySessionKey.delete(context.sessionKey);
|
|
1901
|
+
}
|
|
1804
1902
|
await saveAuthStorage(undefined, async (authFile) => {
|
|
1805
1903
|
const now = Date.now();
|
|
1806
1904
|
const openai = authFile.openai;
|
|
@@ -1834,8 +1932,9 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
1834
1932
|
let sawInvalidGrant = false;
|
|
1835
1933
|
let sawRefreshFailure = false;
|
|
1836
1934
|
let sawMissingRefresh = false;
|
|
1935
|
+
const rotationStrategy = opts.rotationStrategy ?? domain.strategy ?? "sticky";
|
|
1837
1936
|
opts.log?.debug("rotation begin", {
|
|
1838
|
-
strategy:
|
|
1937
|
+
strategy: rotationStrategy,
|
|
1839
1938
|
activeIdentityKey: domain.activeIdentityKey,
|
|
1840
1939
|
totalAccounts: domain.accounts.length,
|
|
1841
1940
|
enabledAccounts: enabled.length,
|
|
@@ -1843,14 +1942,19 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
1843
1942
|
sessionKey: context?.sessionKey ?? null
|
|
1844
1943
|
});
|
|
1845
1944
|
while (attempted.size < domain.accounts.length) {
|
|
1945
|
+
const sessionState = rotationStrategy === "sticky"
|
|
1946
|
+
? stickySessionState
|
|
1947
|
+
: rotationStrategy === "hybrid"
|
|
1948
|
+
? hybridSessionState
|
|
1949
|
+
: undefined;
|
|
1846
1950
|
const selected = selectAccount({
|
|
1847
1951
|
accounts: domain.accounts,
|
|
1848
|
-
strategy:
|
|
1952
|
+
strategy: rotationStrategy,
|
|
1849
1953
|
activeIdentityKey: domain.activeIdentityKey,
|
|
1850
1954
|
now,
|
|
1851
1955
|
stickyPidOffset: opts.pidOffsetEnabled === true,
|
|
1852
|
-
stickySessionKey: context?.sessionKey,
|
|
1853
|
-
stickySessionState,
|
|
1956
|
+
stickySessionKey: isSubagentRequest ? undefined : context?.sessionKey,
|
|
1957
|
+
stickySessionState: sessionState,
|
|
1854
1958
|
onDebug: (event) => {
|
|
1855
1959
|
opts.log?.debug("rotation decision", event);
|
|
1856
1960
|
}
|
|
@@ -1875,6 +1979,9 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
1875
1979
|
break;
|
|
1876
1980
|
}
|
|
1877
1981
|
attempted.add(attemptKey);
|
|
1982
|
+
if (!isSubagentRequest && context?.sessionKey && sessionState) {
|
|
1983
|
+
persistSessionAffinityState();
|
|
1984
|
+
}
|
|
1878
1985
|
opts.log?.debug("rotation candidate selected", {
|
|
1879
1986
|
attemptKey,
|
|
1880
1987
|
selectedIdentityKey: selected.identityKey,
|
|
@@ -2030,6 +2137,17 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
2030
2137
|
},
|
|
2031
2138
|
quietMode: opts.quietMode === true,
|
|
2032
2139
|
state: orchestratorState,
|
|
2140
|
+
onSessionObserved: ({ event, sessionKey }) => {
|
|
2141
|
+
if (isSubagentRequest) {
|
|
2142
|
+
orchestratorState.seenSessionKeys.delete(sessionKey);
|
|
2143
|
+
stickySessionState.bySessionKey.delete(sessionKey);
|
|
2144
|
+
hybridSessionState.bySessionKey.delete(sessionKey);
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
if (event === "new" || event === "resume" || event === "switch") {
|
|
2148
|
+
persistSessionAffinityState();
|
|
2149
|
+
}
|
|
2150
|
+
},
|
|
2033
2151
|
showToast,
|
|
2034
2152
|
onAttemptRequest: async ({ attempt, maxAttempts, request, auth, sessionKey }) => {
|
|
2035
2153
|
await requestSnapshots.captureRequest("outbound-attempt", request, {
|
|
@@ -2121,7 +2239,7 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
2121
2239
|
const { redirectUri } = await startOAuthServer();
|
|
2122
2240
|
const pkce = await generatePKCE();
|
|
2123
2241
|
const state = generateState();
|
|
2124
|
-
const authUrl = buildAuthorizeUrl(redirectUri, pkce, state, "codex_cli_rs");
|
|
2242
|
+
const authUrl = buildAuthorizeUrl(redirectUri, pkce, state, spoofMode === "codex" ? "codex_cli_rs" : "opencode");
|
|
2125
2243
|
const callbackPromise = waitForOAuthCallback(pkce, state, authMode);
|
|
2126
2244
|
void tryOpenUrlInBrowser(authUrl, opts.log);
|
|
2127
2245
|
process.stdout.write(`\nGo to: ${authUrl}\n`);
|
|
@@ -2187,7 +2305,7 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
2187
2305
|
const { redirectUri } = await startOAuthServer();
|
|
2188
2306
|
const pkce = await generatePKCE();
|
|
2189
2307
|
const state = generateState();
|
|
2190
|
-
const authUrl = buildAuthorizeUrl(redirectUri, pkce, state, "codex_cli_rs");
|
|
2308
|
+
const authUrl = buildAuthorizeUrl(redirectUri, pkce, state, spoofMode === "codex" ? "codex_cli_rs" : "opencode");
|
|
2191
2309
|
const callbackPromise = waitForOAuthCallback(pkce, state, authMode);
|
|
2192
2310
|
void tryOpenUrlInBrowser(authUrl, opts.log);
|
|
2193
2311
|
return {
|
|
@@ -2369,15 +2487,9 @@ export async function CodexAuthPlugin(input, opts = {}) {
|
|
|
2369
2487
|
const modelOptions = isRecord(hookInput.model.options) ? hookInput.model.options : {};
|
|
2370
2488
|
const promptCacheKey = resolvePromptCacheKey(modelOptions);
|
|
2371
2489
|
if (spoofMode === "native") {
|
|
2372
|
-
output.headers
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
output.headers.conversation_id = promptCacheKey;
|
|
2376
|
-
}
|
|
2377
|
-
else {
|
|
2378
|
-
delete output.headers.session_id;
|
|
2379
|
-
delete output.headers.conversation_id;
|
|
2380
|
-
}
|
|
2490
|
+
output.headers.session_id = hookInput.sessionID;
|
|
2491
|
+
delete output.headers["OpenAI-Beta"];
|
|
2492
|
+
delete output.headers.conversation_id;
|
|
2381
2493
|
}
|
|
2382
2494
|
else {
|
|
2383
2495
|
output.headers.session_id = promptCacheKey ?? hookInput.sessionID;
|