You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Request sanitizing strips membrane's zero-width carriers, so Responses compaction and hosted-call items are never sent again #320
buildActivationRequest strips every text block whose text is empty or whitespace before a request goes out (src/agent.ts:835, predicate at :852, at c2f9baee; added in 8a89da09 for Anthropic's 400 on empty text blocks). That also strips membrane's zero-width carriers. These are { type: 'text', text: '', rawItem } blocks that membrane stores for provider items with no content-block equivalent:
Responses: a compaction or a hosted tool's call (parseProviderContent, membrane 0.5.86 src/membrane.ts ~1887–1903).
Anthropic: a server_tool_use and other block types membrane doesn't convert (preserveUnconvertibleBlock in providers/anthropic.ts ~1127; parseProviderContent's text branch keeps the rawItem).
membrane's formatters already treat these carriers by provider:
The Responses formatter replays each block's rawItem as an input item, deduplicated per message (formatters/openai-responses.ts).
The native formatter skips an exactly-empty text block itself, with a comment naming these carriers (formatters/native.ts, convertContent).
The XML formatter joins a message's text parts, so a carrier adds nothing there (formatters/anthropic-xml.ts, extractContent).
So on a host that uses membrane's Responses formatter, the compaction and hosted-call items a model returned never reach the provider again. The provider then loses whatever the compaction item stood for. Anthropic-bound requests are unaffected, since both Anthropic formatters already handle the carriers.
One way to fix it: let a text block that carries a rawItem through the sanitize. A whitespace-only plain text block still needs stripping there, since the native formatter drops only exactly-empty text. A test could build a history with a zero-width carrier and a whitespace-only plain block, and assert that the carrier reaches the formatter's input while the plain block is stripped.
Not checked: the chat-completions formatter and Gemini's provider, which would see a carrier only in a history that mixes providers.
Found during the review of #285, which changes code near this. I haven't run a Responses host against it.
Activity