Skip to content

Conversation

@andorep
Copy link

@andorep andorep commented Jan 12, 2026

🎯 Changes

Adding support for deepseek api

βœ… 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

    • DeepSeek adapter added with streaming chat, tool calling, and structured output (Zod-compatible); supports DeepSeek-V3, Reasoner, and Coder models with TypeScript type safety and per-model inference.
  • Documentation

    • New package README and changelog documenting usage, models, configuration, and release notes.
  • Tests

    • Added comprehensive tests validating adapter behavior, streaming, tool calls, thinking mode, and configuration handling.

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

@andorep andorep requested a review from a team January 12, 2026 07:34
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 12, 2026

πŸ“ Walkthrough

Walkthrough

Adds a new TypeScript package @tanstack/ai-deepseek with DeepSeek adapters (text and summarize), model metadata, tools and utils, tests, build/config, and documentation to integrate DeepSeek models (V3, Reasoner, Coder) into TanStack AI with streaming, structured output, and tool-calling.

Changes

Cohort / File(s) Summary
Core Adapters
packages/typescript/ai-deepseek/src/adapters/text.ts, packages/typescript/ai-deepseek/src/adapters/summarize.ts
New DeepSeekTextAdapter with streaming chat, structured output, multimodal handling, and factory helpers; DeepSeekSummarizeAdapter wraps text adapter with summarization prompts and streaming support.
Model Metadata & Types
packages/typescript/ai-deepseek/src/model-meta.ts, packages/typescript/ai-deepseek/src/message-types.ts
Defines DEEPSEEK_CHAT_MODELS, per-model input modalities, provider options, and multimodal message metadata types.
Utilities
packages/typescript/ai-deepseek/src/utils/client.ts, packages/typescript/ai-deepseek/src/utils/schema-converter.ts, packages/typescript/ai-deepseek/src/utils/index.ts
Adds DeepSeek client creation, env API key resolution, ID generation, null->undefined transformer, and schema conversion for DeepSeek structured output; re-exports utilities.
Tooling / Converters
packages/typescript/ai-deepseek/src/tools/function-tool.ts, packages/typescript/ai-deepseek/src/tools/tool-converter.ts, packages/typescript/ai-deepseek/src/tools/index.ts
Converts generic Tool objects to DeepSeek/OpenAI-compatible function tools (strict mode) and exposes converters and types.
Provider Options
packages/typescript/ai-deepseek/src/text/text-provider-options.ts
Adds DeepSeek provider option types (temperature, top_p, max_tokens, penalties, thinking flag) and internal/ external option aliases with a placeholder validator.
Package Entry & Exports
packages/typescript/ai-deepseek/src/index.ts
Tree-shakeable index re-exporting adapters, factories, model-meta, and message types.
Build, Config & Manifest
packages/typescript/ai-deepseek/package.json, packages/typescript/ai-deepseek/tsconfig.json, packages/typescript/ai-deepseek/vite.config.ts
Adds package.json, tsconfig, and Vite/Vitest config including build/test scripts, exports, and coverage setup.
Documentation & Changelog
packages/typescript/ai-deepseek/README.md, packages/typescript/ai-deepseek/CHANGELOG.md, .changeset/add-deepseek-adapter.md
Adds README, CHANGELOG, and changeset describing the new DeepSeek adapter package and features.
Tests
packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
New test suite validating factories, env handling, models, thinking mode, tool calling, streaming, and configuration scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Adapter as DeepSeekTextAdapter
    participant Converter as Option/Message Converter
    participant DeepSeekAPI as DeepSeek API (OpenAI-compatible)
    participant Processor as StreamProcessor

    Client->>Adapter: chatStream(options)
    Adapter->>Converter: mapTextOptionsToDeepSeek(options)
    Converter->>Adapter: mapped request payload
    Adapter->>DeepSeekAPI: POST /chat/completions (stream=true)
    DeepSeekAPI-->>Adapter: streaming chunks (events)
    Adapter->>Processor: processDeepSeekStreamChunks(stream)
    loop per chunk
        Processor-->>Client: yield StreamChunk (content / tool_call / done)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • AlemTuzlak
  • jherr

Poem

🐰 I hopped into code, eager and spry,
DeepSeek adapters now ready to fly.
Streams that whisper and tools that sing,
TanStack AI β€” new wonders we bring! πŸ₯•βœ¨

πŸš₯ Pre-merge checks | βœ… 3
βœ… Passed checks (3 passed)
Check name Status Explanation
Title check βœ… Passed The pull request title 'feat: add Deepseek support' accurately summarizes the main change, which is adding a new DeepSeek adapter package with complete integration for the TanStack AI framework.
Description check βœ… Passed The pull request description follows the template with all required sections completed: changes explained, contributing guide followed, local testing confirmed, and changeset generated for published code.
Docstring Coverage βœ… Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • πŸ“ Generate docstrings

🧹 Recent nitpick comments
packages/typescript/ai-deepseek/README.md (2)

1-3: Add alt text to the header image for accessibility.

The header image is missing alternative text, which is required for screen readers and accessibility compliance.

 <div align="center">
-  <img src="./media/header_ai.png" >
+  <img src="./media/header_ai.png" alt="TanStack AI DeepSeek Adapter" />
 </div>

