From 99269b7cd66a4ba5ece986a4d425693e25f739cd Mon Sep 17 00:00:00 2001 From: reanon <85157-reanon@users.noreply.gitgud.io> Date: Fri, 9 May 2025 06:27:23 -0800 Subject: [PATCH] Edit anthropic.ts --- src/proxy/anthropic.ts | 190 ++++++++++++++++++++++++++++++++--------- 1 file changed, 148 insertions(+), 42 deletions(-) diff --git a/src/proxy/anthropic.ts b/src/proxy/anthropic.ts index 02741b4..4276ab6 100644 --- a/src/proxy/anthropic.ts +++ b/src/proxy/anthropic.ts @@ -146,14 +146,67 @@ function flattenChatResponse( export function transformAnthropicChatResponseToAnthropicText( anthropicBody: Record ): Record { + // Process content directly for better search result display + let completion = ""; + + // Process each content item to ensure search results are shown + if (Array.isArray(anthropicBody.content)) { + for (const item of anthropicBody.content) { + // Add text content + if (item.type === "text" && item.text) { + completion += item.text + "\n"; + + // Add citations + if (Array.isArray(item.citations) && item.citations.length) { + completion += "\nSources:\n"; + item.citations.forEach((cite: any, idx: number) => { + const title = cite.title || cite.url || `source ${idx + 1}`; + const url = cite.url || ""; + completion += `- [${title}](${url})\n`; + }); + completion += "\n"; + } + } + // Include thinking content + else if (item.type === "thinking" && item.thinking) { + completion += `Thinking: ${item.thinking}\n\n`; + } + // Include search query + else if (item.type === "server_tool_use" && item.name === "web_search" && item.input?.query) { + completion += `Search query: "${item.input.query}"\n\n`; + } + // Process search results + else if ((item.type === "web_search_tool_result" || item.type === "tool_result") && Array.isArray(item.content)) { + const searchResults = item.content.filter((r: any) => + ["web_search_result", "search_result"].includes(String(r?.type)) + ); + + if (searchResults.length) { + completion += "Search results:\n"; + searchResults.forEach((result: any, idx: number) => { + const title = result.title || result.url || `result ${idx + 1}`; + const url = result.url || ""; + completion += `- [${title}](${url})\n`; + }); + completion += "\n"; + } + } + } + } + + // If our processing didn't work, fall back to the original flattener + if (!completion.trim()) { + completion = flattenChatResponse(anthropicBody.content); + } + return { type: "completion", - id: "ant-" + anthropicBody.id, - completion: flattenChatResponse(anthropicBody.content), - stop_reason: anthropicBody.stop_reason, - stop: anthropicBody.stop_sequence, - model: anthropicBody.model, - usage: anthropicBody.usage, + id: "ant-" + (anthropicBody.id || "unknown"), + completion: completion.trim(), + stop_reason: anthropicBody.stop_reason || "stop", + stop: anthropicBody.stop_sequence || null, + model: anthropicBody.model || "unknown", + usage: anthropicBody.usage || {}, }; } @@ -188,59 +241,112 @@ function transformAnthropicTextResponseToOpenAI( export function transformAnthropicChatResponseToOpenAI( anthropicBody: Record ): Record { - // Extract any search results or thinking processes that we can display in the response - let content = flattenChatResponse(anthropicBody.content); + // COMPLETE REWRITE - directly map all content including search results + let finalContent = ""; - // Look for other content types that might not be properly flattened - const hasServerToolUse = anthropicBody.content?.some((part: any) => - part.type === 'server_tool_use' || part.type === 'thinking' - ); + // Check if there's any content to process + if (!Array.isArray(anthropicBody.content) || !anthropicBody.content.length) { + return { + id: "ant-" + (anthropicBody.id || "unknown"), + object: "chat.completion", + created: Date.now(), + model: anthropicBody.model || "unknown", + usage: anthropicBody.usage || {}, + choices: [ + { + message: { + role: "assistant", + content: "I apologize, but I couldn't process your request properly.", + }, + finish_reason: anthropicBody.stop_reason || "stop", + index: 0, + }, + ], + }; + } - // If there's tool use/thinking but no content in the flattened result, - // we may need to manually include them - if (hasServerToolUse && !content.includes('Search results:')) { - // Try to find any search results directly - const toolResults = anthropicBody.content?.filter((part: any) => - part.type === 'web_search_tool_result' && Array.isArray(part.content) - ); - - if (toolResults?.length) { - const searchItems = []; + // Process each content item + for (const item of anthropicBody.content) { + // Add any text parts directly + if (item.type === "text" && item.text) { + finalContent += item.text; - for (const result of toolResults) { - const items = result.content - .filter((r: any) => ["web_search_result", "search_result"].includes(String(r?.type))) - .map((r: any, idx: number) => { - const title = r.title || r.url || `result ${idx + 1}`; - const url = r.url || ""; - return `- [${title}](${url})`; - }); - - if (items.length) { - searchItems.push(...items); - } + // Add citations if present + if (Array.isArray(item.citations) && item.citations.length) { + finalContent += "\n\nSources:"; + item.citations.forEach((cite: any, idx: number) => { + const title = cite.title || cite.url || `source ${idx + 1}`; + const url = cite.url || ""; + finalContent += `\n- [${title}](${url})`; + }); } - if (searchItems.length) { - const searchResultsText = `\n\nSearch results:\n${searchItems.join('\n')}`; - content = content + searchResultsText; + // Add a newline separator between text segments + finalContent += "\n"; + } + // Handle thinking blocks (usually shown as "reasoning") + else if (item.type === "thinking" && item.thinking) { + finalContent += `Thinking: ${item.thinking}\n\n`; + } + // Handle server tool use (web search queries) + else if (item.type === "server_tool_use" && item.name === "web_search" && item.input?.query) { + finalContent += `Search query: "${item.input.query}"\n\n`; + } + // Handle search results + else if (item.type === "web_search_tool_result" && Array.isArray(item.content)) { + finalContent += "Search results:\n"; + + // Extract all search results + const searchResults = item.content.filter((r: any) => + ["web_search_result", "search_result"].includes(String(r?.type)) + ); + + if (searchResults.length) { + searchResults.forEach((result: any, idx: number) => { + const title = result.title || result.url || `result ${idx + 1}`; + const url = result.url || ""; + finalContent += `- [${title}](${url})\n`; + }); + } else { + finalContent += "No relevant search results found.\n"; + } + + finalContent += "\n"; + } + // Also catch tool_result type which might contain search results + else if (item.type === "tool_result" && Array.isArray(item.content)) { + const searchResults = item.content.filter((r: any) => + ["web_search_result", "search_result"].includes(String(r?.type)) + ); + + if (searchResults.length) { + finalContent += "Search results:\n"; + searchResults.forEach((result: any, idx: number) => { + const title = result.title || result.url || `result ${idx + 1}`; + const url = result.url || ""; + finalContent += `- [${title}](${url})\n`; + }); + finalContent += "\n"; } } } + // Clean up any extra newlines and ensure there's some content + finalContent = finalContent.trim() || "I apologize, but I couldn't process your request properly."; + return { - id: "ant-" + anthropicBody.id, + id: "ant-" + (anthropicBody.id || "unknown"), object: "chat.completion", created: Date.now(), - model: anthropicBody.model, - usage: anthropicBody.usage, + model: anthropicBody.model || "unknown", + usage: anthropicBody.usage || {}, choices: [ { message: { role: "assistant", - content: content, + content: finalContent, }, - finish_reason: anthropicBody.stop_reason, + finish_reason: anthropicBody.stop_reason || "stop", index: 0, }, ],