@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
108 lines • 4.17 kB
TypeScript
/**
* TYPE PRESERVATION STRATEGY EXPLAINED
* =====================================
*
* "Preserving types" does NOT mean keeping everything as objects/arrays in memory.
* It means:
*
* 1. When receiving LLM responses (which can be ANY type):
* - We accept unknown types (string, object, array, null, undefined)
* - We convert to string ONLY for PARSING OPERATIONS
* - We preserve the original type in the tool call structure
*
* 2. When storing ToolCall.arguments:
* - MUST preserve as Record<string, unknown> (object type)
* - NOT convert to string
* - Enables direct property access without JSON.parse
*
* 3. When displaying/writing to disk:
* - Convert to string for display/storage operations
* - Use JSON.stringify for objects/arrays
* - Use String() for primitives
*
* The confusion comes from mixing up:
* - "Preserve types in memory" (CRITICAL: ToolCall.arguments stays as object)
* - "Convert to string for processing" (NECESSARY: Parser expects strings)
*
* This formatter handles the INCOMING data, then the parser handles the
* conversion to ToolCall format with type preservation.
*/
import type { ToolCall } from '../types/index.js';
/**
* Result of normalizing an LLM response
* Contains the raw response, processed content, extracted tool calls, and metadata
*/
export interface NormalizedResponse {
/** The original response from the LLM (unknown type for maximum flexibility) */
raw: unknown;
/** The content after normalization (always a string for parsing) */
content: string;
/** Any tool calls extracted during normalization */
toolCalls: ToolCall[];
/** Metadata about the response for debugging and strategy selection */
metadata: ResponseMetadata;
}
/**
* Metadata about the normalized response
* Used for:
* - Debugging and logging
* - Selecting the best parsing strategy
* - Error handling and recovery
*/
export interface ResponseMetadata {
/** Whether response contained markdown code blocks */
hasCodeBlocks: boolean;
/** Whether response contained XML tags */
hasXMLTags: boolean;
/** Whether response contained JSON tool call structures */
hasJSONBlocks: boolean;
/** Confidence level in the response type classification */
confidence: 'high' | 'medium' | 'low';
/** Detected response format */
detectedFormat: 'plain' | 'json' | 'xml' | 'mixed' | 'unknown';
/** Whether response appears to be malformed */
isMalformed: boolean;
/** Detected error if malformed */
malformedError?: string;
}
/**
* Main entry point for normalizing LLM responses
*
* This function handles all possible LLM response types:
* - Plain strings (most common)
* - JSON objects (with/without tool_calls field)
* - Arrays (line-based content)
* - Null/undefined (error responses)
* - Mixed content (text + tool calls embedded)
*
* @param response - The raw response from the LLM (can be any type)
* @param options - Configuration options
* @returns A normalized response with content and extracted tool calls
*/
export declare function normalizeLLMResponse(response: unknown, options?: NormalizeOptions): Promise<NormalizedResponse>;
/**
* Formats a normalized response for debugging
*
* @param response - Normalized response to format
* @returns Formatted string for debugging
*/
export declare function formatNormalizedResponse(response: NormalizedResponse): string;
/**
* Checks if a response is complete and ready for processing
*
* A response is complete if:
* 1. It has content
* 2. It has low confidence (means no tool calls were found, so no further processing needed)
* 3. It's not malformed
*
* @param response - Normalized response to check
* @returns True if response is complete
*/
export declare function isResponseComplete(response: NormalizedResponse): boolean;
export interface NormalizeOptions {
/** If true, keeps the raw object structure instead of JSON.stringify */
preserveRawTypes?: boolean;
/** If true, extracts tool calls from mixed content (text + tool calls) */
allowMixedContent?: boolean;
}
//# sourceMappingURL=response-formatter.d.ts.map