@nomyx/assistant
Version:
A powerful assistant library and cli for your AI projects. works with Vertex AI (Claude and Gemini)
126 lines (114 loc) • 4.2 kB
text/typescript
import { ChatMessage } from '../../../types/chat';
import { GenericToolSchema, ParameterDefinition, StandardizedToolCall } from '../../../types/tool';
import { OpenRouterMessage, OpenRouterTool, OpenRouterToolCall, OpenRouterMessageContent } from './types';
export function convertMessages(messages: ChatMessage[]): OpenRouterMessage[] {
return messages.map(msg => {
let convertedMessage: Partial<OpenRouterMessage> = {
content: msg.content,
};
switch (msg.role) {
case 'system':
case 'user':
case 'assistant':
convertedMessage.role = msg.role;
break;
case 'function':
convertedMessage = {
role: 'tool',
content: msg.content,
};
break;
default:
console.warn(`Unknown role "${msg.role}" encountered. Treating as "user".`);
convertedMessage.role = 'user';
}
if (msg.role === 'assistant' && (msg as any).function_call) {
convertedMessage.tool_calls = [{
id: (msg as any).function_call.name,
type: 'function',
function: {
name: (msg as any).function_call.name,
arguments: (msg as any).function_call.arguments,
},
}];
}
return convertedMessage as OpenRouterMessage;
});
}
export function convertToolSchema(schema: GenericToolSchema): OpenRouterTool {
return {
type: 'function',
function: {
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: OpenRouterToolCall): 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: OpenRouterToolCall[] | undefined): StandardizedToolCall[] {
if (!toolCalls || toolCalls.length === 0) return [];
return toolCalls.map(call => {
try {
return convertToolCall(call);
} catch (error) {
console.error('Error converting tool call:', error);
return null;
}
}).filter((call): call is StandardizedToolCall => call !== null);
}
export function extractToolCalls(message: OpenRouterMessage): StandardizedToolCall[] {
if (!message.tool_calls || message.tool_calls.length === 0) {
return [];
}
return message.tool_calls.map(toolCall => {
try {
return {
name: toolCall.function.name,
arguments: JSON.parse(toolCall.function.arguments),
};
} catch (error) {
console.error('Error parsing tool call arguments:', error);
return null;
}
}).filter((call): call is StandardizedToolCall => call !== null);
}