fix(translator): preserve Responses Lite tools across Chat providers
Codex Responses Lite clients routed to a chat-native OpenAI-compatible provider lost tool use in three places: non-streaming Chat responses leaked the raw chat.completion envelope instead of Responses output items, internal reasoning continuity fields leaked into the outbound Chat body causing some upstreams to reject the request, and the Responses to Chat request translator ignored additional_tools, custom_tool_call, and custom_tool_call_output items entirely. Also fixes apiType (chat vs responses) for openai-compatible nodes being resolved from the immutable provider ID instead of the stored node config, so editing a node's API Type had no runtime effect.
This commit is contained in:
@@ -19,9 +19,15 @@ function isAnthropicCompatible(provider) {
|
||||
return typeof provider === "string" && provider.startsWith(ANTHROPIC_COMPATIBLE_PREFIX);
|
||||
}
|
||||
|
||||
function getOpenAICompatibleType(provider) {
|
||||
if (!isOpenAICompatible(provider)) return "chat";
|
||||
return provider.includes("responses") ? "responses" : "chat";
|
||||
// Resolve the API type (chat vs responses) for an openai-compatible node.
|
||||
// The stored apiType on the connection's providerSpecificData (kept in sync with
|
||||
// the node on create/update) is authoritative. Falls back to the node ID
|
||||
// substring for legacy nodes created before apiType was persisted — their IDs
|
||||
// embed the type: openai-compatible-<chat|responses>-<uuid>.
|
||||
export function resolveOpenAICompatibleApiType(provider, credentials = null) {
|
||||
const stored = credentials?.providerSpecificData?.apiType;
|
||||
if (stored === "chat" || stored === "responses") return stored;
|
||||
return typeof provider === "string" && provider.includes("responses") ? "responses" : "chat";
|
||||
}
|
||||
|
||||
// Detect request format from body structure
|
||||
@@ -105,9 +111,9 @@ export function detectFormat(body) {
|
||||
}
|
||||
|
||||
// Get provider config (internal — no external runtime consumer)
|
||||
function getProviderConfig(provider) {
|
||||
function getProviderConfig(provider, credentials = null) {
|
||||
if (isOpenAICompatible(provider)) {
|
||||
const apiType = getOpenAICompatibleType(provider);
|
||||
const apiType = resolveOpenAICompatibleApiType(provider, credentials);
|
||||
return {
|
||||
...PROVIDERS.openai,
|
||||
format: apiType === "responses" ? "openai-responses" : "openai",
|
||||
@@ -125,14 +131,14 @@ function getProviderConfig(provider) {
|
||||
}
|
||||
|
||||
// Get target format for provider
|
||||
export function getTargetFormat(provider) {
|
||||
export function getTargetFormat(provider, credentials = null) {
|
||||
if (isOpenAICompatible(provider)) {
|
||||
return getOpenAICompatibleType(provider) === "responses" ? "openai-responses" : "openai";
|
||||
return resolveOpenAICompatibleApiType(provider, credentials) === "responses" ? "openai-responses" : "openai";
|
||||
}
|
||||
if (isAnthropicCompatible(provider)) {
|
||||
return "claude";
|
||||
}
|
||||
const config = getProviderConfig(provider);
|
||||
const config = getProviderConfig(provider, credentials);
|
||||
return config.format || "openai";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user