add-provider-package

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Adding a New Provider Package

添加新的提供商包

This guide covers the process of creating a new
@ai-sdk/<provider>
package to integrate an AI service into the AI SDK.
本指南介绍了创建新的
@ai-sdk/<provider>
包以将AI服务集成到AI SDK中的完整流程。

First-Party vs Third-Party Providers

官方提供商与第三方提供商

  • Third-party packages: Any provider can create a third-party package. We're happy to link to it from our documentation.
  • First-party
    @ai-sdk/<provider>
    packages
    : If you prefer a first-party package, please create an issue first to discuss.
  • 第三方包:任何提供商都可以创建第三方包。我们会很乐意在文档中添加相关链接。
  • 官方
    @ai-sdk/<provider>
    :如果你希望创建官方包,请先创建一个issue进行讨论。

Reference Example

参考示例

Provider Architecture

提供商架构

The AI SDK uses a layered provider architecture following the adapter pattern:
  1. Specifications (
    @ai-sdk/provider
    ): Defines interfaces like
    LanguageModelV3
    ,
    EmbeddingModelV3
    , etc.
  2. Utilities (
    @ai-sdk/provider-utils
    ): Shared code for implementing providers
  3. Providers (
    @ai-sdk/<provider>
    ): Concrete implementations for each AI service
  4. Core (
    ai
    ): High-level functions like
    generateText
    ,
    streamText
    ,
    generateObject
AI SDK采用遵循适配器模式的分层提供商架构:
  1. 规范层 (
    @ai-sdk/provider
    ):定义
    LanguageModelV3
    EmbeddingModelV3
    等接口。
  2. 工具层 (
    @ai-sdk/provider-utils
    ):用于实现提供商的共享代码
  3. 提供商层 (
    @ai-sdk/<provider>
    ):每个AI服务的具体实现
  4. 核心层 (
    ai
    ):高级函数,如
    generateText
    streamText
    generateObject

Step-by-Step Guide

分步指南

1. Create Package Structure

1. 创建包结构

Create a new folder
packages/<provider>
with the following structure:
packages/<provider>/
├── src/
│   ├── index.ts                  # Main exports
│   ├── version.ts                # Package version
│   ├── <provider>-provider.ts    # Provider implementation
│   ├── <provider>-provider.test.ts
│   ├── <provider>-*-options.ts   # Model-specific options
│   └── <provider>-*-model.ts     # Model implementations (e.g., language, embedding, image)
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── tsup.config.ts
├── turbo.json
├── vitest.node.config.js
├── vitest.edge.config.js
└── README.md
Do not create a
CHANGELOG.md
file. It will be auto-generated.
packages/<provider>
路径下创建新文件夹,结构如下:
packages/<provider>/
├── src/
│   ├── index.ts                  # 主导出文件
│   ├── version.ts                # 包版本文件
│   ├── <provider>-provider.ts    # 提供商实现文件
│   ├── <provider>-provider.test.ts
│   ├── <provider>-*-options.ts   # 模型专属配置选项
│   └── <provider>-*-model.ts     # 模型实现(例如:语言模型、嵌入模型、图像模型)
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── tsup.config.ts
├── turbo.json
├── vitest.node.config.js
├── vitest.edge.config.js
└── README.md
无需创建
CHANGELOG.md
文件,它会自动生成。

2. Configure package.json

2. 配置package.json

Set up your
package.json
with:
  • "name": "@ai-sdk/<provider>"
  • "version": "0.0.0"
    (initial version, will be updated by changeset)
  • "license": "Apache-2.0"
  • "sideEffects": false
  • Dependencies on
    @ai-sdk/provider
    and
    @ai-sdk/provider-utils
    (use
    workspace:*
    )
  • Dev dependencies:
    @ai-sdk/test-server
    ,
    @types/node
    ,
    @vercel/ai-tsconfig
    ,
    tsup
    ,
    typescript
    ,
    zod
  • "engines": { "node": ">=18" }
  • Peer dependency on
    zod
    (both v3 and v4):
    "zod": "^3.25.76 || ^4.1.8"
