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

100 lines 3.53 kB
/** * Checks if an assistant message is empty (no content and no tool calls). * Empty assistant messages cause API errors: * "400 Bad Request: Assistant message must have either content or tool_calls, but not none." * * Exported for testing purposes. */ export function isEmptyAssistantMessage(message) { if (message.role !== 'assistant') { return false; } // Check for content - handle both string and array content formats const hasContent = Array.isArray(message.content) ? message.content.length > 0 : typeof message.content === 'string' && message.content.trim().length > 0; // Tool calls are in a separate property for AI SDK messages const hasToolCalls = 'toolCalls' in message && Array.isArray(message.toolCalls) && message.toolCalls.length > 0; return !hasContent && !hasToolCalls; } /** * Convert our Message format to AI SDK v6 ModelMessage format * * Tool messages: Converted to AI SDK tool-result format with proper structure. */ export function convertToModelMessages(messages) { return messages.map((msg) => { if (msg.role === 'tool') { // Convert to AI SDK tool-result format // AI SDK expects: { role: 'tool', content: [{ type: 'tool-result', toolCallId, toolName, output }] } // where output is { type: 'text', value: string } or { type: 'json', value: JSONValue } return { role: 'tool', content: [ { type: 'tool-result', toolCallId: msg.tool_call_id || '', toolName: msg.name || '', output: { type: 'text', value: msg.content, }, }, ], }; } if (msg.role === 'system') { return { role: 'system', content: msg.content, }; } if (msg.role === 'user') { return { role: 'user', content: msg.content, }; } if (msg.role === 'assistant') { // Build content array const content = []; // Add text content if present if (msg.content) { content.push({ type: 'text', text: msg.content, }); } // Add tool calls if present (for auto-executed messages) if (msg.tool_calls && msg.tool_calls.length > 0) { for (const toolCall of msg.tool_calls) { content.push({ type: 'tool-call', toolCallId: toolCall.id, toolName: toolCall.function.name, input: toolCall.function.arguments, }); } } // If no content at all, add empty text to avoid empty message if (content.length === 0) { content.push({ type: 'text', text: '', }); } return { role: 'assistant', content, }; } // Fallback - should never happen return { role: 'user', content: msg.content, }; }); } //# sourceMappingURL=message-converter.js.map