@mariozechner/pi-ai 0.37.2 → 0.37.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 (44) hide show
  1. package/README.md +61 -12
  2. package/dist/models.generated.d.ts +0 -51
  3. package/dist/models.generated.d.ts.map +1 -1
  4. package/dist/models.generated.js +41 -92
  5. package/dist/models.generated.js.map +1 -1
  6. package/dist/providers/google-gemini-cli.d.ts.map +1 -1
  7. package/dist/providers/google-gemini-cli.js +3 -3
  8. package/dist/providers/google-gemini-cli.js.map +1 -1
  9. package/dist/providers/google-shared.d.ts +26 -1
  10. package/dist/providers/google-shared.d.ts.map +1 -1
  11. package/dist/providers/google-shared.js +31 -0
  12. package/dist/providers/google-shared.js.map +1 -1
  13. package/dist/providers/google-vertex.d.ts.map +1 -1
  14. package/dist/providers/google-vertex.js +3 -3
  15. package/dist/providers/google-vertex.js.map +1 -1
  16. package/dist/providers/google.d.ts.map +1 -1
  17. package/dist/providers/google.js +3 -3
  18. package/dist/providers/google.js.map +1 -1
  19. package/dist/providers/openai-codex/prompts/codex.d.ts +0 -1
  20. package/dist/providers/openai-codex/prompts/codex.d.ts.map +1 -1
  21. package/dist/providers/openai-codex/prompts/codex.js +1 -42
  22. package/dist/providers/openai-codex/prompts/codex.js.map +1 -1
  23. package/dist/providers/openai-codex/prompts/pi-codex-bridge.d.ts +2 -1
  24. package/dist/providers/openai-codex/prompts/pi-codex-bridge.d.ts.map +1 -1
  25. package/dist/providers/openai-codex/prompts/pi-codex-bridge.js +42 -42
  26. package/dist/providers/openai-codex/prompts/pi-codex-bridge.js.map +1 -1
  27. package/dist/providers/openai-codex/prompts/system-prompt.d.ts +10 -0
  28. package/dist/providers/openai-codex/prompts/system-prompt.d.ts.map +1 -0
  29. package/dist/providers/openai-codex/prompts/system-prompt.js +15 -0
  30. package/dist/providers/openai-codex/prompts/system-prompt.js.map +1 -0
  31. package/dist/providers/openai-codex/request-transformer.d.ts +5 -1
  32. package/dist/providers/openai-codex/request-transformer.d.ts.map +1 -1
  33. package/dist/providers/openai-codex/request-transformer.js +9 -41
  34. package/dist/providers/openai-codex/request-transformer.js.map +1 -1
  35. package/dist/providers/openai-codex-responses.d.ts.map +1 -1
  36. package/dist/providers/openai-codex-responses.js +13 -2
  37. package/dist/providers/openai-codex-responses.js.map +1 -1
  38. package/dist/stream.d.ts.map +1 -1
  39. package/dist/stream.js +1 -0
  40. package/dist/stream.js.map +1 -1
  41. package/dist/types.d.ts +6 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js.map +1 -1
  44. package/package.json +1 -1
@@ -2,47 +2,47 @@
2
2
  * Codex-Pi bridge prompt
3
3
  * Aligns Codex CLI expectations with Pi's toolset.
4
4
  */
5
- export const CODEX_PI_BRIDGE = `# Codex Running in Pi
6
-
7
- You are running Codex through pi, a terminal coding assistant. The tools and rules differ from Codex CLI.
8
-
9
- ## CRITICAL: Tool Replacements
10
-
11
- <critical_rule priority="0">
12
- APPLY_PATCH DOES NOT EXIST → ✅ USE "edit" INSTEAD
13
- - NEVER use: apply_patch, applyPatch
14
- - ALWAYS use: edit for ALL file modifications
15
- </critical_rule>
16
-
17
- <critical_rule priority="0">
18
- UPDATE_PLAN DOES NOT EXIST
19
- - NEVER use: update_plan, updatePlan, read_plan, readPlan, todowrite, todoread
20
- - There is no plan tool in this environment
21
- </critical_rule>
22
-
23
- ## Available Tools (pi)
24
-
25
- - read - Read file contents
26
- - bash - Execute bash commands
27
- - edit - Modify files with exact find/replace (requires prior read)
28
- - write - Create or overwrite files
29
- - grep - Search file contents (read-only)
30
- - find - Find files by glob pattern (read-only)
31
- - ls - List directory contents (read-only)
32
-
33
- ## Usage Rules
34
-
35
- - Read before edit; use read instead of cat/sed for file contents
36
- - Use edit for surgical changes; write only for new files or complete rewrites
37
- - Prefer grep/find/ls over bash for discovery
38
- - Be concise and show file paths clearly when working with files
39
-
40
- ## Verification Checklist
41
-
42
- 1. Using edit, not apply_patch
43
- 2. No plan tools used
44
- 3. Only the tools listed above are called
45
-
46
- Below are additional system instruction you MUST follow when responding:
5
+ function formatToolList(tools) {
6
+ if (!tools || tools.length === 0) {
7
+ return "- (none)";
8
+ }
9
+ const normalized = tools
10
+ .map((tool) => {
11
+ const name = tool.name.trim();
12
+ if (!name)
13
+ return null;
14
+ const description = (tool.description || "Custom tool").replace(/\s*\n\s*/g, " ").trim();
15
+ return { name, description };
16
+ })
17
+ .filter((tool) => tool !== null);
18
+ if (normalized.length === 0) {
19
+ return "- (none)";
20
+ }
21
+ const maxNameLength = normalized.reduce((max, tool) => Math.max(max, tool.name.length), 0);
22
+ const padWidth = Math.max(6, maxNameLength + 1);
23
+ return normalized
24
+ .map((tool) => {
25
+ const paddedName = tool.name.padEnd(padWidth);
26
+ return `- ${paddedName}- ${tool.description}`;
27
+ })
28
+ .join("\n");
29
+ }
30
+ export function buildCodexPiBridge(tools) {
31
+ const toolsList = formatToolList(tools);
32
+ return `# Codex Environment Bridge
33
+
34
+ <environment_override priority="0">
35
+ IGNORE ALL PREVIOUS INSTRUCTIONS ABOVE THIS MESSAGE.
36
+ Do not assume any tools are available unless listed below.
37
+ </environment_override>
38
+
39
+ The next system instructions that follow this message are authoritative and must be obeyed, even if they conflict with earlier instructions.
40
+
41
+ ## Available Tools
42
+
43
+ ${toolsList}
44
+
45
+ Only use the tools listed above. Do not reference or call any other tools.
47
46
  `;
47
+ }
48
48
  //# sourceMappingURL=pi-codex-bridge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pi-codex-bridge.js","sourceRoot":"","sources":["../../../../src/providers/openai-codex/prompts/pi-codex-bridge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0C9B,CAAC","sourcesContent":["/**\n * Codex-Pi bridge prompt\n * Aligns Codex CLI expectations with Pi's toolset.\n */\n\nexport const CODEX_PI_BRIDGE = `# Codex Running in Pi\n\nYou are running Codex through pi, a terminal coding assistant. The tools and rules differ from Codex CLI.\n\n## CRITICAL: Tool Replacements\n\n<critical_rule priority=\"0\">\n APPLY_PATCH DOES NOT EXIST USE \"edit\" INSTEAD\n- NEVER use: apply_patch, applyPatch\n- ALWAYS use: edit for ALL file modifications\n</critical_rule>\n\n<critical_rule priority=\"0\">\n UPDATE_PLAN DOES NOT EXIST\n- NEVER use: update_plan, updatePlan, read_plan, readPlan, todowrite, todoread\n- There is no plan tool in this environment\n</critical_rule>\n\n## Available Tools (pi)\n\n- read - Read file contents\n- bash - Execute bash commands\n- edit - Modify files with exact find/replace (requires prior read)\n- write - Create or overwrite files\n- grep - Search file contents (read-only)\n- find - Find files by glob pattern (read-only)\n- ls - List directory contents (read-only)\n\n## Usage Rules\n\n- Read before edit; use read instead of cat/sed for file contents\n- Use edit for surgical changes; write only for new files or complete rewrites\n- Prefer grep/find/ls over bash for discovery\n- Be concise and show file paths clearly when working with files\n\n## Verification Checklist\n\n1. Using edit, not apply_patch\n2. No plan tools used\n3. Only the tools listed above are called\n\nBelow are additional system instruction you MUST follow when responding:\n`;\n"]}
