fix(api): pop null json_schema description/strict omit-real before proxy - #646
fix(api): pop null json_schema description/strict omit-real before proxy#646cursor[bot] wants to merge 15 commits into
Conversation
…closed otherwise Chat history: message-level audio and legacy function_call are null/empty omit no-ops; non-empty fail closed with named errors (including tools passthrough). Tip substrate from #577 assistant refusal/annotations honesty. Local full unit: 940 passed.
…ed otherwise OpenAI fine-tune style message weight is not applied on this gateway. Accept null/0/1 as honest no-ops; reject other types and values with invalid_message_weight. Tip substrate from #578. Local full unit: 943 passed.
…ion role Reject unsupported message keys with named unknown_message_fields (not silent strip or tools-passthrough smuggle). Reject legacy function role with invalid_message_role migration to tool. Tip substrate from #579. Local full unit: 947 passed.
OpenAI partial-assistant prefix flag is not applied on this gateway. null/false are honest no-ops; true and non-booleans fail closed with invalid_message_prefix. Tip substrate from #580. Local full unit: 950 passed.
…therwise Named invalid_max_tool_calls on /v1/chat/completions instead of opaque unknown_fields. Aligns with Responses max_tool_calls honesty; gateway has no multi-step tool loop.
…losed otherwise Legacy /v1/completions treated max_tool_calls as unknown_fields. Accept the key for named invalid_max_tool_calls (null/empty/whitespace omit-equivalent), matching chat/Responses honesty so SDKs get a clear migration path.
SDK clients often send include_usage/include_obfuscation as JSON null. Drop null flag values before validation so null (and null+false mixes) match omit / all-false no-ops on chat, Completions, and Responses. True flags remain fail-closed with invalid_stream_options.
…or Responses parallel true SDK optional defaults often send function.strict and json_schema.strict as null — treat as omit rather than type errors. Align Responses parallel_tool_calls=true with chat by requiring a non-empty tools array.
SDK optional defaults often send description and parameters as JSON null. Treat null as omit rather than type errors; non-null non-string/object values remain fail-closed with invalid_tools.
OpenAI-style tool descriptions are at most 1024 characters. Over-long descriptions fail closed with named invalid_tools so SDKs never believe a truncated description was accepted.
SDK optional participant name blanks ("" / whitespace) are omit-equivalent
like JSON null. Non-string, over-long, and invalid charset names remain
fail-closed with invalid_message_name.
SDK optional defaults serialize omitted tool.function description/parameters/strict as JSON null. Accepting those keys without popping them is not omit-equivalent: proxy_completion forwards the body and several providers reject null parameters. Pop in place so passthrough matches omit; keep non-null wrong types on invalid_tools. Also pop response_format.json_schema.strict null. Tip substrate from #614. Local full unit: 989 passed.
…n keys SDK optional defaults serialize omitted response_format.json_schema description/strict as JSON null or blank. Leave those keys and the gateway forwards them; several providers reject strict: null. Pop in place so passthrough matches omit. Unknown inner keys and non-string descriptions stay invalid_response_format. HTTP echo tests cover chat and Responses. Docs cite OpenAI structured outputs and IETF JSON Schema 2020-12 in APA 7th. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
SDK optional defaults serialize omitted function descriptions as empty or whitespace-only strings. Leaving those keys is not omit-equivalent: proxy_completion forwards them and several providers reject a blank description. Pop in place so passthrough matches omit; keep non-empty strings and fail-closed non-string values. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
Stale comment
Unique tip review (
d59f164+1cb13ae+b09aac3on #638569f760)Verdict: SOUND for the omit-real slice. Do not merge this 151-file honesty stack onto
main.What the unique tip does
- Pops JSON-null / blank
response_format.json_schema.descriptionand JSON-nullstrictin place soproxy_completionforwards omit, notnull.- Fail-closes unknown inner keys and non-string
descriptionwith namedinvalid_response_format.- Pops empty / whitespace-only
tool.function.descriptionthe same way (SDK blank default).- HTTP
echo.response_format/echo.toolscontracts cover chat and Responses.Local evidence
python3 tests/test_json_schema_inner_fields_omit_http_honesty.py
python3 tests/test_tool_description_blank_omit_http_honesty.py
python3 tests/test_tool_function_null_fields_pop_http_honesty.py
python3 tests/test_chat_response_format_http_honesty.py
all printedok.Residual (next unique tip, not a merge of this stack)
json_schema.nameis only “non-empty string.” OpenAI Structured Outputs require[a-zA-Z0-9_-]{1,64}— the same charset already enforced ontool.function.name. Invalid names still reach the provider and the buyer sees an opaque upstream error instead ofinvalid_response_format. Do not fold that onto this PR; land it as the next unique commit after Full unit + Semgrep on this tip.Reviewer next action
Review the three unique commits only. Independent non-author APPROVE is still required. Do not APPROVE the 143-file substrate as a
mainmerge. CI Full unit + Semgrep are queued; they are not a reason to stop the next honesty slice.Sent by Cursor Automation: Fix Issues
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Stale comment
Unique tip review (
569f760..b09aac3)Unique commits
d59f164+1cb13ae+b09aac3are SOUND. Omit is real:_validate_chat_response_formatpops JSON-null / blankresponse_format.json_schema.descriptionand JSON-nullstricton the same dictproxy_completionforwards. Unknown inner keys and non-string descriptions stayinvalid_response_format. Blanktool.function.descriptionis popped after the #638 null helper.Local scripts printed
ok:
tests/test_json_schema_inner_fields_omit_http_honesty.pytests/test_tool_description_blank_omit_http_honesty.pytests/test_tool_function_null_fields_pop_http_honesty.pytests/test_chat_response_format_http_honesty.pytests/test_responses_response_format_http_honesty.pytests/test_tool_strict_null_noop_http_honesty.pyReviewer next action
Do not APPROVE or merge this 151-file honesty stack onto
main. Review the unique tip only. Independent non-author APPROVE is still required for the unique commit.Residual (later unique tip, not this PR)
Official Responses structured output is
text.format. This gateway still returns400 invalid_textfor any non-emptytext— fail-closed, not a null leak. The Responses HTTP test locks the chat-styleresponse_formatshim only. Next honesty slice:json_schema.namemust match[a-zA-Z0-9_-]{1,64}(tool names already do). Do not fold #639/#640 mode/tool_choicehere. Envelope work stays on #628/#648. Instructions omit stays on #649.CI Full unit + Semgrep were queued at review time — not treated as a blocker.
Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Unique tip review (569f760..b09aac3)
Unique commits d59f164 + 1cb13ae + b09aac3 are SOUND. Omit is real: _validate_chat_response_format pops JSON-null / blank response_format.json_schema.description and JSON-null strict on the same dict proxy_completion forwards. Unknown inner keys and non-string descriptions stay invalid_response_format. Blank tool.function.description is popped after the #638 null helper.
Local unique + related honesty scripts printed ok on this run's substrate. Code-reviewer subagent confirmed the same evidence (server.py 2442 / 2484 / 2523-2539; mock _mock_raw echoes the nested dicts).
Reviewer next action
Do not APPROVE or merge this 151-file honesty stack onto main. Review the unique tip only. Independent non-author APPROVE is still required for the unique commit.
Residual (later unique tips, not this PR)
json_schema.name[a-zA-Z0-9_-]{1,64}is already on #654. Do not fold it back here.- Official Responses structured output is
text.format(flattype/name/schema/strict). This gateway still returns400 invalid_textfor any non-emptytext(server.py1183-1197). Chat-styleresponse_formaton/v1/responsesis not that coverage. Next honesty slice: accept officialtext.formatwith the same omit-real / fail-closed rules. - Do not fold #639/#640 mode/
tool_choicehere. Envelope work stays on #628/#648. Instructions omit stays on #649.
CI Full unit + Semgrep were still queued at review time — not treated as a blocker. Name-charset thread on this PR is fully addressed by #654.
Sent by Cursor Automation: Fix Issues
Pull request was closed
|
Superseded by tip substrate ≥ #691 (cumulative OpenAI/gateway honesty band + auto-merge tip). Closing to free product-gate runners (Full unit + Semgrep). |


Summary
response_format.json_schema.description/strictas JSONnullor blank.proxy_completionforwards the body and several providers rejectstrict: null.descriptionand nullstrictin place so passthrough matches omit.description(invalid_response_format).main. Land the unique commit after Full unit + Semgrep.Test plan
python3 tests/test_json_schema_inner_fields_omit_http_honesty.py(ok)python3 tests/test_tool_function_null_fields_pop_http_honesty.py(ok)python3 tests/test_chat_response_format_http_honesty.py(ok)python3 tests/test_tool_strict_null_noop_http_honesty.py(ok)python3 tests/test_responses_response_format_http_honesty.py(ok)Reviewer next action
Review the unique tip (
d59f164) only. Do not APPROVE the 143-file honesty stack as amainmerge. Independent non-author APPROVE is still required for the unique commit.