opencode icon indicating copy to clipboard operation
opencode copied to clipboard

fix(opencode): coerce stringified JSON arrays/objects in tool parameters

Open crottolo opened this issue 5 days ago • 1 comments

Fixes #7512

Problem

LLMs sometimes send tool parameters as strings instead of proper typed values:

{ "todos": "[{...}]" }    // string instead of array
{ "timeout": "180000" }   // string instead of number  
{ "enabled": "true" }     // string instead of boolean

This causes Zod validation to fail with expected X, received string.

Solution

Added automatic coercion in Tool.define():

  1. First attempt normal validation with safeParse
  2. If fails with type error, coerce string values:
    • [ or { prefix → JSON.parse() for arrays/objects
    • Numeric string → Number() for numbers
    • "true"/"false" → boolean conversion
  3. Retry validation with coerced values
  4. If still fails, throw original error (backward compatible)

Verification

Tested all affected tools:

✅ Bash (timeout: number)
✅ Todowrite (todos: array)
✅ Webfetch (timeout: number)
✅ Websearch (numResults: number)
✅ LSP tools (line, character: number)
✅ Read (offset, limit: number)
✅ Normal typed values still work unchanged

Scope

  • 10+ tools affected: Bash, Todowrite, Question, Webfetch, Websearch, LSP, Edit, Multiedit, etc.
  • All providers: Anthropic, OpenAI, Google, etc.
  • Backward compatible: Yes

crottolo avatar Jan 09 '26 18:01 crottolo