@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
JavaScript
;
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;