diff --git a/open-sse/translator/request/openai-responses.ts b/open-sse/translator/request/openai-responses.ts index 357c6e6c..5c9147a2 100644 --- a/open-sse/translator/request/openai-responses.ts +++ b/open-sse/translator/request/openai-responses.ts @@ -10,8 +10,6 @@ import { generateToolCallId } from "../helpers/toolCallHelper.ts"; type JsonRecord = Record; -const UNSUPPORTED_TOOLS = ["file_search", "code_interpreter", "web_search_preview"]; - function toRecord(value: unknown): JsonRecord { return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : {}; } @@ -47,14 +45,16 @@ export function openaiResponsesToOpenAIRequest( const root = toRecord(body); if (root.input === undefined) return body; - // Validate unsupported features - return clear errors instead of silent failure + // Validate tool types — only function tools can be translated to Chat Completions const tools = toArray(root.tools); if (tools.length > 0) { for (const toolValue of tools) { const tool = toRecord(toolValue); - if (UNSUPPORTED_TOOLS.includes(toString(tool.type))) { + const toolType = toString(tool.type); + // Allow: function tools, and tools already in Chat format (have .function property) + if (toolType && toolType !== "function" && !tool.function) { throw unsupportedFeature( - `Unsupported Responses API feature: ${toString(tool.type)} tool type is not supported by omniroute` + `Unsupported Responses API feature: ${toolType} tool type is not supported by omniroute` ); } } diff --git a/tests/unit/responses-translation-fixes.test.mjs b/tests/unit/responses-translation-fixes.test.mjs index 129fc3ce..76df1146 100644 --- a/tests/unit/responses-translation-fixes.test.mjs +++ b/tests/unit/responses-translation-fixes.test.mjs @@ -214,3 +214,50 @@ test("Responses→Chat: built-in tool_choice type throws unsupported error", () (err) => err.message.includes("web_search_preview") ); }); + +test("Responses→Chat: web_search tool type throws unsupported error", () => { + const body = { + model: "gpt-4", + input: "search for cats", + tools: [{ type: "web_search", search_context_size: "medium" }], + }; + assert.throws( + () => openaiResponsesToOpenAIRequest(null, body, null, null), + (err) => err.message.includes("web_search") + ); +}); + +test("Responses→Chat: computer tool type throws unsupported error", () => { + const body = { + model: "gpt-4", + input: "click button", + tools: [{ type: "computer" }], + }; + assert.throws( + () => openaiResponsesToOpenAIRequest(null, body, null, null), + (err) => err.message.includes("computer") + ); +}); + +test("Responses→Chat: mcp tool type throws unsupported error", () => { + const body = { + model: "gpt-4", + input: "hello", + tools: [{ type: "mcp", server_label: "test", server_url: "https://example.com" }], + }; + assert.throws( + () => openaiResponsesToOpenAIRequest(null, body, null, null), + (err) => err.message.includes("mcp") + ); +}); + +test("Responses→Chat: function tool type passes through", () => { + const body = { + model: "gpt-4", + input: "hello", + tools: [{ type: "function", name: "greet", parameters: {} }], + }; + const result = openaiResponsesToOpenAIRequest(null, body, null, null); + assert.equal(result.tools.length, 1); + assert.equal(result.tools[0].type, "function"); +});