@nomyx/assistant
Version:
A powerful assistant library and cli for your AI projects. works with Vertex AI (Claude and Gemini)
90 lines (89 loc) • 3.71 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.chat = chat;
const axios_1 = __importDefault(require("axios"));
const tools_1 = require("./tools");
async function chat(config, messages, options, tools) {
const url = config.getApiUrl();
const convertedMessages = (0, tools_1.convertMessages)(messages);
const requestBody = {
model: config.model,
messages: convertedMessages.filter(msg => msg.role !== 'system'),
max_tokens: options.maxTokens || 4000,
temperature: options.temperature,
};
// Combine all system messages into a single system parameter
const systemMessages = convertedMessages.filter(msg => msg.role === 'system');
if (systemMessages.length > 0) {
requestBody.system = systemMessages.map(msg => msg.content).join('\n\n');
}
if (tools && tools.length > 0) {
const toolNames = tools.map(tool => tool.name).join(', ');
requestBody.system = (requestBody.system || '') + `\n\nYou have access to the following tools: ${toolNames}. Use them when necessary.`;
const convertedTools = tools.map(tool => (0, tools_1.convertToolSchema)(tool.getSchema()));
requestBody.tools = convertedTools;
}
try {
const response = await axios_1.default.post(url, requestBody, {
headers: {
'Content-Type': 'application/json',
'x-api-key': config.apiKey,
'anthropic-version': '2023-06-01',
},
});
return await createProviderResponse(response.data, tools || []);
}
catch (error) {
if (axios_1.default.isAxiosError(error) && error.response) {
throw new Error(`Anthropic API Error: ${error.response.status} - ${JSON.stringify(error.response.data)}`);
}
throw error;
}
}
async function createProviderResponse(data, tools) {
const response = {
content: '',
toolCalls: [],
usage: {
promptTokens: data.usage?.input_tokens || 0,
completionTokens: data.usage?.output_tokens || 0,
totalTokens: (data.usage?.input_tokens || 0) + (data.usage?.output_tokens || 0)
},
};
for (const item of data.content) {
if (item.type === 'text') {
response.content += item.text;
}
else if (item.type === 'tool_use') {
const toolUse = item;
const toolCall = {
name: toolUse.name,
arguments: toolUse.input,
};
response.toolCalls && response.toolCalls.push(toolCall);
const tool = tools.find(t => t.name === toolUse.name);
if (tool) {
try {
const result = await tool.execute(toolUse.input, {});
response.content += `\n\nTool ${toolUse.name} result: ${typeof result === 'string' ? result : JSON.stringify(result)}`;
}
catch (error) {
response.content += `\n\nError executing tool ${toolUse.name}: ${error}`;
}
}
else {
response.content += `\n\nError: Tool not found: ${toolUse.name}`;
}
}
}
// Update usage tokens with the latest data from the response
response.usage = {
promptTokens: data.usage?.input_tokens || 0,
completionTokens: data.usage?.output_tokens || 0,
totalTokens: (data.usage?.input_tokens || 0) + (data.usage?.output_tokens || 0)
};
return response;
}