46-46: Fix heading level to maintain proper hierarchy.

The heading jumps from h1 (line 36) to h3, skipping h2. This violates accessibility guidelines for heading structure.

-### <a href="https://tanstack.com/ai/docs/adapters/deepseek">Read the docs β†’</b></a>
+## <a href="https://tanstack.com/ai/docs/adapters/deepseek">Read the docs β†’</a>

Note: The </b> closing tag is also mismatched (no opening <b>).

packages/typescript/ai-deepseek/src/utils/client.ts (1)

40-45: Consider using slice(2) instead of substring(7) for consistent ID length.

Math.random().toString(36).substring(7) can produce inconsistent lengths because substring(7) depends on the random value's magnitude. Using slice(2) consistently removes just the "0." prefix.

♻️ Suggested improvement
 export function generateId(prefix: string): string {
-  return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`
+  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}`
 }
packages/typescript/ai-deepseek/src/utils/schema-converter.ts (1)

84-88: Consider extracting duplicate oneOf error handling.

The same error is thrown at lines 86-88 and 128-130. Consider extracting to a helper function for consistency.

♻️ Optional refactor
function throwOneOfUnsupportedError(): never {
  throw new Error(
    'oneOf is not supported in DeepSeek structured output schemas. Check the supported outputs here: https://platform.openai.com/docs/guides/structured-outputs#supported-types',
  )
}

Also applies to: 127-131

packages/typescript/ai-deepseek/src/message-types.ts (1)

46-58: Consider using type aliases for empty interfaces.

Biome flags these empty interfaces as equivalent to {}. While they serve as intentional placeholders for future DeepSeek multimodal support, type aliases would be cleaner and silence the linter.

♻️ Suggested refactor
-/**
- * Metadata for DeepSeek video content parts.
- * Note: Video support is currently not available in DeepSeek models.
- */
-export interface DeepSeekVideoMetadata {}
+/**
+ * Metadata for DeepSeek video content parts.
+ * Note: Video support is currently not available in DeepSeek models.
+ */
+export type DeepSeekVideoMetadata = Record<string, never>

-/**
- * Metadata for DeepSeek document content parts.
- * Note: Direct document support may vary; PDFs often need to be converted to images.
- */
-export interface DeepSeekDocumentMetadata {}
+/**
+ * Metadata for DeepSeek document content parts.
+ * Note: Direct document support may vary; PDFs often need to be converted to images.
+ */
+export type DeepSeekDocumentMetadata = Record<string, never>

-/**
- * Metadata for DeepSeek text content parts.
- * Currently no specific metadata options for text in DeepSeek.
- */
-export interface DeepSeekTextMetadata {}
+/**
+ * Metadata for DeepSeek text content parts.
+ * Currently no specific metadata options for text in DeepSeek.
+ */
+export type DeepSeekTextMetadata = Record<string, never>
packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts (1)

131-149: Tests could have stronger assertions.

These tests create adapters but don't actually verify thinking mode behavior - they only check that the adapter can be instantiated. While valid for ensuring no exceptions are thrown, they don't test the actual thinking mode functionality.

Consider adding integration tests (possibly with mocked responses) that verify:

  • thinking stream chunks are emitted for deepseek-reasoner
  • modelOptions: { thinking: true } actually enables thinking mode in the request

πŸ“œ Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between ec7de70 and e05a1cf.

πŸ“’ Files selected for processing (19)
  • .changeset/add-deepseek-adapter.md
  • packages/typescript/ai-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/README.md
  • packages/typescript/ai-deepseek/package.json
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.ts
  • packages/typescript/ai-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • packages/typescript/ai-deepseek/src/utils/client.ts
  • packages/typescript/ai-deepseek/src/utils/index.ts
  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/tsconfig.json
  • packages/typescript/ai-deepseek/vite.config.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/typescript/ai-deepseek/src/utils/index.ts
  • packages/typescript/ai-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • .changeset/add-deepseek-adapter.md
  • packages/typescript/ai-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/vite.config.ts
  • packages/typescript/ai-deepseek/tsconfig.json
  • packages/typescript/ai-deepseek/package.json
🧰 Additional context used
πŸ““ Path-based instructions (5)
**/*.{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-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/utils/client.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
**/*.{ts,tsx,js,jsx}

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

Use camelCase for function and variable names throughout the codebase

Files:

  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/utils/client.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
