mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 05:45:04 +03:00
fix: harden Claude WebSearch tool parsing
This commit is contained in:
@@ -39,7 +39,10 @@ function isClaudeServerWebSearchTool(tool: unknown): tool is JsonRecord {
|
||||
|
||||
function toStringArray(value: unknown): string[] {
|
||||
if (!Array.isArray(value)) return [];
|
||||
return value.map((entry) => String(entry || "").trim()).filter(Boolean);
|
||||
return value
|
||||
.filter((entry): entry is string => typeof entry === "string")
|
||||
.map((entry) => entry.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function convertClaudeServerWebSearchTool(tool: JsonRecord): JsonRecord {
|
||||
@@ -132,15 +135,17 @@ export function claudeToOpenAIRequest(model, body, stream) {
|
||||
return convertClaudeServerWebSearchTool(tool);
|
||||
}
|
||||
|
||||
const name = typeof tool.name === "string" ? tool.name.trim() : "";
|
||||
if (!tool || typeof tool !== "object" || Array.isArray(tool)) return null;
|
||||
const record = tool as JsonRecord;
|
||||
const name = typeof record.name === "string" ? record.name.trim() : "";
|
||||
if (!name) return null; // skip tools with empty/invalid name
|
||||
|
||||
return {
|
||||
type: "function",
|
||||
function: {
|
||||
name,
|
||||
description: typeof tool.description === "string" ? tool.description : "", // fix: never null (#276)
|
||||
parameters: normalizeToolSchema(tool.input_schema),
|
||||
description: typeof record.description === "string" ? record.description : "", // fix: never null (#276)
|
||||
parameters: normalizeToolSchema(record.input_schema),
|
||||
},
|
||||
};
|
||||
})
|
||||
|
||||
@@ -63,8 +63,8 @@ test("Claude -> OpenAI maps Claude server WebSearch to native Responses web_sear
|
||||
{
|
||||
type: "web_search_20250305",
|
||||
name: "web_search",
|
||||
allowed_domains: ["docs.anthropic.com", ""],
|
||||
blocked_domains: ["spam.example"],
|
||||
allowed_domains: ["docs.anthropic.com", "", 123, { domain: "bad.example" }],
|
||||
blocked_domains: ["spam.example", false],
|
||||
max_uses: 8,
|
||||
user_location: { type: "approximate", country: "US" },
|
||||
},
|
||||
@@ -87,6 +87,28 @@ test("Claude -> OpenAI maps Claude server WebSearch to native Responses web_sear
|
||||
assert.deepEqual(result.tool_choice, { type: "web_search" });
|
||||
});
|
||||
|
||||
test("Claude -> OpenAI skips invalid tool payloads without crashing", () => {
|
||||
const result = claudeToOpenAIRequest(
|
||||
"gpt-4o",
|
||||
{
|
||||
messages: [{ role: "user", content: "hi" }],
|
||||
tools: [null, "bad", 42, [], { name: "", input_schema: { type: "object" } }, { name: "ok" }],
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
assert.deepEqual(result.tools, [
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "ok",
|
||||
description: "",
|
||||
parameters: { type: "object", properties: {} },
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("Claude -> OpenAI leaves ordinary web_search function tools as functions", () => {
|
||||
const result = claudeToOpenAIRequest(
|
||||
"gpt-4o",
|
||||
|
||||
Reference in New Issue
Block a user