Skip to content

feat(schemas): @tanstack/ai-schemas with nightly OpenAPI sync (closes #619)#622

Draft
tombeckenham wants to merge 9 commits into
mainfrom
619-create-schemas-library
Draft

feat(schemas): @tanstack/ai-schemas with nightly OpenAPI sync (closes #619)#622
tombeckenham wants to merge 9 commits into
mainfrom
619-create-schemas-library

Conversation

@tombeckenham
Copy link
Copy Markdown
Contributor

Summary

Adds a separate @tanstack/ai-schemas package that ships per-endpoint JSON Schema + Zod definitions for every supported provider, generated nightly from upstream OpenAPI specs. Resolves #619.

Architecture ported from fal-ai/fal-js#212 and generalised to multi-provider.

Pipeline

  1. fetch-schemas — per-provider fetchers under scripts/providers/.
  2. generate-schemas@hey-api/openapi-ts with @hey-api/schemas + Zod 4 plugin.
  3. generate-endpoint-maps — bundles each schema's $ref closure under $defs, emits endpoint-id-keyed maps + namespaced top-level barrels.

Providers covered

Provider Source
OpenAI github.com/openai/openai-openapi raw YAML
Anthropic Stainless OpenAPI resolved via anthropic-sdk-typescript/.stats.yml
Gemini Google Discovery doc converted to OpenAPI in-pipeline
ElevenLabs api.elevenlabs.io/openapi.json
FAL api.fal.ai/v1/models?status=active&expand=openapi-3.0 (needs FAL_KEY)

Spec-level fixes

To keep generator output type-clean, the merge step (scripts/merge-openapi-specs.ts) drops/coerces malformed defaults: default: null on non-nullable fields, default: "string" on enum/array/object fields, type/value mismatches. Post-process step rewrites .extend() calls on discriminated unions to z.intersection(...) so runtime Zod is valid.

The auto-generated *.gen.ts files carry /* eslint-disable */ + // @ts-nocheck (standard codegen convention). All hand-written source still type-checks strictly.

Automation

.github/workflows/sync-schemas.yml runs daily at 05:00 UTC. On diff: bumps patch version, writes a changeset, opens an automated PR. Same pattern as the existing sync-models.yml.

Repo setup: add FAL_KEY to repo secrets so FAL schemas can sync in CI. Other four providers are public.

Per-coupling updates

  • packages/typescript/ai/skills/ai-core/media-generation/SKILL.md — adds a "Validating inputs before submitting" section + cross-ref.
  • packages/typescript/ai/skills/ai-core/adapter-configuration/SKILL.md — cross-references the new package.
  • docs/advanced/ai-schemas.md + docs/config.json — new doc page under Advanced.
  • .changeset/initial-ai-schemas.md — minor release for @tanstack/ai-schemas@0.1.0.

Test plan

  • pnpm install (lockfile updated for @hey-api/openapi-ts, tsx, yaml)
  • pnpm --filter @tanstack/ai-schemas test:lib — 5 unit tests pass (toOpenAIStrict)
  • pnpm --filter @tanstack/ai-schemas test:types — strict tsc, no errors
  • pnpm --filter @tanstack/ai-schemas test:eslint — clean
  • pnpm --filter @tanstack/ai-schemas test:build — publint strict passes
  • pnpm test:sherif, pnpm test:knip, pnpm test:docs — clean
  • Manual: pnpm --filter @tanstack/ai-schemas update-schemas regenerates all 4 public providers end-to-end (~30s)
  • Add FAL_KEY to repo secrets, manually dispatch sync-schemas.yml, confirm FAL category schemas land in the follow-up PR
  • Smoke test a consumer: import { openaiEndpointZodMap } from "@tanstack/ai-schemas/zod/openai", parse a sample request

🤖 Generated with Claude Code

…oses #619)

Adds a separate `@tanstack/ai-schemas` package that ships per-endpoint
JSON Schema + Zod definitions for every supported provider, generated
nightly from upstream OpenAPI specs.

Architecture ported from fal-ai/fal-js PR #212 and generalised to
multi-provider. Pipeline: `fetch-schemas` (per-provider fetchers) →
`generate-schemas` (`@hey-api/openapi-ts` with the Zod 4 plugin) →
`generate-endpoint-maps` (bundles `$ref` closures under `$defs`, emits
endpoint-id-keyed maps and namespaced top-level barrels).

Providers wired up with working generation:
- OpenAI: `github.com/openai/openai-openapi` raw YAML
- Anthropic: Stainless OpenAPI resolved via anthropic-sdk-typescript/.stats.yml
- Gemini: Google Discovery doc → OpenAPI converted in-pipeline
- ElevenLabs: `api.elevenlabs.io/openapi.json`
- FAL: per-model OpenAPI from `api.fal.ai/v1/models` (skips when FAL_KEY absent)

.github/workflows/sync-schemas.yml runs daily and opens an automated PR
when any upstream spec diff lands, following the same pattern as
sync-models.yml.

Per repo coupling rules: media-generation + adapter-configuration
SKILL.md cross-reference the new package; new docs/advanced/ai-schemas.md
page added under the Advanced section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tombeckenham tombeckenham linked an issue May 22, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c7b1d7f4-425b-4a52-af76-089ebdbd6796

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 619-create-schemas-library

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 and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

🚀 Changeset Version Preview

1 package(s) bumped directly, 0 bumped as dependents.

🟨 Minor bumps

Package Version Reason
@tanstack/ai-schemas 0.1.0 → 0.2.0 Changeset

@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 22, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​hey-api/​openapi-ts@​0.97.29710010096100

View full report

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented May 22, 2026

View your CI Pipeline Execution ↗ for commit 192f1a8

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

☁️ Nx Cloud last updated this comment at 2026-05-22 07:53:05 UTC

tombeckenham and others added 3 commits May 22, 2026 15:51
Switches `@tanstack/ai-schemas` from format-first
(`@tanstack/ai-schemas/schemas/openai`, `/zod/gemini`) to provider-first
(`@tanstack/ai-schemas/openai/json-schema`, `/gemini/zod`) and drops the
namespaced aggregator barrels.

With provider-first subpaths and no aggregator, importing one provider's
schemas pulls only that provider's bytes. Importing
`@tanstack/ai-schemas/gemini/json-schema` carries no OpenAI, Anthropic,
ElevenLabs, or FAL code into the consumer's bundle.

The default `.` entry now only re-exports `toOpenAIStrict` (4 KB).

Wildcard exports in package.json:

  "./*/json-schema" -> dist/esm/providers/*/schemas-index.{js,d.ts}
  "./*/zod"         -> dist/esm/providers/*/index.{js,d.ts}

Generator emits a flat layout — `providers/{providerId}` for single-
category providers, `providers/{providerId}-{category}` for FAL
(`fal-image`, `fal-video`, etc.) — so Node's single-segment `*` wildcard
resolves cleanly.

Vite discovers per-provider barrels at build time so the dist mirrors
the provider layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds Grok as a provider in the nightly OpenAPI sync. Source is xAI's
first-party OpenAPI spec at docs.x.ai/openapi.json (OpenAPI 3.1.0, 32
endpoints, 168 schemas). Public, no auth required for the spec.

Grok is API-compatible with OpenAI's chat completions at the wire level
but ships an independent schema set (different names, slightly different
shapes, plus xAI-specific endpoints: deferred-completion, documents/search,
per-modality model lists, video edits/extensions, tokenize-text, etc.).
Each provider stays isolated in the schemas package.

Bumps the build script's heap to 8 GB. With six providers now in the
single dts program, the default 4 GB limit was tight. Knip ignores
`vite` for ai-schemas since the script invokes the binary directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 22, 2026

Open in StackBlitz

@tanstack/ai

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

@tanstack/ai-anthropic

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

@tanstack/ai-client

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

@tanstack/ai-code-mode

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

@tanstack/ai-code-mode-skills

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

@tanstack/ai-devtools-core

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

@tanstack/ai-elevenlabs

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

@tanstack/ai-event-client

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

@tanstack/ai-fal

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

@tanstack/ai-gemini

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

@tanstack/ai-grok

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

@tanstack/ai-groq

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

@tanstack/ai-isolate-cloudflare

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

@tanstack/ai-isolate-node

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

@tanstack/ai-isolate-quickjs

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

@tanstack/ai-ollama

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

@tanstack/ai-openai

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

@tanstack/ai-openrouter

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

@tanstack/ai-preact

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

@tanstack/ai-react

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

@tanstack/ai-react-ui

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

@tanstack/ai-schemas

npm i https://pkg.pr.new/TanStack/ai/@tanstack/ai-schemas@622

@tanstack/ai-solid

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

@tanstack/ai-solid-ui

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

@tanstack/ai-svelte

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

@tanstack/ai-utils

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

@tanstack/ai-vue

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

@tanstack/ai-vue-ui

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

@tanstack/openai-base

npm i https://pkg.pr.new/TanStack/ai/@tanstack/openai-base@622

@tanstack/preact-ai-devtools

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

@tanstack/react-ai-devtools

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

@tanstack/solid-ai-devtools

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

commit: 843e490

tombeckenham and others added 4 commits May 22, 2026 17:11
…bles

The earlier `/* eslint-disable */` and `// @ts-nocheck` headers on every
generated file were holdovers from iterations before the spec-level
transforms (`coerceDefaults`, discriminator rewrites) cleaned up the
codegen. With those in place, the only real issues are:

- One `no-control-regex` lint error in `elevenlabs/zod.gen.ts` (a literal
  `\x09` in a regex pattern, faithful to upstream).
- One tsc error in `openai/zod.gen.ts` where the post-process rewrites
  `.extend()` on a discriminatedUnion to `z.intersection(...)` (runtime
  correct, but intersections aren't `$ZodTypeDiscriminable`).

Replace the blanket suppressors with two surgical mechanisms:

- `suppressControlRegexLines` injects
  `// eslint-disable-next-line no-control-regex` immediately above each
  regex literal containing a control-char escape.
- The `.extend()` rewriter now reports whether it touched anything; only
  files where it did get a two-line header (`ban-ts-comment` disable
  followed by `@ts-nocheck`) so the workspace lint rule doesn't fire.

Net effect: zero file-level disables, two line-level disables on the only
file that needs them, ~100 `no-explicit-any` warnings (warn-level in the
project config, do not fail CI). `pnpm test:eslint` and `pnpm test:types`
both walk the generated files in full and pass clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rkflow

`@hey-api/openapi-ts` runs with full code-execution privileges during
nightly codegen, so an unintentional bump shouldn't be possible. Drop the
caret on the version specifier (`^0.97.2` -> `0.97.2`) so future updates
have to land via an explicit PR. The lockfile already pinned the resolved
version; this just removes the wiggle room in the manifest.

Add a `pnpm audit --audit-level=high` step to sync-schemas.yml. It's
non-blocking (`continue-on-error: true`) because the workspace currently
carries pre-existing transitive advisories (e.g. an old protobufjs via
@google/genai used by ai-gemini) that aren't related to schemas codegen
and shouldn't be allowed to break the nightly. The step's purpose is to
surface any *new* advisory landing on the codegen dep tree so the human
reviewing the automated PR can spot it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
We already have pnpm's trust-downgrade policy active (refuses installs
where provenance attestation regressed), the heyapi version explicitly
pinned without a caret, and an automated PR pattern that forces human
review before any codegen change lands. A non-blocking audit step would
just be log noise, and a blocking one needs scope work we don't want to
take on right now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

Create schemas library

1 participant