Chore/claude sonnet 4.5 (#5271)

* claude sonnet 4.5

* add anthropic built in tools

* add comments to remove tool calls with no id
This commit is contained in:
Henry Heng
2025-09-30 12:31:23 +01:00
committed by GitHub
parent 6890ced939
commit b501932491
5 changed files with 250 additions and 66 deletions
+26 -5
View File
@@ -3,6 +3,13 @@
{
"name": "awsChatBedrock",
"models": [
{
"label": "anthropic.claude-sonnet-4-5-20250929-v1:0",
"name": "anthropic.claude-sonnet-4-5-20250929-v1:0",
"description": "Claude 4.5 Sonnet",
"input_cost": 0.000003,
"output_cost": 0.000015
},
{
"label": "openai.gpt-oss-20b-1:0",
"name": "openai.gpt-oss-20b-1:0",
@@ -486,11 +493,11 @@
"name": "chatAnthropic",
"models": [
{
"label": "claude-opus-4-1",
"name": "claude-opus-4-1",
"description": "Claude 4.1 Opus",
"input_cost": 0.000015,
"output_cost": 0.000075
"label": "claude-sonnet-4-5",
"name": "claude-sonnet-4-5",
"description": "Claude 4.5 Sonnet",
"input_cost": 0.000003,
"output_cost": 0.000015
},
{
"label": "claude-sonnet-4-0",
@@ -499,6 +506,13 @@
"input_cost": 0.000003,
"output_cost": 0.000015
},
{
"label": "claude-opus-4-1",
"name": "claude-opus-4-1",
"description": "Claude 4.1 Opus",
"input_cost": 0.000015,
"output_cost": 0.000075
},
{
"label": "claude-opus-4-0",
"name": "claude-opus-4-0",
@@ -723,6 +737,13 @@
"input_cost": 1.25e-7,
"output_cost": 3.75e-7
},
{
"label": "claude-sonnet-4-5@20250929",
"name": "claude-sonnet-4-5@20250929",
"description": "Claude 4.5 Sonnet",
"input_cost": 0.000003,
"output_cost": 0.000015
},
{
"label": "claude-opus-4-1@20250805",
"name": "claude-opus-4-1@20250805",
@@ -182,6 +182,35 @@ class Agent_Agentflow implements INode {
agentModel: 'chatGoogleGenerativeAI'
}
},
{
label: 'Anthropic Built-in Tools',
name: 'agentToolsBuiltInAnthropic',
type: 'multiOptions',
optional: true,
options: [
{
label: 'Web Search',
name: 'web_search_20250305',
description: 'Search the web for the latest information'
},
{
label: 'Web Fetch',
name: 'web_fetch_20250910',
description: 'Retrieve full content from specified web pages'
}
/*
* Not supported yet as we need to get bash_code_execution_tool_result from content:
https://docs.claude.com/en/docs/agents-and-tools/tool-use/code-execution-tool#retrieve-generated-files
{
label: 'Code Interpreter',
name: 'code_execution_20250825',
description: 'Write and run Python code in a sandboxed environment'
}*/
],
show: {
agentModel: 'chatAnthropic'
}
},
{
label: 'Tools',
name: 'agentTools',
@@ -803,6 +832,43 @@ class Agent_Agentflow implements INode {
}
}
const agentToolsBuiltInAnthropic = convertMultiOptionsToStringArray(nodeData.inputs?.agentToolsBuiltInAnthropic)
if (agentToolsBuiltInAnthropic && agentToolsBuiltInAnthropic.length > 0) {
for (const tool of agentToolsBuiltInAnthropic) {
// split _ to get the tool name by removing the last part (date)
const toolName = tool.split('_').slice(0, -1).join('_')
if (tool === 'code_execution_20250825') {
;(llmNodeInstance as any).clientOptions = {
defaultHeaders: {
'anthropic-beta': ['code-execution-2025-08-25', 'files-api-2025-04-14']
}
}
}
if (tool === 'web_fetch_20250910') {
;(llmNodeInstance as any).clientOptions = {
defaultHeaders: {
'anthropic-beta': ['web-fetch-2025-09-10']
}
}
}
const builtInTool: ICommonObject = {
type: tool,
name: toolName
}
;(toolsInstance as any).push(builtInTool)
;(availableTools as any).push({
name: tool,
toolNode: {
label: tool,
name: tool
}
})
}
}
if (llmNodeInstance && toolsInstance.length > 0) {
if (llmNodeInstance.bindTools === undefined) {
throw new Error(`Agent needs to have a function calling capable models.`)
@@ -1659,6 +1725,10 @@ class Agent_Agentflow implements INode {
}> {
// Track total tokens used throughout this process
let totalTokens = response.usage_metadata?.total_tokens || 0
const usedTools: IUsedTool[] = []
let sourceDocuments: Array<any> = []
let artifacts: any[] = []
let isWaitingForHumanInput: boolean | undefined
if (!response.tool_calls || response.tool_calls.length === 0) {
return { response, usedTools: [], sourceDocuments: [], artifacts: [], totalTokens }
@@ -1669,6 +1739,24 @@ class Agent_Agentflow implements INode {
sseStreamer.streamCalledToolsEvent(chatId, JSON.stringify(response.tool_calls))
}
// Remove tool calls with no id
const toBeRemovedToolCalls = []
for (let i = 0; i < response.tool_calls.length; i++) {
const toolCall = response.tool_calls[i]
if (!toolCall.id) {
toBeRemovedToolCalls.push(toolCall)
usedTools.push({
tool: toolCall.name || 'tool',
toolInput: toolCall.args,
toolOutput: response.content
})
}
}
for (const toolCall of toBeRemovedToolCalls) {
response.tool_calls.splice(response.tool_calls.indexOf(toolCall), 1)
}
// Add LLM response with tool calls to messages
messages.push({
id: response.id,
@@ -1678,11 +1766,6 @@ class Agent_Agentflow implements INode {
usage_metadata: response.usage_metadata
})
const usedTools: IUsedTool[] = []
let sourceDocuments: Array<any> = []
let artifacts: any[] = []
let isWaitingForHumanInput: boolean | undefined
// Process each tool call
for (let i = 0; i < response.tool_calls.length; i++) {
const toolCall = response.tool_calls[i]
@@ -1826,6 +1909,17 @@ class Agent_Agentflow implements INode {
}
}
if (response.tool_calls.length === 0) {
const responseContent = typeof response.content === 'string' ? response.content : JSON.stringify(response.content, null, 2)
return {
response: new AIMessageChunk(responseContent),
usedTools,
sourceDocuments,
artifacts,
totalTokens
}
}
// Get LLM response after tool calls
let newResponse: AIMessageChunk
@@ -1925,6 +2019,10 @@ class Agent_Agentflow implements INode {
isWaitingForHumanInput?: boolean
}> {
let llmNodeInstance = llmWithoutToolsBind
const usedTools: IUsedTool[] = []
let sourceDocuments: Array<any> = []
let artifacts: any[] = []
let isWaitingForHumanInput: boolean | undefined
const lastCheckpointMessages = humanInputAction?.data?.input?.messages ?? []
if (!lastCheckpointMessages.length) {
@@ -1950,6 +2048,24 @@ class Agent_Agentflow implements INode {
sseStreamer.streamCalledToolsEvent(chatId, JSON.stringify(response.tool_calls))
}
// Remove tool calls with no id
const toBeRemovedToolCalls = []
for (let i = 0; i < response.tool_calls.length; i++) {
const toolCall = response.tool_calls[i]
if (!toolCall.id) {
toBeRemovedToolCalls.push(toolCall)
usedTools.push({
tool: toolCall.name || 'tool',
toolInput: toolCall.args,
toolOutput: response.content
})
}
}
for (const toolCall of toBeRemovedToolCalls) {
response.tool_calls.splice(response.tool_calls.indexOf(toolCall), 1)
}
// Add LLM response with tool calls to messages
messages.push({
id: response.id,
@@ -1959,11 +2075,6 @@ class Agent_Agentflow implements INode {
usage_metadata: response.usage_metadata
})
const usedTools: IUsedTool[] = []
let sourceDocuments: Array<any> = []
let artifacts: any[] = []
let isWaitingForHumanInput: boolean | undefined
// Process each tool call
for (let i = 0; i < response.tool_calls.length; i++) {
const toolCall = response.tool_calls[i]
+1 -1
View File
@@ -42,7 +42,7 @@
"@google-cloud/storage": "^7.15.2",
"@google/generative-ai": "^0.24.0",
"@huggingface/inference": "^2.6.1",
"@langchain/anthropic": "0.3.14",
"@langchain/anthropic": "0.3.29",
"@langchain/aws": "^0.1.11",
"@langchain/baidu-qianfan": "^0.1.0",
"@langchain/cohere": "^0.0.7",
@@ -25,7 +25,8 @@ import {
IconCode,
IconWorldWww,
IconPhoto,
IconBrandGoogle
IconBrandGoogle,
IconBrowserCheck
} from '@tabler/icons-react'
import StopCircleIcon from '@mui/icons-material/StopCircle'
import CancelIcon from '@mui/icons-material/Cancel'
@@ -154,6 +155,17 @@ const AgentFlowNode = ({ data }) => {
}
}
const getBuiltInAnthropicToolIcon = (toolName) => {
switch (toolName) {
case 'web_search_20250305':
return <IconWorldWww size={14} color={'white'} />
case 'web_fetch_20250910':
return <IconBrowserCheck size={14} color={'white'} />
default:
return null
}
}
useEffect(() => {
if (ref.current) {
setTimeout(() => {
@@ -455,6 +467,16 @@ const AgentFlowNode = ({ data }) => {
: [],
toolProperty: 'builtInTool',
isBuiltInGemini: true
},
{
tools: data.inputs?.agentToolsBuiltInAnthropic
? (typeof data.inputs.agentToolsBuiltInAnthropic === 'string'
? JSON.parse(data.inputs.agentToolsBuiltInAnthropic)
: data.inputs.agentToolsBuiltInAnthropic
).map((tool) => ({ builtInTool: tool }))
: [],
toolProperty: 'builtInTool',
isBuiltInAnthropic: true
}
]
@@ -541,6 +563,32 @@ const AgentFlowNode = ({ data }) => {
]
}
// Handle built-in Anthropic tools with icons
if (config.isBuiltInAnthropic) {
const icon = getBuiltInAnthropicToolIcon(toolName)
if (!icon) return []
return [
<Box
key={`tool-${configIndex}-${toolIndex}`}
sx={{
width: 20,
height: 20,
borderRadius: '50%',
backgroundColor: customization.isDarkMode
? darken(data.color, 0.5)
: darken(data.color, 0.2),
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
padding: 0.2
}}
>
{icon}
</Box>
]
}
return [
<Box
key={`tool-${configIndex}-${toolIndex}`}
+53 -49
View File
File diff suppressed because one or more lines are too long