UNPKG

@robota-sdk/anthropic

Version:

Anthropic Claude integration for Robota SDK - Claude 3, Claude 2, function calling, and tool integration with Anthropic's API

219 lines (212 loc) 6.66 kB
'use strict'; var Anthropic = require('@anthropic-ai/sdk'); var agents = require('@robota-sdk/agents'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var Anthropic__default = /*#__PURE__*/_interopDefault(Anthropic); // src/provider.ts var AnthropicProvider = class extends agents.BaseAIProvider { name = "anthropic"; version = "1.0.0"; client; options; constructor(options) { super(); this.options = options; if (options.client) { this.client = options.client; } else if (options.apiKey) { this.client = new Anthropic__default.default({ apiKey: options.apiKey, ...options.timeout && { timeout: options.timeout }, ...options.baseURL && { baseURL: options.baseURL } }); } else { throw new Error("Either Anthropic client or apiKey is required"); } } /** * Generate response using UniversalMessage */ async chat(messages, options) { this.validateMessages(messages); const anthropicMessages = this.convertToAnthropicFormat(messages); if (!options?.model) { throw new Error("Model is required in ChatOptions. Please specify a model in defaultModel configuration."); } const requestParams = { model: options.model, messages: anthropicMessages, max_tokens: options?.maxTokens || 4096 }; if (options?.temperature !== void 0) { requestParams.temperature = options.temperature; } if (options?.tools) { requestParams.tools = this.convertToolsToAnthropicFormat(options.tools); } const response = await this.client.messages.create(requestParams); return this.convertFromAnthropicResponse(response); } /** * Generate streaming response using UniversalMessage */ async *chatStream(messages, options) { this.validateMessages(messages); const anthropicMessages = this.convertToAnthropicFormat(messages); if (!options?.model) { throw new Error("Model is required in ChatOptions. Please specify a model in defaultModel configuration."); } const requestParams = { model: options.model, messages: anthropicMessages, max_tokens: options?.maxTokens || 4096, stream: true }; if (options?.temperature !== void 0) { requestParams.temperature = options.temperature; } if (options?.tools) { requestParams.tools = this.convertToolsToAnthropicFormat(options.tools); } const stream = await this.client.messages.create(requestParams); for await (const chunk of stream) { if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") { yield { role: "assistant", content: chunk.delta.text, timestamp: /* @__PURE__ */ new Date() }; } } } supportsTools() { return true; } validateConfig() { return !!this.client && !!this.options && !!this.options.apiKey; } async dispose() { } /** * Convert UniversalMessage to Anthropic format * * CRITICAL: Anthropic API requires specific content handling: * - tool_use messages: content MUST be null * - regular messages: content should be a string */ convertToAnthropicFormat(messages) { return messages.map((msg) => { if (msg.role === "user") { return { role: "user", content: msg.content || "" }; } else if (msg.role === "assistant") { const assistantMsg = msg; if (assistantMsg.toolCalls && assistantMsg.toolCalls.length > 0) { return { role: "assistant", content: null, // MUST be null for tool calls in Anthropic tool_calls: assistantMsg.toolCalls.map((tc) => ({ id: tc.id, type: "function", function: { name: tc.function.name, arguments: JSON.stringify(tc.function.arguments) } })) // eslint-disable-next-line @typescript-eslint/no-explicit-any }; } return { role: "assistant", content: assistantMsg.content || "" }; } else { return { role: "user", // Anthropic doesn't have system role, use user content: msg.content || "" }; } }); } /** * Convert Anthropic response to UniversalMessage */ convertFromAnthropicResponse(response) { if (!response.content || response.content.length === 0) { throw new Error("No content in Anthropic response"); } const content = response.content[0]; if (content && content.type === "text") { const textContent = content; const result = { role: "assistant", content: textContent.text, timestamp: /* @__PURE__ */ new Date() }; if (response.usage) { result.metadata = { inputTokens: response.usage.input_tokens, outputTokens: response.usage.output_tokens, model: response.model }; if (response.stop_reason) { result.metadata["stopReason"] = response.stop_reason; } } return result; } else if (content && content.type === "tool_use") { const toolContent = content; const result = { role: "assistant", content: "", // Empty string for type compatibility timestamp: /* @__PURE__ */ new Date(), toolCalls: [{ id: toolContent.id, type: "function", function: { name: toolContent.name, arguments: JSON.stringify(toolContent.input) } }] }; return result; } throw new Error(`Unsupported content type: ${content.type}`); } /** * Convert tools to Anthropic format */ convertToolsToAnthropicFormat(tools) { return tools.map((tool) => ({ name: tool.name, description: tool.description, input_schema: tool.parameters })); } /** * Validate UniversalMessage array */ validateMessages(messages) { if (!Array.isArray(messages)) { throw new Error("Messages must be an array"); } if (messages.length === 0) { throw new Error("Messages array cannot be empty"); } for (const message of messages) { if (!message.role || !["user", "assistant", "system", "tool"].includes(message.role)) { throw new Error(`Invalid message role: ${message.role}`); } } } }; // src/index.ts function createAnthropicProvider(_options) { } exports.AnthropicProvider = AnthropicProvider; exports.createAnthropicProvider = createAnthropicProvider;