@downcity/agent 1.1.175 → 1.1.179
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/bin/agent/local/AgentPluginFactory.d.ts +4 -2
- package/bin/agent/local/AgentPluginFactory.d.ts.map +1 -1
- package/bin/agent/local/AgentPluginFactory.js +4 -6
- package/bin/agent/local/AgentPluginFactory.js.map +1 -1
- package/bin/agent/local/AgentRuntimeAssembly.d.ts.map +1 -1
- package/bin/agent/local/AgentRuntimeAssembly.js +3 -8
- package/bin/agent/local/AgentRuntimeAssembly.js.map +1 -1
- package/bin/agent/local/ProjectSetup.d.ts +1 -1
- package/bin/agent/local/ProjectSetup.d.ts.map +1 -1
- package/bin/agent/local/ProjectSetup.js +2 -6
- package/bin/agent/local/ProjectSetup.js.map +1 -1
- package/bin/agent/local/services/AgentAssemblyService.d.ts +2 -3
- package/bin/agent/local/services/AgentAssemblyService.d.ts.map +1 -1
- package/bin/agent/local/services/AgentAssemblyService.js +9 -14
- package/bin/agent/local/services/AgentAssemblyService.js.map +1 -1
- package/bin/agent/local/services/AgentBackgroundService.d.ts.map +1 -1
- package/bin/agent/local/services/AgentBackgroundService.js +5 -6
- package/bin/agent/local/services/AgentBackgroundService.js.map +1 -1
- package/bin/agent/local/services/AgentSessionManager.d.ts +2 -2
- package/bin/agent/local/services/AgentSessionManager.d.ts.map +1 -1
- package/bin/agent/local/services/AgentSessionManager.js +1 -28
- package/bin/agent/local/services/AgentSessionManager.js.map +1 -1
- package/bin/config/AgentInitializer.d.ts +4 -4
- package/bin/config/AgentInitializer.d.ts.map +1 -1
- package/bin/config/AgentInitializer.js +7 -49
- package/bin/config/AgentInitializer.js.map +1 -1
- package/bin/config/DowncitySchema.d.ts +3 -4
- package/bin/config/DowncitySchema.d.ts.map +1 -1
- package/bin/config/DowncitySchema.js +1 -2
- package/bin/config/DowncitySchema.js.map +1 -1
- package/bin/executor/composer/system/default/SystemDomain.d.ts.map +1 -1
- package/bin/executor/composer/system/default/SystemDomain.js +1 -2
- package/bin/executor/composer/system/default/SystemDomain.js.map +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.d.ts +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.d.ts.map +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.js +1 -1
- package/bin/executor/composer/system/default/assets/core.prompt.js.map +1 -1
- package/bin/index.d.ts +0 -2
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +1 -4
- package/bin/index.js.map +1 -1
- package/bin/plugin/core/Activation.d.ts +6 -5
- package/bin/plugin/core/Activation.d.ts.map +1 -1
- package/bin/plugin/core/Activation.js +9 -9
- package/bin/plugin/core/Activation.js.map +1 -1
- package/bin/plugin/core/BasePlugin.d.ts +5 -4
- package/bin/plugin/core/BasePlugin.d.ts.map +1 -1
- package/bin/plugin/core/BasePlugin.js +7 -4
- package/bin/plugin/core/BasePlugin.js.map +1 -1
- package/bin/plugin/core/HookRegistry.d.ts +4 -0
- package/bin/plugin/core/HookRegistry.d.ts.map +1 -1
- package/bin/plugin/core/HookRegistry.js +40 -0
- package/bin/plugin/core/HookRegistry.js.map +1 -1
- package/bin/plugin/core/Manager.d.ts +1 -1
- package/bin/plugin/core/Manager.d.ts.map +1 -1
- package/bin/plugin/core/Manager.js +1 -1
- package/bin/plugin/core/Manager.js.map +1 -1
- package/bin/plugin/core/PluginActionRunner.d.ts +13 -7
- package/bin/plugin/core/PluginActionRunner.d.ts.map +1 -1
- package/bin/plugin/core/PluginActionRunner.js +46 -111
- package/bin/plugin/core/PluginActionRunner.js.map +1 -1
- package/bin/plugin/core/PluginCatalog.d.ts +1 -1
- package/bin/plugin/core/PluginCatalog.d.ts.map +1 -1
- package/bin/plugin/core/PluginCatalog.js +1 -21
- package/bin/plugin/core/PluginCatalog.js.map +1 -1
- package/bin/plugin/core/PluginLocalExecution.d.ts +12 -2
- package/bin/plugin/core/PluginLocalExecution.d.ts.map +1 -1
- package/bin/plugin/core/PluginLocalExecution.js +18 -24
- package/bin/plugin/core/PluginLocalExecution.js.map +1 -1
- package/bin/plugin/core/PluginRegistry.d.ts +60 -7
- package/bin/plugin/core/PluginRegistry.d.ts.map +1 -1
- package/bin/plugin/core/PluginRegistry.js +269 -42
- package/bin/plugin/core/PluginRegistry.js.map +1 -1
- package/bin/plugin/core/PluginStateController.d.ts +11 -36
- package/bin/plugin/core/PluginStateController.d.ts.map +1 -1
- package/bin/plugin/core/PluginStateController.js +45 -190
- package/bin/plugin/core/PluginStateController.js.map +1 -1
- package/bin/plugin/types/Plugin.d.ts +1 -1
- package/bin/plugin/types/Plugin.d.ts.map +1 -1
- package/bin/plugin/types/PluginState.d.ts +1 -1
- package/bin/plugin/types/PluginState.d.ts.map +1 -1
- package/bin/plugin/types/Plugins.d.ts +12 -12
- package/bin/plugin/types/Plugins.d.ts.map +1 -1
- package/bin/types/agent/AgentOptions.d.ts +12 -3
- package/bin/types/agent/AgentOptions.d.ts.map +1 -1
- package/bin/types/agent/AgentRuntimeAssembly.d.ts +1 -1
- package/bin/types/config/AgentProject.d.ts +6 -14
- package/bin/types/config/AgentProject.d.ts.map +1 -1
- package/bin/types/plugin/PluginRuntime.d.ts +23 -2
- package/bin/types/plugin/PluginRuntime.d.ts.map +1 -1
- package/bin/types/plugin/PluginState.d.ts +47 -36
- package/bin/types/plugin/PluginState.d.ts.map +1 -1
- package/bin/types/plugin/PluginState.js +4 -3
- package/bin/types/plugin/PluginState.js.map +1 -1
- package/bin/types/runtime/agent/AgentContext.d.ts +3 -3
- package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
- package/bin/types/runtime/agent/AgentContext.js.map +1 -1
- package/package.json +3 -3
- package/src/agent/local/AgentPluginFactory.ts +8 -8
- package/src/agent/local/AgentRuntimeAssembly.ts +3 -9
- package/src/agent/local/ProjectSetup.ts +1 -8
- package/src/agent/local/services/AgentAssemblyService.ts +13 -23
- package/src/agent/local/services/AgentBackgroundService.ts +5 -6
- package/src/agent/local/services/AgentSessionManager.ts +4 -26
- package/src/config/AgentInitializer.ts +7 -57
- package/src/config/DowncitySchema.ts +3 -4
- package/src/executor/composer/system/default/SystemDomain.ts +1 -2
- package/src/executor/composer/system/default/assets/core.prompt.ts +1 -1
- package/src/executor/composer/system/default/assets/core.prompt.ts.txt +1 -1
- package/src/index.ts +1 -8
- package/src/plugin/core/Activation.ts +10 -10
- package/src/plugin/core/BasePlugin.ts +9 -6
- package/src/plugin/core/HookRegistry.ts +41 -0
- package/src/plugin/core/Manager.ts +0 -2
- package/src/plugin/core/PluginActionRunner.ts +52 -133
- package/src/plugin/core/PluginCatalog.ts +1 -23
- package/src/plugin/core/PluginLocalExecution.ts +30 -25
- package/src/plugin/core/PluginRegistry.ts +298 -44
- package/src/plugin/core/PluginStateController.ts +45 -235
- package/src/plugin/types/Plugin.ts +2 -1
- package/src/plugin/types/PluginState.ts +2 -1
- package/src/plugin/types/Plugins.ts +12 -12
- package/src/types/agent/AgentOptions.ts +13 -3
- package/src/types/agent/AgentRuntimeAssembly.ts +1 -1
- package/src/types/config/AgentProject.ts +7 -15
- package/src/types/plugin/PluginRuntime.ts +23 -2
- package/src/types/plugin/PluginState.ts +50 -43
- package/src/types/runtime/agent/AgentContext.ts +3 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/bin/config/Defaults.d.ts +0 -21
- package/bin/config/Defaults.d.ts.map +0 -1
- package/bin/config/Defaults.js +0 -47
- package/bin/config/Defaults.js.map +0 -1
- package/bin/plugin/core/ProjectConfigStore.d.ts +0 -84
- package/bin/plugin/core/ProjectConfigStore.d.ts.map +0 -1
- package/bin/plugin/core/ProjectConfigStore.js +0 -89
- package/bin/plugin/core/ProjectConfigStore.js.map +0 -1
- package/src/config/Defaults.ts +0 -49
- package/src/plugin/core/ProjectConfigStore.ts +0 -155
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Agent plugin runtime。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
5
|
+
* - Plugin 只属于 Agent:注册即生效,卸载即不可见。
|
|
6
|
+
* - 注册时自动启动 plugin lifecycle;卸载时自动停止 plugin lifecycle。
|
|
7
|
+
* - action、system、hook、resolve 都统一以“已注册且 ready”为生效边界。
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
|
-
import { isPluginEnabled } from "@/plugin/core/Activation.js";
|
|
10
10
|
import { toPluginView } from "@/plugin/core/PluginCatalog.js";
|
|
11
11
|
import type { HookRegistry } from "@/plugin/core/HookRegistry.js";
|
|
12
12
|
import type {
|
|
@@ -18,42 +18,218 @@ import type {
|
|
|
18
18
|
PluginReadView,
|
|
19
19
|
PluginView,
|
|
20
20
|
} from "@/plugin/types/Plugin.js";
|
|
21
|
+
import type { AgentSessionSystemBlock } from "@/types/agent/AgentTypes.js";
|
|
21
22
|
import type { AgentContext } from "@/types/runtime/agent/AgentContext.js";
|
|
22
23
|
import type { JsonValue } from "@/types/common/Json.js";
|
|
24
|
+
import type {
|
|
25
|
+
PluginRuntimeRecord,
|
|
26
|
+
PluginSnapshot,
|
|
27
|
+
} from "@/types/plugin/PluginState.js";
|
|
23
28
|
|
|
24
29
|
type ContextResolver = () => AgentContext;
|
|
25
30
|
|
|
31
|
+
function now_ms(): number {
|
|
32
|
+
return Date.now();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function normalize_plugin_name(plugin_name: string): string {
|
|
36
|
+
return String(plugin_name || "").trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function create_record(plugin: Plugin): PluginRuntimeRecord {
|
|
40
|
+
const current_time = now_ms();
|
|
41
|
+
return {
|
|
42
|
+
plugin,
|
|
43
|
+
state: "ready",
|
|
44
|
+
registered_at: current_time,
|
|
45
|
+
updated_at: current_time,
|
|
46
|
+
chain: Promise.resolve(),
|
|
47
|
+
lifecycle_started: false,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function to_plugin_snapshot(record: PluginRuntimeRecord): PluginSnapshot {
|
|
52
|
+
const plugin = record.plugin;
|
|
53
|
+
const last_error = String(record.last_error || "").trim();
|
|
54
|
+
return {
|
|
55
|
+
name: plugin.name,
|
|
56
|
+
title: String(plugin.title || plugin.name || "").trim(),
|
|
57
|
+
description: String(plugin.description || "").trim(),
|
|
58
|
+
status: record.state,
|
|
59
|
+
state: record.state,
|
|
60
|
+
registered_at: record.registered_at,
|
|
61
|
+
updated_at: record.updated_at,
|
|
62
|
+
updatedAt: record.updated_at,
|
|
63
|
+
...(last_error ? { last_error, lastError: last_error } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function update_record_state(
|
|
68
|
+
record: PluginRuntimeRecord,
|
|
69
|
+
state: PluginRuntimeRecord["state"],
|
|
70
|
+
error?: string,
|
|
71
|
+
): void {
|
|
72
|
+
record.state = state;
|
|
73
|
+
record.updated_at = now_ms();
|
|
74
|
+
const normalized_error = String(error || "").trim();
|
|
75
|
+
if (normalized_error) {
|
|
76
|
+
record.last_error = normalized_error;
|
|
77
|
+
} else {
|
|
78
|
+
delete record.last_error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function run_serial(
|
|
83
|
+
record: PluginRuntimeRecord,
|
|
84
|
+
step: () => Promise<void> | void,
|
|
85
|
+
): Promise<void> {
|
|
86
|
+
const next = record.chain.then(() => Promise.resolve(step()));
|
|
87
|
+
record.chain = next.then(
|
|
88
|
+
() => undefined,
|
|
89
|
+
() => undefined,
|
|
90
|
+
);
|
|
91
|
+
await next;
|
|
92
|
+
}
|
|
93
|
+
|
|
26
94
|
/**
|
|
27
|
-
* PluginRegistry:plugin
|
|
95
|
+
* PluginRegistry:Agent plugin 注册、卸载与调用实现。
|
|
28
96
|
*/
|
|
29
97
|
export class PluginRegistry implements AgentPlugins {
|
|
30
98
|
private readonly contextResolver: ContextResolver;
|
|
31
99
|
|
|
32
100
|
private readonly hookRegistry: HookRegistry;
|
|
33
101
|
|
|
34
|
-
private readonly
|
|
102
|
+
private readonly pluginInstances: Map<string, Plugin>;
|
|
103
|
+
|
|
104
|
+
private readonly records = new Map<string, PluginRuntimeRecord>();
|
|
35
105
|
|
|
36
106
|
constructor(params: {
|
|
37
107
|
contextResolver: ContextResolver;
|
|
38
108
|
hookRegistry: HookRegistry;
|
|
109
|
+
pluginInstances: Map<string, Plugin>;
|
|
39
110
|
}) {
|
|
40
111
|
this.contextResolver = params.contextResolver;
|
|
41
112
|
this.hookRegistry = params.hookRegistry;
|
|
113
|
+
this.pluginInstances = params.pluginInstances;
|
|
42
114
|
}
|
|
43
115
|
|
|
44
116
|
/**
|
|
45
|
-
* 注册单个
|
|
117
|
+
* 注册单个 plugin。
|
|
118
|
+
*
|
|
119
|
+
* 说明(中文)
|
|
120
|
+
* - 同名注册表示替换:先卸载旧实例,再注册并启动新实例。
|
|
121
|
+
* - 如果新实例启动失败,会自动回滚为未注册状态并抛错。
|
|
46
122
|
*/
|
|
47
|
-
register(plugin: Plugin):
|
|
48
|
-
const key =
|
|
123
|
+
async register(plugin: Plugin): Promise<PluginSnapshot> {
|
|
124
|
+
const key = normalize_plugin_name(plugin.name);
|
|
49
125
|
if (!key) {
|
|
50
126
|
throw new Error("Plugin name is required");
|
|
51
127
|
}
|
|
52
|
-
if (this.
|
|
128
|
+
if (this.records.has(key)) {
|
|
129
|
+
await this.unregister(key);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const record = create_record(plugin);
|
|
133
|
+
this.records.set(key, record);
|
|
134
|
+
this.register_hooks(plugin);
|
|
135
|
+
this.pluginInstances.set(key, plugin);
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
await this.start_record(record);
|
|
139
|
+
return to_plugin_snapshot(record);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
this.unregister_hooks(key);
|
|
142
|
+
this.records.delete(key);
|
|
143
|
+
this.pluginInstances.delete(key);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 同步挂载 plugin 元信息。
|
|
150
|
+
*
|
|
151
|
+
* 说明(中文)
|
|
152
|
+
* - 仅供 Agent 构造期使用,避免构造函数里 await。
|
|
153
|
+
* - 后续 `startAll()` 会统一启动这些初始 plugin。
|
|
154
|
+
*/
|
|
155
|
+
mount(plugin: Plugin): PluginSnapshot {
|
|
156
|
+
const key = normalize_plugin_name(plugin.name);
|
|
157
|
+
if (!key) {
|
|
158
|
+
throw new Error("Plugin name is required");
|
|
159
|
+
}
|
|
160
|
+
if (this.records.has(key)) {
|
|
53
161
|
throw new Error(`Plugin already registered: ${key}`);
|
|
54
162
|
}
|
|
55
|
-
this.plugins.set(key, plugin);
|
|
56
163
|
|
|
164
|
+
const record = create_record(plugin);
|
|
165
|
+
this.records.set(key, record);
|
|
166
|
+
this.register_hooks(plugin);
|
|
167
|
+
this.pluginInstances.set(key, plugin);
|
|
168
|
+
return to_plugin_snapshot(record);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 卸载指定 plugin。
|
|
173
|
+
*/
|
|
174
|
+
async unregister(pluginName: string): Promise<boolean> {
|
|
175
|
+
const key = normalize_plugin_name(pluginName);
|
|
176
|
+
if (!key) return false;
|
|
177
|
+
const record = this.records.get(key);
|
|
178
|
+
if (!record) return false;
|
|
179
|
+
|
|
180
|
+
await this.stop_record(record);
|
|
181
|
+
this.unregister_hooks(key);
|
|
182
|
+
this.records.delete(key);
|
|
183
|
+
this.pluginInstances.delete(key);
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* 启动全部已挂载 plugin。
|
|
189
|
+
*/
|
|
190
|
+
async startAll(): Promise<PluginSnapshot[]> {
|
|
191
|
+
const snapshots: PluginSnapshot[] = [];
|
|
192
|
+
for (const record of this.records.values()) {
|
|
193
|
+
await this.start_record(record);
|
|
194
|
+
snapshots.push(to_plugin_snapshot(record));
|
|
195
|
+
}
|
|
196
|
+
return snapshots;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 卸载全部 plugin。
|
|
201
|
+
*/
|
|
202
|
+
async unregisterAll(): Promise<void> {
|
|
203
|
+
for (const name of Array.from(this.records.keys())) {
|
|
204
|
+
await this.unregister(name);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 判断 plugin 是否已注册且 ready。
|
|
210
|
+
*/
|
|
211
|
+
isReady(pluginName: string): boolean {
|
|
212
|
+
const record = this.records.get(normalize_plugin_name(pluginName));
|
|
213
|
+
return Boolean(record && record.state === "ready");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* 读取单个 plugin 快照。
|
|
218
|
+
*/
|
|
219
|
+
status(pluginName: string): PluginSnapshot | null {
|
|
220
|
+
const record = this.records.get(normalize_plugin_name(pluginName));
|
|
221
|
+
return record ? to_plugin_snapshot(record) : null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* 判断 plugin 是否已注册。
|
|
226
|
+
*/
|
|
227
|
+
has(pluginName: string): boolean {
|
|
228
|
+
return this.records.has(normalize_plugin_name(pluginName));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private register_hooks(plugin: Plugin): void {
|
|
232
|
+
const key = normalize_plugin_name(plugin.name);
|
|
57
233
|
for (const [hookName, handlers] of Object.entries(
|
|
58
234
|
plugin.hooks?.pipeline || {},
|
|
59
235
|
)) {
|
|
@@ -83,6 +259,43 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
83
259
|
}
|
|
84
260
|
}
|
|
85
261
|
|
|
262
|
+
private unregister_hooks(pluginName: string): void {
|
|
263
|
+
this.hookRegistry.unregisterPlugin(pluginName);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private async start_record(record: PluginRuntimeRecord): Promise<void> {
|
|
267
|
+
if (record.lifecycle_started) {
|
|
268
|
+
update_record_state(record, "ready");
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
await run_serial(record, async () => {
|
|
272
|
+
if (record.lifecycle_started) {
|
|
273
|
+
update_record_state(record, "ready");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
await record.plugin.lifecycle?.start?.(this.contextResolver());
|
|
278
|
+
record.lifecycle_started = true;
|
|
279
|
+
update_record_state(record, "ready");
|
|
280
|
+
} catch (error) {
|
|
281
|
+
update_record_state(record, "error", String(error));
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private async stop_record(record: PluginRuntimeRecord): Promise<void> {
|
|
288
|
+
await run_serial(record, async () => {
|
|
289
|
+
if (!record.lifecycle_started) return;
|
|
290
|
+
try {
|
|
291
|
+
await record.plugin.lifecycle?.stop?.(this.contextResolver());
|
|
292
|
+
} finally {
|
|
293
|
+
record.lifecycle_started = false;
|
|
294
|
+
record.updated_at = now_ms();
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
86
299
|
/**
|
|
87
300
|
* 运行 pipeline 点。
|
|
88
301
|
*/
|
|
@@ -118,15 +331,24 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
118
331
|
* 获取单个 plugin 定义。
|
|
119
332
|
*/
|
|
120
333
|
get(pluginName: string): Plugin | null {
|
|
121
|
-
return this.
|
|
334
|
+
return this.records.get(normalize_plugin_name(pluginName))?.plugin || null;
|
|
122
335
|
}
|
|
123
336
|
|
|
124
337
|
/**
|
|
125
338
|
* 列出全部 plugin 概览视图。
|
|
126
339
|
*/
|
|
127
340
|
list(): PluginView[] {
|
|
128
|
-
return Array.from(this.
|
|
129
|
-
.map((
|
|
341
|
+
return Array.from(this.records.values())
|
|
342
|
+
.map((record) => toPluginView(record.plugin))
|
|
343
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* 列出全部 plugin 注册快照。
|
|
348
|
+
*/
|
|
349
|
+
snapshots(): PluginSnapshot[] {
|
|
350
|
+
return Array.from(this.records.values())
|
|
351
|
+
.map((record) => to_plugin_snapshot(record))
|
|
130
352
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
131
353
|
}
|
|
132
354
|
|
|
@@ -158,7 +380,7 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
158
380
|
plugin?: string;
|
|
159
381
|
action?: string;
|
|
160
382
|
}): PluginReadView | { plugins: PluginView[] } {
|
|
161
|
-
const pluginName =
|
|
383
|
+
const pluginName = normalize_plugin_name(params.plugin || "");
|
|
162
384
|
if (!pluginName) {
|
|
163
385
|
return { plugins: this.list() };
|
|
164
386
|
}
|
|
@@ -171,7 +393,7 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
171
393
|
actions: [],
|
|
172
394
|
};
|
|
173
395
|
}
|
|
174
|
-
const actionName =
|
|
396
|
+
const actionName = normalize_plugin_name(params.action || "");
|
|
175
397
|
const actions = Object.entries(plugin.actions || {})
|
|
176
398
|
.filter(([name]) => !actionName || name === actionName)
|
|
177
399
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
@@ -188,8 +410,9 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
188
410
|
* 检查 plugin 可用性。
|
|
189
411
|
*/
|
|
190
412
|
async availability(pluginName: string): Promise<PluginAvailability> {
|
|
191
|
-
const
|
|
192
|
-
|
|
413
|
+
const key = normalize_plugin_name(pluginName);
|
|
414
|
+
const record = this.records.get(key);
|
|
415
|
+
if (!record) {
|
|
193
416
|
return {
|
|
194
417
|
enabled: false,
|
|
195
418
|
available: false,
|
|
@@ -197,20 +420,18 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
197
420
|
};
|
|
198
421
|
}
|
|
199
422
|
|
|
200
|
-
if (
|
|
201
|
-
return await plugin.availability(this.contextResolver());
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const context = this.contextResolver();
|
|
205
|
-
const enabled = isPluginEnabled({ plugin, context });
|
|
206
|
-
|
|
207
|
-
if (!enabled) {
|
|
423
|
+
if (record.state !== "ready") {
|
|
208
424
|
return {
|
|
209
|
-
enabled:
|
|
425
|
+
enabled: true,
|
|
210
426
|
available: false,
|
|
211
|
-
reasons: [`Plugin "${plugin.name}" is
|
|
427
|
+
reasons: [record.last_error || `Plugin "${record.plugin.name}" is not ready`],
|
|
212
428
|
};
|
|
213
429
|
}
|
|
430
|
+
|
|
431
|
+
if (record.plugin.availability) {
|
|
432
|
+
return await record.plugin.availability(this.contextResolver());
|
|
433
|
+
}
|
|
434
|
+
|
|
214
435
|
return {
|
|
215
436
|
enabled: true,
|
|
216
437
|
available: true,
|
|
@@ -248,8 +469,9 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
248
469
|
action: string;
|
|
249
470
|
payload?: JsonValue;
|
|
250
471
|
}): Promise<PluginActionResult<JsonValue>> {
|
|
251
|
-
const
|
|
252
|
-
|
|
472
|
+
const key = normalize_plugin_name(params.plugin);
|
|
473
|
+
const record = this.records.get(key);
|
|
474
|
+
if (!record) {
|
|
253
475
|
return {
|
|
254
476
|
success: false,
|
|
255
477
|
error: `Unknown plugin: ${params.plugin}`,
|
|
@@ -257,7 +479,7 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
257
479
|
};
|
|
258
480
|
}
|
|
259
481
|
|
|
260
|
-
const actionName =
|
|
482
|
+
const actionName = normalize_plugin_name(params.action);
|
|
261
483
|
if (!actionName) {
|
|
262
484
|
return {
|
|
263
485
|
success: false,
|
|
@@ -266,28 +488,26 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
266
488
|
};
|
|
267
489
|
}
|
|
268
490
|
|
|
269
|
-
|
|
270
|
-
if (!action) {
|
|
491
|
+
if (record.state !== "ready") {
|
|
271
492
|
return {
|
|
272
493
|
success: false,
|
|
273
|
-
error: `Plugin "${plugin.name}"
|
|
274
|
-
message: `Plugin "${plugin.name}"
|
|
494
|
+
error: `Plugin "${record.plugin.name}" is not ready`,
|
|
495
|
+
message: `Plugin "${record.plugin.name}" is not ready`,
|
|
275
496
|
};
|
|
276
497
|
}
|
|
277
498
|
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
if (!enabled && action.allowWhenDisabled !== true) {
|
|
499
|
+
const action = record.plugin.actions?.[actionName];
|
|
500
|
+
if (!action) {
|
|
281
501
|
return {
|
|
282
502
|
success: false,
|
|
283
|
-
error: `Plugin "${plugin.name}"
|
|
284
|
-
message: `Plugin "${plugin.name}"
|
|
503
|
+
error: `Plugin "${record.plugin.name}" does not implement action "${actionName}"`,
|
|
504
|
+
message: `Plugin "${record.plugin.name}" does not implement action "${actionName}"`,
|
|
285
505
|
};
|
|
286
506
|
}
|
|
287
507
|
|
|
288
508
|
try {
|
|
289
509
|
const parsed_payload = this.parseActionPayload({
|
|
290
|
-
pluginName: plugin.name,
|
|
510
|
+
pluginName: record.plugin.name,
|
|
291
511
|
actionName,
|
|
292
512
|
payload: (params.payload ?? {}) as JsonValue,
|
|
293
513
|
action,
|
|
@@ -295,14 +515,19 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
295
515
|
if (!("input" in parsed_payload)) {
|
|
296
516
|
return parsed_payload;
|
|
297
517
|
}
|
|
298
|
-
|
|
299
|
-
context,
|
|
518
|
+
const result = await action.execute({
|
|
519
|
+
context: this.contextResolver(),
|
|
300
520
|
payload: parsed_payload.input,
|
|
301
521
|
input: parsed_payload.input,
|
|
302
|
-
pluginName: plugin.name,
|
|
522
|
+
pluginName: record.plugin.name,
|
|
303
523
|
actionName,
|
|
304
524
|
});
|
|
525
|
+
if (!result.success) {
|
|
526
|
+
update_record_state(record, "error", result.error || result.message);
|
|
527
|
+
}
|
|
528
|
+
return result;
|
|
305
529
|
} catch (error) {
|
|
530
|
+
update_record_state(record, "error", String(error));
|
|
306
531
|
return {
|
|
307
532
|
success: false,
|
|
308
533
|
error: String(error),
|
|
@@ -310,4 +535,33 @@ export class PluginRegistry implements AgentPlugins {
|
|
|
310
535
|
};
|
|
311
536
|
}
|
|
312
537
|
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* 读取当前生效的 plugin system blocks。
|
|
541
|
+
*/
|
|
542
|
+
async systemBlocks(): Promise<AgentSessionSystemBlock[]> {
|
|
543
|
+
const context = this.contextResolver();
|
|
544
|
+
const out: AgentSessionSystemBlock[] = [];
|
|
545
|
+
for (const record of this.records.values()) {
|
|
546
|
+
const plugin = record.plugin;
|
|
547
|
+
if (record.state !== "ready") continue;
|
|
548
|
+
if (typeof plugin.system !== "function") continue;
|
|
549
|
+
try {
|
|
550
|
+
if (typeof plugin.availability === "function") {
|
|
551
|
+
const availability = await plugin.availability(context);
|
|
552
|
+
if (!availability.available) continue;
|
|
553
|
+
}
|
|
554
|
+
const text = String(await plugin.system(context)).trim();
|
|
555
|
+
if (!text) continue;
|
|
556
|
+
out.push({
|
|
557
|
+
source: "plugin",
|
|
558
|
+
name: plugin.name,
|
|
559
|
+
content: text,
|
|
560
|
+
});
|
|
561
|
+
} catch {
|
|
562
|
+
// 单个 plugin system 失败不应阻断 session 主链路。
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return out;
|
|
566
|
+
}
|
|
313
567
|
}
|