@chatbi-v/core 2.1.2 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +65 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ports/plugin-port.ts","../src/utils/logger.ts","../src/application/service-registry.ts","../src/api-context.tsx","../src/components/PluginErrorBoundary.tsx","../src/domain/plugin-manager.ts","../src/adapters/local-storage-adapter.ts","../src/event-bus.ts","../src/sandbox/proxy-sandbox.ts","../src/domain/plugin-sandbox.ts","../src/domain/plugin-runtime.ts","../src/adapters/scoped-storage-adapter.ts","../src/domain/storage-manager.ts","../src/components/PluginSlot.tsx","../src/components/SlotSkeletons.tsx","../src/domain/auto-loader.ts","../src/domain/models.ts","../src/plugin-context.tsx","../src/api/adapters/axios-adapter.ts","../src/api/engine.ts","../src/utils/url.ts","../src/api/utils.ts","../src/utils/date.ts","../src/utils/index.ts","../src/hooks/use-storage-state.ts","../src/hooks/use-plugin-loader.ts"],"sourcesContent":["import React from 'react';\n\nimport { ApiConfig } from './api-port';\nimport { EventBusPort } from './event-bus-port';\nimport { TypedStorage } from './storage-port';\n\n/**\n * 插件类型定义\n */\nexport const PLUGIN_TYPES = ['business', 'functional', 'view', 'theme', 'renderer', 'system'] as const;\nexport type PluginType = typeof PLUGIN_TYPES[number];\n\n/**\n * 路由配置\n */\nexport interface RouteConfig {\n path: string;\n component: React.ComponentType<any>;\n meta?: Record<string, any>;\n}\n\n/**\n * 插件插槽位置\n * @description 定义插件可以注入 UI 的标准位置\n */\nexport const Slot = {\n Sidebar: 'sidebar',\n SidebarPanel: 'sidebar-panel',\n Header: 'header',\n StatusBar: 'status-bar',\n Settings: 'settings',\n MessageRenderer: 'message-renderer',\n MessageContentRenderer: 'message-content-renderer',\n SidebarSystem: 'sidebar-system',\n SidebarBottom: 'sidebar-bottom',\n RootLayout: 'root-layout',\n Custom: 'custom'\n} as const;\n\nexport type SlotType = typeof Slot[keyof typeof Slot];\n\nexport type SlotPosition = SlotType | string;\n\n/**\n * 插件扩展 (插槽注入配置)\n */\nexport interface PluginExtension {\n /** 插槽位置标识符 */\n slot: SlotPosition;\n /** 要注入的 React 组件 */\n component: React.ComponentType<any>;\n /** 排序权重,数值越小越靠前 */\n order?: number;\n /** @internal 插件 ID,由系统在加载时自动注入,用于溯源 */\n _pluginId?: string;\n /** 扩展的元数据信息 */\n meta?: {\n /** 显示图标 */\n icon?: React.ReactNode;\n /** 显示标签文本 */\n label?: string;\n /** 详细描述 */\n description?: string;\n /** 唯一标识符,用于某些特定插槽的索引 */\n key?: string;\n /** 允许其他自定义属性 */\n [key: string]: any;\n };\n}\n\n/**\n * 插件配置项定义\n */\nexport interface PluginConfigItem {\n /** 配置键名 */\n key: string;\n /** 配置类型 */\n type: 'string' | 'number' | 'boolean' | 'select';\n /** 配置显示的标签 */\n label: string;\n /** 配置描述信息 */\n description?: string;\n /** 默认值 */\n default?: any;\n /** 当类型为 select 时的选项列表 */\n options?: { label: string; value: any }[];\n /** 选择模式:支持多选或标签模式 (AntD 风格) */\n mode?: 'multiple' | 'tags';\n /** 最小值 (针对 number 类型) */\n min?: number;\n /** 最大值 (针对 number 类型) */\n max?: number;\n /** \n * 是否为私有配置\n * @description 如果为 true,则该配置不会通过自动配置服务暴露给其他插件\n * @default false\n */\n private?: boolean;\n}\n\n/**\n * 插件能力定义 (Behavioral Capabilities)\n * @description 定义插件的行为特征。注意:路由(routes)和扩展(extensions)属于结构化能力,直接通过 metadata 字段声明,不在此列。\n */\nexport interface PluginCapabilities {\n /** \n * 是否支持配置设置 \n * @default false (如果 metadata.configuration 存在,则可能被隐式视为 true,建议显式声明)\n */\n configurable?: boolean;\n /** \n * 是否可嵌入其他页面 \n * @description 声明该插件是否可以作为 Widget 被其他插件引用\n */\n embeddable?: boolean;\n /** \n * 是否支持多实例 \n * @description 默认为 false (单例)。如果在聊天窗口中每个会话都需要独立状态,则设为 true\n */\n multiInstance?: boolean;\n /** \n * 是否需要后台运行 \n * @description 如果为 true,即使 UI 不可见,插件也不会被卸载\n */\n background?: boolean;\n [key: string]: boolean | undefined;\n}\n\n/**\n * 存储项数据结构定义 (Schema)\n */\nexport interface StorageItemSchema {\n /** 存储键名 */\n key: string;\n /** 数据类型 */\n type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n /** 默认值 */\n default?: any;\n /** 描述信息 */\n description?: string;\n /** \n * 作用域\n * @description 'plugin' 表示仅当前插件可见(带插件 ID 前缀),'shared' 表示全局共享\n */\n scope?: 'plugin' | 'shared';\n}\n\n/**\n * 插件存储接口\n * @description 包含私有存储和共享存储访问能力\n */\nexport interface PluginStorage extends TypedStorage {\n /** 获取插件私有存储数据 */\n get: TypedStorage['get'];\n /** 设置插件私有存储数据 */\n set: TypedStorage['set'];\n /** 移除插件私有存储数据 */\n remove: TypedStorage['remove'];\n /** 全局共享存储访问 */\n shared: TypedStorage & {\n /** 获取全局共享存储数据 */\n get: TypedStorage['get'];\n /** 设置全局共享存储数据 */\n set: TypedStorage['set'];\n /** 移除全局共享存储数据 */\n remove: TypedStorage['remove'];\n };\n}\n\n/**\n * 插件生命周期 Hooks\n * @description 插件可以在不同的生命周期阶段执行特定的逻辑\n */\nexport interface PluginLifecycle {\n /**\n * 插件加载时调用\n * @description 在插件被扫描并注入内核时触发。用于初始化内部状态、注册服务、设置拦截器等。此时 UI 尚未挂载。\n * @param context - 插件上下文对象,提供核心能力的访问\n */\n onLoad?: (context: PluginContext) => void | Promise<void>;\n\n /**\n * 插件挂载到 UI 时调用\n * @description 当插件的 UI 组件(如有)被 React 挂载到 DOM 时触发。\n * @param context - 插件上下文对象\n */\n onMount?: (context: PluginContext) => void;\n\n /**\n * 插件从 UI 卸载时调用\n * @description 当插件的 UI 组件被销毁时触发。用于清理定时器、取消订阅等。\n * @param context - 插件上下文对象\n */\n onUnmount?: (context: PluginContext) => void;\n\n /**\n * 插件配置发生变化时调用\n * @description 当用户通过配置中心修改插件设置时触发。\n * @param newConfig - 变更后的新配置对象\n * @param oldConfig - 变更前的旧配置对象\n */\n onConfigChange?: (newConfig: any, oldConfig: any) => void;\n}\n\n/**\n * 插件上下文\n * @description 传递给插件生命周期钩子的核心对象,是插件访问宿主环境能力的唯一入口。\n */\nexport interface PluginContext {\n /** 当前插件的唯一标识符 */\n pluginId: string;\n /** API 请求能力入口 */\n api: any;\n /** 事件总线能力入口 */\n events: EventBusPort;\n /** 存储管理能力入口 */\n storage: PluginStorage;\n /** 日志输出工具,自动携带插件 ID 前缀 */\n logger: {\n debug: (...args: any[]) => void;\n info: (...args: any[]) => void;\n warn: (...args: any[]) => void;\n error: (...args: any[]) => void;\n };\n /** \n * 访问其他插件提供的服务\n * @param serviceName - 服务注册名称\n * @returns 服务实例,如果不存在则返回 undefined\n */\n getService: <T = any>(serviceName: string) => T | undefined;\n /** \n * 注册当前插件的服务供他人使用\n * @param serviceName - 唯一服务名称\n * @param service - 服务实现对象\n */\n registerService: (serviceName: string, service: any) => void;\n /** 宿主环境 Window 的代理对象 (用于沙箱隔离) */\n window: WindowProxy;\n}\n\n/**\n * 完整的插件对象定义\n */\nexport interface Plugin extends PluginLifecycle {\n /** \n * 插件唯一标识符\n * @description 必须与 metadata.id 一致,通常为只读。\n */\n readonly id: string;\n /** 插件元数据配置 */\n metadata: PluginMetadata;\n /** 插件提供的功能组件集合 (可选) */\n components?: Record<string, React.ComponentType<any>>;\n /** 插件提供的工具函数集合 (可选) */\n utils?: Record<string, any>;\n /** 插件的初始默认配置 (可选) */\n defaultConfig?: Record<string, any>;\n}\n\n/**\n * 插件基础类\n * @deprecated 建议统一使用工厂模式 definePlugin() 定义插件,以消除类与对象定义的歧义。\n * @description 解决插件定义时 id 与 metadata.id 重复定义的问题,并提供基础生命周期管理\n */\nexport abstract class BasePlugin implements Plugin {\n abstract metadata: PluginMetadata;\n \n /** \n * 插件 ID\n * @description 自动从 metadata.id 获取\n */\n get id(): string {\n return this.metadata.id;\n }\n\n onLoad?(context: PluginContext): void | Promise<void>;\n onMount?(context: PluginContext): void;\n onUnmount?(context: PluginContext): void;\n onConfigChange?(newConfig: any, oldConfig: any): void;\n}\n\n/**\n * 辅助函数:定义插件并自动从 metadata.id 注入顶级 id\n * @description 解决插件定义时 id 与 metadata.id 重复定义的问题,提高代码优雅度\n * @param plugin 插件定义(不包含顶级 id)\n * @returns 完整的插件对象\n */\nexport function definePlugin(plugin: Omit<Plugin, 'id'>): Plugin {\n return {\n ...plugin,\n get id() { return this.metadata.id; }\n } as Plugin;\n}\n\n/**\n * 插件元数据定义\n * @description 描述插件的静态属性,用于插件市场展示、权限校验和内核加载参考。\n */\nexport interface PluginMetadata {\n /** 插件唯一 ID (推荐反向域名格式,如 com.company.plugin) */\n id: string;\n /** 插件显示名称 */\n name: string;\n /** 插件版本号 (符合 SemVer 规范) */\n version: string;\n /** 插件类型 */\n type: PluginType;\n /** 插件功能描述 */\n description?: string;\n /** 插件作者信息 */\n author?: string;\n /** 插件图标 (React 组件或图标名称) */\n icon?: React.ReactNode;\n /** 插件依赖的其他插件 ID 列表 */\n dependencies?: string[];\n /** 路由配置集合,用于在主应用中注册页面 */\n routes?: RouteConfig[];\n /** 插槽扩展集合,用于在主应用 UI 预留位注入组件 */\n extensions?: PluginExtension[];\n /** 插件所需调用的 API 接口配置 */\n api?: ApiConfig;\n /** 插件行为能力声明 */\n capabilities?: PluginCapabilities;\n /** 插件的可配置项定义 */\n configuration?: PluginConfigItem[];\n /** 插件所需的存储结构定义 */\n storage?: StorageItemSchema[];\n /** \n * 系统状态自动绑定\n * @description 将插件的配置项自动同步到系统的全局状态中 (如主题色、身份认证等)\n */\n systemStateBindings?: {\n /** 插件配置中的键名 */\n configKey: string;\n /** 系统全局状态中的键名 */\n stateKey: string;\n /** 预设的转换逻辑名称 */\n transform?: 'theme-mode' | 'identity';\n }[];\n}\n","/**\n * 日志等级枚举\n */\nexport enum LogLevel {\n /** 调试级别:输出最详尽的信息 */\n DEBUG = 0,\n /** 信息级别:输出重要的运行状态 */\n INFO = 1,\n /** 警告级别:输出潜在的问题,但不影响运行 */\n WARN = 2,\n /** 错误级别:输出严重的运行异常 */\n ERROR = 3,\n /** 禁用日志:不输出任何信息 */\n NONE = 4,\n}\n\n/**\n * 日志条目结构\n */\ninterface LogEntry {\n level: LogLevel;\n prefix: string;\n message: any[];\n timestamp: number;\n}\n\n/**\n * 简单的颜色生成器 (djb2 hash)\n */\nfunction getColorForString(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) + hash + str.charCodeAt(i);\n }\n // 生成 HSL 颜色,保持较高的饱和度和亮度,适合深/浅色主题\n const hue = Math.abs(hash % 360);\n return `hsl(${hue}, 70%, 45%)`;\n}\n\n/**\n * 简单的 ANSI 颜色代码 (Node.js 环境)\n */\nconst ANSI = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n colors: [\n '\\x1b[31m', // Red\n '\\x1b[32m', // Green\n '\\x1b[33m', // Yellow\n '\\x1b[34m', // Blue\n '\\x1b[35m', // Magenta\n '\\x1b[36m', // Cyan\n ]\n};\n\nfunction getAnsiColorForString(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = str.charCodeAt(i) + ((hash << 5) - hash);\n }\n const index = Math.abs(hash % ANSI.colors.length);\n return ANSI.colors[index];\n}\n\n/**\n * 日志工具类\n * @description 核心工具类,提供统一的日志输出格式 `[Prefix] Message`。\n * 支持通过 `LogLevel` 进行全局过滤。\n * 支持日志缓冲和自动分组,以减少控制台噪音。\n * 支持浏览器端 CSS 样式和 Node.js 端 ANSI 颜色。\n */\nexport class Logger {\n /** 全局静态日志等级,所有实例共享 */\n private static level: LogLevel = LogLevel.INFO;\n \n /** 日志缓冲区 */\n private static buffer: LogEntry[] = [];\n \n /** 缓冲输出防抖定时器 */\n private static flushTimer: any = null;\n \n /** 缓冲时间窗口 (ms) */\n private static FLUSH_INTERVAL = 100;\n\n /** 是否启用缓冲模式 */\n private static bufferEnabled = true;\n\n /** 是否为浏览器环境 */\n private static isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';\n\n /** 当前实例的业务模块前缀 */\n private prefix: string;\n\n /** 实例特定的颜色 */\n private color: string;\n\n /**\n * 构造函数\n * @param prefix - 业务模块前缀,默认为 'App'\n */\n constructor(prefix: string = 'App') {\n this.prefix = prefix;\n this.color = getColorForString(prefix);\n }\n\n /**\n * 静态方法:设置全局日志输出等级\n * @param level - 目标日志等级\n */\n static setLevel(level: LogLevel) {\n this.level = level;\n console.log(`[Logger] Global log level set to: ${LogLevel[level]}`);\n }\n\n /**\n * 静态方法:启用或禁用日志缓冲\n * @param enabled - 是否启用\n */\n static setBufferEnabled(enabled: boolean) {\n this.bufferEnabled = enabled;\n if (!enabled) {\n this.flush();\n }\n }\n\n /**\n * 静态方法:获取当前全局日志等级\n * @returns 当前生效的全局日志等级\n */\n static getLevel(): LogLevel {\n return this.level;\n }\n\n /**\n * 格式化输出前缀\n */\n private getFormattedPrefix(prefix: string, level: LogLevel): any[] {\n if (Logger.isBrowser) {\n const color = getColorForString(prefix);\n // Badge 风格样式\n const style = [\n `background: ${color}`,\n 'color: white',\n 'border-radius: 3px',\n 'padding: 2px 6px',\n 'font-weight: bold',\n 'font-family: monospace'\n ].join(';');\n \n return [`%c ${prefix} `, style];\n } else {\n // Node.js 环境 ANSI 颜色\n const colorCode = getAnsiColorForString(prefix);\n return [`${colorCode}[${prefix}]${ANSI.reset}`];\n }\n }\n\n /**\n * 生成分组标题参数\n */\n private static getGroupTitleArgs(prefix: string, count: number, countDetails: string = ''): any[] {\n if (Logger.isBrowser) {\n const color = getColorForString(prefix);\n const badgeStyle = `background: ${color}; color: white; border-radius: 3px; padding: 2px 6px; font-weight: bold;`;\n const titleStyle = `color: ${color}; font-weight: bold;`;\n const countStyle = 'color: gray; font-size: 0.9em;';\n \n const countStr = count > 0 ? `(${count > 1 ? count + ' messages' : '1 message'}${countDetails ? ', ' + countDetails : ''})` : '';\n \n return [`%c ${prefix} %c ${countStr}`, badgeStyle, countStyle];\n } else {\n const colorCode = getAnsiColorForString(prefix);\n const countStr = count > 0 ? `(${count > 1 ? count + ' messages' : '1 message'}${countDetails ? ', ' + countDetails : ''})` : '';\n return [`${colorCode}[${prefix}]${ANSI.reset} ${ANSI.dim}${countStr}${ANSI.reset}`];\n }\n }\n\n /**\n * 内部方法:将日志推入缓冲区或直接输出\n */\n private log(level: LogLevel, ...args: any[]) {\n if (Logger.level > level) return;\n\n if (level === LogLevel.ERROR) {\n Logger.flush();\n const prefixArgs = this.getFormattedPrefix(this.prefix, level);\n console.error(...prefixArgs, ...args);\n return;\n }\n\n if (!Logger.bufferEnabled) {\n // 非缓冲模式也统一使用 group 输出,保持界面整洁\n const method = level === LogLevel.WARN ? 'warn' : level === LogLevel.DEBUG ? 'debug' : 'info';\n const groupArgs = Logger.getGroupTitleArgs(this.prefix, 1);\n \n console.groupCollapsed(...groupArgs);\n console[method](...args);\n console.groupEnd();\n return;\n }\n\n Logger.buffer.push({\n level,\n prefix: this.prefix,\n message: args,\n timestamp: Date.now(),\n });\n\n if (!Logger.flushTimer) {\n Logger.flushTimer = setTimeout(() => {\n Logger.flush();\n }, Logger.FLUSH_INTERVAL);\n }\n }\n\n /**\n * 静态方法:刷新缓冲区,分组输出日志\n */\n static flush() {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n\n if (this.buffer.length === 0) return;\n\n const groups = new Map<string, LogEntry[]>();\n const prefixOrder: string[] = [];\n\n this.buffer.forEach(entry => {\n if (!groups.has(entry.prefix)) {\n groups.set(entry.prefix, []);\n prefixOrder.push(entry.prefix);\n }\n groups.get(entry.prefix)!.push(entry);\n });\n\n prefixOrder.forEach(prefix => {\n const entries = groups.get(prefix)!;\n \n // 统计各级别数量\n const counts = entries.reduce((acc, curr) => {\n const key = curr.level === LogLevel.WARN ? 'warn' : 'info';\n acc[key] = (acc[key] || 0) + 1;\n return acc;\n }, {} as Record<string, number>);\n \n const countDetails = Object.entries(counts)\n .map(([k, v]) => `${v} ${k}`)\n .join(', ');\n\n // 无论条数多少,统一使用折叠分组\n const groupTitleArgs = Logger.getGroupTitleArgs(prefix, entries.length, entries.length > 1 ? countDetails : '');\n\n console.groupCollapsed(...groupTitleArgs);\n entries.forEach(entry => {\n const method = entry.level === LogLevel.WARN ? 'warn' : entry.level === LogLevel.DEBUG ? 'debug' : 'info';\n // 组内日志不再显示前缀,保持清爽\n console[method](...entry.message);\n });\n console.groupEnd();\n });\n\n this.buffer = [];\n }\n\n /**\n * 打印 DEBUG 级别日志\n */\n debug(...args: any[]) {\n this.log(LogLevel.DEBUG, ...args);\n }\n\n /**\n * 打印 INFO 级别日志\n */\n info(...args: any[]) {\n this.log(LogLevel.INFO, ...args);\n }\n\n /**\n * 打印 WARN 级别日志\n */\n warn(...args: any[]) {\n this.log(LogLevel.WARN, ...args);\n }\n\n /**\n * 打印 ERROR 级别日志\n */\n error(...args: any[]) {\n this.log(LogLevel.ERROR, ...args);\n }\n\n /**\n * 开始一个日志控制台分组\n */\n group(label: string, collapsed: boolean = false) {\n if (Logger.level <= LogLevel.INFO) {\n Logger.flush();\n const prefixArgs = this.getFormattedPrefix(this.prefix, LogLevel.INFO);\n // 这里的 group 只能简单输出,无法像 flush 那样做复杂的样式组合,因为 label 是用户传的\n if (Logger.isBrowser) {\n if (collapsed) {\n console.groupCollapsed(...prefixArgs, label);\n } else {\n console.group(...prefixArgs, label);\n }\n } else {\n const title = `${prefixArgs[0]} ${label}`;\n if (collapsed) {\n console.groupCollapsed(title);\n } else {\n console.group(title);\n }\n }\n }\n }\n\n /**\n * 结束当前日志控制台分组\n */\n groupEnd() {\n if (Logger.level <= LogLevel.INFO) {\n Logger.flush();\n console.groupEnd();\n }\n }\n}\n\n/** 默认 Logger 实例 */\nexport const logger = new Logger();\n\n/**\n * 创建带特定前缀的 Logger 实例\n * @param prefix 日志前缀\n * @returns Logger 实例\n */\nexport const createLogger = (prefix: string) => new Logger(prefix);\n","import { createLogger } from '../utils/logger';\n\nconst logger = createLogger('ServiceRegistry');\n\n/**\n * 服务注册中心 (Service Registry)\n * @description 核心应用层服务,作为微内核架构中的“中枢调度员”。\n * 主要职责:\n * 1. 服务解耦:允许插件将其内部功能暴露为“服务”,而无需与其他插件产生物理依赖。\n * 2. 动态发现:提供按名称查找服务的能力,支持服务热插拔。\n * 3. 依赖协调:通过 `waitFor` 机制解决插件间由于加载顺序导致的初始化依赖问题。\n * \n * 建议的服务命名规范: `pluginId.serviceName` (例如: `auth.sessionService`)\n */\nexport class ServiceRegistry {\n /** 存储已注册服务的 Map 对象 */\n private services = new Map<string, any>();\n /** 存储正在等待特定服务的监听器集合 */\n private listeners = new Map<string, Set<(service: any) => void>>();\n\n /**\n * 注册一个服务实现\n * @param name - 唯一的服务名称\n * @param service - 服务实例或对象\n */\n register(name: string, service: any) {\n if (this.services.has(name)) {\n logger.warn(`服务 \"${name}\" 已存在,将被覆盖`);\n }\n this.services.set(name, service);\n logger.info(`服务已注册: ${name}`);\n\n // 通知正在等待该服务的监听器\n if (this.listeners.has(name)) {\n const set = this.listeners.get(name)!;\n set.forEach(callback => callback(service));\n this.listeners.delete(name);\n }\n }\n\n /**\n * 同步获取服务实例\n * @template T - 服务类型的泛型\n * @param name - 服务名称\n * @returns 服务实例,若不存在则返回 undefined\n */\n get<T = any>(name: string): T | undefined {\n return this.services.get(name);\n }\n\n /**\n * 异步等待并获取服务\n * @description 如果服务尚未注册,将返回一个 Promise,直到该服务被注册时 resolve。\n * 支持设置超时时间,防止因插件加载失败导致的永久挂起。\n * \n * @template T - 服务类型的泛型\n * @param name - 待等待的服务名称\n * @param timeout - 超时时间 (毫秒),默认 10000ms (10秒)。若为 0 则永不超时。\n * @returns 包含服务实例的 Promise\n * @throws {Error} 若在规定时间内服务未注册,则抛出超时异常。\n */\n async waitFor<T = any>(name: string, timeout: number = 10000): Promise<T> {\n const service = this.services.get(name);\n if (service) return service;\n\n return new Promise((resolve, reject) => {\n let timer: any = null;\n\n const callback = (s: T) => {\n if (timer) clearTimeout(timer);\n resolve(s);\n };\n\n if (!this.listeners.has(name)) {\n this.listeners.set(name, new Set());\n }\n this.listeners.get(name)!.add(callback);\n\n // 超时处理\n if (timeout > 0) {\n timer = setTimeout(() => {\n const set = this.listeners.get(name);\n if (set) {\n set.delete(callback);\n if (set.size === 0) this.listeners.delete(name);\n }\n reject(new Error(`等待服务 \"${name}\" 超时 (${timeout}ms)`));\n }, timeout);\n }\n });\n }\n\n /**\n * 检查服务是否已注册\n * @param name - 服务名称\n */\n has(name: string): boolean {\n return this.services.has(name);\n }\n\n /**\n * 注销特定的服务\n * @param name - 服务名称\n */\n unregister(name: string) {\n this.services.delete(name);\n logger.info(`服务已注销: ${name}`);\n }\n\n /**\n * 清除所有已注册的服务和监听器\n * @description 通常仅在系统重置或大型热更新时使用。\n */\n clear() {\n this.services.clear();\n this.listeners.clear();\n }\n}\n\n// 导出单例\nexport const serviceRegistry = new ServiceRegistry();\n","import React, { createContext, useContext } from 'react';\n\nimport type { ApiEngine } from './api';\n\nconst ApiContext = createContext<ApiEngine | null>(null);\n\nexport interface ApiProviderProps {\n api: ApiEngine;\n children: React.ReactNode;\n}\n\nexport const ApiProvider: React.FC<ApiProviderProps> = ({ api, children }) => {\n return <ApiContext.Provider value={api}>{children}</ApiContext.Provider>;\n};\n\nexport const useApi = () => {\n const context = useContext(ApiContext);\n if (!context) {\n throw new Error('useApi must be used within an ApiProvider');\n }\n return context;\n};\n","import React, { Component, ErrorInfo, ReactNode } from 'react';\n\nimport { pluginManager } from '../domain/plugin-manager';\nimport { createLogger } from '../utils/logger';\n\nconst logger = createLogger('PluginErrorBoundary');\n\n/** 插件错误边界组件属性 */\ninterface Props {\n /** 发生错误的插件 ID */\n pluginId?: string;\n /** 错误发生时的降级 UI */\n fallback?: ReactNode;\n /** 子组件内容 */\n children: ReactNode;\n /** 是否静默模式,开启后不显示任何错误 UI,仅记录日志 */\n silent?: boolean;\n}\n\n/** 插件错误边界组件状态 */\ninterface State {\n /** 是否捕获到错误 */\n hasError: boolean;\n /** 捕获到的错误对象 */\n error: Error | null;\n}\n\n/**\n * 插件错误边界组件\n * @description 核心组件,用于捕获子组件渲染过程中的 JavaScript 错误,记录日志并显示降级 UI。\n * 确保单个插件的运行异常不会导致整个主应用或其他插件崩溃。\n */\nexport class PluginErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n /**\n * 从错误中派生状态\n * @param error - 捕获到的错误\n */\n static getDerivedStateFromError(error: any): State {\n // 忽略 Suspense 导致的错误,让 React 正常处理 Suspense\n if (error && typeof error.then === 'function') {\n return { hasError: false, error: null };\n }\n return { hasError: true, error: error instanceof Error ? error : new Error(String(error)) };\n }\n\n /**\n * 捕获到错误后的回调\n * @param error - 错误对象\n * @param errorInfo - 错误堆栈信息\n */\n componentDidCatch(error: any, errorInfo: ErrorInfo) {\n // 忽略 Suspense 导致的错误\n if (error && typeof error.then === 'function') {\n return;\n }\n \n logger.error(`插件 ${this.props.pluginId || '未知'} 渲染发生错误:`, error, errorInfo);\n \n // 如果有 pluginId,尝试在控制台输出更友好的提示,并上报给管理器\n if (this.props.pluginId) {\n console.warn(`[PluginError] 插件 \"${this.props.pluginId}\" 渲染失败。您可以在插件管理面板查看详细信息。`);\n \n // 直接上报插件 ID\n pluginManager.reportPluginError(this.props.pluginId, error);\n }\n }\n\n /**\n * 重置错误状态,尝试重新渲染\n */\n handleRetry = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n if (this.props.silent) {\n return null;\n }\n\n // 默认提供一个极其简约的占位,避免破坏布局,同时通过 data 属性暴露错误信息供调试\n return (\n <div \n className=\"plugin-error-placeholder hidden\" \n data-plugin-id={this.props.pluginId} \n data-error={this.state.error?.message}\n />\n );\n }\n\n return this.props.children;\n }\n}\n","/**\n * @file plugin-manager.ts\n * @description 插件管理器,负责插件的注册、生命周期管理、状态持久化及扩展点收集\n * @author ChatBI Team\n */\n\nimport { startTransition } from 'react';\nimport { LocalStorageAdapter } from '../adapters/local-storage-adapter';\nimport { configManager } from '../config-manager';\nimport { DefaultEventBus } from '../event-bus';\nimport { serviceRegistry } from '../application/service-registry';\nimport {\n Plugin,\n PLUGIN_TYPES,\n PluginExtension,\n RouteConfig,\n SlotPosition,\n StorageItemSchema,\n} from '../ports/plugin-port';\nimport { StoragePort } from '../ports/storage-port';\nimport { createLogger } from '../utils/logger';\nimport { PluginRuntime } from './plugin-runtime';\nimport { StorageManager } from './storage-manager';\n\nconst logger = createLogger('PluginManager');\n\n/**\n * 插件管理器\n * @description 核心领域服务,负责插件的完整生命周期管理,包括扫描、注册、配置合并、状态切换及依赖解析。\n */\nexport class PluginManager {\n /** 全局事件总线,用于插件间及插件与内核间的异步通信 */\n public readonly eventBus = new DefaultEventBus();\n\n /** 存储管理服务,负责插件私有存储和系统级状态的持久化 */\n private storageManager: StorageManager;\n\n /** 插件 ID 到运行时实例的映射表 */\n private runtimes = new Map<string, PluginRuntime>();\n /** 插件 ID 到原始插件定义对象的映射表 */\n private plugins = new Map<string, Plugin>();\n /** 收集到的所有插件路由配置 */\n private routes: RouteConfig[] = [];\n /** 收集到的所有插件扩展点配置,按插槽位置分组 */\n private extensions: Map<SlotPosition, PluginExtension[]> = new Map();\n /** 插件的启用状态和排序信息的内存缓存 */\n private pluginStates: Record<string, { enabled: boolean; order: number }> = {};\n /** 状态变更监听器集合,支持按插槽过滤 */\n private listeners: Set<() => void> = new Set();\n /** 按插槽位置存储的监听器,用于精确通知 */\n private slotListeners: Map<string, Set<() => void>> = new Map();\n /** 扩展点缓存,避免重复计算 */\n private memoizedExtensions: Map<string, PluginExtension[]> = new Map();\n /** 路由缓存 */\n private memoizedRoutes: RouteConfig[] | null = null;\n /** 传递给插件的共享上下文缓存 */\n private sharedContext: Record<string, any> | null = null;\n /** 收集到的插件工具函数集合 */\n private utils: Record<string, any> = {};\n\n /**\n * 构造函数\n * @param storage - 底层存储适配器\n */\n constructor(storage: StoragePort) {\n this.storageManager = new StorageManager(storage);\n\n // 1. 加载持久化的插件状态\n this.loadStates();\n\n // 2. 订阅状态变更以持久化\n this.subscribe(() => {\n this.saveStates();\n });\n }\n\n /**\n * 从持久化存储中恢复插件状态 (启用/禁用、排序等)\n */\n private loadStates() {\n try {\n const systemStorage = this.storageManager.getSystemStorage();\n\n // 1. 优先尝试从新位置 (system:plugin_states) 读取\n const savedStates = systemStorage.getItem('plugin_states');\n\n if (savedStates) {\n this.pluginStates = JSON.parse(savedStates);\n logger.debug('从系统存储中加载状态:', this.pluginStates);\n }\n } catch (e) {\n logger.error('加载插件状态失败:', e);\n }\n }\n\n /**\n * 将当前的插件状态持久化到存储中\n */\n private saveStates() {\n try {\n this.storageManager\n .getSystemStorage()\n .setItem('plugin_states', JSON.stringify(this.pluginStates));\n logger.debug('已保存插件状态到存储');\n } catch (e) {\n logger.error('保存插件状态失败:', e);\n }\n }\n\n /**\n * 订阅插件状态的变更通知\n * @param listener - 变更时的回调函数\n * @param slot - (可选) 指定监听的插槽位置,若提供则仅在该插槽受影响时通知\n * @returns 取消订阅的函数\n */\n subscribe(listener: () => void, slot?: SlotPosition | string) {\n if (slot) {\n const slotStr = String(slot);\n if (!this.slotListeners.has(slotStr)) {\n this.slotListeners.set(slotStr, new Set());\n }\n this.slotListeners.get(slotStr)!.add(listener);\n return () => {\n this.slotListeners.get(slotStr)?.delete(listener);\n };\n } else {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n }\n\n /**\n * 获取存储管理器实例\n * @returns StorageManager 实例\n */\n getStorageManager() {\n return this.storageManager;\n }\n\n /**\n * 触发状态变更通知\n * @param affectedSlot - (可选) 受影响的插槽位置\n */\n private notify(affectedSlot?: SlotPosition | string) {\n // 使用 startTransition 包裹通知,避免 Suspense 导致的同步渲染错误\n startTransition(() => {\n // 1. 清除受影响或全部的缓存\n if (affectedSlot) {\n this.memoizedExtensions.delete(String(affectedSlot));\n } else {\n this.memoizedExtensions.clear();\n this.memoizedRoutes = null;\n }\n\n // 2. 通知全局监听器\n this.listeners.forEach((listener) => listener());\n\n // 3. 通知特定插槽监听器\n if (affectedSlot) {\n this.slotListeners.get(String(affectedSlot))?.forEach(listener => listener());\n } else {\n // 如果没有指定插槽,通知所有插槽监听器\n this.slotListeners.forEach(set => set.forEach(listener => listener()));\n }\n });\n }\n\n /**\n * 获取所有已注册的插件列表\n * @description 结果会根据插件类型优先级和用户自定义排序进行排序\n * @returns 排序后的插件数组\n */\n getPlugins() {\n const typePriority: Record<string, number> = {\n system: 0,\n theme: 1,\n renderer: 2,\n functional: 3,\n business: 4,\n view: 5,\n };\n\n // 按照类型优先级和 order 排序\n return Array.from(this.plugins.values()).sort((a, b) => {\n const priorityA = typePriority[a.metadata.type] ?? 99;\n const priorityB = typePriority[b.metadata.type] ?? 99;\n\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n\n const stateA = this.pluginStates[a.id] || { order: 0 };\n const stateB = this.pluginStates[b.id] || { order: 0 };\n return stateA.order - stateB.order;\n });\n }\n\n /**\n * 获取指定插件的状态信息\n * @param pluginId - 插件 ID\n * @returns 包含启用状态和排序值的对象\n */\n getPluginState(pluginId: string) {\n return this.pluginStates[pluginId] || { enabled: true, order: 0 };\n }\n\n /**\n * 检查指定插件是否处于启用状态\n * @param pluginId - 插件 ID\n * @returns 是否启用\n */\n isPluginEnabled(pluginId: string) {\n const state = this.pluginStates[pluginId];\n return state ? state.enabled : true;\n }\n\n /**\n * 切换插件的启用/禁用状态\n * @description 禁用插件会立即触发其卸载生命周期并销毁运行时。\n * @param pluginId - 插件 ID\n * @param enabled - 目标状态\n */\n togglePlugin(pluginId: string, enabled: boolean) {\n const state = this.pluginStates[pluginId] || { enabled: true, order: 0 };\n this.pluginStates[pluginId] = { ...state, enabled };\n\n // 如果是禁用,卸载运行时\n if (!enabled) {\n const runtime = this.runtimes.get(pluginId);\n if (runtime) {\n runtime.unmount();\n this.runtimes.delete(pluginId);\n }\n } else {\n // 如果是启用,初始化运行时\n // 注意:这里需要确保 initPlugins 已经被调用过,有 sharedContext\n if (this.sharedContext) {\n const plugin = this.plugins.get(pluginId);\n if (plugin) {\n try {\n const runtime = new PluginRuntime(plugin, this.sharedContext, this.storageManager);\n this.runtimes.set(pluginId, runtime);\n runtime.mount();\n } catch (e) {\n logger.error(`启用插件 ${pluginId} 失败:`, e);\n }\n }\n }\n }\n\n this.notify();\n }\n\n /**\n * 设置插件的显示排序权重\n * @param pluginId - 插件 ID\n * @param order - 排序权重值\n */\n setPluginOrder(pluginId: string, order: number) {\n const state = this.pluginStates[pluginId] || { enabled: true, order: 0 };\n this.pluginStates[pluginId] = { ...state, order };\n this.notify();\n }\n\n /**\n * 获取指定插件的运行时状态\n * @param pluginId - 插件 ID\n * @returns 'error' | 'mounted' | 'loaded' | 'initial'\n */\n getPluginRuntimeStatus(pluginId: string) {\n const runtime = this.runtimes.get(pluginId);\n return runtime ? runtime.status : 'initial';\n }\n\n /**\n * 获取指定插件的运行时错误\n * @param pluginId - 插件 ID\n * @returns Error 对象或 null\n */\n getPluginError(pluginId: string) {\n const runtime = this.runtimes.get(pluginId);\n return runtime ? runtime.getError() : null;\n }\n\n /**\n * 报告插件运行时错误 (通常由 ErrorBoundary 调用)\n * @param pluginId - 插件 ID\n * @param error - 错误对象\n */\n reportPluginError(pluginId: string, error: Error) {\n const runtime = this.runtimes.get(pluginId);\n if (runtime) {\n // 这里的实现需要 PluginRuntime 支持外部设置错误\n (runtime as any)._setError?.(error);\n this.notify();\n }\n }\n\n /**\n * 获取插件的完整能力声明\n * @param pluginId - 插件 ID\n * @returns 能力对象\n */\n getUnifiedCapabilities(pluginId: string) {\n const plugin = this.plugins.get(pluginId);\n return plugin?.metadata.capabilities || {};\n }\n\n /**\n * 更新指定插件的某项配置\n * @description 该操作会同步更新内存中的配置、持久化到存储并触发全局事件通知。\n * @param pluginId - 插件 ID\n * @param key - 配置键名\n * @param value - 新的配置值\n */\n updatePluginConfig(pluginId: string, key: string, value: any) {\n // 1. 更新 ConfigManager (Runtime)\n const currentConfig = configManager.get(pluginId) || {};\n currentConfig[key] = value;\n configManager.set(pluginId, currentConfig);\n\n // 2. 持久化到存储 (使用 StorageManager)\n try {\n this.storageManager.getContextStorage(pluginId).set(key, value);\n } catch (e) {\n logger.warn('保存配置到存储失败', e);\n }\n\n // 3. 通过 EventBus 分发事件\n this.eventBus.emit('config:changed', { pluginId, key, value });\n }\n\n /**\n * 获取指定插件的某项配置值\n * @param pluginId - 插件 ID\n * @param key - 配置键名\n * @returns 配置值\n */\n getPluginConfig(pluginId: string, key: string): any {\n const config = configManager.get(pluginId);\n return config ? config[key] : undefined;\n }\n\n /**\n * 获取系统全局配置 (非插件特定)\n * @param key - 系统配置键名\n * @returns 配置值\n */\n getSystemConfig(key: string): any {\n const systemConfig = configManager.get('system');\n return systemConfig ? systemConfig[key] : undefined;\n }\n\n /**\n * 获取由插件注册的服务实例\n * @template T 服务接口类型\n * @param name - 服务注册名称\n * @returns 服务实例或 undefined\n */\n getService<T = any>(name: string): T | undefined {\n return serviceRegistry.get<T>(name);\n }\n\n /**\n * 获取指定插槽位置的所有已启用插件的扩展\n * @param slot - 插槽位置标识\n * @returns 排序后的扩展配置数组\n */\n getExtensions(slot: SlotPosition | string): PluginExtension[] {\n const slotStr = String(slot);\n \n // 1. 优先从缓存获取\n if (this.memoizedExtensions.has(slotStr)) {\n return this.memoizedExtensions.get(slotStr)!;\n }\n\n // 2. 计算扩展点\n const targetSlot = slot as SlotPosition;\n let extensions = this.extensions.get(targetSlot) || [];\n\n // 过滤掉已禁用插件的扩展\n extensions = extensions.filter((ext) => {\n const pluginId = ext._pluginId;\n return !pluginId || this.isPluginEnabled(pluginId);\n });\n\n // 排序\n const sortedExtensions = extensions.sort((a, b) => (a.order || 0) - (b.order || 0));\n \n // 3. 写入缓存\n this.memoizedExtensions.set(slotStr, sortedExtensions);\n \n return sortedExtensions;\n }\n\n /**\n * 获取所有已启用插件注册的路由配置\n * @returns 增强后的路由配置数组\n */\n getRoutes(): RouteConfig[] {\n // 1. 优先从缓存获取\n if (this.memoizedRoutes) {\n return this.memoizedRoutes;\n }\n\n // 2. 计算路由\n const activeRoutes: RouteConfig[] = [];\n this.getPlugins().forEach((plugin) => {\n if (this.isPluginEnabled(plugin.id) && plugin.metadata.routes) {\n // 获取该插件的当前配置,并注入到路由 meta 中\n const config = configManager.get(plugin.id) || {};\n \n plugin.metadata.routes.forEach(route => {\n activeRoutes.push({\n ...route,\n meta: {\n ...route.meta,\n pluginId: plugin.id,\n config: config,\n }\n });\n });\n }\n });\n\n // 3. 写入缓存\n this.memoizedRoutes = activeRoutes;\n \n return activeRoutes;\n }\n\n /**\n * 注册一个新插件到管理器中\n * @description 此阶段会执行元数据校验、存储 Schema 注册、配置合并及扩展点收集。\n * @param plugin - 插件对象\n * @param notify - 是否在注册完成后触发状态变更通知\n */\n register(plugin: Plugin, notify = true) {\n if (!this.validatePlugin(plugin)) {\n logger.error(`插件注册失败: ${plugin?.id || '未知'}`);\n return;\n }\n\n if (this.plugins.has(plugin.id)) {\n // 允许热更新:如果插件已存在且内容不同,则更新;否则跳过\n // 目前简单处理:仅输出日志并跳过,避免重复注册警告视为错误\n // logger.debug(`插件 ${plugin.id} 已注册,跳过。`);\n return;\n }\n\n // 注册存储 Schema (合并 storage 和 configuration 定义)\n const storageSchema: StorageItemSchema[] = [\n ...(plugin.metadata.storage || []),\n ...(plugin.metadata.configuration?.map(c => ({\n key: c.key,\n // 将 configuration 的 type 映射为 storage 支持的类型\n type: (c.type === 'select' ? 'string' : c.type) as any,\n label: c.label,\n description: c.description,\n default: c.default,\n scope: 'plugin' as const\n })) || [])\n ];\n \n if (storageSchema.length > 0) {\n this.storageManager.registerSchema(plugin.id, storageSchema);\n }\n\n // 默认状态逻辑:如果存储中没有状态,默认为启用\n if (!this.pluginStates[plugin.id]) {\n this.pluginStates[plugin.id] = { enabled: true, order: 0 };\n }\n\n // --- 加载并合并配置 ---\n const metadataDefaults: Record<string, any> = {};\n const userOverrides: Record<string, any> = {};\n const pluginStorage = this.storageManager.getPluginStorage(plugin.id);\n\n // 1. 提取元数据中的默认值\n if (plugin.metadata.configuration) {\n plugin.metadata.configuration.forEach((item) => {\n if (item.default !== undefined) {\n metadataDefaults[item.key] = item.default;\n }\n\n // 2. 提取持久化存储中的用户设置 (如果有)\n try {\n const saved = pluginStorage.getItem(item.key);\n if (saved !== null) {\n userOverrides[item.key] = JSON.parse(saved);\n }\n } catch (e) {\n // 忽略解析错误\n }\n });\n }\n\n // 3. 合并逻辑 (优先级从低到高):\n // 1. 元数据默认 (来自 plugin.metadata.configuration)\n // 2. 插件自带默认 (plugin.defaultConfig)\n // 3. 外部传入配置 (来自 chatbi.config.ts, 已存入 configManager)\n // 4. 用户持久化设置 (来自 localStorage)\n const mergedConfig = {\n ...metadataDefaults,\n ...plugin.defaultConfig,\n ...(configManager.get(plugin.id) || {}),\n ...userOverrides,\n };\n\n // 将合并后的配置同步到 ConfigManager,供 runtime 使用\n configManager.set(plugin.id, mergedConfig);\n\n // 根据类型处理\n switch (plugin.metadata.type) {\n case 'business':\n this.handleBusinessPlugin(plugin);\n break;\n case 'functional':\n this.handleFunctionalPlugin(plugin);\n break;\n case 'view':\n this.handleViewPlugin(plugin);\n break;\n case 'theme':\n this.handleThemePlugin(plugin);\n break;\n case 'system':\n this.handleSystemPlugin(plugin);\n break;\n case 'renderer':\n break;\n default:\n logger.warn(`插件 ${plugin.id} 类型未知: ${plugin.metadata.type}`);\n break;\n }\n\n // 收集路由\n if (plugin.metadata.routes && plugin.metadata.routes.length > 0) {\n logger.info(`已从插件 ${plugin.id} 收集路由:`, plugin.metadata.routes);\n }\n\n // 收集扩展点\n if (plugin.metadata.extensions && plugin.metadata.extensions.length > 0) {\n plugin.metadata.extensions.forEach((ext) => {\n const list = this.extensions.get(ext.slot) || [];\n list.push({ ...ext, _pluginId: plugin.id });\n this.extensions.set(ext.slot, list);\n });\n logger.info(`已从插件 ${plugin.id} 收集扩展点`);\n }\n\n this.plugins.set(plugin.id, plugin);\n logger.info(`插件 ${plugin.id} 已注册为 ${plugin.metadata.type}。`);\n\n // 触发状态变更通知\n if (notify) {\n this.notify();\n }\n }\n\n /**\n * 初始化所有插件\n * @param sharedContext 共享上下文\n */\n async initPlugins(sharedContext: Record<string, any> = {}) {\n this.sharedContext = {\n ...sharedContext,\n events: this.eventBus,\n };\n\n // 1. 准备运行时\n this.plugins.forEach((plugin) => {\n if (!this.isPluginEnabled(plugin.id)) return;\n \n if (!this.runtimes.has(plugin.id)) {\n const runtime = new PluginRuntime(plugin, this.sharedContext!, this.storageManager);\n this.runtimes.set(plugin.id, runtime);\n }\n });\n\n // 2. 拓扑排序解析依赖 (简单实现:先加载 system 插件,再加载其他)\n const sortedPluginIds = this.getSortedPluginIds();\n\n // 2.5 依赖完整性校验\n const missingDeps = new Map<string, string[]>();\n const idsToLoad = new Set(sortedPluginIds);\n\n for (const id of sortedPluginIds) {\n const plugin = this.plugins.get(id);\n if (plugin?.metadata.dependencies) {\n const missing = plugin.metadata.dependencies.filter(depId => !this.runtimes.has(depId));\n if (missing.length > 0) {\n missingDeps.set(id, missing);\n // 如果依赖缺失,该插件也不应加载\n idsToLoad.delete(id);\n // 立即移除运行时,以便后续依赖此插件的插件也能检测到缺失\n this.runtimes.delete(id);\n }\n }\n }\n\n if (missingDeps.size > 0) {\n missingDeps.forEach((deps, id) => {\n logger.error(`插件 ${id} 无法加载,缺失依赖: ${deps.join(', ')}`);\n });\n }\n\n // 3. 顺序执行 onLoad (异步)\n for (const id of sortedPluginIds) {\n if (!idsToLoad.has(id)) continue;\n\n const runtime = this.runtimes.get(id);\n if (runtime) {\n try {\n logger.info(`[PluginManager] invoking onLoad for ${id}`);\n await runtime.load();\n logger.info(`[PluginManager] onLoad completed for ${id}`);\n } catch (e) {\n logger.error(`插件 ${id} 加载失败:`, e);\n }\n }\n }\n\n // 4. 顺序执行 onMount\n for (const id of sortedPluginIds) {\n const runtime = this.runtimes.get(id);\n if (runtime) {\n try {\n await runtime.mount();\n } catch (e) {\n logger.error(`插件 ${id} 挂载失败:`, e);\n }\n }\n }\n }\n\n /**\n * 获取排序后的插件 ID 列表 (处理依赖)\n */\n private getSortedPluginIds(): string[] {\n const ids = Array.from(this.runtimes.keys());\n const visited = new Set<string>();\n const sorted: string[] = [];\n const visiting = new Set<string>();\n\n const visit = (id: string) => {\n if (visited.has(id)) return;\n if (visiting.has(id)) {\n logger.error(`循环依赖检测到: ${id}`);\n return;\n }\n\n visiting.add(id);\n\n const plugin = this.plugins.get(id);\n if (plugin?.metadata.dependencies) {\n plugin.metadata.dependencies.forEach(depId => {\n if (this.runtimes.has(depId)) {\n visit(depId);\n }\n });\n }\n\n visiting.delete(id);\n visited.add(id);\n sorted.push(id);\n };\n\n // 简单的优先级排序作为初始顺序:system > functional > business > others\n const priorityMap: Record<string, number> = {\n 'system': 100,\n 'functional': 50,\n 'business': 10,\n };\n \n const sortedIdsByType = [...ids].sort((a, b) => {\n const pA = priorityMap[this.plugins.get(a)?.metadata.type || ''] || 0;\n const pB = priorityMap[this.plugins.get(b)?.metadata.type || ''] || 0;\n return pB - pA;\n });\n\n sortedIdsByType.forEach(id => visit(id));\n\n return sorted;\n }\n\n /**\n * 加载插件列表\n * @param configs 插件配置\n * @param registry 插件注册表 (动态导入函数)\n */\n async loadPlugins(configs: Record<string, any>, registry: Record<string, () => Promise<any>>) {\n logger.info('开始加载插件...');\n\n // 1. 并行加载所有本地插件模块\n const localLoadPromises = Object.entries(registry).map(async ([registryId, importFn]) => {\n try {\n const module = await importFn();\n const config = configs[registryId];\n const plugin = this.instantiatePlugin(registryId, module, config);\n \n // 如果外部传入了配置,暂时存入 configManager,以便 register 时合并\n if (plugin && config) {\n configManager.set(plugin.id, config);\n }\n \n return plugin;\n } catch (e) {\n logger.error(`加载本地插件模块 ${registryId} 失败:`, e);\n return null;\n }\n });\n\n // 2. 加载在线插件 (根据配置中的 url)\n const onlineLoadPromises = Object.entries(configs)\n .filter(([id, config]) => config.url && !registry[id]) // 只有配置了 URL 且不在本地注册表中的才是在线插件\n .map(async ([pluginId, config]) => {\n try {\n const plugin = await this.loadRemotePlugin(pluginId, config.url, config);\n \n // 同样存入 configManager\n if (plugin && config) {\n configManager.set(plugin.id, config);\n }\n \n return plugin;\n } catch (e) {\n logger.error(`加载在线插件 ${pluginId} 失败:`, e);\n return null;\n }\n });\n\n const loadedPlugins = await Promise.all([...localLoadPromises, ...onlineLoadPromises]);\n\n // 3. 注册插件 (批量注册时不触发通知)\n loadedPlugins.forEach((plugin) => {\n if (plugin) {\n this.register(plugin, false);\n }\n });\n\n // 4. 全部注册完成后触发一次通知\n this.notify();\n\n logger.info(`插件加载完成,共加载 ${this.plugins.size} 个插件`);\n }\n\n /**\n * 加载远程插件\n * @param pluginId 插件 ID\n * @param url 远程 URL\n * @param config 插件配置\n */\n async loadRemotePlugin(pluginId: string, url: string, config: any): Promise<Plugin | null> {\n logger.info(`正在从 ${url} 加载远程插件 ${pluginId}...`);\n\n // 如果显式指定了 format 为 iife,则直接使用 IIFE 加载,跳过 ESM\n if (config?.format === 'iife') {\n return this.loadIIFEPlugin(pluginId, url, config);\n }\n\n try {\n // 1. 尝试使用 ESM 动态导入\n // 使用 new Function 绕过 Vite 对 public 目录下文件的静态分析限制\n // Vite 禁止直接 import public 目录下的文件,即使该代码路径在运行时不会执行\n const dynamicImport = new Function('specifier', 'return import(specifier)');\n const module = await dynamicImport(url);\n return this.instantiatePlugin(pluginId, module, config);\n } catch (e) {\n // 只有在没有显式指定 format 的情况下才尝试降级\n // 如果指定了 esm 但失败了,应该直接报错?目前为了健壮性,依然允许降级,但记录日志。\n logger.warn(`ESM 加载失败,尝试 IIFE 加载: ${pluginId}`);\n // 2. 如果 ESM 失败,尝试 IIFE 加载 (微前端模式)\n return this.loadIIFEPlugin(pluginId, url, config);\n }\n }\n\n /**\n * IIFE 模式加载插件\n */\n private loadIIFEPlugin(pluginId: string, url: string, config: any): Promise<Plugin | null> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = () => {\n // 约定:IIFE 模式下插件挂载在 window[pluginId] 或 window[globalName]\n // 我们的 build.ts 中 globalName 是 pkg.name 转换后的\n const globalName = pluginId.replace(/[^a-zA-Z0-9]/g, '_');\n const pluginModule = (window as any)[globalName];\n if (pluginModule) {\n resolve(this.instantiatePlugin(pluginId, pluginModule, config));\n } else {\n reject(new Error(`远程插件 ${pluginId} 加载后未找到全局变量 ${globalName}`));\n }\n };\n script.onerror = () => reject(new Error(`远程插件 ${pluginId} 加载失败: ${url}`));\n document.head.appendChild(script);\n });\n }\n\n /**\n * 实例化插件\n */\n private instantiatePlugin(pluginId: string, module: any, config: any): Plugin | null {\n // 约定:插件模块必须导出一个实现了 Plugin 接口的类或对象\n // 优先查找 default export,其次查找命名的 Plugin 类\n let PluginClass = module.default;\n\n if (!PluginClass) {\n // 尝试查找以 Plugin 结尾的导出\n const key = Object.keys(module).find((k) => k.endsWith('Plugin'));\n if (key) PluginClass = module[key];\n }\n\n if (!PluginClass && typeof module === 'object') {\n // 如果 module 本身看起来像个插件实例 (有 id 和 metadata)\n if (module.id && module.metadata) {\n PluginClass = module;\n }\n }\n\n if (PluginClass) {\n // 如果是类,实例化\n const isClass = typeof PluginClass === 'function' && PluginClass.prototype;\n if (isClass) {\n logger.warn(`插件 ${pluginId} 使用了类定义模式。建议统一使用 definePlugin() 工厂模式以消除歧义并简化代码。`);\n }\n \n const pluginInstance = typeof PluginClass === 'function' ? new PluginClass() : PluginClass;\n \n // 强制使用来自注册表的 ID (registryId),确保配置和存储路径的一致性\n // 但是 registryId 可能是文件路径,而不是真正的 ID\n // 这里的逻辑需要修正:如果 registryId 看起来像个路径(包含 /src/),则不应强制覆盖 metadata.id\n // 除非我们能从路径中解析出正确的包名\n \n const isFilePath = pluginId.includes('/') && (pluginId.includes('.ts') || pluginId.includes('.tsx'));\n if (!isFilePath && pluginId && pluginInstance.metadata) {\n // 只有当插件 ID 与注册表 ID 不一致时才更新,且只更新 metadata.id\n // 因为 pluginInstance.id 已经定义为只读 getter\n if (pluginInstance.metadata.id !== pluginId) {\n pluginInstance.metadata.id = pluginId;\n }\n }\n\n // 确保 id 存在 (降级处理)\n // 如果 pluginInstance 没有 id getter,且 metadata 有 id,则尝试赋值\n if (!pluginInstance.id && pluginInstance.metadata?.id) {\n try {\n pluginInstance.id = pluginInstance.metadata.id;\n } catch (e) {\n // 忽略 getter 导致的赋值失败\n }\n }\n\n // 注入配置\n if (config) {\n pluginInstance.defaultConfig = { ...pluginInstance.defaultConfig, ...config };\n }\n return pluginInstance;\n }\n\n logger.warn(`模块 ${pluginId} 未导出有效的插件入口`);\n return null;\n }\n\n // --- Private Handlers ---\n\n private validatePlugin(plugin: Plugin): boolean {\n if (!plugin.id) return false;\n if (!plugin.metadata) return false;\n return true;\n }\n\n private handleBusinessPlugin(plugin: Plugin) {\n // 业务插件特定逻辑\n }\n\n private handleFunctionalPlugin(plugin: Plugin) {\n // 功能插件特定逻辑\n }\n\n private handleViewPlugin(plugin: Plugin) {\n // 视图插件特定逻辑\n }\n\n private handleThemePlugin(plugin: Plugin) {\n // 主题插件特定逻辑\n }\n\n private handleSystemPlugin(plugin: Plugin) {\n // 系统插件特定逻辑\n }\n}\n\n/**\n * 全局插件管理器实例\n */\nexport const pluginManager = new PluginManager(new LocalStorageAdapter());\n","import { StoragePort } from '../ports/storage-port';\n\n/**\n * 浏览器本地存储 (LocalStorage) 适配器\n * @description 实现 `StoragePort` 接口,封装了对原生 `localStorage` 的访问。\n * 支持可选的命名空间前缀隔离,确保在同一个域下不同模块的数据互不干扰。\n */\nexport class LocalStorageAdapter implements StoragePort {\n /** 命名空间前缀,所有存入的键名都会自动添加此前缀 */\n private prefix: string;\n\n /**\n * 初始化适配器\n * @param prefix - 可选的命名空间前缀(如 'chatbi'),默认为空字符串\n */\n constructor(prefix: string = '') {\n this.prefix = prefix;\n }\n\n /**\n * 内部方法:计算实际存储的键名\n * @param key - 业务层传入的原始键名\n * @returns 拼接前缀后的物理键名\n */\n private getKey(key: string): string {\n return this.prefix ? `${this.prefix}:${key}` : key;\n }\n\n /**\n * 内部方法:从物理键名还原业务键名\n * @param namespacedKey - 物理存储中的完整键名\n * @returns 还原后的原始键名,若前缀不匹配则返回 null\n */\n private getOriginalKey(namespacedKey: string): string | null {\n if (!this.prefix) return namespacedKey;\n if (namespacedKey.startsWith(this.prefix + ':')) {\n return namespacedKey.slice(this.prefix.length + 1);\n }\n return null;\n }\n\n /**\n * 读取存储项\n * @param key - 原始键名\n * @returns 存储的字符串内容,不存在则返回 null\n */\n getItem(key: string): string | null {\n return localStorage.getItem(this.getKey(key));\n }\n\n /**\n * 写入存储项\n * @param key - 原始键名\n * @param value - 待存储的字符串值\n */\n setItem(key: string, value: string): void {\n localStorage.setItem(this.getKey(key), value);\n }\n\n /**\n * 移除特定的存储项\n * @param key - 原始键名\n */\n removeItem(key: string): void {\n localStorage.removeItem(this.getKey(key));\n }\n\n /**\n * 清空存储空间\n * @description \n * - 若定义了前缀:仅删除以该前缀开头的键名,不影响其他数据。\n * - 若未定义前缀:调用原生 `localStorage.clear()` 清空所有数据。\n */\n clear(): void {\n if (!this.prefix) {\n localStorage.clear();\n return;\n }\n\n // 仅清除带有前缀的项\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => localStorage.removeItem(key));\n }\n\n /**\n * 返回当前命名空间下的存储项总数\n */\n get length(): number {\n if (!this.prefix) return localStorage.length;\n let count = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * 根据索引获取对应的原始键名\n * @param index - 索引位置\n * @returns 对应的业务键名,不存在则返回 null\n */\n key(index: number): string | null {\n if (!this.prefix) return localStorage.key(index);\n \n let count = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n if (count === index) {\n return this.getOriginalKey(key);\n }\n count++;\n }\n }\n return null;\n }\n}\n","import { createLogger } from './utils/logger';\n\nconst logger = createLogger('EventBus');\n\nexport type EventCallback = (...args: any[]) => any;\n\n/**\n * 事件总线接口\n */\nexport interface EventBus {\n /**\n * 订阅事件\n * @param event 事件名称\n * @param callback 回调函数\n * @returns 取消订阅函数\n */\n on(event: string, callback: EventCallback): () => void;\n \n /**\n * 取消订阅\n * @param event 事件名称\n * @param callback 回调函数\n */\n off(event: string, callback: EventCallback): void;\n \n /**\n * 触发事件\n * @param event 事件名称\n * @param args 事件参数\n */\n emit(event: string, ...args: any[]): void;\n \n /**\n * 订阅一次性事件\n * @param event 事件名称\n * @param callback 回调函数\n */\n once(event: string, callback: EventCallback): void;\n}\n\nexport class DefaultEventBus implements EventBus {\n private listeners: Map<string, EventCallback[]> = new Map();\n\n on(event: string, callback: EventCallback): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)?.push(callback);\n return () => this.off(event, callback);\n }\n\n off(event: string, callback: EventCallback) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n this.listeners.set(event, callbacks.filter(cb => cb !== callback));\n }\n }\n\n emit(event: string, ...args: any[]) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n callbacks.forEach(cb => {\n try {\n cb(...args);\n } catch (error) {\n logger.error(`事件监听器处理错误 (${event}):`, error);\n }\n });\n }\n }\n\n once(event: string, callback: EventCallback) {\n const wrapper = (...args: any[]) => {\n callback(...args);\n this.off(event, wrapper);\n };\n this.on(event, wrapper);\n }\n}\n","import { createLogger } from '../utils/logger';\n\nconst logger = createLogger('ProxySandbox');\n\n/**\n * ProxySandbox 类\n * @description 基于 Proxy 的 JS 沙箱实现,模拟独立的 Window 环境\n */\nexport class ProxySandbox {\n /** 沙箱名称 */\n public name: string;\n /** 代理后的 Window 对象 */\n public proxy: WindowProxy;\n /** 沙箱是否激活 */\n public running = false;\n\n /** 记录新增/修改的全局变量 */\n private updatedValueSet = new Set<string | symbol>();\n \n /** 绑定函数的缓存池,避免重复 bind 带来的性能开销 */\n private boundFunctionCache = new Map<Function, Function>();\n\n /** 副作用记录池 */\n private effectPool = {\n timeouts: new Set<number>(),\n intervals: new Set<number>(),\n rafs: new Set<number>(), // requestAnimationFrame\n listeners: new Map<string, Array<{ listener: EventListenerOrEventListenerObject; options?: boolean | AddEventListenerOptions }>>(),\n };\n\n /** 真实的 Window 对象 */\n private globalContext: Window;\n\n /** 白名单全局变量(允许透传访问真实 Window) */\n private static globalWhitelist = [\n 'System',\n 'console',\n // 'setTimeout', // 移除白名单,改为劫持\n // 'setInterval',\n // 'clearTimeout',\n // 'clearInterval',\n 'requestAnimationFrame',\n 'cancelAnimationFrame',\n // 'addEventListener', // 移除白名单,改为劫持\n // 'removeEventListener',\n 'location',\n 'history',\n 'navigator',\n 'document', \n ];\n\n constructor(name: string, globalContext = window) {\n this.name = name;\n this.globalContext = globalContext;\n\n const { fakeWindow, propertiesWithGetter } = this.createFakeWindow(globalContext);\n \n // 劫持副作用 API\n this.patchGlobalEffects(fakeWindow);\n\n const proxy = new Proxy(fakeWindow, {\n set: (target: any, p: string | symbol, value: any): boolean => {\n if (this.running) {\n // 记录修改的属性\n this.updatedValueSet.add(p);\n target[p] = value;\n return true;\n }\n // 沙箱未运行时,禁止修改\n logger.warn(`${name} 未运行,无法设置属性 '${String(p)}'`);\n return false;\n },\n\n get: (target: any, p: string | symbol): any => {\n // 1. 优先从 fakeWindow 获取\n if (p === Symbol.unscopables) return undefined;\n if (p === 'window' || p === 'self' || p === 'globalThis') {\n return this.proxy;\n }\n \n if (p === 'top' || p === 'parent') {\n return this.globalContext[p];\n }\n\n const value = target[p];\n if (value !== undefined || this.updatedValueSet.has(p)) {\n return value;\n }\n\n // 2. 尝试从真实 Window 获取\n const rawValue = (this.globalContext as any)[p];\n \n // 处理函数绑定的 this 指向\n if (typeof rawValue === 'function' && !this.isConstructor(rawValue)) {\n if (this.isNativeFunction(rawValue)) {\n return rawValue.bind(this.globalContext);\n }\n }\n \n return rawValue;\n },\n\n has: (target: any, p: string | symbol): boolean => {\n return p in target || p in this.globalContext;\n },\n\n defineProperty: (target: any, p: string | symbol, attributes: PropertyDescriptor): boolean => {\n if (this.running) {\n this.updatedValueSet.add(p);\n return Reflect.defineProperty(target, p, attributes);\n }\n return false;\n },\n });\n\n this.proxy = proxy as WindowProxy;\n }\n\n /**\n * 激活沙箱\n */\n active() {\n if (!this.running) {\n this.running = true;\n }\n }\n\n /**\n * 销毁沙箱\n */\n inactive() {\n this.running = false;\n \n // 清理副作用\n this.effectPool.timeouts.forEach((id) => this.globalContext.clearTimeout(id));\n this.effectPool.timeouts.clear();\n\n this.effectPool.intervals.forEach((id) => this.globalContext.clearInterval(id));\n this.effectPool.intervals.clear();\n\n this.effectPool.rafs.forEach((id) => this.globalContext.cancelAnimationFrame(id));\n this.effectPool.rafs.clear();\n\n this.effectPool.listeners.forEach((listeners, type) => {\n listeners.forEach(({ listener, options }) => {\n this.globalContext.removeEventListener(type, listener, options);\n });\n });\n this.effectPool.listeners.clear();\n \n logger.debug(`${this.name} 已停用,副作用已清除。`);\n }\n\n /**\n * 在沙箱中执行代码\n * @param code JS 代码字符串\n * @returns 执行结果\n */\n eval(code: string) {\n // 添加 sourceURL 以便于在 DevTools 中调试\n const sourceURL = `//# sourceURL=${this.name}.js`;\n // 构造一个函数,接收 window, self, globalThis 作为参数\n // 注意:这里不再依赖全局的 window.proxy\n const evalCode = `\n ;(function(window, self, globalThis){\n with(window) {\n ${code}\n ${sourceURL}\n }\n })\n `;\n // 获取编译后的函数\n const func = (0, eval)(evalCode);\n // 绑定上下文并传入 proxy 对象\n return func.call(this.proxy, this.proxy, this.proxy, this.proxy);\n }\n\n /**\n * 创建伪造的 Window 对象\n */\n private createFakeWindow(globalContext: Window) {\n const propertiesWithGetter = new Map<PropertyKey, boolean>();\n const fakeWindow = {} as any;\n\n // 复制不可配置的属性描述符,防止 Proxy 报错\n Object.getOwnPropertyNames(globalContext).forEach((p) => {\n const descriptor = Object.getOwnPropertyDescriptor(globalContext, p);\n if (descriptor && !descriptor.configurable) {\n // 如果是不可配置属性,必须在 target 上也存在\n // 但由于我们无法完全模拟,这里暂不处理,依赖 get 陷阱透传\n // 实际上 ProxySandbox 的 target 通常是一个空对象\n }\n });\n\n return { fakeWindow, propertiesWithGetter };\n }\n\n private isConstructor(fn: (...args: any[]) => any) {\n const prototype = fn.prototype;\n return !!(prototype && prototype.constructor === fn && Object.getOwnPropertyNames(prototype).length > 0);\n }\n\n private isNativeFunction(fn: (...args: any[]) => any) {\n return fn.toString().indexOf('[native code]') > -1;\n }\n\n /**\n * 劫持全局副作用 API\n */\n private patchGlobalEffects(fakeWindow: any) {\n // 1. 劫持 setTimeout\n fakeWindow.setTimeout = (handler: TimerHandler, timeout?: number, ...args: any[]): number => {\n const id = this.globalContext.setTimeout(handler, timeout, ...args);\n this.effectPool.timeouts.add(id);\n return id;\n };\n fakeWindow.clearTimeout = (id: number | undefined) => {\n if (id) {\n this.effectPool.timeouts.delete(id);\n this.globalContext.clearTimeout(id);\n }\n };\n\n // 2. 劫持 setInterval\n fakeWindow.setInterval = (handler: TimerHandler, timeout?: number, ...args: any[]): number => {\n const id = this.globalContext.setInterval(handler, timeout, ...args);\n this.effectPool.intervals.add(id);\n return id;\n };\n fakeWindow.clearInterval = (id: number | undefined) => {\n if (id) {\n this.effectPool.intervals.delete(id);\n this.globalContext.clearInterval(id);\n }\n };\n\n // 3. 劫持 requestAnimationFrame\n fakeWindow.requestAnimationFrame = (callback: FrameRequestCallback): number => {\n const id = this.globalContext.requestAnimationFrame(callback);\n this.effectPool.rafs.add(id);\n return id;\n };\n fakeWindow.cancelAnimationFrame = (id: number) => {\n if (id) {\n this.effectPool.rafs.delete(id);\n this.globalContext.cancelAnimationFrame(id);\n }\n };\n\n // 4. 劫持 addEventListener\n fakeWindow.addEventListener = (\n type: string, \n listener: EventListenerOrEventListenerObject, \n options?: boolean | AddEventListenerOptions\n ) => {\n const listeners = this.effectPool.listeners.get(type) || [];\n listeners.push({ listener, options });\n this.effectPool.listeners.set(type, listeners);\n return this.globalContext.addEventListener(type, listener, options);\n };\n\n fakeWindow.removeEventListener = (\n type: string, \n listener: EventListenerOrEventListenerObject, \n options?: boolean | AddEventListenerOptions\n ) => {\n const listeners = this.effectPool.listeners.get(type);\n if (listeners) {\n const index = listeners.findIndex(item => item.listener === listener && item.options === options);\n if (index !== -1) listeners.splice(index, 1);\n }\n return this.globalContext.removeEventListener(type, listener, options);\n };\n }\n}\n","import { StoragePort } from '../ports/storage-port';\nimport { createLogger } from '../utils/logger';\nimport { StorageManager } from './storage-manager';\n\n/**\n * 插件隔离沙箱\n * @description 核心领域服务,为每个插件实例创建独立的运行上下文。\n * 它是插件与系统核心之间的“中间层”,确保插件只能访问其权限范围内的资源。\n * 主要职责:\n * 1. 存储隔离:确保插件只能读写属于自己的 LocalStorage 命名空间。\n * 2. 日志隔离:为插件提供带有自身 ID 前缀的日志输出,方便调试。\n */\nexport class PluginSandbox {\n /** 关联的插件唯一标识 */\n private pluginId: string;\n /** 系统全局存储管理器 */\n private storageManager: StorageManager;\n\n /**\n * 构造插件沙箱\n * @param pluginId - 插件 ID\n * @param storageManager - 系统存储管理器实例\n */\n constructor(pluginId: string, storageManager: StorageManager) {\n this.pluginId = pluginId;\n this.storageManager = storageManager;\n }\n\n /**\n * 获取隔离的存储接口\n * @description 返回一个受限的 StoragePort,所有操作都会自动带上插件 ID 前缀。\n */\n get storage() {\n return this.storageManager.getContextStorage(this.pluginId);\n }\n\n /**\n * 获取隔离的日志接口\n * @description 返回一个带插件 ID 前缀的 Logger 实例。\n */\n get logger() {\n return createLogger(`Plugin:${this.pluginId}`);\n }\n}\n","/**\n * @file plugin-runtime.ts\n * @description 插件运行时,封装单个插件的生命周期(load/mount/unmount)、沙箱环境和隔离上下文\n * @author ChatBI Team\n */\n\nimport { serviceRegistry } from '../application/service-registry';\nimport { configManager } from '../config-manager';\nimport { Plugin, PluginContext } from '../ports/plugin-port';\nimport { ProxySandbox } from '../sandbox/proxy-sandbox';\nimport { createLogger } from '../utils/logger';\nimport { PluginSandbox } from './plugin-sandbox';\nimport { StorageManager } from './storage-manager';\n\nconst logger = createLogger('PluginRuntime');\n\n/**\n * 插件运行时类\n * @description 为单个插件提供独立的运行环境,负责管理其生命周期、初始化沙箱环境并组装上下文对象。\n */\nexport class PluginRuntime {\n /** 插件定义对象 */\n public plugin: Plugin;\n /** 传递给插件的上下文对象 */\n public context: PluginContext;\n \n /** 存储沙箱隔离设施 */\n private storageSandbox: PluginSandbox;\n /** Window/全局对象沙箱隔离设施 */\n private windowSandbox: ProxySandbox;\n /** 是否已完成加载阶段 */\n private isLoaded = false;\n /** 是否已完成挂载阶段 */\n private isMounted = false;\n /** 运行时捕获的错误信息 */\n private error: Error | null = null;\n\n /**\n * 构造函数\n * @param plugin - 插件定义对象\n * @param sharedContext - 来自内核的共享上下文资源 (如 API 引擎、事件总线)\n * @param storageManager - 全局存储管理器\n */\n constructor(\n plugin: Plugin, \n sharedContext: Record<string, any>, \n storageManager: StorageManager\n ) {\n this.plugin = plugin;\n \n // 初始化沙箱设施\n this.storageSandbox = new PluginSandbox(plugin.id, storageManager);\n this.windowSandbox = new ProxySandbox(plugin.id);\n\n // 组装插件上下文\n this.context = {\n pluginId: plugin.id,\n api: sharedContext.api,\n events: sharedContext.events,\n storage: this.storageSandbox.storage,\n logger: this.storageSandbox.logger,\n window: this.windowSandbox.proxy,\n getService: <T = any>(name: string) => serviceRegistry.get<T>(name),\n registerService: (name: string, service: any) => serviceRegistry.register(`${plugin.id}.${name}`, service),\n };\n }\n\n /**\n * 执行插件的加载逻辑 (onLoad)\n * @description 此阶段会自动注册插件声明的 API 配置,并调用插件的 onLoad 钩子。\n * 用于执行非 UI 的初始化逻辑,如注册服务、拦截器等。\n */\n async load() {\n if (this.isLoaded) return;\n \n logger.debug(`正在加载插件: ${this.plugin.id}`);\n \n try {\n // 1. 自动注册 API 配置\n if (this.plugin.metadata.api && this.context.api && typeof this.context.api.register === 'function') {\n this.context.api.register(this.plugin.metadata.api);\n logger.debug(`已为插件 ${this.plugin.id} 自动注册 API 配置`);\n }\n\n // 1.5 自动注册配置服务 (Config Service)\n if (this.plugin.metadata.configuration && this.plugin.metadata.configuration.length > 0) {\n // 预先建立配置索引,提升查找性能 (O(1))\n const configMap = new Map(this.plugin.metadata.configuration.map(c => [c.key, c]));\n // 方法缓存,确保相同的方法名返回相同的函数实例 (Identity Consistency)\n const getterCache = new Map<string, () => any>();\n\n // 使用 Proxy 动态拦截属性访问,避免预先生成大量方法对象\n const configService = new Proxy({}, {\n get: (target, prop) => {\n // 1. 边界检查:仅处理字符串类型的属性名\n if (typeof prop !== 'string') {\n return Reflect.get(target, prop);\n }\n\n // 2. 拦截 getXxx 方法调用\n if (prop.startsWith('get')) {\n // 优先从缓存获取\n if (getterCache.has(prop)) {\n return getterCache.get(prop);\n }\n\n // 解析配置键名: getApiKey -> apiKey\n // 注意:这里假设配置键名是 camelCase。\n // 如果配置键名本身是 \"APIKey\",转换后为 \"aPIKey\",可能匹配不到。\n // 为了稳健性,可以尝试几种变体,或者约定 key 必须是 camelCase。\n // 这里保持简单的首字母小写转换。\n const configKey = prop.slice(3).charAt(0).toLowerCase() + prop.slice(3).slice(1);\n \n // 检查该配置项是否存在且允许访问\n const configItem = configMap.get(configKey);\n \n if (configItem) {\n if (configItem.private || (configItem as any).internal) {\n logger.warn(`尝试访问私有配置: ${configKey}`);\n // 对于私有配置,返回 undefined 或抛出错误?\n // 这里选择返回一个总是返回 undefined 的函数,保持接口一致性\n const noop = () => undefined;\n getterCache.set(prop, noop);\n return noop;\n }\n \n // 创建并缓存 Getter 函数\n const getter = () => this.context.storage.get(configKey);\n getterCache.set(prop, getter);\n return getter;\n }\n }\n return Reflect.get(target, prop);\n }\n });\n\n this.context.registerService('config', configService);\n logger.debug(`已为插件 ${this.plugin.id} 自动注册配置服务 (Proxy Mode)`);\n }\n\n // 2. 调用 onLoad 钩子\n if (this.plugin.onLoad) {\n await this.plugin.onLoad(this.context);\n }\n \n this.isLoaded = true;\n this.error = null;\n logger.info(`插件 ${this.plugin.id} 已加载。`);\n } catch (error) {\n this.error = error instanceof Error ? error : new Error(String(error));\n logger.error(`插件 ${this.plugin.id} 加载失败:`, error);\n // 不再抛出错误,避免导致主应用崩溃\n }\n }\n\n /**\n * 执行插件的挂载逻辑 (onMount)\n * @description 此阶段会激活 Window 沙箱并调用插件的 onMount 钩子。\n * 此时插件的 UI 组件(如有)即将或已经进入 DOM。\n */\n async mount() {\n if (!this.isLoaded) await this.load();\n if (this.isMounted) return;\n \n logger.debug(`正在挂载插件: ${this.plugin.id}`);\n \n try {\n // 1. 激活沙箱\n this.windowSandbox.active();\n \n // 2. 调用 onMount 钩子\n if (this.plugin.onMount) {\n this.plugin.onMount(this.context);\n }\n \n this.isMounted = true;\n this.error = null;\n logger.info(`插件 ${this.plugin.id} 已挂载。`);\n } catch (error) {\n this.error = error instanceof Error ? error : new Error(String(error));\n logger.error(`插件 ${this.plugin.id} 挂载失败:`, error);\n // 不再抛出错误,避免导致主应用崩溃\n }\n }\n\n /**\n * 执行插件的卸载逻辑 (onUnmount)\n * @description 调用插件的 onUnmount 钩子并停用沙箱。\n */\n async unmount() {\n if (!this.isMounted) return;\n\n logger.debug(`正在卸载插件: ${this.plugin.id}`);\n\n try {\n // 1. 调用 onUnmount 钩子\n if (this.plugin.onUnmount) {\n this.plugin.onUnmount(this.context);\n }\n } catch (error) {\n logger.error(`插件 ${this.plugin.id} 卸载时出错:`, error);\n } finally {\n // 2. 停用沙箱\n this.windowSandbox.inactive();\n this.isMounted = false;\n this.error = null;\n logger.info(`插件 ${this.plugin.id} 已卸载。`);\n }\n }\n\n /**\n * 彻底销毁插件实例\n * @description 卸载插件并重置加载状态。\n */\n async destroy() {\n await this.unmount();\n this.isLoaded = false;\n this.error = null;\n }\n\n /**\n * 设置运行时错误 (内部使用)\n * @internal\n */\n _setError(error: Error | null) {\n this.error = error;\n }\n\n /**\n * 获取插件运行时错误\n */\n getError() {\n return this.error;\n }\n\n /**\n * 获取插件当前运行状态\n * @returns 'error' | 'mounted' | 'loaded' | 'initial'\n */\n get status() {\n if (this.error) return 'error';\n if (this.isMounted) return 'mounted';\n if (this.isLoaded) return 'loaded';\n return 'initial';\n }\n}\n","import { StoragePort } from '../ports/storage-port';\n\n/**\n * 作用域存储适配器 (ScopedStorageAdapter)\n * @description 采用装饰器模式实现。它包装一个现有的 `StoragePort` 实例,\n * 并为所有存储操作透明地注入一个前缀(命名空间),从而实现逻辑上的存储隔离。\n * 常用于为插件分配独立的存储空间,而无需修改插件代码。\n */\nexport class ScopedStorageAdapter implements StoragePort {\n /**\n * 初始化作用域适配器\n * @param underlyingStorage - 被装饰的底层存储适配器实例\n * @param prefix - 用于隔离的作用域前缀字符串\n */\n constructor(\n private underlyingStorage: StoragePort,\n private prefix: string\n ) {}\n\n /**\n * 内部方法:计算实际存储的键名\n * @param key - 业务层传入的原始键名\n * @returns 拼接前缀后的物理键名\n */\n private getKey(key: string): string {\n return this.prefix ? `${this.prefix}:${key}` : key;\n }\n\n /**\n * 内部方法:从物理键名还原业务键名\n * @param namespacedKey - 物理存储中的完整键名\n * @returns 还原后的原始键名,若前缀不匹配则返回 null\n */\n private getOriginalKey(namespacedKey: string): string | null {\n if (!this.prefix) return namespacedKey;\n if (namespacedKey.startsWith(this.prefix + ':')) {\n return namespacedKey.slice(this.prefix.length + 1);\n }\n return null;\n }\n\n /**\n * 读取当前作用域下的存储项\n * @param key - 原始键名\n * @returns 字符串内容,不存在则返回 null\n */\n getItem(key: string): string | null {\n return this.underlyingStorage.getItem(this.getKey(key));\n }\n\n /**\n * 写入当前作用域下的存储项\n * @param key - 原始键名\n * @param value - 字符串内容\n */\n setItem(key: string, value: string): void {\n this.underlyingStorage.setItem(this.getKey(key), value);\n }\n\n /**\n * 移除当前作用域下的特定存储项\n * @param key - 原始键名\n */\n removeItem(key: string): void {\n this.underlyingStorage.removeItem(this.getKey(key));\n }\n\n /**\n * 清空当前作用域下的所有存储项\n * @description 仅删除匹配当前前缀的键值对,不会影响底层存储中的其他数据。\n */\n clear(): void {\n if (!this.prefix) {\n this.underlyingStorage.clear();\n return;\n }\n\n const keysToRemove: string[] = [];\n for (let i = 0; i < this.underlyingStorage.length; i++) {\n const key = this.underlyingStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n keysToRemove.push(key);\n }\n }\n \n keysToRemove.forEach(k => this.underlyingStorage.removeItem(k));\n }\n\n /**\n * 返回当前作用域下的存储项总数\n */\n get length(): number {\n let count = 0;\n for (let i = 0; i < this.underlyingStorage.length; i++) {\n const key = this.underlyingStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * 根据索引获取当前作用域下的原始键名\n * @param index - 索引位置\n * @returns 对应的业务键名,不存在则返回 null\n */\n key(index: number): string | null {\n let count = 0;\n for (let i = 0; i < this.underlyingStorage.length; i++) {\n const key = this.underlyingStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n if (count === index) {\n return this.getOriginalKey(key);\n }\n count++;\n }\n }\n return null;\n }\n}\n","import { ScopedStorageAdapter } from '../adapters/scoped-storage-adapter';\nimport { configManager } from '../config-manager';\nimport { StorageItemSchema } from '../ports/plugin-port';\nimport { StoragePort } from '../ports/storage-port';\n\n/**\n * 核心领域服务:存储管理器\n * @description 统一管理应用内所有的持久化存储资源。\n * 核心功能:\n * 1. 作用域隔离:通过前缀划分 `plugin`、`shared` 和 `system` 三个层级的存储空间。\n * 2. Schema 校验:支持注册存储描述,规范数据存取,避免键名冲突。\n * 3. 默认值与配置回退:支持从 Schema 默认值或 ConfigManager 中回退取值。\n */\nexport class StorageManager {\n /** 底层物理存储驱动 */\n private baseStorage: StoragePort;\n /** 插件 ID 与存储描述定义的映射关系 */\n private schemas: Map<string, StorageItemSchema[]> = new Map();\n /** 内存缓存,减少 JSON 序列化和物理 IO 开销 */\n private memoryCache: Map<string, any> = new Map();\n\n /**\n * 初始化存储管理器\n * @param baseStorage - 符合 StoragePort 接口的物理存储驱动(如 LocalStorageAdapter)\n */\n constructor(baseStorage: StoragePort) {\n this.baseStorage = baseStorage;\n }\n\n /**\n * 注册插件的存储 Schema\n * @param pluginId - 插件 ID\n * @param schema - 存储项定义列表\n */\n registerSchema(pluginId: string, schema: StorageItemSchema[]) {\n this.schemas.set(pluginId, schema);\n }\n\n /**\n * 内部校验方法:检查键名是否在 Schema 中声明\n * @param pluginId - 插件 ID\n * @param key - 待校验的键名\n * @param scope - 目标作用域\n */\n private validateKey(pluginId: string, key: string, scope: 'plugin' | 'shared' = 'plugin') {\n const schemaList = this.schemas.get(pluginId);\n if (!schemaList) return; // 未定义 Schema 则跳过校验\n\n const item = schemaList.find(s => s.key === key);\n if (!item) {\n console.warn(`[Storage] Key \"${key}\" not defined in plugin \"${pluginId}\" schema.`);\n return;\n }\n\n const definedScope = item.scope || 'plugin';\n if (definedScope !== scope) {\n console.warn(`[Storage] Key \"${key}\" defined in scope \"${definedScope}\" but accessed via \"${scope}\".`);\n }\n }\n\n /**\n * 获取插件私有存储适配器\n * @param pluginId - 插件 ID\n * @returns 自动添加 `plugin:{id}:` 前缀的存储接口\n */\n getPluginStorage(pluginId: string): StoragePort {\n return new ScopedStorageAdapter(this.baseStorage, `plugin:${pluginId}`);\n }\n\n /**\n * 获取全局共享存储适配器\n * @returns 自动添加 `shared:` 前缀的存储接口\n */\n getSharedStorage(): StoragePort {\n return new ScopedStorageAdapter(this.baseStorage, 'shared');\n }\n\n /**\n * 获取系统内部存储适配器\n * @returns 自动添加 `system:` 前缀的存储接口\n */\n getSystemStorage(): StoragePort {\n return new ScopedStorageAdapter(this.baseStorage, 'system');\n }\n\n /**\n * 创建插件沙箱使用的复合存储对象\n * @description 返回的对象封装了对私有存储和共享存储的操作。\n * 特性:\n * - 内存级 LRU 缓存:极大提升高频读写性能。\n * - 自动序列化/反序列化 JSON。\n * - 自动校验 Schema。\n * - 取值回退逻辑:持久化存储 -> ConfigManager -> Schema 默认值。\n * \n * @param pluginId - 插件 ID\n * @returns 包含 get/set/remove 及 shared 子对象的复合接口\n */\n getContextStorage(pluginId: string) {\n const pluginStorage = this.getPluginStorage(pluginId);\n const sharedStorage = this.getSharedStorage();\n\n const createHelpers = (adapter: StoragePort, scope: 'plugin' | 'shared') => {\n // 获取适配器的前缀 (ScopedStorageAdapter 内部属性)\n // 注意:这里由于是内部实现,我们知道前缀的规律\n const prefix = scope === 'plugin' ? `plugin:${pluginId}:` : 'shared:';\n\n return {\n get: <T = any>(key: string): T | null => {\n this.validateKey(pluginId, key, scope);\n const cacheKey = `${prefix}${key}`;\n\n try {\n // 1. 优先尝试从内存缓存获取\n if (this.memoryCache.has(cacheKey)) {\n return this.memoryCache.get(cacheKey);\n }\n\n // 2. 尝试从持久化存储获取 (用户设置)\n const val = adapter.getItem(key);\n if (val !== null) {\n let parsed: any;\n try {\n parsed = JSON.parse(val);\n } catch {\n parsed = val;\n }\n // 存入内存缓存\n this.memoryCache.set(cacheKey, parsed);\n return parsed;\n }\n\n // 3. 尝试从 ConfigManager 获取 (外部注入的配置)\n if (scope === 'plugin') {\n const externalConfig = configManager.get(pluginId);\n if (externalConfig && externalConfig[key] !== undefined) {\n return externalConfig[key];\n }\n }\n\n // 4. 尝试返回 Schema 定义的默认值\n const schema = this.schemas.get(pluginId)?.find((s) => s.key === key);\n if (schema && schema.default !== undefined) {\n return schema.default;\n }\n\n return null;\n } catch (e) {\n console.warn(`[Storage] Failed to read key \"${key}\"`, e);\n return null;\n }\n },\n set: <T = any>(key: string, value: T) => {\n this.validateKey(pluginId, key, scope);\n const cacheKey = `${prefix}${key}`;\n\n try {\n // 更新内存缓存\n this.memoryCache.set(cacheKey, value);\n // 异步持久化 (或者同步,取决于 adapter)\n adapter.setItem(key, JSON.stringify(value));\n } catch (e) {\n console.warn(`[Storage] Failed to stringify key \"${key}\"`, e);\n }\n },\n remove: (key: string) => {\n this.validateKey(pluginId, key, scope);\n const cacheKey = `${prefix}${key}`;\n \n this.memoryCache.delete(cacheKey);\n adapter.removeItem(key);\n }\n };\n };\n\n return {\n ...createHelpers(pluginStorage, 'plugin'),\n shared: createHelpers(sharedStorage, 'shared')\n };\n }\n}\n","import React, { useMemo, useState, useEffect, Suspense } from 'react';\n\nimport type { PluginExtension,SlotPosition } from '../api';\nimport { pluginManager } from '../domain/plugin-manager';\nimport { PluginErrorBoundary } from './PluginErrorBoundary';\nimport { SlotSkeletons } from './SlotSkeletons';\n\n/** 插件插槽组件属性 */\ninterface PluginSlotProps {\n /** 插槽位置标识,决定渲染哪些插件扩展 */\n slot: SlotPosition;\n /** 传递给扩展组件的 Props 对象 */\n props?: Record<string, any>;\n /** 自定义容器类名 (Tailwind CSS) */\n className?: string;\n /** 自定义容器内联样式 */\n style?: React.CSSProperties;\n /** \n * 自定义渲染函数\n * @param item - 包含 key、组件和扩展元信息的对象\n * @param index - 索引位置\n */\n renderItem?: (item: { key: string; component: React.ReactNode; extension: PluginExtension }, index: number) => React.ReactNode;\n /** 骨架屏组件,当插槽内无插件扩展时显示的占位 UI */\n skeleton?: React.ReactNode;\n /** 回退组件,当插槽内无插件扩展时显示的 UI,优先级高于 skeleton */\n fallback?: React.ReactNode;\n}\n\n/**\n * 插件插槽组件\n * @description UI 层的核心组件,用于在应用中声明一个“插槽”。\n * 它会自动根据 slot 标识从 PluginManager 中获取所有注册的插件扩展组件并按顺序渲染。\n * 支持订阅插件变更,实现动态热插拔。\n */\nexport const PluginSlot: React.FC<PluginSlotProps> = ({ \n slot, \n props = {}, \n className = '', \n style,\n renderItem,\n skeleton,\n fallback,\n}: PluginSlotProps) => {\n // 使用简单的强制更新机制,订阅 PluginManager 的变更\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n // 订阅特定插槽的插件变更,减少无效重渲染\n const unsubscribe = pluginManager.subscribe(() => {\n forceUpdate({});\n }, slot);\n return unsubscribe;\n }, [slot]);\n\n // 获取该插槽的所有扩展\n const extensions = pluginManager.getExtensions(slot);\n\n // 注入系统配置到 props\n const systemConfig = pluginManager.getSystemConfig('title') ? {\n title: pluginManager.getSystemConfig('title'),\n logo: pluginManager.getSystemConfig('logo'),\n version: pluginManager.getSystemConfig('version'),\n } : undefined;\n\n const mergedProps = useMemo(() => ({\n ...props,\n systemConfig\n }), [props, systemConfig]);\n\n const items = useMemo(() => {\n return extensions.map((ext, index) => {\n const Component = ext.component;\n // 使用组合键确保唯一性且稳定,避免使用 Math.random() 导致重渲染闪烁\n const key = ext.meta?.key || `${ext.slot}-${ext.order || 0}-${index}`;\n \n return {\n key,\n extension: ext,\n component: (\n <PluginErrorBoundary key={key} pluginId={ext._pluginId}>\n <Suspense fallback={skeleton || <SlotSkeletons slot={slot} />}>\n <Component {...mergedProps} />\n </Suspense>\n </PluginErrorBoundary>\n )\n };\n });\n }, [extensions, mergedProps]);\n\n // 如果没有扩展\n if (items.length === 0) {\n if (fallback) {\n return <>{fallback}</>;\n }\n if (skeleton) {\n return (\n <div className={`plugin-slot plugin-slot-${slot} plugin-slot-skeleton ${className || ''}`} style={style}>\n {skeleton}\n </div>\n );\n }\n return null;\n }\n\n // 如果只有一项且是 RootLayout,可能不需要包装层\n if (items.length === 1 && slot === 'root-layout' && !className && !style && !renderItem) {\n return <>{items[0].component}</>;\n }\n\n return (\n <div className={`plugin-slot plugin-slot-${slot} ${className || ''}`} style={style}>\n {renderItem \n ? items.map((item, index) => renderItem(item, index))\n : items.map(item => item.component)\n }\n </div>\n );\n};\n","import React from 'react';\n\n/**\n * 通用插槽骨架屏组件集合\n * @description 提供一组预定义的骨架屏 UI,用于在插件加载或插槽内容未准备好时提供更好的用户体验。\n */\n\n/**\n * 侧边栏图标骨架屏\n * @param expanded - 是否处于展开状态\n */\nexport const SidebarIconSkeleton: React.FC<{ expanded?: boolean }> = ({ expanded = false }) => (\n <div className={`flex items-center transition-all duration-300 relative\n ${expanded ? 'w-full' : 'w-12 justify-center'} px-3 h-11 rounded-xl`}>\n <div className=\"w-6 h-6 bg-slate-200 dark:bg-white/10 rounded-lg shrink-0 animate-pulse\" />\n {expanded && (\n <div className=\"ml-3 flex-1 h-4 bg-slate-200 dark:bg-white/10 rounded animate-pulse\" />\n )}\n </div>\n);\n\n/**\n * 状态栏项骨架屏\n */\nexport const StatusBarItemSkeleton: React.FC = () => (\n <div className=\"h-4 w-16 bg-slate-200 dark:bg-white/10 rounded animate-pulse\" />\n);\n\n/**\n * 头像骨架屏\n */\nexport const AvatarSkeleton: React.FC = () => (\n <div className=\"w-10 h-10 rounded-full bg-slate-200 dark:bg-white/10 animate-pulse\" />\n);\n\n/**\n * 通用块级骨架屏\n * @param className - 自定义类名\n */\nexport const BlockSkeleton: React.FC<{ className?: string }> = ({ className }) => (\n <div className={`bg-slate-200 dark:bg-white/10 rounded animate-pulse ${className || 'w-full h-full'}`} />\n);\n\n/**\n * 自动根据插槽位置匹配骨架屏\n */\nexport const SlotSkeletons: React.FC<{ slot: string; expanded?: boolean }> = ({ slot, expanded }) => {\n if (slot.includes('sidebar')) {\n return <SidebarIconSkeleton expanded={expanded} />;\n }\n if (slot.includes('status')) {\n return <StatusBarItemSkeleton />;\n }\n if (slot.includes('avatar')) {\n return <AvatarSkeleton />;\n }\n return <BlockSkeleton />;\n};\n","import { createLogger } from '../utils/logger';\n\nconst logger = createLogger('AutoLoader');\n\n/**\n * 插件注册表接口\n * @description 键为插件 ID,值为一个返回插件定义的异步加载函数。\n */\nexport interface PluginRegistry {\n [pluginId: string]: () => Promise<any>;\n}\n\n/**\n * 插件自动发现规则\n */\nexport interface DiscoveryRule {\n /**\n * 路径匹配标识。\n * @example 'plugins' 或 '@chatbi-plugins'\n */\n pathSegment: string;\n /**\n * 生成插件 ID 时的前缀。\n * @example '@chatbi-v/plugin',最终生成如 '@chatbi-v/plugin-demo'\n */\n idPrefix: string;\n}\n\n/**\n * 默认的插件发现约定规则\n */\nconst DEFAULT_RULES: DiscoveryRule[] = [\n { pathSegment: '@chatbi-plugins', idPrefix: '@chatbi-v/plugin' },\n { pathSegment: '@chatbi-apps', idPrefix: '@chatbi-v/app' },\n { pathSegment: 'packages/plugins', idPrefix: '@chatbi-v/plugin' },\n { pathSegment: 'packages/apps', idPrefix: '@chatbi-v/app' },\n];\n\n/**\n * 解析插件注册表\n * @description 核心逻辑:将 Vite 的 `import.meta.glob` 结果映射为标准的插件注册表。\n * 它会根据预定义的路径匹配规则,从文件路径中提取插件目录名,并拼接前缀生成唯一的插件 ID。\n * \n * @param options - 包含待处理模块和匹配规则的选项对象\n * @returns 解析后的 PluginRegistry 对象\n */\nexport const resolvePluginRegistry = (options: {\n /** 原始模块映射 (来自 Vite glob) */\n modules: Record<string, () => Promise<any>>;\n /** 自定义发现规则 (可选) */\n rules?: DiscoveryRule[];\n}): PluginRegistry => {\n const { modules, rules = DEFAULT_RULES } = options;\n const registry: PluginRegistry = {};\n\n // 预编译规则为正则表达式\n const compiledRules = rules.map((rule) => {\n // 处理别名或路径片段,提取文件夹名\n // 支持格式: .../pathSegment/folderName/src/index...\n const escapedSegment = rule.pathSegment.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return {\n ...rule,\n regex: new RegExp(`${escapedSegment}/([^/]+)/src/index`),\n };\n });\n\n for (const path in modules) {\n try {\n let pluginId: string | null = null;\n\n // 匹配规则\n for (const rule of compiledRules) {\n const match = path.match(rule.regex);\n if (match && match[1]) {\n pluginId = `${rule.idPrefix}-${match[1]}`;\n logger.info(`解析路径成功: ${path} -> ${pluginId}`);\n break;\n }\n }\n\n if (pluginId) {\n registry[pluginId] = modules[path];\n } else {\n logger.warn(`无法从路径解析插件 ID: ${path},请检查是否符合命名约定。`);\n }\n } catch (e) {\n logger.error(`解析插件路径失败: ${path}`, e);\n }\n }\n\n return registry;\n};\n","/**\n * 成功状态码\n */\nexport const SUCCESS_CODE = '000000';\n\n/**\n * 基础 API 响应接口\n * @template T 响应数据的类型\n */\nexport interface BaseResponse<T = any> {\n /** 业务状态码 */\n code: string | number;\n /** 响应消息提示 */\n message: string;\n /** 业务响应数据主体 */\n data: T;\n}\n\n/**\n * 业务场景实体接口\n * @description 描述系统中的业务分析场景\n */\nexport interface Scene {\n /** 场景唯一标识符 */\n id: string;\n /** 场景名称 */\n name: string;\n /** 场景详细描述 */\n description: string;\n /** 场景内部代码/标识 */\n code: string;\n /** 场景创建者 ID 或名称 */\n creator: string;\n /** 创建时间字符串 (ISO 格式) */\n createTime: string;\n /** 该场景关联的物理数据表数量 */\n tableCount: number;\n /** 该场景关联的知识库数量 */\n kbCount: number;\n /** 该场景关联的预设问答对数量 */\n qaCount: number;\n /** 场景封面图 URL (可选) */\n cover?: string;\n}\n","import React, { createContext, useContext } from 'react';\n\nimport { PluginManager } from './domain/plugin-manager';\n\nconst PluginContext = createContext<PluginManager | null>(null);\n\nexport interface PluginProviderProps {\n manager: PluginManager;\n children: React.ReactNode;\n}\n\nexport const PluginProvider: React.FC<PluginProviderProps> = ({ manager, children }) => {\n return <PluginContext.Provider value={manager}>{children}</PluginContext.Provider>;\n};\n\nexport const usePluginManager = () => {\n const context = useContext(PluginContext);\n if (!context) {\n throw new Error('usePluginManager must be used within a PluginProvider');\n }\n return context;\n};\n","import axios, { AxiosInstance } from 'axios';\n\nimport { ApiAdapter, ApiEndpointConfig, ApiRequestConfig, StreamCallbacks } from '../../ports/api-port';\n\n/**\n * 基于 Axios 的默认请求适配器\n */\nexport class AxiosAdapter implements ApiAdapter {\n private client: AxiosInstance;\n\n constructor(baseURL: string = '/api', timeout: number = 10000) {\n this.client = axios.create({\n baseURL,\n timeout,\n });\n\n // 保持返回完整响应对象,以便 ApiEngine 可以处理 headers 和 status\n // 错误处理回归标准行为,由 ApiEngine 捕获处理\n this.client.interceptors.response.use(\n (response) => response,\n (error) => Promise.reject(error),\n );\n }\n\n async request<T = any>(config: ApiRequestConfig): Promise<T> {\n return this.client.request(config);\n }\n\n async stream(config: ApiRequestConfig, callbacks: StreamCallbacks, _endpointConfig?: ApiEndpointConfig): Promise<void> {\n const { onMessage, onError, onFinish } = callbacks;\n\n try {\n // 通过 axios.request 发起请求,以利用其拦截器(Interceptors)机制\n // 我们提供一个自定义的 adapter 来执行实际的 fetch 调用\n const response = await this.client.request({\n ...config,\n // 强制不缓存流式响应\n headers: {\n 'Cache-Control': 'no-cache',\n 'Pragma': 'no-cache',\n ...config.headers,\n },\n // 自定义适配器:在拦截器链中执行 fetch\n adapter: async (axiosConfig) => {\n // getUri 会自动处理 baseURL 和 params\n const url = this.client.getUri(axiosConfig);\n\n const fetchResponse = await fetch(url, {\n method: axiosConfig.method?.toUpperCase(),\n headers: axiosConfig.headers as any,\n body: axiosConfig.data ? (typeof axiosConfig.data === 'string' ? axiosConfig.data : JSON.stringify(axiosConfig.data)) : undefined,\n signal: axiosConfig.signal as AbortSignal,\n });\n\n return {\n data: fetchResponse, // 将原始 Response 存入 data,以便在拦截器链后获取\n status: fetchResponse.status,\n statusText: fetchResponse.statusText,\n headers: fetchResponse.headers as any,\n config: axiosConfig,\n };\n },\n });\n\n // 获取 fetch 的 Response 对象\n const fetchResponse = response instanceof Response ? response : response.data;\n\n // 触发 onResponse 回调\n if (callbacks.onResponse) {\n const hijacked = await callbacks.onResponse(response);\n if (hijacked) return;\n }\n\n if (!(fetchResponse instanceof Response)) {\n throw new Error('流式请求失败:未能获取到原始响应流,请检查 Axios 响应拦截器是否正确处理了 Response 对象。');\n }\n\n if (!fetchResponse.ok) {\n throw new Error(`HTTP error! status: ${fetchResponse.status}`);\n }\n\n if (!fetchResponse.body) {\n throw new Error('响应体为空');\n }\n\n const reader = fetchResponse.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // 按 SSE 事件分隔符(双换行)分割\n const parts = buffer.split('\\n\\n');\n\n // 最后一个部分可能是不完整的,保留在 buffer 中\n buffer = parts.pop() || '';\n\n for (const part of parts) {\n if (onMessage) {\n onMessage(part + '\\n\\n');\n }\n }\n }\n\n // 处理最后剩余的内容\n if (buffer && onMessage) {\n onMessage(buffer);\n }\n\n if (onFinish) onFinish();\n } catch (error) {\n if (onError) onError(error);\n }\n }\n}\n\n","import { BaseResponse, SUCCESS_CODE } from '../domain/models';\nimport { ApiAdapter, ApiConfig, ApiEndpointConfig, ApiInterceptor, ApiRequestConfig, RequestOptions } from '../ports/api-port';\nimport { createLogger } from '../utils/logger';\nimport { AxiosAdapter } from './adapters/axios-adapter';\n\nconst logger = createLogger('ApiEngine');\n\n/**\n * API 引擎核心类\n * @description 负责加载配置并执行请求,支持策略模式切换底层请求实现\n */\nexport class ApiEngine {\n private adapter: ApiAdapter;\n private config: ApiConfig = {};\n private interceptors: ApiInterceptor[] = [];\n\n constructor(adapter?: ApiAdapter) {\n // 默认使用 AxiosAdapter\n this.adapter = adapter || new AxiosAdapter();\n }\n\n /**\n * 注册拦截器\n */\n registerInterceptor(interceptor: ApiInterceptor) {\n this.interceptors.push(interceptor);\n }\n\n /**\n * 移除拦截器\n */\n unregisterInterceptor(interceptor: ApiInterceptor) {\n this.interceptors = this.interceptors.filter((i) => i !== interceptor);\n }\n\n /**\n * 切换请求适配器\n * @param adapter 新的适配器实例\n */\n useAdapter(adapter: ApiAdapter) {\n this.adapter = adapter;\n }\n\n /**\n * 注册 API 配置\n * @param config 配置对象\n */\n register(config: ApiConfig) {\n logger.info('正在注册 API 配置:', Object.keys(config));\n this.config = { ...this.config, ...config };\n }\n\n /**\n * 获取接口配置\n */\n getEndpoint(module: string, action: string): ApiEndpointConfig | undefined {\n return this.config[module]?.[action];\n }\n\n /**\n * 发起 API 请求\n * @param module 模块名\n * @param action 动作名\n * @param data 请求数据 (Body 或 Query)\n * @param options 请求选项\n */\n async call<T = any>(\n module: string,\n action: string,\n data?: any,\n options: RequestOptions = {},\n ): Promise<T> {\n const endpoint = this.getEndpoint(module, action);\n if (!endpoint) {\n logger.warn(`未找到 API 定义: ${module}.${action} (当前已注册模块: ${Object.keys(this.config).join(', ')})`);\n return Promise.resolve(undefined as unknown as T);\n }\n\n // 1. 准备并应用请求拦截\n const requestConfig = await this.prepareRequestConfig(endpoint, data, options);\n\n // 2. 调用适配器执行请求\n let response: any;\n try {\n response = await this.adapter.request<any>(requestConfig, endpoint);\n } catch (error: any) {\n if (error.response) {\n response = error.response;\n } else {\n throw error;\n }\n }\n\n // 3. 处理响应拦截\n const hijacked = await this.applyResponseInterceptors(response, requestConfig);\n if (hijacked) {\n logger.info('请求被拦截器劫持:', module, action);\n return undefined as unknown as T;\n }\n\n // 4. 检查 HTTP 状态码\n this.checkHttpStatus(response);\n\n // 5. 提取并处理业务错误\n const responseData = this.extractResponseData(response);\n this.handleBusinessError(responseData, endpoint, module, action);\n\n return responseData as T;\n }\n\n /**\n * 发起流式请求\n * @param module 模块名\n * @param action 动作名\n * @param data 请求数据\n * @param options 请求选项\n */\n async stream(\n module: string,\n action: string,\n data?: any,\n options: RequestOptions = {},\n ): Promise<void> {\n const endpoint = this.getEndpoint(module, action);\n if (!endpoint) {\n logger.warn(`未找到 API 定义: ${module}.${action},跳过流式请求。`);\n return;\n }\n\n if (!this.adapter.stream) {\n logger.warn('当前 API 适配器不支持流式传输。');\n return;\n }\n\n // 1. 准备并应用请求拦截\n const requestConfig = await this.prepareRequestConfig(endpoint, data, options);\n\n const callbacks = {\n onMessage: options.onMessage,\n onError: options.onError,\n onFinish: options.onFinish,\n };\n\n // 2. 执行流式请求\n try {\n await this.adapter.stream(\n requestConfig,\n {\n ...callbacks,\n onResponse: async (response: any) => {\n // 处理响应拦截\n const hijacked = await this.applyResponseInterceptors(response, requestConfig);\n if (hijacked) {\n logger.info('流式请求被拦截器劫持:', module, action);\n // 如果被劫持,主动中止流式传输\n if (requestConfig.signal instanceof AbortController) {\n (requestConfig.signal as AbortController).abort();\n }\n return true;\n }\n\n // 检查 HTTP 状态码\n this.checkHttpStatus(response);\n \n return false;\n },\n },\n endpoint,\n );\n } catch (error) {\n if (callbacks.onError) {\n callbacks.onError(error);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * 准备请求配置,应用 URL 参数替换和请求拦截器\n */\n private async prepareRequestConfig(\n endpoint: ApiEndpointConfig,\n data: any,\n options: RequestOptions,\n ): Promise<ApiRequestConfig> {\n // 1. 处理 URL 参数替换\n let url = endpoint.url;\n const pathParams = options.params || {};\n \n url = url.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {\n if (pathParams[key] !== undefined) return String(pathParams[key]);\n if (data && typeof data === 'object' && data[key] !== undefined) return String(data[key]);\n return `:${key}`;\n });\n\n const method = endpoint.method;\n \n // 2. 构建初始请求配置\n let requestConfig: ApiRequestConfig = {\n ...options,\n url,\n method,\n };\n\n if (method === 'GET' || method === 'DELETE') {\n requestConfig.params = data;\n } else {\n requestConfig.data = data;\n }\n\n // 3. 应用请求拦截器\n return this.applyRequestInterceptors(requestConfig);\n }\n\n /**\n * 应用所有请求拦截器\n */\n private async applyRequestInterceptors(config: ApiRequestConfig): Promise<ApiRequestConfig> {\n let currentConfig = config;\n for (const interceptor of this.interceptors) {\n if (interceptor.interceptRequest) {\n currentConfig = await interceptor.interceptRequest(currentConfig);\n }\n }\n return currentConfig;\n }\n\n /**\n * 应用所有响应拦截器\n * @returns 是否被劫持\n */\n private async applyResponseInterceptors(response: any, config: ApiRequestConfig): Promise<boolean> {\n if (this.interceptors.length === 0) return false;\n\n const context = this.createInterceptorContext(response, config);\n for (const interceptor of this.interceptors) {\n if (interceptor.interceptResponse) {\n const hijacked = await interceptor.interceptResponse(context);\n if (hijacked) return true;\n }\n }\n return false;\n }\n\n /**\n * 检查 HTTP 状态码\n */\n private checkHttpStatus(response: any): void {\n if (response && response.status && (response.status < 200 || response.status >= 300)) {\n // 如果是 BaseResponse,我们通常在 handleBusinessError 中处理业务错误\n // 这里的 checkHttpStatus 主要针对非 2xx 的 HTTP 错误\n const responseData = this.extractResponseData(response);\n if (!this.isBaseResponse(responseData)) {\n throw new Error(`Request failed with status ${response.status}`);\n }\n }\n }\n\n /**\n * 提取响应数据\n */\n private extractResponseData(response: any): any {\n return this.isAxiosResponse(response) ? response.data : response;\n }\n\n /**\n * 处理业务错误\n */\n private handleBusinessError(\n responseData: any, \n endpoint: ApiEndpointConfig, \n module: string, \n action: string\n ): void {\n if (!this.isBaseResponse(responseData)) return;\n\n const res = responseData as BaseResponse;\n const code = String(res.code);\n \n // 假设 SUCCESS_CODE, '200', '0' 为成功\n const isSuccess = code === SUCCESS_CODE || code === '200' || code === '0';\n \n if (!isSuccess) {\n const strategy = endpoint.errorStrategy || 'reject';\n if (strategy === 'reject') {\n logger.error(`API 请求业务错误 (${module}.${action}):`, res.message);\n throw new Error(res.message || `Request failed with code ${code}`);\n }\n }\n }\n\n /**\n * 判断是否为 BaseResponse\n */\n private isBaseResponse(data: any): boolean {\n return (\n data &&\n typeof data === 'object' &&\n 'code' in data &&\n ('message' in data || 'data' in data)\n );\n }\n\n /**\n * 严格判断是否为 AxiosResponse\n */\n private isAxiosResponse(res: any): boolean {\n return (\n res &&\n typeof res === 'object' &&\n 'data' in res &&\n 'status' in res &&\n 'headers' in res\n );\n }\n\n /**\n * 创建拦截上下文\n */\n private createInterceptorContext(response: any, config: ApiRequestConfig) {\n // 适配 Axios 响应结构\n if (response && typeof response === 'object' && 'status' in response && 'headers' in response) {\n return {\n response,\n status: response.status,\n headers: response.headers,\n data: response.data,\n config,\n };\n }\n \n // 兜底逻辑\n return {\n response,\n status: 200,\n headers: {},\n data: response,\n config,\n };\n }\n}\n\nexport const apiEngine = new ApiEngine();\n","type KeepStrategy = 'first' | 'last' | 'search' | 'hash';\n\n/**\n * 把当前地址中所有出现的参数合并成一份。\n * 重复 key 的处理策略:\n * - 'first' : 按出现顺序,第一次的值生效\n * - 'last' : 按出现顺序,最后一次的值生效(默认,最直观)\n * - 'search' : 只要 search 里出现过,就用 search 的\n * - 'hash' : 只要 hash 里出现过,就用 hash 的\n */\nexport function normalizeParams(strategy: KeepStrategy = 'last'): URLSearchParams {\n if (typeof window === 'undefined') return new URLSearchParams();\n \n const { search, hash } = window.location;\n\n // 1. 把 search 和 hash 里的 query 都拆出来\n const searchParams = new URLSearchParams(search);\n const hashParams = new URLSearchParams(hash.split('?')[1] || '');\n\n // 2. 按出现顺序拼成一个数组,方便做“first/last”策略\n const entries: Array<[string, string, 'search' | 'hash']> = [];\n searchParams.forEach((v, k) => entries.push([k, v, 'search']));\n hashParams.forEach((v, k) => entries.push([k, v, 'hash']));\n\n // 3. 根据策略挑值\n const keeper = new Map<string, string>();\n if (strategy === 'first') {\n entries.forEach(([k, v]) => {\n if (!keeper.has(k)) keeper.set(k, v);\n });\n } else if (strategy === 'last') {\n entries.forEach(([k, v]) => keeper.set(k, v));\n } else if (strategy === 'search') {\n entries.forEach(([k, v, src]) => {\n if (src === 'search') keeper.set(k, v);\n });\n // search 里没有的再用 hash 补\n hashParams.forEach((v, k) => {\n if (!keeper.has(k)) keeper.set(k, v);\n });\n } else if (strategy === 'hash') {\n entries.forEach(([k, v, src]) => {\n if (src === 'hash') keeper.set(k, v);\n });\n searchParams.forEach((v, k) => {\n if (!keeper.has(k)) keeper.set(k, v);\n });\n }\n\n return new URLSearchParams(Array.from(keeper.entries()));\n}\n\n/**\n * 清除 URL 中的特定参数并返回新的 URL\n * @description 同时处理 search 和 hash 中的参数\n */\nexport function cleanUrlParams(keysToRemove: string[]): string {\n if (typeof window === 'undefined') return '';\n\n const { pathname, search, hash } = window.location;\n\n // 1. 清理 search\n const searchParams = new URLSearchParams(search);\n keysToRemove.forEach((key) => searchParams.delete(key));\n const newSearch = searchParams.toString();\n\n // 2. 清理 hash\n const hashParts = hash.split('?');\n const hashPath = hashParts[0];\n const hashQuery = hashParts[1] || '';\n const hashParams = new URLSearchParams(hashQuery);\n keysToRemove.forEach((key) => hashParams.delete(key));\n const newHashQuery = hashParams.toString();\n const newHash = hashPath + (newHashQuery ? '?' + newHashQuery : '');\n\n // 3. 拼接新 URL\n return pathname + (newSearch ? '?' + newSearch : '') + newHash;\n}\n","import { ApiConfig } from '../ports/api-port';\n\n/**\n * 深度合并 Mock 数据到 API 定义中\n */\nconst mergeMockData = (def: Record<string, any>, mock: Record<string, any>) => {\n // 深度克隆以避免修改原始对象\n const merged = JSON.parse(JSON.stringify(def));\n\n Object.keys(mock).forEach((key) => {\n if (merged[key]) {\n merged[key] = {\n ...merged[key],\n ...mock[key],\n };\n }\n });\n\n return merged;\n};\n\nimport { normalizeParams } from '../utils/url';\n\n/**\n * 自动检测是否处于 Mock 模式\n */\nexport function isMockMode(): boolean {\n // 1. 检查环境变量\n const envMock = (typeof process !== 'undefined' && process.env.VITE_USE_MOCK === 'true') ||\n (typeof window !== 'undefined' && (window as any).VITE_USE_MOCK === 'true');\n \n // 2. 检查 URL 参数 (优先级最高,用于运行时切换)\n if (typeof window !== 'undefined') {\n const params = normalizeParams();\n const mockParam = params.get('mock');\n \n if (mockParam === 'true') return true;\n if (mockParam === 'false') return false;\n }\n\n return envMock;\n}\n\n/**\n * 从文件模块映射中解析 API 配置\n * @description 配合 Vite 的 import.meta.glob 使用,自动匹配定义文件和 Mock 文件\n * @param definitionsMap API 定义文件映射 (import.meta.glob('./modules/*.ts', { eager: true }))\n * @param mocksMap Mock 文件映射 (import.meta.glob('./modules/*.mock.ts', { eager: true }))\n * @param useMock 是否启用 Mock (如果不传,将自动调用 isMockMode())\n * @returns 合并后的 ApiConfig\n */\nexport function resolveApiModules(\n definitionsMap: Record<string, any>,\n mocksMap: Record<string, any> = {}\n): ApiConfig {\n const config: ApiConfig = {};\n \n // 辅助函数:从路径中获取命名空间(去掉扩展名的文件名)\n const getNamespace = (path: string) => {\n // 处理 ./modules/chat.ts -> chat\n // 处理 /src/api/modules/user.ts -> user\n const fileName = path.split('/').pop() || '';\n // 移除 .mock.ts, .ts, .js, .json 等后缀\n return fileName.replace(/\\.mock\\.(ts|js|tsx|jsx|json)$/, '').replace(/\\.(ts|js|tsx|jsx|json)$/, '');\n };\n\n Object.entries(definitionsMap).forEach(([path, module]) => {\n // 跳过可能是 mock 的文件,防止它们意外进入 definitions glob\n if (path.includes('.mock.')) return;\n\n const namespace = getNamespace(path);\n if (!namespace || !module.default) return;\n\n let apiDef = module.default;\n \n // 始终尝试合并 Mock 数据\n // 这样即使在非 Mock 模式下,API 定义中也包含 Schema,方便动态切换\n const mockEntry = Object.entries(mocksMap).find(([mockPath]) => {\n return getNamespace(mockPath) === namespace && mockPath.includes('.mock.');\n });\n\n if (mockEntry) {\n const mockModule = mockEntry[1] as any;\n const mockData = mockModule.default || mockModule;\n if (mockData) {\n apiDef = mergeMockData(apiDef, mockData);\n }\n }\n\n config[namespace] = apiDef;\n });\n\n return config;\n}\n","import dayjs from 'dayjs';\nimport relativeTime from 'dayjs/plugin/relativeTime';\nimport 'dayjs/locale/zh-cn';\n\n// 加载插件\ndayjs.extend(relativeTime);\n// 设置默认语言\ndayjs.locale('zh-cn');\n\n/**\n * 日期时间格式化工具类\n */\nexport const dateUtils = {\n /**\n * 格式化日期为 YYYY-MM-DD\n */\n formatDate(date?: dayjs.ConfigType): string {\n return dayjs(date).format('YYYY-MM-DD');\n },\n\n /**\n * 格式化时间为 HH:mm:ss\n */\n formatTime(date?: dayjs.ConfigType): string {\n return dayjs(date).format('HH:mm:ss');\n },\n\n /**\n * 格式化日期时间为 YYYY-MM-DD HH:mm:ss\n */\n formatDateTime(date?: dayjs.ConfigType): string {\n return dayjs(date).format('YYYY-MM-DD HH:mm:ss');\n },\n\n /**\n * 获取当前时间戳(毫秒)\n */\n now(): number {\n return dayjs().valueOf();\n },\n\n /**\n * 获取相对时间(例如:几分钟前)\n */\n fromNow(date: dayjs.ConfigType): string {\n return dayjs(date).fromNow();\n },\n\n /**\n * 原始 dayjs 对象,用于更复杂的场景\n */\n dayjs,\n};\n\nexport default dateUtils;\n","export * from './logger';\nexport * from './date';\nexport * from './url';\nexport const version = '1.0.0';\n","import { useCallback,useState } from 'react';\n\nimport { pluginManager } from '../domain/plugin-manager';\n\n/**\n * Hook 配置选项\n */\nexport interface UseStorageStateOptions<T> {\n defaultValue?: T;\n scope?: 'plugin' | 'shared';\n}\n\n/**\n * 统一存储状态 Hook\n * @description 提供与 StorageManager 和 Schema Registry 集成的持久化状态 Hook。\n * @param pluginId 定义该 Key 的插件 ID\n * @param key 存储键名 (必须在 Schema 中注册)\n * @param options 配置项,包含默认值和作用域\n */\nexport function useStorageState<T>(pluginId: string, key: string, options: UseStorageStateOptions<T> = {}): [T, (value: T | ((val: T) => T)) => void] {\n const { defaultValue, scope = 'plugin' } = options;\n const storageManager = pluginManager.getStorageManager();\n \n const getStorage = useCallback(() => {\n const contextStorage = storageManager.getContextStorage(pluginId);\n return scope === 'shared' ? contextStorage.shared : contextStorage;\n }, [pluginId, scope, storageManager]);\n\n const [state, setState] = useState<T>(() => {\n try {\n if (typeof window === 'undefined') return defaultValue as T;\n const storage = getStorage();\n const val = storage.get<T>(key);\n return val !== null ? val : (defaultValue as T);\n } catch (e) {\n console.warn(`[useStorageState] 读取 Key \"${key}\" 失败`, e);\n return defaultValue as T;\n }\n });\n\n const setValue = useCallback((value: T | ((val: T) => T)) => {\n try {\n const valueToStore = value instanceof Function ? value(state) : value;\n setState(valueToStore);\n \n const storage = getStorage();\n storage.set(key, valueToStore);\n } catch (error) {\n console.warn(`[useStorageState] 设置 Key \"${key}\" 失败:`, error);\n }\n }, [key, state, getStorage]);\n\n return [state, setValue];\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { resolvePluginRegistry } from '../domain/auto-loader';\nimport { pluginManager } from '../domain/plugin-manager';\nimport { createLogger } from '../utils/logger';\n\nconst logger = createLogger('PluginLoader');\n\n/** 插件加载 Hook 的配置选项 */\nexport interface PluginLoaderOptions {\n /** 插件发现规则,定义如何从模块列表中识别插件 */\n discoveryRules?: any[];\n /** 插件模块映射,通常由 Vite 的 `import.meta.glob` 生成,键为路径,值为加载函数 */\n modules?: Record<string, () => Promise<any>>;\n /** 预注册的插件注册表,用于手动指定插件加载逻辑,优先级高于自动发现 */\n registry?: Record<string, () => Promise<any>>;\n /** 插件的业务配置映射,键为插件 ID */\n pluginConfigs: Record<string, any>;\n /** 初始化的共享上下文服务,将注入到每个插件的 onLoad 中 */\n sharedContext?: Record<string, any>;\n /** 系统级全局配置,如标题、版本号、Logo 等 */\n systemConfig?: Record<string, any>;\n /** 资源发现的基础 URL,默认为当前 window.location.origin */\n baseUrl?: string;\n}\n\n/**\n * 核心 Hook:通用插件加载器\n * @description 负责应用启动时的插件全生命周期管理:\n * 1. 自动发现:解析 modules 并根据规则识别插件。\n * 2. 注册:将插件信息录入 PluginManager。\n * 3. 加载:调用插件的加载逻辑 (onLoad)。\n * 4. 初始化:调用插件的挂载逻辑 (onMount)。\n * 5. 响应式更新:订阅插件状态变更并触发 UI 刷新。\n * \n * @param options - 加载配置项\n * @returns { pluginsLoaded: boolean, pluginVersion: number } \n * - pluginsLoaded: 插件是否已全部完成初始化\n * - pluginVersion: 插件状态版本号,用于强制触发依赖插件状态的组件重渲染\n */\nexport const usePluginLoader = (options: PluginLoaderOptions) => {\n const [pluginsLoaded, setPluginsLoaded] = useState(false);\n const [pluginVersion, setPluginVersion] = useState(0);\n const loadingRef = useRef(false);\n\n useEffect(() => {\n // 订阅插件管理器状态变更\n const unsubscribe = pluginManager.subscribe(() => {\n logger.debug('Plugin state changed, refreshing UI...');\n setPluginVersion((v) => v + 1);\n });\n\n const load = async () => {\n if (loadingRef.current || pluginsLoaded) return;\n loadingRef.current = true;\n\n try {\n const { \n discoveryRules = [], \n modules = {},\n registry: manualRegistry = {}, \n pluginConfigs, \n sharedContext = {}, \n baseUrl = (window as any).location.origin \n } = options;\n\n logger.info('Starting to load plugins...');\n \n // 1. 自动发现插件 (如果提供了模块)\n const discoveredRegistry = Object.keys(modules).length > 0\n ? resolvePluginRegistry({\n modules,\n rules: discoveryRules.length > 0 ? discoveryRules : undefined,\n })\n : {};\n\n // 2. 合并注册表 (手动注册优先)\n const finalRegistry = { ...discoveredRegistry, ...manualRegistry };\n\n // 2.5 注入系统配置到 configManager\n if (options.systemConfig) {\n const { configManager } = await import('../config-manager');\n configManager.set('system', options.systemConfig);\n }\n\n // 3. 加载插件\n await pluginManager.loadPlugins(pluginConfigs, finalRegistry);\n \n // 4. 初始化 (异步)\n await pluginManager.initPlugins(sharedContext);\n \n setPluginsLoaded(true);\n logger.info('Plugins loaded successfully');\n } catch (error) {\n logger.error('Failed to load plugins:', error);\n } finally {\n loadingRef.current = false;\n }\n };\n\n load();\n\n return () => {\n unsubscribe();\n };\n }, []);\n\n return {\n pluginsLoaded,\n pluginVersion\n };\n};\n"],"mappings":"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","names":["LogLevel","logger","logger","logger","logger","logger","jsx","logger","jsx","jsx","Component","logger","createContext","useContext","jsx","fetchResponse","logger","useState","useState","useEffect","useState","logger","useState","useEffect","configManager"]}
|
|
1
|
+
{"version":3,"sources":["../src/ports/plugin-port.ts","../src/utils/logger.ts","../src/application/service-registry.ts","../src/api-context.tsx","../src/components/PluginErrorBoundary.tsx","../src/domain/plugin-manager.ts","../src/adapters/local-storage-adapter.ts","../src/event-bus.ts","../src/sandbox/proxy-sandbox.ts","../src/domain/plugin-sandbox.ts","../src/domain/plugin-runtime.ts","../src/adapters/scoped-storage-adapter.ts","../src/domain/storage-manager.ts","../src/components/PluginSlot.tsx","../src/components/SlotSkeletons.tsx","../src/domain/auto-loader.ts","../src/domain/models.ts","../src/plugin-context.tsx","../src/api/adapters/axios-adapter.ts","../src/api/engine.ts","../src/utils/url.ts","../src/api/utils.ts","../src/utils/date.ts","../src/utils/index.ts","../src/hooks/use-storage-state.ts","../src/hooks/use-plugin-loader.ts"],"sourcesContent":["import React from 'react';\n\nimport { ApiConfig } from './api-port';\nimport { EventBusPort } from './event-bus-port';\nimport { TypedStorage } from './storage-port';\n\n/**\n * 插件类型定义\n */\nexport const PLUGIN_TYPES = ['business', 'functional', 'view', 'theme', 'renderer', 'system'] as const;\nexport type PluginType = typeof PLUGIN_TYPES[number];\n\n/**\n * 路由配置\n */\nexport interface RouteConfig {\n path: string;\n component: React.ComponentType<any>;\n meta?: Record<string, any>;\n}\n\n/**\n * 插件插槽位置\n * @description 定义插件可以注入 UI 的标准位置\n */\nexport const Slot = {\n Sidebar: 'sidebar',\n SidebarPanel: 'sidebar-panel',\n Header: 'header',\n StatusBar: 'status-bar',\n Settings: 'settings',\n MessageRenderer: 'message-renderer',\n MessageContentRenderer: 'message-content-renderer',\n SidebarSystem: 'sidebar-system',\n SidebarBottom: 'sidebar-bottom',\n RootLayout: 'root-layout',\n Custom: 'custom'\n} as const;\n\nexport type SlotType = typeof Slot[keyof typeof Slot];\n\nexport type SlotPosition = SlotType | string;\n\n/**\n * 插件扩展 (插槽注入配置)\n */\nexport interface PluginExtension {\n /** 插槽位置标识符 */\n slot: SlotPosition;\n /** 要注入的 React 组件 */\n component: React.ComponentType<any>;\n /** 排序权重,数值越小越靠前 */\n order?: number;\n /** @internal 插件 ID,由系统在加载时自动注入,用于溯源 */\n _pluginId?: string;\n /** 扩展的元数据信息 */\n meta?: {\n /** 显示图标 */\n icon?: React.ReactNode;\n /** 显示标签文本 */\n label?: string;\n /** 详细描述 */\n description?: string;\n /** 唯一标识符,用于某些特定插槽的索引 */\n key?: string;\n /** 允许其他自定义属性 */\n [key: string]: any;\n };\n}\n\n/**\n * 插件配置项定义\n */\nexport interface PluginConfigItem {\n /** 配置键名 */\n key: string;\n /** 配置类型 */\n type: 'string' | 'number' | 'boolean' | 'select';\n /** 配置显示的标签 */\n label: string;\n /** 配置描述信息 */\n description?: string;\n /** 默认值 */\n default?: any;\n /** 当类型为 select 时的选项列表 */\n options?: { label: string; value: any }[];\n /** 选择模式:支持多选或标签模式 (AntD 风格) */\n mode?: 'multiple' | 'tags';\n /** 最小值 (针对 number 类型) */\n min?: number;\n /** 最大值 (针对 number 类型) */\n max?: number;\n /** \n * 是否为私有配置\n * @description 如果为 true,则该配置不会通过自动配置服务暴露给其他插件\n * @default false\n */\n private?: boolean;\n}\n\n/**\n * 插件能力定义 (Behavioral Capabilities)\n * @description 定义插件的行为特征。注意:路由(routes)和扩展(extensions)属于结构化能力,直接通过 metadata 字段声明,不在此列。\n */\nexport interface PluginCapabilities {\n /** \n * 是否支持配置设置 \n * @default false (如果 metadata.configuration 存在,则可能被隐式视为 true,建议显式声明)\n */\n configurable?: boolean;\n /** \n * 是否可嵌入其他页面 \n * @description 声明该插件是否可以作为 Widget 被其他插件引用\n */\n embeddable?: boolean;\n /** \n * 是否支持多实例 \n * @description 默认为 false (单例)。如果在聊天窗口中每个会话都需要独立状态,则设为 true\n */\n multiInstance?: boolean;\n /** \n * 是否需要后台运行 \n * @description 如果为 true,即使 UI 不可见,插件也不会被卸载\n */\n background?: boolean;\n [key: string]: boolean | undefined;\n}\n\n/**\n * 存储项数据结构定义 (Schema)\n */\nexport interface StorageItemSchema {\n /** 存储键名 */\n key: string;\n /** 数据类型 */\n type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n /** 默认值 */\n default?: any;\n /** 描述信息 */\n description?: string;\n /** \n * 作用域\n * @description 'plugin' 表示仅当前插件可见(带插件 ID 前缀),'shared' 表示全局共享\n */\n scope?: 'plugin' | 'shared';\n}\n\n/**\n * 插件存储接口\n * @description 包含私有存储和共享存储访问能力\n */\nexport interface PluginStorage extends TypedStorage {\n /** 获取插件私有存储数据 */\n get: TypedStorage['get'];\n /** 设置插件私有存储数据 */\n set: TypedStorage['set'];\n /** 移除插件私有存储数据 */\n remove: TypedStorage['remove'];\n /** 全局共享存储访问 */\n shared: TypedStorage & {\n /** 获取全局共享存储数据 */\n get: TypedStorage['get'];\n /** 设置全局共享存储数据 */\n set: TypedStorage['set'];\n /** 移除全局共享存储数据 */\n remove: TypedStorage['remove'];\n };\n}\n\n/**\n * 插件生命周期 Hooks\n * @description 插件可以在不同的生命周期阶段执行特定的逻辑\n */\nexport interface PluginLifecycle {\n /**\n * 插件加载时调用\n * @description 在插件被扫描并注入内核时触发。用于初始化内部状态、注册服务、设置拦截器等。此时 UI 尚未挂载。\n * @param context - 插件上下文对象,提供核心能力的访问\n */\n onLoad?: (context: PluginContext) => void | Promise<void>;\n\n /**\n * 插件挂载到 UI 时调用\n * @description 当插件的 UI 组件(如有)被 React 挂载到 DOM 时触发。\n * @param context - 插件上下文对象\n */\n onMount?: (context: PluginContext) => void;\n\n /**\n * 插件从 UI 卸载时调用\n * @description 当插件的 UI 组件被销毁时触发。用于清理定时器、取消订阅等。\n * @param context - 插件上下文对象\n */\n onUnmount?: (context: PluginContext) => void;\n\n /**\n * 插件配置发生变化时调用\n * @description 当用户通过配置中心修改插件设置时触发。\n * @param newConfig - 变更后的新配置对象\n * @param oldConfig - 变更前的旧配置对象\n */\n onConfigChange?: (newConfig: any, oldConfig: any) => void;\n}\n\n/**\n * 插件上下文\n * @description 传递给插件生命周期钩子的核心对象,是插件访问宿主环境能力的唯一入口。\n */\nexport interface PluginContext {\n /** 当前插件的唯一标识符 */\n pluginId: string;\n /** API 请求能力入口 */\n api: any;\n /** 事件总线能力入口 */\n events: EventBusPort;\n /** 存储管理能力入口 */\n storage: PluginStorage;\n /** 日志输出工具,自动携带插件 ID 前缀 */\n logger: {\n debug: (...args: any[]) => void;\n info: (...args: any[]) => void;\n warn: (...args: any[]) => void;\n error: (...args: any[]) => void;\n };\n /** \n * 访问其他插件提供的服务\n * @param serviceName - 服务注册名称\n * @returns 服务实例,如果不存在则返回 undefined\n */\n getService: <T = any>(serviceName: string) => T | undefined;\n /** \n * 注册当前插件的服务供他人使用\n * @param serviceName - 唯一服务名称\n * @param service - 服务实现对象\n */\n registerService: (serviceName: string, service: any) => void;\n /** 宿主环境 Window 的代理对象 (用于沙箱隔离) */\n window: WindowProxy;\n}\n\n/**\n * 完整的插件对象定义\n */\nexport interface Plugin extends PluginLifecycle {\n /** \n * 插件唯一标识符\n * @description 必须与 metadata.id 一致,通常为只读。\n */\n readonly id: string;\n /** 插件元数据配置 */\n metadata: PluginMetadata;\n /** 插件提供的功能组件集合 (可选) */\n components?: Record<string, React.ComponentType<any>>;\n /** 插件提供的工具函数集合 (可选) */\n utils?: Record<string, any>;\n /** 插件的初始默认配置 (可选) */\n defaultConfig?: Record<string, any>;\n}\n\n/**\n * 插件基础类\n * @deprecated 建议统一使用工厂模式 definePlugin() 定义插件,以消除类与对象定义的歧义。\n * @description 解决插件定义时 id 与 metadata.id 重复定义的问题,并提供基础生命周期管理\n */\nexport abstract class BasePlugin implements Plugin {\n abstract metadata: PluginMetadata;\n \n /** \n * 插件 ID\n * @description 自动从 metadata.id 获取\n */\n get id(): string {\n return this.metadata.id;\n }\n\n onLoad?(context: PluginContext): void | Promise<void>;\n onMount?(context: PluginContext): void;\n onUnmount?(context: PluginContext): void;\n onConfigChange?(newConfig: any, oldConfig: any): void;\n}\n\n/**\n * 辅助函数:定义插件并自动从 metadata.id 注入顶级 id\n * @description 解决插件定义时 id 与 metadata.id 重复定义的问题,提高代码优雅度\n * @param plugin 插件定义(不包含顶级 id)\n * @returns 完整的插件对象\n */\nexport function definePlugin(plugin: Omit<Plugin, 'id'>): Plugin {\n return {\n ...plugin,\n get id() { return this.metadata.id; }\n } as Plugin;\n}\n\n/**\n * 插件元数据定义\n * @description 描述插件的静态属性,用于插件市场展示、权限校验和内核加载参考。\n */\nexport interface PluginMetadata {\n /** 插件唯一 ID (推荐反向域名格式,如 com.company.plugin) */\n id: string;\n /** 插件显示名称 */\n name: string;\n /** 插件版本号 (符合 SemVer 规范) */\n version: string;\n /** 插件类型 */\n type: PluginType;\n /** 插件功能描述 */\n description?: string;\n /** 插件作者信息 */\n author?: string;\n /** 插件图标 (React 组件或图标名称) */\n icon?: React.ReactNode;\n /** 插件依赖的其他插件 ID 列表 */\n dependencies?: string[];\n /** 路由配置集合,用于在主应用中注册页面 */\n routes?: RouteConfig[];\n /** 插槽扩展集合,用于在主应用 UI 预留位注入组件 */\n extensions?: PluginExtension[];\n /** 插件所需调用的 API 接口配置 */\n api?: ApiConfig;\n /** 插件行为能力声明 */\n capabilities?: PluginCapabilities;\n /** 插件的可配置项定义 */\n configuration?: PluginConfigItem[];\n /** 插件所需的存储结构定义 */\n storage?: StorageItemSchema[];\n /** \n * 系统状态自动绑定\n * @description 将插件的配置项自动同步到系统的全局状态中 (如主题色、身份认证等)\n */\n systemStateBindings?: {\n /** 插件配置中的键名 */\n configKey: string;\n /** 系统全局状态中的键名 */\n stateKey: string;\n /** 预设的转换逻辑名称 */\n transform?: 'theme-mode' | 'identity';\n }[];\n}\n","/**\n * 日志等级枚举\n */\nexport enum LogLevel {\n /** 调试级别:输出最详尽的信息 */\n DEBUG = 0,\n /** 信息级别:输出重要的运行状态 */\n INFO = 1,\n /** 警告级别:输出潜在的问题,但不影响运行 */\n WARN = 2,\n /** 错误级别:输出严重的运行异常 */\n ERROR = 3,\n /** 禁用日志:不输出任何信息 */\n NONE = 4,\n}\n\n/**\n * 日志条目结构\n */\ninterface LogEntry {\n level: LogLevel;\n prefix: string;\n message: any[];\n timestamp: number;\n}\n\n/**\n * 简单的颜色生成器 (djb2 hash)\n */\nfunction getColorForString(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = (hash << 5) + hash + str.charCodeAt(i);\n }\n // 生成 HSL 颜色,保持较高的饱和度和亮度,适合深/浅色主题\n const hue = Math.abs(hash % 360);\n return `hsl(${hue}, 70%, 45%)`;\n}\n\n/**\n * 简单的 ANSI 颜色代码 (Node.js 环境)\n */\nconst ANSI = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n colors: [\n '\\x1b[31m', // Red\n '\\x1b[32m', // Green\n '\\x1b[33m', // Yellow\n '\\x1b[34m', // Blue\n '\\x1b[35m', // Magenta\n '\\x1b[36m', // Cyan\n ]\n};\n\nfunction getAnsiColorForString(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = str.charCodeAt(i) + ((hash << 5) - hash);\n }\n const index = Math.abs(hash % ANSI.colors.length);\n return ANSI.colors[index];\n}\n\n/**\n * 日志工具类\n * @description 核心工具类,提供统一的日志输出格式 `[Prefix] Message`。\n * 支持通过 `LogLevel` 进行全局过滤。\n * 支持日志缓冲和自动分组,以减少控制台噪音。\n * 支持浏览器端 CSS 样式和 Node.js 端 ANSI 颜色。\n */\nexport class Logger {\n /** 全局静态日志等级,所有实例共享 */\n private static level: LogLevel = LogLevel.INFO;\n \n /** 日志缓冲区 */\n private static buffer: LogEntry[] = [];\n \n /** 缓冲输出防抖定时器 */\n private static flushTimer: any = null;\n \n /** 缓冲时间窗口 (ms) */\n private static FLUSH_INTERVAL = 100;\n\n /** 是否启用缓冲模式 */\n private static bufferEnabled = true;\n\n /** 是否为浏览器环境 */\n private static isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';\n\n /** 当前实例的业务模块前缀 */\n private prefix: string;\n\n /** 实例特定的颜色 */\n private color: string;\n\n /**\n * 构造函数\n * @param prefix - 业务模块前缀,默认为 'App'\n */\n constructor(prefix: string = 'App') {\n this.prefix = prefix;\n this.color = getColorForString(prefix);\n }\n\n /**\n * 静态方法:设置全局日志输出等级\n * @param level - 目标日志等级\n */\n static setLevel(level: LogLevel) {\n this.level = level;\n console.log(`[Logger] Global log level set to: ${LogLevel[level]}`);\n }\n\n /**\n * 静态方法:启用或禁用日志缓冲\n * @param enabled - 是否启用\n */\n static setBufferEnabled(enabled: boolean) {\n this.bufferEnabled = enabled;\n if (!enabled) {\n this.flush();\n }\n }\n\n /**\n * 静态方法:获取当前全局日志等级\n * @returns 当前生效的全局日志等级\n */\n static getLevel(): LogLevel {\n return this.level;\n }\n\n /**\n * 格式化输出前缀\n */\n private getFormattedPrefix(prefix: string, level: LogLevel): any[] {\n if (Logger.isBrowser) {\n const color = getColorForString(prefix);\n // Badge 风格样式\n const style = [\n `background: ${color}`,\n 'color: white',\n 'border-radius: 3px',\n 'padding: 2px 6px',\n 'font-weight: bold',\n 'font-family: monospace'\n ].join(';');\n \n return [`%c ${prefix} `, style];\n } else {\n // Node.js 环境 ANSI 颜色\n const colorCode = getAnsiColorForString(prefix);\n return [`${colorCode}[${prefix}]${ANSI.reset}`];\n }\n }\n\n /**\n * 生成分组标题参数\n */\n private static getGroupTitleArgs(prefix: string, count: number, countDetails: string = ''): any[] {\n if (Logger.isBrowser) {\n const color = getColorForString(prefix);\n const badgeStyle = `background: ${color}; color: white; border-radius: 3px; padding: 2px 6px; font-weight: bold;`;\n const titleStyle = `color: ${color}; font-weight: bold;`;\n const countStyle = 'color: gray; font-size: 0.9em;';\n \n const countStr = count > 0 ? `(${count > 1 ? count + ' messages' : '1 message'}${countDetails ? ', ' + countDetails : ''})` : '';\n \n return [`%c ${prefix} %c ${countStr}`, badgeStyle, countStyle];\n } else {\n const colorCode = getAnsiColorForString(prefix);\n const countStr = count > 0 ? `(${count > 1 ? count + ' messages' : '1 message'}${countDetails ? ', ' + countDetails : ''})` : '';\n return [`${colorCode}[${prefix}]${ANSI.reset} ${ANSI.dim}${countStr}${ANSI.reset}`];\n }\n }\n\n /**\n * 内部方法:将日志推入缓冲区或直接输出\n */\n private log(level: LogLevel, ...args: any[]) {\n if (Logger.level > level) return;\n\n if (level === LogLevel.ERROR) {\n Logger.flush();\n const prefixArgs = this.getFormattedPrefix(this.prefix, level);\n console.error(...prefixArgs, ...args);\n return;\n }\n\n if (!Logger.bufferEnabled) {\n // 非缓冲模式也统一使用 group 输出,保持界面整洁\n const method = level === LogLevel.WARN ? 'warn' : level === LogLevel.DEBUG ? 'debug' : 'info';\n const groupArgs = Logger.getGroupTitleArgs(this.prefix, 1);\n \n console.groupCollapsed(...groupArgs);\n console[method](...args);\n console.groupEnd();\n return;\n }\n\n Logger.buffer.push({\n level,\n prefix: this.prefix,\n message: args,\n timestamp: Date.now(),\n });\n\n if (!Logger.flushTimer) {\n Logger.flushTimer = setTimeout(() => {\n Logger.flush();\n }, Logger.FLUSH_INTERVAL);\n }\n }\n\n /**\n * 静态方法:刷新缓冲区,分组输出日志\n */\n static flush() {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n\n if (this.buffer.length === 0) return;\n\n const groups = new Map<string, LogEntry[]>();\n const prefixOrder: string[] = [];\n\n this.buffer.forEach(entry => {\n if (!groups.has(entry.prefix)) {\n groups.set(entry.prefix, []);\n prefixOrder.push(entry.prefix);\n }\n groups.get(entry.prefix)!.push(entry);\n });\n\n prefixOrder.forEach(prefix => {\n const entries = groups.get(prefix)!;\n \n // 统计各级别数量\n const counts = entries.reduce((acc, curr) => {\n const key = curr.level === LogLevel.WARN ? 'warn' : 'info';\n acc[key] = (acc[key] || 0) + 1;\n return acc;\n }, {} as Record<string, number>);\n \n const countDetails = Object.entries(counts)\n .map(([k, v]) => `${v} ${k}`)\n .join(', ');\n\n // 无论条数多少,统一使用折叠分组\n const groupTitleArgs = Logger.getGroupTitleArgs(prefix, entries.length, entries.length > 1 ? countDetails : '');\n\n console.groupCollapsed(...groupTitleArgs);\n entries.forEach(entry => {\n const method = entry.level === LogLevel.WARN ? 'warn' : entry.level === LogLevel.DEBUG ? 'debug' : 'info';\n // 组内日志不再显示前缀,保持清爽\n console[method](...entry.message);\n });\n console.groupEnd();\n });\n\n this.buffer = [];\n }\n\n /**\n * 打印 DEBUG 级别日志\n */\n debug(...args: any[]) {\n this.log(LogLevel.DEBUG, ...args);\n }\n\n /**\n * 打印 INFO 级别日志\n */\n info(...args: any[]) {\n this.log(LogLevel.INFO, ...args);\n }\n\n /**\n * 打印 WARN 级别日志\n */\n warn(...args: any[]) {\n this.log(LogLevel.WARN, ...args);\n }\n\n /**\n * 打印 ERROR 级别日志\n */\n error(...args: any[]) {\n this.log(LogLevel.ERROR, ...args);\n }\n\n /**\n * 开始一个日志控制台分组\n */\n group(label: string, collapsed: boolean = false) {\n if (Logger.level <= LogLevel.INFO) {\n Logger.flush();\n const prefixArgs = this.getFormattedPrefix(this.prefix, LogLevel.INFO);\n // 这里的 group 只能简单输出,无法像 flush 那样做复杂的样式组合,因为 label 是用户传的\n if (Logger.isBrowser) {\n if (collapsed) {\n console.groupCollapsed(...prefixArgs, label);\n } else {\n console.group(...prefixArgs, label);\n }\n } else {\n const title = `${prefixArgs[0]} ${label}`;\n if (collapsed) {\n console.groupCollapsed(title);\n } else {\n console.group(title);\n }\n }\n }\n }\n\n /**\n * 结束当前日志控制台分组\n */\n groupEnd() {\n if (Logger.level <= LogLevel.INFO) {\n Logger.flush();\n console.groupEnd();\n }\n }\n}\n\n/** 默认 Logger 实例 */\nexport const logger = new Logger();\n\n/**\n * 创建带特定前缀的 Logger 实例\n * @param prefix 日志前缀\n * @returns Logger 实例\n */\nexport const createLogger = (prefix: string) => new Logger(prefix);\n","import { createLogger } from '../utils/logger';\n\nconst logger = createLogger('ServiceRegistry');\n\n/**\n * 服务注册中心 (Service Registry)\n * @description 核心应用层服务,作为微内核架构中的“中枢调度员”。\n * 主要职责:\n * 1. 服务解耦:允许插件将其内部功能暴露为“服务”,而无需与其他插件产生物理依赖。\n * 2. 动态发现:提供按名称查找服务的能力,支持服务热插拔。\n * 3. 依赖协调:通过 `waitFor` 机制解决插件间由于加载顺序导致的初始化依赖问题。\n * \n * 建议的服务命名规范: `pluginId.serviceName` (例如: `auth.sessionService`)\n */\nexport class ServiceRegistry {\n /** 存储已注册服务的 Map 对象 */\n private services = new Map<string, any>();\n /** 存储正在等待特定服务的监听器集合 */\n private listeners = new Map<string, Set<(service: any) => void>>();\n\n /**\n * 注册一个服务实现\n * @param name - 唯一的服务名称\n * @param service - 服务实例或对象\n */\n register(name: string, service: any) {\n if (this.services.has(name)) {\n logger.warn(`服务 \"${name}\" 已存在,将被覆盖`);\n }\n this.services.set(name, service);\n logger.info(`服务已注册: ${name}`);\n\n // 通知正在等待该服务的监听器\n if (this.listeners.has(name)) {\n const set = this.listeners.get(name)!;\n set.forEach(callback => callback(service));\n this.listeners.delete(name);\n }\n }\n\n /**\n * 同步获取服务实例\n * @template T - 服务类型的泛型\n * @param name - 服务名称\n * @returns 服务实例,若不存在则返回 undefined\n */\n get<T = any>(name: string): T | undefined {\n return this.services.get(name);\n }\n\n /**\n * 异步等待并获取服务\n * @description 如果服务尚未注册,将返回一个 Promise,直到该服务被注册时 resolve。\n * 支持设置超时时间,防止因插件加载失败导致的永久挂起。\n * \n * @template T - 服务类型的泛型\n * @param name - 待等待的服务名称\n * @param timeout - 超时时间 (毫秒),默认 10000ms (10秒)。若为 0 则永不超时。\n * @returns 包含服务实例的 Promise\n * @throws {Error} 若在规定时间内服务未注册,则抛出超时异常。\n */\n async waitFor<T = any>(name: string, timeout: number = 10000): Promise<T> {\n const service = this.services.get(name);\n if (service) return service;\n\n return new Promise((resolve, reject) => {\n let timer: any = null;\n\n const callback = (s: T) => {\n if (timer) clearTimeout(timer);\n resolve(s);\n };\n\n if (!this.listeners.has(name)) {\n this.listeners.set(name, new Set());\n }\n this.listeners.get(name)!.add(callback);\n\n // 超时处理\n if (timeout > 0) {\n timer = setTimeout(() => {\n const set = this.listeners.get(name);\n if (set) {\n set.delete(callback);\n if (set.size === 0) this.listeners.delete(name);\n }\n reject(new Error(`等待服务 \"${name}\" 超时 (${timeout}ms)`));\n }, timeout);\n }\n });\n }\n\n /**\n * 检查服务是否已注册\n * @param name - 服务名称\n */\n has(name: string): boolean {\n return this.services.has(name);\n }\n\n /**\n * 注销特定的服务\n * @param name - 服务名称\n */\n unregister(name: string) {\n this.services.delete(name);\n logger.info(`服务已注销: ${name}`);\n }\n\n /**\n * 清除所有已注册的服务和监听器\n * @description 通常仅在系统重置或大型热更新时使用。\n */\n clear() {\n this.services.clear();\n this.listeners.clear();\n }\n}\n\n// 导出单例\nexport const serviceRegistry = new ServiceRegistry();\n","import React, { createContext, useContext } from 'react';\n\nimport type { ApiEngine } from './api';\n\nconst ApiContext = createContext<ApiEngine | null>(null);\n\nexport interface ApiProviderProps {\n api: ApiEngine;\n children: React.ReactNode;\n}\n\nexport const ApiProvider: React.FC<ApiProviderProps> = ({ api, children }) => {\n return <ApiContext.Provider value={api}>{children}</ApiContext.Provider>;\n};\n\nexport const useApi = () => {\n const context = useContext(ApiContext);\n if (!context) {\n throw new Error('useApi must be used within an ApiProvider');\n }\n return context;\n};\n","import React, { Component, ErrorInfo, ReactNode } from 'react';\n\nimport { pluginManager } from '../domain/plugin-manager';\nimport { createLogger } from '../utils/logger';\n\nconst logger = createLogger('PluginErrorBoundary');\n\n/** 插件错误边界组件属性 */\ninterface Props {\n /** 发生错误的插件 ID */\n pluginId?: string;\n /** 错误发生时的降级 UI */\n fallback?: ReactNode;\n /** 子组件内容 */\n children: ReactNode;\n /** 是否静默模式,开启后不显示任何错误 UI,仅记录日志 */\n silent?: boolean;\n}\n\n/** 插件错误边界组件状态 */\ninterface State {\n /** 是否捕获到错误 */\n hasError: boolean;\n /** 捕获到的错误对象 */\n error: Error | null;\n}\n\n/**\n * 插件错误边界组件\n * @description 核心组件,用于捕获子组件渲染过程中的 JavaScript 错误,记录日志并显示降级 UI。\n * 确保单个插件的运行异常不会导致整个主应用或其他插件崩溃。\n */\nexport class PluginErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n /**\n * 从错误中派生状态\n * @param error - 捕获到的错误\n */\n static getDerivedStateFromError(error: any): State {\n // 忽略 Suspense 导致的错误,让 React 正常处理 Suspense\n if (error && typeof error.then === 'function') {\n return { hasError: false, error: null };\n }\n return { hasError: true, error: error instanceof Error ? error : new Error(String(error)) };\n }\n\n /**\n * 捕获到错误后的回调\n * @param error - 错误对象\n * @param errorInfo - 错误堆栈信息\n */\n componentDidCatch(error: any, errorInfo: ErrorInfo) {\n // 忽略 Suspense 导致的错误\n if (error && typeof error.then === 'function') {\n return;\n }\n \n logger.error(`插件 ${this.props.pluginId || '未知'} 渲染发生错误:`, error, errorInfo);\n \n // 如果有 pluginId,尝试在控制台输出更友好的提示,并上报给管理器\n if (this.props.pluginId) {\n console.warn(`[PluginError] 插件 \"${this.props.pluginId}\" 渲染失败。您可以在插件管理面板查看详细信息。`);\n \n // 直接上报插件 ID\n pluginManager.reportPluginError(this.props.pluginId, error);\n }\n }\n\n /**\n * 重置错误状态,尝试重新渲染\n */\n handleRetry = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n if (this.props.silent) {\n return null;\n }\n\n // 默认提供一个极其简约的占位,避免破坏布局,同时通过 data 属性暴露错误信息供调试\n return (\n <div \n className=\"plugin-error-placeholder hidden\" \n data-plugin-id={this.props.pluginId} \n data-error={this.state.error?.message}\n />\n );\n }\n\n return this.props.children;\n }\n}\n","/**\n * @file plugin-manager.ts\n * @description 插件管理器,负责插件的注册、生命周期管理、状态持久化及扩展点收集\n * @author ChatBI Team\n */\n\nimport { startTransition } from 'react';\nimport { LocalStorageAdapter } from '../adapters/local-storage-adapter';\nimport { configManager } from '../config-manager';\nimport { DefaultEventBus } from '../event-bus';\nimport { serviceRegistry } from '../application/service-registry';\nimport {\n Plugin,\n PLUGIN_TYPES,\n PluginExtension,\n RouteConfig,\n SlotPosition,\n StorageItemSchema,\n} from '../ports/plugin-port';\nimport { StoragePort } from '../ports/storage-port';\nimport { createLogger } from '../utils/logger';\nimport { PluginRuntime } from './plugin-runtime';\nimport { StorageManager } from './storage-manager';\n\nconst logger = createLogger('PluginManager');\n\n/**\n * 插件管理器\n * @description 核心领域服务,负责插件的完整生命周期管理,包括扫描、注册、配置合并、状态切换及依赖解析。\n */\nexport class PluginManager {\n /** 全局事件总线,用于插件间及插件与内核间的异步通信 */\n public readonly eventBus = new DefaultEventBus();\n\n /** 存储管理服务,负责插件私有存储和系统级状态的持久化 */\n private storageManager: StorageManager;\n\n /** 插件 ID 到运行时实例的映射表 */\n private runtimes = new Map<string, PluginRuntime>();\n /** 插件 ID 到原始插件定义对象的映射表 */\n private plugins = new Map<string, Plugin>();\n /** 收集到的所有插件路由配置 */\n private routes: RouteConfig[] = [];\n /** 收集到的所有插件扩展点配置,按插槽位置分组 */\n private extensions: Map<SlotPosition, PluginExtension[]> = new Map();\n /** 插件的启用状态和排序信息的内存缓存 */\n private pluginStates: Record<string, { enabled: boolean; order: number }> = {};\n /** 状态变更监听器集合,支持按插槽过滤 */\n private listeners: Set<() => void> = new Set();\n /** 按插槽位置存储的监听器,用于精确通知 */\n private slotListeners: Map<string, Set<() => void>> = new Map();\n /** 扩展点缓存,避免重复计算 */\n private memoizedExtensions: Map<string, PluginExtension[]> = new Map();\n /** 路由缓存 */\n private memoizedRoutes: RouteConfig[] | null = null;\n /** 传递给插件的共享上下文缓存 */\n private sharedContext: Record<string, any> | null = null;\n /** 收集到的插件工具函数集合 */\n private utils: Record<string, any> = {};\n\n /** 是否正在初始化插件中,防止重入导致多次加载 */\n private isInitializing = false;\n\n /**\n * 构造函数\n * @param storage - 底层存储适配器\n */\n constructor(storage: StoragePort) {\n this.storageManager = new StorageManager(storage);\n\n // 1. 加载持久化的插件状态\n this.loadStates();\n\n // 2. 订阅状态变更以持久化\n this.subscribe(() => {\n this.saveStates();\n });\n }\n\n /**\n * 从持久化存储中恢复插件状态 (启用/禁用、排序等)\n */\n private loadStates() {\n try {\n const systemStorage = this.storageManager.getSystemStorage();\n\n // 1. 优先尝试从新位置 (system:plugin_states) 读取\n const savedStates = systemStorage.getItem('plugin_states');\n\n if (savedStates) {\n this.pluginStates = JSON.parse(savedStates);\n logger.debug('从系统存储中加载状态:', this.pluginStates);\n }\n } catch (e) {\n logger.error('加载插件状态失败:', e);\n }\n }\n\n /**\n * 将当前的插件状态持久化到存储中\n */\n private saveStates() {\n try {\n this.storageManager\n .getSystemStorage()\n .setItem('plugin_states', JSON.stringify(this.pluginStates));\n logger.debug('已保存插件状态到存储');\n } catch (e) {\n logger.error('保存插件状态失败:', e);\n }\n }\n\n /**\n * 订阅插件状态的变更通知\n * @param listener - 变更时的回调函数\n * @param slot - (可选) 指定监听的插槽位置,若提供则仅在该插槽受影响时通知\n * @returns 取消订阅的函数\n */\n subscribe(listener: () => void, slot?: SlotPosition | string) {\n if (slot) {\n const slotStr = String(slot);\n if (!this.slotListeners.has(slotStr)) {\n this.slotListeners.set(slotStr, new Set());\n }\n this.slotListeners.get(slotStr)!.add(listener);\n return () => {\n this.slotListeners.get(slotStr)?.delete(listener);\n };\n } else {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n }\n\n /**\n * 获取存储管理器实例\n * @returns StorageManager 实例\n */\n getStorageManager() {\n return this.storageManager;\n }\n\n /**\n * 触发状态变更通知\n * @param affectedSlot - (可选) 受影响的插槽位置\n */\n private notify(affectedSlot?: SlotPosition | string) {\n // 使用 startTransition 包裹通知,避免 Suspense 导致的同步渲染错误\n startTransition(() => {\n // 1. 清除受影响或全部的缓存\n if (affectedSlot) {\n this.memoizedExtensions.delete(String(affectedSlot));\n } else {\n this.memoizedExtensions.clear();\n this.memoizedRoutes = null;\n }\n\n // 2. 通知全局监听器\n this.listeners.forEach((listener) => listener());\n\n // 3. 通知特定插槽监听器\n if (affectedSlot) {\n this.slotListeners.get(String(affectedSlot))?.forEach(listener => listener());\n } else {\n // 如果没有指定插槽,通知所有插槽监听器\n this.slotListeners.forEach(set => set.forEach(listener => listener()));\n }\n });\n }\n\n /**\n * 获取所有已注册的插件列表\n * @description 结果会根据插件类型优先级和用户自定义排序进行排序\n * @returns 排序后的插件数组\n */\n getPlugins() {\n const typePriority: Record<string, number> = {\n system: 0,\n theme: 1,\n renderer: 2,\n functional: 3,\n business: 4,\n view: 5,\n };\n\n // 按照类型优先级和 order 排序\n return Array.from(this.plugins.values()).sort((a, b) => {\n const priorityA = typePriority[a.metadata.type] ?? 99;\n const priorityB = typePriority[b.metadata.type] ?? 99;\n\n if (priorityA !== priorityB) {\n return priorityA - priorityB;\n }\n\n const stateA = this.pluginStates[a.id] || { order: 0 };\n const stateB = this.pluginStates[b.id] || { order: 0 };\n return stateA.order - stateB.order;\n });\n }\n\n /**\n * 获取指定插件的状态信息\n * @param pluginId - 插件 ID\n * @returns 包含启用状态和排序值的对象\n */\n getPluginState(pluginId: string) {\n return this.pluginStates[pluginId] || { enabled: true, order: 0 };\n }\n\n /**\n * 检查指定插件是否处于启用状态\n * @param pluginId - 插件 ID\n * @returns 是否启用\n */\n isPluginEnabled(pluginId: string) {\n const state = this.pluginStates[pluginId];\n return state ? state.enabled : true;\n }\n\n /**\n * 切换插件的启用/禁用状态\n * @description 禁用插件会立即触发其卸载生命周期并销毁运行时。\n * @param pluginId - 插件 ID\n * @param enabled - 目标状态\n */\n togglePlugin(pluginId: string, enabled: boolean) {\n const state = this.pluginStates[pluginId] || { enabled: true, order: 0 };\n this.pluginStates[pluginId] = { ...state, enabled };\n\n // 如果是禁用,卸载运行时\n if (!enabled) {\n const runtime = this.runtimes.get(pluginId);\n if (runtime) {\n runtime.unmount();\n this.runtimes.delete(pluginId);\n }\n } else {\n // 如果是启用,初始化运行时\n // 注意:这里需要确保 initPlugins 已经被调用过,有 sharedContext\n if (this.sharedContext) {\n const plugin = this.plugins.get(pluginId);\n if (plugin) {\n try {\n const runtime = new PluginRuntime(plugin, this.sharedContext, this.storageManager);\n this.runtimes.set(pluginId, runtime);\n runtime.mount();\n } catch (e) {\n logger.error(`启用插件 ${pluginId} 失败:`, e);\n }\n }\n }\n }\n\n this.notify();\n }\n\n /**\n * 设置插件的显示排序权重\n * @param pluginId - 插件 ID\n * @param order - 排序权重值\n */\n setPluginOrder(pluginId: string, order: number) {\n const state = this.pluginStates[pluginId] || { enabled: true, order: 0 };\n this.pluginStates[pluginId] = { ...state, order };\n this.notify();\n }\n\n /**\n * 获取指定插件的运行时状态\n * @param pluginId - 插件 ID\n * @returns 'error' | 'mounted' | 'loaded' | 'initial'\n */\n getPluginRuntimeStatus(pluginId: string) {\n const runtime = this.runtimes.get(pluginId);\n return runtime ? runtime.status : 'initial';\n }\n\n /**\n * 获取指定插件的运行时错误\n * @param pluginId - 插件 ID\n * @returns Error 对象或 null\n */\n getPluginError(pluginId: string) {\n const runtime = this.runtimes.get(pluginId);\n return runtime ? runtime.getError() : null;\n }\n\n /**\n * 报告插件运行时错误 (通常由 ErrorBoundary 调用)\n * @param pluginId - 插件 ID\n * @param error - 错误对象\n */\n reportPluginError(pluginId: string, error: Error) {\n const runtime = this.runtimes.get(pluginId);\n if (runtime) {\n // 这里的实现需要 PluginRuntime 支持外部设置错误\n (runtime as any)._setError?.(error);\n this.notify();\n }\n }\n\n /**\n * 获取插件的完整能力声明\n * @param pluginId - 插件 ID\n * @returns 能力对象\n */\n getUnifiedCapabilities(pluginId: string) {\n const plugin = this.plugins.get(pluginId);\n return plugin?.metadata.capabilities || {};\n }\n\n /**\n * 更新指定插件的某项配置\n * @description 该操作会同步更新内存中的配置、持久化到存储并触发全局事件通知。\n * @param pluginId - 插件 ID\n * @param key - 配置键名\n * @param value - 新的配置值\n */\n updatePluginConfig(pluginId: string, key: string, value: any) {\n // 1. 更新 ConfigManager (Runtime)\n const currentConfig = configManager.get(pluginId) || {};\n currentConfig[key] = value;\n configManager.set(pluginId, currentConfig);\n\n // 2. 持久化到存储 (使用 StorageManager)\n try {\n this.storageManager.getContextStorage(pluginId).set(key, value);\n } catch (e) {\n logger.warn('保存配置到存储失败', e);\n }\n\n // 3. 通过 EventBus 分发事件\n this.eventBus.emit('config:changed', { pluginId, key, value });\n }\n\n /**\n * 获取指定插件的某项配置值\n * @param pluginId - 插件 ID\n * @param key - 配置键名\n * @returns 配置值\n */\n getPluginConfig(pluginId: string, key: string): any {\n const config = configManager.get(pluginId);\n return config ? config[key] : undefined;\n }\n\n /**\n * 获取系统全局配置 (非插件特定)\n * @param key - 系统配置键名\n * @returns 配置值\n */\n getSystemConfig(key: string): any {\n const systemConfig = configManager.get('system');\n return systemConfig ? systemConfig[key] : undefined;\n }\n\n /**\n * 获取由插件注册的服务实例\n * @template T 服务接口类型\n * @param name - 服务注册名称\n * @returns 服务实例或 undefined\n */\n getService<T = any>(name: string): T | undefined {\n return serviceRegistry.get<T>(name);\n }\n\n /**\n * 获取指定插槽位置的所有已启用插件的扩展\n * @param slot - 插槽位置标识\n * @returns 排序后的扩展配置数组\n */\n getExtensions(slot: SlotPosition | string): PluginExtension[] {\n const slotStr = String(slot);\n \n // 1. 优先从缓存获取\n if (this.memoizedExtensions.has(slotStr)) {\n return this.memoizedExtensions.get(slotStr)!;\n }\n\n // 2. 计算扩展点\n const targetSlot = slot as SlotPosition;\n let extensions = this.extensions.get(targetSlot) || [];\n\n // 过滤掉已禁用插件的扩展\n extensions = extensions.filter((ext) => {\n const pluginId = ext._pluginId;\n return !pluginId || this.isPluginEnabled(pluginId);\n });\n\n // 排序\n const sortedExtensions = extensions.sort((a, b) => (a.order || 0) - (b.order || 0));\n \n // 3. 写入缓存\n this.memoizedExtensions.set(slotStr, sortedExtensions);\n \n return sortedExtensions;\n }\n\n /**\n * 获取所有已启用插件注册的路由配置\n * @returns 增强后的路由配置数组\n */\n getRoutes(): RouteConfig[] {\n // 1. 优先从缓存获取\n if (this.memoizedRoutes) {\n return this.memoizedRoutes;\n }\n\n // 2. 计算路由\n const activeRoutes: RouteConfig[] = [];\n this.getPlugins().forEach((plugin) => {\n if (this.isPluginEnabled(plugin.id) && plugin.metadata.routes) {\n // 获取该插件的当前配置,并注入到路由 meta 中\n const config = configManager.get(plugin.id) || {};\n \n plugin.metadata.routes.forEach(route => {\n activeRoutes.push({\n ...route,\n meta: {\n ...route.meta,\n pluginId: plugin.id,\n config: config,\n }\n });\n });\n }\n });\n\n // 3. 写入缓存\n this.memoizedRoutes = activeRoutes;\n \n return activeRoutes;\n }\n\n /**\n * 注册一个新插件到管理器中\n * @description 此阶段会执行元数据校验、存储 Schema 注册、配置合并及扩展点收集。\n * @param plugin - 插件对象\n * @param notify - 是否在注册完成后触发状态变更通知\n */\n register(plugin: Plugin, notify = true) {\n if (!this.validatePlugin(plugin)) {\n logger.error(`插件注册失败: ${plugin?.id || '未知'}`);\n return;\n }\n\n if (this.plugins.has(plugin.id)) {\n // 允许热更新:如果插件已存在且内容不同,则更新;否则跳过\n // 目前简单处理:仅输出日志并跳过,避免重复注册警告视为错误\n // logger.debug(`插件 ${plugin.id} 已注册,跳过。`);\n return;\n }\n\n // 注册存储 Schema (合并 storage 和 configuration 定义)\n const storageSchema: StorageItemSchema[] = [\n ...(plugin.metadata.storage || []),\n ...(plugin.metadata.configuration?.map(c => ({\n key: c.key,\n // 将 configuration 的 type 映射为 storage 支持的类型\n type: (c.type === 'select' ? 'string' : c.type) as any,\n label: c.label,\n description: c.description,\n default: c.default,\n scope: 'plugin' as const\n })) || [])\n ];\n \n if (storageSchema.length > 0) {\n this.storageManager.registerSchema(plugin.id, storageSchema);\n }\n\n // 默认状态逻辑:如果存储中没有状态,默认为启用\n if (!this.pluginStates[plugin.id]) {\n this.pluginStates[plugin.id] = { enabled: true, order: 0 };\n }\n\n // --- 加载并合并配置 ---\n const metadataDefaults: Record<string, any> = {};\n const userOverrides: Record<string, any> = {};\n const pluginStorage = this.storageManager.getPluginStorage(plugin.id);\n\n // 1. 提取元数据中的默认值\n if (plugin.metadata.configuration) {\n plugin.metadata.configuration.forEach((item) => {\n if (item.default !== undefined) {\n metadataDefaults[item.key] = item.default;\n }\n\n // 2. 提取持久化存储中的用户设置 (如果有)\n try {\n const saved = pluginStorage.getItem(item.key);\n if (saved !== null) {\n userOverrides[item.key] = JSON.parse(saved);\n }\n } catch (e) {\n // 忽略解析错误\n }\n });\n }\n\n // 3. 合并逻辑 (优先级从低到高):\n // 1. 元数据默认 (来自 plugin.metadata.configuration)\n // 2. 插件自带默认 (plugin.defaultConfig)\n // 3. 外部传入配置 (来自 chatbi.config.ts, 已存入 configManager)\n // 4. 用户持久化设置 (来自 localStorage)\n const mergedConfig = {\n ...metadataDefaults,\n ...plugin.defaultConfig,\n ...(configManager.get(plugin.id) || {}),\n ...userOverrides,\n };\n\n // 将合并后的配置同步到 ConfigManager,供 runtime 使用\n configManager.set(plugin.id, mergedConfig);\n\n // 根据类型处理\n switch (plugin.metadata.type) {\n case 'business':\n this.handleBusinessPlugin(plugin);\n break;\n case 'functional':\n this.handleFunctionalPlugin(plugin);\n break;\n case 'view':\n this.handleViewPlugin(plugin);\n break;\n case 'theme':\n this.handleThemePlugin(plugin);\n break;\n case 'system':\n this.handleSystemPlugin(plugin);\n break;\n case 'renderer':\n break;\n default:\n logger.warn(`插件 ${plugin.id} 类型未知: ${plugin.metadata.type}`);\n break;\n }\n\n // 收集路由\n if (plugin.metadata.routes && plugin.metadata.routes.length > 0) {\n logger.info(`已从插件 ${plugin.id} 收集路由:`, plugin.metadata.routes);\n }\n\n // 收集扩展点\n if (plugin.metadata.extensions && plugin.metadata.extensions.length > 0) {\n plugin.metadata.extensions.forEach((ext) => {\n const list = this.extensions.get(ext.slot) || [];\n list.push({ ...ext, _pluginId: plugin.id });\n this.extensions.set(ext.slot, list);\n });\n logger.info(`已从插件 ${plugin.id} 收集扩展点`);\n }\n\n this.plugins.set(plugin.id, plugin);\n logger.info(`插件 ${plugin.id} 已注册为 ${plugin.metadata.type}。`);\n\n // 触发状态变更通知\n if (notify) {\n this.notify();\n }\n }\n\n /**\n * 初始化所有插件\n * @param sharedContext 共享上下文\n */\n async initPlugins(sharedContext: Record<string, any> = {}) {\n if (this.isInitializing) {\n logger.warn('PluginManager is already initializing, skipping...');\n return;\n }\n this.isInitializing = true;\n\n try {\n this.sharedContext = {\n ...sharedContext,\n events: this.eventBus,\n };\n\n // 1. 准备运行时\n this.plugins.forEach((plugin) => {\n if (!this.isPluginEnabled(plugin.id)) return;\n \n if (!this.runtimes.has(plugin.id)) {\n const runtime = new PluginRuntime(plugin, this.sharedContext!, this.storageManager);\n this.runtimes.set(plugin.id, runtime);\n }\n });\n\n // 2. 拓扑排序解析依赖\n const sortedPluginIds = this.getSortedPluginIds();\n\n // 2.5 依赖完整性校验\n const missingDeps = new Map<string, string[]>();\n const idsToLoad = new Set(sortedPluginIds);\n\n for (const id of sortedPluginIds) {\n const plugin = this.plugins.get(id);\n if (plugin?.metadata.dependencies) {\n const missing = plugin.metadata.dependencies.filter(depId => !this.runtimes.has(depId));\n if (missing.length > 0) {\n missingDeps.set(id, missing);\n // 如果依赖缺失,该插件也不应加载\n idsToLoad.delete(id);\n // 立即移除运行时,以便后续依赖此插件的插件也能检测到缺失\n this.runtimes.delete(id);\n }\n }\n }\n\n if (missingDeps.size > 0) {\n missingDeps.forEach((deps, id) => {\n logger.error(`插件 ${id} 无法加载,缺失依赖: ${deps.join(', ')}`);\n });\n }\n\n // 3. 顺序执行 onLoad (异步)\n for (const id of sortedPluginIds) {\n if (!idsToLoad.has(id)) continue;\n\n const runtime = this.runtimes.get(id);\n if (runtime && runtime.status === 'initial') {\n try {\n logger.info(`[PluginManager] invoking onLoad for ${id}`);\n await runtime.load();\n logger.info(`[PluginManager] onLoad completed for ${id}`);\n } catch (e) {\n logger.error(`插件 ${id} 加载失败:`, e);\n }\n }\n }\n\n // 4. 顺序执行 onMount\n for (const id of sortedPluginIds) {\n if (!idsToLoad.has(id)) continue;\n\n const runtime = this.runtimes.get(id);\n if (runtime && (runtime.status === 'loaded' || runtime.status === 'initial')) {\n try {\n await runtime.mount();\n } catch (e) {\n logger.error(`插件 ${id} 挂载失败:`, e);\n }\n }\n }\n } finally {\n this.isInitializing = false;\n // 初始化完成后触发一次全局通知,确保 UI 得到更新\n this.notify();\n }\n }\n\n /**\n * 获取排序后的插件 ID 列表 (处理依赖)\n */\n private getSortedPluginIds(): string[] {\n const ids = Array.from(this.runtimes.keys());\n const visited = new Set<string>();\n const sorted: string[] = [];\n const visiting = new Set<string>();\n\n const visit = (id: string) => {\n if (visited.has(id)) return;\n if (visiting.has(id)) {\n logger.error(`循环依赖检测到: ${id}`);\n return;\n }\n\n visiting.add(id);\n\n const plugin = this.plugins.get(id);\n if (plugin?.metadata.dependencies) {\n plugin.metadata.dependencies.forEach(depId => {\n if (this.runtimes.has(depId)) {\n visit(depId);\n }\n });\n }\n\n visiting.delete(id);\n visited.add(id);\n sorted.push(id);\n };\n\n // 简单的优先级排序作为初始顺序:system > functional > business > others\n const priorityMap: Record<string, number> = {\n 'system': 100,\n 'functional': 50,\n 'business': 10,\n };\n \n const sortedIdsByType = [...ids].sort((a, b) => {\n const pA = priorityMap[this.plugins.get(a)?.metadata.type || ''] || 0;\n const pB = priorityMap[this.plugins.get(b)?.metadata.type || ''] || 0;\n return pB - pA;\n });\n\n sortedIdsByType.forEach(id => visit(id));\n\n return sorted;\n }\n\n /**\n * 加载插件列表\n * @param configs 插件配置\n * @param registry 插件注册表 (动态导入函数)\n * @param notify 是否在加载完成后触发通知,默认为 true\n */\n async loadPlugins(configs: Record<string, any>, registry: Record<string, () => Promise<any>>, notify = true) {\n logger.info('开始加载插件...');\n\n // 1. 并行加载所有本地插件模块\n const localLoadPromises = Object.entries(registry).map(async ([registryId, importFn]) => {\n try {\n const module = await importFn();\n const config = configs[registryId];\n const plugin = this.instantiatePlugin(registryId, module, config);\n \n // 如果外部传入了配置,暂时存入 configManager,以便 register 时合并\n if (plugin && config) {\n configManager.set(plugin.id, config);\n }\n \n return plugin;\n } catch (e) {\n logger.error(`加载本地插件模块 ${registryId} 失败:`, e);\n return null;\n }\n });\n\n // 2. 加载在线插件 (根据配置中的 url)\n const onlineLoadPromises = Object.entries(configs)\n .filter(([id, config]) => config.url && !registry[id]) // 只有配置了 URL 且不在本地注册表中的才是在线插件\n .map(async ([pluginId, config]) => {\n try {\n const plugin = await this.loadRemotePlugin(pluginId, config.url, config);\n \n // 同样存入 configManager\n if (plugin && config) {\n configManager.set(plugin.id, config);\n }\n \n return plugin;\n } catch (e) {\n logger.error(`加载在线插件 ${pluginId} 失败:`, e);\n return null;\n }\n });\n\n const loadedPlugins = await Promise.all([...localLoadPromises, ...onlineLoadPromises]);\n\n // 3. 注册插件 (批量注册时不触发通知)\n loadedPlugins.forEach((plugin) => {\n if (plugin) {\n this.register(plugin, false);\n }\n });\n\n // 4. 全部注册完成后触发一次通知\n if (notify) {\n this.notify();\n }\n\n logger.info(`插件加载完成,共加载 ${this.plugins.size} 个插件`);\n }\n\n /**\n * 加载远程插件\n * @param pluginId 插件 ID\n * @param url 远程 URL\n * @param config 插件配置\n */\n async loadRemotePlugin(pluginId: string, url: string, config: any): Promise<Plugin | null> {\n logger.info(`正在从 ${url} 加载远程插件 ${pluginId}...`);\n\n // 如果显式指定了 format 为 iife,则直接使用 IIFE 加载,跳过 ESM\n if (config?.format === 'iife') {\n return this.loadIIFEPlugin(pluginId, url, config);\n }\n\n try {\n // 1. 尝试使用 ESM 动态导入\n // 使用 new Function 绕过 Vite 对 public 目录下文件的静态分析限制\n // Vite 禁止直接 import public 目录下的文件,即使该代码路径在运行时不会执行\n const dynamicImport = new Function('specifier', 'return import(specifier)');\n const module = await dynamicImport(url);\n return this.instantiatePlugin(pluginId, module, config);\n } catch (e) {\n // 只有在没有显式指定 format 的情况下才尝试降级\n // 如果指定了 esm 但失败了,应该直接报错?目前为了健壮性,依然允许降级,但记录日志。\n logger.warn(`ESM 加载失败,尝试 IIFE 加载: ${pluginId}`);\n // 2. 如果 ESM 失败,尝试 IIFE 加载 (微前端模式)\n return this.loadIIFEPlugin(pluginId, url, config);\n }\n }\n\n /**\n * IIFE 模式加载插件\n */\n private loadIIFEPlugin(pluginId: string, url: string, config: any): Promise<Plugin | null> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.onload = () => {\n // 约定:IIFE 模式下插件挂载在 window[pluginId] 或 window[globalName]\n // 我们的 build.ts 中 globalName 是 pkg.name 转换后的\n const globalName = pluginId.replace(/[^a-zA-Z0-9]/g, '_');\n const pluginModule = (window as any)[globalName];\n if (pluginModule) {\n resolve(this.instantiatePlugin(pluginId, pluginModule, config));\n } else {\n reject(new Error(`远程插件 ${pluginId} 加载后未找到全局变量 ${globalName}`));\n }\n };\n script.onerror = () => reject(new Error(`远程插件 ${pluginId} 加载失败: ${url}`));\n document.head.appendChild(script);\n });\n }\n\n /**\n * 实例化插件\n */\n private instantiatePlugin(pluginId: string, module: any, config: any): Plugin | null {\n // 约定:插件模块必须导出一个实现了 Plugin 接口的类或对象\n // 优先查找 default export,其次查找命名的 Plugin 类\n let PluginClass = module.default;\n\n if (!PluginClass) {\n // 尝试查找以 Plugin 结尾的导出\n const key = Object.keys(module).find((k) => k.endsWith('Plugin'));\n if (key) PluginClass = module[key];\n }\n\n if (!PluginClass && typeof module === 'object') {\n // 如果 module 本身看起来像个插件实例 (有 id 和 metadata)\n if (module.id && module.metadata) {\n PluginClass = module;\n }\n }\n\n if (PluginClass) {\n // 如果是类,实例化\n const isClass = typeof PluginClass === 'function' && PluginClass.prototype;\n if (isClass) {\n logger.warn(`插件 ${pluginId} 使用了类定义模式。建议统一使用 definePlugin() 工厂模式以消除歧义并简化代码。`);\n }\n \n const pluginInstance = typeof PluginClass === 'function' ? new PluginClass() : PluginClass;\n \n // 强制使用来自注册表的 ID (registryId),确保配置和存储路径的一致性\n // 但是 registryId 可能是文件路径,而不是真正的 ID\n // 这里的逻辑需要修正:如果 registryId 看起来像个路径(包含 /src/),则不应强制覆盖 metadata.id\n // 除非我们能从路径中解析出正确的包名\n \n const isFilePath = pluginId.includes('/') && (pluginId.includes('.ts') || pluginId.includes('.tsx'));\n if (!isFilePath && pluginId && pluginInstance.metadata) {\n // 只有当插件 ID 与注册表 ID 不一致时才更新,且只更新 metadata.id\n // 因为 pluginInstance.id 已经定义为只读 getter\n if (pluginInstance.metadata.id !== pluginId) {\n pluginInstance.metadata.id = pluginId;\n }\n }\n\n // 确保 id 存在 (降级处理)\n // 如果 pluginInstance 没有 id getter,且 metadata 有 id,则尝试赋值\n if (!pluginInstance.id && pluginInstance.metadata?.id) {\n try {\n pluginInstance.id = pluginInstance.metadata.id;\n } catch (e) {\n // 忽略 getter 导致的赋值失败\n }\n }\n\n // 注入配置\n if (config) {\n pluginInstance.defaultConfig = { ...pluginInstance.defaultConfig, ...config };\n }\n return pluginInstance;\n }\n\n logger.warn(`模块 ${pluginId} 未导出有效的插件入口`);\n return null;\n }\n\n // --- Private Handlers ---\n\n private validatePlugin(plugin: Plugin): boolean {\n if (!plugin.id) return false;\n if (!plugin.metadata) return false;\n return true;\n }\n\n private handleBusinessPlugin(plugin: Plugin) {\n // 业务插件特定逻辑\n }\n\n private handleFunctionalPlugin(plugin: Plugin) {\n // 功能插件特定逻辑\n }\n\n private handleViewPlugin(plugin: Plugin) {\n // 视图插件特定逻辑\n }\n\n private handleThemePlugin(plugin: Plugin) {\n // 主题插件特定逻辑\n }\n\n private handleSystemPlugin(plugin: Plugin) {\n // 系统插件特定逻辑\n }\n}\n\n/**\n * 全局插件管理器实例\n */\nexport const pluginManager = new PluginManager(new LocalStorageAdapter());\n","import { StoragePort } from '../ports/storage-port';\n\n/**\n * 浏览器本地存储 (LocalStorage) 适配器\n * @description 实现 `StoragePort` 接口,封装了对原生 `localStorage` 的访问。\n * 支持可选的命名空间前缀隔离,确保在同一个域下不同模块的数据互不干扰。\n */\nexport class LocalStorageAdapter implements StoragePort {\n /** 命名空间前缀,所有存入的键名都会自动添加此前缀 */\n private prefix: string;\n\n /**\n * 初始化适配器\n * @param prefix - 可选的命名空间前缀(如 'chatbi'),默认为空字符串\n */\n constructor(prefix: string = '') {\n this.prefix = prefix;\n }\n\n /**\n * 内部方法:计算实际存储的键名\n * @param key - 业务层传入的原始键名\n * @returns 拼接前缀后的物理键名\n */\n private getKey(key: string): string {\n return this.prefix ? `${this.prefix}:${key}` : key;\n }\n\n /**\n * 内部方法:从物理键名还原业务键名\n * @param namespacedKey - 物理存储中的完整键名\n * @returns 还原后的原始键名,若前缀不匹配则返回 null\n */\n private getOriginalKey(namespacedKey: string): string | null {\n if (!this.prefix) return namespacedKey;\n if (namespacedKey.startsWith(this.prefix + ':')) {\n return namespacedKey.slice(this.prefix.length + 1);\n }\n return null;\n }\n\n /**\n * 读取存储项\n * @param key - 原始键名\n * @returns 存储的字符串内容,不存在则返回 null\n */\n getItem(key: string): string | null {\n return localStorage.getItem(this.getKey(key));\n }\n\n /**\n * 写入存储项\n * @param key - 原始键名\n * @param value - 待存储的字符串值\n */\n setItem(key: string, value: string): void {\n localStorage.setItem(this.getKey(key), value);\n }\n\n /**\n * 移除特定的存储项\n * @param key - 原始键名\n */\n removeItem(key: string): void {\n localStorage.removeItem(this.getKey(key));\n }\n\n /**\n * 清空存储空间\n * @description \n * - 若定义了前缀:仅删除以该前缀开头的键名,不影响其他数据。\n * - 若未定义前缀:调用原生 `localStorage.clear()` 清空所有数据。\n */\n clear(): void {\n if (!this.prefix) {\n localStorage.clear();\n return;\n }\n\n // 仅清除带有前缀的项\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach(key => localStorage.removeItem(key));\n }\n\n /**\n * 返回当前命名空间下的存储项总数\n */\n get length(): number {\n if (!this.prefix) return localStorage.length;\n let count = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * 根据索引获取对应的原始键名\n * @param index - 索引位置\n * @returns 对应的业务键名,不存在则返回 null\n */\n key(index: number): string | null {\n if (!this.prefix) return localStorage.key(index);\n \n let count = 0;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n if (count === index) {\n return this.getOriginalKey(key);\n }\n count++;\n }\n }\n return null;\n }\n}\n","import { createLogger } from './utils/logger';\n\nconst logger = createLogger('EventBus');\n\nexport type EventCallback = (...args: any[]) => any;\n\n/**\n * 事件总线接口\n */\nexport interface EventBus {\n /**\n * 订阅事件\n * @param event 事件名称\n * @param callback 回调函数\n * @returns 取消订阅函数\n */\n on(event: string, callback: EventCallback): () => void;\n \n /**\n * 取消订阅\n * @param event 事件名称\n * @param callback 回调函数\n */\n off(event: string, callback: EventCallback): void;\n \n /**\n * 触发事件\n * @param event 事件名称\n * @param args 事件参数\n */\n emit(event: string, ...args: any[]): void;\n \n /**\n * 订阅一次性事件\n * @param event 事件名称\n * @param callback 回调函数\n */\n once(event: string, callback: EventCallback): void;\n}\n\nexport class DefaultEventBus implements EventBus {\n private listeners: Map<string, EventCallback[]> = new Map();\n\n on(event: string, callback: EventCallback): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)?.push(callback);\n return () => this.off(event, callback);\n }\n\n off(event: string, callback: EventCallback) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n this.listeners.set(event, callbacks.filter(cb => cb !== callback));\n }\n }\n\n emit(event: string, ...args: any[]) {\n const callbacks = this.listeners.get(event);\n if (callbacks) {\n callbacks.forEach(cb => {\n try {\n cb(...args);\n } catch (error) {\n logger.error(`事件监听器处理错误 (${event}):`, error);\n }\n });\n }\n }\n\n once(event: string, callback: EventCallback) {\n const wrapper = (...args: any[]) => {\n callback(...args);\n this.off(event, wrapper);\n };\n this.on(event, wrapper);\n }\n}\n","import { createLogger } from '../utils/logger';\n\nconst logger = createLogger('ProxySandbox');\n\n/**\n * ProxySandbox 类\n * @description 基于 Proxy 的 JS 沙箱实现,模拟独立的 Window 环境\n */\nexport class ProxySandbox {\n /** 沙箱名称 */\n public name: string;\n /** 代理后的 Window 对象 */\n public proxy: WindowProxy;\n /** 沙箱是否激活 */\n public running = false;\n\n /** 记录新增/修改的全局变量 */\n private updatedValueSet = new Set<string | symbol>();\n \n /** 绑定函数的缓存池,避免重复 bind 带来的性能开销 */\n private boundFunctionCache = new Map<Function, Function>();\n\n /** 副作用记录池 */\n private effectPool = {\n timeouts: new Set<number>(),\n intervals: new Set<number>(),\n rafs: new Set<number>(), // requestAnimationFrame\n listeners: new Map<string, Array<{ listener: EventListenerOrEventListenerObject; options?: boolean | AddEventListenerOptions }>>(),\n };\n\n /** 真实的 Window 对象 */\n private globalContext: Window;\n\n /** 白名单全局变量(允许透传访问真实 Window) */\n private static globalWhitelist = [\n 'System',\n 'console',\n // 'setTimeout', // 移除白名单,改为劫持\n // 'setInterval',\n // 'clearTimeout',\n // 'clearInterval',\n 'requestAnimationFrame',\n 'cancelAnimationFrame',\n // 'addEventListener', // 移除白名单,改为劫持\n // 'removeEventListener',\n 'location',\n 'history',\n 'navigator',\n 'document', \n ];\n\n constructor(name: string, globalContext = window) {\n this.name = name;\n this.globalContext = globalContext;\n\n const { fakeWindow, propertiesWithGetter } = this.createFakeWindow(globalContext);\n \n // 劫持副作用 API\n this.patchGlobalEffects(fakeWindow);\n\n const proxy = new Proxy(fakeWindow, {\n set: (target: any, p: string | symbol, value: any): boolean => {\n if (this.running) {\n // 记录修改的属性\n this.updatedValueSet.add(p);\n target[p] = value;\n return true;\n }\n // 沙箱未运行时,禁止修改\n logger.warn(`${name} 未运行,无法设置属性 '${String(p)}'`);\n return false;\n },\n\n get: (target: any, p: string | symbol): any => {\n // 1. 优先从 fakeWindow 获取\n if (p === Symbol.unscopables) return undefined;\n if (p === 'window' || p === 'self' || p === 'globalThis') {\n return this.proxy;\n }\n \n if (p === 'top' || p === 'parent') {\n return this.globalContext[p];\n }\n\n const value = target[p];\n if (value !== undefined || this.updatedValueSet.has(p)) {\n return value;\n }\n\n // 2. 尝试从真实 Window 获取\n const rawValue = (this.globalContext as any)[p];\n \n // 处理函数绑定的 this 指向\n if (typeof rawValue === 'function' && !this.isConstructor(rawValue)) {\n if (this.isNativeFunction(rawValue)) {\n return rawValue.bind(this.globalContext);\n }\n }\n \n return rawValue;\n },\n\n has: (target: any, p: string | symbol): boolean => {\n return p in target || p in this.globalContext;\n },\n\n defineProperty: (target: any, p: string | symbol, attributes: PropertyDescriptor): boolean => {\n if (this.running) {\n this.updatedValueSet.add(p);\n return Reflect.defineProperty(target, p, attributes);\n }\n return false;\n },\n });\n\n this.proxy = proxy as WindowProxy;\n }\n\n /**\n * 激活沙箱\n */\n active() {\n if (!this.running) {\n this.running = true;\n }\n }\n\n /**\n * 销毁沙箱\n */\n inactive() {\n this.running = false;\n \n // 清理副作用\n this.effectPool.timeouts.forEach((id) => this.globalContext.clearTimeout(id));\n this.effectPool.timeouts.clear();\n\n this.effectPool.intervals.forEach((id) => this.globalContext.clearInterval(id));\n this.effectPool.intervals.clear();\n\n this.effectPool.rafs.forEach((id) => this.globalContext.cancelAnimationFrame(id));\n this.effectPool.rafs.clear();\n\n this.effectPool.listeners.forEach((listeners, type) => {\n listeners.forEach(({ listener, options }) => {\n this.globalContext.removeEventListener(type, listener, options);\n });\n });\n this.effectPool.listeners.clear();\n \n logger.debug(`${this.name} 已停用,副作用已清除。`);\n }\n\n /**\n * 在沙箱中执行代码\n * @param code JS 代码字符串\n * @returns 执行结果\n */\n eval(code: string) {\n // 添加 sourceURL 以便于在 DevTools 中调试\n const sourceURL = `//# sourceURL=${this.name}.js`;\n // 构造一个函数,接收 window, self, globalThis 作为参数\n // 注意:这里不再依赖全局的 window.proxy\n const evalCode = `\n ;(function(window, self, globalThis){\n with(window) {\n ${code}\n ${sourceURL}\n }\n })\n `;\n // 获取编译后的函数\n const func = (0, eval)(evalCode);\n // 绑定上下文并传入 proxy 对象\n return func.call(this.proxy, this.proxy, this.proxy, this.proxy);\n }\n\n /**\n * 创建伪造的 Window 对象\n */\n private createFakeWindow(globalContext: Window) {\n const propertiesWithGetter = new Map<PropertyKey, boolean>();\n const fakeWindow = {} as any;\n\n // 复制不可配置的属性描述符,防止 Proxy 报错\n Object.getOwnPropertyNames(globalContext).forEach((p) => {\n const descriptor = Object.getOwnPropertyDescriptor(globalContext, p);\n if (descriptor && !descriptor.configurable) {\n // 如果是不可配置属性,必须在 target 上也存在\n // 但由于我们无法完全模拟,这里暂不处理,依赖 get 陷阱透传\n // 实际上 ProxySandbox 的 target 通常是一个空对象\n }\n });\n\n return { fakeWindow, propertiesWithGetter };\n }\n\n private isConstructor(fn: (...args: any[]) => any) {\n const prototype = fn.prototype;\n return !!(prototype && prototype.constructor === fn && Object.getOwnPropertyNames(prototype).length > 0);\n }\n\n private isNativeFunction(fn: (...args: any[]) => any) {\n return fn.toString().indexOf('[native code]') > -1;\n }\n\n /**\n * 劫持全局副作用 API\n */\n private patchGlobalEffects(fakeWindow: any) {\n // 1. 劫持 setTimeout\n fakeWindow.setTimeout = (handler: TimerHandler, timeout?: number, ...args: any[]): number => {\n const id = this.globalContext.setTimeout(handler, timeout, ...args);\n this.effectPool.timeouts.add(id);\n return id;\n };\n fakeWindow.clearTimeout = (id: number | undefined) => {\n if (id) {\n this.effectPool.timeouts.delete(id);\n this.globalContext.clearTimeout(id);\n }\n };\n\n // 2. 劫持 setInterval\n fakeWindow.setInterval = (handler: TimerHandler, timeout?: number, ...args: any[]): number => {\n const id = this.globalContext.setInterval(handler, timeout, ...args);\n this.effectPool.intervals.add(id);\n return id;\n };\n fakeWindow.clearInterval = (id: number | undefined) => {\n if (id) {\n this.effectPool.intervals.delete(id);\n this.globalContext.clearInterval(id);\n }\n };\n\n // 3. 劫持 requestAnimationFrame\n fakeWindow.requestAnimationFrame = (callback: FrameRequestCallback): number => {\n const id = this.globalContext.requestAnimationFrame(callback);\n this.effectPool.rafs.add(id);\n return id;\n };\n fakeWindow.cancelAnimationFrame = (id: number) => {\n if (id) {\n this.effectPool.rafs.delete(id);\n this.globalContext.cancelAnimationFrame(id);\n }\n };\n\n // 4. 劫持 addEventListener\n fakeWindow.addEventListener = (\n type: string, \n listener: EventListenerOrEventListenerObject, \n options?: boolean | AddEventListenerOptions\n ) => {\n const listeners = this.effectPool.listeners.get(type) || [];\n listeners.push({ listener, options });\n this.effectPool.listeners.set(type, listeners);\n return this.globalContext.addEventListener(type, listener, options);\n };\n\n fakeWindow.removeEventListener = (\n type: string, \n listener: EventListenerOrEventListenerObject, \n options?: boolean | AddEventListenerOptions\n ) => {\n const listeners = this.effectPool.listeners.get(type);\n if (listeners) {\n const index = listeners.findIndex(item => item.listener === listener && item.options === options);\n if (index !== -1) listeners.splice(index, 1);\n }\n return this.globalContext.removeEventListener(type, listener, options);\n };\n }\n}\n","import { StoragePort } from '../ports/storage-port';\nimport { createLogger } from '../utils/logger';\nimport { StorageManager } from './storage-manager';\n\n/**\n * 插件隔离沙箱\n * @description 核心领域服务,为每个插件实例创建独立的运行上下文。\n * 它是插件与系统核心之间的“中间层”,确保插件只能访问其权限范围内的资源。\n * 主要职责:\n * 1. 存储隔离:确保插件只能读写属于自己的 LocalStorage 命名空间。\n * 2. 日志隔离:为插件提供带有自身 ID 前缀的日志输出,方便调试。\n */\nexport class PluginSandbox {\n /** 关联的插件唯一标识 */\n private pluginId: string;\n /** 系统全局存储管理器 */\n private storageManager: StorageManager;\n\n /**\n * 构造插件沙箱\n * @param pluginId - 插件 ID\n * @param storageManager - 系统存储管理器实例\n */\n constructor(pluginId: string, storageManager: StorageManager) {\n this.pluginId = pluginId;\n this.storageManager = storageManager;\n }\n\n /**\n * 获取隔离的存储接口\n * @description 返回一个受限的 StoragePort,所有操作都会自动带上插件 ID 前缀。\n */\n get storage() {\n return this.storageManager.getContextStorage(this.pluginId);\n }\n\n /**\n * 获取隔离的日志接口\n * @description 返回一个带插件 ID 前缀的 Logger 实例。\n */\n get logger() {\n return createLogger(`Plugin:${this.pluginId}`);\n }\n}\n","/**\n * @file plugin-runtime.ts\n * @description 插件运行时,封装单个插件的生命周期(load/mount/unmount)、沙箱环境和隔离上下文\n * @author ChatBI Team\n */\n\nimport { serviceRegistry } from '../application/service-registry';\nimport { configManager } from '../config-manager';\nimport { Plugin, PluginContext } from '../ports/plugin-port';\nimport { ProxySandbox } from '../sandbox/proxy-sandbox';\nimport { createLogger } from '../utils/logger';\nimport { PluginSandbox } from './plugin-sandbox';\nimport { StorageManager } from './storage-manager';\n\nconst logger = createLogger('PluginRuntime');\n\n/**\n * 插件运行时类\n * @description 为单个插件提供独立的运行环境,负责管理其生命周期、初始化沙箱环境并组装上下文对象。\n */\nexport class PluginRuntime {\n /** 插件定义对象 */\n public plugin: Plugin;\n /** 传递给插件的上下文对象 */\n public context: PluginContext;\n \n /** 存储沙箱隔离设施 */\n private storageSandbox: PluginSandbox;\n /** Window/全局对象沙箱隔离设施 */\n private windowSandbox: ProxySandbox;\n /** 是否已完成加载阶段 */\n private isLoaded = false;\n /** 是否已完成挂载阶段 */\n private isMounted = false;\n /** 运行时捕获的错误信息 */\n private error: Error | null = null;\n\n /**\n * 构造函数\n * @param plugin - 插件定义对象\n * @param sharedContext - 来自内核的共享上下文资源 (如 API 引擎、事件总线)\n * @param storageManager - 全局存储管理器\n */\n constructor(\n plugin: Plugin, \n sharedContext: Record<string, any>, \n storageManager: StorageManager\n ) {\n this.plugin = plugin;\n \n // 初始化沙箱设施\n this.storageSandbox = new PluginSandbox(plugin.id, storageManager);\n this.windowSandbox = new ProxySandbox(plugin.id);\n\n // 组装插件上下文\n this.context = {\n pluginId: plugin.id,\n api: sharedContext.api,\n events: sharedContext.events,\n storage: this.storageSandbox.storage,\n logger: this.storageSandbox.logger,\n window: this.windowSandbox.proxy,\n getService: <T = any>(name: string) => serviceRegistry.get<T>(name),\n registerService: (name: string, service: any) => serviceRegistry.register(`${plugin.id}.${name}`, service),\n };\n }\n\n /**\n * 执行插件的加载逻辑 (onLoad)\n * @description 此阶段会自动注册插件声明的 API 配置,并调用插件的 onLoad 钩子。\n * 用于执行非 UI 的初始化逻辑,如注册服务、拦截器等。\n */\n async load() {\n if (this.isLoaded) return;\n \n logger.debug(`正在加载插件: ${this.plugin.id}`);\n \n try {\n // 1. 自动注册 API 配置\n if (this.plugin.metadata.api && this.context.api && typeof this.context.api.register === 'function') {\n this.context.api.register(this.plugin.metadata.api);\n logger.debug(`已为插件 ${this.plugin.id} 自动注册 API 配置`);\n }\n\n // 1.5 自动注册配置服务 (Config Service)\n if (this.plugin.metadata.configuration && this.plugin.metadata.configuration.length > 0) {\n // 预先建立配置索引,提升查找性能 (O(1))\n const configMap = new Map(this.plugin.metadata.configuration.map(c => [c.key, c]));\n // 方法缓存,确保相同的方法名返回相同的函数实例 (Identity Consistency)\n const getterCache = new Map<string, () => any>();\n\n // 使用 Proxy 动态拦截属性访问,避免预先生成大量方法对象\n const configService = new Proxy({}, {\n get: (target, prop) => {\n // 1. 边界检查:仅处理字符串类型的属性名\n if (typeof prop !== 'string') {\n return Reflect.get(target, prop);\n }\n\n // 2. 拦截 getXxx 方法调用\n if (prop.startsWith('get')) {\n // 优先从缓存获取\n if (getterCache.has(prop)) {\n return getterCache.get(prop);\n }\n\n // 解析配置键名: getApiKey -> apiKey\n // 注意:这里假设配置键名是 camelCase。\n // 如果配置键名本身是 \"APIKey\",转换后为 \"aPIKey\",可能匹配不到。\n // 为了稳健性,可以尝试几种变体,或者约定 key 必须是 camelCase。\n // 这里保持简单的首字母小写转换。\n const configKey = prop.slice(3).charAt(0).toLowerCase() + prop.slice(3).slice(1);\n \n // 检查该配置项是否存在且允许访问\n const configItem = configMap.get(configKey);\n \n if (configItem) {\n if (configItem.private || (configItem as any).internal) {\n logger.warn(`尝试访问私有配置: ${configKey}`);\n // 对于私有配置,返回 undefined 或抛出错误?\n // 这里选择返回一个总是返回 undefined 的函数,保持接口一致性\n const noop = () => undefined;\n getterCache.set(prop, noop);\n return noop;\n }\n \n // 创建并缓存 Getter 函数\n const getter = () => this.context.storage.get(configKey);\n getterCache.set(prop, getter);\n return getter;\n }\n }\n return Reflect.get(target, prop);\n }\n });\n\n this.context.registerService('config', configService);\n logger.debug(`已为插件 ${this.plugin.id} 自动注册配置服务 (Proxy Mode)`);\n }\n\n // 2. 调用 onLoad 钩子\n if (this.plugin.onLoad) {\n await this.plugin.onLoad(this.context);\n }\n \n this.isLoaded = true;\n this.error = null;\n logger.info(`插件 ${this.plugin.id} 已加载。`);\n } catch (error) {\n this.error = error instanceof Error ? error : new Error(String(error));\n logger.error(`插件 ${this.plugin.id} 加载失败:`, error);\n // 不再抛出错误,避免导致主应用崩溃\n }\n }\n\n /**\n * 执行插件的挂载逻辑 (onMount)\n * @description 此阶段会激活 Window 沙箱并调用插件的 onMount 钩子。\n * 此时插件的 UI 组件(如有)即将或已经进入 DOM。\n */\n async mount() {\n if (!this.isLoaded) await this.load();\n if (this.isMounted) return;\n \n logger.debug(`正在挂载插件: ${this.plugin.id}`);\n \n try {\n // 1. 激活沙箱\n this.windowSandbox.active();\n \n // 2. 调用 onMount 钩子\n if (this.plugin.onMount) {\n this.plugin.onMount(this.context);\n }\n \n this.isMounted = true;\n this.error = null;\n logger.info(`插件 ${this.plugin.id} 已挂载。`);\n } catch (error) {\n this.error = error instanceof Error ? error : new Error(String(error));\n logger.error(`插件 ${this.plugin.id} 挂载失败:`, error);\n // 不再抛出错误,避免导致主应用崩溃\n }\n }\n\n /**\n * 执行插件的卸载逻辑 (onUnmount)\n * @description 调用插件的 onUnmount 钩子并停用沙箱。\n */\n async unmount() {\n if (!this.isMounted) return;\n\n logger.debug(`正在卸载插件: ${this.plugin.id}`);\n\n try {\n // 1. 调用 onUnmount 钩子\n if (this.plugin.onUnmount) {\n this.plugin.onUnmount(this.context);\n }\n } catch (error) {\n logger.error(`插件 ${this.plugin.id} 卸载时出错:`, error);\n } finally {\n // 2. 停用沙箱\n this.windowSandbox.inactive();\n this.isMounted = false;\n this.error = null;\n logger.info(`插件 ${this.plugin.id} 已卸载。`);\n }\n }\n\n /**\n * 彻底销毁插件实例\n * @description 卸载插件并重置加载状态。\n */\n async destroy() {\n await this.unmount();\n this.isLoaded = false;\n this.error = null;\n }\n\n /**\n * 设置运行时错误 (内部使用)\n * @internal\n */\n _setError(error: Error | null) {\n this.error = error;\n }\n\n /**\n * 获取插件运行时错误\n */\n getError() {\n return this.error;\n }\n\n /**\n * 获取插件当前运行状态\n * @returns 'error' | 'mounted' | 'loaded' | 'initial'\n */\n get status() {\n if (this.error) return 'error';\n if (this.isMounted) return 'mounted';\n if (this.isLoaded) return 'loaded';\n return 'initial';\n }\n}\n","import { StoragePort } from '../ports/storage-port';\n\n/**\n * 作用域存储适配器 (ScopedStorageAdapter)\n * @description 采用装饰器模式实现。它包装一个现有的 `StoragePort` 实例,\n * 并为所有存储操作透明地注入一个前缀(命名空间),从而实现逻辑上的存储隔离。\n * 常用于为插件分配独立的存储空间,而无需修改插件代码。\n */\nexport class ScopedStorageAdapter implements StoragePort {\n /**\n * 初始化作用域适配器\n * @param underlyingStorage - 被装饰的底层存储适配器实例\n * @param prefix - 用于隔离的作用域前缀字符串\n */\n constructor(\n private underlyingStorage: StoragePort,\n private prefix: string\n ) {}\n\n /**\n * 内部方法:计算实际存储的键名\n * @param key - 业务层传入的原始键名\n * @returns 拼接前缀后的物理键名\n */\n private getKey(key: string): string {\n return this.prefix ? `${this.prefix}:${key}` : key;\n }\n\n /**\n * 内部方法:从物理键名还原业务键名\n * @param namespacedKey - 物理存储中的完整键名\n * @returns 还原后的原始键名,若前缀不匹配则返回 null\n */\n private getOriginalKey(namespacedKey: string): string | null {\n if (!this.prefix) return namespacedKey;\n if (namespacedKey.startsWith(this.prefix + ':')) {\n return namespacedKey.slice(this.prefix.length + 1);\n }\n return null;\n }\n\n /**\n * 读取当前作用域下的存储项\n * @param key - 原始键名\n * @returns 字符串内容,不存在则返回 null\n */\n getItem(key: string): string | null {\n return this.underlyingStorage.getItem(this.getKey(key));\n }\n\n /**\n * 写入当前作用域下的存储项\n * @param key - 原始键名\n * @param value - 字符串内容\n */\n setItem(key: string, value: string): void {\n this.underlyingStorage.setItem(this.getKey(key), value);\n }\n\n /**\n * 移除当前作用域下的特定存储项\n * @param key - 原始键名\n */\n removeItem(key: string): void {\n this.underlyingStorage.removeItem(this.getKey(key));\n }\n\n /**\n * 清空当前作用域下的所有存储项\n * @description 仅删除匹配当前前缀的键值对,不会影响底层存储中的其他数据。\n */\n clear(): void {\n if (!this.prefix) {\n this.underlyingStorage.clear();\n return;\n }\n\n const keysToRemove: string[] = [];\n for (let i = 0; i < this.underlyingStorage.length; i++) {\n const key = this.underlyingStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n keysToRemove.push(key);\n }\n }\n \n keysToRemove.forEach(k => this.underlyingStorage.removeItem(k));\n }\n\n /**\n * 返回当前作用域下的存储项总数\n */\n get length(): number {\n let count = 0;\n for (let i = 0; i < this.underlyingStorage.length; i++) {\n const key = this.underlyingStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * 根据索引获取当前作用域下的原始键名\n * @param index - 索引位置\n * @returns 对应的业务键名,不存在则返回 null\n */\n key(index: number): string | null {\n let count = 0;\n for (let i = 0; i < this.underlyingStorage.length; i++) {\n const key = this.underlyingStorage.key(i);\n if (key && key.startsWith(this.prefix + ':')) {\n if (count === index) {\n return this.getOriginalKey(key);\n }\n count++;\n }\n }\n return null;\n }\n}\n","import { ScopedStorageAdapter } from '../adapters/scoped-storage-adapter';\nimport { configManager } from '../config-manager';\nimport { StorageItemSchema } from '../ports/plugin-port';\nimport { StoragePort } from '../ports/storage-port';\n\n/**\n * 核心领域服务:存储管理器\n * @description 统一管理应用内所有的持久化存储资源。\n * 核心功能:\n * 1. 作用域隔离:通过前缀划分 `plugin`、`shared` 和 `system` 三个层级的存储空间。\n * 2. Schema 校验:支持注册存储描述,规范数据存取,避免键名冲突。\n * 3. 默认值与配置回退:支持从 Schema 默认值或 ConfigManager 中回退取值。\n */\nexport class StorageManager {\n /** 底层物理存储驱动 */\n private baseStorage: StoragePort;\n /** 插件 ID 与存储描述定义的映射关系 */\n private schemas: Map<string, StorageItemSchema[]> = new Map();\n /** 内存缓存,减少 JSON 序列化和物理 IO 开销 */\n private memoryCache: Map<string, any> = new Map();\n\n /**\n * 初始化存储管理器\n * @param baseStorage - 符合 StoragePort 接口的物理存储驱动(如 LocalStorageAdapter)\n */\n constructor(baseStorage: StoragePort) {\n this.baseStorage = baseStorage;\n }\n\n /**\n * 注册插件的存储 Schema\n * @param pluginId - 插件 ID\n * @param schema - 存储项定义列表\n */\n registerSchema(pluginId: string, schema: StorageItemSchema[]) {\n this.schemas.set(pluginId, schema);\n }\n\n /**\n * 内部校验方法:检查键名是否在 Schema 中声明\n * @param pluginId - 插件 ID\n * @param key - 待校验的键名\n * @param scope - 目标作用域\n */\n private validateKey(pluginId: string, key: string, scope: 'plugin' | 'shared' = 'plugin') {\n const schemaList = this.schemas.get(pluginId);\n if (!schemaList) return; // 未定义 Schema 则跳过校验\n\n const item = schemaList.find(s => s.key === key);\n if (!item) {\n console.warn(`[Storage] Key \"${key}\" not defined in plugin \"${pluginId}\" schema.`);\n return;\n }\n\n const definedScope = item.scope || 'plugin';\n if (definedScope !== scope) {\n console.warn(`[Storage] Key \"${key}\" defined in scope \"${definedScope}\" but accessed via \"${scope}\".`);\n }\n }\n\n /**\n * 获取插件私有存储适配器\n * @param pluginId - 插件 ID\n * @returns 自动添加 `plugin:{id}:` 前缀的存储接口\n */\n getPluginStorage(pluginId: string): StoragePort {\n return new ScopedStorageAdapter(this.baseStorage, `plugin:${pluginId}`);\n }\n\n /**\n * 获取全局共享存储适配器\n * @returns 自动添加 `shared:` 前缀的存储接口\n */\n getSharedStorage(): StoragePort {\n return new ScopedStorageAdapter(this.baseStorage, 'shared');\n }\n\n /**\n * 获取系统内部存储适配器\n * @returns 自动添加 `system:` 前缀的存储接口\n */\n getSystemStorage(): StoragePort {\n return new ScopedStorageAdapter(this.baseStorage, 'system');\n }\n\n /**\n * 创建插件沙箱使用的复合存储对象\n * @description 返回的对象封装了对私有存储和共享存储的操作。\n * 特性:\n * - 内存级 LRU 缓存:极大提升高频读写性能。\n * - 自动序列化/反序列化 JSON。\n * - 自动校验 Schema。\n * - 取值回退逻辑:持久化存储 -> ConfigManager -> Schema 默认值。\n * \n * @param pluginId - 插件 ID\n * @returns 包含 get/set/remove 及 shared 子对象的复合接口\n */\n getContextStorage(pluginId: string) {\n const pluginStorage = this.getPluginStorage(pluginId);\n const sharedStorage = this.getSharedStorage();\n\n const createHelpers = (adapter: StoragePort, scope: 'plugin' | 'shared') => {\n // 获取适配器的前缀 (ScopedStorageAdapter 内部属性)\n // 注意:这里由于是内部实现,我们知道前缀的规律\n const prefix = scope === 'plugin' ? `plugin:${pluginId}:` : 'shared:';\n\n return {\n get: <T = any>(key: string): T | null => {\n this.validateKey(pluginId, key, scope);\n const cacheKey = `${prefix}${key}`;\n\n try {\n // 1. 优先尝试从内存缓存获取\n if (this.memoryCache.has(cacheKey)) {\n return this.memoryCache.get(cacheKey);\n }\n\n // 2. 尝试从持久化存储获取 (用户设置)\n const val = adapter.getItem(key);\n if (val !== null) {\n let parsed: any;\n try {\n parsed = JSON.parse(val);\n } catch {\n parsed = val;\n }\n // 存入内存缓存\n this.memoryCache.set(cacheKey, parsed);\n return parsed;\n }\n\n // 3. 尝试从 ConfigManager 获取 (外部注入的配置)\n if (scope === 'plugin') {\n const externalConfig = configManager.get(pluginId);\n if (externalConfig && externalConfig[key] !== undefined) {\n return externalConfig[key];\n }\n }\n\n // 4. 尝试返回 Schema 定义的默认值\n const schema = this.schemas.get(pluginId)?.find((s) => s.key === key);\n if (schema && schema.default !== undefined) {\n return schema.default;\n }\n\n return null;\n } catch (e) {\n console.warn(`[Storage] Failed to read key \"${key}\"`, e);\n return null;\n }\n },\n set: <T = any>(key: string, value: T) => {\n this.validateKey(pluginId, key, scope);\n const cacheKey = `${prefix}${key}`;\n\n try {\n // 更新内存缓存\n this.memoryCache.set(cacheKey, value);\n // 异步持久化 (或者同步,取决于 adapter)\n adapter.setItem(key, JSON.stringify(value));\n } catch (e) {\n console.warn(`[Storage] Failed to stringify key \"${key}\"`, e);\n }\n },\n remove: (key: string) => {\n this.validateKey(pluginId, key, scope);\n const cacheKey = `${prefix}${key}`;\n \n this.memoryCache.delete(cacheKey);\n adapter.removeItem(key);\n }\n };\n };\n\n return {\n ...createHelpers(pluginStorage, 'plugin'),\n shared: createHelpers(sharedStorage, 'shared')\n };\n }\n}\n","import React, { useMemo, useState, useEffect, Suspense } from 'react';\n\nimport type { PluginExtension,SlotPosition } from '../api';\nimport { pluginManager } from '../domain/plugin-manager';\nimport { PluginErrorBoundary } from './PluginErrorBoundary';\nimport { SlotSkeletons } from './SlotSkeletons';\n\n/** 插件插槽组件属性 */\ninterface PluginSlotProps {\n /** 插槽位置标识,决定渲染哪些插件扩展 */\n slot: SlotPosition;\n /** 传递给扩展组件的 Props 对象 */\n props?: Record<string, any>;\n /** 自定义容器类名 (Tailwind CSS) */\n className?: string;\n /** 自定义容器内联样式 */\n style?: React.CSSProperties;\n /** \n * 自定义渲染函数\n * @param item - 包含 key、组件和扩展元信息的对象\n * @param index - 索引位置\n */\n renderItem?: (item: { key: string; component: React.ReactNode; extension: PluginExtension }, index: number) => React.ReactNode;\n /** 骨架屏组件,当插槽内无插件扩展时显示的占位 UI */\n skeleton?: React.ReactNode;\n /** 回退组件,当插槽内无插件扩展时显示的 UI,优先级高于 skeleton */\n fallback?: React.ReactNode;\n}\n\n/**\n * 插件插槽组件\n * @description UI 层的核心组件,用于在应用中声明一个“插槽”。\n * 它会自动根据 slot 标识从 PluginManager 中获取所有注册的插件扩展组件并按顺序渲染。\n * 支持订阅插件变更,实现动态热插拔。\n */\nexport const PluginSlot: React.FC<PluginSlotProps> = ({ \n slot, \n props = {}, \n className = '', \n style,\n renderItem,\n skeleton,\n fallback,\n}: PluginSlotProps) => {\n // 使用简单的强制更新机制,订阅 PluginManager 的变更\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n // 订阅特定插槽的插件变更,减少无效重渲染\n const unsubscribe = pluginManager.subscribe(() => {\n forceUpdate({});\n }, slot);\n return unsubscribe;\n }, [slot]);\n\n // 获取该插槽的所有扩展\n const extensions = pluginManager.getExtensions(slot);\n\n // 注入系统配置到 props\n const systemConfig = pluginManager.getSystemConfig('title') ? {\n title: pluginManager.getSystemConfig('title'),\n logo: pluginManager.getSystemConfig('logo'),\n version: pluginManager.getSystemConfig('version'),\n } : undefined;\n\n const mergedProps = useMemo(() => ({\n ...props,\n systemConfig\n }), [props, systemConfig]);\n\n const items = useMemo(() => {\n return extensions.map((ext, index) => {\n const Component = ext.component;\n // 使用组合键确保唯一性且稳定,避免使用 Math.random() 导致重渲染闪烁\n const key = ext.meta?.key || `${ext.slot}-${ext.order || 0}-${index}`;\n \n return {\n key,\n extension: ext,\n component: (\n <PluginErrorBoundary key={key} pluginId={ext._pluginId}>\n <Suspense fallback={skeleton || <SlotSkeletons slot={slot} />}>\n <Component {...mergedProps} />\n </Suspense>\n </PluginErrorBoundary>\n )\n };\n });\n }, [extensions, mergedProps]);\n\n // 如果没有扩展\n if (items.length === 0) {\n if (fallback) {\n return <>{fallback}</>;\n }\n if (skeleton) {\n return (\n <div className={`plugin-slot plugin-slot-${slot} plugin-slot-skeleton ${className || ''}`} style={style}>\n {skeleton}\n </div>\n );\n }\n return null;\n }\n\n // 如果只有一项且是 RootLayout,可能不需要包装层\n if (items.length === 1 && slot === 'root-layout' && !className && !style && !renderItem) {\n return <>{items[0].component}</>;\n }\n\n return (\n <div className={`plugin-slot plugin-slot-${slot} ${className || ''}`} style={style}>\n {renderItem \n ? items.map((item, index) => renderItem(item, index))\n : items.map(item => item.component)\n }\n </div>\n );\n};\n","import React from 'react';\n\n/**\n * 通用插槽骨架屏组件集合\n * @description 提供一组预定义的骨架屏 UI,用于在插件加载或插槽内容未准备好时提供更好的用户体验。\n */\n\n/**\n * 侧边栏图标骨架屏\n * @param expanded - 是否处于展开状态\n */\nexport const SidebarIconSkeleton: React.FC<{ expanded?: boolean }> = ({ expanded = false }) => (\n <div className={`flex items-center transition-all duration-300 relative\n ${expanded ? 'w-full' : 'w-12 justify-center'} px-3 h-11 rounded-xl`}>\n <div className=\"w-6 h-6 bg-slate-200 dark:bg-white/10 rounded-lg shrink-0 animate-pulse\" />\n {expanded && (\n <div className=\"ml-3 flex-1 h-4 bg-slate-200 dark:bg-white/10 rounded animate-pulse\" />\n )}\n </div>\n);\n\n/**\n * 状态栏项骨架屏\n */\nexport const StatusBarItemSkeleton: React.FC = () => (\n <div className=\"h-4 w-16 bg-slate-200 dark:bg-white/10 rounded animate-pulse\" />\n);\n\n/**\n * 头像骨架屏\n */\nexport const AvatarSkeleton: React.FC = () => (\n <div className=\"w-10 h-10 rounded-full bg-slate-200 dark:bg-white/10 animate-pulse\" />\n);\n\n/**\n * 通用块级骨架屏\n * @param className - 自定义类名\n */\nexport const BlockSkeleton: React.FC<{ className?: string }> = ({ className }) => (\n <div className={`bg-slate-200 dark:bg-white/10 rounded animate-pulse ${className || 'w-full h-full'}`} />\n);\n\n/**\n * 自动根据插槽位置匹配骨架屏\n */\nexport const SlotSkeletons: React.FC<{ slot: string; expanded?: boolean }> = ({ slot, expanded }) => {\n if (slot.includes('sidebar')) {\n return <SidebarIconSkeleton expanded={expanded} />;\n }\n if (slot.includes('status')) {\n return <StatusBarItemSkeleton />;\n }\n if (slot.includes('avatar')) {\n return <AvatarSkeleton />;\n }\n return <BlockSkeleton />;\n};\n","import { createLogger } from '../utils/logger';\n\nconst logger = createLogger('AutoLoader');\n\n/**\n * 插件注册表接口\n * @description 键为插件 ID,值为一个返回插件定义的异步加载函数。\n */\nexport interface PluginRegistry {\n [pluginId: string]: () => Promise<any>;\n}\n\n/**\n * 插件自动发现规则\n */\nexport interface DiscoveryRule {\n /**\n * 路径匹配标识。\n * @example 'plugins' 或 '@chatbi-plugins'\n */\n pathSegment: string;\n /**\n * 生成插件 ID 时的前缀。\n * @example '@chatbi-v/plugin',最终生成如 '@chatbi-v/plugin-demo'\n */\n idPrefix: string;\n}\n\n/**\n * 默认的插件发现约定规则\n */\nconst DEFAULT_RULES: DiscoveryRule[] = [\n { pathSegment: '@chatbi-plugins', idPrefix: '@chatbi-v/plugin' },\n { pathSegment: '@chatbi-apps', idPrefix: '@chatbi-v/app' },\n { pathSegment: 'packages/plugins', idPrefix: '@chatbi-v/plugin' },\n { pathSegment: 'packages/apps', idPrefix: '@chatbi-v/app' },\n];\n\n/**\n * 解析插件注册表\n * @description 核心逻辑:将 Vite 的 `import.meta.glob` 结果映射为标准的插件注册表。\n * 它会根据预定义的路径匹配规则,从文件路径中提取插件目录名,并拼接前缀生成唯一的插件 ID。\n * \n * @param options - 包含待处理模块和匹配规则的选项对象\n * @returns 解析后的 PluginRegistry 对象\n */\nexport const resolvePluginRegistry = (options: {\n /** 原始模块映射 (来自 Vite glob) */\n modules: Record<string, () => Promise<any>>;\n /** 自定义发现规则 (可选) */\n rules?: DiscoveryRule[];\n}): PluginRegistry => {\n const { modules, rules = DEFAULT_RULES } = options;\n const registry: PluginRegistry = {};\n\n // 预编译规则为正则表达式\n const compiledRules = rules.map((rule) => {\n // 处理别名或路径片段,提取文件夹名\n // 支持格式: .../pathSegment/folderName/src/index...\n const escapedSegment = rule.pathSegment.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return {\n ...rule,\n regex: new RegExp(`${escapedSegment}/([^/]+)/src/index`),\n };\n });\n\n for (const path in modules) {\n try {\n let pluginId: string | null = null;\n\n // 匹配规则\n for (const rule of compiledRules) {\n const match = path.match(rule.regex);\n if (match && match[1]) {\n pluginId = `${rule.idPrefix}-${match[1]}`;\n logger.info(`解析路径成功: ${path} -> ${pluginId}`);\n break;\n }\n }\n\n if (pluginId) {\n registry[pluginId] = modules[path];\n } else {\n logger.warn(`无法从路径解析插件 ID: ${path},请检查是否符合命名约定。`);\n }\n } catch (e) {\n logger.error(`解析插件路径失败: ${path}`, e);\n }\n }\n\n return registry;\n};\n","/**\n * 成功状态码\n */\nexport const SUCCESS_CODE = '000000';\n\n/**\n * 基础 API 响应接口\n * @template T 响应数据的类型\n */\nexport interface BaseResponse<T = any> {\n /** 业务状态码 */\n code: string | number;\n /** 响应消息提示 */\n message: string;\n /** 业务响应数据主体 */\n data: T;\n}\n\n/**\n * 业务场景实体接口\n * @description 描述系统中的业务分析场景\n */\nexport interface Scene {\n /** 场景唯一标识符 */\n id: string;\n /** 场景名称 */\n name: string;\n /** 场景详细描述 */\n description: string;\n /** 场景内部代码/标识 */\n code: string;\n /** 场景创建者 ID 或名称 */\n creator: string;\n /** 创建时间字符串 (ISO 格式) */\n createTime: string;\n /** 该场景关联的物理数据表数量 */\n tableCount: number;\n /** 该场景关联的知识库数量 */\n kbCount: number;\n /** 该场景关联的预设问答对数量 */\n qaCount: number;\n /** 场景封面图 URL (可选) */\n cover?: string;\n}\n","import React, { createContext, useContext } from 'react';\n\nimport { PluginManager } from './domain/plugin-manager';\n\nconst PluginContext = createContext<PluginManager | null>(null);\n\nexport interface PluginProviderProps {\n manager: PluginManager;\n children: React.ReactNode;\n}\n\nexport const PluginProvider: React.FC<PluginProviderProps> = ({ manager, children }) => {\n return <PluginContext.Provider value={manager}>{children}</PluginContext.Provider>;\n};\n\nexport const usePluginManager = () => {\n const context = useContext(PluginContext);\n if (!context) {\n throw new Error('usePluginManager must be used within a PluginProvider');\n }\n return context;\n};\n","import axios, { AxiosInstance } from 'axios';\n\nimport { ApiAdapter, ApiEndpointConfig, ApiRequestConfig, StreamCallbacks } from '../../ports/api-port';\n\n/**\n * 基于 Axios 的默认请求适配器\n */\nexport class AxiosAdapter implements ApiAdapter {\n private client: AxiosInstance;\n\n constructor(baseURL: string = '/api', timeout: number = 10000) {\n this.client = axios.create({\n baseURL,\n timeout,\n });\n\n // 保持返回完整响应对象,以便 ApiEngine 可以处理 headers 和 status\n // 错误处理回归标准行为,由 ApiEngine 捕获处理\n this.client.interceptors.response.use(\n (response) => response,\n (error) => Promise.reject(error),\n );\n }\n\n async request<T = any>(config: ApiRequestConfig): Promise<T> {\n return this.client.request(config);\n }\n\n async stream(config: ApiRequestConfig, callbacks: StreamCallbacks, _endpointConfig?: ApiEndpointConfig): Promise<void> {\n const { onMessage, onError, onFinish } = callbacks;\n\n try {\n // 通过 axios.request 发起请求,以利用其拦截器(Interceptors)机制\n // 我们提供一个自定义的 adapter 来执行实际的 fetch 调用\n const response = await this.client.request({\n ...config,\n // 强制不缓存流式响应\n headers: {\n 'Cache-Control': 'no-cache',\n 'Pragma': 'no-cache',\n ...config.headers,\n },\n // 自定义适配器:在拦截器链中执行 fetch\n adapter: async (axiosConfig) => {\n // getUri 会自动处理 baseURL 和 params\n const url = this.client.getUri(axiosConfig);\n\n const fetchResponse = await fetch(url, {\n method: axiosConfig.method?.toUpperCase(),\n headers: axiosConfig.headers as any,\n body: axiosConfig.data ? (typeof axiosConfig.data === 'string' ? axiosConfig.data : JSON.stringify(axiosConfig.data)) : undefined,\n signal: axiosConfig.signal as AbortSignal,\n });\n\n return {\n data: fetchResponse, // 将原始 Response 存入 data,以便在拦截器链后获取\n status: fetchResponse.status,\n statusText: fetchResponse.statusText,\n headers: fetchResponse.headers as any,\n config: axiosConfig,\n };\n },\n });\n\n // 获取 fetch 的 Response 对象\n const fetchResponse = response instanceof Response ? response : response.data;\n\n // 触发 onResponse 回调\n if (callbacks.onResponse) {\n const hijacked = await callbacks.onResponse(response);\n if (hijacked) return;\n }\n\n if (!(fetchResponse instanceof Response)) {\n throw new Error('流式请求失败:未能获取到原始响应流,请检查 Axios 响应拦截器是否正确处理了 Response 对象。');\n }\n\n if (!fetchResponse.ok) {\n throw new Error(`HTTP error! status: ${fetchResponse.status}`);\n }\n\n if (!fetchResponse.body) {\n throw new Error('响应体为空');\n }\n\n const reader = fetchResponse.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // 按 SSE 事件分隔符(双换行)分割\n const parts = buffer.split('\\n\\n');\n\n // 最后一个部分可能是不完整的,保留在 buffer 中\n buffer = parts.pop() || '';\n\n for (const part of parts) {\n if (onMessage) {\n onMessage(part + '\\n\\n');\n }\n }\n }\n\n // 处理最后剩余的内容\n if (buffer && onMessage) {\n onMessage(buffer);\n }\n\n if (onFinish) onFinish();\n } catch (error) {\n if (onError) onError(error);\n }\n }\n}\n\n","import { BaseResponse, SUCCESS_CODE } from '../domain/models';\nimport { ApiAdapter, ApiConfig, ApiEndpointConfig, ApiInterceptor, ApiRequestConfig, RequestOptions } from '../ports/api-port';\nimport { createLogger } from '../utils/logger';\nimport { AxiosAdapter } from './adapters/axios-adapter';\n\nconst logger = createLogger('ApiEngine');\n\n/**\n * API 引擎核心类\n * @description 负责加载配置并执行请求,支持策略模式切换底层请求实现\n */\nexport class ApiEngine {\n private adapter: ApiAdapter;\n private config: ApiConfig = {};\n private interceptors: ApiInterceptor[] = [];\n\n constructor(adapter?: ApiAdapter) {\n // 默认使用 AxiosAdapter\n this.adapter = adapter || new AxiosAdapter();\n }\n\n /**\n * 注册拦截器\n */\n registerInterceptor(interceptor: ApiInterceptor) {\n this.interceptors.push(interceptor);\n }\n\n /**\n * 移除拦截器\n */\n unregisterInterceptor(interceptor: ApiInterceptor) {\n this.interceptors = this.interceptors.filter((i) => i !== interceptor);\n }\n\n /**\n * 切换请求适配器\n * @param adapter 新的适配器实例\n */\n useAdapter(adapter: ApiAdapter) {\n this.adapter = adapter;\n }\n\n /**\n * 注册 API 配置\n * @param config 配置对象\n */\n register(config: ApiConfig) {\n logger.info('正在注册 API 配置:', Object.keys(config));\n this.config = { ...this.config, ...config };\n }\n\n /**\n * 获取接口配置\n */\n getEndpoint(module: string, action: string): ApiEndpointConfig | undefined {\n return this.config[module]?.[action];\n }\n\n /**\n * 发起 API 请求\n * @param module 模块名\n * @param action 动作名\n * @param data 请求数据 (Body 或 Query)\n * @param options 请求选项\n */\n async call<T = any>(\n module: string,\n action: string,\n data?: any,\n options: RequestOptions = {},\n ): Promise<T> {\n const endpoint = this.getEndpoint(module, action);\n if (!endpoint) {\n logger.warn(`未找到 API 定义: ${module}.${action} (当前已注册模块: ${Object.keys(this.config).join(', ')})`);\n return Promise.resolve(undefined as unknown as T);\n }\n\n // 1. 准备并应用请求拦截\n const requestConfig = await this.prepareRequestConfig(endpoint, data, options);\n\n // 2. 调用适配器执行请求\n let response: any;\n try {\n response = await this.adapter.request<any>(requestConfig, endpoint);\n } catch (error: any) {\n if (error.response) {\n response = error.response;\n } else {\n throw error;\n }\n }\n\n // 3. 处理响应拦截\n const hijacked = await this.applyResponseInterceptors(response, requestConfig);\n if (hijacked) {\n logger.info('请求被拦截器劫持:', module, action);\n return undefined as unknown as T;\n }\n\n // 4. 检查 HTTP 状态码\n this.checkHttpStatus(response);\n\n // 5. 提取并处理业务错误\n const responseData = this.extractResponseData(response);\n this.handleBusinessError(responseData, endpoint, module, action);\n\n return responseData as T;\n }\n\n /**\n * 发起流式请求\n * @param module 模块名\n * @param action 动作名\n * @param data 请求数据\n * @param options 请求选项\n */\n async stream(\n module: string,\n action: string,\n data?: any,\n options: RequestOptions = {},\n ): Promise<void> {\n const endpoint = this.getEndpoint(module, action);\n if (!endpoint) {\n logger.warn(`未找到 API 定义: ${module}.${action},跳过流式请求。`);\n return;\n }\n\n if (!this.adapter.stream) {\n logger.warn('当前 API 适配器不支持流式传输。');\n return;\n }\n\n // 1. 准备并应用请求拦截\n const requestConfig = await this.prepareRequestConfig(endpoint, data, options);\n\n const callbacks = {\n onMessage: options.onMessage,\n onError: options.onError,\n onFinish: options.onFinish,\n };\n\n // 2. 执行流式请求\n try {\n await this.adapter.stream(\n requestConfig,\n {\n ...callbacks,\n onResponse: async (response: any) => {\n // 处理响应拦截\n const hijacked = await this.applyResponseInterceptors(response, requestConfig);\n if (hijacked) {\n logger.info('流式请求被拦截器劫持:', module, action);\n // 如果被劫持,主动中止流式传输\n if (requestConfig.signal instanceof AbortController) {\n (requestConfig.signal as AbortController).abort();\n }\n return true;\n }\n\n // 检查 HTTP 状态码\n this.checkHttpStatus(response);\n \n return false;\n },\n },\n endpoint,\n );\n } catch (error) {\n if (callbacks.onError) {\n callbacks.onError(error);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * 准备请求配置,应用 URL 参数替换和请求拦截器\n */\n private async prepareRequestConfig(\n endpoint: ApiEndpointConfig,\n data: any,\n options: RequestOptions,\n ): Promise<ApiRequestConfig> {\n // 1. 处理 URL 参数替换\n let url = endpoint.url;\n const pathParams = options.params || {};\n \n url = url.replace(/:([a-zA-Z0-9_]+)/g, (_, key) => {\n if (pathParams[key] !== undefined) return String(pathParams[key]);\n if (data && typeof data === 'object' && data[key] !== undefined) return String(data[key]);\n return `:${key}`;\n });\n\n const method = endpoint.method;\n \n // 2. 构建初始请求配置\n let requestConfig: ApiRequestConfig = {\n ...options,\n url,\n method,\n };\n\n if (method === 'GET' || method === 'DELETE') {\n requestConfig.params = data;\n } else {\n requestConfig.data = data;\n }\n\n // 3. 应用请求拦截器\n return this.applyRequestInterceptors(requestConfig);\n }\n\n /**\n * 应用所有请求拦截器\n */\n private async applyRequestInterceptors(config: ApiRequestConfig): Promise<ApiRequestConfig> {\n let currentConfig = config;\n for (const interceptor of this.interceptors) {\n if (interceptor.interceptRequest) {\n currentConfig = await interceptor.interceptRequest(currentConfig);\n }\n }\n return currentConfig;\n }\n\n /**\n * 应用所有响应拦截器\n * @returns 是否被劫持\n */\n private async applyResponseInterceptors(response: any, config: ApiRequestConfig): Promise<boolean> {\n if (this.interceptors.length === 0) return false;\n\n const context = this.createInterceptorContext(response, config);\n for (const interceptor of this.interceptors) {\n if (interceptor.interceptResponse) {\n const hijacked = await interceptor.interceptResponse(context);\n if (hijacked) return true;\n }\n }\n return false;\n }\n\n /**\n * 检查 HTTP 状态码\n */\n private checkHttpStatus(response: any): void {\n if (response && response.status && (response.status < 200 || response.status >= 300)) {\n // 如果是 BaseResponse,我们通常在 handleBusinessError 中处理业务错误\n // 这里的 checkHttpStatus 主要针对非 2xx 的 HTTP 错误\n const responseData = this.extractResponseData(response);\n if (!this.isBaseResponse(responseData)) {\n throw new Error(`Request failed with status ${response.status}`);\n }\n }\n }\n\n /**\n * 提取响应数据\n */\n private extractResponseData(response: any): any {\n return this.isAxiosResponse(response) ? response.data : response;\n }\n\n /**\n * 处理业务错误\n */\n private handleBusinessError(\n responseData: any, \n endpoint: ApiEndpointConfig, \n module: string, \n action: string\n ): void {\n if (!this.isBaseResponse(responseData)) return;\n\n const res = responseData as BaseResponse;\n const code = String(res.code);\n \n // 假设 SUCCESS_CODE, '200', '0' 为成功\n const isSuccess = code === SUCCESS_CODE || code === '200' || code === '0';\n \n if (!isSuccess) {\n const strategy = endpoint.errorStrategy || 'reject';\n if (strategy === 'reject') {\n logger.error(`API 请求业务错误 (${module}.${action}):`, res.message);\n throw new Error(res.message || `Request failed with code ${code}`);\n }\n }\n }\n\n /**\n * 判断是否为 BaseResponse\n */\n private isBaseResponse(data: any): boolean {\n return (\n data &&\n typeof data === 'object' &&\n 'code' in data &&\n ('message' in data || 'data' in data)\n );\n }\n\n /**\n * 严格判断是否为 AxiosResponse\n */\n private isAxiosResponse(res: any): boolean {\n return (\n res &&\n typeof res === 'object' &&\n 'data' in res &&\n 'status' in res &&\n 'headers' in res\n );\n }\n\n /**\n * 创建拦截上下文\n */\n private createInterceptorContext(response: any, config: ApiRequestConfig) {\n // 适配 Axios 响应结构\n if (response && typeof response === 'object' && 'status' in response && 'headers' in response) {\n return {\n response,\n status: response.status,\n headers: response.headers,\n data: response.data,\n config,\n };\n }\n \n // 兜底逻辑\n return {\n response,\n status: 200,\n headers: {},\n data: response,\n config,\n };\n }\n}\n\nexport const apiEngine = new ApiEngine();\n","type KeepStrategy = 'first' | 'last' | 'search' | 'hash';\n\n/**\n * 把当前地址中所有出现的参数合并成一份。\n * 重复 key 的处理策略:\n * - 'first' : 按出现顺序,第一次的值生效\n * - 'last' : 按出现顺序,最后一次的值生效(默认,最直观)\n * - 'search' : 只要 search 里出现过,就用 search 的\n * - 'hash' : 只要 hash 里出现过,就用 hash 的\n */\nexport function normalizeParams(strategy: KeepStrategy = 'last'): URLSearchParams {\n if (typeof window === 'undefined') return new URLSearchParams();\n \n const { search, hash } = window.location;\n\n // 1. 把 search 和 hash 里的 query 都拆出来\n const searchParams = new URLSearchParams(search);\n const hashParams = new URLSearchParams(hash.split('?')[1] || '');\n\n // 2. 按出现顺序拼成一个数组,方便做“first/last”策略\n const entries: Array<[string, string, 'search' | 'hash']> = [];\n searchParams.forEach((v, k) => entries.push([k, v, 'search']));\n hashParams.forEach((v, k) => entries.push([k, v, 'hash']));\n\n // 3. 根据策略挑值\n const keeper = new Map<string, string>();\n if (strategy === 'first') {\n entries.forEach(([k, v]) => {\n if (!keeper.has(k)) keeper.set(k, v);\n });\n } else if (strategy === 'last') {\n entries.forEach(([k, v]) => keeper.set(k, v));\n } else if (strategy === 'search') {\n entries.forEach(([k, v, src]) => {\n if (src === 'search') keeper.set(k, v);\n });\n // search 里没有的再用 hash 补\n hashParams.forEach((v, k) => {\n if (!keeper.has(k)) keeper.set(k, v);\n });\n } else if (strategy === 'hash') {\n entries.forEach(([k, v, src]) => {\n if (src === 'hash') keeper.set(k, v);\n });\n searchParams.forEach((v, k) => {\n if (!keeper.has(k)) keeper.set(k, v);\n });\n }\n\n return new URLSearchParams(Array.from(keeper.entries()));\n}\n\n/**\n * 清除 URL 中的特定参数并返回新的 URL\n * @description 同时处理 search 和 hash 中的参数\n */\nexport function cleanUrlParams(keysToRemove: string[]): string {\n if (typeof window === 'undefined') return '';\n\n const { pathname, search, hash } = window.location;\n\n // 1. 清理 search\n const searchParams = new URLSearchParams(search);\n keysToRemove.forEach((key) => searchParams.delete(key));\n const newSearch = searchParams.toString();\n\n // 2. 清理 hash\n const hashParts = hash.split('?');\n const hashPath = hashParts[0];\n const hashQuery = hashParts[1] || '';\n const hashParams = new URLSearchParams(hashQuery);\n keysToRemove.forEach((key) => hashParams.delete(key));\n const newHashQuery = hashParams.toString();\n const newHash = hashPath + (newHashQuery ? '?' + newHashQuery : '');\n\n // 3. 拼接新 URL\n return pathname + (newSearch ? '?' + newSearch : '') + newHash;\n}\n","import { ApiConfig } from '../ports/api-port';\n\n/**\n * 深度合并 Mock 数据到 API 定义中\n */\nconst mergeMockData = (def: Record<string, any>, mock: Record<string, any>) => {\n // 深度克隆以避免修改原始对象\n const merged = JSON.parse(JSON.stringify(def));\n\n Object.keys(mock).forEach((key) => {\n if (merged[key]) {\n merged[key] = {\n ...merged[key],\n ...mock[key],\n };\n }\n });\n\n return merged;\n};\n\nimport { normalizeParams } from '../utils/url';\n\n/**\n * 自动检测是否处于 Mock 模式\n */\nexport function isMockMode(): boolean {\n // 1. 检查环境变量\n const envMock = (typeof process !== 'undefined' && process.env.VITE_USE_MOCK === 'true') ||\n (typeof window !== 'undefined' && (window as any).VITE_USE_MOCK === 'true');\n \n // 2. 检查 URL 参数 (优先级最高,用于运行时切换)\n if (typeof window !== 'undefined') {\n const params = normalizeParams();\n const mockParam = params.get('mock');\n \n if (mockParam === 'true') return true;\n if (mockParam === 'false') return false;\n }\n\n return envMock;\n}\n\n/**\n * 从文件模块映射中解析 API 配置\n * @description 配合 Vite 的 import.meta.glob 使用,自动匹配定义文件和 Mock 文件\n * @param definitionsMap API 定义文件映射 (import.meta.glob('./modules/*.ts', { eager: true }))\n * @param mocksMap Mock 文件映射 (import.meta.glob('./modules/*.mock.ts', { eager: true }))\n * @param useMock 是否启用 Mock (如果不传,将自动调用 isMockMode())\n * @returns 合并后的 ApiConfig\n */\nexport function resolveApiModules(\n definitionsMap: Record<string, any>,\n mocksMap: Record<string, any> = {}\n): ApiConfig {\n const config: ApiConfig = {};\n \n // 辅助函数:从路径中获取命名空间(去掉扩展名的文件名)\n const getNamespace = (path: string) => {\n // 处理 ./modules/chat.ts -> chat\n // 处理 /src/api/modules/user.ts -> user\n const fileName = path.split('/').pop() || '';\n // 移除 .mock.ts, .ts, .js, .json 等后缀\n return fileName.replace(/\\.mock\\.(ts|js|tsx|jsx|json)$/, '').replace(/\\.(ts|js|tsx|jsx|json)$/, '');\n };\n\n Object.entries(definitionsMap).forEach(([path, module]) => {\n // 跳过可能是 mock 的文件,防止它们意外进入 definitions glob\n if (path.includes('.mock.')) return;\n\n const namespace = getNamespace(path);\n if (!namespace || !module.default) return;\n\n let apiDef = module.default;\n \n // 始终尝试合并 Mock 数据\n // 这样即使在非 Mock 模式下,API 定义中也包含 Schema,方便动态切换\n const mockEntry = Object.entries(mocksMap).find(([mockPath]) => {\n return getNamespace(mockPath) === namespace && mockPath.includes('.mock.');\n });\n\n if (mockEntry) {\n const mockModule = mockEntry[1] as any;\n const mockData = mockModule.default || mockModule;\n if (mockData) {\n apiDef = mergeMockData(apiDef, mockData);\n }\n }\n\n config[namespace] = apiDef;\n });\n\n return config;\n}\n","import dayjs from 'dayjs';\nimport relativeTime from 'dayjs/plugin/relativeTime';\nimport 'dayjs/locale/zh-cn';\n\n// 加载插件\ndayjs.extend(relativeTime);\n// 设置默认语言\ndayjs.locale('zh-cn');\n\n/**\n * 日期时间格式化工具类\n */\nexport const dateUtils = {\n /**\n * 格式化日期为 YYYY-MM-DD\n */\n formatDate(date?: dayjs.ConfigType): string {\n return dayjs(date).format('YYYY-MM-DD');\n },\n\n /**\n * 格式化时间为 HH:mm:ss\n */\n formatTime(date?: dayjs.ConfigType): string {\n return dayjs(date).format('HH:mm:ss');\n },\n\n /**\n * 格式化日期时间为 YYYY-MM-DD HH:mm:ss\n */\n formatDateTime(date?: dayjs.ConfigType): string {\n return dayjs(date).format('YYYY-MM-DD HH:mm:ss');\n },\n\n /**\n * 获取当前时间戳(毫秒)\n */\n now(): number {\n return dayjs().valueOf();\n },\n\n /**\n * 获取相对时间(例如:几分钟前)\n */\n fromNow(date: dayjs.ConfigType): string {\n return dayjs(date).fromNow();\n },\n\n /**\n * 原始 dayjs 对象,用于更复杂的场景\n */\n dayjs,\n};\n\nexport default dateUtils;\n","export * from './logger';\nexport * from './date';\nexport * from './url';\nexport const version = '1.0.0';\n","import { useCallback,useState } from 'react';\n\nimport { pluginManager } from '../domain/plugin-manager';\n\n/**\n * Hook 配置选项\n */\nexport interface UseStorageStateOptions<T> {\n defaultValue?: T;\n scope?: 'plugin' | 'shared';\n}\n\n/**\n * 统一存储状态 Hook\n * @description 提供与 StorageManager 和 Schema Registry 集成的持久化状态 Hook。\n * @param pluginId 定义该 Key 的插件 ID\n * @param key 存储键名 (必须在 Schema 中注册)\n * @param options 配置项,包含默认值和作用域\n */\nexport function useStorageState<T>(pluginId: string, key: string, options: UseStorageStateOptions<T> = {}): [T, (value: T | ((val: T) => T)) => void] {\n const { defaultValue, scope = 'plugin' } = options;\n const storageManager = pluginManager.getStorageManager();\n \n const getStorage = useCallback(() => {\n const contextStorage = storageManager.getContextStorage(pluginId);\n return scope === 'shared' ? contextStorage.shared : contextStorage;\n }, [pluginId, scope, storageManager]);\n\n const [state, setState] = useState<T>(() => {\n try {\n if (typeof window === 'undefined') return defaultValue as T;\n const storage = getStorage();\n const val = storage.get<T>(key);\n return val !== null ? val : (defaultValue as T);\n } catch (e) {\n console.warn(`[useStorageState] 读取 Key \"${key}\" 失败`, e);\n return defaultValue as T;\n }\n });\n\n const setValue = useCallback((value: T | ((val: T) => T)) => {\n try {\n const valueToStore = value instanceof Function ? value(state) : value;\n setState(valueToStore);\n \n const storage = getStorage();\n storage.set(key, valueToStore);\n } catch (error) {\n console.warn(`[useStorageState] 设置 Key \"${key}\" 失败:`, error);\n }\n }, [key, state, getStorage]);\n\n return [state, setValue];\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { resolvePluginRegistry } from '../domain/auto-loader';\nimport { pluginManager } from '../domain/plugin-manager';\nimport { createLogger } from '../utils/logger';\n\nconst logger = createLogger('PluginLoader');\n\n/** 插件加载 Hook 的配置选项 */\nexport interface PluginLoaderOptions {\n /** 插件发现规则,定义如何从模块列表中识别插件 */\n discoveryRules?: any[];\n /** 插件模块映射,通常由 Vite 的 `import.meta.glob` 生成,键为路径,值为加载函数 */\n modules?: Record<string, () => Promise<any>>;\n /** 预注册的插件注册表,用于手动指定插件加载逻辑,优先级高于自动发现 */\n registry?: Record<string, () => Promise<any>>;\n /** 插件的业务配置映射,键为插件 ID */\n pluginConfigs: Record<string, any>;\n /** 初始化的共享上下文服务,将注入到每个插件的 onLoad 中 */\n sharedContext?: Record<string, any>;\n /** 系统级全局配置,如标题、版本号、Logo 等 */\n systemConfig?: Record<string, any>;\n /** 资源发现的基础 URL,默认为当前 window.location.origin */\n baseUrl?: string;\n}\n\n/**\n * 核心 Hook:通用插件加载器\n * @description 负责应用启动时的插件全生命周期管理:\n * 1. 自动发现:解析 modules 并根据规则识别插件。\n * 2. 注册:将插件信息录入 PluginManager。\n * 3. 加载:调用插件的加载逻辑 (onLoad)。\n * 4. 初始化:调用插件的挂载逻辑 (onMount)。\n * 5. 响应式更新:订阅插件状态变更并触发 UI 刷新。\n * \n * @param options - 加载配置项\n * @returns { pluginsLoaded: boolean, pluginVersion: number } \n * - pluginsLoaded: 插件是否已全部完成初始化\n * - pluginVersion: 插件状态版本号,用于强制触发依赖插件状态的组件重渲染\n */\nexport const usePluginLoader = (options: PluginLoaderOptions) => {\n const [pluginsLoaded, setPluginsLoaded] = useState(false);\n const [pluginVersion, setPluginVersion] = useState(0);\n const loadingRef = useRef(false);\n\n useEffect(() => {\n // 订阅插件管理器状态变更\n const unsubscribe = pluginManager.subscribe(() => {\n logger.debug('Plugin state changed, refreshing UI...');\n setPluginVersion((v) => v + 1);\n });\n\n const load = async () => {\n if (loadingRef.current || pluginsLoaded) return;\n loadingRef.current = true;\n\n try {\n const { \n discoveryRules = [], \n modules = {},\n registry: manualRegistry = {}, \n pluginConfigs, \n sharedContext = {}, \n baseUrl = (window as any).location.origin \n } = options;\n\n logger.info('Starting to load plugins...');\n \n // 1. 自动发现插件 (如果提供了模块)\n const discoveredRegistry = Object.keys(modules).length > 0\n ? resolvePluginRegistry({\n modules,\n rules: discoveryRules.length > 0 ? discoveryRules : undefined,\n })\n : {};\n\n // 2. 合并注册表 (手动注册优先)\n const finalRegistry = { ...discoveredRegistry, ...manualRegistry };\n\n // 2.5 注入系统配置到 configManager\n if (options.systemConfig) {\n const { configManager } = await import('../config-manager');\n configManager.set('system', options.systemConfig);\n }\n\n // 3. 加载插件 (初始加载时不触发通知,等待初始化完成后统一通知)\n await pluginManager.loadPlugins(pluginConfigs, finalRegistry, false);\n \n // 4. 初始化 (异步)\n await pluginManager.initPlugins(sharedContext);\n \n setPluginsLoaded(true);\n logger.info('Plugins loaded successfully');\n } catch (error) {\n logger.error('Failed to load plugins:', error);\n } finally {\n loadingRef.current = false;\n }\n };\n\n load();\n\n return () => {\n unsubscribe();\n };\n }, []);\n\n return {\n pluginsLoaded,\n pluginVersion\n };\n};\n"],"mappings":"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","names":["LogLevel","logger","logger","logger","logger","logger","jsx","logger","jsx","jsx","Component","logger","createContext","useContext","jsx","fetchResponse","logger","useState","useState","useEffect","useState","logger","useState","useEffect","configManager"]}
|