packages/typescript/*/src/model-meta.ts

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

Maintain model metadata files that define provider options and capabilities per model for per-model type safety

Files:

  • packages/typescript/ai-deepseek/src/model-meta.ts
packages/typescript/*/src/adapters/*.ts

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

Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking

Files:

  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/adapters/text.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-deepseek/tests/deepseek-adapter.test.ts
🧠 Learnings (13)
πŸ““ 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/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
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 .eslintrc* : Use ESLint with custom TanStack config for linting all TypeScript and JavaScript files
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
πŸ“š 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 Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference

Applied to files:

  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.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-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/README.md
πŸ“š 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-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/src/adapters/text.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: Maintain type safety through multimodal content support (image, audio, video, document) with model capability awareness

Applied to files:

  • packages/typescript/ai-deepseek/src/message-types.ts
πŸ“š Learning: 2025-12-27T20:22:51.232Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-gpt-oss.ts:92-97
Timestamp: 2025-12-27T20:22:51.232Z
Learning: In the ai-ollama package's model-meta files (packages/typescript/ai-ollama/src/meta/model-meta-*.ts), capability-related comments follow a standard template format across all files for consistency, even if the comment text doesn't precisely match individual model capabilities. This is an intentional design choice to maintain uniformity across the codebase.

Applied to files:

  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
πŸ“š Learning: 2025-12-27T21:39:29.563Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-llama-guard3.ts:70-75
Timestamp: 2025-12-27T21:39:29.563Z
Learning: The standard template comments in ai-ollama model-meta files (like "Models with text, image, audio, video (no document)") should not be modified to match individual model capabilities, as they are intentionally kept uniform across all model-meta-*.ts files for consistency, regardless of what each specific model actually supports.

Applied to files:

  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.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-deepseek/src/model-meta.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-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/README.md
πŸ“š 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: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top

Applied to files:

  • packages/typescript/ai-deepseek/CHANGELOG.md
πŸ“š 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-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/README.md
πŸ“š 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} : Implement isomorphic tool system using `toolDefinition()` with `.server()` and `.client()` implementations for dual-environment execution

Applied to files:

  • packages/typescript/ai-deepseek/src/tools/function-tool.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} : Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses

Applied to files:

  • packages/typescript/ai-deepseek/src/adapters/text.ts
🧬 Code graph analysis (6)
packages/typescript/ai-deepseek/src/utils/schema-converter.ts (1)
packages/typescript/ai-deepseek/src/utils/index.ts (2)
  • transformNullsToUndefined (8-8)
  • makeDeepSeekStructuredOutputCompatible (9-9)
packages/typescript/ai-deepseek/src/message-types.ts (1)
packages/typescript/ai-deepseek/src/index.ts (6)
  • DeepSeekImageMetadata (37-37)
  • DeepSeekAudioMetadata (38-38)
  • DeepSeekVideoMetadata (39-39)
  • DeepSeekDocumentMetadata (40-40)
  • DeepSeekTextMetadata (36-36)
  • DeepSeekMessageMetadataByModality (41-41)
packages/typescript/ai-deepseek/src/model-meta.ts (1)
packages/typescript/ai-deepseek/src/index.ts (5)
  • DEEPSEEK_CHAT_MODELS (34-34)
  • DeepSeekModelInputModalitiesByName (30-30)
  • DeepSeekChatModelProviderOptionsByName (29-29)
  • ResolveProviderOptions (31-31)
  • ResolveInputModalities (32-32)
packages/typescript/ai-deepseek/src/tools/function-tool.ts (2)
packages/typescript/ai/src/types.ts (1)
  • JSONSchema (25-64)
packages/typescript/ai-deepseek/src/utils/schema-converter.ts (1)
  • makeDeepSeekStructuredOutputCompatible (48-134)
packages/typescript/ai-deepseek/src/utils/client.ts (1)
packages/typescript/ai-deepseek/src/utils/index.ts (4)
  • DeepSeekClientConfig (5-5)
  • createDeepSeekClient (2-2)
  • getDeepSeekApiKeyFromEnv (3-3)
  • generateId (4-4)
packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts (4)
packages/typescript/ai-deepseek/src/adapters/text.ts (2)
  • createDeepSeekText (633-641)
  • deepseekText (667-675)
packages/typescript/ai-deepseek/src/index.ts (5)
  • createDeepSeekText (8-8)
  • deepseekText (9-9)
  • createDeepSeekSummarize (17-17)
  • deepseekSummarize (18-18)
  • DEEPSEEK_CHAT_MODELS (34-34)
packages/typescript/ai-deepseek/src/adapters/summarize.ts (2)
  • createDeepSeekSummarize (136-142)
  • deepseekSummarize (168-174)
packages/typescript/ai-deepseek/src/model-meta.ts (1)
  • DEEPSEEK_CHAT_MODELS (87-91)
πŸͺ› Biome (2.1.2)
packages/typescript/ai-deepseek/src/message-types.ts

[error] 46-46: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 52-52: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 58-58: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

πŸͺ› markdownlint-cli2 (0.18.1)
packages/typescript/ai-deepseek/README.md

2-2: Images should have alternate text (alt text)

(MD045, no-alt-text)


12-12: Hard tabs
Column: 1

(MD010, no-hard-tabs)


23-23: Hard tabs
Column: 1

(MD010, no-hard-tabs)


24-24: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 1

(MD010, no-hard-tabs)


46-46: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

πŸ”‡ Additional comments (26)
packages/typescript/ai-deepseek/README.md (1)

48-76: Good use of tree-shakeable adapter pattern.

The documentation correctly demonstrates importing adapters from the /adapters subpath, enabling tree-shaking as per project guidelines. Based on learnings, this aligns with the expected architecture.

packages/typescript/ai-deepseek/CHANGELOG.md (1)

1-23: LGTM!

The changelog accurately documents the initial release with appropriate detail on supported models, features, and the tree-shakeable adapter architecture.

packages/typescript/ai-deepseek/src/utils/client.ts (2)

3-16: LGTM!

The DeepSeekClientConfig interface and createDeepSeekClient function provide a clean abstraction over the OpenAI SDK with sensible defaults for DeepSeek's API endpoint.


22-38: LGTM!

The environment detection logic correctly handles both browser (window.env) and Node.js (process.env) environments with a clear error message when the API key is missing.

packages/typescript/ai-deepseek/src/model-meta.ts (4)

1-24: LGTM!

The ModelMeta interface provides a comprehensive schema for model metadata including input/output modalities, capabilities, context windows, and pricing. This aligns well with the project's per-model type safety guidelines. Based on learnings.


45-62: LGTM - tool_calling correctly excluded.

The deepseek-reasoner model correctly excludes tool_calling from capabilities, addressing the concern from the previous review that standard OpenAI-style function calling is not supported on this model.


132-152: LGTM!

The type resolution helpers provide excellent type-level inference for per-model provider options and input modalities, with sensible fallbacks for unknown models. This enables the compile-time safety emphasized in the coding guidelines.


26-43: Image input is supported on the deepseek-chat model through the OpenAI-compatible API (image_url field in message content arrays). The metadata declaration of input: ['text', 'image'] is accurate.

packages/typescript/ai-deepseek/src/utils/schema-converter.ts (1)

12-35: LGTM!

The transformNullsToUndefined function correctly handles the conversion of null values back to undefined (with omission) to match Zod schema expectations after DeepSeek returns nullable fields. The recursive handling of arrays and objects is well-implemented.

packages/typescript/ai-deepseek/src/tools/function-tool.ts (1)

1-45: Well-structured tool conversion with proper strict mode handling.

The implementation correctly:

  • Provides a sensible default schema when inputSchema is missing
  • Applies DeepSeek-specific transformations via makeDeepSeekStructuredOutputCompatible
  • Enforces strict: true for all function tools

Note: Line 34 sets additionalProperties = false which is already done by makeDeepSeekStructuredOutputCompatible for object types. This redundancy is acceptable as defensive coding for edge cases where the input schema might not be a standard object type.

packages/typescript/ai-deepseek/src/message-types.ts (2)

16-40: Well-documented metadata interfaces with appropriate options.

The DeepSeekImageMetadata and DeepSeekAudioMetadata interfaces are properly documented with JSDoc defaults and clear option descriptions. The image detail options align with the OpenAI-compatible API format.


64-70: Complete modality mapping.

The DeepSeekMessageMetadataByModality interface correctly maps all five content modalities to their respective metadata types, enabling proper type inference for multimodal messages.

packages/typescript/ai-deepseek/src/adapters/text.ts (7)

88-104: Well-structured adapter class with proper generics.

The class correctly extends BaseTextAdapter with proper type parameters for model-specific provider options and input modalities. The constructor properly initializes the OpenAI-compatible client.


106-142: Robust streaming with proper error propagation.

The chatStream method correctly:

  • Yields an error chunk before rethrowing, allowing consumers to handle errors gracefully
  • Uses consistent ID generation via generateId
  • Includes useful debugging information in error logs

254-402: Comprehensive stream chunk processing.

The stream processor correctly handles:

  • Content and reasoning deltas with proper accumulation
  • Tool calls streamed in chunks, accumulated by index in a Map
  • Proper finish reason detection for both explicit tool_calls and implicit tool presence
  • Error recovery with informative error chunks

The reasoning_content access via as any (line 283) is necessary since it's a DeepSeek-specific extension not in the base OpenAI types.


404-474: Clean options mapping with proper validation.

The method correctly:

  • Validates provider options when present
  • Converts tools to DeepSeek format
  • Prepends system prompts to the message array
  • Conditionally enables thinking mode via extra_body

553-616: Well-implemented helper methods.

The helper methods are clean and handle edge cases properly:

  • normalizeContent handles null/string/array uniformly
  • extractTextContent filters for text parts correctly
  • shouldEnableThinking provides clear logic for automatic vs manual activation

618-675: Tree-shakeable factory functions with good documentation.

The factory functions follow the project's tree-shakeable architecture pattern. deepseekText provides convenient environment-based API key detection while createDeepSeekText offers explicit control. Based on learnings, this aligns with the expected adapter export pattern.


144-252: Structured output implementation correctly uses DeepSeek's json_object mode with schema embedded in prompt.

The implementation appropriately handles DeepSeek's JSON output requirements by setting response_format: { type: 'json_object' } and embedding the schema description in the system prompt with the word "json" included. The extraction from response.choices[0]?.message.content matches DeepSeek's documented API response structure. The JSON parsing error handling at lines 232-238 provides helpful context with truncated content preview, and thinking mode integration via extra_body is correctly implemented.

packages/typescript/ai-deepseek/src/adapters/summarize.ts (3)

36-47: Clean adapter composition pattern.

The DeepSeekSummarizeAdapter correctly delegates to DeepSeekTextAdapter, following the single-responsibility principle and enabling tree-shaking as per project guidelines.


93-119: Clear prompt construction with style support.

The buildSummarizationPrompt method handles all summarization styles (bullet-points, paragraph, concise) and optional focus/length constraints in a readable manner.


122-174: Consistent factory function pattern.

The createDeepSeekSummarize and deepseekSummarize factory functions follow the same pattern as the text adapter, maintaining API consistency across the package.

packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts (4)

34-53: Environment variable handling is now properly implemented.

The test correctly saves the original DEEPSEEK_API_KEY before modification and properly restores it (or deletes it if originally undefined) in the cleanup. This addresses the previous review feedback.


81-105: Good model constant coverage.

The tests properly verify:

  • Expected model list matches DEEPSEEK_CHAT_MODELS
  • All models are accepted by both text and summarize adapters

This ensures type safety and prevents regressions when adding new models.


107-121: Appropriate type safety smoke tests.

These tests verify the adapter's public API surface exists and has the expected method types. While simple, they catch compile-time issues and ensure exports are correct.


277-291: Configuration tests provide good coverage.

Tests verify the adapter accepts custom baseURL and empty config objects without throwing, ensuring configuration flexibility.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

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: 8

πŸ€– Fix all issues with AI agents
In @packages/typescript/ai-deepseek/package.json:
- Around line 41-51: The package.json for ai-deepseek is missing zod in
devDependencies; add "zod": "^4.2.0" to the devDependencies section (alongside
@vitest/coverage-v8 and vite) so test/dev tooling matches ai-openai and
ai-anthropic and the peerDependency entry remains as-is.

In @packages/typescript/ai-deepseek/README.md:
- Around line 248-253: The README example uses eval(expression) inside the
tool.server implementation (serverTool) which promotes a security risk; replace
the eval call with a safe expression evaluator or parser (e.g., a math
expression parser) and update the serverTool/tool.server example to parse and
evaluate only numeric expressions, validate inputs (the expression parameter)
and return the numeric result object ({ result: number }) without executing
arbitrary JS code.

In @packages/typescript/ai-deepseek/src/adapters/summarize.ts:
- Around line 49-76: The summarize method is ignoring the provider-level
DeepSeekSummarizeProviderOptions (temperature and maxTokens) and instead
hardcodes temperature: 0.3 and uses options.maxLength; update summarize to use
the configured provider options (e.g., this.options.temperature and
this.options.maxTokens or a merged fallback) when calling
this.textAdapter.chatStream so temperature and maxTokens come from
DeepSeekSummarizeProviderOptions with sensible fallbacks to the per-call
SummarizationOptions (such as options.maxLength) if not set.

In @packages/typescript/ai-deepseek/src/adapters/text.ts:
- Around line 363-373: The tool message mapping currently uses
message.toolCallId || '' which can produce an empty tool_call_id and break
DeepSeek API calls; inside the block handling message.role === 'tool' (the tool
message mapping), validate that message.toolCallId exists and is non-empty and
throw a clear error if it is missing (instead of returning an empty string),
then populate tool_call_id with message.toolCallId; ensure the error message
references the message or context so callers can trace which tool message lacked
an id.

In @packages/typescript/ai-deepseek/src/model-meta.ts:
- Around line 45-62: DEEPSEEK_REASONER's metadata incorrectly advertises
tool_calling support; edit the DEEPSEEK_REASONER constant and remove
'tool_calling' from the supports.capabilities array so it only lists
['reasoning'] (retain other fields unchanged) to prevent consumers from
attempting unsupported OpenAI-style function/tool calls and direct tool-calling
workflows to deepseek-chat instead.

In @packages/typescript/ai-deepseek/src/utils/schema-converter.ts:
- Around line 64-91: The current else-if chain in
makeDeepSeekStructuredOutputCompatible leaves optional nested objects/arrays
non-nullable because recursion occurs before nullable handling; modify the
function so that when wasOptional is true you add 'null' to the property's type
regardless of whether prop.type === 'object' or prop.type === 'array' (either by
applying the nullable transformation before recursing into prop (for
objects/arrays) or by post-processing the already-recursed properties[propName]
to union its type with 'null'); update the branches handling prop.type ===
'object' and prop.type === 'array' to incorporate this nullable union for
optional propName and ensure Array.isArray checks use prop.type on the final
properties[propName] if you choose post-processing.

In @packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts:
- Around line 31-43: The test overwrites process.env.DEEPSEEK_API_KEY without
preserving the prior value; update the test that calls
deepseekText('deepseek-chat') to first store the original
process.env.DEEPSEEK_API_KEY (e.g., orig = process.env.DEEPSEEK_API_KEY), set
the env var to 'test-env-api-key', run the assertions on the returned adapter
(adapter.name, adapter.kind, adapter.model), and finally restore
process.env.DEEPSEEK_API_KEY to the saved original (or delete it if original was
undefined) so the environment is not mutated after the test.
🧹 Nitpick comments (4)
packages/typescript/ai-deepseek/src/message-types.ts (1)

46-58: Consider converting empty interfaces to type aliases or adding a brief justification comment.

The static analysis tool flags these empty interfaces. While keeping them as interfaces is valid for declaration merging and future extensibility, you could either:

  1. Add a brief comment explaining they're placeholders for future extension, or
  2. Convert to type aliases if declaration merging isn't needed

This is a minor stylistic preference; the current approach is acceptable.

♻️ Option: Convert to type aliases
-export interface DeepSeekVideoMetadata {}
+/** Placeholder for future video metadata options */
+export type DeepSeekVideoMetadata = Record<string, never>

