@cherrystudio/ai-core
Version:
Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK
548 lines (541 loc) • 18.9 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_plugins = require('./plugins-Dxz_fOwT.cjs');
const require_initialization = require('./initialization-CThbOFZ0.cjs');
let ai = require("ai");
//#region src/core/models/utils.ts
const isV2Model = (model) => {
return typeof model === "object" && model !== null && model.specificationVersion === "v2";
};
const isV3Model = (model) => {
return typeof model === "object" && model !== null && model.specificationVersion === "v3";
};
//#endregion
//#region src/core/runtime/errors.ts
/**
* Error classes for runtime operations
*/
/**
* Error thrown when image generation fails
*/
var ImageGenerationError = class ImageGenerationError extends Error {
constructor(message, providerId, modelId, cause) {
super(message);
this.providerId = providerId;
this.modelId = modelId;
this.cause = cause;
this.name = "ImageGenerationError";
if (Error.captureStackTrace) Error.captureStackTrace(this, ImageGenerationError);
}
};
/**
* Error thrown when model resolution fails during image generation
*/
var ImageModelResolutionError = class extends ImageGenerationError {
constructor(modelId, providerId, cause) {
super(`Failed to resolve image model: ${modelId}${providerId ? ` for provider: ${providerId}` : ""}`, providerId, modelId, cause);
this.name = "ImageModelResolutionError";
}
};
//#endregion
//#region src/core/errors/index.ts
/**
* AI Core Error System
* Unified error handling for the AI Core package
*/
/**
* Base error class for all AI Core errors
* Provides structured error information with error codes, context, and cause tracking
*/
var AiCoreError = class extends Error {
constructor(code, message, context, cause) {
super(message);
this.code = code;
this.context = context;
this.cause = cause;
this.name = "AiCoreError";
if (cause) this.stack = `${this.stack}\nCaused by: ${cause.stack}`;
}
toJSON() {
return {
name: this.name,
code: this.code,
message: this.message,
context: this.context,
cause: this.cause ? {
name: this.cause.name,
message: this.cause.message
} : void 0
};
}
};
/**
* Recursive depth limit exceeded error
* Thrown when recursive calls exceed the maximum allowed depth
*/
var RecursiveDepthError = class extends AiCoreError {
constructor(requestId, currentDepth, maxDepth) {
super("RECURSIVE_DEPTH_EXCEEDED", `Maximum recursive depth (${maxDepth}) exceeded at depth ${currentDepth}`, {
requestId,
currentDepth,
maxDepth
});
this.name = "RecursiveDepthError";
}
};
/**
* Model resolution failure error
* Thrown when a model ID cannot be resolved to a model instance
*/
var ModelResolutionError = class extends AiCoreError {
constructor(modelId, providerId, cause) {
super("MODEL_RESOLUTION_FAILED", `Failed to resolve model: ${modelId}`, {
modelId,
providerId
}, cause);
this.name = "ModelResolutionError";
}
};
/**
* Parameter validation error
* Thrown when request parameters fail validation
*/
var ParameterValidationError = class extends AiCoreError {
constructor(paramName, reason, value) {
super("PARAMETER_VALIDATION_FAILED", `Invalid parameter '${paramName}': ${reason}`, {
paramName,
reason,
value
});
this.name = "ParameterValidationError";
}
};
/**
* Plugin execution error
* Thrown when a plugin fails during execution
*/
var PluginExecutionError = class extends AiCoreError {
constructor(pluginName, hookName, cause) {
super("PLUGIN_EXECUTION_FAILED", `Plugin '${pluginName}' failed in hook '${hookName}'`, {
pluginName,
hookName
}, cause);
this.name = "PluginExecutionError";
}
};
/**
* Template loading error
* Thrown when a template cannot be loaded
*/
var TemplateLoadError = class extends AiCoreError {
constructor(templateName, cause) {
super("TEMPLATE_LOAD_FAILED", `Failed to load template: ${templateName}`, { templateName }, cause);
this.name = "TemplateLoadError";
}
};
//#endregion
//#region src/core/runtime/pluginEngine.ts
/**
* 插件增强的 AI 客户端
* 专注于插件处理,不暴露用户API
*/
var PluginEngine = class {
constructor(providerId, plugins = []) {
this.providerId = providerId;
this.basePlugins = [];
this.basePlugins = plugins;
}
/**
* 添加插件
*/
use(plugin) {
this.basePlugins.push(plugin);
return this;
}
/**
* 批量添加插件
*/
usePlugins(plugins) {
this.basePlugins.push(...plugins);
return this;
}
/**
* 移除插件
*/
removePlugin(pluginName) {
this.basePlugins = this.basePlugins.filter((p) => p.name !== pluginName);
return this;
}
/**
* 获取插件统计
*/
getPluginStats() {
return new require_plugins.PluginManager(this.basePlugins).getStats();
}
/**
* 获取所有插件
*/
getPlugins() {
return [...this.basePlugins];
}
/**
* 执行带插件的操作(非流式)
* 提供给AiExecutor使用
*/
async executeWithPlugins(methodName, params, executor, _context) {
let resolvedModel;
let modelId;
const { model } = params;
if (typeof model === "string") modelId = model;
else {
resolvedModel = model;
modelId = model.modelId;
}
const context = _context ?? require_plugins.createContext(this.providerId, model, params);
const manager = new require_plugins.PluginManager(this.basePlugins);
context.recursiveCall = async (newParams) => {
if (context.recursiveDepth >= context.maxRecursiveDepth) throw new RecursiveDepthError(context.requestId, context.recursiveDepth, context.maxRecursiveDepth);
const previousDepth = context.recursiveDepth;
const wasRecursive = context.isRecursiveCall;
try {
context.recursiveDepth = previousDepth + 1;
context.isRecursiveCall = true;
return await this.executeWithPlugins(methodName, {
...params,
...newParams
}, executor, context);
} finally {
context.recursiveDepth = previousDepth;
context.isRecursiveCall = wasRecursive;
}
};
try {
await manager.executeConfigureContext(context);
await manager.executeParallel("onRequestStart", context);
if (typeof model === "string") {
const resolved = await manager.executeFirst("resolveModel", modelId, context);
if (!resolved) throw new ModelResolutionError(modelId, this.providerId);
resolvedModel = resolved;
}
if (!resolvedModel) throw new ModelResolutionError(modelId, this.providerId);
if (context.middlewares && context.middlewares.length > 0) resolvedModel = (0, ai.wrapLanguageModel)({
model: resolvedModel,
middleware: context.middlewares
});
const transformedParams = await manager.executeTransformParams(params, context);
const result = await executor(resolvedModel, transformedParams);
const transformedResult = await manager.executeTransformResult(result, context);
await manager.executeParallel("onRequestEnd", context, transformedResult);
return transformedResult;
} catch (error) {
await manager.executeParallel("onError", context, void 0, error);
throw error;
}
}
/**
* 执行带插件的图像生成操作
* 提供给AiExecutor使用
*/
async executeImageWithPlugins(methodName, params, executor, _context) {
let resolvedModel;
let modelId;
const { model } = params;
if (typeof model === "string") modelId = model;
else {
resolvedModel = model;
modelId = model.modelId;
}
const context = _context ?? require_plugins.createContext(this.providerId, model, params);
const manager = new require_plugins.PluginManager(this.basePlugins);
context.recursiveCall = async (newParams) => {
if (context.recursiveDepth >= context.maxRecursiveDepth) throw new RecursiveDepthError(context.requestId, context.recursiveDepth, context.maxRecursiveDepth);
const previousDepth = context.recursiveDepth;
const wasRecursive = context.isRecursiveCall;
try {
context.recursiveDepth = previousDepth + 1;
context.isRecursiveCall = true;
return await this.executeImageWithPlugins(methodName, {
...params,
...newParams
}, executor, context);
} finally {
context.recursiveDepth = previousDepth;
context.isRecursiveCall = wasRecursive;
}
};
try {
await manager.executeConfigureContext(context);
await manager.executeParallel("onRequestStart", context);
if (typeof model === "string") {
const resolved = await manager.executeFirst("resolveModel", modelId, context);
if (!resolved) throw new ModelResolutionError(modelId, this.providerId);
resolvedModel = resolved;
}
if (!resolvedModel) throw new ModelResolutionError(modelId, this.providerId);
const transformedParams = await manager.executeTransformParams(params, context);
const result = await executor(resolvedModel, transformedParams);
const transformedResult = await manager.executeTransformResult(result, context);
await manager.executeParallel("onRequestEnd", context, transformedResult);
return transformedResult;
} catch (error) {
await manager.executeParallel("onError", context, void 0, error);
throw error;
}
}
/**
* 执行流式调用的通用逻辑(支持流转换器)
* 提供给AiExecutor使用
*/
async executeStreamWithPlugins(methodName, params, executor, _context) {
let resolvedModel;
let modelId;
const { model } = params;
if (typeof model === "string") modelId = model;
else {
resolvedModel = model;
modelId = model.modelId;
}
const context = _context ?? require_plugins.createContext(this.providerId, model, params);
const manager = new require_plugins.PluginManager(this.basePlugins);
context.recursiveCall = async (newParams) => {
if (context.recursiveDepth >= context.maxRecursiveDepth) throw new RecursiveDepthError(context.requestId, context.recursiveDepth, context.maxRecursiveDepth);
const previousDepth = context.recursiveDepth;
const wasRecursive = context.isRecursiveCall;
try {
context.recursiveDepth = previousDepth + 1;
context.isRecursiveCall = true;
return await this.executeStreamWithPlugins(methodName, {
...params,
...newParams
}, executor, context);
} finally {
context.recursiveDepth = previousDepth;
context.isRecursiveCall = wasRecursive;
}
};
try {
await manager.executeConfigureContext(context);
await manager.executeParallel("onRequestStart", context);
if (typeof model === "string") {
const resolved = await manager.executeFirst("resolveModel", modelId, context);
if (!resolved) throw new ModelResolutionError(modelId, this.providerId);
resolvedModel = resolved;
context.model = resolvedModel;
}
if (!resolvedModel) throw new ModelResolutionError(modelId, this.providerId);
if (context.middlewares && context.middlewares.length > 0) {
if (typeof resolvedModel === "string") throw new Error(`Model must be resolved before applying middlewares, got string: ${resolvedModel}`);
resolvedModel = (0, ai.wrapLanguageModel)({
model: resolvedModel,
middleware: context.middlewares
});
}
const transformedParams = await manager.executeTransformParams(params, context);
const streamTransforms = manager.collectStreamTransforms(transformedParams, context);
const result = executor(resolvedModel, transformedParams, streamTransforms);
const transformedResult = await manager.executeTransformResult(result, context);
await manager.executeParallel("onRequestEnd", context, transformedResult);
return transformedResult;
} catch (error) {
await manager.executeParallel("onError", context, void 0, error);
throw error;
}
}
};
//#endregion
//#region src/core/runtime/executor.ts
var RuntimeExecutor = class RuntimeExecutor {
constructor(config) {
this.config = config;
this.pluginEngine = new PluginEngine(config.providerId, config.plugins || []);
const provider = config.provider;
if (!provider.embeddingModel && provider.textEmbeddingModel) provider.embeddingModel = (modelId) => provider.textEmbeddingModel(modelId);
this.registry = (0, ai.createProviderRegistry)({ [config.providerId]: provider });
}
createResolveModelPlugin() {
return require_plugins.definePlugin({
name: "_internal_resolveModel",
enforce: "post",
resolveModel: async (modelId) => {
return await this.resolveModel(modelId);
}
});
}
createResolveImageModelPlugin() {
return require_plugins.definePlugin({
name: "_internal_resolveImageModel",
enforce: "post",
resolveModel: async (modelId) => {
return await this.resolveImageModel(modelId);
}
});
}
createConfigureContextPlugin() {
return require_plugins.definePlugin({
name: "_internal_configureContext",
configureContext: async () => {}
});
}
/**
* 流式文本生成
*/
async streamText(params) {
const { model } = params;
if (typeof model === "string") this.pluginEngine.usePlugins([this.createResolveModelPlugin(), this.createConfigureContextPlugin()]);
else this.pluginEngine.usePlugins([this.createConfigureContextPlugin()]);
return this.pluginEngine.executeStreamWithPlugins("streamText", params, (resolvedModel, transformedParams, streamTransforms) => {
const experimental_transform = params?.experimental_transform ?? (streamTransforms.length > 0 ? streamTransforms : void 0);
return (0, ai.streamText)({
...transformedParams,
model: resolvedModel,
experimental_transform
});
});
}
/**
* 生成文本
*/
async generateText(params) {
const { model } = params;
if (typeof model === "string") this.pluginEngine.usePlugins([this.createResolveModelPlugin(), this.createConfigureContextPlugin()]);
else this.pluginEngine.usePlugins([this.createConfigureContextPlugin()]);
return this.pluginEngine.executeWithPlugins("generateText", params, (resolvedModel, transformedParams) => (0, ai.generateText)({
...transformedParams,
model: resolvedModel
}));
}
/**
* 生成图像
*/
async generateImage(params) {
try {
const { model } = params;
if (typeof model === "string") this.pluginEngine.usePlugins([this.createResolveImageModelPlugin(), this.createConfigureContextPlugin()]);
else this.pluginEngine.usePlugins([this.createConfigureContextPlugin()]);
return this.pluginEngine.executeImageWithPlugins("generateImage", params, (resolvedModel, transformedParams) => (0, ai.generateImage)({
...transformedParams,
model: resolvedModel
}));
} catch (error) {
if (error instanceof Error) {
const modelId = typeof params.model === "string" ? params.model : params.model.modelId;
throw new ImageGenerationError(`Failed to generate image: ${error.message}`, this.config.providerId, modelId, error);
}
throw error;
}
}
/**
* 批量嵌入文本
*/
async embedMany(params) {
const { model: modelOrId, ...options } = params;
return (0, ai.embedMany)({
model: typeof modelOrId === "string" ? this.registry.embeddingModel(`${this.config.providerId}:${modelOrId}`) : modelOrId,
...options
});
}
/**
* 解析模型:将字符串 modelId 解析为 model 对象
*
* 对于有 modelResolver 的配置(如 xAI responses, OpenAI chat),
* 使用 resolver 函数解析模型,而不是通过 registry.languageModel()。
* resolver 在 extension 声明处类型安全地捕获了具体 provider 方法。
*/
async resolveModel(modelOrId) {
if (typeof modelOrId === "string") {
if (this.config.modelResolver) return this.config.modelResolver(modelOrId);
return this.registry.languageModel(`${this.config.providerId}:${modelOrId}`);
} else {
if (!isV3Model(modelOrId)) throw new Error(`Model must be V3. Provider "${this.config.providerId}" returned a V2 model. All providers should be wrapped with wrapProvider to return V3 models.`);
return modelOrId;
}
}
/**
* 解析图像模型:如果是字符串则创建图像模型,如果是模型则直接返回
*/
async resolveImageModel(modelOrId) {
try {
if (typeof modelOrId === "string") return this.registry.imageModel(`${this.config.providerId}:${modelOrId}`);
else return modelOrId;
} catch (error) {
throw new ImageModelResolutionError(typeof modelOrId === "string" ? modelOrId : modelOrId.modelId, this.config.providerId, error instanceof Error ? error : void 0);
}
}
/**
* 创建执行器 - 支持已知provider的类型安全
*/
static create(providerId, provider, options, plugins, modelResolver) {
return new RuntimeExecutor({
providerId,
provider,
providerSettings: options,
plugins,
modelResolver
});
}
/**
* 创建OpenAI Compatible执行器
* ✅ Now accepts provider instance directly
*/
static createOpenAICompatible(provider, options, plugins = []) {
return new RuntimeExecutor({
providerId: "openai-compatible",
provider,
providerSettings: options,
plugins
});
}
};
//#endregion
//#region src/core/runtime/index.ts
/**
* 创建运行时执行器 - 支持类型安全的已知provider
* 自动确保 provider 已初始化
*/
async function createExecutor(providerId, options, plugins) {
if (!require_initialization.extensionRegistry.has(providerId)) throw new Error(`Provider extension "${providerId}" not registered`);
const provider = await require_initialization.extensionRegistry.createProvider(providerId, options || {});
const resolver = require_initialization.extensionRegistry.getModelResolver(providerId);
const modelResolver = resolver ? (modelId) => resolver(provider, modelId) : void 0;
return RuntimeExecutor.create(providerId, provider, options, plugins, modelResolver);
}
/**
* 直接流式文本生成
*/
async function streamText(providerId, options, params, plugins) {
return (await createExecutor(providerId, options, plugins)).streamText(params);
}
/**
* 直接生成文本
*/
async function generateText(providerId, options, params, plugins) {
return (await createExecutor(providerId, options, plugins)).generateText(params);
}
/**
* 直接生成图像 - 支持middlewares
*/
async function generateImage(providerId, options, params, plugins) {
return (await createExecutor(providerId, options, plugins)).generateImage(params);
}
/**
* 直接批量嵌入文本
* AI SDK v6 只有 embedMany,没有 embed
*/
async function embedMany(providerId, options, params, plugins) {
return (await createExecutor(providerId, options, plugins)).embedMany(params);
}
//#endregion
exports.AiCoreError = AiCoreError;
exports.ModelResolutionError = ModelResolutionError;
exports.ParameterValidationError = ParameterValidationError;
exports.PluginEngine = PluginEngine;
exports.PluginExecutionError = PluginExecutionError;
exports.RecursiveDepthError = RecursiveDepthError;
exports.TemplateLoadError = TemplateLoadError;
exports.createExecutor = createExecutor;
exports.definePlugin = require_plugins.definePlugin;
exports.embedMany = embedMany;
exports.generateImage = generateImage;
exports.generateText = generateText;
exports.isV2Model = isV2Model;
exports.isV3Model = isV3Model;
exports.streamText = streamText;