Skip to content

fix: preserve free-form OpenAI tool schemas#933

Open
jan-kubica wants to merge 1 commit into
TanStack:mainfrom
jan-kubica:fix/openai-strict-open-object-schemas
Open

fix: preserve free-form OpenAI tool schemas#933
jan-kubica wants to merge 1 commit into
TanStack:mainfrom
jan-kubica:fix/openai-strict-open-object-schemas

Conversation

@jan-kubica

@jan-kubica jan-kubica commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What changed

  • detect open/free-form object schemas before OpenAI strict normalization
  • fall back to strict: false while preserving additionalProperties
  • add converter unit coverage and a final-wire Playwright regression test

Root 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:pr
  • pnpm --filter @tanstack/ai-e2e test:e2e
  • focused OpenAI schema/tool converter Vitest suites
  • OpenAI package typecheck and ESLint

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of free-form map schemas in OpenAI tool requests.
    • Automatically uses non-strict tool formatting when dynamic object keys are required, preventing schema validation errors.
    • Preserves dynamic key definitions and supported value types in serialized requests.
  • Tests

    • Added coverage for nested and free-form map schemas.
    • Added end-to-end validation of tool serialization for dynamic-key inputs.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6f6e48df-b0e1-44cf-a18e-71cfa4100482

📥 Commits

Reviewing files that changed from the base of the PR and between 5fcaf90 and 745adbc.

📒 Files selected for processing (6)
  • .changeset/calm-maps-remain.md
  • packages/openai-base/src/utils/schema-converter.ts
  • packages/openai-base/tests/schema-converter.test.ts
  • packages/openai-base/tests/tool-converter-strict-fallback.test.ts
  • testing/e2e/src/routes/api.openai-shell-skills-wire.ts
  • testing/e2e/tests/openai-shell-skills-wire.spec.ts

📝 Walkthrough

Walkthrough

Free-form map schemas are now identified as incompatible with OpenAI strict mode. Tool converters emit strict: false while preserving dynamic-key schemas, with unit and end-to-end coverage for the serialized request.

Changes

Open-object tool fallback

Layer / File(s) Summary
Open-object compatibility detection
packages/openai-base/src/utils/schema-converter.ts, packages/openai-base/tests/schema-converter.test.ts
isStrictModeCompatible rejects open and hybrid object schemas while accepting explicitly closed empty objects.
Non-strict converter fallback
packages/openai-base/tests/tool-converter-strict-fallback.test.ts
Responses, chat-completions, and function-tool conversions emit strict: false for free-form map schemas, preserving response parameters.
End-to-end wire validation
testing/e2e/src/routes/api.openai-shell-skills-wire.ts, testing/e2e/tests/openai-shell-skills-wire.spec.ts, .changeset/calm-maps-remain.md
The route sends a free-form map tool, the wire test verifies its serialized schema, and a patch changeset records the update.

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
Loading

Possibly related PRs

  • TanStack/ai#786: Extends strict-schema compatibility and fallback handling for OpenAI tool conversion.
  • TanStack/ai#790: Adds related strict-schema fallback logic and test coverage.
  • TanStack/ai#833: Updates isStrictModeCompatible for another schema shape requiring non-strict tools.

Suggested reviewers: alemtuzlak

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change, root cause, impact, and tests, but it omits the required checklist and release impact sections from the template. Add the template sections with completed checklist items and state whether this change affects published code or is docs/CI/dev-only.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: preserving free-form OpenAI tool schemas.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

testing/e2e/tests/openai-shell-skills-wire.spec.ts

Parsing error: "parserOptions.project" has been provided for @typescript-eslint/parser.
The file was not found in any of the provided project(s): testing/e2e/tests/openai-shell-skills-wire.spec.ts


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jan-kubica jan-kubica marked this pull request as ready for review July 14, 2026 10:24
@nx-cloud

nx-cloud Bot commented Jul 14, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 745adbc

Command Status Duration Result
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 14s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-14 12:39:53 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jul 14, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@933

@tanstack/ai-acp

npm i https://pkg.pr.new/@tanstack/ai-acp@933

@tanstack/ai-angular

npm i https://pkg.pr.new/@tanstack/ai-angular@933

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@933

@tanstack/ai-bedrock

npm i https://pkg.pr.new/@tanstack/ai-bedrock@933

@tanstack/ai-claude-code

npm i https://pkg.pr.new/@tanstack/ai-claude-code@933

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@933

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@933

@tanstack/ai-code-mode-skills

npm i https://pkg.pr.new/@tanstack/ai-code-mode-skills@933

@tanstack/ai-codex

npm i https://pkg.pr.new/@tanstack/ai-codex@933

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@933

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@933

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@933

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@933

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@933

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@933

@tanstack/ai-grok-build

npm i https://pkg.pr.new/@tanstack/ai-grok-build@933

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@933

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@933

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@933

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@933

@tanstack/ai-mcp

npm i https://pkg.pr.new/@tanstack/ai-mcp@933

@tanstack/ai-mistral

npm i https://pkg.pr.new/@tanstack/ai-mistral@933

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@933

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@933

@tanstack/ai-opencode

npm i https://pkg.pr.new/@tanstack/ai-opencode@933

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@933

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@933

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@933

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@933

@tanstack/ai-sandbox

npm i https://pkg.pr.new/@tanstack/ai-sandbox@933

@tanstack/ai-sandbox-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-sandbox-cloudflare@933

@tanstack/ai-sandbox-daytona

npm i https://pkg.pr.new/@tanstack/ai-sandbox-daytona@933

@tanstack/ai-sandbox-docker

npm i https://pkg.pr.new/@tanstack/ai-sandbox-docker@933

@tanstack/ai-sandbox-local-process

npm i https://pkg.pr.new/@tanstack/ai-sandbox-local-process@933

@tanstack/ai-sandbox-sprites

npm i https://pkg.pr.new/@tanstack/ai-sandbox-sprites@933

@tanstack/ai-sandbox-vercel

npm i https://pkg.pr.new/@tanstack/ai-sandbox-vercel@933

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@933

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@933

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@933

@tanstack/ai-utils

npm i https://pkg.pr.new/@tanstack/ai-utils@933

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@933

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@933

@tanstack/openai-base

npm i https://pkg.pr.new/@tanstack/openai-base@933

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@933

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@933

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@933

commit: 745adbc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants