contextual-agent-sdk
Version:
SDK for building AI agents with seamless voice-text context switching
292 lines • 13 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnthropicProvider = void 0;
const BaseLLMProvider_1 = require("./BaseLLMProvider");
const ToolConverter_1 = require("../tools/ToolConverter");
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
class AnthropicProvider extends BaseLLMProvider_1.BaseLLMProvider {
type = 'anthropic';
name = 'Anthropic';
config;
client;
constructor(config) {
super();
this.config = config;
if (config.apiKey) {
this.client = new sdk_1.default({
apiKey: config.apiKey,
baseURL: config.baseURL
});
console.log('🎯 Anthropic Provider initialized with official SDK');
}
}
supportsTools() {
return true;
}
supportsStreaming() {
return true;
}
getMaxTokens() {
const model = this.config.model || 'claude-3-5-sonnet-20241022';
if (model.includes('claude-3-5-sonnet'))
return 200000;
if (model.includes('claude-3-sonnet'))
return 200000;
if (model.includes('claude-3-haiku'))
return 200000;
if (model.includes('claude-2'))
return 100000;
if (model.includes('claude-instant'))
return 100000;
return 200000;
}
async generateResponse(options) {
if (!this.client) {
throw new Error('Anthropic SDK provider not configured. Please provide an API key.');
}
try {
const systemMessage = options.messages.find(msg => msg.role === 'system');
const userMessages = options.messages.filter(msg => msg.role !== 'system');
console.log('📤 Anthropic SDK Request (Basic):', {
model: this.config.model || 'claude-3-5-sonnet-20241022',
messages: userMessages.length,
system: !!systemMessage?.content,
max_tokens: options.maxTokens || 1000
});
const response = await this.client.messages.create({
model: this.config.model || 'claude-3-5-sonnet-20241022',
max_tokens: options.maxTokens || this.config.defaultOptions?.maxTokens || 1000,
temperature: options.temperature || this.config.defaultOptions?.temperature || 0.7,
messages: userMessages.map(msg => ({
role: msg.role,
content: msg.content
})),
...(systemMessage && { system: systemMessage.content })
});
console.log('📥 Anthropic SDK Response (Basic):', {
content_length: response.content.length,
stop_reason: response.stop_reason,
usage: response.usage
});
const content = response.content
.filter((block) => block.type === 'text')
.map(block => block.text)
.join('');
return {
content,
usage: response.usage ? {
promptTokens: response.usage.input_tokens,
completionTokens: response.usage.output_tokens,
totalTokens: response.usage.input_tokens + response.usage.output_tokens
} : undefined,
finishReason: response.stop_reason || 'stop'
};
}
catch (error) {
console.error('❌ Anthropic SDK Error:', error);
throw new Error(`Failed to generate response: ${error.message}`);
}
}
async generateWithTools(options) {
if (!this.client) {
throw new Error('Anthropic SDK provider not configured. Please provide an API key.');
}
if (!options.tools || options.tools.length === 0) {
const response = await this.generateResponse(options);
return {
...response,
toolCalls: [],
stopReason: 'stop'
};
}
try {
const anthropicTools = options.tools.map(tool => ({
name: tool.function.name,
description: tool.function.description,
input_schema: tool.function.parameters
}));
const systemMessage = options.messages.find(msg => msg.role === 'system');
const conversationMessages = options.messages.filter(msg => msg.role !== 'system');
console.log('🔧 Anthropic SDK Tool Request (OFFICIAL API):', {
model: this.config.model || 'claude-3-5-sonnet-20241022',
messages: conversationMessages.length,
tools: anthropicTools.map(t => ({ name: t.name, description: t.description })),
system: !!systemMessage?.content
});
const response = await this.client.messages.create({
model: this.config.model || 'claude-3-5-sonnet-20241022',
max_tokens: options.maxTokens || this.config.defaultOptions?.maxTokens || 1000,
temperature: options.temperature || this.config.defaultOptions?.temperature || 0.7,
messages: conversationMessages.map(msg => ({
role: msg.role,
content: msg.content
})),
tools: anthropicTools,
...(systemMessage && { system: systemMessage.content })
});
console.log('🔧 Anthropic SDK Tool Response (OFFICIAL API):', {
content_blocks: response.content.length,
stop_reason: response.stop_reason,
usage: response.usage,
tool_use_blocks: response.content.filter(block => block.type === 'tool_use').length
});
const textContent = response.content
.filter((block) => block.type === 'text')
.map(block => block.text)
.join('');
const toolCalls = response.content
.filter((block) => block.type === 'tool_use')
.map(block => ({
id: block.id,
type: 'function',
function: {
name: block.name,
arguments: JSON.stringify(block.input)
}
}));
const stopReason = response.stop_reason === 'tool_use' ? 'tool_calls' :
response.stop_reason === 'max_tokens' ? 'length' :
'stop';
console.log('🎯 Extracted Tool Calls (OFFICIAL SDK):', toolCalls.map(tc => ({
id: tc.id,
name: tc.function.name,
args: tc.function.arguments
})));
return {
content: textContent,
usage: response.usage ? {
promptTokens: response.usage.input_tokens,
completionTokens: response.usage.output_tokens,
totalTokens: response.usage.input_tokens + response.usage.output_tokens
} : undefined,
finishReason: response.stop_reason || 'stop',
toolCalls,
stopReason,
conversation: options.conversation
};
}
catch (error) {
console.error('❌ Anthropic SDK Tool Error (OFFICIAL API):', error);
throw new Error(`Failed to generate response with tools: ${error.message}`);
}
}
async handleToolLoop(conversation, tools) {
const maxIterations = 10;
let iteration = 0;
console.log(`🔄 Starting Anthropic SDK Tool Loop with ${tools.length} tools`);
while (iteration < maxIterations) {
iteration++;
console.log(`🔄 Tool Loop Iteration ${iteration}/${maxIterations}`);
const messages = this.conversationManager.getConversationHistory(conversation.id);
const response = await this.generateWithTools({
messages,
tools: ToolConverter_1.ToolConverter.toOpenAIFunctions(tools),
conversation,
maxTokens: this.config.defaultOptions?.maxTokens || 1000
});
if (!response.toolCalls || response.toolCalls.length === 0) {
console.log('✅ Tool loop complete - no more tool calls');
return response;
}
console.log(`🔧 Executing ${response.toolCalls.length} tool call(s):`, response.toolCalls.map(tc => tc.function.name));
const toolResults = await ToolConverter_1.ToolConverter.executeToolCalls(response.toolCalls, tools, ToolConverter_1.ToolConverter.createToolContext(conversation.metadata?.agentId || 'unknown', conversation.id, conversation.metadata?.userId));
this.conversationManager.addMessage(conversation.id, {
role: 'assistant',
content: response.content || '',
metadata: { toolCalls: response.toolCalls }
});
for (let i = 0; i < response.toolCalls.length; i++) {
const toolCall = response.toolCalls[i];
const result = toolResults[i];
const resultContent = result.success
? (typeof result.data === 'string' ? result.data : JSON.stringify(result.data))
: `Error: ${result.error}`;
this.conversationManager.addMessage(conversation.id, {
role: 'user',
content: `<tool_result tool_call_id="${toolCall.id}">${resultContent}</tool_result>`,
metadata: {
isToolResult: true,
toolCallId: toolCall.id,
toolResult: result
}
});
console.log(`🎯 Tool ${toolCall.function.name} result:`, {
success: result.success,
hasData: !!result.data,
error: result.error
});
}
const criticalFailure = toolResults.find(result => !result.success && result.metadata?.critical);
if (criticalFailure) {
console.error('❌ Critical tool failure:', criticalFailure);
return {
...response,
content: `Tool execution failed: ${criticalFailure.error}`,
stopReason: 'stop'
};
}
}
throw new Error(`Tool execution loop exceeded maximum iterations (${maxIterations})`);
}
async *streamResponse(options) {
if (!this.client) {
throw new Error('Anthropic SDK provider not configured. Please provide an API key.');
}
try {
const systemMessage = options.messages.find(msg => msg.role === 'system');
const userMessages = options.messages.filter(msg => msg.role !== 'system');
const stream = await this.client.messages.create({
model: this.config.model || 'claude-3-5-sonnet-20241022',
max_tokens: options.maxTokens || this.config.defaultOptions?.maxTokens || 1000,
temperature: options.temperature || this.config.defaultOptions?.temperature || 0.7,
messages: userMessages.map(msg => ({
role: msg.role,
content: msg.content
})),
stream: true,
...(systemMessage && { system: systemMessage.content })
});
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') {
yield {
type: 'content',
content: chunk.delta.text
};
}
}
yield {
type: 'done',
done: true
};
}
catch (error) {
yield {
type: 'error',
error: error.message
};
}
}
async isAvailable() {
return !!this.client && !!this.config.apiKey;
}
async test() {
if (!this.client) {
throw new Error('Anthropic SDK provider not configured');
}
try {
await this.client.messages.create({
model: this.config.model || 'claude-3-5-sonnet-20241022',
max_tokens: 10,
messages: [{ role: 'user', content: 'Hi' }]
});
}
catch (error) {
throw new Error(`Anthropic SDK test failed: ${error.message}`);
}
}
}
exports.AnthropicProvider = AnthropicProvider;
//# sourceMappingURL=AnthropicProvider.js.map