codex-multi-auth 2.19.0 → 2.20.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 (107) hide show
  1. package/.codex-plugin/plugin.json +9 -9
  2. package/LICENSE +21 -21
  3. package/README.md +149 -148
  4. package/assets/codex-multi-auth-icon.svg +39 -39
  5. package/assets/readme-hero.svg +31 -31
  6. package/config/README.md +31 -31
  7. package/config/codex-legacy.json +1021 -1021
  8. package/config/codex-modern.json +347 -347
  9. package/config/minimal-codex.json +15 -15
  10. package/dist/index.js +1 -1
  11. package/dist/lib/accounts/rate-limits.js +5 -0
  12. package/dist/lib/accounts.js +5 -4
  13. package/dist/lib/auth/account-access.js +2 -2
  14. package/dist/lib/codex-cli/version.d.ts +22 -0
  15. package/dist/lib/codex-cli/version.js +78 -0
  16. package/dist/lib/codex-manager/commands/limits.d.ts +2 -0
  17. package/dist/lib/codex-manager/commands/limits.js +31 -0
  18. package/dist/lib/codex-manager/commands/status.js +1 -1
  19. package/dist/lib/codex-manager/dashboard-settings-data.js +2 -0
  20. package/dist/lib/codex-manager/formatters/subscription-status.d.ts +2 -2
  21. package/dist/lib/codex-manager/formatters/text-style.js +4 -1
  22. package/dist/lib/codex-manager/settings-hub/dashboard.d.ts +1 -1
  23. package/dist/lib/codex-manager/settings-hub/dashboard.js +4 -0
  24. package/dist/lib/codex-manager/settings-panels.d.ts +1 -0
  25. package/dist/lib/codex-manager/settings-panels.js +1 -0
  26. package/dist/lib/codex-manager/theme-settings-panel.d.ts +2 -1
  27. package/dist/lib/codex-manager/theme-settings-panel.js +39 -0
  28. package/dist/lib/codex-manager.js +2 -0
  29. package/dist/lib/constants.d.ts +2 -0
  30. package/dist/lib/constants.js +2 -0
  31. package/dist/lib/context-budget/model-context-windows.d.ts +1 -1
  32. package/dist/lib/context-budget/model-context-windows.js +4 -0
  33. package/dist/lib/context-budget-response.js +8 -8
  34. package/dist/lib/context-overflow.js +10 -10
  35. package/dist/lib/dashboard-settings.d.ts +2 -0
  36. package/dist/lib/dashboard-settings.js +18 -0
  37. package/dist/lib/luna-reserve.d.ts +26 -0
  38. package/dist/lib/luna-reserve.js +68 -0
  39. package/dist/lib/model-route-policy.d.ts +5 -5
  40. package/dist/lib/oauth-success.html +125 -125
  41. package/dist/lib/policy/runtime-policy.js +14 -0
  42. package/dist/lib/prompts/codex-host-bridge.js +138 -138
  43. package/dist/lib/prompts/codex.js +79 -79
  44. package/dist/lib/quota-readiness.d.ts +2 -2
  45. package/dist/lib/request/helpers/model-map.d.ts +1 -1
  46. package/dist/lib/request/helpers/model-map.js +12 -0
  47. package/dist/lib/request/response-outcome.d.ts +1 -1
  48. package/dist/lib/request/response-outcome.js +4 -1
  49. package/dist/lib/request/url-rewriting.js +3 -1
  50. package/dist/lib/runtime/account-model-catalog.d.ts +5 -5
  51. package/dist/lib/runtime/account-reset-credits.d.ts +2 -2
  52. package/dist/lib/runtime/account-status.js +2 -1
  53. package/dist/lib/runtime/luna-reserve-usage.d.ts +9 -0
  54. package/dist/lib/runtime/luna-reserve-usage.js +68 -0
  55. package/dist/lib/runtime/model-discovery-status.d.ts +11 -7
  56. package/dist/lib/runtime/model-discovery-status.js +13 -5
  57. package/dist/lib/runtime/reset-credit-routing.js +4 -1
  58. package/dist/lib/runtime/reset-credits.d.ts +7 -7
  59. package/dist/lib/runtime/resume-picker.js +1 -1
  60. package/dist/lib/runtime/rotation-server-types.d.ts +2 -0
  61. package/dist/lib/runtime/runtime-observability.d.ts +2 -0
  62. package/dist/lib/runtime/runtime-observability.js +1 -0
  63. package/dist/lib/runtime/workspace-model-scopes.d.ts +3 -3
  64. package/dist/lib/runtime-rotation-proxy.js +200 -32
  65. package/dist/lib/schemas.d.ts +65 -65
  66. package/dist/lib/ui/index.d.ts +1 -1
  67. package/dist/lib/ui/index.js +1 -1
  68. package/dist/lib/ui/runtime.d.ts +3 -1
  69. package/dist/lib/ui/runtime.js +11 -1
  70. package/dist/lib/ui/theme.d.ts +20 -1
  71. package/dist/lib/ui/theme.js +154 -30
  72. package/dist/lib/ui/ui-copy.d.ts +3 -2
  73. package/dist/lib/ui/ui-copy.js +3 -2
  74. package/dist/lib/usage/pricing.d.ts +1 -1
  75. package/dist/lib/usage/pricing.js +4 -0
  76. package/dist/lib/usage/usage-extraction.d.ts +2 -0
  77. package/dist/lib/usage/usage-extraction.js +25 -1
  78. package/dist/lib/utils.d.ts +1 -1
  79. package/dist/lib/utils.js +1 -1
  80. package/node_modules/@codex-ai/plugin/dist/index.d.ts +2 -2
  81. package/node_modules/@codex-ai/plugin/dist/index.js +2 -2
  82. package/node_modules/@codex-ai/plugin/dist/tool.d.ts +42 -42
  83. package/node_modules/@codex-ai/plugin/dist/tool.js +29 -29
  84. package/node_modules/@codex-ai/plugin/package.json +9 -9
  85. package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -4
  86. package/node_modules/@codex-ai/sdk/dist/index.js +2 -2
  87. package/node_modules/@codex-ai/sdk/package.json +8 -8
  88. package/package.json +207 -206
  89. package/scripts/codex-app-launcher.js +653 -653
  90. package/scripts/codex-app-router.js +374 -373
  91. package/scripts/codex-bin-resolver.js +332 -332
  92. package/scripts/codex-multi-auth.js +65 -65
  93. package/scripts/codex-routing.js +62 -62
  94. package/scripts/codex.js +7006 -7005
  95. package/scripts/install-codex-auth-utils.js +213 -213
  96. package/scripts/mcodex.js +367 -367
  97. package/scripts/postinstall.js +114 -114
  98. package/scripts/preuninstall.js +265 -265
  99. package/skills/codex-auth-setup/SKILL.md +73 -73
  100. package/vendor/codex-ai-plugin/dist/index.d.ts +2 -2
  101. package/vendor/codex-ai-plugin/dist/index.js +2 -2
  102. package/vendor/codex-ai-plugin/dist/tool.d.ts +42 -42
  103. package/vendor/codex-ai-plugin/dist/tool.js +29 -29
  104. package/vendor/codex-ai-plugin/package.json +9 -9
  105. package/vendor/codex-ai-sdk/dist/index.d.ts +4 -4
  106. package/vendor/codex-ai-sdk/dist/index.js +2 -2
  107. package/vendor/codex-ai-sdk/package.json +8 -8
