better-opencode-openai-codex-auth 0.1.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.
Files changed (81) hide show
  1. package/LICENSE +37 -0
  2. package/README.md +99 -0
  3. package/assets/opencode-logo-ornate-dark.svg +18 -0
  4. package/assets/readme-hero.svg +31 -0
  5. package/config/README.md +103 -0
  6. package/config/minimal-opencode.json +12 -0
  7. package/config/opencode-legacy.json +571 -0
  8. package/config/opencode-modern.json +239 -0
  9. package/dist/index.d.ts +42 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +334 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/account-pool.d.ts +17 -0
  14. package/dist/lib/account-pool.d.ts.map +1 -0
  15. package/dist/lib/account-pool.js +243 -0
  16. package/dist/lib/account-pool.js.map +1 -0
  17. package/dist/lib/auth/auth.d.ts +43 -0
  18. package/dist/lib/auth/auth.d.ts.map +1 -0
  19. package/dist/lib/auth/auth.js +162 -0
  20. package/dist/lib/auth/auth.js.map +1 -0
  21. package/dist/lib/auth/browser.d.ts +17 -0
  22. package/dist/lib/auth/browser.d.ts.map +1 -0
  23. package/dist/lib/auth/browser.js +76 -0
  24. package/dist/lib/auth/browser.js.map +1 -0
  25. package/dist/lib/auth/server.d.ts +10 -0
  26. package/dist/lib/auth/server.d.ts.map +1 -0
  27. package/dist/lib/auth/server.js +78 -0
  28. package/dist/lib/auth/server.js.map +1 -0
  29. package/dist/lib/config.d.ts +17 -0
  30. package/dist/lib/config.d.ts.map +1 -0
  31. package/dist/lib/config.js +53 -0
  32. package/dist/lib/config.js.map +1 -0
  33. package/dist/lib/constants.d.ts +67 -0
  34. package/dist/lib/constants.d.ts.map +1 -0
  35. package/dist/lib/constants.js +67 -0
  36. package/dist/lib/constants.js.map +1 -0
  37. package/dist/lib/logger.d.ts +21 -0
  38. package/dist/lib/logger.d.ts.map +1 -0
  39. package/dist/lib/logger.js +77 -0
  40. package/dist/lib/logger.js.map +1 -0
  41. package/dist/lib/oauth-success.html +712 -0
  42. package/dist/lib/prompts/codex-opencode-bridge.d.ts +19 -0
  43. package/dist/lib/prompts/codex-opencode-bridge.d.ts.map +1 -0
  44. package/dist/lib/prompts/codex-opencode-bridge.js +152 -0
  45. package/dist/lib/prompts/codex-opencode-bridge.js.map +1 -0
  46. package/dist/lib/prompts/codex.d.ts +27 -0
  47. package/dist/lib/prompts/codex.d.ts.map +1 -0
  48. package/dist/lib/prompts/codex.js +252 -0
  49. package/dist/lib/prompts/codex.js.map +1 -0
  50. package/dist/lib/prompts/opencode-codex.d.ts +21 -0
  51. package/dist/lib/prompts/opencode-codex.d.ts.map +1 -0
  52. package/dist/lib/prompts/opencode-codex.js +91 -0
  53. package/dist/lib/prompts/opencode-codex.js.map +1 -0
  54. package/dist/lib/request/fetch-helpers.d.ts +73 -0
  55. package/dist/lib/request/fetch-helpers.d.ts.map +1 -0
  56. package/dist/lib/request/fetch-helpers.js +221 -0
  57. package/dist/lib/request/fetch-helpers.js.map +1 -0
  58. package/dist/lib/request/helpers/input-utils.d.ts +6 -0
  59. package/dist/lib/request/helpers/input-utils.d.ts.map +1 -0
  60. package/dist/lib/request/helpers/input-utils.js +174 -0
  61. package/dist/lib/request/helpers/input-utils.js.map +1 -0
  62. package/dist/lib/request/helpers/model-map.d.ts +28 -0
  63. package/dist/lib/request/helpers/model-map.d.ts.map +1 -0
  64. package/dist/lib/request/helpers/model-map.js +126 -0
  65. package/dist/lib/request/helpers/model-map.js.map +1 -0
  66. package/dist/lib/request/request-transformer.d.ts +93 -0
  67. package/dist/lib/request/request-transformer.d.ts.map +1 -0
  68. package/dist/lib/request/request-transformer.js +418 -0
  69. package/dist/lib/request/request-transformer.js.map +1 -0
  70. package/dist/lib/request/response-handler.d.ts +14 -0
  71. package/dist/lib/request/response-handler.d.ts.map +1 -0
  72. package/dist/lib/request/response-handler.js +150 -0
  73. package/dist/lib/request/response-handler.js.map +1 -0
  74. package/dist/lib/types.d.ts +183 -0
  75. package/dist/lib/types.d.ts.map +1 -0
  76. package/dist/lib/types.js +2 -0
  77. package/dist/lib/types.js.map +1 -0
  78. package/package.json +74 -0
  79. package/scripts/install-opencode-codex-auth.js +433 -0
  80. package/scripts/test-all-models.sh +259 -0
  81. package/scripts/validate-model-map.sh +97 -0
