@cherrystudio/ai-core
Version:
Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK
752 lines (740 loc) • 25.8 kB
JavaScript
import { PluginManager, createAnthropicOptions, createContext, createGoogleOptions, createOpenAIOptions, definePlugin, mergeProviderOptions } from "./factory-sYGDaeDD.mjs";
import { createAnthropic } from "@ai-sdk/anthropic";
import { createAzure } from "@ai-sdk/azure";
import { createDeepSeek } from "@ai-sdk/deepseek";
import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { createOpenAI } from "@ai-sdk/openai";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { createXai } from "@ai-sdk/xai";
import * as aiSdk from "ai";
import { Experimental_Agent as Agent, defaultSettingsMiddleware, extractReasoningMiddleware, generateObject as generateObject$1, generateText as generateText$1, simulateStreamingMiddleware, smoothStream, stepCountIs, streamObject, streamText as streamText$1, wrapLanguageModel } from "ai";
//#region src/utils/model.ts
function isOpenAIChatCompletionOnlyModel(modelId) {
if (!modelId) return false;
return modelId.includes("gpt-4o-search-preview") || modelId.includes("gpt-4o-mini-search-preview") || modelId.includes("o1-mini") || modelId.includes("o1-preview");
}
//#endregion
//#region src/core/providers/creator.ts
var ProviderCreationError = class extends Error {
constructor(message, providerId, cause) {
super(message);
this.providerId = providerId;
this.cause = cause;
this.name = "ProviderCreationError";
}
};
/**
* 创建 Provider 实例
* 支持两种模式:直接提供 creator 函数,或动态导入 + 函数名
*/
async function createProvider(config, options) {
try {
if (!validateProviderConfig(config)) throw new ProviderCreationError("Invalid provider configuration: must provide either creator function or import configuration", config.id);
config.validateOptions?.(options);
if (config.creator) return config.creator(options);
if (config.import && config.creatorFunctionName) {
const module = await config.import();
const creatorFunction = module[config.creatorFunctionName];
if (typeof creatorFunction !== "function") throw new ProviderCreationError(`Creator function "${config.creatorFunctionName}" not found in the imported module`, config.id);
return creatorFunction(options);
}
throw new ProviderCreationError("Unexpected provider configuration state", config.id);
} catch (error) {
if (error instanceof ProviderCreationError) throw error;
throw new ProviderCreationError(`Failed to create provider "${config.id}": ${error instanceof Error ? error.message : "Unknown error"}`, config.id, error instanceof Error ? error : void 0);
}
}
/**
* 创建图像生成 Provider 实例
*/
async function createImageProvider(config, options) {
try {
if (!config.supportsImageGeneration) throw new ProviderCreationError(`Provider "${config.id}" does not support image generation`, config.id);
if (config.imageCreator) return config.imageCreator(options);
return await createProvider(config, options);
} catch (error) {
if (error instanceof ProviderCreationError) throw error;
throw new ProviderCreationError(`Failed to create image provider "${config.id}": ${error instanceof Error ? error.message : "Unknown error"}`, config.id, error instanceof Error ? error : void 0);
}
}
/**
* 验证 Provider 配置
*/
function validateProviderConfig(config) {
if (!config.id || !config.name) return false;
if (!config.creator && !(config.import && config.creatorFunctionName)) return false;
return true;
}
//#endregion
//#region src/core/providers/registry.ts
var AiProviderRegistry = class AiProviderRegistry {
static instance;
registry = new Map();
constructor() {
this.initializeProviders();
}
static getInstance() {
if (!AiProviderRegistry.instance) AiProviderRegistry.instance = new AiProviderRegistry();
return AiProviderRegistry.instance;
}
/**
* 初始化所有支持的 Providers
* 基于 AI SDK 官方文档: https://ai-sdk.dev/providers/ai-sdk-providers
*/
initializeProviders() {
const providers = [
{
id: "openai",
name: "OpenAI",
creator: createOpenAI,
supportsImageGeneration: true
},
{
id: "openai-responses",
name: "OpenAI Responses",
creator: (options) => {
return createOpenAI(options).responses;
},
supportsImageGeneration: true
},
{
id: "openai-compatible",
name: "OpenAI Compatible",
creator: createOpenAICompatible,
supportsImageGeneration: true
},
{
id: "anthropic",
name: "Anthropic",
creator: createAnthropic,
supportsImageGeneration: false
},
{
id: "google",
name: "Google Generative AI",
creator: createGoogleGenerativeAI,
supportsImageGeneration: true
},
{
id: "xai",
name: "xAI (Grok)",
creator: createXai,
supportsImageGeneration: true
},
{
id: "azure",
name: "Azure OpenAI",
creator: createAzure,
supportsImageGeneration: true
},
{
id: "deepseek",
name: "DeepSeek",
creator: createDeepSeek,
supportsImageGeneration: false
}
];
providers.forEach((config) => {
this.registry.set(config.id, config);
});
}
/**
* 获取所有已注册的 Providers
*/
getAllProviders() {
return Array.from(this.registry.values());
}
/**
* 根据 ID 获取 Provider 配置
*/
getProvider(id) {
return this.registry.get(id) || this.registry.get("openai-compatible");
}
/**
* 检查 Provider 是否支持(是否已注册)
*/
isSupported(id) {
return this.registry.has(id);
}
/**
* 注册新的 Provider(用于扩展)
*/
registerProvider(config) {
if (!config.creator && !(config.import && config.creatorFunctionName)) throw new Error("Must provide either creator function or import configuration");
if (config.creator && config.import) console.warn("Both creator and import provided, creator will take precedence");
this.registry.set(config.id, config);
}
/**
* 清理资源
*/
cleanup() {
this.registry.clear();
}
};
const aiProviderRegistry = AiProviderRegistry.getInstance();
const getProvider = (id) => aiProviderRegistry.getProvider(id);
const getAllProviders = () => aiProviderRegistry.getAllProviders();
const isProviderSupported = (id) => aiProviderRegistry.isSupported(id);
const registerProvider = (config) => aiProviderRegistry.registerProvider(config);
//#endregion
//#region src/core/models/ModelCreator.ts
var ModelCreationError = class extends Error {
constructor(message, providerId, cause) {
super(message);
this.providerId = providerId;
this.cause = cause;
this.name = "ModelCreationError";
}
};
async function createBaseModel({ providerId, modelId, providerSettings, extraModelConfig }) {
try {
const providerConfig = aiProviderRegistry.getProvider(providerId);
if (!providerConfig) throw new ModelCreationError(`Provider "${providerId}" is not registered`, providerId);
const provider = await createProvider(providerConfig, providerSettings);
const finalProvider = handleProviderSpecificLogic(provider, providerConfig.id, providerSettings, modelId);
if (typeof finalProvider === "function") {
const model = finalProvider(modelId, extraModelConfig);
return model;
} else throw new ModelCreationError(`Unknown model access pattern for provider "${providerId}"`);
} catch (error) {
if (error instanceof ModelCreationError) throw error;
throw new ModelCreationError(`Failed to create base model for provider "${providerId}": ${error instanceof Error ? error.message : "Unknown error"}`, providerId, error instanceof Error ? error : void 0);
}
}
/**
* 处理特定 Provider 的逻辑
*/
function handleProviderSpecificLogic(provider, providerId, providerSettings, modelId) {
if (providerId === "openai") if ("mode" in providerSettings && providerSettings.mode === "responses" && !isOpenAIChatCompletionOnlyModel(modelId)) return provider.responses;
else return provider.chat;
return provider;
}
async function createImageModel(providerId, modelId = "default", options) {
try {
if (!aiProviderRegistry.isSupported(providerId)) throw new ModelCreationError(`Provider "${providerId}" is not supported`, providerId);
const providerConfig = aiProviderRegistry.getProvider(providerId);
if (!providerConfig) throw new ModelCreationError(`Provider "${providerId}" is not registered`, providerId);
if (!providerConfig.supportsImageGeneration) throw new ModelCreationError(`Provider "${providerId}" does not support image generation`, providerId);
const provider = await createImageProvider(providerConfig, options);
if (provider && typeof provider.image === "function") return provider.image(modelId);
else throw new ModelCreationError(`Image model function not found for provider "${providerId}"`);
} catch (error) {
if (error instanceof ModelCreationError) throw error;
throw new ModelCreationError(`Failed to create image model for provider "${providerId}": ${error instanceof Error ? error.message : "Unknown error"}`, providerId, error instanceof Error ? error : void 0);
}
}
/**
* 获取支持的 Providers 列表
*/
function getSupportedProviders() {
return aiProviderRegistry.getAllProviders().map((provider) => ({
id: provider.id,
name: provider.name
}));
}
/**
* 获取 Provider 信息
*/
function getProviderInfo(providerId) {
const effectiveProviderId = aiProviderRegistry.isSupported(providerId) ? providerId : "openai-compatible";
const provider = aiProviderRegistry.getProvider(effectiveProviderId);
return {
id: providerId,
name: provider?.name || providerId,
isSupported: aiProviderRegistry.isSupported(providerId),
effectiveProvider: effectiveProviderId
};
}
//#endregion
//#region src/core/middleware/wrapper.ts
/**
* 使用中间件包装模型
*/
function wrapModelWithMiddlewares(model, middlewares) {
if (middlewares.length === 0) return model;
return wrapLanguageModel({
model,
middleware: middlewares
});
}
//#endregion
//#region src/core/models/factory.ts
/**
* 创建模型 - 核心函数
*/
async function createModel(config) {
validateModelConfig(config);
const baseModel = await createBaseModel(config);
return config.middlewares?.length ? wrapModelWithMiddlewares(baseModel, config.middlewares) : baseModel;
}
/**
* 验证模型配置
*/
function validateModelConfig(config) {
if (!config.providerId) throw new Error("ModelConfig: providerId is required");
if (!config.modelId) throw new Error("ModelConfig: modelId is required");
if (!config.providerSettings) throw new Error("ModelConfig: providerSettings is required");
}
//#endregion
//#region src/core/runtime/pluginEngine.ts
/**
* 插件增强的 AI 客户端
* 专注于插件处理,不暴露用户API
*/
var PluginEngine = class PluginEngine {
pluginManager;
constructor(providerId, plugins = []) {
this.providerId = providerId;
this.pluginManager = new PluginManager(plugins);
}
/**
* 添加插件
*/
use(plugin) {
this.pluginManager.use(plugin);
return this;
}
/**
* 批量添加插件
*/
usePlugins(plugins) {
plugins.forEach((plugin) => this.use(plugin));
return this;
}
/**
* 移除插件
*/
removePlugin(pluginName) {
this.pluginManager.remove(pluginName);
return this;
}
/**
* 获取插件统计
*/
getPluginStats() {
return this.pluginManager.getStats();
}
/**
* 获取所有插件
*/
getPlugins() {
return this.pluginManager.getPlugins();
}
/**
* 执行带插件的操作(非流式)
* 提供给AiExecutor使用
*/
async executeWithPlugins(methodName, modelId, params, executor, _context) {
const context = _context ? _context : createContext(this.providerId, modelId, params);
context.recursiveCall = async (newParams) => {
context.isRecursiveCall = true;
const result = await this.executeWithPlugins(methodName, modelId, newParams, executor, context);
context.isRecursiveCall = false;
return result;
};
try {
await this.pluginManager.executeConfigureContext(context);
await this.pluginManager.executeParallel("onRequestStart", context);
const model = await this.pluginManager.executeFirst("resolveModel", modelId, context);
if (!model) throw new Error(`Failed to resolve model: ${modelId}`);
const transformedParams = await this.pluginManager.executeSequential("transformParams", params, context);
const result = await executor(model, transformedParams);
const transformedResult = await this.pluginManager.executeSequential("transformResult", result, context);
await this.pluginManager.executeParallel("onRequestEnd", context, transformedResult);
return transformedResult;
} catch (error) {
await this.pluginManager.executeParallel("onError", context, void 0, error);
throw error;
}
}
/**
* 执行流式调用的通用逻辑(支持流转换器)
* 提供给AiExecutor使用
*/
async executeStreamWithPlugins(methodName, modelId, params, executor, _context) {
const context = _context ? _context : createContext(this.providerId, modelId, params);
context.recursiveCall = async (newParams) => {
context.isRecursiveCall = true;
const result = await this.executeStreamWithPlugins(methodName, modelId, newParams, executor, context);
context.isRecursiveCall = false;
return result;
};
try {
await this.pluginManager.executeConfigureContext(context);
await this.pluginManager.executeParallel("onRequestStart", context);
const model = await this.pluginManager.executeFirst("resolveModel", modelId, context);
if (!model) throw new Error(`Failed to resolve model: ${modelId}`);
const transformedParams = await this.pluginManager.executeSequential("transformParams", params, context);
const streamTransforms = this.pluginManager.collectStreamTransforms(transformedParams, context);
const result = await executor(model, transformedParams, streamTransforms);
const transformedResult = await this.pluginManager.executeSequential("transformResult", result, context);
await this.pluginManager.executeParallel("onRequestEnd", context, { stream: true });
return transformedResult;
} catch (error) {
await this.pluginManager.executeParallel("onError", context, void 0, error);
throw error;
}
}
/**
* 创建 OpenAI Compatible 客户端
*/
static createOpenAICompatible(config, plugins = []) {
return new PluginEngine("openai-compatible", plugins);
}
static create(providerId, plugins = []) {
if (isProviderSupported(providerId)) return new PluginEngine(providerId, plugins);
else return new PluginEngine("openai-compatible", plugins);
}
};
//#endregion
//#region src/core/runtime/executor.ts
var RuntimeExecutor = class RuntimeExecutor {
pluginEngine;
config;
constructor(config) {
this.config = config;
this.pluginEngine = new PluginEngine(config.providerId, config.plugins || []);
}
createResolveModelPlugin(middlewares) {
return definePlugin({
name: "_internal_resolveModel",
enforce: "post",
resolveModel: async (modelId, context) => {
const extraModelConfig = context.extraModelConfig || {};
return await this.resolveModel(modelId, middlewares, extraModelConfig);
}
});
}
createConfigureContextPlugin() {
return definePlugin({
name: "_internal_configureContext",
configureContext: async (context) => {
context.executor = this;
}
});
}
async streamText(modelOrId, params, options) {
this.pluginEngine.usePlugins([this.createResolveModelPlugin(options?.middlewares), this.createConfigureContextPlugin()]);
return this.pluginEngine.executeStreamWithPlugins("streamText", typeof modelOrId === "string" ? modelOrId : modelOrId.modelId, params, async (model, transformedParams, streamTransforms) => {
const experimental_transform = params?.experimental_transform ?? (streamTransforms.length > 0 ? streamTransforms : void 0);
return await streamText$1({
model,
...transformedParams,
experimental_transform
});
});
}
async generateText(modelOrId, params, options) {
this.pluginEngine.usePlugins([this.createResolveModelPlugin(options?.middlewares), this.createConfigureContextPlugin()]);
return this.pluginEngine.executeWithPlugins("generateText", typeof modelOrId === "string" ? modelOrId : modelOrId.modelId, params, async (model, transformedParams) => {
return await generateText$1({
model,
...transformedParams
});
});
}
async generateObject(modelOrId, params, options) {
this.pluginEngine.usePlugins([this.createResolveModelPlugin(options?.middlewares), this.createConfigureContextPlugin()]);
return this.pluginEngine.executeWithPlugins("generateObject", typeof modelOrId === "string" ? modelOrId : modelOrId.modelId, params, async (model, transformedParams) => {
return await generateObject$1({
model,
...transformedParams
});
});
}
async streamObject(modelOrId, params, options) {
this.pluginEngine.usePlugins([this.createResolveModelPlugin(options?.middlewares), this.createConfigureContextPlugin()]);
return this.pluginEngine.executeWithPlugins("streamObject", typeof modelOrId === "string" ? modelOrId : modelOrId.modelId, params, async (model, transformedParams) => {
return await streamObject({
model,
...transformedParams
});
});
}
/**
* 解析模型:如果是字符串则创建模型,如果是模型则直接返回
*/
async resolveModel(modelOrId, middlewares, extraModelConfig) {
if (typeof modelOrId === "string") return await createModel({
providerId: this.config.providerId,
modelId: modelOrId,
providerSettings: this.config.providerSettings,
middlewares,
extraModelConfig
});
else return modelOrId;
}
/**
* 获取客户端信息
*/
getClientInfo() {
return getProviderInfo(this.config.providerId);
}
/**
* 创建执行器 - 支持已知provider的类型安全
*/
static create(providerId, options, plugins) {
return new RuntimeExecutor({
providerId,
providerSettings: options,
plugins
});
}
/**
* 创建OpenAI Compatible执行器
*/
static createOpenAICompatible(options, plugins = []) {
return new RuntimeExecutor({
providerId: "openai-compatible",
providerSettings: options,
plugins
});
}
};
//#endregion
//#region src/core/runtime/index.ts
/**
* 创建运行时执行器 - 支持类型安全的已知provider
*/
function createExecutor(providerId, options, plugins) {
return RuntimeExecutor.create(providerId, options, plugins);
}
/**
* 创建OpenAI Compatible执行器
*/
function createOpenAICompatibleExecutor(options, plugins = []) {
return RuntimeExecutor.createOpenAICompatible(options, plugins);
}
/**
* 直接流式文本生成 - 支持middlewares
*/
async function streamText(providerId, options, modelId, params, plugins, middlewares) {
const executor = createExecutor(providerId, options, plugins);
return executor.streamText(modelId, params, { middlewares });
}
/**
* 直接生成文本 - 支持middlewares
*/
async function generateText(providerId, options, modelId, params, plugins, middlewares) {
const executor = createExecutor(providerId, options, plugins);
return executor.generateText(modelId, params, { middlewares });
}
/**
* 直接生成结构化对象 - 支持middlewares
*/
async function generateObject(providerId, options, modelId, params, plugins, middlewares) {
const executor = createExecutor(providerId, options, plugins);
return executor.generateObject(modelId, params, { middlewares });
}
//#endregion
//#region src/core/providers/factory.ts
const configHandlers = { azure: (builder, provider) => {
const azureBuilder = builder;
const azureProvider = provider;
azureBuilder.withAzureConfig({
apiVersion: azureProvider.apiVersion,
resourceName: azureProvider.resourceName
});
} };
var ProviderConfigBuilder = class {
config = {};
constructor(providerId) {
this.providerId = providerId;
}
withApiKey(apiKey, options) {
this.config.apiKey = apiKey;
if (this.providerId === "openai" && options) {
const openaiConfig = this.config;
if (options.organization) openaiConfig.organization = options.organization;
if (options.project) openaiConfig.project = options.project;
}
return this;
}
/**
* 设置基础 URL
*/
withBaseURL(baseURL) {
this.config.baseURL = baseURL;
return this;
}
/**
* 设置请求配置
*/
withRequestConfig(options) {
if (options.headers) this.config.headers = {
...this.config.headers,
...options.headers
};
if (options.fetch) this.config.fetch = options.fetch;
return this;
}
withAzureConfig(options) {
if (this.providerId === "azure") {
const azureConfig = this.config;
if (options.apiVersion) azureConfig.apiVersion = options.apiVersion;
if (options.resourceName) azureConfig.resourceName = options.resourceName;
}
return this;
}
withGoogleCredentials() {
return this;
}
/**
* 设置自定义参数
*/
withCustomParams(params) {
Object.assign(this.config, params);
return this;
}
/**
* 构建最终配置
*/
build() {
return this.config;
}
};
/**
* Provider 配置工厂
* 提供便捷的配置创建方法
*/
var ProviderConfigFactory = class {
/**
* 创建配置构建器
*/
static builder(providerId) {
return new ProviderConfigBuilder(providerId);
}
/**
* 从通用Provider对象创建配置 - 使用更优雅的处理器模式
*/
static fromProvider(providerId, provider, options) {
const builder = new ProviderConfigBuilder(providerId);
if (provider.apiKey) builder.withApiKey(provider.apiKey);
if (provider.baseURL) builder.withBaseURL(provider.baseURL);
if (options?.headers) builder.withRequestConfig({ headers: options.headers });
const handler = configHandlers[providerId];
if (handler) handler(builder, provider);
if (options) {
const customOptions = { ...options };
delete customOptions.headers;
if (Object.keys(customOptions).length > 0) builder.withCustomParams(customOptions);
}
return builder.build();
}
/**
* 快速创建 OpenAI 配置
*/
static createOpenAI(apiKey, options) {
const builder = this.builder("openai");
if (options?.organization || options?.project) builder.withApiKey(apiKey, {
organization: options.organization,
project: options.project
});
else builder.withApiKey(apiKey);
return builder.withBaseURL(options?.baseURL || "https://api.openai.com").build();
}
/**
* 快速创建 Anthropic 配置
*/
static createAnthropic(apiKey, options) {
return this.builder("anthropic").withApiKey(apiKey).withBaseURL(options?.baseURL || "https://api.anthropic.com").build();
}
/**
* 快速创建 Azure OpenAI 配置
*/
static createAzureOpenAI(apiKey, options) {
return this.builder("azure").withApiKey(apiKey).withBaseURL(options.baseURL).withAzureConfig({
apiVersion: options.apiVersion,
resourceName: options.resourceName
}).build();
}
/**
* 快速创建 Google 配置
*/
static createGoogle(apiKey, options) {
return this.builder("google").withApiKey(apiKey).withBaseURL(options?.baseURL || "https://generativelanguage.googleapis.com").build();
}
/**
* 快速创建 Vertex AI 配置
*/
static createVertexAI() {}
static createOpenAICompatible(baseURL, apiKey) {
return this.builder("openai-compatible").withBaseURL(baseURL).withApiKey(apiKey).build();
}
};
/**
* 便捷的配置创建函数
*/
const createProviderConfig = ProviderConfigFactory.fromProvider;
const providerConfigBuilder = ProviderConfigFactory.builder;
//#endregion
//#region src/index.ts
const AI_CORE_VERSION = "1.0.0";
const AI_CORE_NAME = "@cherrystudio/ai-core";
const AiCore = {
version: AI_CORE_VERSION,
name: AI_CORE_NAME,
create(providerId, options, plugins = []) {
return createExecutor(providerId, options, plugins);
},
getSupportedProviders() {
return getSupportedProviders();
},
isSupported(providerId) {
return isProviderSupported(providerId);
},
getClientInfo(providerId) {
return getProviderInfo(providerId);
}
};
const createOpenAIExecutor = (options, plugins) => {
return createExecutor("openai", options, plugins);
};
const createAnthropicExecutor = (options, plugins) => {
return createExecutor("anthropic", options, plugins);
};
const createGoogleExecutor = (options, plugins) => {
return createExecutor("google", options, plugins);
};
const createXAIExecutor = (options, plugins) => {
return createExecutor("xai", options, plugins);
};
const DevTools = {
listProviders() {
return aiProviderRegistry.getAllProviders().map((p) => ({
id: p.id,
name: p.name
}));
},
async testProvider(providerId, options) {
try {
const executor = createExecutor(providerId, options);
const info = executor.getClientInfo();
return {
success: true,
providerId: info.id,
name: info.name,
isSupported: info.isSupported
};
} catch (error) {
return {
success: false,
providerId,
error: error instanceof Error ? error.message : "Unknown error"
};
}
},
getProviderDetails() {
const providers = aiProviderRegistry.getAllProviders();
return {
supportedProviders: providers.length,
registeredProviders: providers.length,
providers: providers.map((p) => ({
id: p.id,
name: p.name
}))
};
}
};
//#endregion
export { AI_CORE_NAME, AI_CORE_VERSION, Agent, AiCore, DevTools, ModelCreationError, PluginEngine, PluginManager, ProviderConfigFactory, aiProviderRegistry, aiSdk, createAnthropicExecutor, createAnthropicOptions, createBaseModel as createApiClient, createContext, createExecutor, createGoogleExecutor, createGoogleOptions, createImageModel, createModel, createOpenAICompatibleExecutor, createOpenAIExecutor, createOpenAIOptions, createProviderConfig, createXAIExecutor, defaultSettingsMiddleware, definePlugin, extractReasoningMiddleware, generateObject, generateText, getAllProviders, getProviderInfo as getClientInfo, getProvider, getSupportedProviders, isProviderSupported, mergeProviderOptions, providerConfigBuilder, registerProvider, simulateStreamingMiddleware, smoothStream, stepCountIs, streamText };