From c2809491b45f1be3fdca1f9003e51ebc634b9770 Mon Sep 17 00:00:00 2001 From: Evan <58194240+celestial-vault@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:02:21 -0800 Subject: [PATCH] Anthropic: Bump it up! (#1938) * Updated Anthropic SDK and fixed types * adjust export markdown handling * adjust export markdown handling * added changeset --- .changeset/silver-hotels-reflect.md | 5 +++++ package-lock.json | 24 +++++++++++++----------- package.json | 4 ++-- src/api/providers/anthropic.ts | 4 ++-- src/api/transform/gemini-format.ts | 15 ++++----------- src/api/transform/o1-format.ts | 3 +++ src/api/transform/openai-format.ts | 3 +++ src/api/transform/vscode-lm-format.ts | 3 +++ src/core/Cline.ts | 4 +--- src/integrations/misc/export-markdown.ts | 16 ++++++++++++---- 10 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 .changeset/silver-hotels-reflect.md diff --git a/.changeset/silver-hotels-reflect.md b/.changeset/silver-hotels-reflect.md new file mode 100644 index 0000000000..b9b6143060 --- /dev/null +++ b/.changeset/silver-hotels-reflect.md @@ -0,0 +1,5 @@ +--- +"claude-dev": minor +--- + +Update anthropic SDK to the latest version diff --git a/package-lock.json b/package-lock.json index 7651783195..87752b8621 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "claude-dev", - "version": "3.4.3", + "version": "3.4.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "claude-dev", - "version": "3.4.3", + "version": "3.4.6", "license": "Apache-2.0", "dependencies": { - "@anthropic-ai/bedrock-sdk": "^0.10.2", - "@anthropic-ai/sdk": "^0.26.0", + "@anthropic-ai/bedrock-sdk": "^0.12.4", + "@anthropic-ai/sdk": "^0.37.0", "@anthropic-ai/vertex-sdk": "^0.4.1", "@google/generative-ai": "^0.18.0", "@mistralai/mistralai": "^1.5.0", @@ -76,11 +76,12 @@ } }, "node_modules/@anthropic-ai/bedrock-sdk": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@anthropic-ai/bedrock-sdk/-/bedrock-sdk-0.10.2.tgz", - "integrity": "sha512-sGmTzKJQHVwfXexe+yfzPU3rJmUMCygC+GNPkmMsPX/Jr+WKtJ0M71nGyHONr6vcHwUpUWA6o0MRH/oHaE54KA==", + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@anthropic-ai/bedrock-sdk/-/bedrock-sdk-0.12.4.tgz", + "integrity": "sha512-kraOgWWyVO/Wef3wYbpws77pCZubg/hCzXQ7RGrLRJsRpbTIT+ms+MigGu/0b1qn3o5WuIrumlT3Qtu3esHpzw==", + "license": "MIT", "dependencies": { - "@anthropic-ai/sdk": "^0", + "@anthropic-ai/sdk": ">=0.36 <1", "@aws-crypto/sha256-js": "^4.0.0", "@aws-sdk/client-bedrock-runtime": "^3.423.0", "@aws-sdk/credential-providers": "^3.341.0", @@ -94,9 +95,10 @@ } }, "node_modules/@anthropic-ai/sdk": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.26.0.tgz", - "integrity": "sha512-vNbZ2rnnMfk8Bf4OdeVy6GA4EXao8tGC0tLEoSAl1NZrip9oOxnEGUkXl3FsPQgeBM5hmpGE1tSLuu9HEVJiHg==", + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.37.0.tgz", + "integrity": "sha512-tHjX2YbkUBwEgg0JZU3EFSSAQPoK4qQR/NFYa8Vtzd5UAyXzZksCw2In69Rml4R/TyHPBfRYaLK35XiOe33pjw==", + "license": "MIT", "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", diff --git a/package.json b/package.json index 32e12aa25a..ac4d2b5b8a 100644 --- a/package.json +++ b/package.json @@ -237,8 +237,8 @@ "typescript": "^5.4.5" }, "dependencies": { - "@anthropic-ai/bedrock-sdk": "^0.10.2", - "@anthropic-ai/sdk": "^0.26.0", + "@anthropic-ai/bedrock-sdk": "^0.12.4", + "@anthropic-ai/sdk": "^0.37.0", "@anthropic-ai/vertex-sdk": "^0.4.1", "@google/generative-ai": "^0.18.0", "@mistralai/mistralai": "^1.5.0", diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index 959916e9a8..1b087bcda7 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -20,7 +20,7 @@ export class AnthropicHandler implements ApiHandler { @withRetry() async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream { const model = this.getModel() - let stream: AnthropicStream + let stream: AnthropicStream const modelId = model.id switch (modelId) { // 'latest' alias does not support cache_control @@ -38,7 +38,7 @@ export class AnthropicHandler implements ApiHandler { ) const lastUserMsgIndex = userMsgIndices[userMsgIndices.length - 1] ?? -1 const secondLastMsgUserIndex = userMsgIndices[userMsgIndices.length - 2] ?? -1 - stream = await this.client.beta.promptCaching.messages.create( + stream = await this.client.messages.create( { model: modelId, max_tokens: model.info.maxTokens || 8192, diff --git a/src/api/transform/gemini-format.ts b/src/api/transform/gemini-format.ts index 0a783dc183..ca21a4d326 100644 --- a/src/api/transform/gemini-format.ts +++ b/src/api/transform/gemini-format.ts @@ -11,16 +11,7 @@ import { TextPart, } from "@google/generative-ai" -export function convertAnthropicContentToGemini( - content: - | string - | Array< - | Anthropic.Messages.TextBlockParam - | Anthropic.Messages.ImageBlockParam - | Anthropic.Messages.ToolUseBlockParam - | Anthropic.Messages.ToolResultBlockParam - >, -): Part[] { +export function convertAnthropicContentToGemini(content: string | Anthropic.ContentBlockParam[]): Part[] { if (typeof content === "string") { return [{ text: content } as TextPart] } @@ -133,7 +124,7 @@ export function convertGeminiResponseToAnthropic(response: EnhancedGenerateConte // Add the main text response const text = response.text() if (text) { - content.push({ type: "text", text }) + content.push({ type: "text", text, citations: null }) } // Add function calls as tool_use blocks @@ -183,6 +174,8 @@ export function convertGeminiResponseToAnthropic(response: EnhancedGenerateConte usage: { input_tokens: response.usageMetadata?.promptTokenCount ?? 0, output_tokens: response.usageMetadata?.candidatesTokenCount ?? 0, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, }, } } diff --git a/src/api/transform/o1-format.ts b/src/api/transform/o1-format.ts index b7577cf903..237663cd06 100644 --- a/src/api/transform/o1-format.ts +++ b/src/api/transform/o1-format.ts @@ -376,6 +376,7 @@ export function convertO1ResponseToAnthropicMessage( { type: "text", text: normalText, + citations: null, }, ], model: completion.model, @@ -396,6 +397,8 @@ export function convertO1ResponseToAnthropicMessage( usage: { input_tokens: completion.usage?.prompt_tokens || 0, output_tokens: completion.usage?.completion_tokens || 0, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, }, } diff --git a/src/api/transform/openai-format.ts b/src/api/transform/openai-format.ts index 0b134ad4ac..ddcffc8f76 100644 --- a/src/api/transform/openai-format.ts +++ b/src/api/transform/openai-format.ts @@ -161,6 +161,7 @@ export function convertToAnthropicMessage(completion: OpenAI.Chat.Completions.Ch { type: "text", text: openAiMessage.content || "", + citations: null, }, ], model: completion.model, @@ -181,6 +182,8 @@ export function convertToAnthropicMessage(completion: OpenAI.Chat.Completions.Ch usage: { input_tokens: completion.usage?.prompt_tokens || 0, output_tokens: completion.usage?.completion_tokens || 0, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, }, } diff --git a/src/api/transform/vscode-lm-format.ts b/src/api/transform/vscode-lm-format.ts index acec3656e1..04d7245bec 100644 --- a/src/api/transform/vscode-lm-format.ts +++ b/src/api/transform/vscode-lm-format.ts @@ -175,6 +175,7 @@ export async function convertToAnthropicMessage( return { type: "text", text: part.value, + citations: null, } } @@ -195,6 +196,8 @@ export async function convertToAnthropicMessage( usage: { input_tokens: 0, output_tokens: 0, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, }, } } diff --git a/src/core/Cline.ts b/src/core/Cline.ts index b1c6baa90c..39fa02bc46 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -63,9 +63,7 @@ import { ClineProvider, GlobalFileNames } from "./webview/ClineProvider" const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) ?? path.join(os.homedir(), "Desktop") // may or may not exist but fs checking existence would immediately ask for permission which would be bad UX, need to come up with a better solution type ToolResponse = string | Array -type UserContent = Array< - Anthropic.TextBlockParam | Anthropic.ImageBlockParam | Anthropic.ToolUseBlockParam | Anthropic.ToolResultBlockParam -> +type UserContent = Array export class Cline { readonly taskId: string diff --git a/src/integrations/misc/export-markdown.ts b/src/integrations/misc/export-markdown.ts index 76e95e36b7..f130b3043d 100644 --- a/src/integrations/misc/export-markdown.ts +++ b/src/integrations/misc/export-markdown.ts @@ -35,14 +35,20 @@ export async function downloadTask(dateTs: number, conversationHistory: Anthropi }) if (saveUri) { - // Write content to the selected location - await vscode.workspace.fs.writeFile(saveUri, Buffer.from(markdownContent)) - vscode.window.showTextDocument(saveUri, { preview: true }) + try { + // Write content to the selected location + await vscode.workspace.fs.writeFile(saveUri, new TextEncoder().encode(markdownContent)) + vscode.window.showTextDocument(saveUri, { preview: true }) + } catch (error) { + vscode.window.showErrorMessage( + `Failed to save markdown file: ${error instanceof Error ? error.message : String(error)}`, + ) + } } } export function formatContentBlockToMarkdown( - block: Anthropic.TextBlockParam | Anthropic.ImageBlockParam | Anthropic.ToolUseBlockParam | Anthropic.ToolResultBlockParam, + block: Anthropic.ContentBlockParam, // messages: Anthropic.MessageParam[] ): string { switch (block.type) { @@ -50,6 +56,8 @@ export function formatContentBlockToMarkdown( return block.text case "image": return `[Image]` + case "document": + return `[Document]` case "tool_use": let input: string if (typeof block.input === "object" && block.input !== null) {