Skip to content

Conversation

@AlemTuzlak
Copy link
Contributor

@AlemTuzlak AlemTuzlak commented Dec 24, 2025

🎯 Changes

βœ… Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

πŸš€ Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • New Features

    • Added model metadata exports for Anthropic, Gemini, and OpenAI providers
    • Added utilities to create and extend adapters with custom models
  • Documentation

    • New guide on extending adapter factories with custom models, including usage examples and configuration options
  • Tests

    • Comprehensive test suite for adapter extension functionality

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 24, 2025

πŸ“ Walkthrough

Walkthrough

This PR introduces adapter extension utilities that allow developers to extend existing adapter factories with custom models. New utilities include createModel, extendAdapter, and type inference helpers. Model constants are re-exported from provider packages. Documentation and comprehensive tests are included.

Changes

Cohort / File(s) Summary
Documentation
docs/guides/extend-adapter.md
New guide explaining how to extend adapters with custom models using createModel and extendAdapter, including examples for OpenAI-compatible proxies and fine-tuned models.
Model constant exports
packages/typescript/ai-anthropic/src/index.ts, packages/typescript/ai-gemini/src/index.ts, packages/typescript/ai-openai/src/index.ts
Added public re-exports of model constants: ANTHROPIC_MODELS, GEMINI_MODELS, and OPENAI_CHAT_MODELS from respective model-meta modules.
Adapter extension utilities
packages/typescript/ai/src/extend-adapter.ts
New module introducing ExtendedModelDef interface, createModel helper, type inference utilities (ExtractCustomModelNames, InferFactoryModels, InferConfig, InferAdapterReturn), and extendAdapter function for composing adapters with custom models.
Index exports
packages/typescript/ai/src/index.ts
Added re-exports of createModel, extendAdapter, and ExtendedModelDef type from ./extend-adapter.
Tests
packages/typescript/ai/tests/extend-adapter.test.ts
Comprehensive test suite validating adapter extension behavior, config passthrough, type inference, and custom model handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • jherr

Poem

🐰 With models extended and factories combined,
Custom adapters now perfectly aligned,
Types kept safe through TypeScript's guard,
Creating new adapters becomes less hard,
This humble rabbit hops with delight! πŸŽ‰

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description uses the required template structure but the 'Changes' section is entirely empty, leaving no explanation of what was implemented or why, despite significant code additions. Fill in the 'Changes' section with details about extendAdapter and createModel utilities, explain their purpose, and check the applicable checklist items to confirm testing and changeset status.
βœ… Passed checks (2 passed)
Check name Status Explanation
Title check βœ… Passed The title 'feat: extend adapter and create custom model utilities' directly and clearly matches the main changes: new extendAdapter and createModel utilities are added across the codebase.
Docstring Coverage βœ… Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/extend-adapter

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.

@nx-cloud
Copy link

nx-cloud bot commented Dec 24, 2025