@@ -0,0 +1,243 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { randomUUID } from "node:crypto";
4
+ import { dirname, join } from "node:path";
5
+ const STORAGE_VERSION = 1;
6
+ const DEFAULT_COOLDOWN_MS = 60_000;
7
+ function storagePath() {
8
+ if (process.env.OPENAI_CODEX_ACCOUNTS_PATH) {
9
+ return process.env.OPENAI_CODEX_ACCOUNTS_PATH;
10
+ }
11
+ return join(homedir(), ".opencode", "openai-codex-accounts.json");
12
+ }
13
+ function clampIndex(index, size) {
14
+ if (!Number.isFinite(index) || size <= 0)
15
+ return 0;
16
+ const n = Math.floor(index);
17
+ if (n < 0)
18
+ return 0;
19
+ if (n >= size)
20
+ return size - 1;
21
+ return n;
22
+ }
23
+ function now() {
24
+ return Date.now();
25
+ }
26
+ function normalizeEntry(entry) {
27
+ if (!entry.accountId || !entry.refresh || !entry.access || !Number.isFinite(entry.expires)) {
28
+ return null;
29
+ }
30
+ return {
31
+ accountId: entry.accountId,
32
+ refresh: entry.refresh,
33
+ access: entry.access,
34
+ expires: Math.floor(entry.expires),
35
+ email: entry.email,
36
+ lastUsed: entry.lastUsed,
37
+ rateLimitedUntil: entry.rateLimitedUntil,
38
+ };
39
+ }
40
+ function parseStorage(raw) {
41
+ let parsed;
42
+ try {
43
+ parsed = JSON.parse(raw);
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ if (!parsed || typeof parsed !== "object")
49
+ return null;
50
+ const obj = parsed;
51
+ const accounts = Array.isArray(obj.accounts)
52
+ ? obj.accounts
53
+ .map((e) => normalizeEntry(e))
54
+ .filter((e) => e !== null)
55
+ : [];
56
+ return {
57
+ version: STORAGE_VERSION,
58
+ activeIndex: clampIndex(Number(obj.activeIndex ?? 0), accounts.length || 1),
59
+ accounts,
60
+ };
61
+ }
62
+ function normalizeCooldown(cooldownMs) {
63
+ if (!Number.isFinite(cooldownMs) || cooldownMs < 1000) {
64
+ return DEFAULT_COOLDOWN_MS;
65
+ }
66
+ return Math.floor(cooldownMs);
67
+ }
68
+ function retryAfterFromHeaders(headers, fallbackMs) {
69
+ const maxRetryMs = 86_400_000;
70
+ const retryAfterMs = headers.get("retry-after-ms");
71
+ if (retryAfterMs) {
72
+ const parsed = Number.parseInt(retryAfterMs, 10);
73
+ if (!Number.isNaN(parsed) && parsed > 0 && parsed <= maxRetryMs)
74
+ return parsed;
75
+ }
76
+ const retryAfter = headers.get("retry-after");
77
+ if (retryAfter) {
78
+ const seconds = Number.parseInt(retryAfter, 10);
79
+ if (!Number.isNaN(seconds) && seconds > 0 && seconds * 1000 <= maxRetryMs) {
80
+ return seconds * 1000;
81
+ }
82
+ const retryDateMs = Date.parse(retryAfter);
83
+ if (!Number.isNaN(retryDateMs)) {
84
+ const remaining = retryDateMs - now();
85
+ if (remaining > 0 && remaining <= maxRetryMs)
86
+ return remaining;
87
+ }
88
+ }
89
+ const codexPrimary = headers.get("x-codex-primary-reset-after-seconds");
90
+ if (codexPrimary) {
91
+ const parsed = Number.parseInt(codexPrimary, 10);
92
+ if (!Number.isNaN(parsed) && parsed > 0)
93
+ return parsed * 1000;
94
+ }
95
+ return fallbackMs;
96
+ }
97
+ export class AccountPool {
98
+ accounts = [];
99
+ activeIndex = 0;
100
+ static load() {
101
+ const pool = new AccountPool();
102
+ const path = storagePath();
103
+ if (!existsSync(path))
104
+ return pool;
105
+ try {
106
+ const raw = readFileSync(path, "utf8");
107
+ const parsed = parseStorage(raw);
108
+ if (!parsed)
109
+ return pool;
110
+ pool.accounts = parsed.accounts;
111
+ pool.activeIndex = clampIndex(parsed.activeIndex, parsed.accounts.length || 1);
112
+ return pool;
113
+ }
114
+ catch {
115
+ return pool;
116
+ }
117
+ }
118
+ save() {
119
+ const path = storagePath();
120
+ const dir = dirname(path);
121
+ if (!existsSync(dir)) {
122
+ mkdirSync(dir, { recursive: true });
123
+ }
124
+ const payload = {
125
+ version: STORAGE_VERSION,
126
+ activeIndex: clampIndex(this.activeIndex, this.accounts.length || 1),
127
+ accounts: this.accounts,
128
+ };
129
+ const tempPath = `${path}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;
130
+ writeFileSync(tempPath, `${JSON.stringify(payload, null, 2)}\n`, {
131
+ encoding: "utf8",
132
+ mode: 0o600,
133
+ });
134
+ renameSync(tempPath, path);
135
+ try {
136
+ chmodSync(path, 0o600);
137
+ }
138
+ catch {
139
+ }
140
+ }
141
+ upsert(entry) {
142
+ const normalized = normalizeEntry(entry);
143
+ if (!normalized)
144
+ return;
145
+ const byAccount = this.accounts.findIndex((a) => a.accountId === normalized.accountId);
146
+ const byEmail = normalized.email && byAccount < 0
147
+ ? this.accounts.findIndex((a) => a.email && a.email === normalized.email)
148
+ : -1;
149
+ const idx = byAccount >= 0 ? byAccount : byEmail;
150
+ if (idx >= 0) {
151
+ const existing = this.accounts[idx];
152
+ if (!existing)
153
+ return;
154
+ const incomingIsOlder = normalized.expires < existing.expires;
155
+ const nextAccess = incomingIsOlder ? existing.access : normalized.access;
156
+ const nextRefresh = incomingIsOlder ? existing.refresh : normalized.refresh;
157
+ const nextExpires = incomingIsOlder ? existing.expires : normalized.expires;
158
+ this.accounts[idx] = {
159
+ ...existing,
160
+ ...normalized,
161
+ access: nextAccess,
162
+ refresh: nextRefresh,
163
+ expires: nextExpires,
164
+ rateLimitedUntil: existing.rateLimitedUntil,
165
+ };
166
+ }
167
+ else {
168
+ this.accounts.push(normalized);
169
+ }
170
+ this.activeIndex = clampIndex(this.activeIndex, this.accounts.length || 1);
171
+ }
172
+ count() {
173
+ return this.accounts.length;
174
+ }
175
+ getAvailableCount() {
176
+ const t = now();
177
+ return this.accounts.filter((a) => !a.rateLimitedUntil || a.rateLimitedUntil <= t).length;
178
+ }
179
+ getMinRetryAfterMs() {
180
+ const t = now();
181
+ let min = null;
182
+ for (const account of this.accounts) {
183
+ if (!account.rateLimitedUntil || account.rateLimitedUntil <= t)
184
+ continue;
185
+ const remaining = account.rateLimitedUntil - t;
186
+ if (min === null || remaining < min) {
187
+ min = remaining;
188
+ }
189
+ }
190
+ return min;
191
+ }
192
+ markRateLimited(accountId, headers, cooldownMs) {
193
+ const account = this.accounts.find((a) => a.accountId === accountId);
194
+ if (!account)
195
+ return;
196
+ const fallback = normalizeCooldown(cooldownMs);
197
+ const retryAfter = retryAfterFromHeaders(headers, fallback);
198
+ account.rateLimitedUntil = now() + retryAfter;
199
+ }
200
+ next(strategy) {
201
+ if (this.accounts.length === 0)
202
+ return null;
203
+ this.clearExpiredLimits();
204
+ if (strategy === "sticky") {
205
+ const current = this.accounts[this.activeIndex];
206
+ if (current && !this.isLimited(current)) {
207
+ current.lastUsed = now();
208
+ return current;
209
+ }
210
+ }
211
+ const start = strategy === "round-robin" ? (this.activeIndex + 1) % this.accounts.length : this.activeIndex;
212
+ for (let i = 0; i < this.accounts.length; i++) {
213
+ const idx = (start + i) % this.accounts.length;
214
+ const candidate = this.accounts[idx];
215
+ if (!candidate || this.isLimited(candidate))
216
+ continue;
217
+ this.activeIndex = idx;
218
+ candidate.lastUsed = now();
219
+ return candidate;
220
+ }
221
+ return null;
222
+ }
223
+ replaceAuth(accountId, access, refresh, expires) {
224
+ const account = this.accounts.find((a) => a.accountId === accountId);
225
+ if (!account)
226
+ return;
227
+ account.access = access;
228
+ account.refresh = refresh;
229
+ account.expires = expires;
230
+ }
231
+ isLimited(account) {
232
+ return !!account.rateLimitedUntil && account.rateLimitedUntil > now();
233
+ }
234
+ clearExpiredLimits() {
235
+ const t = now();
236
+ for (const account of this.accounts) {
237
+ if (account.rateLimitedUntil && account.rateLimitedUntil <= t) {
238
+ delete account.rateLimitedUntil;
239
+ }
240
+ }
241
+ }
242
+ }
243
+ //# sourceMappingURL=account-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-pool.js","sourceRoot":"","sources":["../../lib/account-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { AuthorizationFlow, TokenResult, ParsedAuthInput, JWTPayload } from "../types.js";
2
+ export declare const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
3
+ export declare const AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
4
+ export declare const TOKEN_URL = "https://auth.openai.com/oauth/token";
5
+ export declare const REDIRECT_URI = "http://localhost:1455/auth/callback";
6
+ export declare const SCOPE = "openid profile email offline_access";
7
+ /**
8
+ * Generate a random state value for OAuth flow
9
+ * @returns Random hex string
10
+ */
11
+ export declare function createState(): string;
12
+ /**
13
+ * Parse authorization code and state from user input
14
+ * @param input - User input (URL, code#state, or just code)
15
+ * @returns Parsed authorization data
16
+ */
17
+ export declare function parseAuthorizationInput(input: string): ParsedAuthInput;
18
+ /**
19
+ * Exchange authorization code for access and refresh tokens
20
+ * @param code - Authorization code from OAuth flow
21
+ * @param verifier - PKCE verifier
22
+ * @param redirectUri - OAuth redirect URI
23
+ * @returns Token result
24
+ */
25
+ export declare function exchangeAuthorizationCode(code: string, verifier: string, redirectUri?: string): Promise<TokenResult>;
26
+ /**
27
+ * Decode a JWT token to extract payload
28
+ * @param token - JWT token to decode
29
+ * @returns Decoded payload or null if invalid
30
+ */
31
+ export declare function decodeJWT(token: string): JWTPayload | null;
32
+ /**
33
+ * Refresh access token using refresh token
34
+ * @param refreshToken - Refresh token
35
+ * @returns Token result
36
+ */
37
+ export declare function refreshAccessToken(refreshToken: string): Promise<TokenResult>;
38
+ /**
39
+ * Create OAuth authorization flow
40
+ * @returns Authorization flow details
41
+ */
42
+ export declare function createAuthorizationFlow(): Promise<AuthorizationFlow>;
43
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../lib/auth/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAY,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzG,eAAO,MAAM,SAAS,iCAAiC,CAAC;AACxD,eAAO,MAAM,aAAa,4CAA4C,CAAC;AACvE,eAAO,MAAM,SAAS,wCAAwC,CAAC;AAC/D,eAAO,MAAM,YAAY,wCAAwC,CAAC;AAClE,eAAO,MAAM,KAAK,wCAAwC,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAwBtE;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC9C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,MAAqB,GAChC,OAAO,CAAC,WAAW,CAAC,CAoCtB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAU1D;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAiDnF;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAiB1E"}
@@ -0,0 +1,162 @@
1
+ import { generatePKCE } from "@openauthjs/openauth/pkce";
2
+ import { randomBytes } from "node:crypto";
3
+ // OAuth constants (from openai/codex)
4
+ export const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
5
+ export const AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
6
+ export const TOKEN_URL = "https://auth.openai.com/oauth/token";
7
+ export const REDIRECT_URI = "http://localhost:1455/auth/callback";
8
+ export const SCOPE = "openid profile email offline_access";
9
+ /**
10
+ * Generate a random state value for OAuth flow
11
+ * @returns Random hex string
12
+ */
13
+ export function createState() {
14
+ return randomBytes(16).toString("hex");
15
+ }
16
+ /**
17
+ * Parse authorization code and state from user input
18
+ * @param input - User input (URL, code#state, or just code)
19
+ * @returns Parsed authorization data
20
+ */
21
+ export function parseAuthorizationInput(input) {
22
+ const value = (input || "").trim();
23
+ if (!value)
24
+ return {};
25
+ try {
26
+ const url = new URL(value);
27
+ return {
28
+ code: url.searchParams.get("code") ?? undefined,
29
+ state: url.searchParams.get("state") ?? undefined,
30
+ };
31
+ }
32
+ catch { }
33
+ if (value.includes("#")) {
34
+ const [code, state] = value.split("#", 2);
35
+ return { code, state };
36
+ }
37
+ if (value.includes("code=")) {
38
+ const params = new URLSearchParams(value);
39
+ return {
40
+ code: params.get("code") ?? undefined,
41
+ state: params.get("state") ?? undefined,
42
+ };
43
+ }
44
+ return { code: value };
45
+ }
46
+ /**
47
+ * Exchange authorization code for access and refresh tokens
48
+ * @param code - Authorization code from OAuth flow
49
+ * @param verifier - PKCE verifier
50
+ * @param redirectUri - OAuth redirect URI
51
+ * @returns Token result
52
+ */
53
+ export async function exchangeAuthorizationCode(code, verifier, redirectUri = REDIRECT_URI) {
54
+ const res = await fetch(TOKEN_URL, {
55
+ method: "POST",
56
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
57
+ body: new URLSearchParams({
58
+ grant_type: "authorization_code",
59
+ client_id: CLIENT_ID,
60
+ code,
61
+ code_verifier: verifier,
62
+ redirect_uri: redirectUri,
63
+ }),
64
+ });
65
+ if (!res.ok) {
66
+ const text = await res.text().catch(() => "");
67
+ console.error("[openai-codex-plugin] code->token failed:", res.status, text);
68
+ return { type: "failed" };
69
+ }
70
+ const json = (await res.json());
71
+ if (!json?.access_token ||
72
+ !json?.refresh_token ||
73
+ typeof json?.expires_in !== "number") {
74
+ console.error("[openai-codex-plugin] token response missing fields:", json);
75
+ return { type: "failed" };
76
+ }
77
+ return {
78
+ type: "success",
79
+ access: json.access_token,
80
+ refresh: json.refresh_token,
81
+ expires: Date.now() + json.expires_in * 1000,
82
+ };
83
+ }
84
+ /**
85
+ * Decode a JWT token to extract payload
86
+ * @param token - JWT token to decode
87
+ * @returns Decoded payload or null if invalid
88
+ */
89
+ export function decodeJWT(token) {
90
+ try {
91
+ const parts = token.split(".");
92
+ if (parts.length !== 3)
93
+ return null;
94
+ const payload = parts[1];
95
+ const decoded = Buffer.from(payload, "base64").toString("utf-8");
96
+ return JSON.parse(decoded);
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
102
+ /**
103
+ * Refresh access token using refresh token
104
+ * @param refreshToken - Refresh token
105
+ * @returns Token result
106
+ */
107
+ export async function refreshAccessToken(refreshToken) {
108
+ try {
109
+ const response = await fetch(TOKEN_URL, {
110
+ method: "POST",
111
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
112
+ body: new URLSearchParams({
113
+ grant_type: "refresh_token",
114
+ refresh_token: refreshToken,
115
+ client_id: CLIENT_ID,
116
+ }),
117
+ });
118
+ if (!response.ok) {
119
+ const text = await response.text().catch(() => "");
120
+ console.error("[openai-codex-plugin] Token refresh failed:", response.status, text);
121
+ return { type: "failed" };
122
+ }
123
+ const json = (await response.json());
124
+ if (!json?.access_token ||
125
+ typeof json?.expires_in !== "number") {
126
+ console.error("[openai-codex-plugin] Token refresh response missing fields:", json);
127
+ return { type: "failed" };
128
+ }
129
+ return {
130
+ type: "success",
131
+ access: json.access_token,
132
+ refresh: json.refresh_token || refreshToken,
133
+ expires: Date.now() + json.expires_in * 1000,
134
+ };
135
+ }
136
+ catch (error) {
137
+ const err = error;
138
+ console.error("[openai-codex-plugin] Token refresh error:", err);
139
+ return { type: "failed" };
140
+ }
141
+ }
142
+ /**
143
+ * Create OAuth authorization flow
144
+ * @returns Authorization flow details
145
+ */
146
+ export async function createAuthorizationFlow() {
147
+ const pkce = (await generatePKCE());
148
+ const state = createState();
149
+ const url = new URL(AUTHORIZE_URL);
150
+ url.searchParams.set("response_type", "code");
151
+ url.searchParams.set("client_id", CLIENT_ID);
152
+ url.searchParams.set("redirect_uri", REDIRECT_URI);
153
+ url.searchParams.set("scope", SCOPE);
154
+ url.searchParams.set("code_challenge", pkce.challenge);
155
+ url.searchParams.set("code_challenge_method", "S256");
156
+ url.searchParams.set("state", state);
157
+ url.searchParams.set("id_token_add_organizations", "true");
158
+ url.searchParams.set("codex_cli_simplified_flow", "true");
159
+ url.searchParams.set("originator", "codex_cli_rs");
160
+ return { pkce, state, url: url.toString() };
161
+ }
162
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../lib/auth/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Browser utilities for OAuth flow
3
+ * Handles platform-specific browser opening
4
+ */
5
+ /**
6
+ * Gets the platform-specific command to open a URL in the default browser
7
+ * @returns Browser opener command for the current platform
8
+ */
9
+ export declare function getBrowserOpener(): string;
10
+ /**
11
+ * Opens a URL in the default browser
12
+ * Silently fails if browser cannot be opened (user can copy URL manually)
13
+ * @param url - URL to open
14
+ * @returns True if a browser launch was attempted
15
+ */
16
+ export declare function openBrowserUrl(url: string): boolean;
17
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../lib/auth/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAkCD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAgBnD"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Browser utilities for OAuth flow
3
+ * Handles platform-specific browser opening
4
+ */
5
+ import { spawn } from "node:child_process";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { PLATFORM_OPENERS } from "../constants.js";
9
+ /**
10
+ * Gets the platform-specific command to open a URL in the default browser
11
+ * @returns Browser opener command for the current platform
12
+ */
13
+ export function getBrowserOpener() {
14
+ const platform = process.platform;
15
+ if (platform === "darwin")
16
+ return PLATFORM_OPENERS.darwin;
17
+ if (platform === "win32")
18
+ return PLATFORM_OPENERS.win32;
19
+ return PLATFORM_OPENERS.linux;
20
+ }
21
+ function commandExists(command) {
22
+ if (!command)
23
+ return false;
24
+ // "start" is a shell builtin on Windows; rely on shell execution
25
+ if (process.platform === "win32" && command.toLowerCase() === "start") {
26
+ return true;
27
+ }
28
+ const pathValue = process.env.PATH || "";
29
+ const entries = pathValue.split(path.delimiter).filter(Boolean);
30
+ if (entries.length === 0)
31
+ return false;
32
+ if (process.platform === "win32") {
33
+ const pathext = (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM")
34
+ .split(";")
35
+ .filter(Boolean);
36
+ for (const entry of entries) {
37
+ for (const ext of pathext) {
38
+ const candidate = path.join(entry, `${command}${ext}`);
39
+ if (fs.existsSync(candidate))
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ for (const entry of entries) {
46
+ const candidate = path.join(entry, command);
47
+ if (fs.existsSync(candidate))
48
+ return true;
49
+ }
50
+ return false;
51
+ }
52
+ /**
53
+ * Opens a URL in the default browser
54
+ * Silently fails if browser cannot be opened (user can copy URL manually)
55
+ * @param url - URL to open
56
+ * @returns True if a browser launch was attempted
57
+ */
58
+ export function openBrowserUrl(url) {
59
+ try {
60
+ const opener = getBrowserOpener();
61
+ if (!commandExists(opener)) {
62
+ return false;
63
+ }
64
+ const child = spawn(opener, [url], {
65
+ stdio: "ignore",
66
+ shell: process.platform === "win32",
67
+ });
68
+ child.on("error", () => { });
69
+ return true;
70
+ }
71
+ catch (error) {
72
+ // Silently fail - user can manually open the URL from instructions
73
+ return false;
74
+ }
75
+ }
76
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../lib/auth/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,gBAAgB,CAAC,MAAM,CAAC;IAC1D,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC;IACxD,OAAO,gBAAgB,CAAC,KAAK,CAAC;AAC/B,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE3B,iEAAiE;IACjE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC;QACvE,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,qBAAqB,CAAC;aAC5D,KAAK,CAAC,GAAG,CAAC;aACV,MAAM,CAAC,OAAO,CAAC,CAAC;QAClB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC;gBACvD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,OAAO,IAAI,CAAC;YAC3C,CAAC;QACF,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;IAC3C,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACzC,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAClC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE;YAClC,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACnC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,mEAAmE;QACnE,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { OAuthServerInfo } from "../types.js";
2
+ /**
3
+ * Start a small local HTTP server that waits for /auth/callback and returns the code
4
+ * @param options - OAuth state for validation
5
+ * @returns Promise that resolves to server info
6
+ */
7
+ export declare function startLocalOAuthServer({ state }: {
8
+ state: string;
9
+ }): Promise<OAuthServerInfo>;
10
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../lib/auth/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAMnD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAkE5F"}