@@ -48,6 +48,47 @@ function getGlyphs(mode) {
48
48
  cross: "x",
49
49
  };
50
50
  }
51
+ /** Perceived luminance (0.299/0.587/0.114) of the standard 16-color palette. */
52
+ const ANSI16_LUMINANCE = [
53
+ 0, 38, 75, 113, 15, 53, 90, 192, 128, 76, 150, 226, 29, 105, 179, 255,
54
+ ];
55
+ /**
56
+ * Interpret the `COLORFGBG` env convention (`"<fg>;<bg>"`, sometimes
57
+ * `"<fg>;default;<bg>"`) and report whether the terminal background is light.
58
+ * Returns `undefined` when the variable is absent or cannot be parsed.
59
+ */
60
+ function detectLightBackgroundFromEnv(env) {
61
+ const raw = env.COLORFGBG?.trim();
62
+ if (!raw)
63
+ return undefined;
64
+ const bgField = raw.split(";").pop()?.trim() ?? "";
65
+ if (!/^\d{1,2}$/.test(bgField))
66
+ return undefined;
67
+ const bg = Number.parseInt(bgField, 10);
68
+ const luminance = ANSI16_LUMINANCE[bg];
69
+ if (luminance === undefined)
70
+ return undefined;
71
+ return luminance >= 128;
72
+ }
73
+ /**
74
+ * Resolve the effective color mode for a theme.
75
+ *
76
+ * Resolution order:
77
+ * - `CODEX_TUI_COLOR_MODE` env override (`"auto"`, `"dark"`, or `"light"`)
78
+ * - the requested `mode` (`"dark"`/`"light"` win outright)
79
+ * - `COLORFGBG` terminal-background detection
80
+ * - `"dark"` (preserves the historical dark-on-dark styling by default)
81
+ */
82
+ export function resolveUiColorMode(mode = "auto", env = process.env) {
83
+ const envValue = env.CODEX_TUI_COLOR_MODE?.trim().toLowerCase();
84
+ const envMode = envValue === "dark" || envValue === "light" || envValue === "auto"
85
+ ? envValue
86
+ : undefined;
87
+ const requested = envMode ?? mode;
88
+ if (requested !== "auto")
89
+ return requested;
90
+ return detectLightBackgroundFromEnv(env) === true ? "light" : "dark";
91
+ }
51
92
  /**
52
93
  * Selects the ANSI escape sequence for the requested accent color according to the color profile.
53
94
  *
@@ -55,9 +96,47 @@ function getGlyphs(mode) {
55
96
  *
56
97
  * @param profile - The color profile to use (`"truecolor"`, `"ansi256"`, or `"ansi16"`)
57
98
  * @param accent - The accent name to resolve (`"green"`, `"cyan"`, `"blue"`, or `"yellow"`)
99
+ * @param mode - The resolved background mode; `"light"` shifts accent colors darker so they stay readable on light terminal backgrounds
58
100
  * @returns The escape sequence for the accent color suitable for use as a foreground color
59
101
  */
