nobuddhy commited on
Commit
e75cf68
·
1 Parent(s): bad9f96

Accept the OpenAI store flag

Browse files

Agent clients such as pi send store: false with every request. The server
never stores completions, so a boolean store is accepted and ignored instead
of failing the request as an unsupported parameter.

include/ling3/chat_protocol.h CHANGED
@@ -88,7 +88,7 @@ inline Request Parse(const OrderedJson & j) {
88
  "max_completion_tokens", "stream", "stream_options", "temperature", "top_p",
89
  "seed", "stop", "n", "user", "cache_prompt", "top_k", "repeat_penalty",
90
  "enable_thinking", "flow_control", "session_id", "reuse_generated_state",
91
- "tools", "tool_choice", "parallel_tool_calls"};
92
  if (std::find(supported.begin(), supported.end(), it.key()) == supported.end())
93
  fail("unsupported parameter: " + it.key());
94
  }
@@ -168,6 +168,8 @@ inline Request Parse(const OrderedJson & j) {
168
  r.seed = j["seed"].get<std::uint32_t>();
169
  }
170
  if (j.contains("n") && (!j["n"].is_number_integer() || j["n"] != 1)) fail("only n=1 is supported");
 
 
171
  if (j.contains("user") && !j["user"].is_string()) fail("user must be a string");
172
  if (j.contains("user")) r.cache_user = j["user"].get<std::string>();
173
  if (j.contains("stop") && !j["stop"].is_null()) {
 
88
  "max_completion_tokens", "stream", "stream_options", "temperature", "top_p",
89
  "seed", "stop", "n", "user", "cache_prompt", "top_k", "repeat_penalty",
90
  "enable_thinking", "flow_control", "session_id", "reuse_generated_state",
91
+ "tools", "tool_choice", "parallel_tool_calls", "store"};
92
  if (std::find(supported.begin(), supported.end(), it.key()) == supported.end())
93
  fail("unsupported parameter: " + it.key());
94
  }
 
168
  r.seed = j["seed"].get<std::uint32_t>();
169
  }
170
  if (j.contains("n") && (!j["n"].is_number_integer() || j["n"] != 1)) fail("only n=1 is supported");
171
+ // Agent clients send OpenAI's store flag; this server never stores completions.
172
+ if (j.contains("store") && !j["store"].is_boolean()) fail("store must be boolean");
173
  if (j.contains("user") && !j["user"].is_string()) fail("user must be a string");
174
  if (j.contains("user")) r.cache_user = j["user"].get<std::string>();
175
  if (j.contains("stop") && !j["stop"].is_null()) {
tests/chat_tools_test.cpp CHANGED
@@ -26,12 +26,14 @@ int main(int argc, char ** argv) {
26
  Check(Parse(body).tool_calls && Parse(body).parallel_tool_calls, "tools must enable call parsing");
27
  auto none = body; none["tool_choice"] = "none";
28
  Check(!Parse(none).tool_calls && Parse(none).prompt == prompt, "tool_choice none still renders tools");
 
 
29
  auto parts = body;
30
  parts["messages"][1]["content"] = OrderedJson::array({{{"type", "text"}, {"text", "Fix /tmp/a.txt."}}});
31
  Check(Parse(parts).prompt == prompt, "text-part content");
32
  for (const auto & [pointer, value] : std::vector<std::pair<std::string, OrderedJson>>{
33
  {"/tools", "read_file"}, {"/tools/0/type", "code"}, {"/tool_choice", "required"},
34
- {"/parallel_tool_calls", "yes"}, {"/messages/2/tool_calls/0/function/arguments", "{oops"},
35
  {"/messages/2/tool_calls/0/function/arguments", "[1]"}, {"/messages/3/content", nullptr},
36
  {"/messages/3/id", "x"}, {"/messages/1/content", OrderedJson::array({{{"type", "image_url"}}})}}) {
37
  auto bad = body; bad[OrderedJson::json_pointer(pointer)] = value; bool failed = false;
 
26
  Check(Parse(body).tool_calls && Parse(body).parallel_tool_calls, "tools must enable call parsing");
27
  auto none = body; none["tool_choice"] = "none";
28
  Check(!Parse(none).tool_calls && Parse(none).prompt == prompt, "tool_choice none still renders tools");
29
+ auto stored = body; stored["store"] = false;
30
+ Check(Parse(stored).prompt == prompt, "store flag rejected");
31
  auto parts = body;
32
  parts["messages"][1]["content"] = OrderedJson::array({{{"type", "text"}, {"text", "Fix /tmp/a.txt."}}});
33
  Check(Parse(parts).prompt == prompt, "text-part content");
34
  for (const auto & [pointer, value] : std::vector<std::pair<std::string, OrderedJson>>{
35
  {"/tools", "read_file"}, {"/tools/0/type", "code"}, {"/tool_choice", "required"},
36
+ {"/parallel_tool_calls", "yes"}, {"/store", "no"}, {"/messages/2/tool_calls/0/function/arguments", "{oops"},
37
  {"/messages/2/tool_calls/0/function/arguments", "[1]"}, {"/messages/3/content", nullptr},
38
  {"/messages/3/id", "x"}, {"/messages/1/content", OrderedJson::array({{{"type", "image_url"}}})}}) {
39
  auto bad = body; bad[OrderedJson::json_pointer(pointer)] = value; bool failed = false;