Pull requests / #681

#681 serve: a malformed "tools" is a 400, not a dead request thread

closed · @hireymage · 0 评论 · 在 GitHub 查看

Server & API

描述

**Issue:** #592

A request whose `"tools"` is not the list of tool objects it is meant to be (`"auto"`, `["get_weather"]`, a bare
number, a dict) took the request thread down with an `AttributeError` — the connection closes with no reply at
all, a reverse proxy shows a 502. It happened two lines apart, both still on main:

- `serve/frontend.py` — the OpenAI mapping handed non-dict entries on unchanged, and the next consumer
  (`serve/server.py`, `own = {t.get("name") for t in tools or []}`) assumed every entry is a mapping;
- `serve/frontend.py`'s Anthropic path had the same shape one level earlier (`t["name"]` on a non-dict).

### The fix

The same treatment double-encoded `"messages"` got in #460 (`_object_list`): what is not a list of object-shaped
tools is a `ValueError` naming the field, which the server answers with its 400 `invalid_request_error`:

- both paths accept a JSON string of the list (decoded, not iterated character by character);
- the OpenAI path validates each entry: a `function`-type entry needs its `"function"` object with a non-empty
  `"name"`, the llama style needs a name (the working shape from the issue's repro `{"name": "get_weather"}`
  keeps working exactly as before);
- the Anthropic path validates its name-bearing tool definitions the same way.

### Tests

`serve/test_server.py`'s `test_tools_must_be_an_object_list` covers the crashing shapes from the issue end to end,
the entry-level rejections (a `function` entry without its function object, an empty or non-string name), the
double-decode, and the valid shapes mapping as before (119 tests, suite green).

站内延伸阅读

链到安装、模型与版本说明,便于 SEO/GEO,非官方 issue 正文。