better-opencode-openai-codex-auth 0.1.2 → 0.1.4

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 (49) hide show
  1. package/README.md +5 -17
  2. package/config/README.md +14 -93
  3. package/config/minimal-opencode.json +1 -1
  4. package/config/opencode-modern.json +26 -107
  5. package/dist/index.d.ts +0 -12
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +195 -94
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/account-pool.d.ts +29 -3
  10. package/dist/lib/account-pool.d.ts.map +1 -1
  11. package/dist/lib/account-pool.js +210 -47
  12. package/dist/lib/account-pool.js.map +1 -1
  13. package/dist/lib/auth/auth.d.ts +55 -4
  14. package/dist/lib/auth/auth.d.ts.map +1 -1
  15. package/dist/lib/auth/auth.js +130 -6
  16. package/dist/lib/auth/auth.js.map +1 -1
  17. package/dist/lib/auth/ui/account-menu.d.ts +50 -0
  18. package/dist/lib/auth/ui/account-menu.d.ts.map +1 -0
  19. package/dist/lib/auth/ui/account-menu.js +258 -0
  20. package/dist/lib/auth/ui/account-menu.js.map +1 -0
  21. package/dist/lib/auth/ui/ansi.d.ts +23 -0
  22. package/dist/lib/auth/ui/ansi.d.ts.map +1 -0
  23. package/dist/lib/auth/ui/ansi.js +37 -0
  24. package/dist/lib/auth/ui/ansi.js.map +1 -0
  25. package/dist/lib/auth/ui/confirm.d.ts +2 -0
  26. package/dist/lib/auth/ui/confirm.d.ts.map +1 -0
  27. package/dist/lib/auth/ui/confirm.js +8 -0
  28. package/dist/lib/auth/ui/confirm.js.map +1 -0
  29. package/dist/lib/auth/ui/select.d.ts +21 -0
  30. package/dist/lib/auth/ui/select.d.ts.map +1 -0
  31. package/dist/lib/auth/ui/select.js +208 -0
  32. package/dist/lib/auth/ui/select.js.map +1 -0
  33. package/dist/lib/constants.d.ts +51 -3
  34. package/dist/lib/constants.d.ts.map +1 -1
  35. package/dist/lib/constants.js +55 -3
  36. package/dist/lib/constants.js.map +1 -1
  37. package/dist/lib/refresh-queue.d.ts +56 -0
  38. package/dist/lib/refresh-queue.d.ts.map +1 -0
  39. package/dist/lib/refresh-queue.js +148 -0
  40. package/dist/lib/refresh-queue.js.map +1 -0
  41. package/dist/lib/request/fetch-helpers.d.ts +2 -1
  42. package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
  43. package/dist/lib/request/fetch-helpers.js +23 -3
  44. package/dist/lib/request/fetch-helpers.js.map +1 -1
  45. package/dist/lib/types.d.ts +18 -2
  46. package/dist/lib/types.d.ts.map +1 -1
  47. package/package.json +1 -2
  48. package/scripts/install-opencode-codex-auth.js +10 -29
  49. package/config/opencode-legacy.json +0 -571
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Interactive keyboard-driven selection menu for CLI.
3
+ * Ported from NoeFabris/opencode-antigravity-auth with minor adaptations.
4
+ */
5
+ export interface MenuItem<T = string> {
6
+ label: string;
7
+ value: T;
8
+ hint?: string;
9
+ disabled?: boolean;
10
+ separator?: boolean;
11
+ kind?: "heading";
12
+ color?: "red" | "green" | "yellow" | "cyan";
13
+ }
14
+ export interface SelectOptions {
15
+ message: string;
16
+ subtitle?: string;
17
+ help?: string;
18
+ clearScreen?: boolean;
19
+ }
20
+ export declare function select<T>(items: MenuItem<T>[], opts: SelectOptions): Promise<T | null>;
21
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../../lib/auth/ui/select.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,MAAM;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAuCD,wBAAsB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAgI5F"}
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Interactive keyboard-driven selection menu for CLI.
3
+ * Ported from NoeFabris/opencode-antigravity-auth with minor adaptations.
4
+ */
5
+ import { ANSI, isTTY, parseKey } from "./ansi.js";
6
+ const ESCAPE_TIMEOUT_MS = 50;
7
+ const ANSI_REGEX = /\x1b\[[0-9;]*m/g;
8
+ const ANSI_LEADING_REGEX = /^\x1b\[[0-9;]*m/;
9
+ function stripAnsi(s) {
10
+ return s.replace(ANSI_REGEX, "");
11
+ }
12
+ function truncateAnsi(s, max) {
13
+ if (max <= 0)
14
+ return "";
15
+ const visible = stripAnsi(s);
16
+ if (visible.length <= max)
17
+ return s;
18
+ const suffix = max >= 3 ? "..." : ".".repeat(max);
19
+ const keep = Math.max(0, max - suffix.length);
20
+ let out = "";
21
+ let i = 0;
22
+ let kept = 0;
23
+ while (i < s.length && kept < keep) {
24
+ if (s[i] === "\x1b") {
25
+ const m = s.slice(i).match(ANSI_LEADING_REGEX);
26
+ if (m) {
27
+ out += m[0];
28
+ i += m[0].length;
29
+ continue;
30
+ }
31
+ }
32
+ out += s[i];
33
+ i++;
34
+ kept++;
35
+ }
36
+ return (out.includes("\x1b[") ? `${out}${ANSI.reset}` : out) + suffix;
37
+ }
38
+ function colorCode(color) {
39
+ switch (color) {
40
+ case "red": return ANSI.red;
41
+ case "green": return ANSI.green;
42
+ case "yellow": return ANSI.yellow;
43
+ case "cyan": return ANSI.cyan;
44
+ default: return "";
45
+ }
46
+ }
47
+ export async function select(items, opts) {
48
+ if (!isTTY())
49
+ throw new Error("Interactive select requires a TTY terminal");
50
+ if (!items.length)
51
+ throw new Error("No menu items");
52
+ const selectable = (i) => !i.disabled && !i.separator && i.kind !== "heading";
53
+ const enabled = items.filter(selectable);
54
+ if (!enabled.length)
55
+ throw new Error("All items disabled");
56
+ if (enabled.length === 1)
57
+ return enabled[0].value;
58
+ const { stdin, stdout } = process;
59
+ let cursor = items.findIndex(selectable);
60
+ if (cursor === -1)
61
+ cursor = 0;
62
+ let escTimeout = null;
63
+ let cleaned = false;
64
+ let rendered = 0;
65
+ const render = () => {
66
+ const cols = stdout.columns ?? 80;
67
+ const rows = stdout.rows ?? 24;
68
+ const prev = rendered;
69
+ if (opts.clearScreen) {
70
+ stdout.write(ANSI.clearScreen + ANSI.moveTo(1, 1));
71
+ }
72
+ else if (prev > 0) {
73
+ stdout.write(ANSI.up(prev));
74
+ }
75
+ let lines = 0;
76
+ const wl = (line) => { stdout.write(`${ANSI.clearLine}${line}\n`); lines++; };
77
+ const subtitleLines = opts.subtitle ? 3 : 0;
78
+ const maxVisible = Math.max(1, Math.min(items.length, rows - 1 - subtitleLines - 3));
79
+ let winStart = 0;
80
+ let winEnd = items.length;
81
+ if (items.length > maxVisible) {
82
+ winStart = Math.max(0, Math.min(cursor - Math.floor(maxVisible / 2), items.length - maxVisible));
83
+ winEnd = winStart + maxVisible;
84
+ }
85
+ wl(`${ANSI.dim}┌ ${ANSI.reset}${truncateAnsi(opts.message, Math.max(1, cols - 4))}`);
86
+ if (opts.subtitle) {
87
+ wl(`${ANSI.dim}│${ANSI.reset}`);
88
+ wl(`${ANSI.cyan}◆${ANSI.reset} ${truncateAnsi(opts.subtitle, Math.max(1, cols - 4))}`);
89
+ wl("");
90
+ }
91
+ for (let i = winStart; i < winEnd; i++) {
92
+ const item = items[i];
93
+ if (!item)
94
+ continue;
95
+ if (item.separator) {
96
+ wl(`${ANSI.dim}│${ANSI.reset}`);
97
+ continue;
98
+ }
99
+ if (item.kind === "heading") {
100
+ wl(`${ANSI.cyan}│${ANSI.reset} ${truncateAnsi(`${ANSI.dim}${ANSI.bold}${item.label}${ANSI.reset}`, Math.max(1, cols - 6))}`);
101
+ continue;
102
+ }
103
+ const sel = i === cursor;
104
+ const cc = colorCode(item.color);
105
+ let label;
106
+ if (item.disabled) {
107
+ label = `${ANSI.dim}${item.label} (unavailable)${ANSI.reset}`;
108
+ }
109
+ else if (sel) {
110
+ label = cc ? `${cc}${item.label}${ANSI.reset}` : item.label;
111
+ if (item.hint)
112
+ label += ` ${ANSI.dim}${item.hint}${ANSI.reset}`;
113
+ }
114
+ else {
115
+ label = cc ? `${ANSI.dim}${cc}${item.label}${ANSI.reset}` : `${ANSI.dim}${item.label}${ANSI.reset}`;
116
+ if (item.hint)
117
+ label += ` ${ANSI.dim}${item.hint}${ANSI.reset}`;
118
+ }
119
+ label = truncateAnsi(label, Math.max(1, cols - 8));
120
+ if (sel) {
121
+ wl(`${ANSI.cyan}│${ANSI.reset} ${ANSI.green}●${ANSI.reset} ${label}`);
122
+ }
123
+ else {
124
+ wl(`${ANSI.cyan}│${ANSI.reset} ${ANSI.dim}○${ANSI.reset} ${label}`);
125
+ }
126
+ }
127
+ const windowHint = items.length > winEnd - winStart ? ` (${winStart + 1}-${winEnd}/${items.length})` : "";
128
+ const help = truncateAnsi((opts.help ?? `↑↓ navigate Enter confirm Esc cancel`) + windowHint, Math.max(1, cols - 6));
129
+ wl(`${ANSI.cyan}│${ANSI.reset} ${ANSI.dim}${help}${ANSI.reset}`);
130
+ wl(`${ANSI.cyan}└${ANSI.reset}`);
131
+ if (!opts.clearScreen && prev > lines) {
132
+ for (let i = 0; i < prev - lines; i++)
133
+ wl("");
134
+ }
135
+ rendered = lines;
136
+ };
137
+ return new Promise((resolve) => {
138
+ const wasRaw = stdin.isRaw ?? false;
139
+ const cleanup = () => {
140
+ if (cleaned)
141
+ return;
142
+ cleaned = true;
143
+ if (escTimeout) {
144
+ clearTimeout(escTimeout);
145
+ escTimeout = null;
146
+ }
147
+ try {
148
+ stdin.removeListener("data", onKey);
149
+ stdin.setRawMode(wasRaw);
150
+ stdin.pause();
151
+ stdout.write(ANSI.show);
152
+ }
153
+ catch { }
154
+ process.removeListener("SIGINT", onSignal);
155
+ process.removeListener("SIGTERM", onSignal);
156
+ };
157
+ const onSignal = () => { cleanup(); resolve(null); };
158
+ const finish = (v) => { cleanup(); resolve(v); };
159
+ const nextSel = (from, dir) => {
160
+ let n = from;
161
+ do {
162
+ n = (n + dir + items.length) % items.length;
163
+ } while (items[n]?.disabled || items[n]?.separator || items[n]?.kind === "heading");
164
+ return n;
165
+ };
166
+ const onKey = (data) => {
167
+ if (escTimeout) {
168
+ clearTimeout(escTimeout);
169
+ escTimeout = null;
170
+ }
171
+ const action = parseKey(data);
172
+ switch (action) {
173
+ case "up":
174
+ cursor = nextSel(cursor, -1);
175
+ render();
176
+ return;
177
+ case "down":
178
+ cursor = nextSel(cursor, 1);
179
+ render();
180
+ return;
181
+ case "enter":
182
+ finish(items[cursor]?.value ?? null);
183
+ return;
184
+ case "escape":
185
+ finish(null);
186
+ return;
187
+ case "escape-start":
188
+ escTimeout = setTimeout(() => finish(null), ESCAPE_TIMEOUT_MS);
189
+ return;
190
+ }
191
+ };
192
+ process.once("SIGINT", onSignal);
193
+ process.once("SIGTERM", onSignal);
194
+ try {
195
+ stdin.setRawMode(true);
196
+ }
197
+ catch {
198
+ cleanup();
199
+ resolve(null);
200
+ return;
201
+ }
202
+ stdin.resume();
203
+ stdout.write(ANSI.hide);
204
+ render();
205
+ stdin.on("data", onKey);
206
+ });
207
+ }
208
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../lib/auth/ui/select.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@
4
4
  */
5
5
  /** Plugin identifier for logging and error messages */
6
6
  export declare const PLUGIN_NAME = "openai-codex-plugin";
7
+ /** Plugin version — keep in sync with package.json */
8
+ export declare const PLUGIN_VERSION = "0.1.4";
7
9
  /** Base URL for ChatGPT backend API */
8
10
  export declare const CODEX_BASE_URL = "https://chatgpt.com/backend-api";
9
11
  /** Dummy API key used for OpenAI SDK (actual auth via OAuth) */
@@ -28,12 +30,15 @@ export declare const OPENAI_HEADERS: {
28
30
  /** OpenAI-specific header values */
29
31
  export declare const OPENAI_HEADER_VALUES: {
30
32
  readonly BETA_RESPONSES: "responses=experimental";
31
- readonly ORIGINATOR_CODEX: "codex_cli_rs";
33
+ /** Match the first-party opencode CodexAuthPlugin — do not spoof codex_cli_rs */
34
+ readonly ORIGINATOR_CODEX: "opencode";
32
35
  };
33
36
  /** URL path segments */
34
37
  export declare const URL_PATHS: {
35
38
  readonly RESPONSES: "/responses";
36
39
  readonly CODEX_RESPONSES: "/codex/responses";
40
+ /** Alternate path opencode may use (chat completions compat layer) */
41
+ readonly CHAT_COMPLETIONS: "/chat/completions";
37
42
  };
38
43
  /** JWT claim path for ChatGPT account ID */
39
44
  export declare const JWT_CLAIM_PATH: "https://api.openai.com/auth";
@@ -58,11 +63,15 @@ export declare const PLATFORM_OPENERS: {
58
63
  };
59
64
  /** OAuth authorization labels */
60
65
  export declare const AUTH_LABELS: {
61
- readonly OAUTH: "ChatGPT Plus/Pro (Codex Subscription)";
62
- readonly OAUTH_MANUAL: "ChatGPT Plus/Pro (Manual URL Paste)";
66
+ readonly MANAGE_ACCOUNTS: "Manage accounts (view / remove)";
67
+ readonly OAUTH: "ChatGPT Plus/Pro (browser)";
68
+ readonly OAUTH_MANUAL: "ChatGPT Plus/Pro (manual URL paste)";
69
+ /** Headless device-code flow — no browser required */
70
+ readonly OAUTH_DEVICE: "ChatGPT Plus/Pro (headless / device code)";
63
71
  readonly API_KEY: "Manually enter API Key";
64
72
  readonly INSTRUCTIONS: "A browser window should open. If it doesn't, copy the URL and open it manually.";
65
73
  readonly INSTRUCTIONS_MANUAL: "After logging in, copy the full redirect URL and paste it here.";
74
+ readonly INSTRUCTIONS_DEVICE: "Go to the URL shown and enter the code to authenticate without a browser.";
66
75
  };
67
76
  /** OAuth callback server configuration */
68
77
  export declare const OAUTH_SERVER: {
@@ -73,6 +82,19 @@ export declare const OAUTH_SERVER: {
73
82
  /** Port for local OAuth callback server */
74
83
  readonly PORT: 1455;
75
84
  };
85
+ /** Device authorization flow configuration (headless auth) */
86
+ export declare const DEVICE_AUTH: {
87
+ /** Endpoint to request a user code */
88
+ readonly USERCODE_URL: "https://auth.openai.com/api/accounts/deviceauth/usercode";
89
+ /** Endpoint to poll for token after user completes device auth */
90
+ readonly TOKEN_URL: "https://auth.openai.com/api/accounts/deviceauth/token";
91
+ /** URL the user visits to enter the code */
92
+ readonly ACTIVATE_URL: "https://auth.openai.com/codex/device";
93
+ /** redirect_uri for device-flow token exchange */
94
+ readonly REDIRECT_URI: "https://auth.openai.com/deviceauth/callback";
95
+ /** Extra milliseconds added to the server-supplied poll interval (safety margin) */
96
+ readonly POLL_SAFETY_MARGIN_MS: 3000;
97
+ };
76
98
  /** Stream and output size limits */
77
99
  export declare const SIZE_LIMITS: {
78
100
  /** Maximum SSE stream size in bytes before rejecting (50MB) */
@@ -89,4 +111,30 @@ export declare const CACHE_TTL: {
89
111
  /** GitHub cache time-to-live in milliseconds (15 minutes) */
90
112
  readonly MS: number;
91
113
  };
114
+ /**
115
+ * Consecutive-failure tracking for per-account auth cooldown.
116
+ * After MAX_FAILURES consecutive failures, the account is skipped for COOLDOWN_MS.
117
+ * The failure counter resets if no failure occurred in the last FAILURE_RESET_MS.
118
+ */
119
+ export declare const ACCOUNT_FAILURE: {
120
+ readonly MAX_FAILURES: 5;
121
+ /** How long to skip a failing account (ms) */
122
+ readonly COOLDOWN_MS: 30000;
123
+ /** Window after which the consecutive-failure counter resets (ms) */
124
+ readonly FAILURE_RESET_MS: 7200000;
125
+ };
126
+ /**
127
+ * Tiered rate-limit cooldown durations keyed by ChatGPT error code.
128
+ *
129
+ * - usage_limit_reached → billing quota exhausted → 4-hour cooldown
130
+ * - usage_not_included → plan doesn't include Codex → 24-hour cooldown
131
+ * - rate_limit_exceeded → RPM/TPM throttle → 60-second cooldown
132
+ * - default → honour retry-after header, or fall back to 60 s
133
+ */
134
+ export declare const RATE_LIMIT_TIERS: Record<string, number>;
135
+ /**
136
+ * Maximum time to wait for any account to recover from rate-limiting before
137
+ * giving up and returning a 429 to the caller (#11 wait-for-recovery).
138
+ */
139
+ export declare const MAX_RECOVERY_WAIT_MS: number;
92
140
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uDAAuD;AACvD,eAAO,MAAM,WAAW,wBAAwB,CAAC;AAEjD,uCAAuC;AACvC,eAAO,MAAM,cAAc,oCAAoC,CAAC;AAEhE,gEAAgE;AAChE,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAE7C,6CAA6C;AAC7C,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC,wBAAwB;AACxB,eAAO,MAAM,WAAW;;;;;CAKd,CAAC;AAEX,8BAA8B;AAC9B,eAAO,MAAM,cAAc;;;;;;CAMjB,CAAC;AAEX,oCAAoC;AACpC,eAAO,MAAM,oBAAoB;;;CAGvB,CAAC;AAEX,wBAAwB;AACxB,eAAO,MAAM,SAAS;;;CAGZ,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,cAAc,EAAG,6BAAsC,CAAC;AAErE,qBAAqB;AACrB,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,qCAAqC;AACrC,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX,gDAAgD;AAChD,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAEX,iCAAiC;AACjC,eAAO,MAAM,WAAW;;;;;;CAQd,CAAC;AAEX,0CAA0C;AAC1C,eAAO,MAAM,YAAY;IACxB,uEAAuE;;IAEvE,sEAAsE;;IAEtE,2CAA2C;;CAElC,CAAC;AAEX,oCAAoC;AACpC,eAAO,MAAM,WAAW;IACvB,+DAA+D;;IAE/D,iEAAiE;;CAExD,CAAC;AAEX,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,QAA4E,CAAC;AAE7G,8BAA8B;AAC9B,eAAO,MAAM,SAAS;IACrB,2CAA2C;;IAE3C,6DAA6D;;CAEpD,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uDAAuD;AACvD,eAAO,MAAM,WAAW,wBAAwB,CAAC;AAEjD,sDAAsD;AACtD,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,uCAAuC;AACvC,eAAO,MAAM,cAAc,oCAAoC,CAAC;AAEhE,gEAAgE;AAChE,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAE7C,6CAA6C;AAC7C,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC,wBAAwB;AACxB,eAAO,MAAM,WAAW;;;;;CAKd,CAAC;AAEX,8BAA8B;AAC9B,eAAO,MAAM,cAAc;;;;;;CAMjB,CAAC;AAEX,oCAAoC;AACpC,eAAO,MAAM,oBAAoB;;IAEhC,iFAAiF;;CAExE,CAAC;AAEX,wBAAwB;AACxB,eAAO,MAAM,SAAS;;;IAGrB,sEAAsE;;CAE7D,CAAC;AAEX,4CAA4C;AAC5C,eAAO,MAAM,cAAc,EAAG,6BAAsC,CAAC;AAErE,qBAAqB;AACrB,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,qCAAqC;AACrC,eAAO,MAAM,UAAU;;;;;CAKb,CAAC;AAEX,gDAAgD;AAChD,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAEX,iCAAiC;AACjC,eAAO,MAAM,WAAW;;;;IAIvB,sDAAsD;;;;;;CAS7C,CAAC;AAEX,0CAA0C;AAC1C,eAAO,MAAM,YAAY;IACxB,uEAAuE;;IAEvE,sEAAsE;;IAEtE,2CAA2C;;CAElC,CAAC;AAEX,8DAA8D;AAC9D,eAAO,MAAM,WAAW;IACvB,sCAAsC;;IAEtC,kEAAkE;;IAElE,4CAA4C;;IAE5C,kDAAkD;;IAElD,oFAAoF;;CAE3E,CAAC;AAEX,oCAAoC;AACpC,eAAO,MAAM,WAAW;IACvB,+DAA+D;;IAE/D,iEAAiE;;CAExD,CAAC;AAEX,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,QAA4E,CAAC;AAE7G,8BAA8B;AAC9B,eAAO,MAAM,SAAS;IACrB,2CAA2C;;IAE3C,6DAA6D;;CAEpD,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,eAAe;;IAE3B,8CAA8C;;IAE9C,qEAAqE;;CAE5D,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAInD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAAgB,CAAC"}
@@ -4,6 +4,8 @@
4
4
  */
5
5
  /** Plugin identifier for logging and error messages */
6
6
  export const PLUGIN_NAME = "openai-codex-plugin";
7
+ /** Plugin version — keep in sync with package.json */
8
+ export const PLUGIN_VERSION = "0.1.4";
7
9
  /** Base URL for ChatGPT backend API */
8
10
  export const CODEX_BASE_URL = "https://chatgpt.com/backend-api";
9
11
  /** Dummy API key used for OpenAI SDK (actual auth via OAuth) */
@@ -28,12 +30,15 @@ export const OPENAI_HEADERS = {
28
30
  /** OpenAI-specific header values */
29
31
  export const OPENAI_HEADER_VALUES = {
30
32
  BETA_RESPONSES: "responses=experimental",
31
- ORIGINATOR_CODEX: "codex_cli_rs",
33
+ /** Match the first-party opencode CodexAuthPlugin — do not spoof codex_cli_rs */
34
+ ORIGINATOR_CODEX: "opencode",
32
35
  };
33
36
  /** URL path segments */
34
37
  export const URL_PATHS = {
35
38
  RESPONSES: "/responses",
36
39
  CODEX_RESPONSES: "/codex/responses",
40
+ /** Alternate path opencode may use (chat completions compat layer) */
41
+ CHAT_COMPLETIONS: "/chat/completions",
37
42
  };
38
43
  /** JWT claim path for ChatGPT account ID */
39
44
  export const JWT_CLAIM_PATH = "https://api.openai.com/auth";
@@ -58,11 +63,15 @@ export const PLATFORM_OPENERS = {
58
63
  };
59
64
  /** OAuth authorization labels */
60
65
  export const AUTH_LABELS = {
61
- OAUTH: "ChatGPT Plus/Pro (Codex Subscription)",
62
- OAUTH_MANUAL: "ChatGPT Plus/Pro (Manual URL Paste)",
66
+ MANAGE_ACCOUNTS: "Manage accounts (view / remove)",
67
+ OAUTH: "ChatGPT Plus/Pro (browser)",
68
+ OAUTH_MANUAL: "ChatGPT Plus/Pro (manual URL paste)",
69
+ /** Headless device-code flow — no browser required */
70
+ OAUTH_DEVICE: "ChatGPT Plus/Pro (headless / device code)",
63
71
  API_KEY: "Manually enter API Key",
64
72
  INSTRUCTIONS: "A browser window should open. If it doesn't, copy the URL and open it manually.",
65
73
  INSTRUCTIONS_MANUAL: "After logging in, copy the full redirect URL and paste it here.",
74
+ INSTRUCTIONS_DEVICE: "Go to the URL shown and enter the code to authenticate without a browser.",
66
75
  };
67
76
  /** OAuth callback server configuration */
68
77
  export const OAUTH_SERVER = {
@@ -73,6 +82,19 @@ export const OAUTH_SERVER = {
73
82
  /** Port for local OAuth callback server */
74
83
  PORT: 1455,
75
84
  };
85
+ /** Device authorization flow configuration (headless auth) */
86
+ export const DEVICE_AUTH = {
87
+ /** Endpoint to request a user code */
88
+ USERCODE_URL: "https://auth.openai.com/api/accounts/deviceauth/usercode",
89
+ /** Endpoint to poll for token after user completes device auth */
90
+ TOKEN_URL: "https://auth.openai.com/api/accounts/deviceauth/token",
91
+ /** URL the user visits to enter the code */
92
+ ACTIVATE_URL: "https://auth.openai.com/codex/device",
93
+ /** redirect_uri for device-flow token exchange */
94
+ REDIRECT_URI: "https://auth.openai.com/deviceauth/callback",
95
+ /** Extra milliseconds added to the server-supplied poll interval (safety margin) */
96
+ POLL_SAFETY_MARGIN_MS: 3_000,
97
+ };
76
98
  /** Stream and output size limits */
77
99
  export const SIZE_LIMITS = {
78
100
  /** Maximum SSE stream size in bytes before rejecting (50MB) */
@@ -89,4 +111,34 @@ export const CACHE_TTL = {
89
111
  /** GitHub cache time-to-live in milliseconds (15 minutes) */
90
112
  MS: 15 * 60 * 1000,
91
113
  };
114
+ /**
115
+ * Consecutive-failure tracking for per-account auth cooldown.
116
+ * After MAX_FAILURES consecutive failures, the account is skipped for COOLDOWN_MS.
117
+ * The failure counter resets if no failure occurred in the last FAILURE_RESET_MS.
118
+ */
119
+ export const ACCOUNT_FAILURE = {
120
+ MAX_FAILURES: 5,
121
+ /** How long to skip a failing account (ms) */
122
+ COOLDOWN_MS: 30_000,
123
+ /** Window after which the consecutive-failure counter resets (ms) */
124
+ FAILURE_RESET_MS: 7_200_000, // 2 hours
125
+ };
126
+ /**
127
+ * Tiered rate-limit cooldown durations keyed by ChatGPT error code.
128
+ *
129
+ * - usage_limit_reached → billing quota exhausted → 4-hour cooldown
130
+ * - usage_not_included → plan doesn't include Codex → 24-hour cooldown
131
+ * - rate_limit_exceeded → RPM/TPM throttle → 60-second cooldown
132
+ * - default → honour retry-after header, or fall back to 60 s
133
+ */
134
+ export const RATE_LIMIT_TIERS = {
135
+ usage_limit_reached: 4 * 60 * 60 * 1000, // 4 hours
136
+ usage_not_included: 24 * 60 * 60 * 1000, // 24 hours
137
+ rate_limit_exceeded: 60_000, // 60 seconds
138
+ };
139
+ /**
140
+ * Maximum time to wait for any account to recover from rate-limiting before
141
+ * giving up and returning a 429 to the caller (#11 wait-for-recovery).
142
+ */
143
+ export const MAX_RECOVERY_WAIT_MS = 5 * 60 * 1000; // 5 minutes
92
144
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../lib/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uDAAuD;AACvD,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAEjD,uCAAuC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,iCAAiC,CAAC;AAEhE,gEAAgE;AAChE,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAE7C,6CAA6C;AAC7C,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC,wBAAwB;AACxB,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,EAAE,EAAE,GAAG;IACP,YAAY,EAAE,GAAG;IACjB,SAAS,EAAE,GAAG;IACd,iBAAiB,EAAE,GAAG;CACb,CAAC;AAEX,8BAA8B;AAC9B,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,IAAI,EAAE,aAAa;IACnB,UAAU,EAAE,oBAAoB;IAChC,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,eAAe,EAAE,iBAAiB;CACzB,CAAC;AAEX,oCAAoC;AACpC,MAAM,CAAC,MAAM,oBAAoB,GAAG;IACnC,cAAc,EAAE,wBAAwB;IACxC,gBAAgB,EAAE,cAAc;CACvB,CAAC;AAEX,wBAAwB;AACxB,MAAM,CAAC,MAAM,SAAS,GAAG;IACxB,SAAS,EAAE,YAAY;IACvB,eAAe,EAAE,kBAAkB;CAC1B,CAAC;AAEX,4CAA4C;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,6BAAsC,CAAC;AAErE,qBAAqB;AACrB,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,aAAa,EAAE,wCAAwC;IACvD,oBAAoB,EAAE,kDAAkD;IACxE,mBAAmB,EAAE,uBAAuB;CACnC,CAAC;AAEX,qCAAqC;AACrC,MAAM,CAAC,MAAM,UAAU,GAAG;IACzB,gBAAgB,EAAE,kBAAkB;IACpC,eAAe,EAAE,iBAAiB;IAClC,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,gBAAgB;CACvB,CAAC;AAEX,gDAAgD;AAChD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC/B,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,UAAU;CACR,CAAC;AAEX,iCAAiC;AACjC,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,KAAK,EAAE,uCAAuC;IAC9C,YAAY,EAAE,qCAAqC;IACnD,OAAO,EAAE,wBAAwB;IACjC,YAAY,EACX,iFAAiF;IAClF,mBAAmB,EAClB,iEAAiE;CACzD,CAAC;AAEX,0CAA0C;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B,uEAAuE;IACvE,gBAAgB,EAAE,GAAG;IACrB,sEAAsE;IACtE,mBAAmB,EAAE,GAAG;IACxB,2CAA2C;IAC3C,IAAI,EAAE,IAAI;CACD,CAAC;AAEX,oCAAoC;AACpC,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,+DAA+D;IAC/D,oBAAoB,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;IACtC,iEAAiE;IACjE,sBAAsB,EAAE,MAAM;CACrB,CAAC;AAEX,sEAAsE;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAG,yEAAyE,CAAC;AAE7G,8BAA8B;AAC9B,MAAM,CAAC,MAAM,SAAS,GAAG;IACxB,2CAA2C;IAC3C,OAAO,EAAE,EAAE;IACX,6DAA6D;IAC7D,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI;CACT,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../lib/constants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Proactive Token Refresh Queue (#8)
3
+ *
4
+ * Runs as a background timer and refreshes OAuth tokens that are approaching
5
+ * expiry. This ensures user requests are never blocked by an in-flight token
6
+ * refresh — the pool always has fresh credentials ready.
7
+ *
8
+ * Adapted from the LLM-API-Key-Proxy pattern used in
9
+ * NoeFabris/opencode-antigravity-auth, stripped of Google-specific logic.
10
+ *
11
+ * Key properties:
12
+ * - Non-blocking: runs independently of the request path
13
+ * - Serialized: only one refresh pass runs at a time (no concurrent storms)
14
+ * - Per-account: skips expired or already-up-to-date tokens
15
+ * - Configurable: buffer window and check interval are tunable
16
+ */
17
+ import type { AccountPool } from "./account-pool.js";
18
+ /** Configuration for the proactive refresh queue */
19
+ export interface ProactiveRefreshConfig {
20
+ /** Enable proactive token refresh (default: true) */
21
+ enabled: boolean;
22
+ /** Seconds before expiry to trigger proactive refresh (default: 1800 = 30 min) */
23
+ bufferSeconds: number;
24
+ /** Interval between refresh checks in seconds (default: 300 = 5 min) */
25
+ checkIntervalSeconds: number;
26
+ }
27
+ export declare const DEFAULT_PROACTIVE_REFRESH_CONFIG: ProactiveRefreshConfig;
28
+ /**
29
+ * Proactive Token Refresh Queue.
30
+ *
31
+ * Usage:
32
+ * const queue = new ProactiveRefreshQueue(accountPool);
33
+ * queue.start();
34
+ * // ... plugin runs ...
35
+ * queue.stop(); // optional, on process exit
36
+ */
37
+ export declare class ProactiveRefreshQueue {
38
+ private readonly config;
39
+ private readonly pool;
40
+ private isRunning;
41
+ private isRefreshing;
42
+ private intervalHandle;
43
+ constructor(pool: AccountPool, config?: Partial<ProactiveRefreshConfig>);
44
+ /**
45
+ * Start the background refresh loop.
46
+ * An initial check runs 5 s after start (letting things settle).
47
+ */
48
+ start(): void;
49
+ stop(): void;
50
+ /** Whether the queue is currently running */
51
+ get running(): boolean;
52
+ private needsRefresh;
53
+ private isAlreadyExpired;
54
+ private runRefreshCheck;
55
+ }
56
+ //# sourceMappingURL=refresh-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh-queue.d.ts","sourceRoot":"","sources":["../../lib/refresh-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,oDAAoD;AACpD,MAAM,WAAW,sBAAsB;IACtC,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,oBAAoB,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,gCAAgC,EAAE,sBAI9C,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IAEnC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAA+C;gBAEzD,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC;IAKvE;;;OAGG;IACH,KAAK,IAAI,IAAI;IA2Bb,IAAI,IAAI,IAAI;IAUZ,6CAA6C;IAC7C,IAAI,OAAO,IAAI,OAAO,CAErB;IAID,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;YAKV,eAAe;CAoD7B"}