Example exports configuration:
json
{
  "exports": {
    "./package.json": "./package.json",
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    }
  }
}
按以下要求设置
package.json
  • "name": "@ai-sdk/<provider>"
  • "version": "0.0.0"
    (初始版本,后续会由changeset更新)
  • "license": "Apache-2.0"
  • "sideEffects": false
  • 依赖
    @ai-sdk/provider
    @ai-sdk/provider-utils
    (使用
    workspace:*
  • 开发依赖:
    @ai-sdk/test-server
    ,
    @types/node
    ,
    @vercel/ai-tsconfig
    ,
    tsup
    ,
    typescript
    ,
    zod
  • "engines": { "node": ">=18" }
  • 对等依赖
    zod
    (支持v3和v4版本):
    "zod": "^3.25.76 || ^4.1.8"
导出配置示例:
json
{
  "exports": {
    "./package.json": "./package.json",
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    }
  }
}

3. Create TypeScript Configurations

3. 创建TypeScript配置

tsconfig.json:
json
{
  "extends": "@vercel/ai-tsconfig/base.json",
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "dist"]
}
tsconfig.build.json:
json
{
  "extends": "./tsconfig.json",
  "exclude": [
    "**/*.test.ts",
    "**/*.test-d.ts",
    "**/__snapshots__",
    "**/__fixtures__"
  ]
}
tsconfig.json:
json
{
  "extends": "@vercel/ai-tsconfig/base.json",
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "dist"]
}
tsconfig.build.json:
json
{
  "extends": "./tsconfig.json",
  "exclude": [
    "**/*.test.ts",
    "**/*.test-d.ts",
    "**/__snapshots__",
    "**/__fixtures__"
  ]
}

4. Configure Build Tool (tsup)

4. 配置构建工具(tsup)

Create
tsup.config.ts
:
typescript
import { defineConfig } from 'tsup';

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm'],
  dts: true,
  sourcemap: true,
  clean: true,
});
创建
tsup.config.ts
typescript
import { defineConfig } from 'tsup';

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm'],
  dts: true,
  sourcemap: true,
  clean: true,
});

5. Configure Test Runners

5. 配置测试运行器

Create both
vitest.node.config.js
and
vitest.edge.config.js
(copy from existing provider like
anthropic
).
创建
vitest.node.config.js
vitest.edge.config.js
(可复制现有提供商如
anthropic
的配置)。

6. Implement Provider

6. 实现提供商

Provider implementation pattern:
typescript
// <provider>-provider.ts
import { NoSuchModelError } from '@ai-sdk/provider';
import { loadApiKey } from '@ai-sdk/provider-utils';

export interface ProviderSettings {
  apiKey?: string;
  baseURL?: string;
  // provider-specific settings
}

export class ProviderInstance {
  readonly apiKey?: string;
  readonly baseURL?: string;

  constructor(options: ProviderSettings = {}) {
    this.apiKey = options.apiKey;
    this.baseURL = options.baseURL;
  }

  private get baseConfig() {
    return {
      apiKey: () =>
        loadApiKey({
          apiKey: this.apiKey,
          environmentVariableName: 'PROVIDER_API_KEY',
          description: 'Provider API key',
        }),
      baseURL: this.baseURL ?? 'https://api.provider.com',
    };
  }

  languageModel(modelId: string) {
    return new ProviderLanguageModel(modelId, this.baseConfig);
  }

  // Shorter alias
  chat(modelId: string) {
    return this.languageModel(modelId);
  }
}

// Export default instance
export const providerName = new ProviderInstance();
提供商实现模式
typescript
// <provider>-provider.ts
import { NoSuchModelError } from '@ai-sdk/provider';
import { loadApiKey } from '@ai-sdk/provider-utils';

export interface ProviderSettings {
  apiKey?: string;
  baseURL?: string;
  // 提供商专属配置
}

export class ProviderInstance {
  readonly apiKey?: string;
  readonly baseURL?: string;

  constructor(options: ProviderSettings = {}) {
    this.apiKey = options.apiKey;
    this.baseURL = options.baseURL;
  }

