From 4fd5d08ed852d4fa2de42ba0ae2fa5ba87c0fd3d Mon Sep 17 00:00:00 2001 From: reanon <> Date: Fri, 9 May 2025 15:55:49 +0200 Subject: [PATCH] ui test --- src/proxy/anthropic.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/proxy/anthropic.ts b/src/proxy/anthropic.ts index ba1874a..284f23e 100644 --- a/src/proxy/anthropic.ts +++ b/src/proxy/anthropic.ts @@ -85,10 +85,34 @@ const anthropicBlockingResponseHandler: ProxyResHandlerWithBody = async ( function flattenChatResponse( content: { type: string; text: string }[] ): string { + // We preserve the original behaviour (concatenate all `text` parts), + // but we also embed any web-search citations so the final string still + // makes sense in UIs that do **not** have dedicated citation rendering. return content - .map((part: { type: string; text: string }) => - part.type === "text" ? part.text : "" - ) + .map((part: any) => { + if (part.type !== "text" || !part.text) return ""; + + let segment = part.text; + + // When Claude returns web-search citations they live next to the text + // in a `citations` array. We convert them into a simple markdown list + // so that plain-text renderers (like SillyTavern today) still show + // the sources rather than hiding them completely. + if (Array.isArray(part.citations) && part.citations.length) { + const sources = part.citations + .map((cite: any, idx: number) => { + const title = cite.title || cite.url || `source ${idx + 1}`; + const url = cite.url || ""; + return `- [${title}](${url})`; + }) + .join("\n"); + + segment += `\n\nSources:\n${sources}`; + } + + return segment; + }) + .filter(Boolean) .join("\n"); }