Spaces:
Paused
Paused
| /** | |
| * Shared tool format conversion utilities. | |
| * | |
| * Converts tool definitions and tool_choice from each protocol | |
| * (OpenAI, Anthropic, Gemini) into the Codex Responses API format. | |
| */ | |
| import type { ChatCompletionRequest } from "../types/openai.js"; | |
| import type { AnthropicMessagesRequest } from "../types/anthropic.js"; | |
| import type { GeminiGenerateContentRequest } from "../types/gemini.js"; | |
| // ββ Helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| /** OpenAI requires `properties` when schema `type` is `"object"`. */ | |
| function normalizeSchema( | |
| schema: Record<string, unknown>, | |
| ): Record<string, unknown> { | |
| if (schema.type === "object" && !("properties" in schema)) { | |
| return { ...schema, properties: {} }; | |
| } | |
| return schema; | |
| } | |
| // ββ Codex Responses API tool format βββββββββββββββββββββββββββββ | |
| export interface CodexToolDefinition { | |
| type: "function"; | |
| name: string; | |
| description?: string; | |
| parameters?: Record<string, unknown>; | |
| strict?: boolean; | |
| } | |
| // ββ OpenAI β Codex ββββββββββββββββββββββββββββββββββββββββββββββ | |
| export function openAIToolsToCodex( | |
| tools: NonNullable<ChatCompletionRequest["tools"]>, | |
| ): CodexToolDefinition[] { | |
| return tools.map((t) => { | |
| const def: CodexToolDefinition = { | |
| type: "function", | |
| name: t.function.name, | |
| }; | |
| if (t.function.description) def.description = t.function.description; | |
| if (t.function.parameters) def.parameters = normalizeSchema(t.function.parameters); | |
| return def; | |
| }); | |
| } | |
| export function openAIToolChoiceToCodex( | |
| choice: ChatCompletionRequest["tool_choice"], | |
| ): string | { type: "function"; name: string } | undefined { | |
| if (!choice) return undefined; | |
| if (typeof choice === "string") { | |
| // "none" | "auto" | "required" β pass through | |
| return choice; | |
| } | |
| // { type: "function", function: { name } } β { type: "function", name } | |
| return { type: "function", name: choice.function.name }; | |
| } | |
| /** | |
| * Convert legacy OpenAI `functions` array to Codex tool definitions. | |
| */ | |
| export function openAIFunctionsToCodex( | |
| functions: NonNullable<ChatCompletionRequest["functions"]>, | |
| ): CodexToolDefinition[] { | |
| return functions.map((f) => { | |
| const def: CodexToolDefinition = { | |
| type: "function", | |
| name: f.name, | |
| }; | |
| if (f.description) def.description = f.description; | |
| if (f.parameters) def.parameters = normalizeSchema(f.parameters); | |
| return def; | |
| }); | |
| } | |
| // ββ Anthropic β Codex βββββββββββββββββββββββββββββββββββββββββββ | |
| export function anthropicToolsToCodex( | |
| tools: NonNullable<AnthropicMessagesRequest["tools"]>, | |
| ): CodexToolDefinition[] { | |
| return tools.map((t) => { | |
| const def: CodexToolDefinition = { | |
| type: "function", | |
| name: t.name, | |
| }; | |
| if (t.description) def.description = t.description; | |
| if (t.input_schema) def.parameters = normalizeSchema(t.input_schema); | |
| return def; | |
| }); | |
| } | |
| export function anthropicToolChoiceToCodex( | |
| choice: AnthropicMessagesRequest["tool_choice"], | |
| ): string | { type: "function"; name: string } | undefined { | |
| if (!choice) return undefined; | |
| switch (choice.type) { | |
| case "auto": | |
| return "auto"; | |
| case "any": | |
| return "required"; | |
| case "tool": | |
| return { type: "function", name: choice.name }; | |
| default: | |
| return undefined; | |
| } | |
| } | |
| // ββ Gemini β Codex ββββββββββββββββββββββββββββββββββββββββββββββ | |
| export function geminiToolsToCodex( | |
| tools: NonNullable<GeminiGenerateContentRequest["tools"]>, | |
| ): CodexToolDefinition[] { | |
| const defs: CodexToolDefinition[] = []; | |
| for (const toolGroup of tools) { | |
| if (toolGroup.functionDeclarations) { | |
| for (const fd of toolGroup.functionDeclarations) { | |
| const def: CodexToolDefinition = { | |
| type: "function", | |
| name: fd.name, | |
| }; | |
| if (fd.description) def.description = fd.description; | |
| if (fd.parameters) def.parameters = normalizeSchema(fd.parameters); | |
| defs.push(def); | |
| } | |
| } | |
| } | |
| return defs; | |
| } | |
| export function geminiToolConfigToCodex( | |
| config: GeminiGenerateContentRequest["toolConfig"], | |
| ): string | undefined { | |
| if (!config?.functionCallingConfig?.mode) return undefined; | |
| switch (config.functionCallingConfig.mode) { | |
| case "AUTO": | |
| return "auto"; | |
| case "NONE": | |
| return "none"; | |
| case "ANY": | |
| return "required"; | |
| default: | |
| return undefined; | |
| } | |
| } | |