@nanocollective/nanocoder
Version:
A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter
58 lines • 2.55 kB
JavaScript
import { XMLToolCallParser } from '../../tool-calling/xml-parser.js';
import { getLogger } from '../../utils/logging/index.js';
import { normalizeLLMResponse } from '../../utils/response-formatter.js';
/**
* Processes XML tool calls from response content
*/
export async function processXMLToolCalls(response, tools, callbacks) {
const logger = getLogger();
const toolCalls = [];
// NEW: Normalize response before processing
const normalized = await normalizeLLMResponse(response);
const content = normalized.content;
// Only process if tools are available and no native tool calls were found
if (Object.keys(tools).length === 0 || !content) {
return { toolCalls, cleanedContent: content };
}
logger.debug('Checking for XML tool calls in response content');
// Initialize cleanedContent with original content (preserved if no tool calls found)
let cleanedContent = content;
// First check for malformed XML tool calls
const malformedError = XMLToolCallParser.detectMalformedToolCall(content);
if (malformedError) {
logger.warn('Malformed XML tool call detected', {
error: malformedError.error,
});
// Return malformed tool call with validation error
// This mimics how validators work - returns tool call that will show error
const malformedCall = {
id: 'malformed_xml_validation',
function: {
name: '__xml_validation_error__',
arguments: {
error: malformedError.error,
},
},
};
toolCalls.push(malformedCall);
callbacks.onToolCall?.(malformedCall);
cleanedContent = ''; // Clear content since it was malformed
}
else if (XMLToolCallParser.hasToolCalls(content)) {
logger.debug('Parsing XML tool calls from content');
// Try to parse well-formed XML tool calls
const parsedToolCalls = XMLToolCallParser.parseToolCalls(content);
const xmlToolCalls = XMLToolCallParser.convertToToolCalls(parsedToolCalls);
cleanedContent = XMLToolCallParser.removeToolCallsFromContent(content);
logger.debug('XML tool calls parsed', {
toolCallCount: xmlToolCalls.length,
contentLength: cleanedContent.length,
});
for (const tc of xmlToolCalls) {
toolCalls.push(tc);
callbacks.onToolCall?.(tc);
}
}
return { toolCalls, cleanedContent };
}
//# sourceMappingURL=tool-processor.js.map