-export interface DeepSeekDocumentMetadata {}
+/** Placeholder for future document metadata options */
+export type DeepSeekDocumentMetadata = Record<string, never>

-export interface DeepSeekTextMetadata {}
+/** Placeholder for future text metadata options */
+export type DeepSeekTextMetadata = Record<string, never>
packages/typescript/ai-deepseek/package.json (1)

15-20: Consider adding /adapters subpath export for tree-shaking.

Based on learnings, the package should expose adapters via a dedicated subpath export (e.g., @tanstack/ai-deepseek/adapters) to enable optimal tree-shaking and align with other adapter packages in the ecosystem.

♻️ Suggested exports configuration
   "exports": {
     ".": {
       "types": "./dist/esm/index.d.ts",
       "import": "./dist/esm/index.js"
+    },
+    "./adapters": {
+      "types": "./dist/esm/adapters/index.d.ts",
+      "import": "./dist/esm/adapters/index.js"
     }
   },
packages/typescript/ai-deepseek/src/utils/client.ts (1)

43-45: generateId may produce inconsistent ID lengths.

Math.random().toString(36).substring(7) can produce variable-length strings (0-6 characters) depending on the random value. For consistent, predictable IDs, consider using substring(2, 8) to always get 6 characters from the base-36 representation.

♻️ Suggested fix
 export function generateId(prefix: string): string {
-  return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`
+  return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`
 }
