[codex] fix llm tool schema shaping for near ai - #2951
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors tool schema normalization by introducing a dedicated tool_schema module that supports different policies: StrictOpenAi and FlattenOnly. This allows NearAiChatProvider to use a more permissive flattening strategy that preserves optional fields, while other providers continue to use strict normalization. The changes include moving existing logic from rig_adapter.rs to the new module and updating relevant providers and tests. Feedback suggests an optimization in tool_schema.rs to reduce redundant map lookups during recursive schema normalization.
There was a problem hiding this comment.
Pull request overview
This PR centralizes provider-boundary JSON Schema shaping for tool definitions and adjusts NEAR AI’s tool schema behavior to avoid OpenAI strict-mode “required-nullable” rewriting while still flattening OpenAI-incompatible top-level combinators.
Changes:
- Extracted shared tool schema shaping into
src/llm/tool_schema.rswith aToolSchemaPolicy(StrictOpenAivsFlattenOnly). - Updated the rig adapter and Codex provider to keep strict OpenAI/Codex schema shaping.
- Switched NEAR AI chat completions to
FlattenOnlyand updated/added tests + docs accordingly.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/llm/tool_schema.rs | New shared schema shaping module with strict vs flatten-only policies + tests |
| src/llm/rig_adapter.rs | Uses shared shaping for rig-based providers; removes in-file normalizer implementation |
| src/llm/openai_codex_provider.rs | Uses shared shaping for Codex tool definitions |
| src/llm/nearai_chat.rs | Uses FlattenOnly shaping and updates tests to verify optional-field preservation + flattening |
| src/llm/mod.rs | Exposes the new tool_schema module within llm |
| src/llm/CLAUDE.md | Updates documentation to reflect new shaping policies and provider behavior |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two sibling bugs in the OAuth direct-HTTP Anthropic provider that blocked any tool-using request: 1. Tool input_schema not sanitized — t.parameters was passed raw, so any tool whose schema has top-level oneOf/anyOf/allOf returned "input_schema does not support oneOf, allOf, or anyOf at the top level". Sibling site missed by PR nearai#2951 (which fixed nearai_chat for the same Anthropic family of restrictions). Now routes through shape_tool_schema(FlattenOnly) to match nearai_chat.rs and the rig-based Anthropic path. 2. temperature parameter sent unconditionally — Anthropic deprecated it for the 4.7 family, returning "temperature is deprecated for this model.". Strip at the provider boundary by model-name pattern (-4-7) instead of patching every caller (heartbeat, compaction, dispatcher, routine engine all set temperature). Tested locally with claude-haiku-4-5 (works). claude-opus-4-7 was blocked by both issues; Claude.ai consumer OAuth tokens aren't entitled to opus-4-7 anyway, which probably explains why upstream didn't catch these (API-key-based testing has full model access). Host: ironclaw-dev Model: claude-opus-4-7 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix llm tool schema shaping for near ai * fix clippy in tool schema shaping * fix tool schema object-like handling * fix explicit non-object schema flattening * fix schema hint truncation handling
Summary
src/llm/tool_schema.rsFlattenOnlypolicy so top-level combinators still flatten but optional fields stay optionalWhy
NEAR AI was going through the same strict schema rewrite used by the strict OpenAI paths. That rewrote optional fields into required-nullable fields and pushed models toward sending
nullarguments that were not part of the original tool contract.At the same time, NEAR AI still needs the top-level combinator flattening boundary for OpenAI-compatible tool requests, so the fix keeps that compatibility layer while removing the unwanted strictification.
Impact
oneOf/anyOf/allOf/enum/notschemas before request serializationValidation
cargo test test_convert_tool_definition_preserves_optional_fields --libcargo test test_convert_tool_definition_flattens_top_level_oneof_without_strictifying --libcargo test tool_schema::tests --libcargo test test_convert_tool_definition_handles_top_level_oneof_dispatcher --lib