[Bugfix][Rust Frontend] Preserve whitespace in GLM string arguments (#59654)
Signed-off-by: ai-jz <ai-jz@users.noreply.github.com> Co-authored-by: ai-jz <ai-jz@users.noreply.github.com> Co-authored-by: Bugen Zhao <i@bugenzhao.com>
ai-jz committed
Oct 1, 2026 at 19:10 UTC
e5d33a36e71da9e3e122ac9b139f3ab3b944ef71
1 file changed
+34
-2
rust/src/parser/src/tool/glm_xml/mod.rs
+34
-2
@@ -261,7 +261,7 @@ fn parse_parameter(input: &mut &str) -> ModalResult<(String, String)> {
261
_: literal(ARG_KEY_END),
262
_: ws0,
263
_: literal(ARG_VALUE_START),
264
- take_until(0.., ARG_VALUE_END).map(str::trim),
264
+ take_until(0.., ARG_VALUE_END),
265
_: literal(ARG_VALUE_END),
266
)
267
.parse_next(input)?;
@@ -274,7 +274,7 @@ mod tests {
274
use serde_json::{Value, json};
275
use thiserror_ext::AsReport;
276
277
- use super::Glm45MoeToolParser;
277
+ use super::{Glm45MoeToolParser, Glm47MoeToolParser};
278
use crate::tool::test_utils::{collect_stream, split_by_chars, test_tools};
279
use crate::tool::{ToolParser, ToolParserTestExt as _};
280
@@ -320,6 +320,38 @@ mod tests {
320
);
321
}
322
323
+ #[test]
324
+ fn glm_parse_complete_preserves_string_whitespace() {
325
+ let tools = test_tools();
326
+ let text = glm45_tool_call("get_weather", &[("city", " Paris \n"), ("days", " 2 ")]);
327
+ for mut parser in [
328
+ Glm45MoeToolParser::create(&tools).unwrap(),
329
+ Glm47MoeToolParser::create(&tools).unwrap(),
330
+ ] {
331
+ let output = parser.parse_complete(&text).unwrap();
332
+ assert_eq!(
333
+ serde_json::from_str::<Value>(&output.calls()[0].arguments).unwrap(),
334
+ json!({"city": " Paris \n", "days": 2})
335
+ );
336
+ }
337
+ }
338
+
339
+ #[test]
340
+ fn glm_streaming_preserves_string_whitespace() {
341
+ let tools = test_tools();
342
+ let text = glm45_tool_call("get_weather", &[("city", " Paris \n"), ("days", " 2 ")]);
343
+ for mut parser in [
344
+ Glm45MoeToolParser::create(&tools).unwrap(),
345
+ Glm47MoeToolParser::create(&tools).unwrap(),
346
+ ] {
347
+ let output = collect_stream(&mut *parser, &split_by_chars(&text, 7));
348
+ assert_eq!(
349
+ serde_json::from_str::<Value>(&output.calls()[0].arguments).unwrap(),
350
+ json!({"city": " Paris \n", "days": 2})
351
+ );
352
+ }
353
+ }
354
+
355
#[test]
356
fn glm45_streaming_extracts_multiple_tool_calls() {
357
let mut parser = Glm45MoeToolParser::new(&test_tools());