diff --git a/python/sglang/srt/function_call/glm47_moe_detector.py b/python/sglang/srt/function_call/glm47_moe_detector.py
index 0b25b11eb..9bc11d770 100644
--- a/python/sglang/srt/function_call/glm47_moe_detector.py
+++ b/python/sglang/srt/function_call/glm47_moe_detector.py
@@ -759,7 +759,6 @@ class Glm47MoeDetector(BaseFormatDetector):
arguments = {}
for arg_key, arg_value in pairs:
arg_key = arg_key.strip()
- arg_value = arg_value.strip()
arg_type = get_argument_type(func_name, arg_key, tools)
parsed_value, is_good_json = parse_arguments(arg_value, arg_type)
diff --git a/python/sglang/srt/function_call/glm4_moe_detector.py b/python/sglang/srt/function_call/glm4_moe_detector.py
index 0761e24e7..36992b3fe 100644
--- a/python/sglang/srt/function_call/glm4_moe_detector.py
+++ b/python/sglang/srt/function_call/glm4_moe_detector.py
@@ -613,7 +613,6 @@ class Glm4MoeDetector(BaseFormatDetector):
arguments = {}
for arg_key, arg_value in pairs:
arg_key = arg_key.strip()
- arg_value = arg_value.strip()
arg_type = get_argument_type(func_name, arg_key, tools)
parsed_value, is_good_json = parse_arguments(arg_value, arg_type)
diff --git a/test/registered/unit/function_call/test_function_call_parser.py b/test/registered/unit/function_call/test_function_call_parser.py
index 01aa99904..f0974d45e 100644
--- a/test/registered/unit/function_call/test_function_call_parser.py
+++ b/test/registered/unit/function_call/test_function_call_parser.py
@@ -2276,6 +2276,39 @@ class TestGlm4MoeDetector(unittest.TestCase):
self.assertIsInstance(result, StreamingParseResult)
self.assertEqual(result.calls, [])
+ def test_whitespace_preserved_in_arg_values(self):
+ """Test that leading/trailing whitespace in arg values is not stripped."""
+ tools_with_string = [
+ Tool(
+ type="function",
+ function=Function(
+ name="apply_diff",
+ description="Apply a diff",
+ parameters={
+ "type": "object",
+ "properties": {
+ "old_string": {"type": "string"},
+ "new_string": {"type": "string"},
+ },
+ "required": ["old_string", "new_string"],
+ },
+ ),
+ )
+ ]
+ text = (
+ "apply_diff\n"
+ "old_string\n"
+ " indented code\n"
+ "new_string\n"
+ " also indented\n"
+ ""
+ )
+ result = self.detector.detect_and_parse(text, tools_with_string)
+ self.assertEqual(len(result.calls), 1)
+ params = json.loads(result.calls[0].parameters)
+ self.assertEqual(params["old_string"], " indented code")
+ self.assertEqual(params["new_string"], " also indented")
+
class TestGlm47MoeDetector(unittest.TestCase):
def setUp(self):
@@ -2552,6 +2585,39 @@ class TestGlm47MoeDetector(unittest.TestCase):
)
check_single_todos(result, expected_output)
+ def test_whitespace_preserved_in_arg_values(self):
+ """Test that leading/trailing whitespace in arg values is not stripped."""
+ tools_with_string = [
+ Tool(
+ type="function",
+ function=Function(
+ name="apply_diff",
+ description="Apply a diff",
+ parameters={
+ "type": "object",
+ "properties": {
+ "old_string": {"type": "string"},
+ "new_string": {"type": "string"},
+ },
+ "required": ["old_string", "new_string"],
+ },
+ ),
+ )
+ ]
+ text = (
+ "apply_diff"
+ "old_string"
+ " indented code"
+ "new_string"
+ " also indented"
+ ""
+ )
+ result = self.detector.detect_and_parse(text, tools_with_string)
+ self.assertEqual(len(result.calls), 1)
+ params = json.loads(result.calls[0].parameters)
+ self.assertEqual(params["old_string"], " indented code")
+ self.assertEqual(params["new_string"], " also indented")
+
class TestJsonArrayParser(unittest.TestCase):
def setUp(self):