refactor(open-sse): registry consolidation + DRY media/oauth/adhoc cleanup
- Single-source registry: oauth clientId/tokenUrl, usage URLs, image/embed configs, search defaultModel, codex fixedPort, google token url derive. - Remove 29 unused OmniRoute providers (registry 100→71); media intact. - De-adhoc: codex literals → registry format/oauth flags; reasoningInject, image/embed openrouter headers + xai bodyFields config-driven. - Add REGISTRY_TEMPLATE.js + expand PROVIDER_DEFAULTS/schema JSDoc. - Baselines updated; PROVIDERS 62 + alias 90 byte-for-byte, golden snapshots. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -56,8 +56,10 @@ export function claudeToOpenAIRequest(model, body, stream) {
|
||||
}
|
||||
}
|
||||
|
||||
// Fix missing tool responses - OpenAI requires every tool_call to have a response
|
||||
fixMissingToolResponses(result.messages);
|
||||
// Fix missing tool responses - OpenAI requires every tool_call to have a response.
|
||||
// Local variant: scans contiguous tool replies + inserts "[No response received]"
|
||||
// (distinct from the global immediate-next check in toolCallHelper, runs on the openai leg).
|
||||
fixMissingToolResponsesOpenAI(result.messages);
|
||||
|
||||
// Tools
|
||||
if (body.tools && Array.isArray(body.tools)) {
|
||||
@@ -80,7 +82,7 @@ export function claudeToOpenAIRequest(model, body, stream) {
|
||||
}
|
||||
|
||||
// Fix missing tool responses - add empty responses for tool_calls without responses
|
||||
function fixMissingToolResponses(messages) {
|
||||
function fixMissingToolResponsesOpenAI(messages) {
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
const msg = messages[i];
|
||||
if (msg.role === "assistant" && msg.tool_calls && msg.tool_calls.length > 0) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { FORMATS } from "../formats.js";
|
||||
import { CLAUDE_SYSTEM_PROMPT } from "../../config/appConstants.js";
|
||||
import { adjustMaxTokens } from "../helpers/maxTokensHelper.js";
|
||||
import { safeParseJSON } from "../helpers/jsonUtil.js";
|
||||
import { parseDataUri } from "../helpers/imageHelper.js";
|
||||
|
||||
// Empty prefix matches real Claude Code behavior (no tool name prefix).
|
||||
// Previously "proxy_" was used but this is a detectable fingerprint difference.
|
||||
@@ -235,11 +236,11 @@ function getContentBlocksFromMessage(msg, toolNameMap = new Map()) {
|
||||
});
|
||||
} else if (part.type === "image_url") {
|
||||
const url = part.image_url.url;
|
||||
const match = url.match(/^data:([^;]+);base64,(.+)$/);
|
||||
if (match) {
|
||||
const parsed = parseDataUri(url);
|
||||
if (parsed) {
|
||||
blocks.push({
|
||||
type: "image",
|
||||
source: { type: "base64", media_type: match[1], data: match[2] }
|
||||
source: { type: "base64", media_type: parsed.mimeType, data: parsed.base64 }
|
||||
});
|
||||
} else if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
blocks.push({
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
KIRO_AGENTIC_SYSTEM_PROMPT,
|
||||
resolveDefaultProfileArn
|
||||
} from "../../config/kiroConstants.js";
|
||||
import { parseDataUri } from "../helpers/imageHelper.js";
|
||||
|
||||
/** Render a single tool call as a readable text line. */
|
||||
function toolCallToText(name, input) {
|
||||
@@ -289,11 +290,10 @@ function convertMessages(messages, tools, model) {
|
||||
} else if (c.type === "image_url") {
|
||||
// OpenAI format: image_url.url with data URI
|
||||
const url = c.image_url?.url || "";
|
||||
const base64Match = url.match(/^data:([^;]+);base64,(.+)$/);
|
||||
if (base64Match) {
|
||||
const mediaType = base64Match[1];
|
||||
const format = mediaType.split("/")[1] || mediaType;
|
||||
pendingImages.push({ format, source: { bytes: base64Match[2] } });
|
||||
const parsed = parseDataUri(url);
|
||||
if (parsed) {
|
||||
const format = parsed.mimeType.split("/")[1] || parsed.mimeType;
|
||||
pendingImages.push({ format, source: { bytes: parsed.base64 } });
|
||||
} else if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
// Kiro only supports base64 — fallback to URL text
|
||||
textParts.push(`[Image: ${url}]`);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { register } from "../index.js";
|
||||
import { FORMATS } from "../formats.js";
|
||||
import { parseDataUri } from "../helpers/imageHelper.js";
|
||||
|
||||
/**
|
||||
* Convert OpenAI request to Ollama format
|
||||
@@ -179,10 +180,10 @@ function extractImagesFromContent(content) {
|
||||
const url = typeof block.image_url === "string" ? block.image_url : block.image_url?.url;
|
||||
if (typeof url !== "string" || !url) continue;
|
||||
|
||||
const m = url.match(/^data:[^;]+;base64,([\s\S]+)$/);
|
||||
if (!m) continue;
|
||||
const parsed = parseDataUri(url);
|
||||
if (!parsed) continue;
|
||||
|
||||
images.push(m[1]);
|
||||
images.push(parsed.base64);
|
||||
}
|
||||
|
||||
return images;
|
||||
|
||||
Reference in New Issue
Block a user