@darkjd/opencode-openai-codex-auth 4.10.1

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 (90) hide show
  1. package/LICENSE +37 -0
  2. package/README.md +137 -0
  3. package/assets/opencode-logo-ornate-dark.svg +18 -0
  4. package/assets/readme-hero.svg +31 -0
  5. package/dist/index.d.ts +42 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +226 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/lib/auth/auth.d.ts +43 -0
  10. package/dist/lib/auth/auth.d.ts.map +1 -0
  11. package/dist/lib/auth/auth.js +163 -0
  12. package/dist/lib/auth/auth.js.map +1 -0
  13. package/dist/lib/auth/browser.d.ts +17 -0
  14. package/dist/lib/auth/browser.d.ts.map +1 -0
  15. package/dist/lib/auth/browser.js +76 -0
  16. package/dist/lib/auth/browser.js.map +1 -0
  17. package/dist/lib/auth/server.d.ts +10 -0
  18. package/dist/lib/auth/server.d.ts.map +1 -0
  19. package/dist/lib/auth/server.js +78 -0
  20. package/dist/lib/auth/server.js.map +1 -0
  21. package/dist/lib/auth/v2-storage.d.ts +35 -0
  22. package/dist/lib/auth/v2-storage.d.ts.map +1 -0
  23. package/dist/lib/auth/v2-storage.js +79 -0
  24. package/dist/lib/auth/v2-storage.js.map +1 -0
  25. package/dist/lib/config.d.ts +17 -0
  26. package/dist/lib/config.d.ts.map +1 -0
  27. package/dist/lib/config.js +51 -0
  28. package/dist/lib/config.js.map +1 -0
  29. package/dist/lib/constants.d.ts +69 -0
  30. package/dist/lib/constants.d.ts.map +1 -0
  31. package/dist/lib/constants.js +69 -0
  32. package/dist/lib/constants.js.map +1 -0
  33. package/dist/lib/logger.d.ts +21 -0
  34. package/dist/lib/logger.d.ts.map +1 -0
  35. package/dist/lib/logger.js +77 -0
  36. package/dist/lib/logger.js.map +1 -0
  37. package/dist/lib/oauth-success.html +712 -0
  38. package/dist/lib/prompts/codex-opencode-bridge.d.ts +19 -0
  39. package/dist/lib/prompts/codex-opencode-bridge.d.ts.map +1 -0
  40. package/dist/lib/prompts/codex-opencode-bridge.js +157 -0
  41. package/dist/lib/prompts/codex-opencode-bridge.js.map +1 -0
  42. package/dist/lib/prompts/codex.d.ts +27 -0
  43. package/dist/lib/prompts/codex.d.ts.map +1 -0
  44. package/dist/lib/prompts/codex.js +256 -0
  45. package/dist/lib/prompts/codex.js.map +1 -0
  46. package/dist/lib/prompts/opencode-codex.d.ts +21 -0
  47. package/dist/lib/prompts/opencode-codex.d.ts.map +1 -0
  48. package/dist/lib/prompts/opencode-codex.js +91 -0
  49. package/dist/lib/prompts/opencode-codex.js.map +1 -0
  50. package/dist/lib/request/fetch-helpers.d.ts +73 -0
  51. package/dist/lib/request/fetch-helpers.d.ts.map +1 -0
  52. package/dist/lib/request/fetch-helpers.js +231 -0
  53. package/dist/lib/request/fetch-helpers.js.map +1 -0
  54. package/dist/lib/request/helpers/input-utils.d.ts +6 -0
  55. package/dist/lib/request/helpers/input-utils.d.ts.map +1 -0
  56. package/dist/lib/request/helpers/input-utils.js +174 -0
  57. package/dist/lib/request/helpers/input-utils.js.map +1 -0
  58. package/dist/lib/request/helpers/model-map.d.ts +28 -0
  59. package/dist/lib/request/helpers/model-map.d.ts.map +1 -0
  60. package/dist/lib/request/helpers/model-map.js +134 -0
  61. package/dist/lib/request/helpers/model-map.js.map +1 -0
  62. package/dist/lib/request/helpers/model-registry-data.d.ts +86 -0
  63. package/dist/lib/request/helpers/model-registry-data.d.ts.map +1 -0
  64. package/dist/lib/request/helpers/model-registry-data.js +293 -0
  65. package/dist/lib/request/helpers/model-registry-data.js.map +1 -0
  66. package/dist/lib/request/helpers/model-registry.d.ts +45 -0
  67. package/dist/lib/request/helpers/model-registry.d.ts.map +1 -0
  68. package/dist/lib/request/helpers/model-registry.js +208 -0
  69. package/dist/lib/request/helpers/model-registry.js.map +1 -0
  70. package/dist/lib/request/helpers/skill-catalog.d.ts +59 -0
  71. package/dist/lib/request/helpers/skill-catalog.d.ts.map +1 -0
  72. package/dist/lib/request/helpers/skill-catalog.js +81 -0
  73. package/dist/lib/request/helpers/skill-catalog.js.map +1 -0
  74. package/dist/lib/request/request-transformer.d.ts +81 -0
  75. package/dist/lib/request/request-transformer.d.ts.map +1 -0
  76. package/dist/lib/request/request-transformer.js +477 -0
  77. package/dist/lib/request/request-transformer.js.map +1 -0
  78. package/dist/lib/request/response-handler.d.ts +14 -0
  79. package/dist/lib/request/response-handler.d.ts.map +1 -0
  80. package/dist/lib/request/response-handler.js +88 -0
  81. package/dist/lib/request/response-handler.js.map +1 -0
  82. package/dist/lib/types.d.ts +178 -0
  83. package/dist/lib/types.d.ts.map +1 -0
  84. package/dist/lib/types.js +2 -0
  85. package/dist/lib/types.js.map +1 -0
  86. package/dist/v2.d.ts +34 -0
  87. package/dist/v2.d.ts.map +1 -0
  88. package/dist/v2.js +259 -0
  89. package/dist/v2.js.map +1 -0
  90. package/package.json +87 -0