  private get baseConfig() {
    return {
      apiKey: () =>
        loadApiKey({
          apiKey: this.apiKey,
          environmentVariableName: 'PROVIDER_API_KEY',
          description: 'Provider API key',
        }),
      baseURL: this.baseURL ?? 'https://api.provider.com',
    };
  }

  languageModel(modelId: string) {
    return new ProviderLanguageModel(modelId, this.baseConfig);
  }

  // 简写别名
  chat(modelId: string) {
    return this.languageModel(modelId);
  }
}

// 导出默认实例
export const providerName = new ProviderInstance();

7. Implement Model Classes

7. 实现模型类

Each model type (language, embedding, image, etc.) should implement the appropriate interface from
@ai-sdk/provider
:
  • LanguageModelV3
    for text generation models
  • EmbeddingModelV3
    for embedding models
  • ImageModelV1
    for image generation models
  • etc.
Schema guidelines:
Provider Options (user-facing):
  • Use
    .optional()
    unless
    null
    is meaningful
  • Be as restrictive as possible for future flexibility
Response Schemas (API responses):
  • Use
    .nullish()
    instead of
    .optional()
  • Keep minimal - only include properties you need
  • Allow flexibility for provider API changes
每种模型类型(语言、嵌入、图像等)都应实现
@ai-sdk/provider
中的对应接口:
  • 文本生成模型实现
    LanguageModelV3
  • 嵌入模型实现
    EmbeddingModelV3
  • 图像生成模型实现
    ImageModelV1
  • 其他模型类型依此类推
Schema规范
提供商配置选项(面向用户):
  • 除非
    null
    有特定含义,否则使用
    .optional()
  • 为了未来的灵活性,尽可能设置严格的限制
响应Schema(API响应):
  • 使用
    .nullish()
    而非
    .optional()
  • 保持精简 - 仅包含需要的属性
  • 为提供商API的变更预留灵活性

8. Create README.md

8. 创建README.md

Include:
  • Brief description linking to documentation
  • Installation instructions
  • Basic usage example
  • Link to full documentation
应包含:
  • 简短描述并链接至文档
  • 安装说明
  • 基础使用示例
  • 完整文档链接

9. Write Tests

9. 编写测试

  • Unit tests for provider logic
  • API response parsing tests using fixtures in
    __fixtures__
    subdirectory
  • Both Node.js and Edge runtime tests
See
capture-api-response-test-fixture
skill for capturing real API responses for testing.
  • 提供商逻辑的单元测试
  • 使用
    __fixtures__
    子目录中的测试数据进行API响应解析测试
  • 同时包含Node.js和Edge运行时测试
可参考
capture-api-response-test-fixture
工具来捕获真实API响应用于测试。

10. Add Examples

10. 添加示例

Create examples in
examples/ai-functions/src/
for each model type the provider supports:
  • generate-text/<provider>.ts
    - Basic text generation
  • stream-text/<provider>.ts
    - Streaming text
  • generate-object/<provider>.ts
    - Structured output (if supported)
  • stream-object/<provider>.ts
    - Streaming structured output (if supported)
  • embed/<provider>.ts
    - Embeddings (if supported)
  • generate-image/<provider>.ts
    - Image generation (if supported)
  • etc.
Add feature-specific examples as needed (e.g.,
<provider>-tool-call.ts
,
<provider>-cache-control.ts
).
examples/ai-functions/src/
中为提供商支持的每种模型类型创建示例:
  • generate-text/<provider>.ts
    - 基础文本生成
  • stream-text/<provider>.ts
    - 流式文本生成
  • generate-object/<provider>.ts
    - 结构化输出(如果支持)
  • stream-object/<provider>.ts
    - 流式结构化输出(如果支持)
  • embed/<provider>.ts
    - 嵌入模型(如果支持)
  • generate-image/<provider>.ts
    - 图像生成(如果支持)
  • 其他类型依此类推
根据需要添加特定功能的示例(例如:
<provider>-tool-call.ts
,
<provider>-cache-control.ts
)。

11. Add Documentation

