UNPKG

@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
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