packages/typescript/ai-deepseek/src/adapters/text.ts (1)

78-85: Consider removing verbose console logging in production adapter.

The error handling logs the full error, stack trace, and message to console. While useful for debugging, this verbose logging may expose sensitive information and clutter production logs. Consider using a configurable debug mode or structured logging.

♻️ Suggested minimal logging
     } catch (error: unknown) {
       const err = error as Error
-      console.error('>>> chatStream: Fatal error during response creation <<<')
-      console.error('>>> Error message:', err.message)
-      console.error('>>> Error stack:', err.stack)
-      console.error('>>> Full error:', err)
       throw error
     }
πŸ“œ Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 0e37d8b and ec7de70.

πŸ“’ Files selected for processing (19)
  • .changeset/add-deepseek-adapter.md
  • packages/typescript/ai-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/README.md
  • packages/typescript/ai-deepseek/package.json
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.ts
  • packages/typescript/ai-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • packages/typescript/ai-deepseek/src/utils/client.ts
  • packages/typescript/ai-deepseek/src/utils/index.ts
  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/tsconfig.json
  • packages/typescript/ai-deepseek/vite.config.ts
🧰 Additional context used
πŸ““ Path-based instructions (6)
**/*.{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-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • packages/typescript/ai-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/vite.config.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/src/utils/client.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/utils/index.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.ts
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
**/*.{ts,tsx,js,jsx}

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