@@ -0,0 +1,477 @@
1
+ import { logDebug, logWarn } from "../logger.js";
2
+ import { TOOL_REMAP_MESSAGE } from "../prompts/codex.js";
3
+ import { CODEX_OPENCODE_BRIDGE } from "../prompts/codex-opencode-bridge.js";
4
+ import { getOpenCodeCodexPrompt } from "../prompts/opencode-codex.js";
5
+ import { getNormalizedModel } from "./helpers/model-map.js";
6
+ import { lookupModelRegistryEntry } from "./helpers/model-registry.js";
7
+ import { extractOpenCodeCapabilityBlocks, formatPreservedCapabilityBlocks, } from "./helpers/skill-catalog.js";
8
+ import { filterOpenCodeSystemPromptsWithCachedPrompt, normalizeOrphanedToolOutputs, } from "./helpers/input-utils.js";
9
+ export { isOpenCodeSystemPrompt, filterOpenCodeSystemPromptsWithCachedPrompt, } from "./helpers/input-utils.js";
10
+ /**
11
+ * Normalize model name to Codex-supported variants
12
+ *
13
+ * Uses explicit model map for known models, with fallback pattern matching
14
+ * for unknown/custom model names.
15
+ *
16
+ * @param model - Original model name (e.g., "gpt-5.1-codex-low", "openai/gpt-5-codex")
17
+ * @returns Normalized model name (e.g., "gpt-5.1-codex", "gpt-5-codex")
18
+ */
19
+ export function normalizeModel(model) {
20
+ if (!model)
21
+ return "gpt-5.1";
22
+ // Strip provider prefix if present (e.g., "openai/gpt-5-codex" → "gpt-5-codex")
23
+ const modelId = model.includes("/") ? model.split("/").pop() : model;
24
+ // Try explicit model map first (handles all known model variants)
25
+ const mappedModel = getNormalizedModel(modelId);
26
+ if (mappedModel) {
27
+ return mappedModel;
28
+ }
29
+ // Try the model registry (bundled defaults + optional remote overlay).
30
+ // This is the preferred place to add support for a brand-new model
31
+ // family — see lib/request/helpers/model-registry-data.ts — so most new
32
+ // models never need to touch the pattern-matching fallback below at all.
33
+ const registryEntry = lookupModelRegistryEntry(modelId);
34
+ if (registryEntry) {
35
+ return registryEntry.id;
36
+ }
37
+ // Last-resort fallback: generic pattern-based matching for names that are
38
+ // in neither the static map nor the registry (e.g. brand-new/unregistered
39
+ // custom model strings). This preserves backwards compatibility with old
40
+ // verbose names like "GPT 5 Codex Low (ChatGPT Subscription)".
41
+ const normalized = modelId.toLowerCase();
42
+ // Priority order for pattern matching (most specific first):
43
+ // 1. GPT-5.6 tiers. The base alias routes to Sol.
44
+ if (normalized.includes("gpt-5.6-terra") ||
45
+ normalized.includes("gpt 5.6 terra")) {
46
+ return "gpt-5.6-terra";
47
+ }
48
+ if (normalized.includes("gpt-5.6-luna") ||
49
+ normalized.includes("gpt 5.6 luna")) {
50
+ return "gpt-5.6-luna";
51
+ }
52
+ if (normalized.includes("gpt-5.6-sol") ||
53
+ normalized.includes("gpt 5.6 sol") ||
54
+ normalized.includes("gpt-5.6") ||
55
+ normalized.includes("gpt 5.6")) {
56
+ return "gpt-5.6-sol";
57
+ }
58
+ // 2. GPT-5.2 Codex
59
+ if (normalized.includes("gpt-5.2-codex") ||
60
+ normalized.includes("gpt 5.2 codex")) {
61
+ return "gpt-5.2-codex";
62
+ }
63
+ // 3. GPT-5.2 (general purpose)
64
+ if (normalized.includes("gpt-5.2") || normalized.includes("gpt 5.2")) {
65
+ return "gpt-5.2";
66
+ }
67
+ // 3. GPT-5.1 Codex Max
68
+ if (normalized.includes("gpt-5.1-codex-max") ||
69
+ normalized.includes("gpt 5.1 codex max")) {
70
+ return "gpt-5.1-codex-max";
71
+ }
72
+ // 4. GPT-5.1 Codex Mini
73
+ if (normalized.includes("gpt-5.1-codex-mini") ||
74
+ normalized.includes("gpt 5.1 codex mini")) {
75
+ return "gpt-5.1-codex-mini";
76
+ }
77
+ // 5. Legacy Codex Mini
78
+ if (normalized.includes("codex-mini-latest") ||
79
+ normalized.includes("gpt-5-codex-mini") ||
80
+ normalized.includes("gpt 5 codex mini")) {
81
+ return "codex-mini-latest";
82
+ }
83
+ // 6. GPT-5.1 Codex
84
+ if (normalized.includes("gpt-5.1-codex") ||
85
+ normalized.includes("gpt 5.1 codex")) {
86
+ return "gpt-5.1-codex";
87
+ }
88
+ // 7. GPT-5.1 (general-purpose)
89
+ if (normalized.includes("gpt-5.1") || normalized.includes("gpt 5.1")) {
90
+ return "gpt-5.1";
91
+ }
92
+ // 8. GPT-5 Codex family (any variant with "codex")
93
+ if (normalized.includes("codex")) {
94
+ return "gpt-5.1-codex";
95
+ }
96
+ // 9. GPT-5 family (any variant) - default to 5.1 as 5 is being phased out
97
+ if (normalized.includes("gpt-5") || normalized.includes("gpt 5")) {
98
+ return "gpt-5.1";
99
+ }
100
+ // 10. Safety net for a genuinely unrecognized model whose numeric version
101
+ // is NEWER than anything this plugin's pattern-matching knows about (e.g.
102
+ // a brand-new "gpt-7-nova" or "gpt-6-something" released before a registry
103
+ // entry was added for it — this is exactly what happened with gpt-6-sol
104
+ // and gpt-6-luna before they were added above). Passing the id through
105
+ // unchanged lets the real Codex backend decide whether it's valid, which
106
+ // is much safer than silently downgrading the request to a much older,
107
+ // weaker model with no error at all. Older/legacy families (e.g. "gpt-4")
108
+ // are intentionally NOT covered by this — they keep normalizing forward
109
+ // to gpt-5.1 via the final fallback below, matching existing migration
110
+ // behavior and every "unknown-model"/"gpt-4" test case.
111
+ const versionMatch = normalized.match(/^gpt[-\s]?(\d+)(?:\.(\d+))?/);
112
+ if (versionMatch) {
113
+ const major = parseInt(versionMatch[1], 10);
114
+ const minor = versionMatch[2] ? parseInt(versionMatch[2], 10) : 0;
115
+ const version = major + minor / 10;
116
+ // Highest major.minor version explicitly known to the pattern-matching
117
+ // chain above (registry-known models like gpt-6-astra never reach this
118
+ // point at all, since lookupModelRegistryEntry() already returned).
119
+ const HIGHEST_KNOWN_FALLBACK_VERSION = 5.6;
120
+ if (version > HIGHEST_KNOWN_FALLBACK_VERSION) {
121
+ return modelId;
122
+ }
123
+ }
124
+ // Default fallback - use gpt-5.1 as gpt-5 is being phased out
125
+ return "gpt-5.1";
126
+ }
127
+ /**
128
+ * Extract configuration for a specific model
129
+ * Merges global options with model-specific options (model-specific takes precedence)
130
+ * @param modelName - Model name (e.g., "gpt-5-codex")
131
+ * @param userConfig - Full user configuration object
132
+ * @returns Merged configuration for this model
133
+ */
134
+ export function getModelConfig(modelName, userConfig = { global: {}, models: {} }) {
135
+ const globalOptions = userConfig.global || {};
136
+ const modelOptions = userConfig.models?.[modelName]?.options || {};
137
+ // Model-specific options override global options
138
+ return { ...globalOptions, ...modelOptions };
139
+ }
140
+ function resolveReasoningConfig(modelName, modelConfig, body) {
141
+ const providerOpenAI = body.providerOptions?.openai;
142
+ const existingEffort = body.reasoning?.effort ?? providerOpenAI?.reasoningEffort;
143
+ const existingSummary = body.reasoning?.summary ?? providerOpenAI?.reasoningSummary;
144
+ const mergedConfig = {
145
+ ...modelConfig,
146
+ ...(existingEffort ? { reasoningEffort: existingEffort } : {}),
147
+ ...(existingSummary ? { reasoningSummary: existingSummary } : {}),
148
+ };
149
+ return getReasoningConfig(modelName, mergedConfig);
150
+ }
151
+ function resolveTextVerbosity(modelConfig, body) {
152
+ const providerOpenAI = body.providerOptions?.openai;
153
+ return (body.text?.verbosity ??
154
+ providerOpenAI?.textVerbosity ??
155
+ modelConfig.textVerbosity ??
156
+ "medium");
157
+ }
158
+ function resolveInclude(modelConfig, body) {
159
+ const providerOpenAI = body.providerOptions?.openai;
160
+ const base = body.include ??
161
+ providerOpenAI?.include ??
162
+ modelConfig.include ??
163
+ ["reasoning.encrypted_content"];
164
+ const include = Array.from(new Set(base.filter(Boolean)));
165
+ if (!include.includes("reasoning.encrypted_content")) {
166
+ include.push("reasoning.encrypted_content");
167
+ }
168
+ return include;
169
+ }
170
+ /**
171
+ * Legacy pattern-matching derivation of reasoning capabilities, kept as the
172
+ * fallback for any model name not present in the model registry (bundled or
173
+ * remote-overlaid) — see lib/request/helpers/model-registry-data.ts, which is
174
+ * the preferred place to add support for a new model going forward.
175
+ */
176
+ function deriveLegacyReasoningFlags(modelName) {
177
+ const normalizedName = modelName?.toLowerCase() ?? "";
178
+ const isGpt56 = normalizedName.includes("gpt-5.6") || normalizedName.includes("gpt 5.6");
179
+ // GPT-5.2 Codex is the newest codex model (supports xhigh, but not "none")
180
+ const isGpt52Codex = normalizedName.includes("gpt-5.2-codex") ||
181
+ normalizedName.includes("gpt 5.2 codex");
182
+ // GPT-5.2 general purpose (not codex variant)
183
+ const isGpt52General = (normalizedName.includes("gpt-5.2") || normalizedName.includes("gpt 5.2")) &&
184
+ !isGpt52Codex;
185
+ const isCodexMax = normalizedName.includes("codex-max") ||
186
+ normalizedName.includes("codex max");
187
+ const isCodexMini = normalizedName.includes("codex-mini") ||
188
+ normalizedName.includes("codex mini") ||
189
+ normalizedName.includes("codex_mini") ||
190
+ normalizedName.includes("codex-mini-latest");
191
+ const isCodex = normalizedName.includes("codex") && !isCodexMini;
192
+ const isLightweight = !isCodexMini &&
193
+ (normalizedName.includes("nano") ||
194
+ normalizedName.includes("mini"));
195
+ // GPT-5.1 general purpose (not codex variants) - supports "none" per OpenAI API docs
196
+ const isGpt51General = (normalizedName.includes("gpt-5.1") || normalizedName.includes("gpt 5.1")) &&
197
+ !isCodex &&
198
+ !isCodexMax &&
199
+ !isCodexMini;
200
+ // GPT 5.2, GPT 5.2 Codex, and Codex Max support xhigh reasoning
201
+ const supportsXhigh = isGpt56 || isGpt52General || isGpt52Codex || isCodexMax;
202
+ const supportsMax = isGpt56;
203
+ // GPT 5.1 general and GPT 5.2 general support "none" reasoning per:
204
+ // - OpenAI API docs: "gpt-5.1 defaults to none, supports: none, low, medium, high"
205
+ // - Codex CLI: ReasoningEffort enum includes None variant (codex-rs/protocol/src/openai_models.rs)
206
+ // - Codex CLI: docs/config.md lists "none" as valid for model_reasoning_effort
207
+ // - gpt-5.2 (being newer) also supports: none, low, medium, high, xhigh
208
+ // - Codex models (including GPT-5.2 Codex) do NOT support "none"
209
+ const supportsNone = isGpt56 || isGpt52General || isGpt51General;
210
+ // Default based on model type (Codex CLI defaults)
211
+ // Note: OpenAI docs say gpt-5.1 defaults to "none", but we default to "medium"
212
+ // for better coding assistance unless user explicitly requests "none"
213
+ const defaultEffort = isCodexMini
214
+ ? "medium"
215
+ : isGpt56
216
+ ? "medium"
217
+ : supportsXhigh
218
+ ? "high"
219
+ : isLightweight
220
+ ? "minimal"
221
+ : "medium";
222
+ return { supportsXhigh, supportsMax, supportsNone, isCodexMini, defaultEffort };
223
+ }
224
+ export function getReasoningConfig(modelName, userConfig = {}) {
225
+ // Prefer the model registry (bundled + optional remote overlay) — see
226
+ // lib/request/helpers/model-registry-data.ts. Fall back to legacy
227
+ // pattern-matching only for names the registry doesn't recognize at all,
228
+ // so existing/custom model strings keep working exactly as before.
229
+ const registryEntry = lookupModelRegistryEntry(modelName);
230
+ const { supportsXhigh, supportsMax, supportsNone, isCodexMini, defaultEffort } = registryEntry
231
+ ? {
232
+ supportsXhigh: !!registryEntry.capabilities?.xhigh,
233
+ supportsMax: !!registryEntry.capabilities?.max,
234
+ supportsNone: !!registryEntry.capabilities?.none,
235
+ isCodexMini: !!registryEntry.isCodexMini,
236
+ defaultEffort: registryEntry.defaultEffort,
237
+ }
238
+ : deriveLegacyReasoningFlags(modelName);
239
+ // Get user-requested effort
240
+ let effort = userConfig.reasoningEffort || defaultEffort;
241
+ if (isCodexMini) {
242
+ if (effort === "minimal" || effort === "low" || effort === "none") {
243
+ effort = "medium";
244
+ }
245
+ if (effort === "xhigh") {
246
+ effort = "high";
247
+ }
248
+ if (effort !== "high" && effort !== "medium") {
249
+ effort = "medium";
250
+ }
251
+ }
252
+ if (!supportsMax && effort === "max") {
253
+ effort = supportsXhigh ? "xhigh" : "high";
254
+ }
255
+ // For models that don't support xhigh, downgrade to high
256
+ if (!supportsXhigh && effort === "xhigh") {
257
+ effort = "high";
258
+ }
259
+ // For models that don't support "none", upgrade to "low"
260
+ // (Codex models don't support "none" - only GPT-5.1 and GPT-5.2 general purpose do)
261
+ if (!supportsNone && effort === "none") {
262
+ effort = "low";
263
+ }
264
+ // Normalize "minimal" to "low" for all non-mini models
265
+ // The ChatGPT Codex backend does not accept "minimal" (supports none/low/medium/high).
266
+ if (effort === "minimal") {
267
+ effort = "low";
268
+ }
269
+ return {
270
+ effort,
271
+ summary: userConfig.reasoningSummary || "auto", // Changed from "detailed" to match Codex CLI
272
+ };
273
+ }
274
+ /**
275
+ * Filter input array for stateless Codex API (store: false)
276
+ *
277
+ * Two transformations needed:
278
+ * 1. Remove AI SDK-specific items (not supported by Codex API)
279
+ * 2. Strip IDs from all remaining items (stateless mode)
280
+ *
281
+ * AI SDK constructs to REMOVE (not in OpenAI Responses API spec):
282
+ * - type: "item_reference" - AI SDK uses this for server-side state lookup
283
+ *
284
+ * Items to KEEP (strip IDs):
285
+ * - type: "message" - Conversation messages (provides context to LLM)
286
+ * - type: "function_call" - Tool calls from conversation
287
+ * - type: "function_call_output" - Tool results from conversation
288
+ *
289
+ * Context is maintained through:
290
+ * - Full message history (without IDs)
291
+ * - reasoning.encrypted_content (for reasoning continuity)
292
+ *
293
+ * @param input - Original input array from OpenCode/AI SDK
294
+ * @returns Filtered input array compatible with Codex API
295
+ */
296
+ export function filterInput(input) {
297
+ if (!Array.isArray(input))
298
+ return input;
299
+ return input
300
+ .filter((item) => {
301
+ // Remove AI SDK constructs not supported by Codex API
302
+ if (item.type === "item_reference") {
303
+ return false; // AI SDK only - references server state
304
+ }
305
+ return true; // Keep all other items
306
+ })
307
+ .map((item) => {
308
+ // Strip IDs from all items (Codex API stateless mode)
309
+ if (item.id) {
310
+ const { id, ...itemWithoutId } = item;
311
+ return itemWithoutId;
312
+ }
313
+ return item;
314
+ });
315
+ }
316
+ /**
317
+ * Filter out OpenCode system prompts from input
318
+ * Used in CODEX_MODE to replace OpenCode prompts with Codex-OpenCode bridge
319
+ * @param input - Input array
320
+ * @returns Input array without OpenCode system prompts
321
+ */
322
+ export async function filterOpenCodeSystemPrompts(input) {
323
+ if (!Array.isArray(input))
324
+ return input;
325
+ // Fetch cached OpenCode prompt for verification
326
+ let cachedPrompt = null;
327
+ try {
328
+ cachedPrompt = await getOpenCodeCodexPrompt();
329
+ }
330
+ catch {
331
+ // If fetch fails, fallback to text-based detection only
332
+ // This is safe because we still have the "starts with" check
333
+ }
334
+ return filterOpenCodeSystemPromptsWithCachedPrompt(input, cachedPrompt);
335
+ }
336
+ /**
337
+ * Add Codex-OpenCode bridge message to input if tools are present
338
+ * @param input - Input array
339
+ * @param hasTools - Whether tools are present in request
340
+ * @returns Input array with bridge message prepended if needed
341
+ */
342
+ export function addCodexBridgeMessage(input, hasTools) {
343
+ if (!hasTools || !Array.isArray(input))
344
+ return input;
345
+ const bridgeMessage = {
346
+ type: "message",
347
+ role: "developer",
348
+ content: [
349
+ {
350
+ type: "input_text",
351
+ text: CODEX_OPENCODE_BRIDGE,
352
+ },
353
+ ],
354
+ };
355
+ return [bridgeMessage, ...input];
356
+ }
357
+ /**
358
+ * Add tool remapping message to input if tools are present
359
+ * @param input - Input array
360
+ * @param hasTools - Whether tools are present in request
361
+ * @returns Input array with tool remap message prepended if needed
362
+ */
363
+ export function addToolRemapMessage(input, hasTools) {
364
+ if (!hasTools || !Array.isArray(input))
365
+ return input;
366
+ const toolRemapMessage = {
367
+ type: "message",
368
+ role: "developer",
369
+ content: [
370
+ {
371
+ type: "input_text",
372
+ text: TOOL_REMAP_MESSAGE,
373
+ },
374
+ ],
375
+ };
376
+ return [toolRemapMessage, ...input];
377
+ }
378
+ /**
379
+ * Transform request body for Codex API
380
+ *
381
+ * NOTE: Configuration follows Codex CLI patterns instead of opencode defaults:
382
+ * - opencode sets textVerbosity="low" for gpt-5, but Codex CLI uses "medium"
383
+ * - opencode excludes gpt-5-codex from reasoning configuration
384
+ * - This plugin uses store=false (stateless), requiring encrypted reasoning content
385
+ *
386
+ * @param body - Original request body
387
+ * @param codexInstructions - Codex system instructions
388
+ * @param userConfig - User configuration from loader
389
+ * @param codexMode - Enable CODEX_MODE (bridge prompt instead of tool remap) - defaults to true
390
+ * @returns Transformed request body
391
+ */
392
+ export async function transformRequestBody(body, codexInstructions, userConfig = { global: {}, models: {} }, codexMode = true) {
393
+ const originalModel = body.model;
394
+ const normalizedModel = normalizeModel(body.model);
395
+ // Get model-specific configuration using ORIGINAL model name (config key)
396
+ // This allows per-model options like "gpt-5-codex-low" to work correctly
397
+ const lookupModel = originalModel || normalizedModel;
398
+ const modelConfig = getModelConfig(lookupModel, userConfig);
399
+ // Debug: Log which config was resolved
400
+ logDebug(`Model config lookup: "${lookupModel}" → normalized to "${normalizedModel}" for API`, {
401
+ hasModelSpecificConfig: !!userConfig.models?.[lookupModel],
402
+ resolvedConfig: modelConfig,
403
+ });
404
+ // Normalize model name for API call
405
+ body.model = normalizedModel;
406
+ // Codex required fields
407
+ // ChatGPT backend REQUIRES store=false (confirmed via testing)
408
+ body.store = false;
409
+ // Always set stream=true for API - response handling detects original intent
410
+ body.stream = true;
411
+ // Preserve opencode's <available_skills>/<mcp_instructions> blocks before
412
+ // they get overwritten below - see specs/skill-catalog-passthrough.md.
413
+ // opencode's isOpenaiOauth path puts its full system prompt (including
414
+ // these capability blocks) into body.instructions instead of role:system
415
+ // messages, so this is the only place they can be recovered from.
416
+ const preservedCapabilityBlocks = extractOpenCodeCapabilityBlocks(body.instructions);
417
+ body.instructions = codexInstructions + formatPreservedCapabilityBlocks(preservedCapabilityBlocks);
418
+ // Prompt caching relies on the host providing a stable prompt_cache_key
419
+ // (OpenCode passes its session identifier). We no longer synthesize one here.
420
+ // Filter and transform input
421
+ if (body.input && Array.isArray(body.input)) {
422
+ // Debug: Log original input message IDs before filtering
423
+ const originalIds = body.input
424
+ .filter((item) => item.id)
425
+ .map((item) => item.id);
426
+ if (originalIds.length > 0) {
427
+ logDebug(`Filtering ${originalIds.length} message IDs from input:`, originalIds);
428
+ }
429
+ body.input = filterInput(body.input);
430
+ // Debug: Verify all IDs were removed
431
+ const remainingIds = (body.input || [])
432
+ .filter((item) => item.id)
433
+ .map((item) => item.id);
434
+ if (remainingIds.length > 0) {
435
+ logWarn(`WARNING: ${remainingIds.length} IDs still present after filtering:`, remainingIds);
436
+ }
437
+ else if (originalIds.length > 0) {
438
+ logDebug(`Successfully removed all ${originalIds.length} message IDs`);
439
+ }
440
+ if (codexMode) {
441
+ // CODEX_MODE: Remove OpenCode system prompt, add bridge prompt
442
+ body.input = await filterOpenCodeSystemPrompts(body.input);
443
+ body.input = addCodexBridgeMessage(body.input, !!body.tools);
444
+ }
445
+ else {
446
+ // DEFAULT MODE: Keep original behavior with tool remap message
447
+ body.input = addToolRemapMessage(body.input, !!body.tools);
448
+ }
449
+ // Handle orphaned function_call_output items (where function_call was an item_reference that got filtered)
450
+ // Instead of removing orphans (which causes infinite loops as LLM loses tool results),
451
+ // convert them to messages to preserve context while avoiding API errors
452
+ if (body.input) {
453
+ body.input = normalizeOrphanedToolOutputs(body.input);
454
+ }
455
+ }
456
+ // Configure reasoning (prefer existing body/provider options, then config defaults)
457
+ const reasoningConfig = resolveReasoningConfig(normalizedModel, modelConfig, body);
458
+ body.reasoning = {
459
+ ...body.reasoning,
460
+ ...reasoningConfig,
461
+ };
462
+ // Configure text verbosity (support user config)
463
+ // Default: "medium" (matches Codex CLI default for all GPT-5 models)
464
+ body.text = {
465
+ ...body.text,
466
+ verbosity: resolveTextVerbosity(modelConfig, body),
467
+ };
468
+ // Add include for encrypted reasoning content
469
+ // Default: ["reasoning.encrypted_content"] (required for stateless operation with store=false)
470
+ // This allows reasoning context to persist across turns without server-side storage
471
+ body.include = resolveInclude(modelConfig, body);
472
+ // Remove unsupported parameters
473
+ body.max_output_tokens = undefined;
474
+ body.max_completion_tokens = undefined;
475
+ return body;
476
+ }
477
+ //# sourceMappingURL=request-transformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-transformer.js","sourceRoot":"","sources":["../../../lib/request/request-transformer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Convert SSE stream response to JSON for generateText()
3
+ * @param response - Fetch response with SSE stream
4
+ * @param headers - Response headers
5
+ * @returns Response with JSON body
6
+ */
7
+ export declare function convertSseToJson(response: Response, headers: Headers): Promise<Response>;
8
+ /**
9
+ * Ensure response has content-type header
10
+ * @param headers - Response headers
11
+ * @returns Headers with content-type set
12
+ */
13
+ export declare function ensureContentType(headers: Headers): Headers;
14
+ //# sourceMappingURL=response-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../../lib/request/response-handler.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkD9F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ3D"}
@@ -0,0 +1,88 @@
1
+ import { logRequest, LOGGING_ENABLED } from "../logger.js";
2
+ /**
3
+ * Parse SSE stream to extract final response
4
+ * @param sseText - Complete SSE stream text
5
+ * @returns Final response object or null if not found
6
+ */
7
+ function parseSseStream(sseText) {
8
+ const lines = sseText.split('\n');
9
+ for (const line of lines) {
10
+ if (line.startsWith('data: ')) {
11
+ try {
12
+ const data = JSON.parse(line.substring(6));
13
+ // Look for response.done event with final data
14
+ if (data.type === 'response.done' || data.type === 'response.completed') {
15
+ return data.response;
16
+ }
17
+ }
18
+ catch (e) {
19
+ // Skip malformed JSON
20
+ }
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ /**
26
+ * Convert SSE stream response to JSON for generateText()
27
+ * @param response - Fetch response with SSE stream
28
+ * @param headers - Response headers
29
+ * @returns Response with JSON body
30
+ */
31
+ export async function convertSseToJson(response, headers) {
32
+ if (!response.body) {
33
+ throw new Error('[openai-codex-plugin] Response has no body');
34
+ }
35
+ const reader = response.body.getReader();
36
+ const decoder = new TextDecoder();
37
+ let fullText = '';
38
+ try {
39
+ // Consume the entire stream
40
+ while (true) {
41
+ const { done, value } = await reader.read();
42
+ if (done)
43
+ break;
44
+ fullText += decoder.decode(value, { stream: true });
45
+ }
46
+ if (LOGGING_ENABLED) {
47
+ logRequest("stream-full", { fullContent: fullText });
48
+ }
49
+ // Parse SSE events to extract the final response
50
+ const finalResponse = parseSseStream(fullText);
51
+ if (!finalResponse) {
52
+ console.error('[openai-codex-plugin] Could not find final response in SSE stream');
53
+ logRequest("stream-error", { error: "No response.done event found" });
54
+ // Return original stream if we can't parse
55
+ return new Response(fullText, {
56
+ status: response.status,
57
+ statusText: response.statusText,
58
+ headers: headers,
59
+ });
60
+ }
61
+ // Return as plain JSON (not SSE)
62
+ const jsonHeaders = new Headers(headers);
63
+ jsonHeaders.set('content-type', 'application/json; charset=utf-8');
64
+ return new Response(JSON.stringify(finalResponse), {
65
+ status: response.status,
66
+ statusText: response.statusText,
67
+ headers: jsonHeaders,
68
+ });
69
+ }
70
+ catch (error) {
71
+ console.error('[openai-codex-plugin] Error converting stream:', error);
72
+ logRequest("stream-error", { error: String(error) });
73
+ throw error;
74
+ }
75
+ }
76
+ /**
77
+ * Ensure response has content-type header
78
+ * @param headers - Response headers
79
+ * @returns Headers with content-type set
80
+ */
81
+ export function ensureContentType(headers) {
82
+ const responseHeaders = new Headers(headers);
83
+ if (!responseHeaders.has('content-type')) {
84
+ responseHeaders.set('content-type', 'text/event-stream; charset=utf-8');
85
+ }
86
+ return responseHeaders;
87
+ }
88
+ //# sourceMappingURL=response-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-handler.js","sourceRoot":"","sources":["../../../lib/request/response-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG3D;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAAe;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACJ,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAiB,CAAC;gBAE3D,+CAA+C;gBAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;oBACzE,OAAO,IAAI,CAAC,QAAQ,CAAC;gBACtB,CAAC;YACF,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACZ,sBAAsB;YACvB,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAkB,EAAE,OAAgB;IAC1E,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,QAAQ,GAAG,EAAE,CAAC;IAElB,IAAI,CAAC;QACJ,4BAA4B;QAC5B,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAChB,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,eAAe,EAAE,CAAC;YACrB,UAAU,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,iDAAiD;QACjD,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE/C,IAAI,CAAC,aAAa,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;YACnF,UAAU,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC,CAAC;YAEtE,2CAA2C;YAC3C,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE;gBAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,OAAO,EAAE,OAAO;aAChB,CAAC,CAAC;QACJ,CAAC;QAED,iCAAiC;QACjC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;QACzC,WAAW,CAAC,GAAG,CAAC,cAAc,EAAE,iCAAiC,CAAC,CAAC;QAEnE,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE;YAClD,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,OAAO,EAAE,WAAW;SACpB,CAAC,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,KAAK,CAAC,CAAC;QACvE,UAAU,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IACjD,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE7C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1C,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,kCAAkC,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,eAAe,CAAC;AACxB,CAAC"}