fix: preserve free-form OpenAI tool schemas - #933
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughFree-form map schemas are now identified as incompatible with OpenAI strict mode. Tool converters emit ChangesOpen-object tool fallback
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Route
participant OpenAIAdapter
participant RequestCapture
Route->>OpenAIAdapter: pass freeFormMapTool
OpenAIAdapter->>RequestCapture: serialize strict: false
RequestCapture-->>Route: expose dynamic labels schema
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
testing/e2e/tests/openai-shell-skills-wire.spec.tsParsing error: "parserOptions.project" has been provided for Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit 745adbc
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-devtools-core
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-mcp
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
…ict-schema 400 Linear's save_diff_comment.anchor started shipping as a free-form map (propertyNames + open additionalProperties). @tanstack/ai-openai@0.15.2 forced strict:true on every tool and 400d the whole turn on such schemas. @tanstack/openai-base@0.9.8 (PR TanStack/ai#933, shipped in @tanstack/ai-openai@0.17.0) detects free-form-map schemas and emits those tools with strict:false instead, so they stay callable. Bump to pick that up: @tanstack/ai ^0.32.0 -> ^0.42.0 @tanstack/ai-openai ^0.15.2 -> ^0.17.1 @tanstack/ai-mcp ^0.1.3 -> ^0.2.5 zod ^3 -> ^4 (peer of ai-openai 0.17) No runtime code change — the fix lives in the upgraded adapter.
…ict-schema 400 (#6088) ## Problem The deployed Slack triage bot (`examples/slack`) started failing **every** turn with: ``` 400 Invalid schema for function 'save_diff_comment': In context=('properties','anchor'), 'propertyNames' is not permitted. ``` No change on our side triggered it — Linear's hosted MCP server changed the `save_diff_comment` tool schema. Its `anchor` param is now a free-form map (open object declared with `propertyNames` + open `additionalProperties`). The bot fetches Linear's tool list at runtime, so it picked up the new schema automatically. ## Root cause `@tanstack/ai-openai@0.15.2` (what the bot resolves to) forces `strict: true` on every function tool. OpenAI's strict function-calling validator only accepts a subset of JSON Schema and **rejects the entire request (400, before the model runs)** for a free-form-map object like `anchor`. One over-rich third-party tool takes down the whole turn. ## Fix — adopt the upstream fix via a dependency upgrade Already fixed upstream: `@tanstack/openai-base@0.9.8` ([TanStack/ai#933](TanStack/ai#933)) makes the tool converter detect free-form-map schemas and emit those tools with `strict: false` (so they stay callable) instead of forcing an invalid strict schema. First ships in `@tanstack/ai-openai@0.17.0`. The bot's `^0.15.2` range can't reach it, so this bumps the aligned set and refreshes `pnpm-lock.yaml`: | package | before | after | |---|---|---| | `@tanstack/ai` | `^0.32.0` | `^0.42.0` | | `@tanstack/ai-openai` | `^0.15.2` | `^0.17.1` (→ `openai-base@0.9.9`) | | `@tanstack/ai-mcp` | `^0.1.3` | `^0.2.5` | **zod stays at `^3.25.76`.** The repo pins zod to 3.x via a root `pnpm.overrides` (`zod: ">=3.22.3"`), so the whole workspace resolves zod 3 regardless. `ai-openai@0.17` peers `zod ^4` (unmet → advisory warning only), but the strict-schema fix operates on plain JSON Schema, not zod, so it's unaffected. **No runtime code change** — the fix lives entirely in the upgraded adapter (an earlier revision of this PR hand-rolled a schema sanitizer; that's removed in favor of leaning on TanStack's built-in handling). ## Verification⚠️ Not verifiable in this worktree (example deps aren't installed here). Before merge, in an installed env: - `pnpm --filter slack-example check-types` and `pnpm --filter slack-example test` - One live turn hitting Linear (previously-failing `save_diff_comment` path) - Sanity-check the bot runs on the workspace's pinned **zod 3** despite `ai-openai@0.17`'s `zod ^4` peer (the fix path is zod-independent, but confirm no other `@tanstack/ai` code the bot exercises needs a zod-4-only API). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
What changed
strict: falsewhile preservingadditionalPropertiesRoot cause
Strict compatibility checked unsupported keywords and typeless nodes, but not open objects. Strict normalization could therefore close hybrid maps and change their semantics, while property-less maps could reach OpenAI as invalid strict schemas.
Impact
Function tools with record/map inputs keep accepting dynamic keys and no longer fail the entire OpenAI request on strict-schema validation.
Test plan
pnpm test:prpnpm --filter @tanstack/ai-e2e test:e2eSummary by CodeRabbit
Bug Fixes
Tests