@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
69 lines • 2.73 kB
JavaScript
import { XMLToolCallParser } from '../tool-calling/xml-parser.js';
import { ensureString } from '../utils/type-helpers.js';
/**
* Strip tags from content (some models output thinking that shouldn't be shown)
*/
function stripThinkTags(content) {
return (content
// Strip complete blocks
.replace(/<think>[\s\S]*?<\/think>/gi, '')
// Strip orphaned/incomplete think tags
.replace(/<think>[\s\S]*$/gi, '')
.replace(/<\/think>/gi, ''));
}
/**
* Normalize whitespace in content to remove excessive blank lines and spacing
*/
function normalizeWhitespace(content) {
return (content
// Remove trailing whitespace from each line
.replace(/[ \t]+$/gm, '')
// Collapse multiple spaces (but not at start of line for indentation)
.replace(/([^ \t\n]) {2,}/g, '$1 ')
// Remove lines that are only whitespace
.replace(/^[ \t]+$/gm, '')
// Collapse 3+ consecutive newlines to exactly 2 (one blank line)
.replace(/\n{3,}/g, '\n\n')
.trim());
}
/**
* Parses XML tool calls from content (used for non-tool-calling models).
* Only runs on the XML fallback path when native tool calling is disabled.
* Type-preserving: Accepts unknown type, converts to string for processing.
*/
export function parseToolCalls(content) {
// 1. Safety Coercion
const contentStr = ensureString(content);
// Strip tags first - some models (like GLM-4) emit these for chain-of-thought
const strippedContent = stripThinkTags(contentStr);
// 2. Try XML parser for valid tool calls (OPTIMISTIC: Success first!)
if (XMLToolCallParser.hasToolCalls(strippedContent)) {
// Parse valid XML tool calls
const parsedCalls = XMLToolCallParser.parseToolCalls(strippedContent);
const convertedCalls = XMLToolCallParser.convertToToolCalls(parsedCalls);
if (convertedCalls.length > 0) {
const cleanedContent = XMLToolCallParser.removeToolCallsFromContent(strippedContent);
return {
success: true,
toolCalls: convertedCalls,
cleanedContent,
};
}
}
// 3. Check for malformed XML patterns (DEFENSIVE: Error second!)
const xmlMalformed = XMLToolCallParser.detectMalformedToolCall(strippedContent);
if (xmlMalformed) {
return {
success: false,
error: xmlMalformed.error,
examples: xmlMalformed.examples,
};
}
// 4. No tool calls found - normalize whitespace in content
return {
success: true,
toolCalls: [],
cleanedContent: normalizeWhitespace(strippedContent),
};
}
//# sourceMappingURL=tool-parser.js.map