Skip to content

fix(provider): ensure non-empty assistant content for openai-compatible (#33280) - #33899

Closed
Haohao-end wants to merge 1 commit into
anomalyco:devfrom
Haohao-end:non-empty-assistant-content
Closed

fix(provider): ensure non-empty assistant content for openai-compatible (#33280)#33899
Haohao-end wants to merge 1 commit into
anomalyco:devfrom
Haohao-end:non-empty-assistant-content

Conversation

@Haohao-end

@Haohao-end Haohao-end commented Jun 25, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #33280

Type of change

  • Bug fix

What does this PR do?

When an assistant message contains only tool calls (no text), the Vercel AI SDK emits content: "" on the wire. OpenAI-compatible proxies (e.g. GLM-5.2 via api.svips.org) sanitise empty content by injecting a visible placeholder — [System: Empty message content sanitised to satisfy protocol] — which then leaks into the stored conversation on every tool-call turn.

The fix adds a targeted transform for @ai-sdk/openai-compatible that prepends a single-space text part to assistant messages that have tool-call parts but no non-empty text part. This keeps the wire content non-empty so the proxy passes it through unchanged. The space is ephemeral — it only exists in the messages handed to the provider, not in persisted session history.

How did you verify your code works?

Added 4 regression tests in test/provider/transform.test.ts:

  1. Tool-call-only assistant message gets a space text part prepended
  2. Assistant message with existing text is unchanged
  3. Non-assistant messages are unchanged
  4. Fix does not apply to non-openai-compatible providers

All 4 tests pass. Existing anthropic/bedrock empty-content tests unchanged (9/9 pass). Typecheck clean.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…le (anomalyco#33280)

When an assistant message carries only tool calls the Vercel AI SDK emits
content: "" on the wire. Proxies that sit between opencode and the upstream
LLM (e.g. GLM-5.2 gateways) sanitise empty content by injecting a visible
placeholder — "[System: Empty message content sanitised to satisfy protocol]"
— which then leaks into the stored conversation on every tool-call turn.

The fix prepends a single-space text part to assistant messages that have
tool-call parts but no non-empty text part, but only for @ai-sdk/openai-compatible
providers. This keeps the wire content non-empty without altering the model's
intent or touching persisted session history.
@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels Jun 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@codeg-dev

Copy link
Copy Markdown

Heads-up: related PR #38270 (for #37946) overlaps with this one — analysis posted at #38270 (comment).

Short version: this PR's !hasToolCall early-return does not cover assistant messages with no tool calls and no text (e.g. an aborted reasoning-only turn, which is #37946's exact failing shape — strict providers 400 the replayed request and brick the session). #38270 covers that case as well as the tool-call-only case handled here. Both PRs use the same single-space technique at different layers (here: ProviderTransform.message; there: a post-pass in toModelMessagesEffect). Consolidating into one guard — this location with the hasToolCall requirement dropped, or #38270's layer — would avoid maintaining two near-identical transforms. Happy to align with whichever direction maintainers prefer.

@github-actions

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[regression] [System: Empty message content sanitised to satisfy protocol] still appears with GLM-5.2 via OpenAI-compatible provider

2 participants