mirror of
https://github.com/SilenceLurker/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 10:05:50 +00:00
添加 ModelCaller 和 Options 类,重构 Logger,增强 Amily2Bus 架构,更新 README 和 TODO 文件
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import Logger from './log/Logger.js';
|
||||
import FilePipe from './file/FilePipe.js';
|
||||
import ModelCaller from './api/ModelCaller.js';
|
||||
import Options from './api/Options.js';
|
||||
|
||||
// 【逃生通道】创建一个纯净的 Console 对象,绕过任何潜在的劫持
|
||||
const getSafeConsole = () => {
|
||||
@@ -21,34 +23,87 @@ const getSafeConsole = () => {
|
||||
class Amily2Bus {
|
||||
constructor() {
|
||||
this.safeConsole = getSafeConsole();
|
||||
/** @type {Logger|null} */
|
||||
this.Logger = new Logger();
|
||||
/** @type {FilePipe|null} */
|
||||
this.FilePipe = new FilePipe();
|
||||
|
||||
// 已注册插件列表,防止重复注册
|
||||
this.registry = new Set();
|
||||
|
||||
this.safeConsole.log('[Amily2Bus] Core container initialized with secure registry.');
|
||||
// 1. 初始化 Logger
|
||||
/** @type {Logger} */
|
||||
this.Logger = new Logger(this.safeConsole);
|
||||
/** @type {FilePipe} */
|
||||
this.FilePipe = new FilePipe();
|
||||
|
||||
// 2. 依赖注入 (Dependency Injection)
|
||||
// 创建一个 Logger 代理适配器传给 ModelCaller
|
||||
const loggerDelegate = {
|
||||
log: (type, message, origin, plugin) => {
|
||||
// 回调 Bus 的 Logger 实例
|
||||
this.Logger.process(plugin || 'Global', origin || 'Model', type, message);
|
||||
}
|
||||
};
|
||||
|
||||
// ModelCaller 不再包含 Bus,只包含 logger 代理
|
||||
/** @type {ModelCaller} */
|
||||
this.ModelCaller = new ModelCaller(loggerDelegate);
|
||||
|
||||
// 存储上下文引用(严格锁:每个插件名仅限一次成功注册)
|
||||
this.registry = new Map();
|
||||
// 存储公开的联动接口(联动模块)
|
||||
this.publicRegistry = new Map();
|
||||
|
||||
this.safeConsole.log('[Amily2Bus] Core Initialized (Decoupled Architecture).');
|
||||
|
||||
// 3. 自动注册并锁定 PUBLIC 命名空间
|
||||
this._initPublicNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化系统保留的 PUBLIC 模块
|
||||
* 用于提供系统级信息的联动查询,防止 PUBLIC 命名被滥用
|
||||
*/
|
||||
_initPublicNamespace() {
|
||||
try {
|
||||
// 这里利用 register 的机制,直接抢占 'PUBLIC' 并加上严格锁
|
||||
const sysCtx = this.register('PUBLIC');
|
||||
|
||||
// 暴露系统级能力给 query('PUBLIC')
|
||||
sysCtx.expose({
|
||||
description: 'Amily2 System Public Interface',
|
||||
version: '2.0.0-Core',
|
||||
|
||||
// 允许查询当前有哪些插件暴露了公共接口
|
||||
getAvailableModules: () => {
|
||||
return Array.from(this.publicRegistry.keys());
|
||||
},
|
||||
|
||||
// 允许查询当前所有已注册(被锁定的)插件名
|
||||
getRegisteredPlugins: () => {
|
||||
return Array.from(this.registry.keys());
|
||||
},
|
||||
|
||||
// 简单的系统状态检查
|
||||
ping: () => 'pong'
|
||||
});
|
||||
|
||||
// 内部记录一条初始化日志
|
||||
sysCtx.log('System', 'info', 'PUBLIC namespace reserved and strictly locked.');
|
||||
|
||||
} catch (e) {
|
||||
this.safeConsole.error('[Amily2Bus] CRITICAL: Failed to init PUBLIC namespace.', e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 直接记录系统级日志 (Global Scope)
|
||||
* 支持手动指定来源,方便终端调试或非插件环境调用
|
||||
* @param {string} type 日志级别 (debug, info, warn, error)
|
||||
* @param {string} message 消息内容
|
||||
* @param {string} [origin='Bus'] 来源模块,默认为 'Bus'
|
||||
* @param {string} [origin='Bus' 来源模块,默认为 'Bus'
|
||||
* @param {string} [plugin='Global'] 来源插件/命名空间,调试时可指定如 'Console'
|
||||
*/
|
||||
log(type, message, origin = 'Bus', plugin = 'Global') {
|
||||
this.safeConsole.error('[Amily2Bus DEBUG] log called (via SafeConsole):', { type, loggerExists: !!this.Logger });
|
||||
if (this.Logger) {
|
||||
this.Logger.process(plugin, origin, type, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册插件并获取专属上下文
|
||||
* 注册插件并获取专属上下文 (严格锁机制)
|
||||
* @param {string} pluginName 插件名称
|
||||
* @returns {Object} 包含该插件专属 API 的上下文对象
|
||||
*/
|
||||
@@ -58,23 +113,17 @@ class Amily2Bus {
|
||||
}
|
||||
|
||||
if (this.registry.has(pluginName)) {
|
||||
console.warn(`[Amily2Bus] Plugin '${pluginName}' is already registered.`);
|
||||
} else {
|
||||
this.registry.add(pluginName);
|
||||
console.log(`[Amily2Bus] Plugin registered: ${pluginName}`);
|
||||
const errorMsg = `[Amily2Bus] Security Error: Plugin '${pluginName}' is already registered and locked.`;
|
||||
this.safeConsole.error(errorMsg);
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
// 返回该插件专属的 API 上下文 (Capability Token)
|
||||
return {
|
||||
// 绑定了身份的日志接口
|
||||
log: (origin, type, message) => {
|
||||
if (this.Logger) {
|
||||
// 自动填充 plugin 参数
|
||||
this.Logger.log(pluginName, origin, type, message);
|
||||
}
|
||||
},
|
||||
|
||||
// 绑定了身份的文件接口
|
||||
const context = {
|
||||
// 1. 日志能力 (绑定了身份的日志接口)
|
||||
log: (origin, type, message) => this.Logger.log(pluginName, origin, type, message),
|
||||
|
||||
// 2. 文件能力 (绑定了身份的文件接口)
|
||||
file: {
|
||||
read: (path) => {
|
||||
return this.FilePipe ? this.FilePipe.read(pluginName, path) : null;
|
||||
@@ -82,18 +131,49 @@ class Amily2Bus {
|
||||
write: (path, data) => {
|
||||
return this.FilePipe ? this.FilePipe.write(pluginName, path, data) : false;
|
||||
}
|
||||
},
|
||||
|
||||
// 3. 网络能力 (ModelCaller)
|
||||
model: {
|
||||
// 暴露 Options 类,方便插件直接 new context.model.Options() 或使用 builder
|
||||
Options: Options,
|
||||
// 插件调用时,Bus 负责将 pluginName 传给无状态的 ModelCaller
|
||||
call: (messages, options) => this.ModelCaller.call(pluginName, messages, options)
|
||||
},
|
||||
|
||||
/**
|
||||
* 将本插件的能力暴露给公共查询池,实现插件间联动
|
||||
* @param {Object} apiMethods
|
||||
*/
|
||||
expose: (apiMethods) => {
|
||||
if (typeof apiMethods !== 'object') throw new Error('Exposed API must be an object');
|
||||
this.publicRegistry.set(pluginName, Object.freeze(apiMethods));
|
||||
this.log('info', `Module exposed to public registry.`, 'Bus', pluginName);
|
||||
}
|
||||
};
|
||||
|
||||
this.registry.set(pluginName, context);
|
||||
this.safeConsole.log(`[Amily2Bus] Plugin registered: ${pluginName}`);
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 联动查询:获取其他插件通过 expose 暴露的能力
|
||||
* @param {string} pluginName 目标插件名称
|
||||
* @returns {Object|null}
|
||||
*/
|
||||
query(pluginName) {
|
||||
return this.publicRegistry.get(pluginName) || null;
|
||||
}
|
||||
}
|
||||
// 挂载全局单例 (自动初始化)
|
||||
if (!window.Amily2Bus || !(window.Amily2Bus instanceof Amily2Bus)) {
|
||||
// 挂载全局单例
|
||||
if (!window.Amily2Bus) {
|
||||
window.Amily2Bus = new Amily2Bus();
|
||||
}
|
||||
|
||||
export function initializeAmilyBus() {
|
||||
if (!window.Amily2Bus || !(window.Amily2Bus instanceof Amily2Bus)) {
|
||||
if (!(window.Amily2Bus instanceof Amily2Bus)) {
|
||||
window.Amily2Bus = new Amily2Bus();
|
||||
console.log('[Amily2] Amily2Bus 已成功初始化并附加到 window 对象');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user