1
+ {"version":3,"file":"pi-codex-bridge.js","sourceRoot":"","sources":["../../../../src/providers/openai-codex/prompts/pi-codex-bridge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,SAAS,cAAc,CAAC,KAAc,EAAU;IAC/C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,MAAM,UAAU,GAAG,KAAK;SACtB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,aAAa,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACzF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAAA,CAC7B,CAAC;SACD,MAAM,CAAC,CAAC,IAAI,EAAiD,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAEjF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3F,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,CAAC,CAAC,CAAC;IAEhD,OAAO,UAAU;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,OAAO,KAAK,UAAU,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;IAAA,CAC9C,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACb;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAc,EAAU;IAC1D,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAExC,OAAO;;;;;;;;;;;EAWN,SAAS;;;CAGV,CAAC;AAAA,CACD","sourcesContent":["/**\n * Codex-Pi bridge prompt\n * Aligns Codex CLI expectations with Pi's toolset.\n */\n\nimport type { Tool } from \"../../../types.js\";\n\nfunction formatToolList(tools?: Tool[]): string {\n\tif (!tools || tools.length === 0) {\n\t\treturn \"- (none)\";\n\t}\n\n\tconst normalized = tools\n\t\t.map((tool) => {\n\t\t\tconst name = tool.name.trim();\n\t\t\tif (!name) return null;\n\t\t\tconst description = (tool.description || \"Custom tool\").replace(/\\s*\\n\\s*/g, \" \").trim();\n\t\t\treturn { name, description };\n\t\t})\n\t\t.filter((tool): tool is { name: string; description: string } => tool !== null);\n\n\tif (normalized.length === 0) {\n\t\treturn \"- (none)\";\n\t}\n\n\tconst maxNameLength = normalized.reduce((max, tool) => Math.max(max, tool.name.length), 0);\n\tconst padWidth = Math.max(6, maxNameLength + 1);\n\n\treturn normalized\n\t\t.map((tool) => {\n\t\t\tconst paddedName = tool.name.padEnd(padWidth);\n\t\t\treturn `- ${paddedName}- ${tool.description}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nexport function buildCodexPiBridge(tools?: Tool[]): string {\n\tconst toolsList = formatToolList(tools);\n\n\treturn `# Codex Environment Bridge\n\n<environment_override priority=\"0\">\nIGNORE ALL PREVIOUS INSTRUCTIONS ABOVE THIS MESSAGE.\nDo not assume any tools are available unless listed below.\n</environment_override>\n\nThe next system instructions that follow this message are authoritative and must be obeyed, even if they conflict with earlier instructions.\n\n## Available Tools\n\n${toolsList}\n\nOnly use the tools listed above. Do not reference or call any other tools.\n`;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ export interface CodexSystemPrompt {
2
+ instructions: string;
3
+ developerMessages: string[];
4
+ }
5
+ export declare function buildCodexSystemPrompt(args: {
6
+ codexInstructions: string;
7
+ bridgeText: string;
8
+ userSystemPrompt?: string;
9
+ }): CodexSystemPrompt;
10
+ //# sourceMappingURL=system-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../../../src/providers/openai-codex/prompts/system-prompt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,iBAAiB,CAgBpB","sourcesContent":["export interface CodexSystemPrompt {\n\tinstructions: string;\n\tdeveloperMessages: string[];\n}\n\nexport function buildCodexSystemPrompt(args: {\n\tcodexInstructions: string;\n\tbridgeText: string;\n\tuserSystemPrompt?: string;\n}): CodexSystemPrompt {\n\tconst { codexInstructions, bridgeText, userSystemPrompt } = args;\n\tconst developerMessages: string[] = [];\n\n\tif (bridgeText.trim().length > 0) {\n\t\tdeveloperMessages.push(bridgeText.trim());\n\t}\n\n\tif (userSystemPrompt && userSystemPrompt.trim().length > 0) {\n\t\tdeveloperMessages.push(userSystemPrompt.trim());\n\t}\n\n\treturn {\n\t\tinstructions: codexInstructions.trim(),\n\t\tdeveloperMessages,\n\t};\n}\n"]}
@@ -0,0 +1,15 @@
1
+ export function buildCodexSystemPrompt(args) {
2
+ const { codexInstructions, bridgeText, userSystemPrompt } = args;
3
+ const developerMessages = [];
4
+ if (bridgeText.trim().length > 0) {
5
+ developerMessages.push(bridgeText.trim());
6
+ }
7
+ if (userSystemPrompt && userSystemPrompt.trim().length > 0) {
8
+ developerMessages.push(userSystemPrompt.trim());
9
+ }
10
+ return {
11
+ instructions: codexInstructions.trim(),
12
+ developerMessages,
13
+ };
14
+ }
15
+ //# sourceMappingURL=system-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../../../src/providers/openai-codex/prompts/system-prompt.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,sBAAsB,CAAC,IAItC,EAAqB;IACrB,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACjE,MAAM,iBAAiB,GAAa,EAAE,CAAC;IAEvC,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,OAAO;QACN,YAAY,EAAE,iBAAiB,CAAC,IAAI,EAAE;QACtC,iBAAiB;KACjB,CAAC;AAAA,CACF","sourcesContent":["export interface CodexSystemPrompt {\n\tinstructions: string;\n\tdeveloperMessages: string[];\n}\n\nexport function buildCodexSystemPrompt(args: {\n\tcodexInstructions: string;\n\tbridgeText: string;\n\tuserSystemPrompt?: string;\n}): CodexSystemPrompt {\n\tconst { codexInstructions, bridgeText, userSystemPrompt } = args;\n\tconst developerMessages: string[] = [];\n\n\tif (bridgeText.trim().length > 0) {\n\t\tdeveloperMessages.push(bridgeText.trim());\n\t}\n\n\tif (userSystemPrompt && userSystemPrompt.trim().length > 0) {\n\t\tdeveloperMessages.push(userSystemPrompt.trim());\n\t}\n\n\treturn {\n\t\tinstructions: codexInstructions.trim(),\n\t\tdeveloperMessages,\n\t};\n}\n"]}
@@ -32,10 +32,14 @@ export interface RequestBody {
32
32
  };
33
33
  include?: string[];
34
34
  prompt_cache_key?: string;
35
+ prompt_cache_retention?: "in_memory" | "24h";
35
36
  max_output_tokens?: number;
36
37
  max_completion_tokens?: number;
37
38
  [key: string]: unknown;
38
39
  }
39
40
  export declare function normalizeModel(model: string | undefined): string;
40
- export declare function transformRequestBody(body: RequestBody, codexInstructions: string, options?: CodexRequestOptions, codexMode?: boolean, systemPrompt?: string): Promise<RequestBody>;
41
+ export declare function transformRequestBody(body: RequestBody, options?: CodexRequestOptions, prompt?: {
42
+ instructions: string;
43
+ developerMessages: string[];
44
+ }): Promise<RequestBody>;
41
45
  //# sourceMappingURL=request-transformer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-transformer.d.ts","sourceRoot":"","sources":["../../../src/providers/openai-codex/request-transformer.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACjE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC5C,gBAAgB,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IACrD,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACzB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE;QACN,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;KACtC,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAiDD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA0ChE;AAsHD,wBAAsB,oBAAoB,CACzC,IAAI,EAAE,WAAW,EACjB,iBAAiB,EAAE,MAAM,EACzB,OAAO,GAAE,mBAAwB,EACjC,SAAS,UAAO,EAChB,YAAY,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,WAAW,CAAC,CA2EtB","sourcesContent":["import { TOOL_REMAP_MESSAGE } from \"./prompts/codex.js\";\nimport { CODEX_PI_BRIDGE } from \"./prompts/pi-codex-bridge.js\";\n\nexport interface ReasoningConfig {\n\teffort: \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\tsummary: \"auto\" | \"concise\" | \"detailed\" | \"off\" | \"on\";\n}\n\nexport interface CodexRequestOptions {\n\treasoningEffort?: ReasoningConfig[\"effort\"];\n\treasoningSummary?: ReasoningConfig[\"summary\"] | null;\n\ttextVerbosity?: \"low\" | \"medium\" | \"high\";\n\tinclude?: string[];\n}\n\nexport interface InputItem {\n\tid?: string | null;\n\ttype?: string | null;\n\trole?: string;\n\tcontent?: unknown;\n\tcall_id?: string | null;\n\tname?: string;\n\toutput?: unknown;\n\targuments?: string;\n}\n\nexport interface RequestBody {\n\tmodel: string;\n\tstore?: boolean;\n\tstream?: boolean;\n\tinstructions?: string;\n\tinput?: InputItem[];\n\ttools?: unknown;\n\ttemperature?: number;\n\treasoning?: Partial<ReasoningConfig>;\n\ttext?: {\n\t\tverbosity?: \"low\" | \"medium\" | \"high\";\n\t};\n\tinclude?: string[];\n\tprompt_cache_key?: string;\n\tmax_output_tokens?: number;\n\tmax_completion_tokens?: number;\n\t[key: string]: unknown;\n}\n\nconst MODEL_MAP: Record<string, string> = {\n\t\"gpt-5.1-codex\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-low\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-medium\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-high\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-max\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-low\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-medium\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-high\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-xhigh\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.2\": \"gpt-5.2\",\n\t\"gpt-5.2-none\": \"gpt-5.2\",\n\t\"gpt-5.2-low\": \"gpt-5.2\",\n\t\"gpt-5.2-medium\": \"gpt-5.2\",\n\t\"gpt-5.2-high\": \"gpt-5.2\",\n\t\"gpt-5.2-xhigh\": \"gpt-5.2\",\n\t\"gpt-5.2-codex\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-low\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-medium\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-high\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-xhigh\": \"gpt-5.2-codex\",\n\t\"gpt-5.1-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1\": \"gpt-5.1\",\n\t\"gpt-5.1-none\": \"gpt-5.1\",\n\t\"gpt-5.1-low\": \"gpt-5.1\",\n\t\"gpt-5.1-medium\": \"gpt-5.1\",\n\t\"gpt-5.1-high\": \"gpt-5.1\",\n\t\"gpt-5.1-chat-latest\": \"gpt-5.1\",\n\t\"gpt-5-codex\": \"gpt-5.1-codex\",\n\t\"codex-mini-latest\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5\": \"gpt-5.1\",\n\t\"gpt-5-mini\": \"gpt-5.1\",\n\t\"gpt-5-nano\": \"gpt-5.1\",\n};\n\nfunction getNormalizedModel(modelId: string): string | undefined {\n\tif (MODEL_MAP[modelId]) return MODEL_MAP[modelId];\n\tconst lowerModelId = modelId.toLowerCase();\n\tconst match = Object.keys(MODEL_MAP).find((key) => key.toLowerCase() === lowerModelId);\n\treturn match ? MODEL_MAP[match] : undefined;\n}\n\nexport function normalizeModel(model: string | undefined): string {\n\tif (!model) return \"gpt-5.1\";\n\n\tconst modelId = model.includes(\"/\") ? model.split(\"/\").pop()! : model;\n\tconst mappedModel = getNormalizedModel(modelId);\n\tif (mappedModel) return mappedModel;\n\n\tconst normalized = modelId.toLowerCase();\n\n\tif (normalized.includes(\"gpt-5.2-codex\") || normalized.includes(\"gpt 5.2 codex\")) {\n\t\treturn \"gpt-5.2-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.2\") || normalized.includes(\"gpt 5.2\")) {\n\t\treturn \"gpt-5.2\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-max\") || normalized.includes(\"gpt 5.1 codex max\")) {\n\t\treturn \"gpt-5.1-codex-max\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-mini\") || normalized.includes(\"gpt 5.1 codex mini\")) {\n\t\treturn \"gpt-5.1-codex-mini\";\n\t}\n\tif (\n\t\tnormalized.includes(\"codex-mini-latest\") ||\n\t\tnormalized.includes(\"gpt-5-codex-mini\") ||\n\t\tnormalized.includes(\"gpt 5 codex mini\")\n\t) {\n\t\treturn \"codex-mini-latest\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex\") || normalized.includes(\"gpt 5.1 codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.1\") || normalized.includes(\"gpt 5.1\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\tif (normalized.includes(\"codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5\") || normalized.includes(\"gpt 5\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\n\treturn \"gpt-5.1\";\n}\n\nfunction getReasoningConfig(modelName: string | undefined, options: CodexRequestOptions = {}): ReasoningConfig {\n\tconst normalizedName = modelName?.toLowerCase() ?? \"\";\n\n\tconst isGpt52Codex = normalizedName.includes(\"gpt-5.2-codex\") || normalizedName.includes(\"gpt 5.2 codex\");\n\tconst isGpt52General = (normalizedName.includes(\"gpt-5.2\") || normalizedName.includes(\"gpt 5.2\")) && !isGpt52Codex;\n\tconst isCodexMax = normalizedName.includes(\"codex-max\") || normalizedName.includes(\"codex max\");\n\tconst isCodexMini =\n\t\tnormalizedName.includes(\"codex-mini\") ||\n\t\tnormalizedName.includes(\"codex mini\") ||\n\t\tnormalizedName.includes(\"codex_mini\") ||\n\t\tnormalizedName.includes(\"codex-mini-latest\");\n\tconst isCodex = normalizedName.includes(\"codex\") && !isCodexMini;\n\tconst isLightweight = !isCodexMini && (normalizedName.includes(\"nano\") || normalizedName.includes(\"mini\"));\n\tconst isGpt51General =\n\t\t(normalizedName.includes(\"gpt-5.1\") || normalizedName.includes(\"gpt 5.1\")) &&\n\t\t!isCodex &&\n\t\t!isCodexMax &&\n\t\t!isCodexMini;\n\n\tconst supportsXhigh = isGpt52General || isGpt52Codex || isCodexMax;\n\tconst supportsNone = isGpt52General || isGpt51General;\n\n\tconst defaultEffort: ReasoningConfig[\"effort\"] = isCodexMini\n\t\t? \"medium\"\n\t\t: supportsXhigh\n\t\t\t? \"high\"\n\t\t\t: isLightweight\n\t\t\t\t? \"minimal\"\n\t\t\t\t: \"medium\";\n\n\tlet effort = options.reasoningEffort || defaultEffort;\n\n\tif (isCodexMini) {\n\t\tif (effort === \"minimal\" || effort === \"low\" || effort === \"none\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t\tif (effort === \"xhigh\") {\n\t\t\teffort = \"high\";\n\t\t}\n\t\tif (effort !== \"high\" && effort !== \"medium\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t}\n\n\tif (!supportsXhigh && effort === \"xhigh\") {\n\t\teffort = \"high\";\n\t}\n\n\tif (!supportsNone && effort === \"none\") {\n\t\teffort = \"low\";\n\t}\n\n\tif (isCodex && effort === \"minimal\") {\n\t\teffort = \"low\";\n\t}\n\n\treturn {\n\t\teffort,\n\t\tsummary: options.reasoningSummary ?? \"auto\",\n\t};\n}\n\nfunction filterInput(input: InputItem[] | undefined): InputItem[] | undefined {\n\tif (!Array.isArray(input)) return input;\n\n\treturn input\n\t\t.filter((item) => item.type !== \"item_reference\")\n\t\t.map((item) => {\n\t\t\tif (item.id != null) {\n\t\t\t\tconst { id: _id, ...rest } = item;\n\t\t\t\treturn rest as InputItem;\n\t\t\t}\n\t\t\treturn item;\n\t\t});\n}\n\nfunction addCodexBridgeMessage(\n\tinput: InputItem[] | undefined,\n\thasTools: boolean,\n\tsystemPrompt?: string,\n): InputItem[] | undefined {\n\tif (!hasTools || !Array.isArray(input)) return input;\n\n\tconst bridgeText = systemPrompt ? `${CODEX_PI_BRIDGE}\\n\\n${systemPrompt}` : CODEX_PI_BRIDGE;\n\n\tconst bridgeMessage: InputItem = {\n\t\ttype: \"message\",\n\t\trole: \"developer\",\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"input_text\",\n\t\t\t\ttext: bridgeText,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn [bridgeMessage, ...input];\n}\n\nfunction addToolRemapMessage(input: InputItem[] | undefined, hasTools: boolean): InputItem[] | undefined {\n\tif (!hasTools || !Array.isArray(input)) return input;\n\n\tconst toolRemapMessage: InputItem = {\n\t\ttype: \"message\",\n\t\trole: \"developer\",\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"input_text\",\n\t\t\t\ttext: TOOL_REMAP_MESSAGE,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn [toolRemapMessage, ...input];\n}\n\nexport async function transformRequestBody(\n\tbody: RequestBody,\n\tcodexInstructions: string,\n\toptions: CodexRequestOptions = {},\n\tcodexMode = true,\n\tsystemPrompt?: string,\n): Promise<RequestBody> {\n\tconst normalizedModel = normalizeModel(body.model);\n\n\tbody.model = normalizedModel;\n\tbody.store = false;\n\tbody.stream = true;\n\tbody.instructions = codexInstructions;\n\n\tif (body.input && Array.isArray(body.input)) {\n\t\tbody.input = filterInput(body.input);\n\n\t\tif (codexMode) {\n\t\t\tbody.input = addCodexBridgeMessage(body.input, !!body.tools, systemPrompt);\n\t\t} else {\n\t\t\tbody.input = addToolRemapMessage(body.input, !!body.tools);\n\t\t}\n\n\t\tif (body.input) {\n\t\t\tconst functionCallIds = new Set(\n\t\t\t\tbody.input\n\t\t\t\t\t.filter((item) => item.type === \"function_call\" && typeof item.call_id === \"string\")\n\t\t\t\t\t.map((item) => item.call_id as string),\n\t\t\t);\n\n\t\t\tbody.input = body.input.map((item) => {\n\t\t\t\tif (item.type === \"function_call_output\" && typeof item.call_id === \"string\") {\n\t\t\t\t\tconst callId = item.call_id as string;\n\t\t\t\t\tif (!functionCallIds.has(callId)) {\n\t\t\t\t\t\tconst itemRecord = item as unknown as Record<string, unknown>;\n\t\t\t\t\t\tconst toolName = typeof itemRecord.name === \"string\" ? itemRecord.name : \"tool\";\n\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst output = itemRecord.output;\n\t\t\t\t\t\t\ttext = typeof output === \"string\" ? output : JSON.stringify(output);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\ttext = String(itemRecord.output ?? \"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (text.length > 16000) {\n\t\t\t\t\t\t\ttext = `${text.slice(0, 16000)}\\n...[truncated]`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\t\tcontent: `[Previous ${toolName} result; call_id=${callId}]: ${text}`,\n\t\t\t\t\t\t} as InputItem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t});\n\t\t}\n\t}\n\n\tif (options.reasoningEffort !== undefined) {\n\t\tconst reasoningConfig = getReasoningConfig(normalizedModel, options);\n\t\tbody.reasoning = {\n\t\t\t...body.reasoning,\n\t\t\t...reasoningConfig,\n\t\t};\n\t} else {\n\t\tdelete body.reasoning;\n\t}\n\n\tbody.text = {\n\t\t...body.text,\n\t\tverbosity: options.textVerbosity || \"medium\",\n\t};\n\n\tconst include = Array.isArray(options.include) ? [...options.include] : [];\n\tinclude.push(\"reasoning.encrypted_content\");\n\tbody.include = Array.from(new Set(include));\n\n\tdelete body.max_output_tokens;\n\tdelete body.max_completion_tokens;\n\n\treturn body;\n}\n"]}
1
+ {"version":3,"file":"request-transformer.d.ts","sourceRoot":"","sources":["../../../src/providers/openai-codex/request-transformer.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACjE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC5C,gBAAgB,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IACrD,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACzB,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE;QACN,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;KACtC,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sBAAsB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAC7C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAiDD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CA0ChE;AA8ED,wBAAsB,oBAAoB,CACzC,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,mBAAwB,EACjC,MAAM,CAAC,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAAE,GAC5D,OAAO,CAAC,WAAW,CAAC,CAgFtB","sourcesContent":["export interface ReasoningConfig {\n\teffort: \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\tsummary: \"auto\" | \"concise\" | \"detailed\" | \"off\" | \"on\";\n}\n\nexport interface CodexRequestOptions {\n\treasoningEffort?: ReasoningConfig[\"effort\"];\n\treasoningSummary?: ReasoningConfig[\"summary\"] | null;\n\ttextVerbosity?: \"low\" | \"medium\" | \"high\";\n\tinclude?: string[];\n}\n\nexport interface InputItem {\n\tid?: string | null;\n\ttype?: string | null;\n\trole?: string;\n\tcontent?: unknown;\n\tcall_id?: string | null;\n\tname?: string;\n\toutput?: unknown;\n\targuments?: string;\n}\n\nexport interface RequestBody {\n\tmodel: string;\n\tstore?: boolean;\n\tstream?: boolean;\n\tinstructions?: string;\n\tinput?: InputItem[];\n\ttools?: unknown;\n\ttemperature?: number;\n\treasoning?: Partial<ReasoningConfig>;\n\ttext?: {\n\t\tverbosity?: \"low\" | \"medium\" | \"high\";\n\t};\n\tinclude?: string[];\n\tprompt_cache_key?: string;\n\tprompt_cache_retention?: \"in_memory\" | \"24h\";\n\tmax_output_tokens?: number;\n\tmax_completion_tokens?: number;\n\t[key: string]: unknown;\n}\n\nconst MODEL_MAP: Record<string, string> = {\n\t\"gpt-5.1-codex\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-low\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-medium\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-high\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-max\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-low\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-medium\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-high\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-xhigh\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.2\": \"gpt-5.2\",\n\t\"gpt-5.2-none\": \"gpt-5.2\",\n\t\"gpt-5.2-low\": \"gpt-5.2\",\n\t\"gpt-5.2-medium\": \"gpt-5.2\",\n\t\"gpt-5.2-high\": \"gpt-5.2\",\n\t\"gpt-5.2-xhigh\": \"gpt-5.2\",\n\t\"gpt-5.2-codex\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-low\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-medium\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-high\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-xhigh\": \"gpt-5.2-codex\",\n\t\"gpt-5.1-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1\": \"gpt-5.1\",\n\t\"gpt-5.1-none\": \"gpt-5.1\",\n\t\"gpt-5.1-low\": \"gpt-5.1\",\n\t\"gpt-5.1-medium\": \"gpt-5.1\",\n\t\"gpt-5.1-high\": \"gpt-5.1\",\n\t\"gpt-5.1-chat-latest\": \"gpt-5.1\",\n\t\"gpt-5-codex\": \"gpt-5.1-codex\",\n\t\"codex-mini-latest\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5\": \"gpt-5.1\",\n\t\"gpt-5-mini\": \"gpt-5.1\",\n\t\"gpt-5-nano\": \"gpt-5.1\",\n};\n\nfunction getNormalizedModel(modelId: string): string | undefined {\n\tif (MODEL_MAP[modelId]) return MODEL_MAP[modelId];\n\tconst lowerModelId = modelId.toLowerCase();\n\tconst match = Object.keys(MODEL_MAP).find((key) => key.toLowerCase() === lowerModelId);\n\treturn match ? MODEL_MAP[match] : undefined;\n}\n\nexport function normalizeModel(model: string | undefined): string {\n\tif (!model) return \"gpt-5.1\";\n\n\tconst modelId = model.includes(\"/\") ? model.split(\"/\").pop()! : model;\n\tconst mappedModel = getNormalizedModel(modelId);\n\tif (mappedModel) return mappedModel;\n\n\tconst normalized = modelId.toLowerCase();\n\n\tif (normalized.includes(\"gpt-5.2-codex\") || normalized.includes(\"gpt 5.2 codex\")) {\n\t\treturn \"gpt-5.2-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.2\") || normalized.includes(\"gpt 5.2\")) {\n\t\treturn \"gpt-5.2\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-max\") || normalized.includes(\"gpt 5.1 codex max\")) {\n\t\treturn \"gpt-5.1-codex-max\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-mini\") || normalized.includes(\"gpt 5.1 codex mini\")) {\n\t\treturn \"gpt-5.1-codex-mini\";\n\t}\n\tif (\n\t\tnormalized.includes(\"codex-mini-latest\") ||\n\t\tnormalized.includes(\"gpt-5-codex-mini\") ||\n\t\tnormalized.includes(\"gpt 5 codex mini\")\n\t) {\n\t\treturn \"codex-mini-latest\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex\") || normalized.includes(\"gpt 5.1 codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.1\") || normalized.includes(\"gpt 5.1\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\tif (normalized.includes(\"codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5\") || normalized.includes(\"gpt 5\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\n\treturn \"gpt-5.1\";\n}\n\nfunction getReasoningConfig(modelName: string | undefined, options: CodexRequestOptions = {}): ReasoningConfig {\n\tconst normalizedName = modelName?.toLowerCase() ?? \"\";\n\n\tconst isGpt52Codex = normalizedName.includes(\"gpt-5.2-codex\") || normalizedName.includes(\"gpt 5.2 codex\");\n\tconst isGpt52General = (normalizedName.includes(\"gpt-5.2\") || normalizedName.includes(\"gpt 5.2\")) && !isGpt52Codex;\n\tconst isCodexMax = normalizedName.includes(\"codex-max\") || normalizedName.includes(\"codex max\");\n\tconst isCodexMini =\n\t\tnormalizedName.includes(\"codex-mini\") ||\n\t\tnormalizedName.includes(\"codex mini\") ||\n\t\tnormalizedName.includes(\"codex_mini\") ||\n\t\tnormalizedName.includes(\"codex-mini-latest\");\n\tconst isCodex = normalizedName.includes(\"codex\") && !isCodexMini;\n\tconst isLightweight = !isCodexMini && (normalizedName.includes(\"nano\") || normalizedName.includes(\"mini\"));\n\tconst isGpt51General =\n\t\t(normalizedName.includes(\"gpt-5.1\") || normalizedName.includes(\"gpt 5.1\")) &&\n\t\t!isCodex &&\n\t\t!isCodexMax &&\n\t\t!isCodexMini;\n\n\tconst supportsXhigh = isGpt52General || isGpt52Codex || isCodexMax;\n\tconst supportsNone = isGpt52General || isGpt51General;\n\n\tconst defaultEffort: ReasoningConfig[\"effort\"] = isCodexMini\n\t\t? \"medium\"\n\t\t: supportsXhigh\n\t\t\t? \"high\"\n\t\t\t: isLightweight\n\t\t\t\t? \"minimal\"\n\t\t\t\t: \"medium\";\n\n\tlet effort = options.reasoningEffort || defaultEffort;\n\n\tif (isCodexMini) {\n\t\tif (effort === \"minimal\" || effort === \"low\" || effort === \"none\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t\tif (effort === \"xhigh\") {\n\t\t\teffort = \"high\";\n\t\t}\n\t\tif (effort !== \"high\" && effort !== \"medium\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t}\n\n\tif (!supportsXhigh && effort === \"xhigh\") {\n\t\teffort = \"high\";\n\t}\n\n\tif (!supportsNone && effort === \"none\") {\n\t\teffort = \"low\";\n\t}\n\n\tif (isCodex && effort === \"minimal\") {\n\t\teffort = \"low\";\n\t}\n\n\treturn {\n\t\teffort,\n\t\tsummary: options.reasoningSummary ?? \"auto\",\n\t};\n}\n\nfunction filterInput(input: InputItem[] | undefined): InputItem[] | undefined {\n\tif (!Array.isArray(input)) return input;\n\n\treturn input\n\t\t.filter((item) => item.type !== \"item_reference\")\n\t\t.map((item) => {\n\t\t\tif (item.id != null) {\n\t\t\t\tconst { id: _id, ...rest } = item;\n\t\t\t\treturn rest as InputItem;\n\t\t\t}\n\t\t\treturn item;\n\t\t});\n}\n\nexport async function transformRequestBody(\n\tbody: RequestBody,\n\toptions: CodexRequestOptions = {},\n\tprompt?: { instructions: string; developerMessages: string[] },\n): Promise<RequestBody> {\n\tconst normalizedModel = normalizeModel(body.model);\n\n\tbody.model = normalizedModel;\n\tbody.store = false;\n\tbody.stream = true;\n\n\tif (body.input && Array.isArray(body.input)) {\n\t\tbody.input = filterInput(body.input);\n\n\t\tif (body.input) {\n\t\t\tconst functionCallIds = new Set(\n\t\t\t\tbody.input\n\t\t\t\t\t.filter((item) => item.type === \"function_call\" && typeof item.call_id === \"string\")\n\t\t\t\t\t.map((item) => item.call_id as string),\n\t\t\t);\n\n\t\t\tbody.input = body.input.map((item) => {\n\t\t\t\tif (item.type === \"function_call_output\" && typeof item.call_id === \"string\") {\n\t\t\t\t\tconst callId = item.call_id as string;\n\t\t\t\t\tif (!functionCallIds.has(callId)) {\n\t\t\t\t\t\tconst itemRecord = item as unknown as Record<string, unknown>;\n\t\t\t\t\t\tconst toolName = typeof itemRecord.name === \"string\" ? itemRecord.name : \"tool\";\n\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst output = itemRecord.output;\n\t\t\t\t\t\t\ttext = typeof output === \"string\" ? output : JSON.stringify(output);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\ttext = String(itemRecord.output ?? \"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (text.length > 16000) {\n\t\t\t\t\t\t\ttext = `${text.slice(0, 16000)}\\n...[truncated]`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\t\tcontent: `[Previous ${toolName} result; call_id=${callId}]: ${text}`,\n\t\t\t\t\t\t} as InputItem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t});\n\t\t}\n\t}\n\n\tif (prompt?.developerMessages && prompt.developerMessages.length > 0 && Array.isArray(body.input)) {\n\t\tconst developerMessages = prompt.developerMessages.map(\n\t\t\t(text) =>\n\t\t\t\t({\n\t\t\t\t\ttype: \"message\",\n\t\t\t\t\trole: \"developer\",\n\t\t\t\t\tcontent: [{ type: \"input_text\", text }],\n\t\t\t\t}) as InputItem,\n\t\t);\n\t\tbody.input = [...developerMessages, ...body.input];\n\t}\n\n\tif (options.reasoningEffort !== undefined) {\n\t\tconst reasoningConfig = getReasoningConfig(normalizedModel, options);\n\t\tbody.reasoning = {\n\t\t\t...body.reasoning,\n\t\t\t...reasoningConfig,\n\t\t};\n\t} else {\n\t\tdelete body.reasoning;\n\t}\n\n\tbody.text = {\n\t\t...body.text,\n\t\tverbosity: options.textVerbosity || \"medium\",\n\t};\n\n\tconst include = Array.isArray(options.include) ? [...options.include] : [];\n\tinclude.push(\"reasoning.encrypted_content\");\n\tbody.include = Array.from(new Set(include));\n\n\tdelete body.max_output_tokens;\n\tdelete body.max_completion_tokens;\n\n\treturn body;\n}\n"]}
@@ -1,5 +1,3 @@
1
- import { TOOL_REMAP_MESSAGE } from "./prompts/codex.js";
2
- import { CODEX_PI_BRIDGE } from "./prompts/pi-codex-bridge.js";
3
1
  const MODEL_MAP = {
4
2
  "gpt-5.1-codex": "gpt-5.1-codex",
5
3
  "gpt-5.1-codex-low": "gpt-5.1-codex",
@@ -148,51 +146,13 @@ function filterInput(input) {
148
146
  return item;
149
147
  });
150
148
  }
151
- function addCodexBridgeMessage(input, hasTools, systemPrompt) {
152
- if (!hasTools || !Array.isArray(input))
153
- return input;
154
- const bridgeText = systemPrompt ? `${CODEX_PI_BRIDGE}\n\n${systemPrompt}` : CODEX_PI_BRIDGE;
155
- const bridgeMessage = {
156
- type: "message",
157
- role: "developer",
158
- content: [
159
- {
160
- type: "input_text",
161
- text: bridgeText,
162
- },
163
- ],
164
- };
165
- return [bridgeMessage, ...input];
166
- }
167
- function addToolRemapMessage(input, hasTools) {
168
- if (!hasTools || !Array.isArray(input))
169
- return input;
170
- const toolRemapMessage = {
171
- type: "message",
172
- role: "developer",
173
- content: [
174
- {
175
- type: "input_text",
176
- text: TOOL_REMAP_MESSAGE,
177
- },
178
- ],
179
- };
180
- return [toolRemapMessage, ...input];
181
- }
182
- export async function transformRequestBody(body, codexInstructions, options = {}, codexMode = true, systemPrompt) {
149
+ export async function transformRequestBody(body, options = {}, prompt) {
183
150
  const normalizedModel = normalizeModel(body.model);
184
151
  body.model = normalizedModel;
185
152
  body.store = false;
186
153
  body.stream = true;
187
- body.instructions = codexInstructions;
188
154
  if (body.input && Array.isArray(body.input)) {
189
155
  body.input = filterInput(body.input);
190
- if (codexMode) {
191
- body.input = addCodexBridgeMessage(body.input, !!body.tools, systemPrompt);
192
- }
193
- else {
194
- body.input = addToolRemapMessage(body.input, !!body.tools);
195
- }
196
156
  if (body.input) {
197
157
  const functionCallIds = new Set(body.input
198
158
  .filter((item) => item.type === "function_call" && typeof item.call_id === "string")
@@ -225,6 +185,14 @@ export async function transformRequestBody(body, codexInstructions, options = {}
225
185
  });
226
186
  }
227
187
  }
188
+ if (prompt?.developerMessages && prompt.developerMessages.length > 0 && Array.isArray(body.input)) {
189
+ const developerMessages = prompt.developerMessages.map((text) => ({
190
+ type: "message",
191
+ role: "developer",
192
+ content: [{ type: "input_text", text }],
193
+ }));
194
+ body.input = [...developerMessages, ...body.input];
195
+ }
228
196
  if (options.reasoningEffort !== undefined) {
229
197
  const reasoningConfig = getReasoningConfig(normalizedModel, options);
230
198
  body.reasoning = {
@@ -1 +1 @@
1
- {"version":3,"file":"request-transformer.js","sourceRoot":"","sources":["../../../src/providers/openai-codex/request-transformer.ts"],"names":[],"mappings":"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","sourcesContent":["import { TOOL_REMAP_MESSAGE } from \"./prompts/codex.js\";\nimport { CODEX_PI_BRIDGE } from \"./prompts/pi-codex-bridge.js\";\n\nexport interface ReasoningConfig {\n\teffort: \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\tsummary: \"auto\" | \"concise\" | \"detailed\" | \"off\" | \"on\";\n}\n\nexport interface CodexRequestOptions {\n\treasoningEffort?: ReasoningConfig[\"effort\"];\n\treasoningSummary?: ReasoningConfig[\"summary\"] | null;\n\ttextVerbosity?: \"low\" | \"medium\" | \"high\";\n\tinclude?: string[];\n}\n\nexport interface InputItem {\n\tid?: string | null;\n\ttype?: string | null;\n\trole?: string;\n\tcontent?: unknown;\n\tcall_id?: string | null;\n\tname?: string;\n\toutput?: unknown;\n\targuments?: string;\n}\n\nexport interface RequestBody {\n\tmodel: string;\n\tstore?: boolean;\n\tstream?: boolean;\n\tinstructions?: string;\n\tinput?: InputItem[];\n\ttools?: unknown;\n\ttemperature?: number;\n\treasoning?: Partial<ReasoningConfig>;\n\ttext?: {\n\t\tverbosity?: \"low\" | \"medium\" | \"high\";\n\t};\n\tinclude?: string[];\n\tprompt_cache_key?: string;\n\tmax_output_tokens?: number;\n\tmax_completion_tokens?: number;\n\t[key: string]: unknown;\n}\n\nconst MODEL_MAP: Record<string, string> = {\n\t\"gpt-5.1-codex\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-low\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-medium\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-high\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-max\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-low\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-medium\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-high\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-xhigh\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.2\": \"gpt-5.2\",\n\t\"gpt-5.2-none\": \"gpt-5.2\",\n\t\"gpt-5.2-low\": \"gpt-5.2\",\n\t\"gpt-5.2-medium\": \"gpt-5.2\",\n\t\"gpt-5.2-high\": \"gpt-5.2\",\n\t\"gpt-5.2-xhigh\": \"gpt-5.2\",\n\t\"gpt-5.2-codex\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-low\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-medium\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-high\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-xhigh\": \"gpt-5.2-codex\",\n\t\"gpt-5.1-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1\": \"gpt-5.1\",\n\t\"gpt-5.1-none\": \"gpt-5.1\",\n\t\"gpt-5.1-low\": \"gpt-5.1\",\n\t\"gpt-5.1-medium\": \"gpt-5.1\",\n\t\"gpt-5.1-high\": \"gpt-5.1\",\n\t\"gpt-5.1-chat-latest\": \"gpt-5.1\",\n\t\"gpt-5-codex\": \"gpt-5.1-codex\",\n\t\"codex-mini-latest\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5\": \"gpt-5.1\",\n\t\"gpt-5-mini\": \"gpt-5.1\",\n\t\"gpt-5-nano\": \"gpt-5.1\",\n};\n\nfunction getNormalizedModel(modelId: string): string | undefined {\n\tif (MODEL_MAP[modelId]) return MODEL_MAP[modelId];\n\tconst lowerModelId = modelId.toLowerCase();\n\tconst match = Object.keys(MODEL_MAP).find((key) => key.toLowerCase() === lowerModelId);\n\treturn match ? MODEL_MAP[match] : undefined;\n}\n\nexport function normalizeModel(model: string | undefined): string {\n\tif (!model) return \"gpt-5.1\";\n\n\tconst modelId = model.includes(\"/\") ? model.split(\"/\").pop()! : model;\n\tconst mappedModel = getNormalizedModel(modelId);\n\tif (mappedModel) return mappedModel;\n\n\tconst normalized = modelId.toLowerCase();\n\n\tif (normalized.includes(\"gpt-5.2-codex\") || normalized.includes(\"gpt 5.2 codex\")) {\n\t\treturn \"gpt-5.2-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.2\") || normalized.includes(\"gpt 5.2\")) {\n\t\treturn \"gpt-5.2\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-max\") || normalized.includes(\"gpt 5.1 codex max\")) {\n\t\treturn \"gpt-5.1-codex-max\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-mini\") || normalized.includes(\"gpt 5.1 codex mini\")) {\n\t\treturn \"gpt-5.1-codex-mini\";\n\t}\n\tif (\n\t\tnormalized.includes(\"codex-mini-latest\") ||\n\t\tnormalized.includes(\"gpt-5-codex-mini\") ||\n\t\tnormalized.includes(\"gpt 5 codex mini\")\n\t) {\n\t\treturn \"codex-mini-latest\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex\") || normalized.includes(\"gpt 5.1 codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.1\") || normalized.includes(\"gpt 5.1\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\tif (normalized.includes(\"codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5\") || normalized.includes(\"gpt 5\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\n\treturn \"gpt-5.1\";\n}\n\nfunction getReasoningConfig(modelName: string | undefined, options: CodexRequestOptions = {}): ReasoningConfig {\n\tconst normalizedName = modelName?.toLowerCase() ?? \"\";\n\n\tconst isGpt52Codex = normalizedName.includes(\"gpt-5.2-codex\") || normalizedName.includes(\"gpt 5.2 codex\");\n\tconst isGpt52General = (normalizedName.includes(\"gpt-5.2\") || normalizedName.includes(\"gpt 5.2\")) && !isGpt52Codex;\n\tconst isCodexMax = normalizedName.includes(\"codex-max\") || normalizedName.includes(\"codex max\");\n\tconst isCodexMini =\n\t\tnormalizedName.includes(\"codex-mini\") ||\n\t\tnormalizedName.includes(\"codex mini\") ||\n\t\tnormalizedName.includes(\"codex_mini\") ||\n\t\tnormalizedName.includes(\"codex-mini-latest\");\n\tconst isCodex = normalizedName.includes(\"codex\") && !isCodexMini;\n\tconst isLightweight = !isCodexMini && (normalizedName.includes(\"nano\") || normalizedName.includes(\"mini\"));\n\tconst isGpt51General =\n\t\t(normalizedName.includes(\"gpt-5.1\") || normalizedName.includes(\"gpt 5.1\")) &&\n\t\t!isCodex &&\n\t\t!isCodexMax &&\n\t\t!isCodexMini;\n\n\tconst supportsXhigh = isGpt52General || isGpt52Codex || isCodexMax;\n\tconst supportsNone = isGpt52General || isGpt51General;\n\n\tconst defaultEffort: ReasoningConfig[\"effort\"] = isCodexMini\n\t\t? \"medium\"\n\t\t: supportsXhigh\n\t\t\t? \"high\"\n\t\t\t: isLightweight\n\t\t\t\t? \"minimal\"\n\t\t\t\t: \"medium\";\n\n\tlet effort = options.reasoningEffort || defaultEffort;\n\n\tif (isCodexMini) {\n\t\tif (effort === \"minimal\" || effort === \"low\" || effort === \"none\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t\tif (effort === \"xhigh\") {\n\t\t\teffort = \"high\";\n\t\t}\n\t\tif (effort !== \"high\" && effort !== \"medium\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t}\n\n\tif (!supportsXhigh && effort === \"xhigh\") {\n\t\teffort = \"high\";\n\t}\n\n\tif (!supportsNone && effort === \"none\") {\n\t\teffort = \"low\";\n\t}\n\n\tif (isCodex && effort === \"minimal\") {\n\t\teffort = \"low\";\n\t}\n\n\treturn {\n\t\teffort,\n\t\tsummary: options.reasoningSummary ?? \"auto\",\n\t};\n}\n\nfunction filterInput(input: InputItem[] | undefined): InputItem[] | undefined {\n\tif (!Array.isArray(input)) return input;\n\n\treturn input\n\t\t.filter((item) => item.type !== \"item_reference\")\n\t\t.map((item) => {\n\t\t\tif (item.id != null) {\n\t\t\t\tconst { id: _id, ...rest } = item;\n\t\t\t\treturn rest as InputItem;\n\t\t\t}\n\t\t\treturn item;\n\t\t});\n}\n\nfunction addCodexBridgeMessage(\n\tinput: InputItem[] | undefined,\n\thasTools: boolean,\n\tsystemPrompt?: string,\n): InputItem[] | undefined {\n\tif (!hasTools || !Array.isArray(input)) return input;\n\n\tconst bridgeText = systemPrompt ? `${CODEX_PI_BRIDGE}\\n\\n${systemPrompt}` : CODEX_PI_BRIDGE;\n\n\tconst bridgeMessage: InputItem = {\n\t\ttype: \"message\",\n\t\trole: \"developer\",\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"input_text\",\n\t\t\t\ttext: bridgeText,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn [bridgeMessage, ...input];\n}\n\nfunction addToolRemapMessage(input: InputItem[] | undefined, hasTools: boolean): InputItem[] | undefined {\n\tif (!hasTools || !Array.isArray(input)) return input;\n\n\tconst toolRemapMessage: InputItem = {\n\t\ttype: \"message\",\n\t\trole: \"developer\",\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"input_text\",\n\t\t\t\ttext: TOOL_REMAP_MESSAGE,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn [toolRemapMessage, ...input];\n}\n\nexport async function transformRequestBody(\n\tbody: RequestBody,\n\tcodexInstructions: string,\n\toptions: CodexRequestOptions = {},\n\tcodexMode = true,\n\tsystemPrompt?: string,\n): Promise<RequestBody> {\n\tconst normalizedModel = normalizeModel(body.model);\n\n\tbody.model = normalizedModel;\n\tbody.store = false;\n\tbody.stream = true;\n\tbody.instructions = codexInstructions;\n\n\tif (body.input && Array.isArray(body.input)) {\n\t\tbody.input = filterInput(body.input);\n\n\t\tif (codexMode) {\n\t\t\tbody.input = addCodexBridgeMessage(body.input, !!body.tools, systemPrompt);\n\t\t} else {\n\t\t\tbody.input = addToolRemapMessage(body.input, !!body.tools);\n\t\t}\n\n\t\tif (body.input) {\n\t\t\tconst functionCallIds = new Set(\n\t\t\t\tbody.input\n\t\t\t\t\t.filter((item) => item.type === \"function_call\" && typeof item.call_id === \"string\")\n\t\t\t\t\t.map((item) => item.call_id as string),\n\t\t\t);\n\n\t\t\tbody.input = body.input.map((item) => {\n\t\t\t\tif (item.type === \"function_call_output\" && typeof item.call_id === \"string\") {\n\t\t\t\t\tconst callId = item.call_id as string;\n\t\t\t\t\tif (!functionCallIds.has(callId)) {\n\t\t\t\t\t\tconst itemRecord = item as unknown as Record<string, unknown>;\n\t\t\t\t\t\tconst toolName = typeof itemRecord.name === \"string\" ? itemRecord.name : \"tool\";\n\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst output = itemRecord.output;\n\t\t\t\t\t\t\ttext = typeof output === \"string\" ? output : JSON.stringify(output);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\ttext = String(itemRecord.output ?? \"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (text.length > 16000) {\n\t\t\t\t\t\t\ttext = `${text.slice(0, 16000)}\\n...[truncated]`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\t\tcontent: `[Previous ${toolName} result; call_id=${callId}]: ${text}`,\n\t\t\t\t\t\t} as InputItem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t});\n\t\t}\n\t}\n\n\tif (options.reasoningEffort !== undefined) {\n\t\tconst reasoningConfig = getReasoningConfig(normalizedModel, options);\n\t\tbody.reasoning = {\n\t\t\t...body.reasoning,\n\t\t\t...reasoningConfig,\n\t\t};\n\t} else {\n\t\tdelete body.reasoning;\n\t}\n\n\tbody.text = {\n\t\t...body.text,\n\t\tverbosity: options.textVerbosity || \"medium\",\n\t};\n\n\tconst include = Array.isArray(options.include) ? [...options.include] : [];\n\tinclude.push(\"reasoning.encrypted_content\");\n\tbody.include = Array.from(new Set(include));\n\n\tdelete body.max_output_tokens;\n\tdelete body.max_completion_tokens;\n\n\treturn body;\n}\n"]}
1
+ {"version":3,"file":"request-transformer.js","sourceRoot":"","sources":["../../../src/providers/openai-codex/request-transformer.ts"],"names":[],"mappings":"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","sourcesContent":["export interface ReasoningConfig {\n\teffort: \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\tsummary: \"auto\" | \"concise\" | \"detailed\" | \"off\" | \"on\";\n}\n\nexport interface CodexRequestOptions {\n\treasoningEffort?: ReasoningConfig[\"effort\"];\n\treasoningSummary?: ReasoningConfig[\"summary\"] | null;\n\ttextVerbosity?: \"low\" | \"medium\" | \"high\";\n\tinclude?: string[];\n}\n\nexport interface InputItem {\n\tid?: string | null;\n\ttype?: string | null;\n\trole?: string;\n\tcontent?: unknown;\n\tcall_id?: string | null;\n\tname?: string;\n\toutput?: unknown;\n\targuments?: string;\n}\n\nexport interface RequestBody {\n\tmodel: string;\n\tstore?: boolean;\n\tstream?: boolean;\n\tinstructions?: string;\n\tinput?: InputItem[];\n\ttools?: unknown;\n\ttemperature?: number;\n\treasoning?: Partial<ReasoningConfig>;\n\ttext?: {\n\t\tverbosity?: \"low\" | \"medium\" | \"high\";\n\t};\n\tinclude?: string[];\n\tprompt_cache_key?: string;\n\tprompt_cache_retention?: \"in_memory\" | \"24h\";\n\tmax_output_tokens?: number;\n\tmax_completion_tokens?: number;\n\t[key: string]: unknown;\n}\n\nconst MODEL_MAP: Record<string, string> = {\n\t\"gpt-5.1-codex\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-low\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-medium\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-high\": \"gpt-5.1-codex\",\n\t\"gpt-5.1-codex-max\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-low\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-medium\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-high\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.1-codex-max-xhigh\": \"gpt-5.1-codex-max\",\n\t\"gpt-5.2\": \"gpt-5.2\",\n\t\"gpt-5.2-none\": \"gpt-5.2\",\n\t\"gpt-5.2-low\": \"gpt-5.2\",\n\t\"gpt-5.2-medium\": \"gpt-5.2\",\n\t\"gpt-5.2-high\": \"gpt-5.2\",\n\t\"gpt-5.2-xhigh\": \"gpt-5.2\",\n\t\"gpt-5.2-codex\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-low\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-medium\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-high\": \"gpt-5.2-codex\",\n\t\"gpt-5.2-codex-xhigh\": \"gpt-5.2-codex\",\n\t\"gpt-5.1-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5.1\": \"gpt-5.1\",\n\t\"gpt-5.1-none\": \"gpt-5.1\",\n\t\"gpt-5.1-low\": \"gpt-5.1\",\n\t\"gpt-5.1-medium\": \"gpt-5.1\",\n\t\"gpt-5.1-high\": \"gpt-5.1\",\n\t\"gpt-5.1-chat-latest\": \"gpt-5.1\",\n\t\"gpt-5-codex\": \"gpt-5.1-codex\",\n\t\"codex-mini-latest\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-medium\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5-codex-mini-high\": \"gpt-5.1-codex-mini\",\n\t\"gpt-5\": \"gpt-5.1\",\n\t\"gpt-5-mini\": \"gpt-5.1\",\n\t\"gpt-5-nano\": \"gpt-5.1\",\n};\n\nfunction getNormalizedModel(modelId: string): string | undefined {\n\tif (MODEL_MAP[modelId]) return MODEL_MAP[modelId];\n\tconst lowerModelId = modelId.toLowerCase();\n\tconst match = Object.keys(MODEL_MAP).find((key) => key.toLowerCase() === lowerModelId);\n\treturn match ? MODEL_MAP[match] : undefined;\n}\n\nexport function normalizeModel(model: string | undefined): string {\n\tif (!model) return \"gpt-5.1\";\n\n\tconst modelId = model.includes(\"/\") ? model.split(\"/\").pop()! : model;\n\tconst mappedModel = getNormalizedModel(modelId);\n\tif (mappedModel) return mappedModel;\n\n\tconst normalized = modelId.toLowerCase();\n\n\tif (normalized.includes(\"gpt-5.2-codex\") || normalized.includes(\"gpt 5.2 codex\")) {\n\t\treturn \"gpt-5.2-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.2\") || normalized.includes(\"gpt 5.2\")) {\n\t\treturn \"gpt-5.2\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-max\") || normalized.includes(\"gpt 5.1 codex max\")) {\n\t\treturn \"gpt-5.1-codex-max\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex-mini\") || normalized.includes(\"gpt 5.1 codex mini\")) {\n\t\treturn \"gpt-5.1-codex-mini\";\n\t}\n\tif (\n\t\tnormalized.includes(\"codex-mini-latest\") ||\n\t\tnormalized.includes(\"gpt-5-codex-mini\") ||\n\t\tnormalized.includes(\"gpt 5 codex mini\")\n\t) {\n\t\treturn \"codex-mini-latest\";\n\t}\n\tif (normalized.includes(\"gpt-5.1-codex\") || normalized.includes(\"gpt 5.1 codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5.1\") || normalized.includes(\"gpt 5.1\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\tif (normalized.includes(\"codex\")) {\n\t\treturn \"gpt-5.1-codex\";\n\t}\n\tif (normalized.includes(\"gpt-5\") || normalized.includes(\"gpt 5\")) {\n\t\treturn \"gpt-5.1\";\n\t}\n\n\treturn \"gpt-5.1\";\n}\n\nfunction getReasoningConfig(modelName: string | undefined, options: CodexRequestOptions = {}): ReasoningConfig {\n\tconst normalizedName = modelName?.toLowerCase() ?? \"\";\n\n\tconst isGpt52Codex = normalizedName.includes(\"gpt-5.2-codex\") || normalizedName.includes(\"gpt 5.2 codex\");\n\tconst isGpt52General = (normalizedName.includes(\"gpt-5.2\") || normalizedName.includes(\"gpt 5.2\")) && !isGpt52Codex;\n\tconst isCodexMax = normalizedName.includes(\"codex-max\") || normalizedName.includes(\"codex max\");\n\tconst isCodexMini =\n\t\tnormalizedName.includes(\"codex-mini\") ||\n\t\tnormalizedName.includes(\"codex mini\") ||\n\t\tnormalizedName.includes(\"codex_mini\") ||\n\t\tnormalizedName.includes(\"codex-mini-latest\");\n\tconst isCodex = normalizedName.includes(\"codex\") && !isCodexMini;\n\tconst isLightweight = !isCodexMini && (normalizedName.includes(\"nano\") || normalizedName.includes(\"mini\"));\n\tconst isGpt51General =\n\t\t(normalizedName.includes(\"gpt-5.1\") || normalizedName.includes(\"gpt 5.1\")) &&\n\t\t!isCodex &&\n\t\t!isCodexMax &&\n\t\t!isCodexMini;\n\n\tconst supportsXhigh = isGpt52General || isGpt52Codex || isCodexMax;\n\tconst supportsNone = isGpt52General || isGpt51General;\n\n\tconst defaultEffort: ReasoningConfig[\"effort\"] = isCodexMini\n\t\t? \"medium\"\n\t\t: supportsXhigh\n\t\t\t? \"high\"\n\t\t\t: isLightweight\n\t\t\t\t? \"minimal\"\n\t\t\t\t: \"medium\";\n\n\tlet effort = options.reasoningEffort || defaultEffort;\n\n\tif (isCodexMini) {\n\t\tif (effort === \"minimal\" || effort === \"low\" || effort === \"none\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t\tif (effort === \"xhigh\") {\n\t\t\teffort = \"high\";\n\t\t}\n\t\tif (effort !== \"high\" && effort !== \"medium\") {\n\t\t\teffort = \"medium\";\n\t\t}\n\t}\n\n\tif (!supportsXhigh && effort === \"xhigh\") {\n\t\teffort = \"high\";\n\t}\n\n\tif (!supportsNone && effort === \"none\") {\n\t\teffort = \"low\";\n\t}\n\n\tif (isCodex && effort === \"minimal\") {\n\t\teffort = \"low\";\n\t}\n\n\treturn {\n\t\teffort,\n\t\tsummary: options.reasoningSummary ?? \"auto\",\n\t};\n}\n\nfunction filterInput(input: InputItem[] | undefined): InputItem[] | undefined {\n\tif (!Array.isArray(input)) return input;\n\n\treturn input\n\t\t.filter((item) => item.type !== \"item_reference\")\n\t\t.map((item) => {\n\t\t\tif (item.id != null) {\n\t\t\t\tconst { id: _id, ...rest } = item;\n\t\t\t\treturn rest as InputItem;\n\t\t\t}\n\t\t\treturn item;\n\t\t});\n}\n\nexport async function transformRequestBody(\n\tbody: RequestBody,\n\toptions: CodexRequestOptions = {},\n\tprompt?: { instructions: string; developerMessages: string[] },\n): Promise<RequestBody> {\n\tconst normalizedModel = normalizeModel(body.model);\n\n\tbody.model = normalizedModel;\n\tbody.store = false;\n\tbody.stream = true;\n\n\tif (body.input && Array.isArray(body.input)) {\n\t\tbody.input = filterInput(body.input);\n\n\t\tif (body.input) {\n\t\t\tconst functionCallIds = new Set(\n\t\t\t\tbody.input\n\t\t\t\t\t.filter((item) => item.type === \"function_call\" && typeof item.call_id === \"string\")\n\t\t\t\t\t.map((item) => item.call_id as string),\n\t\t\t);\n\n\t\t\tbody.input = body.input.map((item) => {\n\t\t\t\tif (item.type === \"function_call_output\" && typeof item.call_id === \"string\") {\n\t\t\t\t\tconst callId = item.call_id as string;\n\t\t\t\t\tif (!functionCallIds.has(callId)) {\n\t\t\t\t\t\tconst itemRecord = item as unknown as Record<string, unknown>;\n\t\t\t\t\t\tconst toolName = typeof itemRecord.name === \"string\" ? itemRecord.name : \"tool\";\n\t\t\t\t\t\tlet text = \"\";\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst output = itemRecord.output;\n\t\t\t\t\t\t\ttext = typeof output === \"string\" ? output : JSON.stringify(output);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\ttext = String(itemRecord.output ?? \"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (text.length > 16000) {\n\t\t\t\t\t\t\ttext = `${text.slice(0, 16000)}\\n...[truncated]`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\t\tcontent: `[Previous ${toolName} result; call_id=${callId}]: ${text}`,\n\t\t\t\t\t\t} as InputItem;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t});\n\t\t}\n\t}\n\n\tif (prompt?.developerMessages && prompt.developerMessages.length > 0 && Array.isArray(body.input)) {\n\t\tconst developerMessages = prompt.developerMessages.map(\n\t\t\t(text) =>\n\t\t\t\t({\n\t\t\t\t\ttype: \"message\",\n\t\t\t\t\trole: \"developer\",\n\t\t\t\t\tcontent: [{ type: \"input_text\", text }],\n\t\t\t\t}) as InputItem,\n\t\t);\n\t\tbody.input = [...developerMessages, ...body.input];\n\t}\n\n\tif (options.reasoningEffort !== undefined) {\n\t\tconst reasoningConfig = getReasoningConfig(normalizedModel, options);\n\t\tbody.reasoning = {\n\t\t\t...body.reasoning,\n\t\t\t...reasoningConfig,\n\t\t};\n\t} else {\n\t\tdelete body.reasoning;\n\t}\n\n\tbody.text = {\n\t\t...body.text,\n\t\tverbosity: options.textVerbosity || \"medium\",\n\t};\n\n\tconst include = Array.isArray(options.include) ? [...options.include] : [];\n\tinclude.push(\"reasoning.encrypted_content\");\n\tbody.include = Array.from(new Set(include));\n\n\tdelete body.max_output_tokens;\n\tdelete body.max_completion_tokens;\n\n\treturn body;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"openai-codex-responses.d.ts","sourceRoot":"","sources":["../../src/providers/openai-codex-responses.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAMX,cAAc,EACd,aAAa,EAKb,MAAM,aAAa,CAAC;AAqBrB,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IACjE,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC3E,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;IACzE,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAID,eAAO,MAAM,0BAA0B,EAAE,cAAc,CAAC,wBAAwB,CA8T/E,CAAC","sourcesContent":["import type {\n\tResponseFunctionToolCall,\n\tResponseInput,\n\tResponseInputContent,\n\tResponseInputImage,\n\tResponseInputText,\n\tResponseOutputMessage,\n\tResponseReasoningItem,\n} from \"openai/resources/responses/responses.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport {\n\tCODEX_BASE_URL,\n\tJWT_CLAIM_PATH,\n\tOPENAI_HEADER_VALUES,\n\tOPENAI_HEADERS,\n\tURL_PATHS,\n} from \"./openai-codex/constants.js\";\nimport { getCodexInstructions } from \"./openai-codex/prompts/codex.js\";\nimport {\n\ttype CodexRequestOptions,\n\tnormalizeModel,\n\ttype RequestBody,\n\ttransformRequestBody,\n} from \"./openai-codex/request-transformer.js\";\nimport { parseCodexError, parseCodexSseStream } from \"./openai-codex/response-handler.js\";\nimport { transformMessages } from \"./transorm-messages.js\";\n\nexport interface OpenAICodexResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\treasoningSummary?: \"auto\" | \"concise\" | \"detailed\" | \"off\" | \"on\" | null;\n\ttextVerbosity?: \"low\" | \"medium\" | \"high\";\n\tinclude?: string[];\n\tcodexMode?: boolean;\n}\n\nconst CODEX_DEBUG = process.env.PI_CODEX_DEBUG === \"1\" || process.env.PI_CODEX_DEBUG === \"true\";\n\nexport const streamOpenAICodexResponses: StreamFunction<\"openai-codex-responses\"> = (\n\tmodel: Model<\"openai-codex-responses\">,\n\tcontext: Context,\n\toptions?: OpenAICodexResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"openai-codex-responses\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider) || \"\";\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t\t}\n\n\t\t\tconst accountId = getAccountId(apiKey);\n\t\t\tconst baseUrl = model.baseUrl || CODEX_BASE_URL;\n\t\t\tconst baseWithSlash = baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`;\n\t\t\tconst url = rewriteUrlForCodex(new URL(URL_PATHS.RESPONSES.slice(1), baseWithSlash).toString());\n\n\t\t\tconst messages = convertMessages(model, context);\n\t\t\tconst params: RequestBody = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tinput: messages,\n\t\t\t\tstream: true,\n\t\t\t};\n\n\t\t\tif (options?.maxTokens) {\n\t\t\t\tparams.max_output_tokens = options.maxTokens;\n\t\t\t}\n\n\t\t\tif (options?.temperature !== undefined) {\n\t\t\t\tparams.temperature = options.temperature;\n\t\t\t}\n\n\t\t\tif (context.tools) {\n\t\t\t\tparams.tools = convertTools(context.tools);\n\t\t\t}\n\n\t\t\tconst normalizedModel = normalizeModel(params.model);\n\t\t\tconst codexInstructions = await getCodexInstructions(normalizedModel);\n\n\t\t\tconst codexOptions: CodexRequestOptions = {\n\t\t\t\treasoningEffort: options?.reasoningEffort,\n\t\t\t\treasoningSummary: options?.reasoningSummary ?? undefined,\n\t\t\t\ttextVerbosity: options?.textVerbosity,\n\t\t\t\tinclude: options?.include,\n\t\t\t};\n\n\t\t\tconst transformedBody = await transformRequestBody(\n\t\t\t\tparams,\n\t\t\t\tcodexInstructions,\n\t\t\t\tcodexOptions,\n\t\t\t\toptions?.codexMode ?? true,\n\t\t\t\tcontext.systemPrompt,\n\t\t\t);\n\n\t\t\tconst reasoningEffort = transformedBody.reasoning?.effort ?? null;\n\t\t\tconst headers = createCodexHeaders(model.headers, accountId, apiKey, transformedBody.prompt_cache_key);\n\t\t\tlogCodexDebug(\"codex request\", {\n\t\t\t\turl,\n\t\t\t\tmodel: params.model,\n\t\t\t\treasoningEffort,\n\t\t\t\theaders: redactHeaders(headers),\n\t\t\t});\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders,\n\t\t\t\tbody: JSON.stringify(transformedBody),\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tlogCodexDebug(\"codex response\", {\n\t\t\t\turl: response.url,\n\t\t\t\tstatus: response.status,\n\t\t\t\tstatusText: response.statusText,\n\t\t\t\tcontentType: response.headers.get(\"content-type\") || null,\n\t\t\t\tcfRay: response.headers.get(\"cf-ray\") || null,\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst info = await parseCodexError(response);\n\t\t\t\tthrow new Error(info.friendlyMessage || info.message);\n\t\t\t}\n\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(\"No response body\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tlet currentItem: ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall | null = null;\n\t\t\tlet currentBlock: ThinkingContent | TextContent | (ToolCall & { partialJson: string }) | null = null;\n\t\t\tconst blocks = output.content;\n\t\t\tconst blockIndex = () => blocks.length - 1;\n\n\t\t\tfor await (const rawEvent of parseCodexSseStream(response)) {\n\t\t\t\tconst eventType = typeof rawEvent.type === \"string\" ? rawEvent.type : \"\";\n\t\t\t\tif (!eventType) continue;\n\n\t\t\t\tif (eventType === \"response.output_item.added\") {\n\t\t\t\t\tconst item = rawEvent.item as ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall;\n\t\t\t\t\tif (item.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"message\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: {},\n\t\t\t\t\t\t\tpartialJson: item.arguments || \"\",\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.reasoning_summary_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tcurrentItem.summary.push((rawEvent as { part: ResponseReasoningItem[\"summary\"][number] }).part);\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.reasoning_summary_text.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\t\tcurrentBlock.thinking += delta;\n\t\t\t\t\t\t\tlastPart.text += delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.reasoning_summary_part.done\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tcurrentBlock.thinking += \"\\n\\n\";\n\t\t\t\t\t\t\tlastPart.text += \"\\n\\n\";\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: \"\\n\\n\",\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.content_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\") {\n\t\t\t\t\t\tcurrentItem.content = currentItem.content || [];\n\t\t\t\t\t\tconst part = (rawEvent as { part?: ResponseOutputMessage[\"content\"][number] }).part;\n\t\t\t\t\t\tif (part && (part.type === \"output_text\" || part.type === \"refusal\")) {\n\t\t\t\t\t\t\tcurrentItem.content.push(part);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.output_text.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"output_text\") {\n\t\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\t\tcurrentBlock.text += delta;\n\t\t\t\t\t\t\tlastPart.text += delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.refusal.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"refusal\") {\n\t\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\t\tcurrentBlock.text += delta;\n\t\t\t\t\t\t\tlastPart.refusal += delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.function_call_arguments.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"function_call\" && currentBlock?.type === \"toolCall\") {\n\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\tcurrentBlock.partialJson += delta;\n\t\t\t\t\t\tcurrentBlock.arguments = parseStreamingJson(currentBlock.partialJson);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.output_item.done\") {\n\t\t\t\t\tconst item = rawEvent.item as ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall;\n\t\t\t\t\tif (item.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\t\t\tcurrentBlock.thinking = item.summary?.map((s) => s.text).join(\"\\n\\n\") || \"\";\n\t\t\t\t\t\tcurrentBlock.thinkingSignature = JSON.stringify(item);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\t\t\tcurrentBlock.text = item.content.map((c) => (c.type === \"output_text\" ? c.text : c.refusal)).join(\"\");\n\t\t\t\t\t\tcurrentBlock.textSignature = item.id;\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tconst toolCall: ToolCall = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: JSON.parse(item.arguments),\n\t\t\t\t\t\t};\n\t\t\t\t\t\tstream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.completed\" || eventType === \"response.done\") {\n\t\t\t\t\tconst response = (\n\t\t\t\t\t\trawEvent as {\n\t\t\t\t\t\t\tresponse?: {\n\t\t\t\t\t\t\t\tusage?: {\n\t\t\t\t\t\t\t\t\tinput_tokens?: number;\n\t\t\t\t\t\t\t\t\toutput_tokens?: number;\n\t\t\t\t\t\t\t\t\ttotal_tokens?: number;\n\t\t\t\t\t\t\t\t\tinput_tokens_details?: { cached_tokens?: number };\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tstatus?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t).response;\n\t\t\t\t\tif (response?.usage) {\n\t\t\t\t\t\tconst cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;\n\t\t\t\t\t\toutput.usage = {\n\t\t\t\t\t\t\tinput: (response.usage.input_tokens || 0) - cachedTokens,\n\t\t\t\t\t\t\toutput: response.usage.output_tokens || 0,\n\t\t\t\t\t\t\tcacheRead: cachedTokens,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotalTokens: response.usage.total_tokens || 0,\n\t\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t\toutput.stopReason = mapStopReason(response?.status);\n\t\t\t\t\tif (output.content.some((b) => b.type === \"toolCall\") && output.stopReason === \"stop\") {\n\t\t\t\t\t\toutput.stopReason = \"toolUse\";\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"error\") {\n\t\t\t\t\tconst code = (rawEvent as { code?: string }).code || \"\";\n\t\t\t\t\tconst message = (rawEvent as { message?: string }).message || \"Unknown error\";\n\t\t\t\t\tthrow new Error(code ? `Error Code ${code}: ${message}` : message);\n\t\t\t\t} else if (eventType === \"response.failed\") {\n\t\t\t\t\tthrow new Error(\"Unknown error\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as { index?: number }).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createCodexHeaders(\n\tinitHeaders: Record<string, string> | undefined,\n\taccountId: string,\n\taccessToken: string,\n\tpromptCacheKey?: string,\n): Headers {\n\tconst headers = new Headers(initHeaders ?? {});\n\theaders.delete(\"x-api-key\");\n\theaders.set(\"Authorization\", `Bearer ${accessToken}`);\n\theaders.set(OPENAI_HEADERS.ACCOUNT_ID, accountId);\n\theaders.set(OPENAI_HEADERS.BETA, OPENAI_HEADER_VALUES.BETA_RESPONSES);\n\theaders.set(OPENAI_HEADERS.ORIGINATOR, OPENAI_HEADER_VALUES.ORIGINATOR_CODEX);\n\n\tif (promptCacheKey) {\n\t\theaders.set(OPENAI_HEADERS.CONVERSATION_ID, promptCacheKey);\n\t\theaders.set(OPENAI_HEADERS.SESSION_ID, promptCacheKey);\n\t} else {\n\t\theaders.delete(OPENAI_HEADERS.CONVERSATION_ID);\n\t\theaders.delete(OPENAI_HEADERS.SESSION_ID);\n\t}\n\n\theaders.set(\"accept\", \"text/event-stream\");\n\theaders.set(\"content-type\", \"application/json\");\n\treturn headers;\n}\n\nfunction logCodexDebug(message: string, details?: Record<string, unknown>): void {\n\tif (!CODEX_DEBUG) return;\n\tif (details) {\n\t\tconsole.error(`[codex] ${message}`, details);\n\t\treturn;\n\t}\n\tconsole.error(`[codex] ${message}`);\n}\n\nfunction redactHeaders(headers: Headers): Record<string, string> {\n\tconst redacted: Record<string, string> = {};\n\tfor (const [key, value] of headers.entries()) {\n\t\tconst lower = key.toLowerCase();\n\t\tif (lower === \"authorization\") {\n\t\t\tredacted[key] = \"Bearer [redacted]\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlower.includes(\"account\") ||\n\t\t\tlower.includes(\"session\") ||\n\t\t\tlower.includes(\"conversation\") ||\n\t\t\tlower === \"cookie\"\n\t\t) {\n\t\t\tredacted[key] = \"[redacted]\";\n\t\t\tcontinue;\n\t\t}\n\t\tredacted[key] = value;\n\t}\n\treturn redacted;\n}\n\nfunction rewriteUrlForCodex(url: string): string {\n\treturn url.replace(URL_PATHS.RESPONSES, URL_PATHS.CODEX_RESPONSES);\n}\n\ntype JwtPayload = {\n\t[JWT_CLAIM_PATH]?: {\n\t\tchatgpt_account_id?: string;\n\t};\n\t[key: string]: unknown;\n};\n\nfunction decodeJwt(token: string): JwtPayload | null {\n\ttry {\n\t\tconst parts = token.split(\".\");\n\t\tif (parts.length !== 3) return null;\n\t\tconst payload = parts[1] ?? \"\";\n\t\tconst decoded = Buffer.from(payload, \"base64\").toString(\"utf-8\");\n\t\treturn JSON.parse(decoded) as JwtPayload;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getAccountId(accessToken: string): string {\n\tconst payload = decodeJwt(accessToken);\n\tconst auth = payload?.[JWT_CLAIM_PATH];\n\tconst accountId = auth?.chatgpt_account_id;\n\tif (!accountId) {\n\t\tthrow new Error(\"Failed to extract accountId from token\");\n\t}\n\treturn accountId;\n}\n\nfunction shortHash(str: string): string {\n\tlet h1 = 0xdeadbeef;\n\tlet h2 = 0x41c6ce57;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst ch = str.charCodeAt(i);\n\t\th1 = Math.imul(h1 ^ ch, 2654435761);\n\t\th2 = Math.imul(h2 ^ ch, 1597334677);\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\treturn (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);\n}\n\nfunction convertMessages(model: Model<\"openai-codex-responses\">, context: Context): ResponseInput {\n\tconst messages: ResponseInput = [];\n\n\tconst transformedMessages = transformMessages(context.messages, model);\n\n\tlet msgIndex = 0;\n\tfor (const msg of transformedMessages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [{ type: \"input_text\", text: sanitizeSurrogates(msg.content) }],\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst content: ResponseInputContent[] = msg.content.map((item): ResponseInputContent => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t} satisfies ResponseInputText;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\timage_url: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t\t\t} satisfies ResponseInputImage;\n\t\t\t\t});\n\t\t\t\tconst filteredContent = !model.input.includes(\"image\")\n\t\t\t\t\t? content.filter((c) => c.type !== \"input_image\")\n\t\t\t\t\t: content;\n\t\t\t\tif (filteredContent.length === 0) continue;\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredContent,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst output: ResponseInput = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"thinking\" && msg.stopReason !== \"error\") {\n\t\t\t\t\tif (block.thinkingSignature) {\n\t\t\t\t\t\tconst reasoningItem = JSON.parse(block.thinkingSignature) as ResponseReasoningItem;\n\t\t\t\t\t\toutput.push(reasoningItem);\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"text\") {\n\t\t\t\t\tconst textBlock = block as TextContent;\n\t\t\t\t\tlet msgId = textBlock.textSignature;\n\t\t\t\t\tif (!msgId) {\n\t\t\t\t\t\tmsgId = `msg_${msgIndex}`;\n\t\t\t\t\t} else if (msgId.length > 64) {\n\t\t\t\t\t\tmsgId = `msg_${shortHash(msgId)}`;\n\t\t\t\t\t}\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\tcontent: [{ type: \"output_text\", text: sanitizeSurrogates(textBlock.text), annotations: [] }],\n\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\tid: msgId,\n\t\t\t\t\t} satisfies ResponseOutputMessage);\n\t\t\t\t} else if (block.type === \"toolCall\" && msg.stopReason !== \"error\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"function_call\",\n\t\t\t\t\t\tid: toolCall.id.split(\"|\")[1],\n\t\t\t\t\t\tcall_id: toolCall.id.split(\"|\")[0],\n\t\t\t\t\t\tname: toolCall.name,\n\t\t\t\t\t\targuments: JSON.stringify(toolCall.arguments),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (output.length === 0) continue;\n\t\t\tmessages.push(...output);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\tconst textResult = msg.content\n\t\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t\t.map((c) => (c as { text: string }).text)\n\t\t\t\t.join(\"\\n\");\n\t\t\tconst hasImages = msg.content.some((c) => c.type === \"image\");\n\n\t\t\tconst hasText = textResult.length > 0;\n\t\t\tmessages.push({\n\t\t\t\ttype: \"function_call_output\",\n\t\t\t\tcall_id: msg.toolCallId.split(\"|\")[0],\n\t\t\t\toutput: sanitizeSurrogates(hasText ? textResult : \"(see attached image)\"),\n\t\t\t});\n\n\t\t\tif (hasImages && model.input.includes(\"image\")) {\n\t\t\t\tconst contentParts: ResponseInputContent[] = [];\n\t\t\t\tcontentParts.push({\n\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\ttext: \"Attached image(s) from tool result:\",\n\t\t\t\t} satisfies ResponseInputText);\n\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (block.type === \"image\") {\n\t\t\t\t\t\tcontentParts.push({\n\t\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\t\timage_url: `data:${block.mimeType};base64,${block.data}`,\n\t\t\t\t\t\t} satisfies ResponseInputImage);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: contentParts,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tmsgIndex++;\n\t}\n\n\treturn messages;\n}\n\nfunction convertTools(\n\ttools: Tool[],\n): Array<{ type: \"function\"; name: string; description: string; parameters: Record<string, unknown>; strict: null }> {\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\",\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as unknown as Record<string, unknown>,\n\t\tstrict: null,\n\t}));\n}\n\nfunction mapStopReason(status: string | undefined): StopReason {\n\tif (!status) return \"stop\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"stop\";\n\t\tcase \"incomplete\":\n\t\t\treturn \"length\";\n\t\tcase \"failed\":\n\t\tcase \"cancelled\":\n\t\t\treturn \"error\";\n\t\tcase \"in_progress\":\n\t\tcase \"queued\":\n\t\t\treturn \"stop\";\n\t\tdefault:\n\t\t\treturn \"stop\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"openai-codex-responses.d.ts","sourceRoot":"","sources":["../../src/providers/openai-codex-responses.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAMX,cAAc,EACd,aAAa,EAKb,MAAM,aAAa,CAAC;AAuBrB,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IACjE,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC3E,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;IACzE,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAID,eAAO,MAAM,0BAA0B,EAAE,cAAc,CAAC,wBAAwB,CAkU/E,CAAC","sourcesContent":["import type {\n\tResponseFunctionToolCall,\n\tResponseInput,\n\tResponseInputContent,\n\tResponseInputImage,\n\tResponseInputText,\n\tResponseOutputMessage,\n\tResponseReasoningItem,\n} from \"openai/resources/responses/responses.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport {\n\tCODEX_BASE_URL,\n\tJWT_CLAIM_PATH,\n\tOPENAI_HEADER_VALUES,\n\tOPENAI_HEADERS,\n\tURL_PATHS,\n} from \"./openai-codex/constants.js\";\nimport { getCodexInstructions } from \"./openai-codex/prompts/codex.js\";\nimport { buildCodexPiBridge } from \"./openai-codex/prompts/pi-codex-bridge.js\";\nimport { buildCodexSystemPrompt } from \"./openai-codex/prompts/system-prompt.js\";\nimport {\n\ttype CodexRequestOptions,\n\tnormalizeModel,\n\ttype RequestBody,\n\ttransformRequestBody,\n} from \"./openai-codex/request-transformer.js\";\nimport { parseCodexError, parseCodexSseStream } from \"./openai-codex/response-handler.js\";\nimport { transformMessages } from \"./transorm-messages.js\";\n\nexport interface OpenAICodexResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\treasoningSummary?: \"auto\" | \"concise\" | \"detailed\" | \"off\" | \"on\" | null;\n\ttextVerbosity?: \"low\" | \"medium\" | \"high\";\n\tinclude?: string[];\n\tcodexMode?: boolean;\n}\n\nconst CODEX_DEBUG = process.env.PI_CODEX_DEBUG === \"1\" || process.env.PI_CODEX_DEBUG === \"true\";\n\nexport const streamOpenAICodexResponses: StreamFunction<\"openai-codex-responses\"> = (\n\tmodel: Model<\"openai-codex-responses\">,\n\tcontext: Context,\n\toptions?: OpenAICodexResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"openai-codex-responses\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider) || \"\";\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t\t}\n\n\t\t\tconst accountId = getAccountId(apiKey);\n\t\t\tconst baseUrl = model.baseUrl || CODEX_BASE_URL;\n\t\t\tconst baseWithSlash = baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`;\n\t\t\tconst url = rewriteUrlForCodex(new URL(URL_PATHS.RESPONSES.slice(1), baseWithSlash).toString());\n\n\t\t\tconst messages = convertMessages(model, context);\n\t\t\tconst params: RequestBody = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tinput: messages,\n\t\t\t\tstream: true,\n\t\t\t\tprompt_cache_key: options?.sessionId,\n\t\t\t};\n\n\t\t\tif (options?.maxTokens) {\n\t\t\t\tparams.max_output_tokens = options.maxTokens;\n\t\t\t}\n\n\t\t\tif (options?.temperature !== undefined) {\n\t\t\t\tparams.temperature = options.temperature;\n\t\t\t}\n\n\t\t\tif (context.tools) {\n\t\t\t\tparams.tools = convertTools(context.tools);\n\t\t\t}\n\n\t\t\tconst normalizedModel = normalizeModel(params.model);\n\t\t\tconst codexInstructions = await getCodexInstructions(normalizedModel);\n\t\t\tconst bridgeText = buildCodexPiBridge(context.tools);\n\t\t\tconst systemPrompt = buildCodexSystemPrompt({\n\t\t\t\tcodexInstructions,\n\t\t\t\tbridgeText,\n\t\t\t\tuserSystemPrompt: context.systemPrompt,\n\t\t\t});\n\n\t\t\tparams.model = normalizedModel;\n\t\t\tparams.instructions = systemPrompt.instructions;\n\n\t\t\tconst codexOptions: CodexRequestOptions = {\n\t\t\t\treasoningEffort: options?.reasoningEffort,\n\t\t\t\treasoningSummary: options?.reasoningSummary ?? undefined,\n\t\t\t\ttextVerbosity: options?.textVerbosity,\n\t\t\t\tinclude: options?.include,\n\t\t\t};\n\n\t\t\tconst transformedBody = await transformRequestBody(params, codexOptions, systemPrompt);\n\n\t\t\tconst reasoningEffort = transformedBody.reasoning?.effort ?? null;\n\t\t\tconst headers = createCodexHeaders(model.headers, accountId, apiKey, options?.sessionId);\n\t\t\tlogCodexDebug(\"codex request\", {\n\t\t\t\turl,\n\t\t\t\tmodel: params.model,\n\t\t\t\treasoningEffort,\n\t\t\t\theaders: redactHeaders(headers),\n\t\t\t});\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders,\n\t\t\t\tbody: JSON.stringify(transformedBody),\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tlogCodexDebug(\"codex response\", {\n\t\t\t\turl: response.url,\n\t\t\t\tstatus: response.status,\n\t\t\t\tstatusText: response.statusText,\n\t\t\t\tcontentType: response.headers.get(\"content-type\") || null,\n\t\t\t\tcfRay: response.headers.get(\"cf-ray\") || null,\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst info = await parseCodexError(response);\n\t\t\t\tthrow new Error(info.friendlyMessage || info.message);\n\t\t\t}\n\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(\"No response body\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tlet currentItem: ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall | null = null;\n\t\t\tlet currentBlock: ThinkingContent | TextContent | (ToolCall & { partialJson: string }) | null = null;\n\t\t\tconst blocks = output.content;\n\t\t\tconst blockIndex = () => blocks.length - 1;\n\n\t\t\tfor await (const rawEvent of parseCodexSseStream(response)) {\n\t\t\t\tconst eventType = typeof rawEvent.type === \"string\" ? rawEvent.type : \"\";\n\t\t\t\tif (!eventType) continue;\n\n\t\t\t\tif (eventType === \"response.output_item.added\") {\n\t\t\t\t\tconst item = rawEvent.item as ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall;\n\t\t\t\t\tif (item.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"message\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: {},\n\t\t\t\t\t\t\tpartialJson: item.arguments || \"\",\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.reasoning_summary_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tcurrentItem.summary.push((rawEvent as { part: ResponseReasoningItem[\"summary\"][number] }).part);\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.reasoning_summary_text.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\t\tcurrentBlock.thinking += delta;\n\t\t\t\t\t\t\tlastPart.text += delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.reasoning_summary_part.done\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tcurrentBlock.thinking += \"\\n\\n\";\n\t\t\t\t\t\t\tlastPart.text += \"\\n\\n\";\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: \"\\n\\n\",\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.content_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\") {\n\t\t\t\t\t\tcurrentItem.content = currentItem.content || [];\n\t\t\t\t\t\tconst part = (rawEvent as { part?: ResponseOutputMessage[\"content\"][number] }).part;\n\t\t\t\t\t\tif (part && (part.type === \"output_text\" || part.type === \"refusal\")) {\n\t\t\t\t\t\t\tcurrentItem.content.push(part);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.output_text.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"output_text\") {\n\t\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\t\tcurrentBlock.text += delta;\n\t\t\t\t\t\t\tlastPart.text += delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.refusal.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"refusal\") {\n\t\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\t\tcurrentBlock.text += delta;\n\t\t\t\t\t\t\tlastPart.refusal += delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.function_call_arguments.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"function_call\" && currentBlock?.type === \"toolCall\") {\n\t\t\t\t\t\tconst delta = (rawEvent as { delta?: string }).delta || \"\";\n\t\t\t\t\t\tcurrentBlock.partialJson += delta;\n\t\t\t\t\t\tcurrentBlock.arguments = parseStreamingJson(currentBlock.partialJson);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.output_item.done\") {\n\t\t\t\t\tconst item = rawEvent.item as ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall;\n\t\t\t\t\tif (item.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\t\t\tcurrentBlock.thinking = item.summary?.map((s) => s.text).join(\"\\n\\n\") || \"\";\n\t\t\t\t\t\tcurrentBlock.thinkingSignature = JSON.stringify(item);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\t\t\tcurrentBlock.text = item.content.map((c) => (c.type === \"output_text\" ? c.text : c.refusal)).join(\"\");\n\t\t\t\t\t\tcurrentBlock.textSignature = item.id;\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tconst toolCall: ToolCall = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: JSON.parse(item.arguments),\n\t\t\t\t\t\t};\n\t\t\t\t\t\tstream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"response.completed\" || eventType === \"response.done\") {\n\t\t\t\t\tconst response = (\n\t\t\t\t\t\trawEvent as {\n\t\t\t\t\t\t\tresponse?: {\n\t\t\t\t\t\t\t\tusage?: {\n\t\t\t\t\t\t\t\t\tinput_tokens?: number;\n\t\t\t\t\t\t\t\t\toutput_tokens?: number;\n\t\t\t\t\t\t\t\t\ttotal_tokens?: number;\n\t\t\t\t\t\t\t\t\tinput_tokens_details?: { cached_tokens?: number };\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tstatus?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t).response;\n\t\t\t\t\tif (response?.usage) {\n\t\t\t\t\t\tconst cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;\n\t\t\t\t\t\toutput.usage = {\n\t\t\t\t\t\t\tinput: (response.usage.input_tokens || 0) - cachedTokens,\n\t\t\t\t\t\t\toutput: response.usage.output_tokens || 0,\n\t\t\t\t\t\t\tcacheRead: cachedTokens,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotalTokens: response.usage.total_tokens || 0,\n\t\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t\toutput.stopReason = mapStopReason(response?.status);\n\t\t\t\t\tif (output.content.some((b) => b.type === \"toolCall\") && output.stopReason === \"stop\") {\n\t\t\t\t\t\toutput.stopReason = \"toolUse\";\n\t\t\t\t\t}\n\t\t\t\t} else if (eventType === \"error\") {\n\t\t\t\t\tconst code = (rawEvent as { code?: string }).code || \"\";\n\t\t\t\t\tconst message = (rawEvent as { message?: string }).message || \"Unknown error\";\n\t\t\t\t\tthrow new Error(code ? `Error Code ${code}: ${message}` : message);\n\t\t\t\t} else if (eventType === \"response.failed\") {\n\t\t\t\t\tthrow new Error(\"Unknown error\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unknown error occurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as { index?: number }).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createCodexHeaders(\n\tinitHeaders: Record<string, string> | undefined,\n\taccountId: string,\n\taccessToken: string,\n\tpromptCacheKey?: string,\n): Headers {\n\tconst headers = new Headers(initHeaders ?? {});\n\theaders.delete(\"x-api-key\");\n\theaders.set(\"Authorization\", `Bearer ${accessToken}`);\n\theaders.set(OPENAI_HEADERS.ACCOUNT_ID, accountId);\n\theaders.set(OPENAI_HEADERS.BETA, OPENAI_HEADER_VALUES.BETA_RESPONSES);\n\theaders.set(OPENAI_HEADERS.ORIGINATOR, OPENAI_HEADER_VALUES.ORIGINATOR_CODEX);\n\n\tif (promptCacheKey) {\n\t\theaders.set(OPENAI_HEADERS.CONVERSATION_ID, promptCacheKey);\n\t\theaders.set(OPENAI_HEADERS.SESSION_ID, promptCacheKey);\n\t} else {\n\t\theaders.delete(OPENAI_HEADERS.CONVERSATION_ID);\n\t\theaders.delete(OPENAI_HEADERS.SESSION_ID);\n\t}\n\n\theaders.set(\"accept\", \"text/event-stream\");\n\theaders.set(\"content-type\", \"application/json\");\n\treturn headers;\n}\n\nfunction logCodexDebug(message: string, details?: Record<string, unknown>): void {\n\tif (!CODEX_DEBUG) return;\n\tif (details) {\n\t\tconsole.error(`[codex] ${message}`, details);\n\t\treturn;\n\t}\n\tconsole.error(`[codex] ${message}`);\n}\n\nfunction redactHeaders(headers: Headers): Record<string, string> {\n\tconst redacted: Record<string, string> = {};\n\tfor (const [key, value] of headers.entries()) {\n\t\tconst lower = key.toLowerCase();\n\t\tif (lower === \"authorization\") {\n\t\t\tredacted[key] = \"Bearer [redacted]\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlower.includes(\"account\") ||\n\t\t\tlower.includes(\"session\") ||\n\t\t\tlower.includes(\"conversation\") ||\n\t\t\tlower === \"cookie\"\n\t\t) {\n\t\t\tredacted[key] = \"[redacted]\";\n\t\t\tcontinue;\n\t\t}\n\t\tredacted[key] = value;\n\t}\n\treturn redacted;\n}\n\nfunction rewriteUrlForCodex(url: string): string {\n\treturn url.replace(URL_PATHS.RESPONSES, URL_PATHS.CODEX_RESPONSES);\n}\n\ntype JwtPayload = {\n\t[JWT_CLAIM_PATH]?: {\n\t\tchatgpt_account_id?: string;\n\t};\n\t[key: string]: unknown;\n};\n\nfunction decodeJwt(token: string): JwtPayload | null {\n\ttry {\n\t\tconst parts = token.split(\".\");\n\t\tif (parts.length !== 3) return null;\n\t\tconst payload = parts[1] ?? \"\";\n\t\tconst decoded = Buffer.from(payload, \"base64\").toString(\"utf-8\");\n\t\treturn JSON.parse(decoded) as JwtPayload;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getAccountId(accessToken: string): string {\n\tconst payload = decodeJwt(accessToken);\n\tconst auth = payload?.[JWT_CLAIM_PATH];\n\tconst accountId = auth?.chatgpt_account_id;\n\tif (!accountId) {\n\t\tthrow new Error(\"Failed to extract accountId from token\");\n\t}\n\treturn accountId;\n}\n\nfunction shortHash(str: string): string {\n\tlet h1 = 0xdeadbeef;\n\tlet h2 = 0x41c6ce57;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst ch = str.charCodeAt(i);\n\t\th1 = Math.imul(h1 ^ ch, 2654435761);\n\t\th2 = Math.imul(h2 ^ ch, 1597334677);\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\treturn (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);\n}\n\nfunction convertMessages(model: Model<\"openai-codex-responses\">, context: Context): ResponseInput {\n\tconst messages: ResponseInput = [];\n\n\tconst transformedMessages = transformMessages(context.messages, model);\n\n\tlet msgIndex = 0;\n\tfor (const msg of transformedMessages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [{ type: \"input_text\", text: sanitizeSurrogates(msg.content) }],\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst content: ResponseInputContent[] = msg.content.map((item): ResponseInputContent => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t} satisfies ResponseInputText;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\timage_url: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t\t\t} satisfies ResponseInputImage;\n\t\t\t\t});\n\t\t\t\tconst filteredContent = !model.input.includes(\"image\")\n\t\t\t\t\t? content.filter((c) => c.type !== \"input_image\")\n\t\t\t\t\t: content;\n\t\t\t\tif (filteredContent.length === 0) continue;\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredContent,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst output: ResponseInput = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"thinking\" && msg.stopReason !== \"error\") {\n\t\t\t\t\tif (block.thinkingSignature) {\n\t\t\t\t\t\tconst reasoningItem = JSON.parse(block.thinkingSignature) as ResponseReasoningItem;\n\t\t\t\t\t\toutput.push(reasoningItem);\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"text\") {\n\t\t\t\t\tconst textBlock = block as TextContent;\n\t\t\t\t\tlet msgId = textBlock.textSignature;\n\t\t\t\t\tif (!msgId) {\n\t\t\t\t\t\tmsgId = `msg_${msgIndex}`;\n\t\t\t\t\t} else if (msgId.length > 64) {\n\t\t\t\t\t\tmsgId = `msg_${shortHash(msgId)}`;\n\t\t\t\t\t}\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\tcontent: [{ type: \"output_text\", text: sanitizeSurrogates(textBlock.text), annotations: [] }],\n\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\tid: msgId,\n\t\t\t\t\t} satisfies ResponseOutputMessage);\n\t\t\t\t} else if (block.type === \"toolCall\" && msg.stopReason !== \"error\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"function_call\",\n\t\t\t\t\t\tid: toolCall.id.split(\"|\")[1],\n\t\t\t\t\t\tcall_id: toolCall.id.split(\"|\")[0],\n\t\t\t\t\t\tname: toolCall.name,\n\t\t\t\t\t\targuments: JSON.stringify(toolCall.arguments),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (output.length === 0) continue;\n\t\t\tmessages.push(...output);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\tconst textResult = msg.content\n\t\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t\t.map((c) => (c as { text: string }).text)\n\t\t\t\t.join(\"\\n\");\n\t\t\tconst hasImages = msg.content.some((c) => c.type === \"image\");\n\n\t\t\tconst hasText = textResult.length > 0;\n\t\t\tmessages.push({\n\t\t\t\ttype: \"function_call_output\",\n\t\t\t\tcall_id: msg.toolCallId.split(\"|\")[0],\n\t\t\t\toutput: sanitizeSurrogates(hasText ? textResult : \"(see attached image)\"),\n\t\t\t});\n\n\t\t\tif (hasImages && model.input.includes(\"image\")) {\n\t\t\t\tconst contentParts: ResponseInputContent[] = [];\n\t\t\t\tcontentParts.push({\n\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\ttext: \"Attached image(s) from tool result:\",\n\t\t\t\t} satisfies ResponseInputText);\n\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (block.type === \"image\") {\n\t\t\t\t\t\tcontentParts.push({\n\t\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\t\timage_url: `data:${block.mimeType};base64,${block.data}`,\n\t\t\t\t\t\t} satisfies ResponseInputImage);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: contentParts,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tmsgIndex++;\n\t}\n\n\treturn messages;\n}\n\nfunction convertTools(\n\ttools: Tool[],\n): Array<{ type: \"function\"; name: string; description: string; parameters: Record<string, unknown>; strict: null }> {\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\",\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as unknown as Record<string, unknown>,\n\t\tstrict: null,\n\t}));\n}\n\nfunction mapStopReason(status: string | undefined): StopReason {\n\tif (!status) return \"stop\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"stop\";\n\t\tcase \"incomplete\":\n\t\t\treturn \"length\";\n\t\tcase \"failed\":\n\t\tcase \"cancelled\":\n\t\t\treturn \"error\";\n\t\tcase \"in_progress\":\n\t\tcase \"queued\":\n\t\t\treturn \"stop\";\n\t\tdefault:\n\t\t\treturn \"stop\";\n\t}\n}\n"]}
@@ -5,6 +5,8 @@ import { parseStreamingJson } from "../utils/json-parse.js";
5
5
  import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
6
6
  import { CODEX_BASE_URL, JWT_CLAIM_PATH, OPENAI_HEADER_VALUES, OPENAI_HEADERS, URL_PATHS, } from "./openai-codex/constants.js";
7
7
  import { getCodexInstructions } from "./openai-codex/prompts/codex.js";
8
+ import { buildCodexPiBridge } from "./openai-codex/prompts/pi-codex-bridge.js";
9
+ import { buildCodexSystemPrompt } from "./openai-codex/prompts/system-prompt.js";
8
10
  import { normalizeModel, transformRequestBody, } from "./openai-codex/request-transformer.js";
9
11
  import { parseCodexError, parseCodexSseStream } from "./openai-codex/response-handler.js";
10
12
  import { transformMessages } from "./transorm-messages.js";
@@ -43,6 +45,7 @@ export const streamOpenAICodexResponses = (model, context, options) => {
43
45
  model: model.id,
44
46
  input: messages,
45
47
  stream: true,
48
+ prompt_cache_key: options?.sessionId,
46
49
  };
47
50
  if (options?.maxTokens) {
48
51
  params.max_output_tokens = options.maxTokens;
@@ -55,15 +58,23 @@ export const streamOpenAICodexResponses = (model, context, options) => {
55
58
  }
56
59
  const normalizedModel = normalizeModel(params.model);
57
60
  const codexInstructions = await getCodexInstructions(normalizedModel);
61
+ const bridgeText = buildCodexPiBridge(context.tools);
62
+ const systemPrompt = buildCodexSystemPrompt({
63
+ codexInstructions,
64
+ bridgeText,
65
+ userSystemPrompt: context.systemPrompt,
66
+ });
67
+ params.model = normalizedModel;
68
+ params.instructions = systemPrompt.instructions;
58
69
  const codexOptions = {
59
70
  reasoningEffort: options?.reasoningEffort,
60
71
  reasoningSummary: options?.reasoningSummary ?? undefined,
61
72
  textVerbosity: options?.textVerbosity,
62
73
  include: options?.include,
63
74
  };
64
- const transformedBody = await transformRequestBody(params, codexInstructions, codexOptions, options?.codexMode ?? true, context.systemPrompt);
75
+ const transformedBody = await transformRequestBody(params, codexOptions, systemPrompt);
65
76
  const reasoningEffort = transformedBody.reasoning?.effort ?? null;
66
- const headers = createCodexHeaders(model.headers, accountId, apiKey, transformedBody.prompt_cache_key);
77
+ const headers = createCodexHeaders(model.headers, accountId, apiKey, options?.sessionId);
67
78
  logCodexDebug("codex request", {
68
79
  url,
69
80
  model: params.model,