fix: sanitize tool-call inputs to prevent LiteLLM invalid dict error (#2890)
should fix #2879.
## Summary
- Add defensive sanitization ensuring tool-call `input` fields are
always valid objects (at minimum `{}`) before messages reach the
Anthropic API
- Prevents LiteLLM from sending empty strings as `tool_use.input` when
converting OpenAI→Anthropic format, which causes `400
invalid_request_error: Input should be a valid dictionary`
- Adds sanitization in two locations: `cleanMessageForOpenAI` (stored
messages) and `maybeCaptureRetryReplayEvent` (stream replay events)
## Context
This is a known LiteLLM bug pattern (issues
[#5063](https://github.com/BerriAI/litellm/issues/5063),
[#15322](https://github.com/BerriAI/litellm/issues/15322),
[#19061](https://github.com/BerriAI/litellm/issues/19061)). When
`function.arguments` is empty or malformed, LiteLLM's `json.loads()`
fails and falls back to passing the raw string as `input`, which
Anthropic rejects.
## Test plan
- [x] Added 3 new unit tests for `cleanMessageForOpenAI` covering empty
string, null, and valid inputs
- [x] All 847 existing tests pass
- [x] Lint, format, and type checks pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- devin-review-badge-begin -->
---
<a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2890"
target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
</picture>
</a>
<!-- devin-review-badge-end -->
---------
Co-authored-by:
Will Chen <willchen90@gmail.com>
Co-authored-by:
Claude Opus 4.6 <noreply@anthropic.com>
正在显示
请
注册
或者
登录
后发表评论