Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 62 additions & 80 deletions libs/langchain-core/src/messages/block_translators/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,6 @@ export function convertToV1FromAnthropicContentBlock(
mimeType: String(block.source.media_type ?? "text/plain"),
data: block.source.data,
};
} else {
return block as ContentBlock.Standard;
}
} else if (
_isContentBlock(block, "image") &&
Expand Down Expand Up @@ -229,8 +227,6 @@ export function convertToV1FromAnthropicContentBlock(
type: "image",
fileId: block.source.file_id,
};
} else {
return block as ContentBlock.Standard;
}
}
return undefined;
Expand Down Expand Up @@ -263,29 +259,6 @@ export function convertToV1FromAnthropicInput(
return Array.from(iterateContent());
}

type AnthropicCodeExecutionToolResult = {
type: "code_execution_tool_result";
tool_use_id: string;
content:
| {
// BetaCodeExecutionToolResultError
type: "code_execution_tool_result_error";
error_code: string;
}
| {
// BetaCodeExecutionResultBlock
type: "code_execution_result";
stderr: string;
stdout: string;
return_code: number;
content: {
// BetaCodeExecutionOutputBlock
type: "code_execution_output";
file_id: string;
}[];
};
};

/**
* Converts an Anthropic AI message to an array of v1 standard content blocks.
*
Expand Down Expand Up @@ -341,12 +314,14 @@ export function convertToV1FromAnthropicMessage(
text,
annotations: _citations,
};
continue;
} else {
yield {
...rest,
type: "text",
text,
};
continue;
}
}
// ThinkingBlock
Expand All @@ -361,9 +336,11 @@ export function convertToV1FromAnthropicMessage(
reasoning: thinking,
signature,
};
continue;
}
// RedactedThinkingBlock
else if (_isContentBlock(block, "redacted_thinking")) {
yield { type: "non_standard", value: block };
continue;
}
// ToolUseBlock
Expand All @@ -378,6 +355,7 @@ export function convertToV1FromAnthropicMessage(
name: block.name,
args: block.input,
};
continue;
}
// message chunks can have input_json_delta contents
else if (_isContentBlock(block, "input_json_delta")) {
Expand All @@ -390,8 +368,8 @@ export function convertToV1FromAnthropicMessage(
args: tool_call_chunk.args,
index: tool_call_chunk.index,
};
continue;
}
// TODO: implement
}
// ServerToolUseBlock
else if (
Expand All @@ -418,9 +396,11 @@ export function convertToV1FromAnthropicMessage(
});
yield {
id,
type: "web_search_call",
query,
type: "server_tool_call",
name: "web_search",
args: { query },
};
continue;
} else if (block.name === "code_execution") {
const code = iife(() => {
if (typeof block.input === "string") {
Expand All @@ -437,9 +417,11 @@ export function convertToV1FromAnthropicMessage(
});
yield {
id,
type: "code_interpreter_call",
code,
type: "server_tool_call",
name: "code_execution",
args: { code },
};
continue;
}
}
// WebSearchToolResultBlock
Expand All @@ -456,89 +438,89 @@ export function convertToV1FromAnthropicMessage(
return acc;
}, []);
yield {
id: tool_use_id,
type: "web_search_result",
urls,
type: "server_tool_call_result",
name: "web_search",
toolCallId: tool_use_id,
status: "success",
output: {
urls,
},
};
continue;
}
// CodeExecutionToolResultBlock
else if (
_isContentBlock(block, "code_execution_tool_result") &&
_isString(block.tool_use_id)
_isString(block.tool_use_id) &&
_isObject(block.content)
) {
// We just make a type assertion here instead of deep checking every property
// since `code_execution_tool_result` is an anthropic only block
const { content, tool_use_id } =
block as AnthropicCodeExecutionToolResult;
const output = iife(() => {
if (content.type === "code_execution_tool_result_error") {
return [
{
type: "code_interpreter_output" as const,
returnCode: 1,
stderr: content.error_code,
},
];
}
if (content.type === "code_execution_result") {
const fileIds = Array.isArray(content.content)
? content.content
.filter((content) => content.type === "code_execution_output")
.map((content) => content.file_id)
: [];
return [
{
type: "code_interpreter_output" as const,
returnCode: content.return_code ?? 0,
stderr: content.stderr,
stdout: content.stdout,
fileIds,
},
];
}
return [];
});
yield {
id: tool_use_id,
type: "code_interpreter_result",
output,
type: "server_tool_call_result",
name: "code_execution",
toolCallId: block.tool_use_id,
status: "success",
output: block.content,
};
continue;
}
// MCPToolUseBlock
else if (block.type === "mcp_tool_use") {
else if (_isContentBlock(block, "mcp_tool_use")) {
yield {
id: block.id,
type: "server_tool_call",
name: "mcp_tool_use",
args: block.input,
};
continue;
}
// MCPToolResultBlock
else if (block.type === "mcp_tool_result") {
else if (
_isContentBlock(block, "mcp_tool_result") &&
_isString(block.tool_use_id) &&
_isObject(block.content)
) {
yield {
type: "server_tool_call_result",
name: "mcp_tool_use",
toolCallId: block.tool_use_id,
status: "success",
output: block.content,
};
continue;
}
// ContainerUploadBlock
else if (block.type === "container_upload") {
else if (_isContentBlock(block, "container_upload")) {
yield {
type: "server_tool_call",
name: "container_upload",
args: block.input,
};
continue;
}
// SearchResultBlockParam
else if (block.type === "search_result") {
else if (_isContentBlock(block, "search_result")) {
yield { id: block.id, type: "non_standard", value: block };
continue;
}
// ToolResultBlockParam
else if (block.type === "tool_result") {
// TODO: Implement
else if (_isContentBlock(block, "tool_result")) {
yield { id: block.id, type: "non_standard", value: block };
continue;
} else {
// For all other blocks, we try to convert them to a standard block
const stdBlock = convertToV1FromAnthropicContentBlock(block);
if (stdBlock) {
yield stdBlock;
} else {
// TODO: non standard?
continue;
}
}
yield { type: "non_standard", value: block };
}
}
return Array.from(iterateContent());
}

export const anthropicTranslator: StandardContentBlockTranslator = {
export const ChatAnthropicTranslator: StandardContentBlockTranslator = {
translateContent: convertToV1FromAnthropicMessage,
translateContentChunk: convertToV1FromAnthropicMessage,
};
Expand Down
10 changes: 0 additions & 10 deletions libs/langchain-core/src/messages/block_translators/bedrock.ts

This file was deleted.

8 changes: 4 additions & 4 deletions libs/langchain-core/src/messages/block_translators/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { AIMessage, AIMessageChunk } from "../ai.js";
import type { ContentBlock } from "../content/index.js";

import { anthropicTranslator } from "./anthropic.js";
import { ChatAnthropicTranslator } from "./anthropic.js";
import { ChatBedrockConverseTranslator } from "./bedrock_converse.js";
import { ChatGoogleGenAITranslator } from "./google_genai.js";
import { ChatVertexTranslator } from "./google_vertexai.js";
import { openaiTranslator } from "./openai.js";
import { ChatOpenAITranslator } from "./openai.js";

export interface StandardContentBlockTranslator {
translateContent(message: AIMessage): Array<ContentBlock.Standard>;
Expand All @@ -19,11 +19,11 @@ declare global {
}

globalThis.lc_block_translators_registry ??= new Map([
["anthropic", anthropicTranslator],
["anthropic", ChatAnthropicTranslator],
["bedrock-converse", ChatBedrockConverseTranslator],
["google-genai", ChatGoogleGenAITranslator],
["google-vertexai", ChatVertexTranslator],
["openai", openaiTranslator],
["openai", ChatOpenAITranslator],
]);

export function registerTranslator(
Expand Down
Loading