UNPKG

contextual-agent-sdk

Version:

SDK for building AI agents with seamless voice-text context switching

292 lines 13 kB
"use strict"; 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