AIX: Anthropic: wires: update with new API features and tools

- tools allowed callers for client and server
- all tool definitions common options
- new code_execution, web_fetch, web_search tools
- top-level cache_contol
- thinking with disabled summaries for speed
- message updates with container variants
-fix tool_search_tool results
This commit is contained in:
Enrico Ros
2026-03-21 17:35:42 -07:00
parent 0afa70aaab
commit b07fc759c2
3 changed files with 155 additions and 64 deletions
@@ -155,12 +155,14 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
if (model.vndAntThinkingBudget === 'adaptive') {
payload.thinking = {
type: 'adaptive',
// display: 'summarized', // default, use 'omitted' to not include it and stream faster while preserving the signature
};
delete payload.temperature;
} else if (model.vndAntThinkingBudget !== null) {
payload.thinking = {
type: 'enabled',
budget_tokens: model.vndAntThinkingBudget < payload.max_tokens ? model.vndAntThinkingBudget : payload.max_tokens - 1,
// display: 'summarized', // default, use 'omitted' to not include it and stream faster while preserving the signature
};
delete payload.temperature;
} else {
@@ -217,9 +219,9 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
if (model.vndAntWebSearch === 'auto') {
hostedTools.push({
type: 'web_search_20250305',
// type: 'web_search_20260209', // TODO
name: 'web_search',
...(model.vndAntWebSearchMaxUses !== undefined ? { max_uses: model.vndAntWebSearchMaxUses } : {}), // Allow up to 10 searches by default
// max_uses: model.vndAntWebSearchMaxUses ?? DEFAULT_WEB_SEARCH_MAX_USES, // Allow up to 10 searches by default
...(model.vndAntWebSearchMaxUses !== undefined ? { max_uses: model.vndAntWebSearchMaxUses } : {}),
// Pass user geolocation for location-aware search results
...(model.userGeolocation ? {
user_location: { type: 'approximate' as const, ...model.userGeolocation },
@@ -231,9 +233,9 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
if (model.vndAntWebFetch === 'auto') {
hostedTools.push({
type: 'web_fetch_20250910',
//type: 'web_fetch_20260209',
name: 'web_fetch',
...(model.vndAntWebFetchMaxUses !== undefined ? { max_uses: model.vndAntWebFetchMaxUses } : {}), // Allow up to 5 fetches by default
// max_uses: model.vndAntWebFetchMaxUses ?? DEFAULT_WEB_FETCH_MAX_USES, // Allow up to 5 fetches by default
...(model.vndAntWebFetchMaxUses !== undefined ? { max_uses: model.vndAntWebFetchMaxUses } : {}),
citations: { enabled: true }, // Enable citations
});
}
@@ -279,8 +281,8 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
if (!payload.tools?.length)
payload.tools = [];
if (!payload.tools.some(t => t.type === 'code_execution_20250825'))
payload.tools.push({ type: 'code_execution_20250825', name: 'code_execution' });
if (!payload.tools.some(t => t.type === 'code_execution_20260120' /* Beta */ || t.type === 'code_execution_20250825'))
payload.tools.push({ type: 'code_execution_20260120', name: 'code_execution' });
}
}
@@ -457,7 +459,7 @@ function _toAnthropicTools(itds: AixTools_ToolDefinition[], strictToolsEnabled:
// [Anthropic, 2025-11-24] Tool Search Tool - auto-defer all custom tools
...(toolSearchToolEnabled ? { defer_loading: true } : {}),
// [Anthropic, 2025-11-24] Programmatic Tool Calling - pass through allowed_callers and input_examples
...(allowed_callers ? { allowed_callers: allowed_callers.map(c => c === 'code_execution' ? 'code_execution_20250825' : c) } : {}),
...(allowed_callers ? { allowed_callers: allowed_callers.map(c => c === 'code_execution' ? 'code_execution_20260120' : c) } : {}),
...(input_examples ? { input_examples } : {}),
};
@@ -330,6 +330,10 @@ export function createAnthropicMessageParser(): ChatGenerateParseFunction {
file_count: fileIds.length,
file_ids: fileIds,
});
} else if (content_block.content.type === 'encrypted_code_execution_result') {
// Encrypted variant (PFC + web_search) - stdout is encrypted, show as transient placeholder
pt.sendVoidPlaceholder('code-exec', 'Code executed (encrypted output)');
console.log('[Anthropic] Encrypted code execution result:', { return_code: content_block.content.return_code });
} else if (content_block.content.type === 'code_execution_tool_result_error') {
// Error during code execution
pt.appendText(`\n\n⚠️ Skill execution error: ${content_block.content.error_code}\n`);
@@ -403,10 +407,10 @@ export function createAnthropicMessageParser(): ChatGenerateParseFunction {
// using the Files API with content_block.file_id
break;
case 'tool_result': // [Anthropic, 2025-11-24] Tool Search Tool - The actual tool definitions are auto-expanded by Anthropic's API
if (Array.isArray(content_block.content)) {
case 'tool_search_tool_result': // [Anthropic, 2025-11-24] Tool Search Tool
if (content_block.content?.type === 'tool_search_tool_search_result') {
// success
const toolNames = content_block.content.map((ref: { type: string; tool_name: string }) => ref.tool_name);
const toolNames = content_block.content.tool_references.map(ref => ref.tool_name);
pt.sendVoidPlaceholder('code-exec', `🔍 Discovered ${toolNames.length} tool(s): ${toolNames.join(', ')}`);
// Log for future debugging
console.log('[Anthropic] Tool search discovered:', { tools: toolNames });
@@ -806,6 +810,10 @@ export function createAnthropicMessageParserNS(): ChatGenerateParseFunction {
file_count: fileIds.length,
file_ids: fileIds,
});
} else if (contentBlock.content.type === 'encrypted_code_execution_result') {
// Encrypted variant (PFC + web_search) - stdout is encrypted, show as transient placeholder
pt.sendVoidPlaceholder('code-exec', 'Code executed (encrypted output)');
console.log('[Anthropic] Encrypted code execution result (non-streaming):', { return_code: contentBlock.content.return_code });
} else if (contentBlock.content.type === 'code_execution_tool_result_error') {
// Error during code execution
pt.appendText(`\n\n⚠️ Skill execution error: ${contentBlock.content.error_code}\n`);
@@ -872,16 +880,16 @@ export function createAnthropicMessageParserNS(): ChatGenerateParseFunction {
});
break;
case 'tool_result': // [Anthropic, 2025-11-24] Tool Search Tool - The actual tool definitions are auto-expanded by Anthropic's API
if (Array.isArray(contentBlock.content)) {
case 'tool_search_tool_result': // [Anthropic, 2025-11-24] Tool Search Tool
if (contentBlock.content?.type === 'tool_search_tool_search_result') {
// success
const toolNames = contentBlock.content.map((ref: { type: string; tool_name: string }) => ref.tool_name);
const toolNames = contentBlock.content.tool_references.map(ref => ref.tool_name);
pt.sendVoidPlaceholder('code-exec', `🔍 Discovered ${toolNames.length} tool(s): ${toolNames.join(', ')}`);
// Log for future debugging
console.log('[Anthropic] Tool search discovered (non-streaming):', { tools: toolNames });
} else if ((contentBlock.content as any)?.type === 'tool_search_tool_result_error') {
} else if (contentBlock.content?.type === 'tool_search_tool_result_error') {
// error during tool search
pt.sendVoidPlaceholder('code-exec', `🔍 Tool search error: ${(contentBlock.content as any).error_code}`);
pt.sendVoidPlaceholder('code-exec', `🔍 Tool search error: ${contentBlock.content.error_code}`);
}
break;