11. 添加文档

Create documentation in
content/providers/01-ai-sdk-providers/<last number + 10>-<provider>.mdx
Include:
  • Setup instructions
  • Available models
  • Model capabilities
  • Provider-specific options
  • Usage examples
  • API configuration
content/providers/01-ai-sdk-providers/<last number + 10>-<provider>.mdx
路径下创建文档:
应包含:
  • 配置说明
  • 可用模型列表
  • 模型能力介绍
  • 提供商专属配置选项
  • 使用示例
  • API配置说明

12. Create Changeset

12. 创建变更集

Run
pnpm changeset
and:
  • Select the new provider package
  • Choose
    major
    version (for new packages starting at 0.0.0)
  • Describe what the package provides
运行
pnpm changeset
并:
  • 选择新的提供商包
  • 选择
    major
    版本(对于初始版本为0.0.0的新包)
  • 描述该包提供的功能

13. Update References

13. 更新引用

Run
pnpm update-references
from the workspace root to update tsconfig references.
在工作区根目录运行
pnpm update-references
以更新tsconfig引用。

14. Build and Test

14. 构建与测试

bash
undefined
bash
undefined

From workspace root

从工作区根目录执行

pnpm build
pnpm build

From provider package

进入提供商包目录

cd packages/<provider> pnpm test # Run all tests pnpm test:node # Run Node.js tests pnpm test:edge # Run Edge tests pnpm type-check # Type checking
cd packages/<provider> pnpm test # 运行所有测试 pnpm test:node # 运行Node.js测试 pnpm test:edge # 运行Edge测试 pnpm type-check # 类型检查

From workspace root

从工作区根目录执行

pnpm type-check:full # Full type check including examples
undefined
pnpm type-check:full # 完整类型检查,包含示例
undefined

15. Run Examples

15. 运行示例

Test your examples:
bash
cd examples/ai-functions
pnpm tsx src/generate-text/<provider>.ts
pnpm tsx src/stream-text/<provider>.ts
测试你的示例代码:
bash
cd examples/ai-functions
pnpm tsx src/generate-text/<provider>.ts
pnpm tsx src/stream-text/<provider>.ts

Provider Method Naming

提供商方法命名规范

  • Full names:
    languageModel(id)
    ,
    imageModel(id)
    ,
    embeddingModel(id)
    (required)
  • Short aliases:
    .chat(id)
    ,
    .image(id)
    ,
    .embedding(id)
    (for DX)
  • 完整名称
    languageModel(id)
    ,
    imageModel(id)
    ,
    embeddingModel(id)
    (必填)
  • 简写别名
    .chat(id)
    ,
    .image(id)
    ,
    .embedding(id)
    (提升开发体验)

File Naming Conventions

文件命名规范

  • Source files:
    kebab-case.ts
  • Test files:
    kebab-case.test.ts
  • Type test files:
    kebab-case.test-d.ts
  • Provider classes:
    <Provider>Provider
    ,
    <Provider>LanguageModel
    , etc.
  • 源文件:
    kebab-case.ts
  • 测试文件:
    kebab-case.test.ts
  • 类型测试文件:
    kebab-case.test-d.ts
  • 提供商类:
    <Provider>Provider
    ,
    <Provider>LanguageModel

Security Best Practices

安全最佳实践

  • Never use
    JSON.parse
    directly - use
    parseJSON
    or
    safeParseJSON
    from
    @ai-sdk/provider-utils
  • Load API keys securely using
    loadApiKey
    from
    @ai-sdk/provider-utils
  • Validate all API responses against schemas
  • 切勿直接使用
    JSON.parse
    - 请使用
    @ai-sdk/provider-utils
    中的
    parseJSON
    safeParseJSON
  • 使用
    @ai-sdk/provider-utils
    中的
    loadApiKey
    安全加载API密钥
  • 验证所有API响应是否符合Schema

Error Handling

错误处理

Errors should extend
AISDKError
from
@ai-sdk/provider
and use a marker pattern:
typescript
import { AISDKError } from '@ai-sdk/provider';

