MODEL_CAPS

This commit is contained in:
decolua
2026-04-04 23:24:24 +07:00
parent 5448eedbdd
commit 333e704b2a
7 changed files with 239 additions and 10 deletions

View File

@@ -51,11 +51,38 @@ function ensureInitialized() {
require("./response/ollama-to-openai.js");
}
// Strip multimodal content blocks (image/audio/video) from messages if model doesn't support them
function stripUnsupportedMultimodal(body, multimodal = {}) {
if (!body.messages || !Array.isArray(body.messages)) return;
for (const msg of body.messages) {
if (!Array.isArray(msg.content)) continue;
msg.content = msg.content.filter(part => {
if (part.type === "image_url" || part.type === "image") return multimodal.image === true;
if (part.type === "audio_url" || part.type === "input_audio") return multimodal.audio === true;
return true; // keep text, tool_use, tool_result, etc.
});
// If content array becomes empty after filtering, replace with empty string to avoid API errors
if (msg.content.length === 0) msg.content = "";
}
}
// Translate request: source -> openai -> target
export function translateRequest(sourceFormat, targetFormat, model, body, stream = true, credentials = null, provider = null, reqLogger = null) {
export function translateRequest(sourceFormat, targetFormat, model, body, stream = true, credentials = null, provider = null, reqLogger = null, caps = null) {
ensureInitialized();
let result = body;
// Apply model capability guards before translation
if (caps) {
// Strip multimodal content if model doesn't support it
stripUnsupportedMultimodal(result, caps.multimodal || {});
// Strip thinking config if model doesn't support thinking
if (!caps.thinking) {
delete result.thinking;
delete result.reasoning_effort;
}
}
// Normalize thinking config: remove if lastMessage is not user
normalizeThinkingConfig(result);

View File

@@ -428,11 +428,15 @@ function wrapInCloudCodeEnvelopeForClaude(model, claudeRequest, credentials = nu
return envelope;
}
// Detect if model should use Claude backend in Antigravity
// Claude models have specific ID patterns — more reliable than caps at routing level
function isClaudeModel(model) {
return model.toLowerCase().includes("claude");
}
// OpenAI -> Antigravity (Sandbox Cloud Code with wrapper)
export function openaiToAntigravityRequest(model, body, stream, credentials = null) {
const isClaude = model.toLowerCase().includes("claude");
if (isClaude) {
if (isClaudeModel(model)) {
const claudeRequest = openaiToClaudeRequestForAntigravity(model, body, stream);
return wrapInCloudCodeEnvelopeForClaude(model, claudeRequest, credentials);
}

View File

@@ -20,8 +20,8 @@ function convertMessages(messages, tools, model) {
let pendingImages = [];
let currentRole = null;
// Only Claude models support images in Kiro
const supportsImages = model && model.toLowerCase().includes("claude");
// Image support is pre-filtered by caps in translateRequest before reaching here
const supportsImages = true;
const flushPending = () => {
if (currentRole === "user") {