@aalis/core 0.1.0
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/README.md +21 -0
- package/dist/app.d.ts +166 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +348 -0
- package/dist/app.js.map +1 -0
- package/dist/config.d.ts +174 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +377 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +31 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +36 -0
- package/dist/constants.js.map +1 -0
- package/dist/context.d.ts +328 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +521 -0
- package/dist/context.js.map +1 -0
- package/dist/disposable-chain.d.ts +31 -0
- package/dist/disposable-chain.d.ts.map +1 -0
- package/dist/disposable-chain.js +66 -0
- package/dist/disposable-chain.js.map +1 -0
- package/dist/events.d.ts +64 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +145 -0
- package/dist/events.js.map +1 -0
- package/dist/hooks.d.ts +49 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +102 -0
- package/dist/hooks.js.map +1 -0
- package/dist/i18n.d.ts +6 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +26 -0
- package/dist/i18n.js.map +1 -0
- package/dist/identity.d.ts +26 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +36 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +20 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +455 -0
- package/dist/init.js.map +1 -0
- package/dist/llm-router.d.ts.map +1 -0
- package/dist/llm-router.js +123 -0
- package/dist/llm-router.js.map +1 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +187 -0
- package/dist/logger.js.map +1 -0
- package/dist/marketplace-bootstrap.d.ts +54 -0
- package/dist/marketplace-bootstrap.d.ts.map +1 -0
- package/dist/marketplace-bootstrap.js +132 -0
- package/dist/marketplace-bootstrap.js.map +1 -0
- package/dist/mixin-registry.d.ts +34 -0
- package/dist/mixin-registry.d.ts.map +1 -0
- package/dist/mixin-registry.js +60 -0
- package/dist/mixin-registry.js.map +1 -0
- package/dist/model-ref.d.ts +22 -0
- package/dist/model-ref.d.ts.map +1 -0
- package/dist/model-ref.js +46 -0
- package/dist/model-ref.js.map +1 -0
- package/dist/pending-buffer.d.ts +46 -0
- package/dist/pending-buffer.d.ts.map +1 -0
- package/dist/pending-buffer.js +131 -0
- package/dist/pending-buffer.js.map +1 -0
- package/dist/platform-registry.d.ts +40 -0
- package/dist/platform-registry.d.ts.map +1 -0
- package/dist/platform-registry.js +64 -0
- package/dist/platform-registry.js.map +1 -0
- package/dist/plugin-activation.d.ts +43 -0
- package/dist/plugin-activation.d.ts.map +1 -0
- package/dist/plugin-activation.js +172 -0
- package/dist/plugin-activation.js.map +1 -0
- package/dist/plugin-topology.d.ts +40 -0
- package/dist/plugin-topology.d.ts.map +1 -0
- package/dist/plugin-topology.js +126 -0
- package/dist/plugin-topology.js.map +1 -0
- package/dist/plugin.d.ts +184 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +549 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers.d.ts +85 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +2 -0
- package/dist/providers.js.map +1 -0
- package/dist/semver-mini.d.ts +20 -0
- package/dist/semver-mini.d.ts.map +1 -0
- package/dist/semver-mini.js +94 -0
- package/dist/semver-mini.js.map +1 -0
- package/dist/service-helpers.d.ts +34 -0
- package/dist/service-helpers.d.ts.map +1 -0
- package/dist/service-helpers.js +68 -0
- package/dist/service-helpers.js.map +1 -0
- package/dist/service.d.ts +145 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +279 -0
- package/dist/service.js.map +1 -0
- package/dist/types/agent.d.ts +51 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +3 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/app.d.ts +74 -0
- package/dist/types/app.d.ts.map +1 -0
- package/dist/types/app.js +3 -0
- package/dist/types/app.js.map +1 -0
- package/dist/types/archive.d.ts +59 -0
- package/dist/types/archive.d.ts.map +1 -0
- package/dist/types/archive.js +16 -0
- package/dist/types/archive.js.map +1 -0
- package/dist/types/authority.d.ts +63 -0
- package/dist/types/authority.d.ts.map +1 -0
- package/dist/types/authority.js +3 -0
- package/dist/types/authority.js.map +1 -0
- package/dist/types/capabilities.d.ts +53 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +87 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/cli.d.ts +14 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +3 -0
- package/dist/types/cli.js.map +1 -0
- package/dist/types/commands.d.ts +98 -0
- package/dist/types/commands.d.ts.map +1 -0
- package/dist/types/commands.js +3 -0
- package/dist/types/commands.js.map +1 -0
- package/dist/types/core.d.ts +117 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +6 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/disposable-service.d.ts +31 -0
- package/dist/types/disposable-service.d.ts.map +1 -0
- package/dist/types/disposable-service.js +3 -0
- package/dist/types/disposable-service.js.map +1 -0
- package/dist/types/embedding.d.ts +7 -0
- package/dist/types/embedding.d.ts.map +1 -0
- package/dist/types/embedding.js +3 -0
- package/dist/types/embedding.js.map +1 -0
- package/dist/types/flow-control.d.ts +51 -0
- package/dist/types/flow-control.d.ts.map +1 -0
- package/dist/types/flow-control.js +12 -0
- package/dist/types/flow-control.js.map +1 -0
- package/dist/types/gateway.d.ts +24 -0
- package/dist/types/gateway.d.ts.map +1 -0
- package/dist/types/gateway.js +15 -0
- package/dist/types/gateway.js.map +1 -0
- package/dist/types/hooks.d.ts +3 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +18 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/image-recognition.d.ts +123 -0
- package/dist/types/image-recognition.d.ts.map +1 -0
- package/dist/types/image-recognition.js +31 -0
- package/dist/types/image-recognition.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +17 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/llm.d.ts +146 -0
- package/dist/types/llm.d.ts.map +1 -0
- package/dist/types/llm.js +27 -0
- package/dist/types/llm.js.map +1 -0
- package/dist/types/memory.d.ts +62 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +22 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/persona.d.ts +45 -0
- package/dist/types/persona.d.ts.map +1 -0
- package/dist/types/persona.js +3 -0
- package/dist/types/persona.js.map +1 -0
- package/dist/types/platform.d.ts +126 -0
- package/dist/types/platform.d.ts.map +1 -0
- package/dist/types/platform.js +5 -0
- package/dist/types/platform.js.map +1 -0
- package/dist/types/plugin.d.ts +84 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +24 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/types/service.d.ts +43 -0
- package/dist/types/service.d.ts.map +1 -0
- package/dist/types/service.js +38 -0
- package/dist/types/service.js.map +1 -0
- package/dist/types/services.d.ts +17 -0
- package/dist/types/services.d.ts.map +1 -0
- package/dist/types/services.js +41 -0
- package/dist/types/services.js.map +1 -0
- package/dist/types/session.d.ts +153 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +19 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/storage.d.ts +100 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js +29 -0
- package/dist/types/storage.js.map +1 -0
- package/dist/types/tools.d.ts +39 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +3 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/types/trigger-policy.d.ts +16 -0
- package/dist/types/trigger-policy.d.ts.map +1 -0
- package/dist/types/trigger-policy.js +6 -0
- package/dist/types/trigger-policy.js.map +1 -0
- package/dist/types/vectorstore.d.ts +23 -0
- package/dist/types/vectorstore.d.ts.map +1 -0
- package/dist/types/vectorstore.js +3 -0
- package/dist/types/vectorstore.js.map +1 -0
- package/dist/types/web-search.d.ts +88 -0
- package/dist/types/web-search.d.ts.map +1 -0
- package/dist/types/web-search.js +23 -0
- package/dist/types/web-search.js.map +1 -0
- package/dist/types/webui.d.ts +137 -0
- package/dist/types/webui.d.ts.map +1 -0
- package/dist/types/webui.js +3 -0
- package/dist/types/webui.js.map +1 -0
- package/package.json +22 -0
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
import { activatePlugin, computeTargetState, ensureServiceProvider } from './plugin-activation.js';
|
|
2
|
+
import { evictDownstreamConsumers, topoSortByDeps } from './plugin-topology.js';
|
|
3
|
+
import { normalizeDependency } from './service.js';
|
|
4
|
+
import { parseInstanceId, } from './types/plugin.js';
|
|
5
|
+
// 类型与纯辅助 re-export,保留同名旧导入路径
|
|
6
|
+
export { parseInstanceId };
|
|
7
|
+
/**
|
|
8
|
+
* 插件管理器
|
|
9
|
+
*
|
|
10
|
+
* 负责:
|
|
11
|
+
* - 注册/加载/卸载插件
|
|
12
|
+
* - 依赖追踪 (required + optional, 支持 capability 匹配)
|
|
13
|
+
* - 当所需服务就绪时自动激活插件
|
|
14
|
+
* - 当所需服务移除时自动停用插件
|
|
15
|
+
* - 插件启用/禁用控制
|
|
16
|
+
*/
|
|
17
|
+
export class PluginManager {
|
|
18
|
+
plugins = new Map();
|
|
19
|
+
rootCtx;
|
|
20
|
+
logger;
|
|
21
|
+
/** recompute 单飞标志:true 表示一次 recompute(含排队补跑)正在进行 */
|
|
22
|
+
reloading = false;
|
|
23
|
+
/**
|
|
24
|
+
* 手动 dispose 段计数器:disablePlugin / unload / bouncePlugin 在「dispose 旧
|
|
25
|
+
* ctx → 改 entry.state」这段不可分割的状态变更期间 +1。期间 dispose 触发的
|
|
26
|
+
* service:unregistered 反应式 recompute 会被**排队**(而非立即跑——那会看到
|
|
27
|
+
* 半成品状态,比如把正在禁用的插件重新激活),由这些方法收尾的 softReload 统一消化。
|
|
28
|
+
*
|
|
29
|
+
* 用计数器而非布尔:dispose hook 内可能同步级联调用 disablePlugin/unload(级联
|
|
30
|
+
* 禁用),嵌套时内层的 finally 若复位布尔会过早解除外层的挂起态——计数器确保
|
|
31
|
+
* 只有最外层退出(归零)才解除(审计 HIGH #3)。
|
|
32
|
+
*/
|
|
33
|
+
suspendDepth = 0;
|
|
34
|
+
get suspended() {
|
|
35
|
+
return this.suspendDepth > 0;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 被推迟的 recompute 请求(修 lost wakeup:在飞期间到达的请求不再被丢弃)。
|
|
39
|
+
* 多个请求合并为一——除 shutdown 保留原 reason 外统一退化为
|
|
40
|
+
* plugin-state-changed(service-up/down 的特殊语义本就只在第一轮生效)。
|
|
41
|
+
*/
|
|
42
|
+
queuedReason = null;
|
|
43
|
+
/**
|
|
44
|
+
* 全局关机标志。app.stop() 在 dispose 前置位,所有反应式级联(service:registered/
|
|
45
|
+
* unregistered → checkPending/Active)都会因此跳过——避免「正在关机还去 bounce
|
|
46
|
+
* 一个永远不会被重新激活的插件」这种无意义噪声,也避免下游插件 dispose 中
|
|
47
|
+
* 试图 register 命令 / 监听服务等动作触发误重入。
|
|
48
|
+
*/
|
|
49
|
+
shuttingDown = false;
|
|
50
|
+
/** 是否正在关机——供插件 dispose hook 短路用 */
|
|
51
|
+
isShuttingDown() {
|
|
52
|
+
return this.shuttingDown;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 必需服务列表: softReload 完成后若缺失会自动恢复。
|
|
56
|
+
* 由 App 设置。
|
|
57
|
+
*/
|
|
58
|
+
requiredServices = [];
|
|
59
|
+
/**
|
|
60
|
+
* 必需服务恢复政策(由 App 从 AppOptions.serviceRecovery 设置)。
|
|
61
|
+
* autoEnableDisabled=false 时恢复路径不会自动启用被用户禁用的提供者插件。
|
|
62
|
+
*/
|
|
63
|
+
recoveryPolicy = { autoEnableDisabled: true };
|
|
64
|
+
constructor(rootCtx, logger) {
|
|
65
|
+
this.rootCtx = rootCtx;
|
|
66
|
+
this.logger = logger.child('plugins');
|
|
67
|
+
// 监听服务注册/注销,路由到统一 recompute()。
|
|
68
|
+
// 单飞/挂起/关机的取舍都在 recompute 内部处理(在飞期间排队,关机后跳过)。
|
|
69
|
+
rootCtx.on('service:registered', name => {
|
|
70
|
+
this.recompute({ type: 'service-up', service: name }).catch(err => {
|
|
71
|
+
this.logger.error(`recompute(service-up:${name}) 报错: ${err instanceof Error ? err.message : String(err)}`);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
rootCtx.on('service:unregistered', name => {
|
|
75
|
+
this.recompute({ type: 'service-down', service: name }).catch(err => {
|
|
76
|
+
this.logger.error(`recompute(service-down:${name}) 报错: ${err instanceof Error ? err.message : String(err)}`);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 注册并尝试加载一个插件
|
|
82
|
+
*
|
|
83
|
+
* @param module 插件模块
|
|
84
|
+
* @param config 插件配置
|
|
85
|
+
* @param instanceId 实例 ID(多实例时为 `name:suffix`,留空则使用 module.name)
|
|
86
|
+
*/
|
|
87
|
+
async register(module, config = {}, instanceId) {
|
|
88
|
+
const id = instanceId ?? module.name;
|
|
89
|
+
// 多实例检查:同一 module 非 reusable 时不允许重复注册
|
|
90
|
+
if (this.plugins.has(id)) {
|
|
91
|
+
this.logger.warn(`插件 "${id}" 已注册,跳过`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (id !== module.name && !module.reusable) {
|
|
95
|
+
this.logger.warn(`插件 "${module.name}" 未声明 reusable,不允许多实例注册 "${id}"`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const inject = module.inject ?? {};
|
|
99
|
+
const requiredDeps = (inject.required ?? []).map(normalizeDependency);
|
|
100
|
+
const optionalDeps = (inject.optional ?? []).map(normalizeDependency);
|
|
101
|
+
// 检查是否被配置禁用(按 instanceId 检查)
|
|
102
|
+
const isDisabled = this.rootCtx.config.isPluginDisabled(id);
|
|
103
|
+
const entry = {
|
|
104
|
+
module,
|
|
105
|
+
instanceId: id,
|
|
106
|
+
config,
|
|
107
|
+
state: isDisabled ? 'disabled' : 'pending',
|
|
108
|
+
requiredDeps,
|
|
109
|
+
optionalDeps,
|
|
110
|
+
};
|
|
111
|
+
this.plugins.set(id, entry);
|
|
112
|
+
if (isDisabled) {
|
|
113
|
+
this.logger.info(`插件已注册(禁用): ${id}`);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
this.logger.info(`插件已注册: ${id}`);
|
|
117
|
+
// 走统一 recompute:依赖满足则被拓扑正序激活,否则保持 pending
|
|
118
|
+
await this.recompute({ type: 'plugin-state-changed' });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 卸载一个插件
|
|
123
|
+
*/
|
|
124
|
+
async unload(name) {
|
|
125
|
+
const entry = this.plugins.get(name);
|
|
126
|
+
if (!entry)
|
|
127
|
+
return;
|
|
128
|
+
// dispose 段守卫(与 disablePlugin 对齐):dispose 触发的反应式 recompute
|
|
129
|
+
// 排队到收尾的 softReload,避免在 entry 半卸载态下重算。
|
|
130
|
+
this.suspendDepth++;
|
|
131
|
+
try {
|
|
132
|
+
if (entry.state === 'active' && entry.context) {
|
|
133
|
+
entry.context.dispose();
|
|
134
|
+
entry.context = undefined;
|
|
135
|
+
this.rootCtx.emit('plugin:unloaded', name).catch(err => {
|
|
136
|
+
this.logger.warn(`emit plugin:unloaded 失败 (${name}): ${err}`);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
entry.state = 'disposed';
|
|
140
|
+
this.plugins.delete(name);
|
|
141
|
+
this.logger.info(`插件已卸载: ${name}`);
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
this.suspendDepth--;
|
|
145
|
+
}
|
|
146
|
+
// 级联重算:依赖被卸载插件所提供服务的下游需要转 pending
|
|
147
|
+
await this.softReload();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* 启用一个已禁用的插件
|
|
151
|
+
*/
|
|
152
|
+
async enablePlugin(name) {
|
|
153
|
+
const entry = this.plugins.get(name);
|
|
154
|
+
if (!entry)
|
|
155
|
+
return false;
|
|
156
|
+
if (entry.state !== 'disabled' && entry.state !== 'error')
|
|
157
|
+
return true; // 已经启用
|
|
158
|
+
entry.state = 'pending';
|
|
159
|
+
entry.error = undefined;
|
|
160
|
+
this.rootCtx.config.setPluginEnabled(name, true);
|
|
161
|
+
this.logger.info(`插件已启用: ${name}`);
|
|
162
|
+
await this.softReload();
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* 禁用一个活跃的插件(core 插件不能禁用)
|
|
167
|
+
*/
|
|
168
|
+
async disablePlugin(name) {
|
|
169
|
+
const entry = this.plugins.get(name);
|
|
170
|
+
if (!entry)
|
|
171
|
+
return false;
|
|
172
|
+
if (entry.module.core) {
|
|
173
|
+
this.logger.warn(`核心插件 "${name}" 不能被禁用`);
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
if (entry.state === 'disabled')
|
|
177
|
+
return true; // 已经禁用
|
|
178
|
+
// dispose 段守卫:期间反应式 recompute 排队到收尾的 softReload
|
|
179
|
+
this.suspendDepth++;
|
|
180
|
+
try {
|
|
181
|
+
if (entry.state === 'active' && entry.context) {
|
|
182
|
+
entry.context.dispose();
|
|
183
|
+
entry.context = undefined;
|
|
184
|
+
this.rootCtx.emit('plugin:unloaded', name).catch(err => {
|
|
185
|
+
this.logger.warn(`emit plugin:unloaded 失败 (${name}): ${err}`);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
entry.state = 'disabled';
|
|
189
|
+
this.rootCtx.config.setPluginEnabled(name, false);
|
|
190
|
+
this.logger.info(`插件已禁用: ${name}`);
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
this.suspendDepth--;
|
|
194
|
+
}
|
|
195
|
+
await this.softReload();
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* 获取所有已注册插件的状态
|
|
200
|
+
*
|
|
201
|
+
* 返回类型即 PluginManagerService 接口的 PluginStatusEntry(types/app.ts),
|
|
202
|
+
* 编译期保证两边不漂移。
|
|
203
|
+
*/
|
|
204
|
+
getStatus() {
|
|
205
|
+
return [...this.plugins.entries()].map(([, entry]) => {
|
|
206
|
+
// subsystem / extends 由 @aalis/plugin-webui-api 通过 declaration merging
|
|
207
|
+
// 注入,core 不感知其语义,仅透传给 listPlugins() 调用方。
|
|
208
|
+
// 实际消费者:plugin-webui-server(按 subsystem 将插件归组渲染到 dashboard,
|
|
209
|
+
// 见 packages/plugin-webui-server/src/index.ts)。"core 不消费 ≠ 系统未消费"。
|
|
210
|
+
const m = entry.module;
|
|
211
|
+
return {
|
|
212
|
+
name: entry.module.name,
|
|
213
|
+
instanceId: entry.instanceId,
|
|
214
|
+
displayName: entry.module.displayName,
|
|
215
|
+
subsystem: m.subsystem,
|
|
216
|
+
state: entry.state,
|
|
217
|
+
provides: entry.module.provides,
|
|
218
|
+
core: entry.module.core,
|
|
219
|
+
reusable: entry.module.reusable,
|
|
220
|
+
extends: m.extends,
|
|
221
|
+
requiredServices: entry.requiredDeps.length > 0 ? entry.requiredDeps.map(d => d.service) : undefined,
|
|
222
|
+
optionalServices: entry.optionalDeps.length > 0 ? entry.optionalDeps.map(d => d.service) : undefined,
|
|
223
|
+
config: entry.config,
|
|
224
|
+
configSchema: entry.module.configSchema,
|
|
225
|
+
defaultConfig: entry.module.defaultConfig,
|
|
226
|
+
error: entry.error,
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 获取单个插件
|
|
232
|
+
*/
|
|
233
|
+
getPlugin(name) {
|
|
234
|
+
return this.plugins.get(name);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* 更新插件配置(thin alias,转发到 bouncePlugin)。保留独立方法名是为了
|
|
238
|
+
* 让 host 层调用点(WebUI / 配置文件热重载)语义清晰且向后兼容。
|
|
239
|
+
*/
|
|
240
|
+
async updatePluginConfig(name, config) {
|
|
241
|
+
return this.bouncePlugin(name, { config });
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 增量重载单个插件(核心入口):
|
|
245
|
+
*
|
|
246
|
+
* 1. 持久化新 config(如有)+ 替换 module(如有)+ dispose 旧 ctx
|
|
247
|
+
* + 转 pending + softReload 重新激活。下游消费者默认不会被级联 bounce,
|
|
248
|
+
* 除非显式声明 `requiresBounceOnDepChange: true`(见 evictDownstreamConsumers)。
|
|
249
|
+
* 2. `error` 态插件会被重置为 pending 重试 apply。
|
|
250
|
+
*
|
|
251
|
+
* 不负责"重新从磁盘 import"——那是宿主层的职责。
|
|
252
|
+
*
|
|
253
|
+
* @returns false 表示找不到 entry 或处于 disabled 态(拒绝 bounce)。
|
|
254
|
+
*/
|
|
255
|
+
async bouncePlugin(name, opts) {
|
|
256
|
+
const entry = this.plugins.get(name);
|
|
257
|
+
if (!entry)
|
|
258
|
+
return false;
|
|
259
|
+
if (entry.state === 'disabled') {
|
|
260
|
+
this.logger.warn(`bouncePlugin: 插件 "${name}" 处于 disabled 态,跳过`);
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
const newConfig = opts?.config;
|
|
264
|
+
const newModule = opts?.module;
|
|
265
|
+
if (newConfig) {
|
|
266
|
+
entry.config = newConfig;
|
|
267
|
+
this.rootCtx.config.setPluginConfig(name, newConfig);
|
|
268
|
+
}
|
|
269
|
+
if (newModule)
|
|
270
|
+
entry.module = newModule;
|
|
271
|
+
// dispose 段守卫(与 disablePlugin / unload 对齐):dispose 触发的反应式
|
|
272
|
+
// recompute 不能在 entry 尚未转 pending 时跑——会把半 bounce 态误判。
|
|
273
|
+
this.suspendDepth++;
|
|
274
|
+
try {
|
|
275
|
+
if (entry.state === 'active' && entry.context) {
|
|
276
|
+
evictDownstreamConsumers({
|
|
277
|
+
provider: entry,
|
|
278
|
+
plugins: this.plugins,
|
|
279
|
+
rootCtx: this.rootCtx,
|
|
280
|
+
logger: this.logger,
|
|
281
|
+
});
|
|
282
|
+
entry.context.dispose();
|
|
283
|
+
entry.context = undefined;
|
|
284
|
+
this.rootCtx.emit('plugin:unloaded', name).catch(err => {
|
|
285
|
+
this.logger.warn(`emit plugin:unloaded 失败 (${name}): ${err}`);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
entry.state = 'pending';
|
|
289
|
+
entry.error = undefined;
|
|
290
|
+
}
|
|
291
|
+
finally {
|
|
292
|
+
this.suspendDepth--;
|
|
293
|
+
}
|
|
294
|
+
await this.softReload();
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* 在运行时基于 reusable 模块新增一个实例(写入配置 + 触发激活)。
|
|
299
|
+
*
|
|
300
|
+
* @param moduleName 原始模块名(如 `@aalis/plugin-openai`)
|
|
301
|
+
* @param suffix 实例后缀(如 `vision`),将生成 instanceId `moduleName:suffix`
|
|
302
|
+
* @param config 新实例的配置
|
|
303
|
+
* @returns 新实例的 instanceId,失败返回 undefined
|
|
304
|
+
*/
|
|
305
|
+
async createInstance(moduleName, suffix, config = {}) {
|
|
306
|
+
// 从已注册的插件中查找同 module 的 entry
|
|
307
|
+
let sourceModule;
|
|
308
|
+
for (const entry of this.plugins.values()) {
|
|
309
|
+
if (entry.module.name === moduleName) {
|
|
310
|
+
sourceModule = entry.module;
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (!sourceModule) {
|
|
315
|
+
this.logger.warn(`创建实例失败: 模块 "${moduleName}" 未找到`);
|
|
316
|
+
return undefined;
|
|
317
|
+
}
|
|
318
|
+
if (!sourceModule.reusable) {
|
|
319
|
+
this.logger.warn(`创建实例失败: 模块 "${moduleName}" 未声明 reusable`);
|
|
320
|
+
return undefined;
|
|
321
|
+
}
|
|
322
|
+
const instanceId = `${moduleName}:${suffix}`;
|
|
323
|
+
if (this.plugins.has(instanceId)) {
|
|
324
|
+
this.logger.warn(`创建实例失败: "${instanceId}" 已存在`);
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
// 合并配置:默认配置 ← 传入配置
|
|
328
|
+
const defaults = sourceModule.defaultConfig ?? {};
|
|
329
|
+
const mergedConfig = { ...defaults, ...config };
|
|
330
|
+
// 写入配置文件
|
|
331
|
+
this.rootCtx.config.setPluginConfig(instanceId, mergedConfig);
|
|
332
|
+
// 注册并尝试激活
|
|
333
|
+
await this.register(sourceModule, mergedConfig, instanceId);
|
|
334
|
+
return instanceId;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* 移除一个多实例插件(不允许移除主实例)
|
|
338
|
+
*/
|
|
339
|
+
async removeInstance(instanceId) {
|
|
340
|
+
const { suffix } = parseInstanceId(instanceId);
|
|
341
|
+
if (!suffix) {
|
|
342
|
+
this.logger.warn(`不能移除主实例 "${instanceId}"`);
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
const entry = this.plugins.get(instanceId);
|
|
346
|
+
if (!entry)
|
|
347
|
+
return false;
|
|
348
|
+
// 卸载
|
|
349
|
+
await this.unload(instanceId);
|
|
350
|
+
// 从配置文件中移除
|
|
351
|
+
this.rootCtx.config.removePluginConfig(instanceId);
|
|
352
|
+
await this.softReload();
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* 全局停机:按依赖拓扑逆序 dispose 所有 active 插件。
|
|
357
|
+
*
|
|
358
|
+
* 顺序原则:「消费者先关,提供者后关」——一个插件若 require/optional 依赖另一个
|
|
359
|
+
* 插件 provides 的服务,则前者 dispose 必须先于后者。这样下游插件的 dispose hook
|
|
360
|
+
* 还能安全地访问其依赖的服务(如把待持久化数据冲到 storage、把订阅从 gateway 摘掉)。
|
|
361
|
+
*
|
|
362
|
+
* 实现是 Kahn 风格 BFS:
|
|
363
|
+
* 1. 把 active 插件构成「依赖图」边:consumer → provider(基于 module.provides)
|
|
364
|
+
* 2. 反复挑出 in-degree==0 的节点(没人依赖它们 = 处于拓扑顶端 = 应当先 dispose)
|
|
365
|
+
* 3. dispose 后从图中移除,刷新 in-degree
|
|
366
|
+
* 4. 若残留环(不应该发生,softReload 期间会警告),按声明顺序 dispose 兜底
|
|
367
|
+
*
|
|
368
|
+
* 此方法预设 `shuttingDown=true`,service:unregistered 不再触发反应式 bounce;
|
|
369
|
+
* 因此本方法是**关机时唯一**的 dispose 编排者,不与级联机制竞争。
|
|
370
|
+
*/
|
|
371
|
+
async stopAll() {
|
|
372
|
+
await this.recompute({ type: 'shutdown' });
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* 软重载(薄壳):把"插件状态需要重算"统一委托给 recompute()。
|
|
376
|
+
*
|
|
377
|
+
* 历史上 softReload / stopAll / checkActivePlugins / checkPendingPlugins 是四
|
|
378
|
+
* 条独立路径,每条都自己判断"哪些插件该跑、按什么顺序"。逻辑漂移导致 stopAll
|
|
379
|
+
* 之外的三条路径在"同一轮多个插件同时变状态"时无法保证消费者先于提供者关闭,
|
|
380
|
+
* 瞬态会出现 dispose hook 访问已失效服务的情况。现在四条路径共用 recompute()。
|
|
381
|
+
*/
|
|
382
|
+
async softReload() {
|
|
383
|
+
await this.recompute({ type: 'plugin-state-changed' });
|
|
384
|
+
}
|
|
385
|
+
// ---- 单一状态转移入口 ----
|
|
386
|
+
/**
|
|
387
|
+
* 重算所有插件的目标态并按依赖拓扑序应用转移。
|
|
388
|
+
*
|
|
389
|
+
* 这是 PluginManager 唯一的状态变更入口(除 ensureServiceProvider 这种显式
|
|
390
|
+
* 启用 disabled 提供者的恢复策略之外)。
|
|
391
|
+
*
|
|
392
|
+
* 算法:
|
|
393
|
+
* 1. 反应式 reason 决定"是否走完整 fixed-point + 是否触发 optional bounce";
|
|
394
|
+
* shutdown 走单向 down 路径,其它走 fixed-point。
|
|
395
|
+
* 2. 每轮先按依赖正序(提供者→消费者)做拓扑排序。
|
|
396
|
+
* 3. Phase A:反向遍历,把"目标不再 active"的 entry 一并 dispose
|
|
397
|
+
* (消费者先关、提供者后关,dispose hook 访问依赖服务安全)。
|
|
398
|
+
* 4. Phase B(非 shutdown):正向遍历,激活"目标 active 且依赖满足"的 pending entry
|
|
399
|
+
* (提供者先起、消费者后起)。
|
|
400
|
+
* 5. 若本轮有变动则继续下一轮,直到稳定或达到 maxRounds。
|
|
401
|
+
* 6. 非 shutdown 时检查必需服务并发出 plugins:changed。
|
|
402
|
+
*
|
|
403
|
+
* Aalis 直接用"服务在不在 + capabilities 命中"
|
|
404
|
+
* 做判断 —— 表达力等价、复杂度更低。
|
|
405
|
+
*/
|
|
406
|
+
async recompute(reason) {
|
|
407
|
+
if (this.shuttingDown && reason.type !== 'shutdown') {
|
|
408
|
+
// 关机已置位时非关机请求无意义;但若队列里躺着一个被挂起的 shutdown
|
|
409
|
+
// (stop() 与手动 dispose 段竞态),借这次调用把它接过来跑完。
|
|
410
|
+
if (this.queuedReason?.type !== 'shutdown')
|
|
411
|
+
return;
|
|
412
|
+
reason = this.queuedReason;
|
|
413
|
+
this.queuedReason = null;
|
|
414
|
+
}
|
|
415
|
+
if (reason.type === 'shutdown')
|
|
416
|
+
this.shuttingDown = true;
|
|
417
|
+
// 单飞 + 排队(修 lost wakeup):在飞期间/手动 dispose 段的请求合并排队,
|
|
418
|
+
// 由在飞 run 收尾时补跑或 dispose 段收尾的 softReload 消化。注意这里必须
|
|
419
|
+
// 立即返回而不能把在飞 promise 交还调用方——若调用方恰在某插件 apply()
|
|
420
|
+
// 内同步调用(在飞 run 正 await 它),等待在飞 promise 会自我死锁。
|
|
421
|
+
if (this.reloading || this.suspended) {
|
|
422
|
+
this.queuedReason = reason.type === 'shutdown' ? reason : (this.queuedReason ?? { type: 'plugin-state-changed' });
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
this.reloading = true;
|
|
426
|
+
try {
|
|
427
|
+
let current = reason;
|
|
428
|
+
while (current) {
|
|
429
|
+
await this.recomputeOnce(current);
|
|
430
|
+
current = this.queuedReason;
|
|
431
|
+
this.queuedReason = null;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
finally {
|
|
435
|
+
this.reloading = false;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/** 单次完整重算:fixed-point 状态转移 + (非关机)必需服务恢复与 plugins:changed 通知 */
|
|
439
|
+
async recomputeOnce(reason) {
|
|
440
|
+
let currentReason = reason;
|
|
441
|
+
let changed = true;
|
|
442
|
+
let rounds = 0;
|
|
443
|
+
const maxRounds = 20;
|
|
444
|
+
while (changed && rounds < maxRounds) {
|
|
445
|
+
changed = false;
|
|
446
|
+
rounds++;
|
|
447
|
+
const entries = [...this.plugins.values()];
|
|
448
|
+
const order = topoSortByDeps(entries, this.logger);
|
|
449
|
+
// Phase A: 反向遍历,关掉目标不是 active 的 active entry
|
|
450
|
+
for (const entry of [...order].reverse()) {
|
|
451
|
+
if (entry.state !== 'active')
|
|
452
|
+
continue;
|
|
453
|
+
const target = computeTargetState(entry, currentReason, this.rootCtx);
|
|
454
|
+
if (target === 'active')
|
|
455
|
+
continue;
|
|
456
|
+
// 日志:区分 shutdown / required 不满 / optional bounce
|
|
457
|
+
if (currentReason.type === 'shutdown') {
|
|
458
|
+
// 静默
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
const unmet = entry.requiredDeps.find(d => !this.rootCtx.hasService(d.service, d.capabilities.length > 0 ? d.capabilities : undefined));
|
|
462
|
+
if (unmet) {
|
|
463
|
+
this.logger.info(`依赖 "${unmet.service}" 不可用,停用插件: ${entry.instanceId}`);
|
|
464
|
+
}
|
|
465
|
+
else if (currentReason.type === 'service-down') {
|
|
466
|
+
// 被动级联降级(依赖服务下线 → 转 pending 等待重新满足),
|
|
467
|
+
// 区别于 bouncePlugin() 的主动重载,措辞不混用 bounce。
|
|
468
|
+
this.logger.info(`依赖服务 "${currentReason.service}" 已下线,降级插件为待激活: ${entry.instanceId}`);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (entry.context) {
|
|
472
|
+
try {
|
|
473
|
+
entry.context.dispose();
|
|
474
|
+
}
|
|
475
|
+
catch (err) {
|
|
476
|
+
this.logger.error(`插件 "${entry.instanceId}" dispose 抛错: ${err instanceof Error ? err.message : String(err)}`);
|
|
477
|
+
}
|
|
478
|
+
entry.context = undefined;
|
|
479
|
+
}
|
|
480
|
+
entry.state = currentReason.type === 'shutdown' ? 'disposed' : 'pending';
|
|
481
|
+
if (currentReason.type !== 'shutdown') {
|
|
482
|
+
this.rootCtx.emit('plugin:unloaded', entry.instanceId).catch(err => {
|
|
483
|
+
this.logger.warn(`emit plugin:unloaded 失败 (${entry.instanceId}): ${err}`);
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
changed = true;
|
|
487
|
+
}
|
|
488
|
+
// 关机不需要再激活
|
|
489
|
+
if (currentReason.type === 'shutdown')
|
|
490
|
+
break;
|
|
491
|
+
// Phase B: 正向遍历,激活目标 active 的 pending entry
|
|
492
|
+
for (const entry of order) {
|
|
493
|
+
if (entry.state !== 'pending')
|
|
494
|
+
continue;
|
|
495
|
+
const target = computeTargetState(entry, currentReason, this.rootCtx);
|
|
496
|
+
if (target !== 'active')
|
|
497
|
+
continue;
|
|
498
|
+
await activatePlugin(entry, { plugins: this.plugins, rootCtx: this.rootCtx, logger: this.logger });
|
|
499
|
+
if (entry.state === 'active')
|
|
500
|
+
changed = true;
|
|
501
|
+
}
|
|
502
|
+
// service-up / service-down 的"特殊语义"只在第一轮生效(避免无限 bounce);
|
|
503
|
+
// 第二轮起退化为普通的 plugin-state-changed 重算。
|
|
504
|
+
if (currentReason.type === 'service-up' || currentReason.type === 'service-down') {
|
|
505
|
+
currentReason = { type: 'plugin-state-changed' };
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (rounds >= maxRounds) {
|
|
509
|
+
this.logger.warn('recompute 达到最大迭代次数,可能存在循环依赖');
|
|
510
|
+
}
|
|
511
|
+
if (reason.type === 'shutdown')
|
|
512
|
+
return;
|
|
513
|
+
// 必需服务自动恢复
|
|
514
|
+
for (const service of this.requiredServices) {
|
|
515
|
+
if (!this.rootCtx.hasService(service)) {
|
|
516
|
+
this.logger.warn(`必需服务 "${service}" 缺失,尝试自动恢复...`);
|
|
517
|
+
const activated = await ensureServiceProvider(service, {
|
|
518
|
+
plugins: this.plugins,
|
|
519
|
+
rootCtx: this.rootCtx,
|
|
520
|
+
logger: this.logger,
|
|
521
|
+
recovery: this.recoveryPolicy,
|
|
522
|
+
});
|
|
523
|
+
if (activated) {
|
|
524
|
+
this.logger.info(`必需服务 "${service}" 已通过插件 "${activated}" 恢复`);
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
this.logger.error(`必需服务 "${service}" 自动恢复失败!`);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
this.rootCtx.emit('plugins:changed').catch(err => {
|
|
532
|
+
this.logger.warn(`emit plugins:changed 失败: ${err}`);
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* 为外部(App)暴露的「必需服务自动恢复」入口。
|
|
537
|
+
*
|
|
538
|
+
* 实际逻辑在 plugin-activation.ts。PluginManager 仅负责注入 plugins/rootCtx/logger。
|
|
539
|
+
*/
|
|
540
|
+
async ensureServiceProvider(serviceName) {
|
|
541
|
+
return ensureServiceProvider(serviceName, {
|
|
542
|
+
plugins: this.plugins,
|
|
543
|
+
rootCtx: this.rootCtx,
|
|
544
|
+
logger: this.logger,
|
|
545
|
+
recovery: this.recoveryPolicy,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { AalisConfig } from './config.js';
|
|
2
|
+
import type { PluginModule } from './plugin.js';
|
|
3
|
+
/**
|
|
4
|
+
* `@aalis/core` 注入点(host providers)。
|
|
5
|
+
*
|
|
6
|
+
* 把"配置从哪里来 / 插件从哪里来 / 怎么重启"这三件 I/O 相关的事
|
|
7
|
+
* 抽成接口,由宿主(src/runtime 或外部嵌入者)实现并注入。core 本身
|
|
8
|
+
* 不再 import 任何 `node:fs` / `node:path` / `node:url` / `node:child_process`
|
|
9
|
+
* / `yaml`,可在浏览器、单文件二进制、嵌入式集成等场景里运行。
|
|
10
|
+
*
|
|
11
|
+
* 设计原则:
|
|
12
|
+
* - **同步优先**:能同步就同步(fs sync 读 yaml 完全可接受);异步留给真异步源
|
|
13
|
+
* (HTTP、远程配置中心等)。
|
|
14
|
+
* - **可选能力**:`save` / `watch` / `reload` 都标记为可选;只读宿主可以不提供。
|
|
15
|
+
* - **opaque metadata**:descriptor.source 等字段是 loader 自己理解的字符串;core 不解释。
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* 配置提供者:负责"持久化层"。core 内部的 `ConfigManager` 持有运行时
|
|
19
|
+
* 解析后的 `AalisConfig` 快照,所有读写都走自己的内存结构;
|
|
20
|
+
* `save()` / `watch()` 才转交给 provider。
|
|
21
|
+
*
|
|
22
|
+
* 因此 provider 不必提供 `load()`——`AalisConfig` 由宿主在构造 `App` 之前
|
|
23
|
+
* 自己加载好传进来即可。这让 core 完全无视"配置从哪里读"的细节。
|
|
24
|
+
*/
|
|
25
|
+
export interface ConfigProvider {
|
|
26
|
+
/**
|
|
27
|
+
* 持久化当前完整 config 快照。
|
|
28
|
+
*
|
|
29
|
+
* 实现可以做:写文件、PUT 到 HTTP 端点、写 KV 存储等。
|
|
30
|
+
* 不提供时表示宿主拒绝持久化(典型场景:内存配置 / 只读部署)。
|
|
31
|
+
*/
|
|
32
|
+
save?(config: AalisConfig): void | Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* 订阅外部对配置源的变更(其他进程改了配置文件、远端推送等)。
|
|
35
|
+
*
|
|
36
|
+
* 当 provider 检测到 config 已变化时调用 `onChange(next)`,
|
|
37
|
+
* core 的 ConfigManager 会用新快照重置内部状态并触发热重载。
|
|
38
|
+
*
|
|
39
|
+
* 返回的 dispose 函数会在 `App.stop()` 时被调用。
|
|
40
|
+
*/
|
|
41
|
+
watch?(onChange: (next: AalisConfig) => void): () => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 已发现但尚未导入的插件条目。`source` 是 loader 自己理解的字符串
|
|
45
|
+
* (fs loader 用绝对路径,URL loader 用 URL,内存 loader 用 module 别名)。
|
|
46
|
+
* core 仅用它在 `reload()` 调用时回传——不解释含义。
|
|
47
|
+
*/
|
|
48
|
+
export interface PluginDescriptor {
|
|
49
|
+
/** 插件模块名,与 `PluginModule.name` 一致;core 用此匹配多实例配置 */
|
|
50
|
+
name: string;
|
|
51
|
+
/** 给 loader 自己用的不透明定位串 */
|
|
52
|
+
source: string;
|
|
53
|
+
/** loader 可挂任意辅助元数据(cache key、版本号、manifest 等) */
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 插件加载器:负责"插件从哪里来"。
|
|
58
|
+
*
|
|
59
|
+
* - `discover()` 列出当前可用的插件条目
|
|
60
|
+
* - `load(descriptor)` 把条目 import 成 `PluginModule`
|
|
61
|
+
* - `reload(descriptor)` 可选——支持热重载(fs loader 用 mtime 做 cache buster)
|
|
62
|
+
*/
|
|
63
|
+
export interface PluginLoader {
|
|
64
|
+
discover(): Promise<PluginDescriptor[]>;
|
|
65
|
+
load(descriptor: PluginDescriptor): Promise<PluginModule | null>;
|
|
66
|
+
/** 热重载——不提供时 `App.rescanPlugins()` 会退化为 `load()` */
|
|
67
|
+
reload?(descriptor: PluginDescriptor): Promise<PluginModule | null>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 重启策略:`App.restart()` 把"如何重启"委托给宿主。
|
|
71
|
+
*
|
|
72
|
+
* - Node 进程宿主:spawn 一个新进程然后退出
|
|
73
|
+
* - 浏览器宿主:`location.reload()`
|
|
74
|
+
* - 嵌入式宿主:可能就是 noop,或者通知外层重新创建 App
|
|
75
|
+
*
|
|
76
|
+
* `restart(opts.stop)` 由 App 传入"先停掉当前实例"的回调;
|
|
77
|
+
* **时序由 strategy 决定**——例如 HTTP 宿主可能想先延迟几百毫秒让响应返回客户端再 stop,
|
|
78
|
+
* CLI/嵌入式宿主可能直接 `await stop()` 后立刻重启,core 不再硬编码时延。
|
|
79
|
+
*/
|
|
80
|
+
export interface RestartStrategy {
|
|
81
|
+
restart(opts: {
|
|
82
|
+
stop: () => Promise<void>;
|
|
83
|
+
}): void | Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AAMH;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC3D;AAMD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACjE,oDAAoD;IACpD,MAAM,CAAC,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;CACrE;AAMD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE"}
|