Skip to content

server: infer JSON types for GLM tool-call arguments - #729

Open
Flor1an-B wants to merge 1 commit into
antirez:mainfrom
Flor1an-B:fix-glm-tool-arg-types
Open

server: infer JSON types for GLM tool-call arguments#729
Flor1an-B wants to merge 1 commit into
antirez:mainfrom
Flor1an-B:fix-glm-tool-arg-types

Conversation

@Flor1an-B

Copy link
Copy Markdown

Fixes #569.

GLM's <arg_key>/<arg_value> wire format carries no type attribute, unlike DSML's string="true|false" that the DeepSeek path already honors. Every argument was therefore quoted as a JSON string regardless of its actual type — numbers became "10", arrays became "[]", booleans became "true". Any client that validates tool-call arguments against the tool's JSON schema (zod/ajv-style validators) rejects the call.

Fix (the heuristic option from the issue): a value that fully parses as one JSON value (number, bool, null, array, or object) with nothing left over after trimming whitespace is passed through raw instead of being quoted — reusing the same whole-string validation semantics json_minify_raw_value's existing callers already rely on for DSML's explicit string="false" path. A plain string is unaffected and still gets quoted exactly as before.

Root cause and the fix approach were identified by @solodddd in #569, including the exact repro (WebSearch with a string/number/array argument mix) that the new test is built from.

Testing: full make ds4_test suite passes. Added test_json_text_is_whole_value (the new helper in isolation) and test_parse_glm_tool_call_infers_json_value_types (the exact issue repro end-to-end through parse_generated_message_ex_for_syntax, asserting max_results and exclude_domains are now unquoted while query stays a quoted string). Updated the one pre-existing assertion that encoded the old behavior (test_parse_glm_tool_call_message expected "timeout": "10", now "timeout": 10).

GLM's <arg_key>/<arg_value> wire format carries no type attribute, unlike
DSML's string="true|false" that the DeepSeek path already honors. Every
argument was therefore quoted as a JSON string regardless of its actual
type: numbers became "10", arrays became "[]", booleans became "true".
Clients that validate tool-call arguments against the tool's JSON schema
(zod/ajv-style validators) reject the call (issue antirez#569).

Fix: a value that fully parses as one JSON value (number, bool, null,
array, or object) with nothing left over is passed through raw instead of
being quoted -- the same heuristic the report proposed and the same
whole-string validation semantics json_minify_raw_value's callers already
rely on for DSML's explicit string="false" path. A plain string still gets
quoted exactly as before.

Root cause and fix approach identified by @solodddd in antirez#569, including the
exact repro used for the new test.

Tested: full `make ds4_test` suite passes, including the exact WebSearch
repro from the issue (string/number/array argument mix) asserting the
client-visible JSON now has unquoted numbers/arrays and still-quoted
strings.
@solodddd

Copy link
Copy Markdown

Verified on M3 Ultra 512GB (Metal) — this fixes the #569 repro for the numeric case.

Environment:

  • M3 Ultra, 512 GiB RAM, Metal backend
  • Model: GLM-5.2-UD-Q2_K_RoutedQ2K.gguf
  • Branch: pr729 @ 93eb22b

Results:

Before this PR: "max_results":"10"
After: "max_results":10 (JSON number)

Server log shows a single WebSearch tool call with arguments
{"query":"ByteDance inference chips","max_results":10}.

One honest caveat: in this run the model did not emit exclude_domains,
so the array case wasn't exercised end-to-end here — the numeric
(max_results) case from #569 is confirmed fixed. Happy to run a variant
that forces an array argument if that would help.

Thanks for the fix — and for crediting the original report in #569.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

server: GLM tool-call parser stringifies all argument values (numbers/arrays become strings), breaking schema-validating clients

2 participants