UNPKG

@cherrystudio/ai-core

Version:

Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK

169 lines (167 loc) 4.27 kB
//#region src/core/plugins/manager.ts /** * 插件管理器 */ var PluginManager = class { constructor(plugins = []) { this.plugins = []; this.plugins = this.sortPlugins(plugins); } /** * 添加插件 */ use(plugin) { this.plugins = this.sortPlugins([...this.plugins, plugin]); return this; } /** * 移除插件 */ remove(pluginName) { this.plugins = this.plugins.filter((p) => p.name !== pluginName); return this; } /** * 插件排序:pre -> normal -> post */ sortPlugins(plugins) { const pre = []; const normal = []; const post = []; plugins.forEach((plugin) => { if (plugin.enforce === "pre") pre.push(plugin); else if (plugin.enforce === "post") post.push(plugin); else normal.push(plugin); }); return [ ...pre, ...normal, ...post ]; } /** * 执行 First 钩子 - 返回第一个有效结果 */ async executeFirst(hookName, arg, context) { for (const plugin of this.plugins) { const hook = plugin[hookName]; if (hook) { const result = await hook(arg, context); if (result !== null && result !== void 0) return result; } } return null; } /** * 执行 transformParams 钩子 - 链式参数转换 * 每个插件返回 Partial<TParams>,逐步合并到原始参数 */ async executeTransformParams(initialValue, context) { let result = initialValue; for (const plugin of this.plugins) if (plugin.transformParams) { const partial = await plugin.transformParams(result, context); result = { ...result, ...partial }; } return result; } /** * 执行 transformResult 钩子 - 链式结果转换 * 每个插件接收并返回完整的 TResult */ async executeTransformResult(initialValue, context) { let result = initialValue; for (const plugin of this.plugins) if (plugin.transformResult) result = await plugin.transformResult(result, context); return result; } /** * 执行 ConfigureContext 钩子 - 串行配置上下文 */ async executeConfigureContext(context) { for (const plugin of this.plugins) { const hook = plugin.configureContext; if (hook) await hook(context); } } /** * 执行 Parallel 钩子 - 并行副作用 */ async executeParallel(hookName, context, result, error) { const promises = this.plugins.map((plugin) => { const hook = plugin[hookName]; if (!hook) return null; if (hookName === "onError" && error !== void 0) return hook(error, context); else if (hookName === "onRequestEnd" && result !== void 0) return hook(context, result); else if (hookName === "onRequestStart") return hook(context); return null; }).filter(Boolean); await Promise.all(promises); } /** * 收集所有流转换器(返回数组,AI SDK 原生支持) */ collectStreamTransforms(params, context) { return this.plugins.filter((plugin) => plugin.transformStream).map((plugin) => plugin.transformStream?.(params, context)); } /** * 获取所有插件信息 */ getPlugins() { return [...this.plugins]; } /** * 获取插件统计信息 */ getStats() { const stats = { total: this.plugins.length, pre: 0, normal: 0, post: 0, hooks: { resolveModel: 0, loadTemplate: 0, transformParams: 0, transformResult: 0, onRequestStart: 0, onRequestEnd: 0, onError: 0, transformStream: 0 } }; this.plugins.forEach((plugin) => { if (plugin.enforce === "pre") stats.pre++; else if (plugin.enforce === "post") stats.post++; else stats.normal++; Object.keys(stats.hooks).forEach((hookName) => { if (plugin[hookName]) stats.hooks[hookName]++; }); }); return stats; } }; //#endregion //#region src/core/plugins/index.ts function createContext(providerId, model, originalParams) { return { providerId, model, originalParams, metadata: {}, startTime: Date.now(), requestId: `${providerId}-${typeof model === "string" ? model : model?.modelId}-${Date.now()}-${Math.random().toString(36).slice(2)}`, isRecursiveCall: false, recursiveDepth: 0, maxRecursiveDepth: 10, extensions: /* @__PURE__ */ new Map(), middlewares: [], recursiveCall: () => Promise.resolve(null) }; } function definePlugin(plugin) { return plugin; } //#endregion export { definePlugin as n, PluginManager as r, createContext as t };