From 2fa811b2e228f2241c5220c06c1dd98b0c7bfef5 Mon Sep 17 00:00:00 2001 From: Jinx Date: Sun, 12 Apr 2026 20:52:51 +0000 Subject: [PATCH] add test_nested_bad_properties (Tool 21 bug reproduction) --- test_devstral.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/test_devstral.py b/test_devstral.py index b807e23..338babd 100644 --- a/test_devstral.py +++ b/test_devstral.py @@ -402,7 +402,63 @@ def test_openclaw_tool_schema(): record("openclaw tool schema", True, "Middleware fixed parameters.properties=[] → {}") -# ── 8. OpenClaw full payload (chat_template_kwargs + tools) ─ +# ── 8. Nested properties=[] in tool schema (Tool 21 bug) ──── + +def test_nested_bad_properties(): + """ + Reproduce the exact Tool 21 400 error: + schema['properties']['fields']['items']['properties'] = [] + + This happens when a tool has an array-of-objects parameter where + the items' properties field is [] instead of {}. The middleware + must recurse into the schema to fix ALL properties fields. + """ + print(f"\n{'='*60}") + print(f"[{ts()}] TEST: Nested properties=[] in tool schema (Tool 21 bug)") + print(f"{'='*60}") + + # This is the exact shape that causes: "Tool 21 function has invalid 'parameters' schema: + # [] is not of type 'object' ... On schema['properties']['fields']['items']['properties']" + tools = [{ + "type": "function", + "function": { + "name": "message", + "description": "Send a message", + "parameters": { + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": [] # <-- THIS causes the 400 + } + } + } + } + } + }] + + with make_client() as c: + r = c.post(f"{API_BASE}/chat/completions", json={ + "model": MODEL, + "messages": [{"role": "user", "content": "Send a message to Bob"}], + "tools": tools, + "tool_choice": "auto", + "stream": False, + "max_tokens": 128, + }) + print(f"[{ts()}] Status: {r.status_code}") + body = r.json() + if r.status_code != 200: + print(f"[{ts()}] Error: {json.dumps(body, indent=2)[:500]}") + record("nested bad properties", False, f"HTTP {r.status_code}: {json.dumps(body)[:200]}") + return + print(f"[{ts()}] Success — middleware fixed nested properties=[] to {{}}") + record("nested bad properties", True, "Middleware fixed nested properties.properties=[] to {}") + + +# ── 9. OpenClaw full payload (chat_template_kwargs + tools) ─ def test_openclaw_full_payload(): """ @@ -472,6 +528,7 @@ def main(): test_tool_response_flow() test_param_sweep() test_openclaw_tool_schema() + test_nested_bad_properties() test_openclaw_full_payload() print(f"\n\n{'='*60}")