Skip to content

Commit 01354f4

Browse files
committed
LLMs: Anthropic: sync proto
1 parent 489e327 commit 01354f4

4 files changed

Lines changed: 65 additions & 13 deletions

File tree

src/modules/aix/server/dispatch/chatGenerate/adapters/anthropic.messageCreate.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function aixAnthropicHostedFeatures(model: AixAPI_Model, chatGenerate: Ai
3434
const _hasAixCustomTools = chatGenerate.tools?.some(t => t.type === 'function_call');
3535
const _hasAixToolRestrictivePolicy = chatGenerate.toolsPolicy?.type === 'any' || chatGenerate.toolsPolicy?.type === 'function_call';
3636

37-
// Dynamic web tools (20260209) require code execution for programmatic tool calling
37+
// Dynamic web tools (20260318, was 20260209) require code execution for programmatic tool calling
3838
// const hasDynamicWebTools = model.vndAntWebDynamic === true && (model.vndAntWebSearch === 'auto' || model.vndAntWebFetch === 'auto');
3939

4040
// Programmatic Tool Calling - tools with allowed_callers or input_examples
@@ -49,7 +49,7 @@ export function aixAnthropicHostedFeatures(model: AixAPI_Model, chatGenerate: Ai
4949
// three ways, all converging on ONE explicit container: the standalone Code Sandbox toggle (a
5050
// general-purpose hosted-container sandbox), Skills (which run inside the container), and Programmatic Tool Calling
5151
// (which uses the container as its script executor).
52-
// Dynamic web tools (_20260209) have their OWN internal code execution. We never AUTO-enable the
52+
// Dynamic web tools (_20260318, was _20260209) have their OWN internal code execution. We never AUTO-enable the
5353
// standalone tool from them (#1087: a 2nd implicit environment is parasitic), nor from container
5454
// continuity alone. We DO honor an explicit user toggle even alongside dynamic web: Anthropic's
5555
// docs note this can create two execution environments that may confuse the model (mitigable via
@@ -285,10 +285,11 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
285285
if (!disableAllHostedTools) {
286286
const hostedTools: NonNullable<TRequest['tools']> = [];
287287

288-
// Web Search Tool - dynamic filtering (20260209) uses internal code execution for better results
288+
// Web Search Tool - dynamic filtering (20260318, supersedes 20260209) uses internal code execution for better results.
289+
// response_inclusion intentionally left unset (defaults to 'full') - unchanged behavior, see _WebSearchTool_20260318_schema.
289290
if (model.vndAntWebSearch === 'auto') {
290291
hostedTools.push({
291-
type: model.vndAntWebDynamic ? 'web_search_20260209' : 'web_search_20250305',
292+
type: model.vndAntWebDynamic ? 'web_search_20260318' : 'web_search_20250305',
292293
name: 'web_search',
293294
...(model.vndAntWebSearchMaxUses !== undefined ? { max_uses: model.vndAntWebSearchMaxUses } : {}),
294295
...(model.userGeolocation ? {
@@ -297,10 +298,11 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
297298
});
298299
}
299300

300-
// Web Fetch Tool - dynamic filtering (20260209) uses internal code execution for better results
301+
// Web Fetch Tool - dynamic filtering (20260318, supersedes 20260209/20260309) uses internal code execution for better results.
302+
// response_inclusion intentionally left unset (defaults to 'full') - unchanged behavior, see _WebFetchTool_20260318_schema.
301303
if (model.vndAntWebFetch === 'auto') {
302304
hostedTools.push({
303-
type: model.vndAntWebDynamic ? 'web_fetch_20260209' : 'web_fetch_20250910',
305+
type: model.vndAntWebDynamic ? 'web_fetch_20260318' : 'web_fetch_20250910',
304306
name: 'web_fetch',
305307
...(model.vndAntWebFetchMaxUses !== undefined ? { max_uses: model.vndAntWebFetchMaxUses } : {}),
306308
citations: { enabled: true },
@@ -320,10 +322,11 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
320322
});
321323

322324
// Code execution tool (Anthropic's) - added for the Code Sandbox toggle, Skills, container reuse, and Programmatic Tool Calling.
323-
// Not AUTO-added for dynamic web tools (_20260209) which execute code internally; an explicit user
325+
// Not AUTO-added for dynamic web tools (_20260318, was _20260209) which execute code internally; an explicit user
324326
// toggle may still coexist with them by design (see aixAnthropicHostedFeatures note re #1087).
325327
// Keep _20260120: it matches the code execution version dynamic web auto-injects, so coexisting
326-
// merges into ONE environment. An older version (e.g. _20250825) 400s: 'tool names must be unique'.
328+
// merges into ONE environment (re-verified empirically on _20260318: caller.type is still 'code_execution_20260120').
329+
// An older version (e.g. _20250825) 400s: 'tool names must be unique'.
327330
if (enableCodeExecution)
328331
hostedTools.push({ type: 'code_execution_20260120', name: 'code_execution' });
329332

@@ -334,7 +337,7 @@ export function aixToAnthropicMessageCreate(model: AixAPI_Model, _chatGenerate:
334337
}
335338

336339
// --- Container continuity between calls ---
337-
// Re-attaching the container is DECOUPLED from enableCodeExecution: dynamic web tools (_20260209)
340+
// Re-attaching the container is DECOUPLED from enableCodeExecution: dynamic web tools (_20260318, was _20260209)
338341
// use a container internally, and the API accepts a `container` alongside them WITHOUT the standalone
339342
// code_execution tool (empirically verified). So we keep ONE sandbox across mixed search/skills/code
340343
// turns - a file written by code execution survives an intervening search turn (verified: ls /tmp). This

src/modules/aix/server/dispatch/chatGenerate/parsers/anthropic.parser.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ const hotFixAntInjectToolsTextSpacer = true;
7474
* - Message Deltas will provide a 'stop reason' on the message
7575
* - Begin/End are explicit
7676
*/
77+
78+
// TODO (tracked, not implemented): Anthropic GA'd "mid-conversation system messages" 2026-05-28 (Opus 4.8 only so far) -
79+
// a `{role: 'system'}` message can be appended mid-`messages` (must immediately follow a user/tool-result turn, and
80+
// either end the array or precede an assistant turn) to inject operator-priority instructions without invalidating the
81+
// cached prefix - unlike editing the top-level `system` field, which busts the cache for everything after it. This is a
82+
// REQUEST-construction feature (would live in anthropic.messageCreate.ts's per-message content-block generator, not
83+
// here) - noted in this file as the spot we track Anthropic protocol deltas pending wider model support past Opus 4.8.
84+
// See: https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages
85+
7786
export function createAnthropicMessageParser(): ChatGenerateParseFunction {
7887
const parserCreationTimestamp = Date.now();
7988
let responseMessage: AnthropicWire_API_Message_Create.Response;

src/modules/aix/server/dispatch/wiretypes/anthropic.wiretypes.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ const hotFixAntShipNoEmptyTextBlocks = true; // Replace empty text blocks with a
1313
*
1414
* ## Updates
1515
*
16+
* ### 2026-06-30 - API Sync: new tool versions, refusal categories, Sonnet 5 verified
17+
* - Tools: Added web_search_20260318 / web_fetch_20260318 (GA, 2026-06-11) - adds `response_inclusion` ('full'|'excluded')
18+
* to drop the nested search/fetch call+result pair from the response once consumed by a completed code-execution call
19+
* (dynamic filtering). Wired as the new default for the dynamic-filtering path (replacing _20260209); `response_inclusion`
20+
* left unset (defaults to 'full') - this is purely the version bump, no behavior change.
21+
* - StopDetails.category: added 'frontier_llm', 'military_weapons' (current docs list these alongside 'cyber'/'bio'/'reasoning_extraction')
22+
* - Verified empirically against the live API: Claude Sonnet 5 (launched 2026-06-29) breaking changes (temperature/top_p/top_k
23+
* rejected, manual thinking budget rejected, but thinking.disabled and forced tool_choice both OK unlike Fable/Mythos 5) -
24+
* existing adapter logic already handles all of these correctly via LLM_IF_HOTFIX_NoTemperature + per-model thinking-budget plumbing.
25+
* - NOT adopted (tracked in anthropic.parser.ts top comment): mid-conversation system messages (role: 'system', Opus 4.8
26+
* only, GA 2026-05-28) - appends operator-priority instructions mid-`messages` without invalidating the cached prefix.
27+
*
1628
* ### 2026-06-09 - API Sync: Claude Fable 5 / Mythos 5, forward-compatible parsing
1729
* - StopDetails.category: added 'reasoning_extraction' (Fable 5 ToS classifier for reverse engineering / output duplication)
1830
* - StopDetails: added `recommended_model` (suggested retry model when a server-side fallback could not run)
@@ -802,6 +814,18 @@ export namespace AnthropicWire_Tools {
802814
use_cache: z.boolean().optional(), // default true; set false to bypass cache and fetch fresh content
803815
});
804816

817+
/**
818+
* [Anthropic, 2026-06-11 GA] Latest - adds `response_inclusion`.
819+
* When the fetch was called programmatically from a completed code-execution call (dynamic filtering), 'excluded'
820+
* drops the nested server_tool_use(web_fetch) + web_fetch_tool_result pair from the response entirely (verified
821+
* empirically: ~98% response size reduction on a full page fetch). Default 'full' (unchanged from prior versions).
822+
* Direct calls, or code-execution calls that paused before completing, are always returned in full regardless.
823+
*/
824+
const _WebFetchTool_20260318_schema = _WebFetchTool_20260309_schema.extend({
825+
type: z.literal('web_fetch_20260318'),
826+
response_inclusion: z.enum(['full', 'excluded']).optional(), // default: 'full'
827+
});
828+
805829
// -- Web Search Tools --
806830

807831
const _WebSearchTool_20250305_schema = _ToolDefinitionBase_schema.extend({
@@ -813,11 +837,17 @@ export namespace AnthropicWire_Tools {
813837
user_location: z.any().nullish(), // UserLocation schema
814838
});
815839

816-
/** [Anthropic, Feb 2026 GA] Web search v2 - latest. */
840+
/** [Anthropic, Feb 2026 GA] Web search v2. */
817841
const _WebSearchTool_20260209_schema = _WebSearchTool_20250305_schema.extend({
818842
type: z.literal('web_search_20260209'),
819843
});
820844

845+
/** [Anthropic, 2026-06-11 GA] Latest - adds `response_inclusion`, see _WebFetchTool_20260318_schema for semantics. */
846+
const _WebSearchTool_20260318_schema = _WebSearchTool_20260209_schema.extend({
847+
type: z.literal('web_search_20260318'),
848+
response_inclusion: z.enum(['full', 'excluded']).optional(), // default: 'full'
849+
});
850+
821851

822852
export const ToolDefinition_schema = z.discriminatedUnion('type', [
823853
// Client-side tools
@@ -835,8 +865,10 @@ export namespace AnthropicWire_Tools {
835865
_WebFetchTool_20250910_schema,
836866
_WebFetchTool_20260209_schema,
837867
_WebFetchTool_20260309_schema,
868+
_WebFetchTool_20260318_schema,
838869
_WebSearchTool_20250305_schema,
839870
_WebSearchTool_20260209_schema,
871+
_WebSearchTool_20260318_schema,
840872
]);
841873

842874
}
@@ -878,7 +910,7 @@ export namespace AnthropicWire_API_Message_Create {
878910
*/
879911
const StopDetails_schema = z.object({
880912
type: z.enum(['refusal']).or(z.string()),
881-
category: z.enum(['cyber', 'bio', 'reasoning_extraction']).or(z.string()).nullish(),
913+
category: z.enum(['cyber', 'bio', 'reasoning_extraction', 'frontier_llm', 'military_weapons']).or(z.string()).nullish(),
882914
explanation: z.string().nullish(),
883915
/** [Anthropic, 2026-06-09] Model suggested for a direct retry when a server-side fallback could not run (e.g. fallback model rate-limited). Hint only, may be null. */
884916
recommended_model: z.string().nullish(),

src/modules/llms/server/anthropic/anthropic.models.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ const _hardcodedAnthropicThinkingVariants: ModelVariantMap & { [id: string]: { i
114114
parameterSpecs: [
115115
{ paramId: 'llmVndAntThinkingBudget', hidden: true, initialValue: -1 /* FORCE adaptive - 4.7 rejects budget_tokens */ },
116116
{ paramId: 'llmVndAntEffort', enumValues: ['low', 'medium', 'high', 'xhigh', 'max'] },
117+
// TODO 2026-07-24: fast mode deprecated 2026-06-25, HARD REMOVAL on this date - speed:'fast' will then return
118+
// an error (unlike Opus 4.6's silent no-op removal). Drop 'fast_6x' here once removed; migrate users to Opus 4.8.
117119
{ paramId: 'llmVndAntInfSpeed', enumValues: ['fast_6x'] },
118120
...ANT_TOOLS_DYNAMIC,
119121
],
@@ -129,7 +131,9 @@ const _hardcodedAnthropicThinkingVariants: ModelVariantMap & { [id: string]: { i
129131
parameterSpecs: [
130132
{ paramId: 'llmVndAntThinkingBudget', hidden: true, initialValue: -1 /* FORCE adaptive */ },
131133
{ paramId: 'llmVndAntEffort', enumValues: ['low', 'medium', 'high', 'max'] },
132-
{ paramId: 'llmVndAntInfSpeed', enumValues: ['fast_6x'] }, // fast mode deprecated 2026-05-28, removal ~30d later
134+
// fast mode REMOVED by Anthropic 2026-06-29: speed:'fast' no longer errors, but silently runs at standard
135+
// speed/price (no usage.speed field to detect this client-side - see anthropic.wiretypes.ts). Toggle dropped
136+
// here so the UI doesn't advertise a dead control. If Anthropic restores it, re-add 'fast_6x'.
133137
...ANT_TOOLS_DYNAMIC,
134138
],
135139
benchmark: { cbaElo: 1502 }, // claude-opus-4-6-thinking
@@ -364,6 +368,8 @@ export const hardcodedAnthropicModels = llmsDefineModels<_AnthropicModelDef>()([
364368
interfaces: [...IF_47, LLM_IF_ANT_ToolsSearch],
365369
parameterSpecs: [
366370
{ paramId: 'llmVndAntEffort', enumValues: ['low', 'medium', 'high', 'xhigh', 'max'] },
371+
// TODO 2026-07-24: fast mode deprecated 2026-06-25, HARD REMOVAL on this date - speed:'fast' will then return
372+
// an error (unlike Opus 4.6's silent no-op removal). Drop 'fast_6x' here once removed; migrate users to Opus 4.8.
367373
{ paramId: 'llmVndAntInfSpeed', enumValues: ['fast_6x'] }, // fast mode: research preview since 2026-05-12, Anthropic API only (6x tier, $30/$150)
368374
...ANT_TOOLS_DYNAMIC,
369375
],
@@ -385,7 +391,9 @@ export const hardcodedAnthropicModels = llmsDefineModels<_AnthropicModelDef>()([
385391
interfaces: [...IF_4, LLM_IF_ANT_ToolsSearch],
386392
parameterSpecs: [
387393
{ paramId: 'llmVndAntEffort', enumValues: ['low', 'medium', 'high', 'max'] },
388-
{ paramId: 'llmVndAntInfSpeed', enumValues: ['fast_6x'] }, // fast mode deprecated 2026-05-28, removal ~30d later
394+
// fast mode REMOVED by Anthropic 2026-06-29: speed:'fast' no longer errors, but silently runs at standard
395+
// speed/price (no usage.speed field to detect this client-side - see anthropic.wiretypes.ts). Toggle dropped
396+
// here so the UI doesn't advertise a dead control. If Anthropic restores it, re-add 'fast_6x'.
389397
...ANT_TOOLS_DYNAMIC,
390398
],
391399
// Opus 4.6: flat $5/$25 pricing (1M context GA at standard pricing since 2026-03-13, no opt-in required)

0 commit comments

Comments
 (0)