Spaces:
Paused
Paused
File size: 4,795 Bytes
ab2754a 2df0167 ab2754a 2df0167 ab2754a 2df0167 ab2754a 2df0167 ab2754a 2df0167 ab2754a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | /**
* 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;
}
}
|