UNPKG

@nomyx/assistant

Version:

A powerful assistant library and cli for your AI projects. works with Vertex AI (Claude and Gemini)

120 lines (107 loc) 4.68 kB
import { ChatMessage, FunctionCall, ProviderResponse } from '../../../types/chat'; import { GenericToolSchema, ParameterDefinition, StandardizedToolCall } from '../../../types/tool'; import { OpenAIMessage, MODELS_WITHOUT_SYSTEM_MESSAGES, OpenAIFunction, OpenAIToolCall } from './types'; export function convertMessages(messages: ChatMessage[], model: string): OpenAIMessage[] { const supportsSystemMessages = !MODELS_WITHOUT_SYSTEM_MESSAGES.includes(model); return messages.map(msg => { let convertedMessage: Partial<OpenAIMessage> = { content: msg.content, }; switch (msg.role) { case 'system': convertedMessage.role = supportsSystemMessages ? 'system' : 'user'; if (!supportsSystemMessages) { convertedMessage.content = `System: ${msg.content}`; } break; case 'user': case 'assistant': convertedMessage.role = msg.role; break; case 'function': convertedMessage = { role: 'function', content: msg.content, name: msg.name || 'unknown', }; break; default: console.warn(`Unknown role "${msg.role}" encountered. Treating as "user".`); convertedMessage.role = 'user'; } if (msg.role === 'assistant' && 'function_call' in msg && msg.function_call) { (convertedMessage as OpenAIMessage).function_call = convertFunctionCall(msg.function_call as FunctionCall); } return convertedMessage as OpenAIMessage; }); } export function convertFunctionCall(functionCall: FunctionCall): { name: string; arguments: string } { return { name: functionCall.name, arguments: JSON.stringify(functionCall.arguments) }; } export function convertToolSchema(schema: GenericToolSchema): OpenAIFunction { return { name: schema.name, description: schema.description, parameters: { type: 'object', properties: convertParameters(schema.parameters.properties), required: schema.parameters.required, }, }; } export function convertParameters(params: Record<string, ParameterDefinition>): Record<string, ParameterDefinition> { const result: Record<string, ParameterDefinition> = {}; for (const [key, value] of Object.entries(params)) { result[key] = convertParameterDefinition(value); } return result; } export function convertParameterDefinition(param: ParameterDefinition): ParameterDefinition { const result: ParameterDefinition = { type: param.type }; if (param.description) result.description = param.description; if (param.enum) result.enum = param.enum; if (param.items) result.items = convertParameterDefinition(param.items); if (param.properties) result.properties = convertParameters(param.properties); if (param.required) result.required = param.required; return result; } export function convertToolCall(call: OpenAIToolCall): StandardizedToolCall { try { const convertedCall = { name: call.function.name, arguments: JSON.parse(call.function.arguments || '{}'), }; validateToolCall(convertedCall); return convertedCall; } catch (error) { throw new Error(`Failed to convert tool call: ${error instanceof Error ? error.message : String(error)}`); } } export function validateToolCall(toolCall: StandardizedToolCall): void { if (typeof toolCall.name !== 'string' || toolCall.name.trim() === '') { throw new Error('Invalid tool call: name must be a non-empty string'); } if (typeof toolCall.arguments !== 'object' || toolCall.arguments === null) { throw new Error('Invalid tool call: arguments must be an object'); } } export function convertToolCalls(toolCalls: OpenAIToolCall[] | undefined): StandardizedToolCall[] { if (!toolCalls || toolCalls.length === 0) return []; return toolCalls.map(call => { try { return convertToolCall(call); } catch (error) { return null; } }).filter((call): call is StandardizedToolCall => call !== null); } export function convertUsage(usage: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number } | undefined): ProviderResponse['usage'] { return { promptTokens: usage?.prompt_tokens || 0, completionTokens: usage?.completion_tokens || 0, totalTokens: usage?.total_tokens || 0, }; }