Commit ef5c397
fix(tool-args): coerce JSON-encoded strings on str_replace_editor numeric args
Some local models routed through OpenAI compatible endpoints (LiteLLM,
vLLM, Ollama, etc.) emit list-typed and int-typed tool arguments as
JSON-encoded strings instead of proper structured values, e.g.
`"view_range": "[1, 50]"` rather than `"view_range": [1, 50]`. Pydantic
strict validation in pydantic-ai then rejects the call with:
ValidationError: 1 validation error for str_replace_editor
view_range
Input should be a valid array
[type=list_type, input_value='[1, 50]', input_type=str]
After the configured `max_retries` the run aborts with
`UnexpectedModelBehavior: Tool 'str_replace_editor' exceeded max retries`.
This patch adds a Pydantic `BeforeValidator` that parses a JSON-encoded
string back into its structured form before strict validation runs, on
the two args observed to fail in practice (`view_range` and
`insert_line`). The validator is a no-op when the value is already typed
correctly, so Anthropic native API users (who emit structured JSON tool
args) are unaffected.
Empirically validated: same model, same prompt, same repo, the only
change is this validator. Before patch: tool exceeds max retries on
every run. After patch: documentation generation completes successfully.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 738e0c4 commit ef5c397
1 file changed
Lines changed: 27 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
28 | 52 | | |
29 | 53 | | |
30 | 54 | | |
| |||
713 | 737 | | |
714 | 738 | | |
715 | 739 | | |
716 | | - | |
| 740 | + | |
717 | 741 | | |
718 | 742 | | |
719 | | - | |
| 743 | + | |
720 | 744 | | |
721 | 745 | | |
722 | 746 | | |
| |||
0 commit comments