@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
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// ===== Model 引用编解码 =====
|
|
2
|
+
//
|
|
3
|
+
// 把 (provider, model) 二元组与配置/UI 友好的 string 形式互转,避免在 yaml 与 form 里
|
|
4
|
+
// 引入复合 schema。yaml 与 WebUI dynamicOptions:'llm' 的 select value 都使用此格式:
|
|
5
|
+
//
|
|
6
|
+
// "<providerContextId>::<modelId>"
|
|
7
|
+
//
|
|
8
|
+
// 例如:
|
|
9
|
+
// "@aalis/plugin-openai::gpt-4o"
|
|
10
|
+
// "@aalis/plugin-deepseek::deepseek-chat"
|
|
11
|
+
// "@aalis/plugin-ollama::qwen2.5:7b" ← model id 内部出现 ':' 仍然安全(用 '::' 分隔)
|
|
12
|
+
//
|
|
13
|
+
// 只接受 contextId 作为 provider 部分;不接受 label,避免歧义。
|
|
14
|
+
const MODEL_REF_SEPARATOR = '::';
|
|
15
|
+
/**
|
|
16
|
+
* 解析复合 model 引用字符串。
|
|
17
|
+
*
|
|
18
|
+
* - `"@aalis/plugin-openai::gpt-4o"` → `{ provider: "@aalis/plugin-openai", model: "gpt-4o" }`
|
|
19
|
+
* - `"gpt-4o"` (无 `::`)→ `{ model: "gpt-4o" }`(旧风格,仅 model)
|
|
20
|
+
* - `""` / null / undefined → `{}`(让调用方走默认 provider/model)
|
|
21
|
+
*
|
|
22
|
+
* 注意:分隔符使用 `::` 而非 `:`,因为 model id 中允许包含 `:`(如 ollama 的 `qwen2.5:7b`)。
|
|
23
|
+
*/
|
|
24
|
+
export function parseModelRef(value) {
|
|
25
|
+
if (!value)
|
|
26
|
+
return {};
|
|
27
|
+
const idx = value.indexOf(MODEL_REF_SEPARATOR);
|
|
28
|
+
if (idx < 0)
|
|
29
|
+
return { model: value };
|
|
30
|
+
const provider = value.slice(0, idx);
|
|
31
|
+
const model = value.slice(idx + MODEL_REF_SEPARATOR.length);
|
|
32
|
+
return {
|
|
33
|
+
provider: provider || undefined,
|
|
34
|
+
model: model || undefined,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 将 (provider, model) 编码为复合 string,用于持久化或 UI 选项 value。
|
|
39
|
+
* 任一方缺失时不输出分隔符(避免产生 `::xxx` 或 `xxx::` 这种不规整形式)。
|
|
40
|
+
*/
|
|
41
|
+
export function formatModelRef(ref) {
|
|
42
|
+
if (ref.provider && ref.model)
|
|
43
|
+
return `${ref.provider}${MODEL_REF_SEPARATOR}${ref.model}`;
|
|
44
|
+
return ref.model ?? ref.provider ?? '';
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=model-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-ref.js","sourceRoot":"","sources":["../src/model-ref.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,EAAE;AACF,kEAAkE;AAClE,uEAAuE;AACvE,EAAE;AACF,qCAAqC;AACrC,EAAE;AACF,MAAM;AACN,mCAAmC;AACnC,4CAA4C;AAC5C,6EAA6E;AAC7E,EAAE;AACF,+CAA+C;AAE/C,MAAM,mBAAmB,GAAG,IAAI,CAAC;AASjC;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,KAAgC;IAC5D,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC/C,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5D,OAAO;QACL,QAAQ,EAAE,QAAQ,IAAI,SAAS;QAC/B,KAAK,EAAE,KAAK,IAAI,SAAS;KAC1B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAa;IAC1C,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,KAAK;QAAE,OAAO,GAAG,GAAG,CAAC,QAAQ,GAAG,mBAAmB,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;IAC1F,OAAO,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { DisposableChain } from './disposable-chain.js';
|
|
2
|
+
import type { Logger } from './logger.js';
|
|
3
|
+
import type { ServiceContainer } from './service.js';
|
|
4
|
+
import type { RegisteredTool, ToolGroupInfo, CommandDefinition, AalisEvents } from './types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* 工具/指令注册缓冲
|
|
7
|
+
*
|
|
8
|
+
* 用途:插件加载顺序无法保证 tools/commands 服务已就绪时,
|
|
9
|
+
* 调用 `ctx.registerTool / registerToolGroup / command` 会被临时收纳,
|
|
10
|
+
* 等 `service:registered` 事件触发后自动刷入真实服务。
|
|
11
|
+
*
|
|
12
|
+
* 从 Context 抽出以便独立测试与理解。
|
|
13
|
+
*
|
|
14
|
+
* 设计要点:
|
|
15
|
+
* - 该缓冲是"按 Context 实例一份"的,因为每条注册都要归属到发起者 contextId
|
|
16
|
+
* - 刷入成功后获得的 dispose 函数会被加入传入的 DisposableChain,保证 Context
|
|
17
|
+
* dispose 时能统一回收
|
|
18
|
+
* - 如调用方尚未刷入前主动 dispose,会从本地数组里移除条目,不会到达底层服务
|
|
19
|
+
*/
|
|
20
|
+
export declare class PendingRegistrationBuffer {
|
|
21
|
+
private readonly contextId;
|
|
22
|
+
private readonly services;
|
|
23
|
+
private readonly logger;
|
|
24
|
+
private readonly disposables;
|
|
25
|
+
/** 由 Context 注入的 `on(event, handler)` —— 让生命周期统一托管 */
|
|
26
|
+
private readonly onEvent;
|
|
27
|
+
private _tools;
|
|
28
|
+
private _toolGroups;
|
|
29
|
+
private _commands;
|
|
30
|
+
private _flushListenerAttached;
|
|
31
|
+
constructor(contextId: string, services: ServiceContainer, logger: Logger, disposables: DisposableChain,
|
|
32
|
+
/** 由 Context 注入的 `on(event, handler)` —— 让生命周期统一托管 */
|
|
33
|
+
onEvent: <E extends string & keyof AalisEvents>(event: E, handler: (...args: AalisEvents[E]) => void | Promise<void>) => () => void);
|
|
34
|
+
/** 注册 AI 工具。服务可用则直接注册,否则缓冲到 tools 服务就绪。 */
|
|
35
|
+
registerTool(tool: Omit<RegisteredTool, 'pluginName'>): () => void;
|
|
36
|
+
/** 注册工具分组。行为同 registerTool。 */
|
|
37
|
+
registerToolGroup(group: Omit<ToolGroupInfo, 'pluginName'>): () => void;
|
|
38
|
+
/** 注册斜杠指令。服务可用则直接注册,否则缓冲到 commands 服务就绪。 */
|
|
39
|
+
registerCommand(def: CommandDefinition): () => void;
|
|
40
|
+
/** 清空本地缓冲(Context.dispose 时调用,底层服务已由 DisposableChain 回收) */
|
|
41
|
+
clear(): void;
|
|
42
|
+
private _ensureFlushListener;
|
|
43
|
+
private _flushTools;
|
|
44
|
+
private _flushCommands;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=pending-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-buffer.d.ts","sourceRoot":"","sources":["../src/pending-buffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,iBAAiB,EAA+B,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEnI;;;;;;;;;;;;;;GAcG;AACH,qBAAa,yBAAyB;IAOlC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,sDAAsD;IACtD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX1B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,SAAS,CAAmD;IACpE,OAAO,CAAC,sBAAsB,CAAS;gBAGpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,eAAe;IAC7C,sDAAsD;IACrC,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,WAAW,EAC7D,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KACvD,MAAM,IAAI;IAGjB,2CAA2C;IAC3C,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,GAAG,MAAM,IAAI;IAgBlE,+BAA+B;IAC/B,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,GAAG,MAAM,IAAI;IAgBvE,4CAA4C;IAC5C,eAAe,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAiBnD,4DAA4D;IAC5D,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,cAAc;CASvB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工具/指令注册缓冲
|
|
3
|
+
*
|
|
4
|
+
* 用途:插件加载顺序无法保证 tools/commands 服务已就绪时,
|
|
5
|
+
* 调用 `ctx.registerTool / registerToolGroup / command` 会被临时收纳,
|
|
6
|
+
* 等 `service:registered` 事件触发后自动刷入真实服务。
|
|
7
|
+
*
|
|
8
|
+
* 从 Context 抽出以便独立测试与理解。
|
|
9
|
+
*
|
|
10
|
+
* 设计要点:
|
|
11
|
+
* - 该缓冲是"按 Context 实例一份"的,因为每条注册都要归属到发起者 contextId
|
|
12
|
+
* - 刷入成功后获得的 dispose 函数会被加入传入的 DisposableChain,保证 Context
|
|
13
|
+
* dispose 时能统一回收
|
|
14
|
+
* - 如调用方尚未刷入前主动 dispose,会从本地数组里移除条目,不会到达底层服务
|
|
15
|
+
*/
|
|
16
|
+
export class PendingRegistrationBuffer {
|
|
17
|
+
contextId;
|
|
18
|
+
services;
|
|
19
|
+
logger;
|
|
20
|
+
disposables;
|
|
21
|
+
onEvent;
|
|
22
|
+
_tools = [];
|
|
23
|
+
_toolGroups = [];
|
|
24
|
+
_commands = [];
|
|
25
|
+
_flushListenerAttached = false;
|
|
26
|
+
constructor(contextId, services, logger, disposables,
|
|
27
|
+
/** 由 Context 注入的 `on(event, handler)` —— 让生命周期统一托管 */
|
|
28
|
+
onEvent) {
|
|
29
|
+
this.contextId = contextId;
|
|
30
|
+
this.services = services;
|
|
31
|
+
this.logger = logger;
|
|
32
|
+
this.disposables = disposables;
|
|
33
|
+
this.onEvent = onEvent;
|
|
34
|
+
}
|
|
35
|
+
/** 注册 AI 工具。服务可用则直接注册,否则缓冲到 tools 服务就绪。 */
|
|
36
|
+
registerTool(tool) {
|
|
37
|
+
const tools = this.services.get('tools');
|
|
38
|
+
if (tools) {
|
|
39
|
+
const dispose = tools.register(tool, this.contextId);
|
|
40
|
+
this.disposables.push(dispose);
|
|
41
|
+
return dispose;
|
|
42
|
+
}
|
|
43
|
+
this._tools.push(tool);
|
|
44
|
+
this._ensureFlushListener();
|
|
45
|
+
this.logger.debug(`工具 "${tool.definition.function.name}" 已缓冲,等待 tools 服务就绪`);
|
|
46
|
+
return () => {
|
|
47
|
+
const idx = this._tools.indexOf(tool);
|
|
48
|
+
if (idx >= 0)
|
|
49
|
+
this._tools.splice(idx, 1);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** 注册工具分组。行为同 registerTool。 */
|
|
53
|
+
registerToolGroup(group) {
|
|
54
|
+
const tools = this.services.get('tools');
|
|
55
|
+
if (tools) {
|
|
56
|
+
const dispose = tools.registerGroup(group, this.contextId);
|
|
57
|
+
this.disposables.push(dispose);
|
|
58
|
+
return dispose;
|
|
59
|
+
}
|
|
60
|
+
this._toolGroups.push(group);
|
|
61
|
+
this._ensureFlushListener();
|
|
62
|
+
this.logger.debug(`工具分组 "${group.name}" 已缓冲,等待 tools 服务就绪`);
|
|
63
|
+
return () => {
|
|
64
|
+
const idx = this._toolGroups.indexOf(group);
|
|
65
|
+
if (idx >= 0)
|
|
66
|
+
this._toolGroups.splice(idx, 1);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** 注册斜杠指令。服务可用则直接注册,否则缓冲到 commands 服务就绪。 */
|
|
70
|
+
registerCommand(def) {
|
|
71
|
+
const commands = this.services.get('commands');
|
|
72
|
+
if (commands) {
|
|
73
|
+
const dispose = commands.register(def, this.contextId);
|
|
74
|
+
this.disposables.push(dispose);
|
|
75
|
+
return dispose;
|
|
76
|
+
}
|
|
77
|
+
const entry = { def, ctxId: this.contextId };
|
|
78
|
+
this._commands.push(entry);
|
|
79
|
+
this._ensureFlushListener();
|
|
80
|
+
this.logger.debug(`指令 "${def.name}" 已缓冲,等待 commands 服务就绪`);
|
|
81
|
+
return () => {
|
|
82
|
+
const idx = this._commands.indexOf(entry);
|
|
83
|
+
if (idx >= 0)
|
|
84
|
+
this._commands.splice(idx, 1);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** 清空本地缓冲(Context.dispose 时调用,底层服务已由 DisposableChain 回收) */
|
|
88
|
+
clear() {
|
|
89
|
+
this._tools = [];
|
|
90
|
+
this._toolGroups = [];
|
|
91
|
+
this._commands = [];
|
|
92
|
+
}
|
|
93
|
+
_ensureFlushListener() {
|
|
94
|
+
if (this._flushListenerAttached)
|
|
95
|
+
return;
|
|
96
|
+
this._flushListenerAttached = true;
|
|
97
|
+
const off = this.onEvent('service:registered', (svcName) => {
|
|
98
|
+
if (svcName === 'tools')
|
|
99
|
+
this._flushTools();
|
|
100
|
+
if (svcName === 'commands')
|
|
101
|
+
this._flushCommands();
|
|
102
|
+
});
|
|
103
|
+
this.disposables.push(off);
|
|
104
|
+
}
|
|
105
|
+
_flushTools() {
|
|
106
|
+
const tools = this.services.get('tools');
|
|
107
|
+
if (!tools)
|
|
108
|
+
return;
|
|
109
|
+
for (const tool of this._tools) {
|
|
110
|
+
const dispose = tools.register(tool, this.contextId);
|
|
111
|
+
this.disposables.push(dispose);
|
|
112
|
+
}
|
|
113
|
+
this._tools = [];
|
|
114
|
+
for (const group of this._toolGroups) {
|
|
115
|
+
const dispose = tools.registerGroup(group, this.contextId);
|
|
116
|
+
this.disposables.push(dispose);
|
|
117
|
+
}
|
|
118
|
+
this._toolGroups = [];
|
|
119
|
+
}
|
|
120
|
+
_flushCommands() {
|
|
121
|
+
const commands = this.services.get('commands');
|
|
122
|
+
if (!commands)
|
|
123
|
+
return;
|
|
124
|
+
for (const { def, ctxId } of this._commands) {
|
|
125
|
+
const dispose = commands.register(def, ctxId);
|
|
126
|
+
this.disposables.push(dispose);
|
|
127
|
+
}
|
|
128
|
+
this._commands = [];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=pending-buffer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-buffer.js","sourceRoot":"","sources":["../src/pending-buffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ServiceContainer } from './service.js';
|
|
2
|
+
import type { PlatformAdapter, PlatformConnection, PlatformSelfIdentity } from './types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* 平台注册表
|
|
5
|
+
*
|
|
6
|
+
* 从 ServiceContainer 中聚合 `'platform'` 服务的所有条目,返回按不同视角
|
|
7
|
+
* 的平台信息快照。不持有状态——每次调用直接从容器读取。
|
|
8
|
+
*
|
|
9
|
+
* 提取动机:把"领域聚合查询"从 Context 里抽出,与 LLMRouter 同风格。
|
|
10
|
+
*/
|
|
11
|
+
export declare class PlatformRegistry {
|
|
12
|
+
private readonly services;
|
|
13
|
+
constructor(services: ServiceContainer);
|
|
14
|
+
/**
|
|
15
|
+
* 获取所有已注册的平台适配器实例(过滤掉不合规的)。
|
|
16
|
+
*/
|
|
17
|
+
listAdapters(): PlatformAdapter[];
|
|
18
|
+
/**
|
|
19
|
+
* 获取所有已注册的平台名称(去重)。
|
|
20
|
+
*
|
|
21
|
+
* 基于各 platform 服务的 capabilities 聚合,而非 adapter.platform 字段,
|
|
22
|
+
* 因此一个 adapter 可以声明承载多个 platform(罕见)。
|
|
23
|
+
*/
|
|
24
|
+
listPlatformNames(): string[];
|
|
25
|
+
/**
|
|
26
|
+
* 获取所有平台适配器及其连接详情
|
|
27
|
+
*/
|
|
28
|
+
listDetails(): Array<{
|
|
29
|
+
adapterName: string;
|
|
30
|
+
platform: string;
|
|
31
|
+
contextId: string;
|
|
32
|
+
capabilities: string[];
|
|
33
|
+
connections: PlatformConnection[];
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* 获取某个平台账号自身身份。
|
|
37
|
+
*/
|
|
38
|
+
getSelfIdentity(platform: string, sessionId?: string): PlatformSelfIdentity | undefined;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=platform-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-registry.d.ts","sourceRoot":"","sources":["../src/platform-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAElG;;;;;;;GAOG;AACH,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,gBAAgB;IAEvD;;OAEG;IACH,YAAY,IAAI,eAAe,EAAE;IAMjC;;;;;OAKG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAQ7B;;OAEG;IACH,WAAW,IAAI,KAAK,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,WAAW,EAAE,kBAAkB,EAAE,CAAC;KACnC,CAAC;IAaF;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS;CAQxF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 平台注册表
|
|
3
|
+
*
|
|
4
|
+
* 从 ServiceContainer 中聚合 `'platform'` 服务的所有条目,返回按不同视角
|
|
5
|
+
* 的平台信息快照。不持有状态——每次调用直接从容器读取。
|
|
6
|
+
*
|
|
7
|
+
* 提取动机:把"领域聚合查询"从 Context 里抽出,与 LLMRouter 同风格。
|
|
8
|
+
*/
|
|
9
|
+
export class PlatformRegistry {
|
|
10
|
+
services;
|
|
11
|
+
constructor(services) {
|
|
12
|
+
this.services = services;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 获取所有已注册的平台适配器实例(过滤掉不合规的)。
|
|
16
|
+
*/
|
|
17
|
+
listAdapters() {
|
|
18
|
+
return this.services.getEntries('platform')
|
|
19
|
+
.map(e => e.instance)
|
|
20
|
+
.filter(a => a && typeof a.getConnections === 'function');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 获取所有已注册的平台名称(去重)。
|
|
24
|
+
*
|
|
25
|
+
* 基于各 platform 服务的 capabilities 聚合,而非 adapter.platform 字段,
|
|
26
|
+
* 因此一个 adapter 可以声明承载多个 platform(罕见)。
|
|
27
|
+
*/
|
|
28
|
+
listPlatformNames() {
|
|
29
|
+
const names = new Set();
|
|
30
|
+
for (const entry of this.services.getEntries('platform')) {
|
|
31
|
+
for (const cap of entry.capabilities)
|
|
32
|
+
names.add(cap);
|
|
33
|
+
}
|
|
34
|
+
return [...names];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 获取所有平台适配器及其连接详情
|
|
38
|
+
*/
|
|
39
|
+
listDetails() {
|
|
40
|
+
return this.services.getEntries('platform').map(entry => {
|
|
41
|
+
const adapter = entry.instance;
|
|
42
|
+
return {
|
|
43
|
+
adapterName: adapter.adapterName,
|
|
44
|
+
platform: adapter.platform,
|
|
45
|
+
contextId: entry.contextId,
|
|
46
|
+
capabilities: [...entry.capabilities],
|
|
47
|
+
connections: adapter.getConnections(),
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 获取某个平台账号自身身份。
|
|
53
|
+
*/
|
|
54
|
+
getSelfIdentity(platform, sessionId) {
|
|
55
|
+
for (const entry of this.services.getEntries('platform')) {
|
|
56
|
+
const adapter = entry.instance;
|
|
57
|
+
if (!adapter || adapter.platform !== platform)
|
|
58
|
+
continue;
|
|
59
|
+
return adapter.getSelfIdentity?.(sessionId);
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=platform-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-registry.js","sourceRoot":"","sources":["../src/platform-registry.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,OAAO,gBAAgB;IACE;IAA7B,YAA6B,QAA0B;QAA1B,aAAQ,GAAR,QAAQ,CAAkB;IAAG,CAAC;IAE3D;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;aACxC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAA2B,CAAC;aACvC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,cAAc,KAAK,UAAU,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;OAKG;IACH,iBAAiB;QACf,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACzD,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,YAAY;gBAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,WAAW;QAOT,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACtD,MAAM,OAAO,GAAG,KAAK,CAAC,QAA2B,CAAC;YAClD,OAAO;gBACL,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC;gBACrC,WAAW,EAAE,OAAO,CAAC,cAAc,EAAE;aACtC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,QAAgB,EAAE,SAAkB;QAClD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACzD,MAAM,OAAO,GAAG,KAAK,CAAC,QAA2B,CAAC;YAClD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;gBAAE,SAAS;YACxD,OAAO,OAAO,CAAC,eAAe,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Context } from './context.js';
|
|
2
|
+
import type { Logger } from './logger.js';
|
|
3
|
+
import type { PluginEntry, PluginState, RecomputeReason } from './types/plugin.js';
|
|
4
|
+
interface ActivationDeps {
|
|
5
|
+
plugins: Map<string, PluginEntry>;
|
|
6
|
+
rootCtx: Context;
|
|
7
|
+
logger: Logger;
|
|
8
|
+
/** 必需服务恢复政策(宿主经 AppOptions.serviceRecovery 注入;缺省允许自动启用 disabled 提供者) */
|
|
9
|
+
recovery?: {
|
|
10
|
+
autoEnableDisabled: boolean;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 计算单个 entry 的目标状态。
|
|
15
|
+
*
|
|
16
|
+
* - disabled / disposed / error 是显式态,recompute 不动它们
|
|
17
|
+
* - required 依赖不满足 → pending
|
|
18
|
+
* - service-down 命中 optional 依赖且服务确实没了且声明了
|
|
19
|
+
* `requiresBounceOnDepChange: true` → pending(级联 bounce);
|
|
20
|
+
* 默认不级联,期望下游在每次访问时 `ctx.getService(...)` 惰性查询
|
|
21
|
+
* - 其余 active / pending / activating → active
|
|
22
|
+
*/
|
|
23
|
+
export declare function computeTargetState(entry: PluginEntry, reason: RecomputeReason, rootCtx: Context): PluginState;
|
|
24
|
+
/**
|
|
25
|
+
* 尝试激活一个 pending 插件:依赖检查 → fork ctx → apply → provides 校验。
|
|
26
|
+
*
|
|
27
|
+
* 失败时把 entry 转为 error 态(带 message),ctx 已 dispose,外层 recompute 不会重试。
|
|
28
|
+
* 调用方需保证 entry.state === 'pending' 才调用本函数(否则直接 return)。
|
|
29
|
+
*/
|
|
30
|
+
export declare function activatePlugin(entry: PluginEntry, deps: ActivationDeps): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* 查找能提供指定服务的插件并尝试激活它。
|
|
33
|
+
*
|
|
34
|
+
* 用于核心必需服务的自动恢复:
|
|
35
|
+
* 1. 优先找已注册但被禁用的提供者 → 启用
|
|
36
|
+
* 2. 其次找已注册但处于 pending/error 的提供者 → 重新激活
|
|
37
|
+
* 3. 已经 active 的跳过(说明服务应该已存在;若仍不存在则插件 bug)
|
|
38
|
+
*
|
|
39
|
+
* @returns 成功激活的插件 instanceId,或 undefined
|
|
40
|
+
*/
|
|
41
|
+
export declare function ensureServiceProvider(serviceName: string, deps: ActivationDeps, resolving?: Set<string>): Promise<string | undefined>;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=plugin-activation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-activation.d.ts","sourceRoot":"","sources":["../src/plugin-activation.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEnF,UAAU,cAAc;IACtB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,QAAQ,CAAC,EAAE;QAAE,kBAAkB,EAAE,OAAO,CAAA;KAAE,CAAC;CAC5C;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,WAAW,CAmB7G;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgE5F;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,cAAc,EACpB,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsE7B"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// plugin-activation.ts — 插件激活路径辅助
|
|
3
|
+
//
|
|
4
|
+
// 从 plugin.ts 拆出的"如何把单个 entry 推进到 active 态"逻辑:
|
|
5
|
+
// - computeTargetState:给定 reason,单个 entry 的目标态是什么
|
|
6
|
+
// - activatePlugin:fork ctx → apply → 校验 provides → 标记 active/error
|
|
7
|
+
// - ensureServiceProvider:必需服务自动恢复(启用 disabled / 重试 pending)
|
|
8
|
+
//
|
|
9
|
+
// 这些都需要 PluginManager 的状态(plugins map / requiredServices / rootCtx),
|
|
10
|
+
// 但被有意提成 free function:传入 deps 对象,方便单测 mock + 让 PluginManager
|
|
11
|
+
// 自身只负责"事件路由 + recompute 编排"。
|
|
12
|
+
// ============================================================
|
|
13
|
+
/**
|
|
14
|
+
* 计算单个 entry 的目标状态。
|
|
15
|
+
*
|
|
16
|
+
* - disabled / disposed / error 是显式态,recompute 不动它们
|
|
17
|
+
* - required 依赖不满足 → pending
|
|
18
|
+
* - service-down 命中 optional 依赖且服务确实没了且声明了
|
|
19
|
+
* `requiresBounceOnDepChange: true` → pending(级联 bounce);
|
|
20
|
+
* 默认不级联,期望下游在每次访问时 `ctx.getService(...)` 惰性查询
|
|
21
|
+
* - 其余 active / pending / activating → active
|
|
22
|
+
*/
|
|
23
|
+
export function computeTargetState(entry, reason, rootCtx) {
|
|
24
|
+
if (entry.state === 'disabled' || entry.state === 'disposed' || entry.state === 'error') {
|
|
25
|
+
return entry.state;
|
|
26
|
+
}
|
|
27
|
+
if (reason.type === 'shutdown')
|
|
28
|
+
return 'disposed';
|
|
29
|
+
const reqUnmet = entry.requiredDeps.some(d => !rootCtx.hasService(d.service, d.capabilities.length > 0 ? d.capabilities : undefined));
|
|
30
|
+
if (reqUnmet)
|
|
31
|
+
return 'pending';
|
|
32
|
+
if (reason.type === 'service-down' && entry.module.requiresBounceOnDepChange) {
|
|
33
|
+
const optHit = entry.optionalDeps.find(d => d.service === reason.service);
|
|
34
|
+
if (optHit &&
|
|
35
|
+
!rootCtx.hasService(optHit.service, optHit.capabilities.length > 0 ? optHit.capabilities : undefined)) {
|
|
36
|
+
return 'pending';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return 'active';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 尝试激活一个 pending 插件:依赖检查 → fork ctx → apply → provides 校验。
|
|
43
|
+
*
|
|
44
|
+
* 失败时把 entry 转为 error 态(带 message),ctx 已 dispose,外层 recompute 不会重试。
|
|
45
|
+
* 调用方需保证 entry.state === 'pending' 才调用本函数(否则直接 return)。
|
|
46
|
+
*/
|
|
47
|
+
export async function activatePlugin(entry, deps) {
|
|
48
|
+
const { rootCtx, logger } = deps;
|
|
49
|
+
if (entry.state !== 'pending')
|
|
50
|
+
return;
|
|
51
|
+
for (const dep of entry.requiredDeps) {
|
|
52
|
+
if (!rootCtx.hasService(dep.service, dep.capabilities.length > 0 ? dep.capabilities : undefined)) {
|
|
53
|
+
logger.debug(`插件 "${entry.instanceId}" 等待服务: ${dep.service}${dep.capabilities.length ? ` [${dep.capabilities.join(', ')}]` : ''}`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 先标记为 activating,防止 service:registered 事件导致重入
|
|
58
|
+
entry.state = 'activating';
|
|
59
|
+
const ctx = rootCtx.fork(entry.instanceId);
|
|
60
|
+
entry.context = ctx;
|
|
61
|
+
try {
|
|
62
|
+
await entry.module.apply(ctx, entry.config);
|
|
63
|
+
if (entry.module.provides) {
|
|
64
|
+
const missing = entry.module.provides.filter(name => !rootCtx.serviceContainer.hasByContext(name, entry.instanceId));
|
|
65
|
+
if (missing.length > 0) {
|
|
66
|
+
throw new Error(`声明 provides [${missing.join(', ')}] 但未实际注册这些服务`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// dev mode:反向一致性检查 —— 实际注册的服务名是否都在 provides 中声明
|
|
70
|
+
// 不在 provides 的服务无法享受拓扑排序与服务恢复,下游可能错过依赖关系
|
|
71
|
+
// 注:是否 dev 由宿主通过 `App({ devMode })` 显式注入,core 不读 process.env
|
|
72
|
+
if (rootCtx.devMode) {
|
|
73
|
+
const declared = new Set(entry.module.provides ?? []);
|
|
74
|
+
const actuallyProvided = rootCtx.serviceContainer
|
|
75
|
+
.getServiceNames()
|
|
76
|
+
.filter(name => rootCtx.serviceContainer.hasByContext(name, entry.instanceId));
|
|
77
|
+
const undeclared = actuallyProvided.filter(name => !declared.has(name));
|
|
78
|
+
if (undeclared.length > 0) {
|
|
79
|
+
logger.warn(`插件 "${entry.instanceId}" 注册了服务 [${undeclared.join(', ')}] 但未在 module.provides 中声明 —— ` +
|
|
80
|
+
`下游依赖排序和自动恢复将无法找到该 provider(仅靠 reactive 兜底),建议补全 provides 列表`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
entry.state = 'active';
|
|
84
|
+
entry.error = undefined;
|
|
85
|
+
logger.info(`插件已激活: ${entry.instanceId}`);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
89
|
+
logger.error(`插件 "${entry.instanceId}" 激活失败: ${message}`);
|
|
90
|
+
ctx.dispose();
|
|
91
|
+
entry.context = undefined;
|
|
92
|
+
entry.state = 'error';
|
|
93
|
+
entry.error = message;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// 激活成败只由 apply/provides 校验决定。emit 放在 try 块外:旁观插件的
|
|
97
|
+
// 监听器出问题不能把刚激活成功的无辜插件打成 error 终态(归因错位)。
|
|
98
|
+
await rootCtx.emit('plugin:loaded', entry.instanceId);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 查找能提供指定服务的插件并尝试激活它。
|
|
102
|
+
*
|
|
103
|
+
* 用于核心必需服务的自动恢复:
|
|
104
|
+
* 1. 优先找已注册但被禁用的提供者 → 启用
|
|
105
|
+
* 2. 其次找已注册但处于 pending/error 的提供者 → 重新激活
|
|
106
|
+
* 3. 已经 active 的跳过(说明服务应该已存在;若仍不存在则插件 bug)
|
|
107
|
+
*
|
|
108
|
+
* @returns 成功激活的插件 instanceId,或 undefined
|
|
109
|
+
*/
|
|
110
|
+
export async function ensureServiceProvider(serviceName, deps, resolving) {
|
|
111
|
+
const { plugins, rootCtx, logger } = deps;
|
|
112
|
+
if (rootCtx.hasService(serviceName))
|
|
113
|
+
return undefined;
|
|
114
|
+
const inFlight = resolving ?? new Set();
|
|
115
|
+
if (inFlight.has(serviceName)) {
|
|
116
|
+
logger.error(`检测到循环依赖,跳过: ${serviceName}`);
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
inFlight.add(serviceName);
|
|
120
|
+
const candidates = [];
|
|
121
|
+
for (const entry of plugins.values()) {
|
|
122
|
+
if (!entry.module.provides?.includes(serviceName))
|
|
123
|
+
continue;
|
|
124
|
+
candidates.push(entry);
|
|
125
|
+
}
|
|
126
|
+
if (candidates.length === 0) {
|
|
127
|
+
logger.error(`必需服务 "${serviceName}" 无可用提供者插件`);
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
// 政策:是否允许为恢复必需服务而自动启用被用户禁用的提供者。
|
|
131
|
+
// 默认允许("必需服务可用"压过"尊重禁用");宿主可注入 false 反转取舍。
|
|
132
|
+
const allowAutoEnable = deps.recovery?.autoEnableDisabled ?? true;
|
|
133
|
+
const disabledCandidates = candidates.filter(e => e.state === 'disabled');
|
|
134
|
+
if (!allowAutoEnable && disabledCandidates.length > 0) {
|
|
135
|
+
logger.warn(`必需服务 "${serviceName}" 存在被禁用的提供者 [${disabledCandidates.map(e => e.instanceId).join(', ')}],` +
|
|
136
|
+
`但 serviceRecovery.autoEnableDisabled=false,不自动启用`);
|
|
137
|
+
}
|
|
138
|
+
const ordered = [
|
|
139
|
+
...(allowAutoEnable ? disabledCandidates : []),
|
|
140
|
+
...candidates.filter(e => e.state === 'pending' || e.state === 'error'),
|
|
141
|
+
];
|
|
142
|
+
for (const candidate of ordered) {
|
|
143
|
+
if (candidate.state === 'disabled') {
|
|
144
|
+
logger.warn(`必需服务 "${serviceName}" 缺失,自动启用插件: ${candidate.instanceId}`);
|
|
145
|
+
candidate.state = 'pending';
|
|
146
|
+
candidate.error = undefined;
|
|
147
|
+
rootCtx.config.setPluginEnabled(candidate.instanceId, true);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
logger.warn(`必需服务 "${serviceName}" 缺失,尝试激活插件: ${candidate.instanceId}`);
|
|
151
|
+
candidate.state = 'pending';
|
|
152
|
+
candidate.error = undefined;
|
|
153
|
+
}
|
|
154
|
+
for (const dep of candidate.requiredDeps) {
|
|
155
|
+
if (!rootCtx.hasService(dep.service, dep.capabilities.length > 0 ? dep.capabilities : undefined)) {
|
|
156
|
+
await ensureServiceProvider(dep.service, deps, inFlight);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
await activatePlugin(candidate, deps);
|
|
160
|
+
if (candidate.state === 'active') {
|
|
161
|
+
rootCtx.config.save();
|
|
162
|
+
return candidate.instanceId;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const active = candidates.find(e => e.state === 'active');
|
|
166
|
+
if (active) {
|
|
167
|
+
logger.warn(`插件 "${active.instanceId}" 已激活但未提供 "${serviceName}" 服务`);
|
|
168
|
+
}
|
|
169
|
+
logger.error(`无法为必需服务 "${serviceName}" 找到可用的提供者`);
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=plugin-activation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-activation.js","sourceRoot":"","sources":["../src/plugin-activation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Context } from './context.js';
|
|
2
|
+
import type { Logger } from './logger.js';
|
|
3
|
+
import type { PluginEntry } from './types/plugin.js';
|
|
4
|
+
/**
|
|
5
|
+
* 按"提供者 → 消费者"方向的拓扑排序(Kahn)。
|
|
6
|
+
*
|
|
7
|
+
* 关闭顺序 = 此结果反向;激活顺序 = 此结果正序。
|
|
8
|
+
* 服务名 → 提供者映射只取首个 provides 该服务名的 entry,足以表达依赖图。
|
|
9
|
+
*
|
|
10
|
+
* 仅 `requiredDeps` 参与建图:optional 依赖语义为"如果存在则消费",
|
|
11
|
+
* 由运行时 `service-up`/`service-down` recompute 异步补救(whenService 钩子等),
|
|
12
|
+
* 不应制造排序约束。否则插件之间互相 optional 会产生伪环并退化到声明序。
|
|
13
|
+
*
|
|
14
|
+
* 残留环(仅由 required 形成的真环)按声明序兜底追加。
|
|
15
|
+
*/
|
|
16
|
+
export declare function topoSortByDeps(entries: PluginEntry[], logger: Logger): PluginEntry[];
|
|
17
|
+
/**
|
|
18
|
+
* 把下游消费者降级为 pending —— 仅对显式声明 `requiresBounceOnDepChange: true`
|
|
19
|
+
* 的插件生效。
|
|
20
|
+
*
|
|
21
|
+
* 历史背景:早期 core 默认对所有 active 下游做级联 bounce,前提是所有插件都会
|
|
22
|
+
* 在 apply 时把 `ctx.getService(...)` 的结果缓存到长寿命对象里(class field /
|
|
23
|
+
* 闭包),导致 provider 一旦 dispose+重启,下游缓存的裸引用立刻失效。
|
|
24
|
+
*
|
|
25
|
+
* 当前的契约改为:"插件应在每次访问时通过 `ctx.getService(...)` 惰性查询",
|
|
26
|
+
* 这样 provider 切换天然跟随,无需级联 bounce。绝大多数 first-party 插件已经
|
|
27
|
+
* 满足该契约,因此默认行为是**不**级联 dispose 下游。
|
|
28
|
+
*
|
|
29
|
+
* `requiresBounceOnDepChange: true` 是给少数无法响应式处理状态的插件
|
|
30
|
+
* (或迁移成本高的第三方插件)的逃生舱。
|
|
31
|
+
*
|
|
32
|
+
* 同步执行(不 await),caller 紧接着会 await softReload 完成全部重激活。
|
|
33
|
+
*/
|
|
34
|
+
export declare function evictDownstreamConsumers(args: {
|
|
35
|
+
provider: PluginEntry;
|
|
36
|
+
plugins: ReadonlyMap<string, PluginEntry>;
|
|
37
|
+
rootCtx: Context;
|
|
38
|
+
logger: Logger;
|
|
39
|
+
}): void;
|
|
40
|
+
//# sourceMappingURL=plugin-topology.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-topology.d.ts","sourceRoot":"","sources":["../src/plugin-topology.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CA+CpF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CA4BP"}
|