fix(ai): reject non-finite tool schema numbers#104470
Conversation
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
|
Codex review: stale review; fresh review needed. Summary Next step Review history (9 earlier review cycles; latest 8 shown)
|
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
|
Updated this PR for the ClawSweeper review findings. What changed:
Real behavior proof now included in the PR body:
Validation: @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
|
Added one more focused regression for the reviewer concern around path tracking through custom serializers. What changed in the latest commit:
Validation: This is intentionally test-only; the production fix remains the shared single-serialization projection path already pushed in |
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
|
Merged via squash.
|
* fix(ai): reject non-finite tool schema numbers Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): catch non-finite values from tool schema serializers Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> * test(ai): cover nested tool schema serializers Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): satisfy schema projection lint Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): satisfy schema projection lint Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): preserve empty-key schema diagnostic paths * fix(ai): reject boxed non-finite schema numbers * fix(ai): ignore spoofed boxed-number tags * fix(ai): isolate boxed-number brand probes * refactor(ai): use intrinsic boxed-number detection --------- Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> Co-authored-by: Peter Steinberger <[email protected]>
Closes #104469
What Problem This Solves
Fixes an issue where tool schemas containing non-finite numeric values could be projected into provider-facing schemas with those values silently changed to
null.The trigger is a runtime/custom tool schema that contains a JavaScript-only numeric value such as
Number.POSITIVE_INFINITYorNumber.NaNin a JSON Schema numeric constraint/default. The shared projector serialized the schema withJSON.stringify()before validating the projected JSON value, so those values could become explicitnullfields while reporting no schema violation.Why This Change Was Made
The shared runtime tool schema projector now detects non-finite numbers before JSON serialization and reports the exact offending schema path as non-JSON-serializable.
This keeps the existing quarantine behavior narrow: the invalid tool is dropped with diagnostics, healthy sibling tools remain available, and provider-specific schema cleanup is left unchanged. The changed shared path is used by OpenAI and Anthropic tool projection; sibling provider paths such as Google/Gemini and Mistral use separate schema handling and are not changed by this PR.
User Impact
Plugin/tool authors and operators get safer tool schema handling. Invalid non-finite numeric schema values now produce a clear projection violation instead of being silently rewritten into materially different provider payloads.
For example, a bad
bad_limitstool withmaximum: Number.POSITIVE_INFINITYis quarantined, while a healthy siblinglookuptool remains available for provider use.Evidence
Behavior proof:
Focused regression coverage added:
src/agents/tool-schema-projection.test.tscoversNumber.NaNat the shared runtime schema projection layer and expectsparameters.properties.score.default is not JSON-serializable.packages/ai/src/providers/openai-tool-projection.test.tscovers OpenAI tool projection quarantining a badmaximum: Number.POSITIVE_INFINITYtool while preserving a healthy sibling.packages/ai/src/providers/anthropic-tool-projection.test.tscovers Anthropic tool projection quarantining the bad original tool while preserving a healthy sibling.Validation run:
Additional local validation note:
was attempted separately but did not reach useful typechecking in this checkout because workspace package resolution reports
@openclaw/gateway-protocol@workspace:*frompackages/gateway-clientwhile no@openclaw/gateway-protocolpackage is present in the local workspace. That appears unrelated to the four files changed here.