60
- function accentColorForProfile(profile, accent) {
102
+ function accentColorForProfile(profile, accent, mode) {
103
+ if (mode === "light") {
104
+ switch (profile) {
105
+ case "truecolor":
106
+ switch (accent) {
107
+ case "cyan":
108
+ return truecolor(14, 116, 144);
109
+ case "blue":
110
+ return truecolor(29, 78, 216);
111
+ case "yellow":
112
+ return truecolor(180, 83, 9);
113
+ default:
114
+ return truecolor(21, 128, 61);
115
+ }
116
+ case "ansi256":
117
+ switch (accent) {
118
+ case "cyan":
119
+ return ansi256(31);
120
+ case "blue":
121
+ return ansi256(25);
122
+ case "yellow":
123
+ return ansi256(166);
124
+ default:
125
+ return ansi256(28);
126
+ }
127
+ default:
128
+ switch (accent) {
129
+ case "cyan":
130
+ return ansi16(36);
131
+ case "blue":
132
+ return ansi16(34);
133
+ case "yellow":
134
+ return ansi16(33);
135
+ default:
136
+ return ansi16(32);
137
+ }
138
+ }
139
+ }
61
140
  switch (profile) {
62
141
  case "truecolor":
63
142
  switch (accent) {
@@ -102,57 +181,95 @@ function accentColorForProfile(profile, accent) {
102
181
  * @param profile - The color capability profile to target (`"ansi16" | "ansi256" | "truecolor"`)
103
182
  * @param palette - The UI palette selection that influences primary/success/border colors (`"green" | "blue"`)
104
183
  * @param accent - The accent color choice used for the `accent` token (`"green" | "cyan" | "blue" | "yellow"`)
184
+ * @param mode - The resolved background mode; `"light"` darkens colors painted directly on the terminal background while badge/focus colors keep their own dark backgrounds
105
185
  * @returns A UiThemeColors object containing resolved color tokens (e.g., `reset`, `dim`, `muted`, `heading`, `primary`, `accent`, `success`, `warning`, `danger`, `border`, `focusBg`, and `focusText`)
106
186
  */
107
- function getColors(profile, palette, accent) {
108
- const accentColor = accentColorForProfile(profile, accent);
187
+ function getColors(profile, palette, accent, mode) {
188
+ const accentColor = accentColorForProfile(profile, accent, mode);
109
189
  const isBluePalette = palette === "blue";
190
+ const light = mode === "light";
110
191
  switch (profile) {
111
- case "truecolor":
192
+ case "truecolor": {
193
+ const primary = isBluePalette
194
+ ? light
195
+ ? truecolor(29, 78, 216)
196
+ : truecolor(96, 165, 250)
197
+ : light
198
+ ? truecolor(21, 128, 61)
199
+ : truecolor(74, 222, 128);
112
200
  return {
113
201
  reset: "\x1b[0m",
114
202
  dim: "\x1b[2m",
115
- muted: truecolor(148, 163, 184),
116
- heading: truecolor(240, 253, 244),
117
- primary: isBluePalette ? truecolor(96, 165, 250) : truecolor(74, 222, 128),
203
+ muted: light ? truecolor(71, 85, 105) : truecolor(148, 163, 184),
204
+ heading: light ? truecolor(30, 41, 59) : truecolor(240, 253, 244),
205
+ primary,
118
206
  accent: accentColor,
119
- success: isBluePalette ? truecolor(96, 165, 250) : truecolor(74, 222, 128),
120
- warning: truecolor(245, 158, 11),
121
- danger: truecolor(239, 68, 68),
122
- border: isBluePalette ? truecolor(59, 130, 246) : truecolor(34, 197, 94),
207
+ success: primary,
208
+ warning: light ? truecolor(180, 83, 9) : truecolor(245, 158, 11),
209
+ danger: light ? truecolor(185, 28, 28) : truecolor(239, 68, 68),
210
+ border: isBluePalette
211
+ ? light
212
+ ? truecolor(37, 99, 235)
213
+ : truecolor(59, 130, 246)
214
+ : light
215
+ ? truecolor(22, 163, 74)
216
+ : truecolor(34, 197, 94),
123
217
  focusBg: isBluePalette ? truecolorBg(37, 99, 235) : truecolorBg(22, 101, 52),
124
218
  focusText: truecolor(248, 250, 252),
125
219
  };
126
- case "ansi256":
220
+ }
221
+ case "ansi256": {
222
+ const primary = isBluePalette
223
+ ? light
224
+ ? ansi256(25)
225
+ : ansi256(75)
226
+ : light
227
+ ? ansi256(28)
228
+ : ansi256(83);
127
229
  return {
128
230
  reset: "\x1b[0m",
129
231
  dim: "\x1b[2m",
130
- muted: ansi256(102),
131
- heading: ansi256(255),
132
- primary: isBluePalette ? ansi256(75) : ansi256(83),
232
+ muted: light ? ansi256(240) : ansi256(102),
233
+ heading: light ? ansi256(234) : ansi256(255),
234
+ primary,
133
235
  accent: accentColor,
134
- success: isBluePalette ? ansi256(75) : ansi256(83),
135
- warning: ansi256(214),
136
- danger: ansi256(196),
137
- border: isBluePalette ? ansi256(27) : ansi256(40),
236
+ success: primary,
237
+ warning: light ? ansi256(166) : ansi256(214),
238
+ danger: light ? ansi256(160) : ansi256(196),
239
+ border: isBluePalette
240
+ ? light
241
+ ? ansi256(25)
242
+ : ansi256(27)
243
+ : light
244
+ ? ansi256(28)
245
+ : ansi256(40),
138
246
  focusBg: isBluePalette ? ansi256Bg(26) : ansi256Bg(28),
139
247
  focusText: ansi256(231),
140
248
  };
141
- default:
249
+ }
250
+ default: {
251
+ const primary = isBluePalette
252
+ ? light
253
+ ? ansi16(34)
254
+ : ansi16(94)
255
+ : light
256
+ ? ansi16(32)
257
+ : ansi16(92);
142
258
  return {
143
259
  reset: "\x1b[0m",
144
260
  dim: "\x1b[2m",
145
- muted: ansi16(37),
146
- heading: ansi16(97),
147
- primary: isBluePalette ? ansi16(94) : ansi16(92),
261
+ muted: light ? ansi16(30) : ansi16(37),
262
+ heading: light ? ansi16(30) : ansi16(97),
263
+ primary,
148
264
  accent: accentColor,
149
- success: isBluePalette ? ansi16(94) : ansi16(92),
150
- warning: ansi16(93),
151
- danger: ansi16(91),
152
- border: isBluePalette ? ansi16(94) : ansi16(92),
265
+ success: primary,
266
+ warning: light ? ansi16(33) : ansi16(93),
267
+ danger: light ? ansi16(31) : ansi16(91),
268
+ border: primary,
153
269
  focusBg: isBluePalette ? "\x1b[104m" : "\x1b[102m",
154
270
  focusText: "\x1b[30m",
155
271
  };
272
+ }
156
273
  }
157
274
  }
158
275
  /**
@@ -191,8 +308,11 @@ function stripColors(colors) {
191
308
  * - glyphMode: glyph rendering mode; defaults to `"ascii"`.
192
309
  * - palette: overall palette variant; defaults to `"green"`.
193
310
  * - accent: accent color selection; defaults to `"green"`.
311
+ * - colorMode: background mode; defaults to `"auto"`, which honors
312
+ * `CODEX_TUI_COLOR_MODE`, then `COLORFGBG` detection, then `"dark"`.
194
313
  * - disableColor: force the color-stripped theme regardless of env/TTY.
195
- * @returns The constructed UiTheme object containing `profile`, `glyphMode`, `glyphs`, and `colors`.
314
+ * - env: environment override for detection and color gating; defaults to `process.env`.
315
+ * @returns The constructed UiTheme object containing `profile`, `glyphMode`, resolved `colorMode`, `glyphs`, and `colors`.
196
316
  *
197
317
  * @remarks
198
318
  * - Concurrency: creation is pure and side-effect free, safe to call concurrently.
@@ -204,14 +324,18 @@ export function createUiTheme(options) {
204
324
  const glyphMode = options?.glyphMode ?? "ascii";
205
325
  const palette = options?.palette ?? "green";
206
326
  const accent = options?.accent ?? "green";
327
+ const env = options?.env ?? process.env;
207
328
  const resolvedGlyphMode = resolveGlyphMode(glyphMode);
208
- const colors = getColors(profile, palette, accent);
329
+ const colorMode = resolveUiColorMode(options?.colorMode ?? "auto", env);
330
+ const colors = getColors(profile, palette, accent, colorMode);
209
331
  // ui-04: honor NO_COLOR / FORCE_COLOR / non-TTY by blanking color tokens. The
210
332
  // caller may also force this explicitly (e.g. for snapshot-stable output).
211
- const disableColor = options?.disableColor ?? shouldDisableColor();
333
+ const disableColor = options?.disableColor ??
334
+ shouldDisableColor(env, Boolean(process.stdout?.isTTY));
212
335
  return {
213
336
  profile,
214
337
  glyphMode,
338
+ colorMode,
215
339
  glyphs: getGlyphs(resolvedGlyphMode),
216
340
  colors: disableColor ? stripColors(colors) : colors,
217
341
  };
@@ -120,8 +120,8 @@ export declare const UI_COPY: {
120
120
  readonly behaviorSubtitle: "Control how result screens return";
121
121
  readonly behaviorHelp: "Enter Select | 1-3 Delay | P Pause | L AutoFetch | F Status | T TTL | S Save | Q Back (No Save)";
122
122
  readonly themeTitle: "Color Theme";
123
- readonly themeSubtitle: "Pick base color and accent";
124
- readonly themeHelp: "Enter Select | 1-2 Base | S Save | Q Back (No Save)";
123
+ readonly themeSubtitle: "Pick base color, accent, and background mode";
124
+ readonly themeHelp: "Enter Select | 1-2 Base | A/D/L Mode | S Save | Q Back (No Save)";
125
125
  readonly backendTitle: "Backend Controls";
126
126
  readonly backendSubtitle: "Tune sync, retry, and limit behavior";
127
127
  readonly backendHelp: "Enter Open | 1-4 Category | S Save | R Reset | Q Back (No Save)";
@@ -136,6 +136,7 @@ export declare const UI_COPY: {
136
136
  readonly backendBackToCategories: "Back to Categories";
137
137
  readonly baseTheme: "Base Color";
138
138
  readonly accentColor: "Accent Color";
139
+ readonly terminalBackground: "Terminal Background";
139
140
  readonly actionTiming: "Auto Return Delay";
140
141
  readonly moveUp: "Move Focused Field Up";
141
142
  readonly moveDown: "Move Focused Field Down";
@@ -121,8 +121,8 @@ export const UI_COPY = {
121
121
  behaviorSubtitle: "Control how result screens return",
122
122
  behaviorHelp: "Enter Select | 1-3 Delay | P Pause | L AutoFetch | F Status | T TTL | S Save | Q Back (No Save)",
123
123
  themeTitle: "Color Theme",
124
- themeSubtitle: "Pick base color and accent",
125
- themeHelp: "Enter Select | 1-2 Base | S Save | Q Back (No Save)",
124
+ themeSubtitle: "Pick base color, accent, and background mode",
125
+ themeHelp: "Enter Select | 1-2 Base | A/D/L Mode | S Save | Q Back (No Save)",
126
126
  backendTitle: "Backend Controls",
127
127
  backendSubtitle: "Tune sync, retry, and limit behavior",
128
128
  backendHelp: "Enter Open | 1-4 Category | S Save | R Reset | Q Back (No Save)",
@@ -137,6 +137,7 @@ export const UI_COPY = {
137
137
  backendBackToCategories: "Back to Categories",
138
138
  baseTheme: "Base Color",
139
139
  accentColor: "Accent Color",
140
+ terminalBackground: "Terminal Background",
140
141
  actionTiming: "Auto Return Delay",
141
142
  moveUp: "Move Focused Field Up",
142
143
  moveDown: "Move Focused Field Down",
@@ -51,7 +51,7 @@ export declare const SHORT_CONTEXT_MAX_INPUT_TOKENS = 272000;
51
51
  * `test/usage-pricing-coverage.test.ts` fails if a NEW routable model appears
52
52
  * in neither list.
53
53
  */
54
- export declare const UNPRICED_ROUTABLE_MODELS: readonly ["gpt-daybreak-blue-latest", "gpt-daybreak-red-latest"];
54
+ export declare const UNPRICED_ROUTABLE_MODELS: readonly ["gpt-reserve", "gpt-daybreak-blue-latest", "gpt-daybreak-red-latest"];
55
55
  export declare function getUsageModelPricing(model: string | null | undefined): UsageModelPricing | null;
56
56
  export declare function estimateUsageCostUsd(model: string | null | undefined, tokens: UsageTokenCounts): number | null;
57
57
  export declare function listUsageModelPricing(): Record<string, UsageModelPricing>;
@@ -168,6 +168,10 @@ const MODEL_PRICING = {
168
168
  * in neither list.
169
169
  */
170
170
  export const UNPRICED_ROUTABLE_MODELS = [
171
+ // Luna Reserve is a separately metered subscription allowance. The backend
172
+ // exposes usage percentage, not a public per-token dollar rate; cost budgets
173
+ // therefore remain fail-closed instead of borrowing Luna API pricing.
174
+ "gpt-reserve",
171
175
  // The Daybreak cyber models are sold under a separate controlled-access
172
176
  // agreement with no public per-token rate.
173
177
  "gpt-daybreak-blue-latest",
@@ -22,6 +22,8 @@ export declare function extractUsageTokenCounts(usage: unknown): UsageTokenCount
22
22
  */
23
23
  export declare function extractResponsesUsage(payload: unknown): UsageTokenCounts | null;
24
24
  export interface UsageStreamScanner {
25
+ /** The shared format decision, updated as the bounded body prefix arrives. */
26
+ isSse: () => boolean;
25
27
  /** Feed one forwarded chunk. Never throws. */
26
28
  push: (chunk: Uint8Array) => void;
27
29
  /** Flush any trailing partial data and return the final counts, if any. */
@@ -9,6 +9,8 @@
9
9
  */
10
10
  /** Cap on retained bytes so a hostile or unterminated body cannot grow forever. */
11
11
  const MAX_BUFFERED_BYTES = 1_048_576;
12
+ /** Only inspect this many leading bytes when the media type does not identify SSE. */
13
+ const MAX_SNIFF_BYTES = 4_096;
12
14
  /** Terminal Responses stream events that carry the final `usage` object. */
13
15
  const TERMINAL_EVENT_TYPES = new Set([
14
16
  "response.completed",
@@ -132,7 +134,11 @@ export function extractResponsesUsage(payload) {
132
134
  * bound.
133
135
  */
134
136
  export function createUsageStreamScanner(options) {
135
- const sse = (options.contentType ?? "").toLowerCase().includes("text/event-stream");
137
+ let sse = (options.contentType ?? "").toLowerCase().includes("text/event-stream");
138
+ let sniffing = !sse;
139
+ let sniffedBytes = 0;
140
+ let sniffPrefix = "";
141
+ const sniffDecoder = new TextDecoder("utf-8");
136
142
  const decoder = new TextDecoder("utf-8");
137
143
  let pending = "";
138
144
  let bufferedBytes = 0;
@@ -190,11 +196,29 @@ export function createUsageStreamScanner(options) {
190
196
  }
191
197
  eventData.push(value);
192
198
  };
199
+ const sniffFormat = (chunk) => {
200
+ if (!sniffing)
201
+ return;
202
+ const prefix = chunk.subarray(0, MAX_SNIFF_BYTES - sniffedBytes);
203
+ sniffedBytes += prefix.byteLength;
204
+ sniffPrefix += sniffDecoder.decode(prefix, { stream: true });
205
+ // Match only at the start (after blank lines/BOM), never a data: string
206
+ // inside JSON. A field or comment identifies SSE before a possibly huge
207
+ // event arrives, so streaming never depends on buffering its whole frame.
208
+ sse = /^(?:\r?\n)*(?::|(?:data|event|id|retry):)/.test(sniffPrefix);
209
+ const first = sniffPrefix.trimStart()[0];
210
+ if (sse || first === "{" || first === "[" || sniffedBytes >= MAX_SNIFF_BYTES) {
211
+ sniffing = false;
212
+ sniffPrefix = "";
213
+ }
214
+ };
193
215
  return {
216
+ isSse: () => sse,
194
217
  push: (chunk) => {
195
218
  try {
196
219
  if (overflowed || chunk.byteLength === 0)
197
220
  return;
221
+ sniffFormat(chunk);
198
222
  bufferedBytes += chunk.byteLength;
199
223
  pending += decoder.decode(chunk, { stream: true });
200
224
  if (!sse) {
@@ -18,7 +18,7 @@ export declare function isAbortError(error: unknown): boolean;
18
18
  * Combines two abort signals into one that aborts when the FIRST input does.
19
19
  *
20
20
  * This is a thin null-tolerant wrapper over `AbortSignal.any` — available
21
- * since Node 18.17.0, which the engines floor already requires. Using the
21
+ * on every Node version the engines floor (`>=22.19`) permits. Using the
22
22
  * native composite matters beyond brevity: a manual addEventListener pair
23
23
  * stays registered on BOTH inputs until one fires, so a caller that combines
24
24
  * a long-lived signal (e.g. a proxy-lifetime abort) once per request would
package/dist/lib/utils.js CHANGED
@@ -25,7 +25,7 @@ export function isAbortError(error) {
25
25
  * Combines two abort signals into one that aborts when the FIRST input does.
26
26
  *
27
27
  * This is a thin null-tolerant wrapper over `AbortSignal.any` — available
28
- * since Node 18.17.0, which the engines floor already requires. Using the
28
+ * on every Node version the engines floor (`>=22.19`) permits. Using the
29
29
  * native composite matters beyond brevity: a manual addEventListener pair
30
30
  * stays registered on BOTH inputs until one fires, so a caller that combines
31
31
  * a long-lived signal (e.g. a proxy-lifetime abort) once per request would
@@ -1,2 +1,2 @@
1
- export type PluginInput = any;
2
- export type Plugin = any;
1
+ export type PluginInput = any;
2
+ export type Plugin = any;
@@ -1,2 +1,2 @@
1
- export {};
2
-
1
+ export {};
2
+
@@ -1,42 +1,42 @@
1
- export interface ToolContext {
2
- [key: string]: any;
3
- directory: string;
4
- worktree: string;
5
- ask: (request: any) => Promise<any> | any;
6
- }
7
-
8
- export interface ToolDefinition<TArgs = any, TResult = any> {
9
- description?: string;
10
- args?: Record<string, any>;
11
- parameters?: unknown;
12
- execute: (args: TArgs, context: ToolContext) => Promise<TResult> | TResult;
13
- [key: string]: any;
14
- }
15
-
16
- export interface SchemaNode {
17
- optional: () => SchemaNode;
18
- describe: (_text: string) => SchemaNode;
19
- min: (_value: number) => SchemaNode;
20
- max: (_value: number) => SchemaNode;
21
- default: (_value: unknown) => SchemaNode;
22
- int: () => SchemaNode;
23
- array: (_node?: unknown) => SchemaNode;
24
- [key: string]: any;
25
- }
26
-
27
- export interface ToolFactory {
28
- <TArgs = any, TResult = any>(definition: ToolDefinition<TArgs, TResult>): ToolDefinition<TArgs, TResult>;
29
- schema: {
30
- string: () => SchemaNode;
31
- number: () => SchemaNode;
32
- boolean: () => SchemaNode;
33
- object: (shape: Record<string, unknown>) => SchemaNode;
34
- enum: (values: readonly unknown[]) => SchemaNode;
35
- literal: (value: unknown) => SchemaNode;
36
- array: (node: unknown) => SchemaNode;
37
- any: () => SchemaNode;
38
- unknown: () => SchemaNode;
39
- };
40
- }
41
-
42
- export declare const tool: ToolFactory;
1
+ export interface ToolContext {
2
+ [key: string]: any;
3
+ directory: string;
4
+ worktree: string;
5
+ ask: (request: any) => Promise<any> | any;
6
+ }
7
+
8
+ export interface ToolDefinition<TArgs = any, TResult = any> {
9
+ description?: string;
10
+ args?: Record<string, any>;
11
+ parameters?: unknown;
12
+ execute: (args: TArgs, context: ToolContext) => Promise<TResult> | TResult;
13
+ [key: string]: any;
14
+ }
15
+
16
+ export interface SchemaNode {
17
+ optional: () => SchemaNode;
18
+ describe: (_text: string) => SchemaNode;
19
+ min: (_value: number) => SchemaNode;
20
+ max: (_value: number) => SchemaNode;
21
+ default: (_value: unknown) => SchemaNode;
22
+ int: () => SchemaNode;
23
+ array: (_node?: unknown) => SchemaNode;
24
+ [key: string]: any;
25
+ }
26
+
27
+ export interface ToolFactory {
28
+ <TArgs = any, TResult = any>(definition: ToolDefinition<TArgs, TResult>): ToolDefinition<TArgs, TResult>;
29
+ schema: {
30
+ string: () => SchemaNode;
31
+ number: () => SchemaNode;
32
+ boolean: () => SchemaNode;
33
+ object: (shape: Record<string, unknown>) => SchemaNode;
34
+ enum: (values: readonly unknown[]) => SchemaNode;
35
+ literal: (value: unknown) => SchemaNode;
36
+ array: (node: unknown) => SchemaNode;
37
+ any: () => SchemaNode;
38
+ unknown: () => SchemaNode;
39
+ };
40
+ }
41
+
42
+ export declare const tool: ToolFactory;
@@ -1,29 +1,29 @@
1
- const chain = {
2
- optional() { return this; },
3
- describe() { return this; },
4
- min() { return this; },
5
- max() { return this; },
6
- default() { return this; },
7
- int() { return this; },
8
- array() { return this; },
9
- };
10
-
11
- function node() {
12
- return Object.create(chain);
13
- }
14
-
15
- export function tool(definition) {
16
- return definition;
17
- }
18
-
19
- tool.schema = {
20
- string: () => node(),
21
- number: () => node(),
22
- boolean: () => node(),
23
- object: () => node(),
24
- enum: () => node(),
25
- literal: () => node(),
26
- array: () => node(),
27
- any: () => node(),
28
- unknown: () => node(),
29
- };
1
+ const chain = {
2
+ optional() { return this; },
3
+ describe() { return this; },
4
+ min() { return this; },
5
+ max() { return this; },
6
+ default() { return this; },
7
+ int() { return this; },
8
+ array() { return this; },
9
+ };
10
+
11
+ function node() {
12
+ return Object.create(chain);
13
+ }
14
+
15
+ export function tool(definition) {
16
+ return definition;
17
+ }
18
+
19
+ tool.schema = {
20
+ string: () => node(),
21
+ number: () => node(),
22
+ boolean: () => node(),
23
+ object: () => node(),
24
+ enum: () => node(),
25
+ literal: () => node(),
26
+ array: () => node(),
27
+ any: () => node(),
28
+ unknown: () => node(),
29
+ };
@@ -1,9 +1,9 @@
1
- {
2
- "name": "@codex-ai/plugin",
3
- "version": "1.2.10-codex.1",
4
- "type": "module",
5
- "exports": {
6
- ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" },
7
- "./tool": { "import": "./dist/tool.js", "types": "./dist/tool.d.ts" }
8
- }
9
- }
1
+ {
2
+ "name": "@codex-ai/plugin",
3
+ "version": "1.2.10-codex.1",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" },
7
+ "./tool": { "import": "./dist/tool.js", "types": "./dist/tool.d.ts" }
8
+ }
9
+ }
@@ -1,4 +1,4 @@
1
- export type Auth = any;
2
- export type Provider = any;
3
- export type Model = any;
4
- export type CodexClient = any;
1
+ export type Auth = any;
2
+ export type Provider = any;
3
+ export type Model = any;
4
+ export type CodexClient = any;
@@ -1,2 +1,2 @@
1
- export {};
2
-
1
+ export {};
2
+
@@ -1,8 +1,8 @@
1
- {
2
- "name": "@codex-ai/sdk",
3
- "version": "1.2.10-codex.1",
4
- "type": "module",
5
- "exports": {
6
- ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" }
7
- }
8
- }
1
+ {
2
+ "name": "@codex-ai/sdk",
3
+ "version": "1.2.10-codex.1",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" }
7
+ }
8
+ }