@cherrystudio/ai-core
Version:
Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK
169 lines (167 loc) • 4.27 kB
JavaScript
//#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 };