Use camelCase for function and variable names throughout the codebase

Files:

  • packages/typescript/ai-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • packages/typescript/ai-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/vite.config.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/src/utils/client.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/utils/index.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.ts
  • packages/typescript/ai-deepseek/src/adapters/summarize.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-deepseek/src/index.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-deepseek/tests/deepseek-adapter.test.ts
packages/typescript/*/src/adapters/*.ts

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

Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking

Files:

  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/adapters/summarize.ts
packages/typescript/*/src/model-meta.ts

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

Maintain model metadata files that define provider options and capabilities per model for per-model type safety

Files:

  • packages/typescript/ai-deepseek/src/model-meta.ts
🧠 Learnings (16)
πŸ““ 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/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
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: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
πŸ“š 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-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/vite.config.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/README.md
  • packages/typescript/ai-deepseek/src/utils/client.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • .changeset/add-deepseek-adapter.md
  • packages/typescript/ai-deepseek/src/utils/index.ts
  • packages/typescript/ai-deepseek/tsconfig.json
  • packages/typescript/ai-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/package.json
  • packages/typescript/ai-deepseek/src/adapters/summarize.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-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • packages/typescript/ai-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/README.md
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • .changeset/add-deepseek-adapter.md
  • packages/typescript/ai-deepseek/src/utils/index.ts
  • packages/typescript/ai-deepseek/tsconfig.json
  • packages/typescript/ai-deepseek/src/model-meta.ts
  • packages/typescript/ai-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/package.json
  • packages/typescript/ai-deepseek/src/tools/function-tool.ts
  • packages/typescript/ai-deepseek/src/adapters/summarize.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-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • packages/typescript/ai-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts
  • packages/typescript/ai-deepseek/README.md
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • .changeset/add-deepseek-adapter.md
  • packages/typescript/ai-deepseek/CHANGELOG.md
  • packages/typescript/ai-deepseek/package.json
  • packages/typescript/ai-deepseek/src/adapters/summarize.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} : Implement isomorphic tool system using `toolDefinition()` with `.server()` and `.client()` implementations for dual-environment execution

Applied to files:

  • packages/typescript/ai-deepseek/src/tools/index.ts
  • packages/typescript/ai-deepseek/src/tools/tool-converter.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.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-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/model-meta.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/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-deepseek/src/text/text-provider-options.ts
  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/index.ts
  • packages/typescript/ai-deepseek/src/adapters/text.ts
  • packages/typescript/ai-deepseek/src/model-meta.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: Maintain type safety through multimodal content support (image, audio, video, document) with model capability awareness

