From 9ee15ceec9b7b74b2343b386bdd4c7cb92dfe2f3 Mon Sep 17 00:00:00 2001 From: suyao Date: Mon, 29 Dec 2025 19:22:12 +0800 Subject: [PATCH] refactor: improve type safety and documentation in PluginManager and PluginEngine --- packages/aiCore/src/core/plugins/manager.ts | 13 ++++++------- packages/aiCore/src/core/runtime/pluginEngine.ts | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/aiCore/src/core/plugins/manager.ts b/packages/aiCore/src/core/plugins/manager.ts index 1d0c588767..e7cd9da3c0 100644 --- a/packages/aiCore/src/core/plugins/manager.ts +++ b/packages/aiCore/src/core/plugins/manager.ts @@ -1,8 +1,7 @@ import type { AiPlugin, AiRequestContext } from './types' /** - * 插件管理器(泛型化) - * 支持类型安全的插件管理,同时通过逆变保持灵活性 + * 插件管理器 */ export class PluginManager { private plugins: AiPlugin[] = [] @@ -12,7 +11,7 @@ export class PluginManager { } /** - * 添加插件(支持逆变:AiPlugin 可赋值给 AiPlugin) + * 添加插件 */ use(plugin: AiPlugin): this { this.plugins = this.sortPlugins([...this.plugins, plugin]) @@ -131,12 +130,12 @@ export class PluginManager { const hook = plugin[hookName] if (!hook) return null - if (hookName === 'onError' && error) { - return (hook as any)(error, context) + if (hookName === 'onError' && error !== undefined) { + return (hook as NonNullable)(error, context) } else if (hookName === 'onRequestEnd' && result !== undefined) { - return (hook as any)(context, result) + return (hook as NonNullable)(context, result) } else if (hookName === 'onRequestStart') { - return (hook as any)(context) + return (hook as NonNullable)(context) } return null }) diff --git a/packages/aiCore/src/core/runtime/pluginEngine.ts b/packages/aiCore/src/core/runtime/pluginEngine.ts index 7f992a3b03..92b79d4d89 100644 --- a/packages/aiCore/src/core/runtime/pluginEngine.ts +++ b/packages/aiCore/src/core/runtime/pluginEngine.ts @@ -20,8 +20,18 @@ import { type ProviderId } from '../providers/types' * 专注于插件处理,不暴露用户API */ export class PluginEngine { - // ✅ 存储为非泛型数组(允许混合不同类型的插件) - private basePlugins: AiPlugin[] = [] + /** + * Plugin storage with explicit any/any generics + * + * SAFETY: Plugins are contravariant in TParams and covariant in TResult. + * The cast to AiPlugin[] in PluginManager is safe due to variance rules: + * - A plugin accepting any params (TParams = any) can handle specific params + * - A plugin returning any result (TResult = any) can be used as any specific result type + * + * Using AiPlugin instead of AiPlugin preserves generic type information + * and makes the variance relationship explicit for type checking. + */ + private basePlugins: AiPlugin[] = [] constructor( private readonly providerId: T,