Files
openclaw-ollama-toolcall-proxy/src/proxy/response-rewriter.ts
2026-03-22 13:16:22 +08:00

60 lines
1.9 KiB
TypeScript
Executable File

import { OllamaChatResponse, ToolCall } from '../types/ollama';
import { parseXmlToolCalls } from '../parsers';
import { logger } from '../utils/logger';
/**
* Rewrites the Ollama response to include structured tool calls if missing
* but present in XML tags within the content.
*/
export function rewriteResponse(response: OllamaChatResponse): OllamaChatResponse {
// If the response isn't properly formed or has no message, return as is
if (!response || !response.message) {
return response;
}
// If the response already has tool_calls, do nothing
if (response.message.tool_calls && response.message.tool_calls.length > 0) {
return response;
}
const content = response.message.content;
if (!content) {
return response;
}
// Try to parse XML tool calls from content
const parsedCalls = parseXmlToolCalls(content);
if (parsedCalls.length > 0) {
logger.info(`Rewriting response: found ${parsedCalls.length} tool calls in XML content`);
// Construct standard tool_calls
const standardToolCalls: ToolCall[] = parsedCalls.map((call, index) => {
// Ensure arguments are correctly stringified as expected by standard OpenAI/Ollama APIs
let argumentsString = '{}';
try {
argumentsString = JSON.stringify(call.args);
} catch (e) {
logger.error('Failed to stringify arguments for tool call', call.args);
}
return {
id: `call_${Date.now()}_${index}`,
type: 'function',
function: {
name: call.name,
arguments: argumentsString,
}
};
});
// We can decide to either clear the content or keep it.
// Usually, if we parsed tool calls, we clear the content to avoid confusion
// But retaining it is also fine. Let's clear the XML parts or the whole content to be safe.
response.message.tool_calls = standardToolCalls;
response.message.content = '';
}
return response;
}