fix(config): allow requiresReasoningContentOnAssistantMessages in ModelCompatSchema#89832
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 4, 2026, 7:39 AM ET / 11:39 UTC. Summary PR surface: Source +3, Tests +60. Total +63 across 4 files. Reproducibility: yes. Source inspection shows current main's strict schema omits the key and active Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the PR after maintainer acceptance of the opt-in compatibility surface and normal checks, keeping default auto-detection behavior unchanged. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main's strict schema omits the key and active Is this the best way to solve the issue? Yes. Adding the missing schema key and honoring AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against a3af4263532d. Label changesLabel justifications:
Evidence reviewedPR surface: Source +3, Tests +60. Total +63 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
…ges from config Addresses clawsweeper review on openclaw#89832 (P1 compatibility trap). getCompat() in openai-transport-stream resolved every compat field as "compat.X ?? detected.X" EXCEPT requiresReasoningContentOnAssistantMessages, which used detected.X alone. So a custom OpenAI-compatible proxy (not auto-detected as DeepSeek/Xiaomi) that set the flag in config would pass schema validation but be ignored by the active transport — a startup-success/runtime-failure trap. Now resolves compat.X ?? detected.X, matching openai-completions.ts:1333 and every sibling field. Exposes getCompat via the existing test-only testing export and adds a focused regression: a custom provider with the flag set resolves true (verified to fail against the pre-fix detected-only code); the same provider without the flag falls back to detection (false).
|
Thanks for the review — good catch on the compatibility trap. Addressed it: |
…elCompatSchema Closes openclaw#89660. The field is consumed at runtime (detectCompat/getCompat inject reasoning_content: "" on assistant messages for DeepSeek) and is declared on the canonical ModelCompatConfig type (packages/llm-core/src/types.ts), but was missing from the strict Zod ModelCompatSchema. A config setting it (to replicate native DeepSeek behavior on a custom OpenAI-compatible proxy) was rejected at gateway startup with "Unrecognized key(s) in object". Add the optional boolean to ModelCompatSchema, matching the existing type and the other requires* compat flags. The bidirectional AssertAssignable guard did not catch the gap because a missing *optional* field does not break type assignability in either direction.
…ges from config Addresses clawsweeper review on openclaw#89832 (P1 compatibility trap). getCompat() in openai-transport-stream resolved every compat field as "compat.X ?? detected.X" EXCEPT requiresReasoningContentOnAssistantMessages, which used detected.X alone. So a custom OpenAI-compatible proxy (not auto-detected as DeepSeek/Xiaomi) that set the flag in config would pass schema validation but be ignored by the active transport — a startup-success/runtime-failure trap. Now resolves compat.X ?? detected.X, matching openai-completions.ts:1333 and every sibling field. Exposes getCompat via the existing test-only testing export and adds a focused regression: a custom provider with the flag set resolves true (verified to fail against the pre-fix detected-only code); the same provider without the flag falls back to detection (false).
c54c4f3 to
5bd1474
Compare
|
Land-ready maintainer proof for rebased head What changed:
Tested locally before landing: Real behavior proof status:
CI note:
|
Summary
requiresReasoningContentOnAssistantMessagesis consumed at runtime (it gates injecting the DeepSeekreasoning_contentreplay contract on assistant messages) and is declared on the canonicalModelCompatConfigtype, but a custom OpenAI-compatible proxy could not actually use it: (1) the strict ZodModelCompatSchemarejected the key at startup, and (2) even past validation,getCompatin the active transport ignored the explicit config value for custom providers.Unrecognized key. Without (2), the key would validate but be silently ignored at runtime for non-auto-detected providers — a startup-success / runtime-failure trap (raised in review).src/config/zod-schema.core.ts— addrequiresReasoningContentOnAssistantMessages: z.boolean().optional()toModelCompatSchema, matching the type and the siblingrequires*flags.src/agents/openai-transport-stream.ts—getCompatnow resolvescompat.requiresReasoningContentOnAssistantMessages ?? detected.…, matchingopenai-completions.ts:1333and every other field in the same return object (it was the lone field usingdetected.…alone).packages/llm-core/src/types.ts:383), so no type change was needed; the create-once approval-index write and unrelated transports are untouched.Linked context
Real behavior proof (required for external PRs)
Behavior or issue addressed: the OpenClaw config validator rejected, and the active transport then ignored, a custom-provider config that sets
compat.requiresReasoningContentOnAssistantMessages: true.Real environment tested: OpenClaw checked out and
pnpm install-ed on Linux, Node v22.20.0. Drove the real productionModelsConfigSchemaand the realgetCompatresolution used bybuildOpenAICompletionsParams.Exact steps or command run after this patch: ran
node --import tsx run-validator.mtsagainst the real schema, and exercised the transportgetCompatresolution for a custom-proxy model.Evidence after fix: live
nodeconsole output — the same command was run against the unpatched and patched schema:Observed result after fix: running
nodeagainst the patched schema printsCONFIG ACCEPTEDand the resolved compat carries the flag. For the transport, a custom-proxy model that sets the flag now resolvesrequiresReasoningContentOnAssistantMessages: true(it resolvedfalseagainst the pre-fixdetected-only code — confirmed by reverting the line), while the same provider without the flag falls back to detection (false).What was not tested: a full
openclaw gatewayboot against a live DeepSeek proxy (needs real proxy + credentials); the change is config + compat-resolution, both driven directly above.Proof limitations or environment constraints: validator/resolution driven by focused harnesses rather than a daemon boot, to isolate the two code paths the issue and review describe; modules under test are the unmodified production files.
Root cause
getCompatinopenai-transport-streamresolved it fromdetectedonly instead ofcompat.X ?? detected.Xlike its siblings (ignored at runtime for custom providers).AssertAssignableguards don't catch a missing optional field; and the transport field was the only one not following thecompat.X ?? detected.Xpattern, so nothing flagged the divergence. The addedzod-schema.models.test.tsandopenai-transport-stream.test.tscases now cover both.