mirror of
https://github.com/decolua/9router.git
synced 2026-05-08 12:01:28 +00:00
feat: AI SDK compatibility - Accept header & JSON markdown stripping
- Respect Accept: application/json header to return non-streaming JSON instead of SSE, fixing AI SDK generateObject/generateText compatibility - Strip markdown code block markers (```json...```) from Claude non-streaming responses to prevent JSON parse errors Cherry-picked and adapted from PR #290 by @rothnic https://github.com/decolua/9router/pull/290 Made-with: Cursor
This commit is contained in:
@@ -39,7 +39,16 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
||||
|
||||
const clientRequestedStreaming = body.stream === true || sourceFormat === FORMATS.ANTIGRAVITY || sourceFormat === FORMATS.GEMINI || sourceFormat === FORMATS.GEMINI_CLI;
|
||||
const providerRequiresStreaming = provider === "openai" || provider === "codex";
|
||||
const stream = providerRequiresStreaming ? true : (body.stream !== false);
|
||||
let stream = providerRequiresStreaming ? true : (body.stream !== false);
|
||||
|
||||
// Check client Accept header preference for non-streaming requests
|
||||
// This fixes AI SDK compatibility where clients send Accept: application/json
|
||||
const acceptHeader = clientRawRequest?.headers?.accept || "";
|
||||
const clientPrefersJson = acceptHeader.includes("application/json");
|
||||
const clientPrefersSSE = acceptHeader.includes("text/event-stream");
|
||||
if (clientPrefersJson && !clientPrefersSSE && body.stream !== true) {
|
||||
stream = false;
|
||||
}
|
||||
|
||||
const reqLogger = await createRequestLogger(sourceFormat, targetFormat, model);
|
||||
if (clientRawRequest) reqLogger.logClientRawRequest(clientRawRequest.endpoint, clientRawRequest.body, clientRawRequest.headers);
|
||||
|
||||
@@ -77,8 +77,11 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
|
||||
const toolCalls = [];
|
||||
|
||||
for (const block of responseBody.content) {
|
||||
if (block.type === "text") textContent += block.text;
|
||||
else if (block.type === "thinking") thinkingContent += block.thinking || "";
|
||||
if (block.type === "text") {
|
||||
// Strip markdown code block markers (e.g. kimi wraps JSON in ```json...```)
|
||||
const text = block.text.replace(/^\s*```\s*json\s*\n?/i, "").replace(/\n?\s*```\s*$/i, "");
|
||||
textContent += text;
|
||||
} else if (block.type === "thinking") thinkingContent += block.thinking || "";
|
||||
else if (block.type === "tool_use") {
|
||||
toolCalls.push({ id: block.id, type: "function", function: { name: block.name, arguments: JSON.stringify(block.input || {}) } });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user