AIX: Anthropic: Parser: hotfix for 4.6 to elide the double-newline at the beginning when present

This commit is contained in:
Enrico Ros
2026-02-09 04:40:14 -08:00
parent 4b166120e6
commit 83161bbe98
@@ -15,7 +15,20 @@ const ANTHROPIC_DEBUG_EVENT_SEQUENCE = false; // true: shows the sequence of eve
// NOTE: the following weakens protocol validation - remove if possible. testing with web search active to see if blocks come out of order
const ANTHROPIC_FIX_REUSED_BLOCK_INDEX = true; // [Anthropic, 2026-01-12] Block Start Index issue workaround
const hotFixAntInjectToolsTextSpacer = true; // FIXME: check if this is still needed with 4.6
/**
* [Anthropic, Opus-4.6] First text packet is '\n\n' - elide it
*
* NOTE: disabled because the sequence seems:
* {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}
* {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"\\n\\n"}
* {"type":"content_block_stop","index":0 }
*/
const hotFixAntElideLeadingDoubleNewline = false;
/**
* This was needed because tools and text were too close together
* FIXME: check if this is still needed with 4.6
*/
const hotFixAntInjectToolsTextSpacer = true;
/**
@@ -68,6 +81,14 @@ export function createAnthropicMessageParser(): ChatGenerateParseFunction {
let chatInTokens: number | undefined = undefined;
let needsTextSeparator = false; // insert text separator when text follows server tool
let elideFirstTextBlock = hotFixAntElideLeadingDoubleNewline;
const elisionCheck = (fullText: string) => {
elideFirstTextBlock = false;
if (fullText !== '\n\n') return false;
console.log('[DEV] Anthropic: 🔷 Eliding leading \\n\\n text block');
return true;
};
return function(pt: IParticleTransmitter, eventData: string, eventName?: string, context?: { retriesAvailable: boolean }): void {
// Time to first event
@@ -170,6 +191,8 @@ export function createAnthropicMessageParser(): ChatGenerateParseFunction {
switch (content_block.type) { // .content_block_start.type
case 'text':
// Hotfix Opus-4.6: elide first text block if it's '\n\n'
if (elisionCheck(content_block.text)) break;
// add separator when text follows server tool execution
pt.appendText(!needsTextSeparator ? content_block.text : '\n\n' + content_block.text);
needsTextSeparator = false;
@@ -428,6 +451,8 @@ export function createAnthropicMessageParser(): ChatGenerateParseFunction {
switch (delta.type) {
case 'text_delta':
if (contentBlock.type === 'text') {
// Hotfix Opus-4.6: elide first text block if it's '\n\n'
if (elisionCheck(delta.text)) break;
contentBlock.text += delta.text;
pt.appendText(delta.text);
} else
@@ -603,6 +628,14 @@ export function createAnthropicMessageParserNS(): ChatGenerateParseFunction {
const parserCreationTimestamp = Date.now();
let needsTextSeparator = false; // insert text separator when text follows server tool
let elideFirstTextBlock = hotFixAntElideLeadingDoubleNewline;
const elisionCheck = (fullText: string) => {
elideFirstTextBlock = false;
if (fullText !== '\n\n') return false;
console.log('[DEV] Anthropic: 🔷 Eliding leading \\n\\n text block');
return true;
};
return function(pt: IParticleTransmitter, fullData: string /*, eventName?: string, context?: { retriesAvailable: boolean } */): void {
// parse with validation (e.g. type: 'message' && role: 'assistant')
@@ -623,6 +656,8 @@ export function createAnthropicMessageParserNS(): ChatGenerateParseFunction {
const isLastBlock = i === content.length - 1;
switch (contentBlock.type) { // .content_block (non-streaming)
case 'text':
// Hotfix Opus-4.6: elide first text block if it's '\n\n'
if (elisionCheck(contentBlock.text)) break;
// add separator when text follows server tool execution
pt.appendText(!needsTextSeparator ? contentBlock.text : '\n\n' + contentBlock.text);
needsTextSeparator = false;