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:
@@ -1,7 +1,10 @@
|
||||
import { register } from "../index.js";
|
||||
import { FORMATS } from "../formats.js";
|
||||
import { adjustMaxTokens } from "../helpers/maxTokensHelper.js";
|
||||
import { encodeDataUri } from "../helpers/imageHelper.js";
|
||||
import { adjustMaxTokens } from "../formats/maxTokens.js";
|
||||
import { encodeDataUri } from "../concerns/image.js";
|
||||
import { ROLE, GEMINI_ROLE, OPENAI_BLOCK } from "../schema/index.js";
|
||||
import { budgetToEffort } from "../concerns/thinking.js";
|
||||
import { collapseTextParts } from "../concerns/message.js";
|
||||
|
||||
// Convert Antigravity request to OpenAI format
|
||||
// Antigravity body: { project, model, userAgent, requestType, requestId, request: { contents, systemInstruction, tools, toolConfig, generationConfig, sessionId } }
|
||||
@@ -32,16 +35,8 @@ export function antigravityToOpenAIRequest(model, body, stream) {
|
||||
|
||||
// Thinking config → reasoning_effort
|
||||
if (config.thinkingConfig) {
|
||||
const budget = config.thinkingConfig.thinkingBudget || 0;
|
||||
if (budget > 0) {
|
||||
if (budget <= 2048) {
|
||||
result.reasoning_effort = "low";
|
||||
} else if (budget <= 16384) {
|
||||
result.reasoning_effort = "medium";
|
||||
} else {
|
||||
result.reasoning_effort = "high";
|
||||
}
|
||||
}
|
||||
const effort = budgetToEffort(config.thinkingConfig.thinkingBudget || 0);
|
||||
if (effort) result.reasoning_effort = effort;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +44,7 @@ export function antigravityToOpenAIRequest(model, body, stream) {
|
||||
if (req.systemInstruction) {
|
||||
const systemText = extractText(req.systemInstruction);
|
||||
if (systemText) {
|
||||
result.messages.push({ role: "system", content: systemText });
|
||||
result.messages.push({ role: ROLE.SYSTEM, content: systemText });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +69,7 @@ export function antigravityToOpenAIRequest(model, body, stream) {
|
||||
if (tool.functionDeclarations) {
|
||||
for (const func of tool.functionDeclarations) {
|
||||
result.tools.push({
|
||||
type: "function",
|
||||
type: OPENAI_BLOCK.FUNCTION,
|
||||
function: {
|
||||
name: func.name,
|
||||
description: func.description || "",
|
||||
@@ -123,7 +118,7 @@ function normalizeSchemaTypes(schema) {
|
||||
// Convert Antigravity content to OpenAI message
|
||||
// Handles: text, thought, thoughtSignature, functionCall, functionResponse, inlineData
|
||||
function convertContent(content) {
|
||||
const role = content.role === "model" ? "assistant" : content.role === "user" ? "user" : content.role;
|
||||
const role = content.role === GEMINI_ROLE.MODEL ? ROLE.ASSISTANT : content.role === GEMINI_ROLE.USER ? ROLE.USER : content.role;
|
||||
|
||||
if (!content.parts || !Array.isArray(content.parts)) {
|
||||
return null;
|
||||
@@ -143,19 +138,19 @@ function convertContent(content) {
|
||||
|
||||
// Text with thoughtSignature = regular text after thinking
|
||||
if (part.thoughtSignature && part.text !== undefined) {
|
||||
textParts.push({ type: "text", text: part.text });
|
||||
textParts.push({ type: OPENAI_BLOCK.TEXT, text: part.text });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Regular text
|
||||
if (part.text !== undefined) {
|
||||
textParts.push({ type: "text", text: part.text });
|
||||
textParts.push({ type: OPENAI_BLOCK.TEXT, text: part.text });
|
||||
}
|
||||
|
||||
// Inline data (images)
|
||||
if (part.inlineData) {
|
||||
textParts.push({
|
||||
type: "image_url",
|
||||
type: OPENAI_BLOCK.IMAGE_URL,
|
||||
image_url: {
|
||||
url: encodeDataUri(part.inlineData.mimeType, part.inlineData.data)
|
||||
}
|
||||
@@ -166,7 +161,7 @@ function convertContent(content) {
|
||||
if (part.functionCall) {
|
||||
toolCalls.push({
|
||||
id: part.functionCall.id || `call_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
||||
type: "function",
|
||||
type: OPENAI_BLOCK.FUNCTION,
|
||||
function: {
|
||||
name: part.functionCall.name,
|
||||
arguments: JSON.stringify(part.functionCall.args || {})
|
||||
@@ -177,7 +172,7 @@ function convertContent(content) {
|
||||
// Function response → collect all, each becomes a separate tool message
|
||||
if (part.functionResponse) {
|
||||
toolResults.push({
|
||||
role: "tool",
|
||||
role: ROLE.TOOL,
|
||||
tool_call_id: part.functionResponse.id || part.functionResponse.name,
|
||||
content: JSON.stringify(part.functionResponse.response?.result || part.functionResponse.response || {})
|
||||
});
|
||||
@@ -191,9 +186,9 @@ function convertContent(content) {
|
||||
|
||||
// Assistant with tool calls
|
||||
if (toolCalls.length > 0) {
|
||||
const msg = { role: "assistant" };
|
||||
const msg = { role: ROLE.ASSISTANT };
|
||||
if (textParts.length > 0) {
|
||||
msg.content = textParts.length === 1 && textParts[0].type === "text" ? textParts[0].text : textParts;
|
||||
msg.content = collapseTextParts(textParts);
|
||||
}
|
||||
if (reasoningContent) {
|
||||
msg.reasoning_content = reasoningContent;
|
||||
@@ -206,7 +201,7 @@ function convertContent(content) {
|
||||
if (textParts.length > 0 || reasoningContent) {
|
||||
const msg = { role };
|
||||
if (textParts.length > 0) {
|
||||
msg.content = textParts.length === 1 && textParts[0].type === "text" ? textParts[0].text : textParts;
|
||||
msg.content = collapseTextParts(textParts);
|
||||
}
|
||||
if (reasoningContent) {
|
||||
msg.reasoning_content = reasoningContent;
|
||||
|
||||
Reference in New Issue
Block a user