Applied to files:

  • packages/typescript/ai-deepseek/src/message-types.ts
πŸ“š Learning: 2025-12-27T20:22:51.232Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-gpt-oss.ts:92-97
Timestamp: 2025-12-27T20:22:51.232Z
Learning: In the ai-ollama package's model-meta files (packages/typescript/ai-ollama/src/meta/model-meta-*.ts), capability-related comments follow a standard template format across all files for consistency, even if the comment text doesn't precisely match individual model capabilities. This is an intentional design choice to maintain uniformity across the codebase.

Applied to files:

  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.ts
πŸ“š Learning: 2025-12-27T21:39:29.563Z
Learnt from: harry-whorlow
Repo: TanStack/ai PR: 117
File: packages/typescript/ai-ollama/src/meta/model-meta-llama-guard3.ts:70-75
Timestamp: 2025-12-27T21:39:29.563Z
Learning: The standard template comments in ai-ollama model-meta files (like "Models with text, image, audio, video (no document)") should not be modified to match individual model capabilities, as they are intentionally kept uniform across all model-meta-*.ts files for consistency, regardless of what each specific model actually supports.

Applied to files:

  • packages/typescript/ai-deepseek/src/message-types.ts
  • packages/typescript/ai-deepseek/src/model-meta.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-deepseek/vite.config.ts
  • packages/typescript/ai-deepseek/tsconfig.json
πŸ“š 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 .eslintrc* : Use ESLint with custom TanStack config for linting all TypeScript and JavaScript files

Applied to files:

  • packages/typescript/ai-deepseek/vite.config.ts
  • packages/typescript/ai-deepseek/tsconfig.json
  • packages/typescript/ai-deepseek/package.json
πŸ“š 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 Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference

Applied to files:

  • packages/typescript/ai-deepseek/src/utils/schema-converter.ts
  • packages/typescript/ai-deepseek/src/tools/function-tool.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: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top

Applied to files:

  • packages/typescript/ai-deepseek/README.md
  • packages/typescript/ai-deepseek/CHANGELOG.md
πŸ“š 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} : Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses

