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:
decolua
2026-06-14 13:15:48 +07:00
parent 9105dd0e25
commit bb9e9aa91f
166 changed files with 3089 additions and 3067 deletions

View File

@@ -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) {

View File

@@ -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({

View File

@@ -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}]`);

View File

@@ -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;