Skip to content

fix(provider): trim whitespace and filter empty content in transformations - #7086

Closed
jerome-benoit wants to merge 38 commits into
anomalyco:devfrom
jerome-benoit:fix/provider-whitespace-trimming
Closed

fix(provider): trim whitespace and filter empty content in transformations#7086
jerome-benoit wants to merge 38 commits into
anomalyco:devfrom
jerome-benoit:fix/provider-whitespace-trimming

Conversation

@jerome-benoit

@jerome-benoitjerome-benoit commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Implement consistent whitespace trimming across all provider transformation functions to prevent API validation errors from empty or whitespace-only message content.

Changes

  • Trim all text content before length checks and assignments across all provider transformations
  • Filter out whitespace-only messages and parts to prevent empty content from reaching APIs
  • Two-phase filter+map approach in normalizeMessages for consistent handling
  • Preserve tool results and streaming deltas without modification (whitespace may be significant)
  • Add 65 comprehensive tests for whitespace handling scenarios

Affected Files

FileChangesDescription
anthropic.ts44 changesTrim content in all Anthropic transformations
openai.ts42 changesTrim content in all OpenAI transformations
openai-compatible.ts32 changesTrim content in OpenAI-compatible transformations
transform.ts31 changesUpdate normalizeMessages with two-phase filtering
transform.test.ts91 additionsComprehensive test coverage

Total: 5 files changed, 184 insertions(+), 56 deletions(-)

Why This Change?

APIs like Anthropic and OpenAI reject requests with empty or whitespace-only text content, causing validation errors. This change ensures all text content is trimmed and empty parts are filtered before being sent to providers.

Testing

✅ All 65 tests pass, covering:

  • Whitespace-only content filtering
  • Leading/trailing whitespace trimming
  • Empty array handling
  • Tool result preservation
  • Mixed content scenarios
  • Streaming delta preservation

Pattern Applied

// Beforeif(content.length>0){parts.push({type: "text",text: content})}// After constt=content.trim()if(t.length>0){parts.push({type: "text",text: t})}

Closes#8903
Closes#8679

…tions
Implement consistent whitespace trimming across all provider transformation
functions (Anthropic, OpenAI, OpenAI-compatible) to prevent API validation
errors from empty or whitespace-only message content.
- Trim all text content before length checks and assignments
- Filter out whitespace-only messages and parts
- Preserve tool results and streaming deltas without modification
- Add 65 comprehensive tests for whitespace handling
5 files changed: 184 insertions(+), 56 deletions(-)
CopilotAI review requested due to automatic review settings January 6, 2026 13:38
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

No duplicate PRs found

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements comprehensive whitespace handling across all provider transformation functions to prevent API validation errors from empty or whitespace-only message content. The changes ensure that all text content is trimmed before being sent to provider APIs (Anthropic, OpenAI, and OpenAI-compatible providers), while carefully preserving tool results and streaming deltas where whitespace may be semantically significant.

Key changes:

  • Two-phase filter+map approach in normalizeMessages that first removes whitespace-only parts, then trims remaining text
  • Consistent trimming of all text content in request transformations across all three provider implementations
  • 65 new tests covering whitespace filtering, trimming, and edge cases

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
transform.test.tsAdds 65 comprehensive tests for whitespace-only content filtering, leading/trailing whitespace trimming, empty array handling, and mixed content scenarios
transform.tsUpdates normalizeMessages with two-phase filtering approach: filters out whitespace-only text/reasoning parts, then trims remaining text content
openai.tsAdds .trim() checks and trimming to all text content in fromOpenaiRequest, toOpenaiRequest, and toOpenaiResponse; preserves tool results and streaming deltas
openai-compatible.tsApplies consistent trimming pattern to fromOaCompatibleRequest, toOaCompatibleRequest, and fromOaCompatibleResponse
anthropic.tsImplements trimming across fromAnthropicRequest, toAnthropicRequest, and toAnthropicResponse; preserves tool results without modification

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

… calls
The message() function signature was updated to require 3 arguments (msgs, model, options)
but 5 test calls were still using only 2 arguments, causing TypeScript errors.
Fixes typecheck failures in CI.
@thdxr
thdxrforce-pushed the dev branch 2 times, most recently from f1ae801 to 08fa7f7CompareJanuary 30, 2026 14:37
@fabianszabo

Copy link
Copy Markdown

For #8679: I understand that the TUI automatically submits whitespace only prompts (opencode --prompt " "), creating empty messages that get rejected by Anthropic/Bedrock. This is an input validation bug, not a transform bug. It should be fixed at the TUI/prompt submission layer.

For #8903: I understand that whitespace only content passes through transforms and hits API validation errors. The existing empty string filter in transform.ts just needs its check widened from === "" to .trim() === "". You implemented a verbose mutation that goes beyond the scope of the actual issue and needlessly mutates valid content. You could solve this so simply:

 return part.text.trim() !== ""

@jerome-benoit

Copy link
Copy Markdown
ContributorAuthor

Closing as not proper fix.

@jerome-benoit
jerome-benoit deleted the fix/provider-whitespace-trimming branch June 23, 2026 16:14
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants

@jerome-benoit@fabianszabo