Applied to files:

  • packages/typescript/ai-deepseek/src/adapters/text.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/*/package.json : Use `workspace:*` protocol for internal package dependencies in package.json (e.g., `"tanstack/ai": "workspace:*"`)

Applied to files:

  • packages/typescript/ai-deepseek/package.json
🧬 Code graph analysis (3)
packages/typescript/ai-deepseek/src/text/text-provider-options.ts (4)
packages/typescript/ai-deepseek/src/index.ts (1)
  • DeepSeekTextProviderOptions (11-11)
packages/typescript/ai-deepseek/src/tools/function-tool.ts (1)
  • FunctionTool (6-6)
packages/typescript/ai-deepseek/src/tools/index.ts (1)
  • FunctionTool (1-1)
packages/typescript/ai-deepseek/src/adapters/text.ts (1)
  • ExternalTextProviderOptions (40-40)
packages/typescript/ai-deepseek/tests/deepseek-adapter.test.ts (4)
packages/typescript/ai-deepseek/src/adapters/text.ts (2)
  • createDeepSeekText (482-490)
  • deepseekText (516-524)
packages/typescript/ai-deepseek/src/index.ts (5)
  • createDeepSeekText (8-8)
  • deepseekText (9-9)
  • createDeepSeekSummarize (17-17)
  • deepseekSummarize (18-18)
  • DEEPSEEK_CHAT_MODELS (34-34)
packages/typescript/ai-deepseek/src/adapters/summarize.ts (2)
  • createDeepSeekSummarize (136-142)
  • deepseekSummarize (168-174)
packages/typescript/ai-deepseek/src/model-meta.ts (1)
  • DEEPSEEK_CHAT_MODELS (87-91)
packages/typescript/ai-deepseek/src/model-meta.ts (1)
packages/typescript/ai-deepseek/src/index.ts (5)
  • DEEPSEEK_CHAT_MODELS (34-34)
  • DeepSeekModelInputModalitiesByName (30-30)
  • DeepSeekChatModelProviderOptionsByName (29-29)
  • ResolveProviderOptions (31-31)
  • ResolveInputModalities (32-32)
πŸͺ› Biome (2.1.2)
packages/typescript/ai-deepseek/src/message-types.ts

[error] 46-46: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 52-52: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 58-58: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

πŸ”‡ Additional comments (24)
packages/typescript/ai-deepseek/tsconfig.json (1)

1-9: LGTM!

The TypeScript configuration correctly extends the base config and sets up appropriate paths for the new package.

packages/typescript/ai-deepseek/CHANGELOG.md (1)

1-23: LGTM!

The changelog comprehensively documents the initial release with accurate feature descriptions and appropriate caveats about limited multimodal support.

packages/typescript/ai-deepseek/src/message-types.ts (1)

64-70: LGTM!

The metadata mapping interface provides clean type inference for multimodal message construction.

packages/typescript/ai-deepseek/src/utils/schema-converter.ts (2)

12-35: LGTM!

The null-to-undefined transformation handles primitives, arrays, and objects correctly with clear documentation of the behavior.


119-135: LGTM!

The utility provides reasonable handling for schema formats with appropriate error messaging for unsupported Zod schemas.

.changeset/add-deepseek-adapter.md (1)

1-5: LGTM!

The changeset is properly formatted with an appropriate minor version bump for the new adapter package.

packages/typescript/ai-deepseek/src/tools/tool-converter.ts (1)

9-17: LGTM!

Clean implementation with appropriate documentation explaining the function-tool-only conversion for DeepSeek's OpenAI-compatible API.

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

1-2: LGTM!

Clean barrel exports following the tree-shakeable adapter architecture pattern. Individual exports enable consumers to import only what they need. Based on learnings about subpath exports.

packages/typescript/ai-deepseek/vite.config.ts (1)

1-36: LGTM!

Well-structured Vitest configuration with appropriate coverage settings, exclusions, and integration with TanStack's shared Vite config. The ESM-only output (cjs: false) aligns with modern package distribution.

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

97-124: LGTM!

Good coverage for type safety assertions and configuration acceptance. The runtime checks for expected method types provide useful compile-time and runtime guarantees.


71-78: No issues found. The test correctly verifies that DEEPSEEK_CHAT_MODELS matches the actual model names defined in model-meta.ts: DEEPSEEK_V3.name ('deepseek-chat'), DEEPSEEK_REASONER.name ('deepseek-reasoner'), and DEEPSEEK_CODER_V2_INSTRUCT.name ('deepseek-coder').

packages/typescript/ai-deepseek/src/tools/function-tool.ts (2)

19-45: LGTM!

The conversion logic correctly handles schema defaults, applies DeepSeek-specific strict mode transformations, and returns a properly typed FunctionTool. The satisfies keyword ensures type safety without widening.


1-3: No issue foundβ€”the import path is correct. The function makeDeepSeekStructuredOutputCompatible is properly exported from schema-converter.ts (line 48), so the import on line 1 of function-tool.ts will resolve successfully without errors.

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

1-9: LGTM!

Clean barrel exports consolidating utility functions with clear module separation. This enables tree-shaking and provides a clean public API surface for DeepSeek utilities. Based on learnings about tree-shakeable exports.

packages/typescript/ai-deepseek/README.md (1)

1-311: Documentation is comprehensive and well-structured.

The README provides excellent coverage of installation, usage patterns, streaming, tool calling, structured output, configuration, and error handling. The tree-shakeable adapter documentation aligns well with the coding guidelines.

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

1-42: Well-organized tree-shakeable exports.

The index file properly separates adapter exports from type exports, enabling tree-shaking and minimizing bundle size. This aligns with the coding guidelines for the package structure. Based on learnings, the tree-shakeable adapter architecture is correctly implemented.

packages/typescript/ai-deepseek/src/model-meta.ts (1)

1-44: Model metadata structure is well-designed.

The ModelMeta interface and type-safe mappings (ResolveProviderOptions, ResolveInputModalities) provide excellent compile-time safety for per-model configuration. This aligns with the coding guidelines for maintaining model metadata files. Based on learnings, per-model type safety is correctly implemented.

Also applies to: 64-152

packages/typescript/ai-deepseek/src/utils/client.ts (1)

1-38: Client creation and environment detection look good.

The createDeepSeekClient properly wraps the OpenAI SDK with DeepSeek's base URL, and getDeepSeekApiKeyFromEnv handles both Node.js and browser environments with clear error messaging.

packages/typescript/ai-deepseek/src/text/text-provider-options.ts (1)

1-77: Well-structured provider options with clear documentation.

The type hierarchy (base β†’ text β†’ internal) provides clean separation of concerns. JSDoc comments document valid ranges for parameters. The no-op validator is an acceptable placeholder that maintains the validation contract for future enhancement.

packages/typescript/ai-deepseek/src/adapters/summarize.ts (2)

93-119: Prompt building logic is well-implemented.

The buildSummarizationPrompt method handles different summarization styles cleanly with appropriate prompts for bullet-points, paragraph, and concise formats. Focus and maxLength constraints are properly incorporated.


122-174: Factory functions follow established patterns.

Both createDeepSeekSummarize and deepseekSummarize factory functions mirror the text adapter's patterns, providing consistent API for explicit and environment-based API key usage. Documentation is thorough with examples.

packages/typescript/ai-deepseek/src/adapters/text.ts (3)

100-171: Structured output implementation handles DeepSeek's limitations well.

The implementation correctly notes that DeepSeek doesn't support OpenAI's json_schema format and instead embeds the schema in the prompt with json_object mode. The error handling for JSON parse failures provides useful context.


173-305: Stream processing is robust with proper tool call accumulation.

The processDeepSeekStreamChunks method correctly handles incremental tool call arguments, accumulates content, and properly emits all event types. The toolCallsInProgress map pattern handles the streaming nature of tool calls well.


430-524: Factory functions and helper methods are well-implemented.

The createDeepSeekText and deepseekText factories follow established patterns with proper type inference. Content normalization helpers (normalizeContent, extractTextContent) handle edge cases correctly.

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.

1 participant