refactor(open-sse): translator DRY + schema enums, bug fixes, dead code cleanup

- Bug B1-B7: media UI m.kind||m.type, serviceKinds, gemini mediaPriority, schema kind, models/info lookup by kind
- Dead code D1-D6: safeParseJSON, drop PROVIDER_ENDPOINTS, orphan fetcher, GITHUB_CONFIG derive, getProviderConfig internal, legacy kiro file
- Translator concerns: toOpenAIUsage, toOpenAIFinish (gemini/kiro/ollama + fix kiro tool finish), thinking effort maps
- Reorg helpers/ → concerns/ (logic) + formats/ (per-format) + schema/ (pure enums: roles/blocks/finishReasons/defaults)
- Wire ~280 hardcoded role/block/finish/default literals to schema enums across 20+ files
- collapseTextParts + extractTextContent dedup
- Normalize translator fn names to openaiToXRequest / xToOpenAIResponse
- Golden tests lock behavior; 0 regression (byte-for-byte providers/alias, 26=26 known fails)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
decolua
2026-06-14 18:49:38 +07:00
parent c5c9061eac
commit d3f61aac2f
145 changed files with 1252 additions and 1160 deletions

View File

@@ -1,6 +1,8 @@
import { register } from "../index.js";
import { FORMATS } from "../formats.js";
import { parseDataUri } from "../helpers/imageHelper.js";
import { parseDataUri } from "../concerns/image.js";
import { safeParseJSON } from "../concerns/json.js";
import { ROLE, OPENAI_BLOCK } from "../schema/index.js";
/**
* Convert OpenAI request to Ollama format
@@ -68,7 +70,7 @@ function normalizeMessages(messages) {
// First pass: build tool_call_id -> tool_name map from assistant messages
for (const msg of messages) {
if (msg.role === "assistant" && msg.tool_calls) {
if (msg.role === ROLE.ASSISTANT && msg.tool_calls) {
for (const tc of msg.tool_calls) {
if (tc.id && tc.function?.name) {
toolCallMap.set(tc.id, tc.function.name);
@@ -80,7 +82,7 @@ function normalizeMessages(messages) {
// Second pass: convert messages
for (const msg of messages) {
// Handle tool result messages (OpenAI format -> Ollama format)
if (msg.role === "tool") {
if (msg.role === ROLE.TOOL) {
const toolResult = normalizeContent(msg.content);
if (!toolResult) continue;
@@ -88,7 +90,7 @@ function normalizeMessages(messages) {
const toolName = toolCallMap.get(msg.tool_call_id) || msg.name || "unknown_tool";
result.push({
role: "tool",
role: ROLE.TOOL,
tool_name: toolName,
content: toolResult
});
@@ -96,23 +98,23 @@ function normalizeMessages(messages) {
}
// Handle assistant messages with tool_calls
if (msg.role === "assistant" && msg.tool_calls) {
if (msg.role === ROLE.ASSISTANT && msg.tool_calls) {
const content = normalizeContent(msg.content) || "";
// Convert OpenAI tool_calls format to Ollama format
const ollamaToolCalls = msg.tool_calls.map(tc => ({
type: "function",
type: OPENAI_BLOCK.FUNCTION,
function: {
index: tc.index || 0,
name: tc.function?.name || "",
arguments: typeof tc.function?.arguments === "string"
? JSON.parse(tc.function.arguments || "{}")
? safeParseJSON(tc.function.arguments || "{}", {})
: tc.function?.arguments || {}
}
}));
result.push({
role: "assistant",
role: ROLE.ASSISTANT,
content: content,
tool_calls: ollamaToolCalls
});
@@ -125,7 +127,7 @@ function normalizeMessages(messages) {
const images = extractImagesFromContent(msg.content);
// Skip empty messages (except assistant)
if (!content && role !== "assistant") continue;
if (!content && role !== ROLE.ASSISTANT) continue;
const out = {
role: role,
@@ -154,7 +156,7 @@ function normalizeContent(content) {
if (Array.isArray(content)) {
// Extract text from content array
const textParts = content
.filter(block => block && block.type === "text" && block.text)
.filter(block => block && block.type === OPENAI_BLOCK.TEXT && block.text)
.map(block => block.text);
return textParts.join("\n") || "";
@@ -175,7 +177,7 @@ function extractImagesFromContent(content) {
const images = [];
for (const block of content) {
if (!block || block.type !== "image_url") continue;
if (!block || block.type !== OPENAI_BLOCK.IMAGE_URL) continue;
const url = typeof block.image_url === "string" ? block.image_url : block.image_url?.url;
if (typeof url !== "string" || !url) continue;