View your CI Pipeline Execution β†— for commit 0dd7195

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... βœ… Succeeded 2m 24s View β†—
nx run-many --targets=build --exclude=examples/** βœ… Succeeded 1m 1s View β†—

☁️ Nx Cloud last updated this comment at 2025-12-24 14:23:09 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 24, 2025

Open in StackBlitz

@tanstack/ai

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

@tanstack/ai-anthropic

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

@tanstack/ai-client

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

@tanstack/ai-devtools-core

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

@tanstack/ai-gemini

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

@tanstack/ai-ollama

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

@tanstack/ai-openai

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

@tanstack/ai-react

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

@tanstack/ai-react-ui

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

@tanstack/ai-solid

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

@tanstack/ai-solid-ui

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

@tanstack/ai-svelte

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

@tanstack/ai-vue

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

@tanstack/ai-vue-ui

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

@tanstack/react-ai-devtools

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

@tanstack/solid-ai-devtools

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

commit: 0dd7195

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
docs/guides/extend-adapter.md (2)

12-13: Minor formatting: add space after comma for consistency.

The code style in the example is inconsistent with other examples in this file.

πŸ”Ž Suggested fix
-const myOpenaiModel = createModel('my-fine-tuned-gpt4',['text', 'image']);
-const myOpenaiModelButCooler = createModel('my-fine-tuned-gpt5',['text', 'image']);
+const myOpenaiModel = createModel('my-fine-tuned-gpt4', ['text', 'image']);
+const myOpenaiModelButCooler = createModel('my-fine-tuned-gpt5', ['text', 'image']);

61-65: Consider adding as const to demonstrate proper tuple inference.

Without as const, the array type will be inferred as ExtendedModelDef[] rather than a tuple, which may not provide the expected literal type inference for model names.

πŸ”Ž Suggested fix
 const models = [
   createModel('text-only-model', ['text']),
   createModel('multimodal-model', ['text', 'image', 'audio']),
-] as const
+] as const  // Required for literal type inference

Note: The as const is already present, but a brief inline comment would help clarify why it's necessary.

packages/typescript/ai/tests/extend-adapter.test.ts (1)

198-222: Consider clarifying the type test comment.

The comment says "should infer custom model name type" but the assertion checks that adapter.model extends MockModel. This is expected behavior (the returned adapter type comes from the original factory), but the comment could be clearer about what's actually being verified.

πŸ”Ž Suggested clarification
   describe('Type inference for custom models', () => {
-    it('should infer custom model name type', () => {
+    it('should return adapter with original factory return type', () => {
       const extendedMock = extendAdapter(mockText, customModels)
       const adapter = extendedMock('my-fine-tuned-model')

-      // The adapter model type is the union of all possible models from the factory return
-      // (This is expected since extendAdapter returns the factory's return type)
+      // The adapter's model property type comes from the original factory's return type
+      // Custom model names are accepted as input but the return type is InferAdapterReturn<TFactory>
       expectTypeOf(adapter.model).toExtend<MockModel>()
     })
πŸ“œ Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between f4019b9 and 0dd7195.

πŸ“’ Files selected for processing (7)
  • docs/guides/extend-adapter.md
  • packages/typescript/ai-anthropic/src/index.ts
  • packages/typescript/ai-gemini/src/index.ts
  • packages/typescript/ai-openai/src/index.ts
  • packages/typescript/ai/src/extend-adapter.ts
  • packages/typescript/ai/src/index.ts
  • packages/typescript/ai/tests/extend-adapter.test.ts
🧰 Additional context used
πŸ““ Path-based instructions (4)
**/*.{ts,tsx}

πŸ“„ CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from /adapters subpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions with toolDefinition() and Zod schema inference
Implement isomorphic tool system using toolDefinition() with .server() and .client() implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses

Files:

  • packages/typescript/ai-openai/src/index.ts
  • packages/typescript/ai-anthropic/src/index.ts
  • packages/typescript/ai-gemini/src/index.ts
  • packages/typescript/ai/tests/extend-adapter.test.ts
  • packages/typescript/ai/src/index.ts
  • packages/typescript/ai/src/extend-adapter.ts
packages/typescript/*/src/index.ts

πŸ“„ CodeRabbit inference engine (CLAUDE.md)

Export tree-shakeable adapters with clear subpath exports in package.json (e.g., @tanstack/ai/adapters, @tanstack/ai-openai/adapters) to minimize bundle size

Files:

  • packages/typescript/ai-openai/src/index.ts
  • packages/typescript/ai-anthropic/src/index.ts
  • packages/typescript/ai-gemini/src/index.ts
  • packages/typescript/ai/src/index.ts
**/*.{ts,tsx,js,jsx}

πŸ“„ CodeRabbit inference engine (CLAUDE.md)

Use camelCase for function and variable names throughout the codebase

Files:

  • packages/typescript/ai-openai/src/index.ts
  • packages/typescript/ai-anthropic/src/index.ts
  • packages/typescript/ai-gemini/src/index.ts
  • packages/typescript/ai/tests/extend-adapter.test.ts
  • packages/typescript/ai/src/index.ts
  • packages/typescript/ai/src/extend-adapter.ts
