merge: resolve conflicts with origin/master - keep both local and remote features
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import { detectFormat, getTargetFormat } from "../services/provider.js";
|
||||
import { detectFormat, getTargetFormat, resolveTransport } from "../services/provider.js";
|
||||
import { translateRequest } from "../translator/index.js";
|
||||
import { FORMATS } from "../translator/formats.js";
|
||||
import { normalizeClaudePassthrough } from "../translator/helpers/claudeHelper.js";
|
||||
import { normalizeClaudePassthrough } from "../translator/formats/claude.js";
|
||||
import { COLORS } from "../utils/stream.js";
|
||||
import { createStreamController } from "../utils/streamHandler.js";
|
||||
import { refreshWithRetry } from "../services/tokenRefresh.js";
|
||||
import { createRequestLogger } from "../utils/requestLogger.js";
|
||||
import { getModelTargetFormat, getModelStrip, getModelUpstreamId, getModelType, PROVIDER_ID_TO_ALIAS } from "../config/providerModels.js";
|
||||
import { PROVIDERS } from "../config/providers.js";
|
||||
import { createErrorResult, parseUpstreamError, formatProviderError } from "../utils/error.js";
|
||||
import { HTTP_STATUS } from "../config/runtimeConfig.js";
|
||||
import { handleBypassRequest } from "../utils/bypassHandler.js";
|
||||
@@ -19,7 +20,12 @@ import { handleStreamingResponse, buildOnStreamComplete } from "./chatCore/strea
|
||||
import { detectClientTool, isNativePassthrough } from "../utils/clientDetector.js";
|
||||
import { dedupeTools } from "../utils/toolDeduper.js";
|
||||
import { injectCaveman } from "../rtk/caveman.js";
|
||||
import { injectPonytail } from "../rtk/ponytail.js";
|
||||
import { compressMessages, formatRtkLog } from "../rtk/index.js";
|
||||
import { compressWithHeadroom, formatHeadroomLog } from "../rtk/headroom.js";
|
||||
import { getCapabilitiesForModel } from "../providers/capabilities.js";
|
||||
import { stripUnsupportedModalities } from "../translator/concerns/modality.js";
|
||||
import { prefetchRemoteImages } from "../translator/concerns/prefetch.js";
|
||||
|
||||
/**
|
||||
* Core chat handler - shared between SSE and Worker
|
||||
@@ -28,7 +34,7 @@ import { compressMessages, formatRtkLog } from "../rtk/index.js";
|
||||
* @param {object} options.credentials - Provider credentials
|
||||
* @param {string} options.sourceFormatOverride - Override detected source format (e.g. "openai-responses")
|
||||
*/
|
||||
export async function handleChatCore({ body, modelInfo, credentials, log, onCredentialsRefreshed, onRequestSuccess, onDisconnect, onMidStreamError, clientRawRequest, connectionId, userAgent, apiKey, ccFilterNaming, rtkEnabled, cavemanEnabled, cavemanLevel, sourceFormatOverride, providerThinking }) {
|
||||
export async function handleChatCore({ body, modelInfo, credentials, log, onCredentialsRefreshed, onRequestSuccess, onDisconnect, onMidStreamError, clientRawRequest, connectionId, userAgent, apiKey, ccFilterNaming, rtkEnabled, headroomEnabled, headroomUrl, headroomCompressUserMessages, cavemanEnabled, cavemanLevel, ponytailEnabled, ponytailLevel, sourceFormatOverride, providerThinking }) {
|
||||
const { provider, model } = modelInfo;
|
||||
const requestStartTime = Date.now();
|
||||
|
||||
@@ -40,7 +46,10 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
||||
|
||||
const alias = PROVIDER_ID_TO_ALIAS[provider] || provider;
|
||||
const modelTargetFormat = getModelTargetFormat(alias, model);
|
||||
const targetFormat = modelTargetFormat || getTargetFormat(provider);
|
||||
// Multi-endpoint providers: pick transport matching sourceFormat → zero translation
|
||||
const runtimeTransport = resolveTransport(provider, sourceFormat);
|
||||
const targetFormat = modelTargetFormat || runtimeTransport?.format || getTargetFormat(provider);
|
||||
if (runtimeTransport && credentials) credentials.runtimeTransport = runtimeTransport;
|
||||
const stripList = getModelStrip(alias, model);
|
||||
const upstreamModel = getModelUpstreamId(alias, model);
|
||||
|
||||
@@ -59,9 +68,16 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
||||
}
|
||||
|
||||
const clientRequestedStreaming = body.stream === true || sourceFormat === FORMATS.ANTIGRAVITY || sourceFormat === FORMATS.GEMINI || sourceFormat === FORMATS.GEMINI_CLI;
|
||||
const providerRequiresStreaming = provider === "openai" || provider === "codex" || provider === "commandcode";
|
||||
const providerRequiresStreaming = PROVIDERS[provider]?.forceStream === true;
|
||||
let stream = providerRequiresStreaming ? true : (body.stream !== false);
|
||||
|
||||
// Image generation models require non-streaming (Google v1internal:generateContent)
|
||||
const modelType = getModelType(alias, model);
|
||||
const isImageGenModel = modelType === "imageGen" || /image|imagen|image-generation/i.test(model);
|
||||
if (isImageGenModel && (provider === "antigravity" || provider === "gemini-cli")) {
|
||||
stream = false;
|
||||
}
|
||||
|
||||
// DeepSeek-TUI: interactive TUI panel sends stream:true and needs SSE.
|
||||
// Non-interactive mode (-p flag) sends without stream and can't parse SSE.
|
||||
// Only force non-streaming when client didn't explicitly request it.
|
||||
@@ -87,6 +103,22 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
||||
const clientTool = detectClientTool(clientRawRequest?.headers || {}, body);
|
||||
const passthrough = isNativePassthrough(clientTool, provider);
|
||||
|
||||
// Expose raw client headers to translators/executors for session-id resolution
|
||||
if (credentials) credentials.rawHeaders = clientRawRequest?.headers || {};
|
||||
|
||||
// Auto-strip media blocks the model can't read (vision/audio/pdf) before translation.
|
||||
if (!passthrough) {
|
||||
const caps = getCapabilitiesForModel(provider, model);
|
||||
if (stripUnsupportedModalities(body, sourceFormat, caps)) {
|
||||
log?.debug?.("MODALITY", `stripped unsupported media for ${provider}/${model}`);
|
||||
}
|
||||
// Convert remote image URLs to base64 for targets that can't fetch URLs.
|
||||
try {
|
||||
const n = await prefetchRemoteImages(body, sourceFormat, targetFormat, { signal: undefined });
|
||||
if (n > 0) log?.debug?.("MODALITY", `prefetched ${n} remote image(s) for ${targetFormat}`);
|
||||
} catch (e) { log?.warn?.("MODALITY", `image prefetch failed: ${e.message}`); }
|
||||
}
|
||||
|
||||
let translatedBody;
|
||||
let toolNameMap;
|
||||
if (passthrough) {
|
||||
@@ -129,12 +161,23 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
|
||||
const rtkLine = formatRtkLog(rtkStats);
|
||||
if (rtkLine) console.log(rtkLine);
|
||||
|
||||
// Headroom: optional external proxy compression; fail open if proxy is absent.
|
||||
const headroomStats = await compressWithHeadroom(translatedBody, { enabled: headroomEnabled, url: headroomUrl, model: upstreamModel, format: finalFormat, compressUserMessages: headroomCompressUserMessages });
|
||||
const headroomLine = formatHeadroomLog(headroomStats);
|
||||
if (headroomLine) log?.info?.("HEADROOM", headroomLine);
|
||||
|
||||
// Caveman: inject terse-style system prompt
|
||||
if (cavemanEnabled && cavemanLevel) {
|
||||
injectCaveman(translatedBody, finalFormat, cavemanLevel);
|
||||
log?.debug?.("CAVEMAN", `${cavemanLevel} | ${finalFormat}`);
|
||||
}
|
||||
|
||||
// Ponytail: inject lazy-senior-dev system prompt
|
||||
if (ponytailEnabled && ponytailLevel) {
|
||||
injectPonytail(translatedBody, finalFormat, ponytailLevel);
|
||||
log?.debug?.("PONYTAIL", `${ponytailLevel} | ${finalFormat}`);
|
||||
}
|
||||
|
||||
const executor = getExecutor(provider);
|
||||
trackPendingRequest(model, provider, connectionId, true);
|
||||
appendRequestLog({ model, provider, connectionId, status: "PENDING" }).catch(() => { });
|
||||
|
||||
Reference in New Issue
Block a user