const name = 'AI_ProviderError';
const marker = `vercel.ai.error.${name}`;
const symbol = Symbol.for(marker);

export class ProviderError extends AISDKError {
  private readonly [symbol] = true;

  constructor({ message, cause }: { message: string; cause?: unknown }) {
    super({ name, message, cause });
  }

  static isInstance(error: unknown): error is ProviderError {
    return AISDKError.hasMarker(error, marker);
  }
}
错误应继承自
@ai-sdk/provider
中的
AISDKError
并使用标记模式:
typescript
import { AISDKError } from '@ai-sdk/provider';

const name = 'AI_ProviderError';
const marker = `vercel.ai.error.${name}`;
const symbol = Symbol.for(marker);

export class ProviderError extends AISDKError {
  private readonly [symbol] = true;

  constructor({ message, cause }: { message: string; cause?: unknown }) {
    super({ name, message, cause });
  }

  static isInstance(error: unknown): error is ProviderError {
    return AISDKError.hasMarker(error, marker);
  }
}

Pre-release Mode

预发布模式

If
main
is set up to publish
beta
releases, no further action is necessary. Just make sure not to backport it to the
vX.Y
stable branch since it will result in an npm version conflict once we exit pre-release mode on
main
.
如果
main
分支已配置为发布
beta
版本,则无需额外操作。只需注意不要将其回传到
vX.Y
稳定分支,否则在
main
分支退出预发布模式后会导致npm版本冲突。

Checklist

检查清单

  • Package structure created in
    packages/<provider>
  • package.json
    configured with correct dependencies
  • TypeScript configs set up (
    tsconfig.json
    ,
    tsconfig.build.json
    )
  • Build configuration (
    tsup.config.ts
    )
  • Test configurations (
    vitest.node.config.js
    ,
    vitest.edge.config.js
    )
  • Provider implementation complete
  • Model classes implement appropriate interfaces
  • Unit tests written and passing
  • API response test fixtures captured
  • Examples created in
    examples/ai-functions/src/
  • Documentation added in
    content/providers/01-ai-sdk-providers/
  • README.md written
  • Major changeset created
  • pnpm update-references
    run
  • All tests passing (
    pnpm test
    from package)
  • Type checking passing (
    pnpm type-check:full
    from root)
  • Examples run successfully
  • packages/<provider>
    中创建了包结构
  • 正确配置了
    package.json
    的依赖
  • 设置了TypeScript配置(
    tsconfig.json
    ,
    tsconfig.build.json
  • 配置了构建工具(
    tsup.config.ts
  • 配置了测试运行器(
    vitest.node.config.js
    ,
    vitest.edge.config.js
  • 完成了提供商实现
  • 模型类实现了对应的接口
  • 编写并通过了单元测试
  • 捕获了API响应测试数据
  • examples/ai-functions/src/
    中创建了示例
  • content/providers/01-ai-sdk-providers/
    中添加了文档
  • 编写了README.md
  • 创建了major版本的变更集
  • 运行了
    pnpm update-references
  • 所有测试通过(在包目录执行
    pnpm test
  • 类型检查通过(在根目录执行
    pnpm type-check:full
  • 示例运行成功

Common Issues

常见问题

  • Missing tsconfig references: Run
    pnpm update-references
    from workspace root
  • Type errors in examples: Run
    pnpm type-check:full
    to catch issues early
  • Test failures: Ensure both Node and Edge tests pass
  • Build errors: Check that
    tsup.config.ts
    is configured correctly
  • 缺少tsconfig引用:在工作区根目录运行
    pnpm update-references
  • 示例中出现类型错误:运行
    pnpm type-check:full
    提前发现问题
  • 测试失败:确保Node.js和Edge运行时的测试都通过
  • 构建错误:检查
    tsup.config.ts
    的配置是否正确

Related Documentation

相关文档

  • Provider Architecture
  • Provider Development Notes
  • Develop AI Functions Example
  • Capture API Response Test Fixture
  • 提供商架构
  • 提供商开发说明
  • 开发AI函数示例
  • 捕获API响应测试数据