**/*.test.ts

πŸ“„ CodeRabbit inference engine (CLAUDE.md)

Write unit tests using Vitest alongside source files with .test.ts naming convention

Files:

  • packages/typescript/ai/tests/extend-adapter.test.ts
🧠 Learnings (7)
πŸ““ Common learnings
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/model-meta.ts : Maintain model metadata files that define provider options and capabilities per model for per-model type safety
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
πŸ“š Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/model-meta.ts : Maintain model metadata files that define provider options and capabilities per model for per-model type safety

Applied to files:

  • packages/typescript/ai-openai/src/index.ts
  • packages/typescript/ai-anthropic/src/index.ts
  • packages/typescript/ai-gemini/src/index.ts
  • docs/guides/extend-adapter.md
  • packages/typescript/ai/tests/extend-adapter.test.ts
  • packages/typescript/ai/src/index.ts
  • packages/typescript/ai/src/extend-adapter.ts
πŸ“š Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size

Applied to files:

  • packages/typescript/ai-openai/src/index.ts
  • packages/typescript/ai-anthropic/src/index.ts
  • packages/typescript/ai-gemini/src/index.ts
  • packages/typescript/ai/tests/extend-adapter.test.ts
  • packages/typescript/ai/src/index.ts
  • packages/typescript/ai/src/extend-adapter.ts
πŸ“š Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety

Applied to files:

  • packages/typescript/ai-anthropic/src/index.ts
  • docs/guides/extend-adapter.md
  • packages/typescript/ai/src/extend-adapter.ts
πŸ“š Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking

Applied to files:

  • packages/typescript/ai-gemini/src/index.ts
  • docs/guides/extend-adapter.md
  • packages/typescript/ai/tests/extend-adapter.test.ts
  • packages/typescript/ai/src/index.ts
  • packages/typescript/ai/src/extend-adapter.ts
πŸ“š Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters

Applied to files:

  • packages/typescript/ai-gemini/src/index.ts
  • docs/guides/extend-adapter.md
  • packages/typescript/ai/tests/extend-adapter.test.ts
  • packages/typescript/ai/src/index.ts
  • packages/typescript/ai/src/extend-adapter.ts
πŸ“š Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.test.ts : Write unit tests using Vitest alongside source files with `.test.ts` naming convention

Applied to files:

  • packages/typescript/ai/tests/extend-adapter.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
πŸ”‡ Additional comments (10)
packages/typescript/ai-openai/src/index.ts (1)

82-88: LGTM!

The new OPENAI_CHAT_MODELS export follows the existing pattern and aligns with the tree-shakeable architecture. This enables consumers to access chat model metadata for use with the new extendAdapter utilities.

packages/typescript/ai-anthropic/src/index.ts (1)

31-31: LGTM!

The ANTHROPIC_MODELS export is consistent with the pattern used in other provider packages.

packages/typescript/ai-gemini/src/index.ts (1)

55-59: LGTM!

The new GEMINI_MODELS export provides consistency with other provider packages (ANTHROPIC_MODELS, OPENAI_CHAT_MODELS) while the existing GeminiTextModels alias is preserved for backward compatibility.

packages/typescript/ai/tests/extend-adapter.test.ts (2)

1-19: LGTM!

Comprehensive test suite with clear documentation of what's being verified. Good use of type-level testing with expectTypeOf alongside runtime assertions.


76-119: Mock adapter implementation is well-structured.

The mock accurately represents the per-model type patterns (provider options and input modalities by model name) used by real adapters like OpenAI. The eslint-disable comments for @typescript-eslint/require-await are acceptable for async generator mocks.

packages/typescript/ai/src/index.ts (1)

115-118: LGTM!

The new exports follow the established patterns: runtime values exported directly, types exported with type keyword. The grouping under "Adapter extension utilities" is clear and maintains the file's organization.

packages/typescript/ai/src/extend-adapter.ts (4)

61-70: LGTM!

Good use of const generic modifiers to preserve literal types without requiring callers to use as const. The modelOptions: {} as unknown is appropriate since it's only used as a type brand.


91-98: Type fallback behavior is reasonable.

The fallback to string when model type can't be inferred provides a safe default. This ensures the utility works even with unconventional factory signatures, though the extended model union won't provide type safety in those edge cases.


166-182: Clean implementation with appropriate type-level design.

The runtime passthrough (return factory as any) is intentional per the documented behavior - all validation happens at compile time. The _customModels parameter is correctly prefixed to indicate it's unused at runtime but required for type inference.

One consideration: if a user passes an invalid custom model name at runtime, the error will come from the underlying provider API rather than this utility. This is documented in the guide but worth noting.


103-108: No changes needed. The InferConfig utility correctly returns undefined when a factory has no config parameter, and the conditional spread (lines 174-176) properly handles this case by using an empty args array. This behavior is already tested in the codebase with factories like ollamaText that accept only a model parameter without optional config.

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