@zhin.js/core 1.0.50 → 1.0.52

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -1
  3. package/lib/adapter.d.ts +10 -19
  4. package/lib/adapter.d.ts.map +1 -1
  5. package/lib/adapter.js +47 -80
  6. package/lib/adapter.js.map +1 -1
  7. package/lib/ai/types.d.ts +11 -0
  8. package/lib/ai/types.d.ts.map +1 -1
  9. package/lib/built/common-adapter-tools.d.ts +2 -2
  10. package/lib/built/common-adapter-tools.js +3 -3
  11. package/lib/built/common-adapter-tools.js.map +1 -1
  12. package/lib/built/dispatcher.d.ts +52 -42
  13. package/lib/built/dispatcher.d.ts.map +1 -1
  14. package/lib/built/dispatcher.js +194 -60
  15. package/lib/built/dispatcher.js.map +1 -1
  16. package/lib/built/login-assist.d.ts +61 -0
  17. package/lib/built/login-assist.d.ts.map +1 -0
  18. package/lib/built/login-assist.js +75 -0
  19. package/lib/built/login-assist.js.map +1 -0
  20. package/lib/built/skill.d.ts +3 -20
  21. package/lib/built/skill.d.ts.map +1 -1
  22. package/lib/built/skill.js +1 -53
  23. package/lib/built/skill.js.map +1 -1
  24. package/lib/index.d.ts +1 -0
  25. package/lib/index.d.ts.map +1 -1
  26. package/lib/index.js +2 -0
  27. package/lib/index.js.map +1 -1
  28. package/lib/plugin.d.ts +18 -0
  29. package/lib/plugin.d.ts.map +1 -1
  30. package/lib/plugin.js +1 -1
  31. package/lib/plugin.js.map +1 -1
  32. package/lib/types.d.ts +13 -0
  33. package/lib/types.d.ts.map +1 -1
  34. package/lib/utils.js +1 -1
  35. package/package.json +6 -6
  36. package/src/adapter.ts +51 -95
  37. package/src/ai/types.ts +3 -1
  38. package/src/built/common-adapter-tools.ts +3 -3
  39. package/src/built/dispatcher.ts +264 -99
  40. package/src/built/login-assist.ts +131 -0
  41. package/src/built/skill.ts +3 -75
  42. package/src/index.ts +2 -0
  43. package/src/plugin.ts +24 -5
  44. package/src/types.ts +16 -0
  45. package/src/utils.ts +1 -1
  46. package/tests/adapter.test.ts +40 -128
  47. package/tests/dispatcher.test.ts +155 -8
  48. package/tests/redos-protection.test.ts +5 -4
@@ -11,32 +11,52 @@
11
11
  * ▼
12
12
  * ┌────────────────────────────────────────┐
13
13
  * │ Stage 2: Route(路径判定) │
14
- * │ 精确命令 Command 快速路径
15
- * │ 其它消息 AI Agent 路径
14
+ * │ exclusive:命令与 AI 互斥(旧行为)
15
+ * │ dual:命令与 AI 独立判定,可同时命中
16
16
  * └──────────────┬─────────────────────────┘
17
17
  * ▼
18
18
  * ┌────────────────────────────────────────┐
19
19
  * │ Stage 3: Handle(处理) │
20
20
  * │ Command: commandService.handle() │
21
21
  * │ AI: aiHandler (由 AI 模块注册) │
22
+ * │ 出站:replyWithPolish → $reply → Adapter.sendMessage → before.sendMessage │
22
23
  * └────────────────────────────────────────┘
23
24
  *
24
25
  * 注意:Context key 为 'dispatcher',避免与 HTTP 模块的 'router' 冲突。
26
+ *
27
+ * 默认路由为 exclusive(命令与 AI 互斥);需双轨时请显式 dualRoute.mode: 'dual'。
25
28
  */
29
+ import { AsyncLocalStorage } from 'node:async_hooks';
26
30
  import { getPlugin } from '../plugin.js';
31
+ /** Dispatcher 管理的「会话回复」异步上下文,供 `before.sendMessage` 内读取(与 Adapter.renderSendMessage 同链) */
32
+ const outboundReplyAls = new AsyncLocalStorage();
33
+ export function getOutboundReplyStore() {
34
+ return outboundReplyAls.getStore();
35
+ }
36
+ const DUAL_ROUTE_DEFAULTS = {
37
+ mode: 'exclusive',
38
+ order: 'command-first',
39
+ allowDualReply: false,
40
+ };
41
+ function resolveDualRouteConfig(partial) {
42
+ return {
43
+ mode: partial?.mode ?? DUAL_ROUTE_DEFAULTS.mode,
44
+ order: partial?.order ?? DUAL_ROUTE_DEFAULTS.order,
45
+ allowDualReply: partial?.allowDualReply ?? DUAL_ROUTE_DEFAULTS.allowDualReply,
46
+ };
47
+ }
27
48
  // ============================================================================
28
49
  // 实现
29
50
  // ============================================================================
30
- /**
31
- * 创建 MessageDispatcher Context
32
- */
33
- export function createMessageDispatcher() {
51
+ export function createMessageDispatcher(options) {
34
52
  const guardrails = [];
53
+ /** mounted 前注册的润色,在 mounted 时挂到 root.before.sendMessage */
54
+ const pendingOutboundPolish = [];
35
55
  let aiHandler = null;
36
56
  let aiTriggerMatcher = null;
37
57
  let commandMatcher = null;
38
58
  let rootPlugin = null;
39
- // Command prefix index — rebuilt lazily for O(1) lookup
59
+ let dualRoute = resolveDualRouteConfig(options?.dualRoute);
40
60
  let commandPrefixIndex = null;
41
61
  let lastCommandCount = -1;
42
62
  function rebuildCommandIndex() {
@@ -62,16 +82,15 @@ export function createMessageDispatcher() {
62
82
  }
63
83
  return commandPrefixIndex;
64
84
  }
65
- /**
66
- * Guardrail pipeline — a guardrail that does NOT call next() blocks the message.
67
- */
68
85
  async function runGuardrails(message) {
69
86
  if (guardrails.length === 0)
70
87
  return true;
71
88
  for (const guardrail of guardrails) {
72
89
  let nextCalled = false;
73
90
  try {
74
- await guardrail(message, async () => { nextCalled = true; });
91
+ await guardrail(message, async () => {
92
+ nextCalled = true;
93
+ });
75
94
  }
76
95
  catch {
77
96
  return false;
@@ -81,12 +100,42 @@ export function createMessageDispatcher() {
81
100
  }
82
101
  return true;
83
102
  }
84
- function route(message) {
103
+ function extractText(message) {
104
+ if (!message.$content)
105
+ return '';
106
+ return message.$content
107
+ .map((seg) => {
108
+ if (typeof seg === 'string')
109
+ return seg;
110
+ if (seg.type === 'text')
111
+ return seg.data?.text || '';
112
+ return '';
113
+ })
114
+ .join('')
115
+ .trim();
116
+ }
117
+ function matchCommandInternal(message) {
118
+ const text = extractText(message);
119
+ if (commandMatcher && commandMatcher(text, message))
120
+ return true;
121
+ const index = getCommandIndex();
122
+ for (const [prefix] of index) {
123
+ if (text.startsWith(prefix))
124
+ return true;
125
+ }
126
+ return false;
127
+ }
128
+ function matchAIInternal(message) {
129
+ if (!aiTriggerMatcher)
130
+ return { triggered: false, content: '' };
131
+ return aiTriggerMatcher(message);
132
+ }
133
+ /** 互斥路由(与旧版 route 一致) */
134
+ function routeExclusive(message) {
85
135
  const text = extractText(message);
86
136
  if (commandMatcher && commandMatcher(text, message)) {
87
137
  return { type: 'command' };
88
138
  }
89
- // Use indexed lookup instead of O(N) scan
90
139
  const index = getCommandIndex();
91
140
  for (const [prefix] of index) {
92
141
  if (text.startsWith(prefix)) {
@@ -101,62 +150,111 @@ export function createMessageDispatcher() {
101
150
  }
102
151
  return { type: 'skip' };
103
152
  }
104
- function extractText(message) {
105
- if (!message.$content)
106
- return '';
107
- return message.$content
108
- .map((seg) => {
109
- if (typeof seg === 'string')
110
- return seg;
111
- if (seg.type === 'text')
112
- return seg.data?.text || '';
113
- return '';
114
- })
115
- .join('')
116
- .trim();
153
+ function wrapPolishAsBeforeSend(handler) {
154
+ return async (options) => {
155
+ const store = outboundReplyAls.getStore();
156
+ if (!store)
157
+ return;
158
+ const ctx = {
159
+ message: store.message,
160
+ content: options.content,
161
+ source: store.source,
162
+ };
163
+ const next = await handler(ctx);
164
+ if (next !== undefined)
165
+ return { ...options, content: next };
166
+ };
167
+ }
168
+ function flushPendingOutboundPolish() {
169
+ if (!rootPlugin)
170
+ return;
171
+ const root = rootPlugin.root;
172
+ for (const mw of pendingOutboundPolish) {
173
+ const fn = wrapPolishAsBeforeSend(mw);
174
+ root.on('before.sendMessage', fn);
175
+ }
176
+ pendingOutboundPolish.length = 0;
177
+ }
178
+ async function replyWithPolishInternal(message, source, content) {
179
+ if (!rootPlugin) {
180
+ return message.$reply(content);
181
+ }
182
+ return outboundReplyAls.run({ message, source }, () => message.$reply(content));
183
+ }
184
+ async function runCommandBranch(message) {
185
+ if (!rootPlugin)
186
+ return;
187
+ const commandService = rootPlugin.inject('command');
188
+ if (!commandService)
189
+ return;
190
+ const response = await commandService.handle(message, rootPlugin);
191
+ if (response) {
192
+ await replyWithPolishInternal(message, 'command', response);
193
+ }
194
+ }
195
+ async function runCustomMiddlewares(message) {
196
+ if (!rootPlugin)
197
+ return;
198
+ const customMiddlewares = rootPlugin._getCustomMiddlewares?.();
199
+ if (customMiddlewares && customMiddlewares.length > 0) {
200
+ const { compose } = await import('../utils.js');
201
+ const composed = compose(customMiddlewares);
202
+ await composed(message, async () => { });
203
+ }
117
204
  }
118
205
  const service = {
119
206
  async dispatch(message) {
120
- // Stage 1: Guardrail
121
207
  const passed = await runGuardrails(message);
122
208
  if (!passed)
123
209
  return;
124
- // Stage 2: Route
125
- const result = route(message);
126
- // Stage 3: Handle
127
- switch (result.type) {
128
- case 'command': {
129
- if (rootPlugin) {
130
- const commandService = rootPlugin.inject('command');
131
- if (commandService) {
132
- const response = await commandService.handle(message, rootPlugin);
133
- if (response) {
134
- await message.$reply(response);
135
- }
136
- }
137
- }
138
- break;
210
+ const cfg = dualRoute;
211
+ if (cfg.mode === 'exclusive') {
212
+ const result = routeExclusive(message);
213
+ switch (result.type) {
214
+ case 'command':
215
+ await runCommandBranch(message);
216
+ break;
217
+ case 'ai':
218
+ if (aiHandler)
219
+ await aiHandler(message, result.content);
220
+ break;
221
+ default:
222
+ break;
139
223
  }
140
- case 'ai': {
141
- if (aiHandler) {
142
- await aiHandler(message, result.content);
143
- }
144
- break;
145
- }
146
- case 'skip':
147
- default:
148
- break;
224
+ await runCustomMiddlewares(message);
225
+ return;
149
226
  }
150
- // Run legacy custom middlewares (skip the built-in command middleware at index 0).
151
- // This ensures plugins that registered middlewares via addMiddleware() still work.
152
- if (rootPlugin) {
153
- const customMiddlewares = rootPlugin._getCustomMiddlewares?.();
154
- if (customMiddlewares && customMiddlewares.length > 0) {
155
- const { compose } = await import('../utils.js');
156
- const composed = compose(customMiddlewares);
157
- await composed(message, async () => { });
158
- }
227
+ // dual 模式
228
+ let wantCmd = matchCommandInternal(message);
229
+ const aiRes = matchAIInternal(message);
230
+ let wantAi = aiRes.triggered;
231
+ if (!wantCmd && !wantAi) {
232
+ await runCustomMiddlewares(message);
233
+ return;
234
+ }
235
+ if (!cfg.allowDualReply && wantCmd && wantAi) {
236
+ if (cfg.order === 'command-first')
237
+ wantAi = false;
238
+ else
239
+ wantCmd = false;
159
240
  }
241
+ const runCmd = async () => {
242
+ if (wantCmd)
243
+ await runCommandBranch(message);
244
+ };
245
+ const runAi = async () => {
246
+ if (wantAi && aiHandler)
247
+ await aiHandler(message, aiRes.content);
248
+ };
249
+ if (cfg.order === 'ai-first') {
250
+ await runAi();
251
+ await runCmd();
252
+ }
253
+ else {
254
+ await runCmd();
255
+ await runAi();
256
+ }
257
+ await runCustomMiddlewares(message);
160
258
  },
161
259
  addGuardrail(guardrail) {
162
260
  guardrails.push(guardrail);
@@ -178,6 +276,35 @@ export function createMessageDispatcher() {
178
276
  hasAIHandler() {
179
277
  return aiHandler !== null;
180
278
  },
279
+ setDualRouteConfig(config) {
280
+ dualRoute = resolveDualRouteConfig({ ...dualRoute, ...config });
281
+ },
282
+ getDualRouteConfig() {
283
+ return { ...dualRoute };
284
+ },
285
+ addOutboundPolish(handler) {
286
+ const fn = wrapPolishAsBeforeSend(handler);
287
+ if (rootPlugin) {
288
+ const root = rootPlugin.root;
289
+ root.on('before.sendMessage', fn);
290
+ return () => root.off('before.sendMessage', fn);
291
+ }
292
+ pendingOutboundPolish.push(handler);
293
+ return () => {
294
+ const i = pendingOutboundPolish.indexOf(handler);
295
+ if (i !== -1)
296
+ pendingOutboundPolish.splice(i, 1);
297
+ };
298
+ },
299
+ replyWithPolish(message, source, content) {
300
+ return replyWithPolishInternal(message, source, content);
301
+ },
302
+ matchCommand(message) {
303
+ return matchCommandInternal(message);
304
+ },
305
+ matchAI(message) {
306
+ return matchAIInternal(message);
307
+ },
181
308
  };
182
309
  return {
183
310
  name: 'dispatcher',
@@ -185,6 +312,7 @@ export function createMessageDispatcher() {
185
312
  value: service,
186
313
  mounted(plugin) {
187
314
  rootPlugin = plugin.root;
315
+ flushPendingOutboundPolish();
188
316
  return service;
189
317
  },
190
318
  extensions: {
@@ -194,6 +322,12 @@ export function createMessageDispatcher() {
194
322
  plugin.onDispose(dispose);
195
323
  return dispose;
196
324
  },
325
+ addOutboundPolish(handler) {
326
+ const plugin = getPlugin();
327
+ const dispose = service.addOutboundPolish(handler);
328
+ plugin.onDispose(dispose);
329
+ return dispose;
330
+ },
197
331
  },
198
332
  };
199
333
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/built/dispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/built/dispatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * LoginAssist — 登录辅助生产者-消费者
3
+ *
4
+ * 适配器在需要人为辅助登录时(扫码、短信、滑块等)作为生产者投递待办;
5
+ * Web 控制台、命令行等作为消费者拉取待办并提交结果。
6
+ * 待办未消费前会一直保留,刷新页面后仍可继续消费。
7
+ *
8
+ * 事件:
9
+ * bot.login.pending — 有新待办时触发,payload: PendingLoginTask
10
+ */
11
+ import type { Plugin } from '../plugin.js';
12
+ export type LoginAssistType = 'qrcode' | 'sms' | 'slider' | 'device' | 'other';
13
+ export interface PendingLoginTaskPayload {
14
+ /** 说明文案(如「请扫码登录」) */
15
+ message?: string;
16
+ /** 二维码图片 URL 或 base64(type=qrcode 时) */
17
+ image?: string;
18
+ /** 滑块验证 URL(type=slider 时) */
19
+ url?: string;
20
+ /** 其它扩展字段 */
21
+ [key: string]: unknown;
22
+ }
23
+ export interface PendingLoginTask {
24
+ id: string;
25
+ adapter: string;
26
+ botId: string;
27
+ type: LoginAssistType;
28
+ payload: PendingLoginTaskPayload;
29
+ createdAt: number;
30
+ }
31
+ export declare class LoginAssist {
32
+ private readonly plugin;
33
+ private readonly pending;
34
+ private idSeq;
35
+ constructor(plugin: Plugin);
36
+ /**
37
+ * 生产者:等待用户输入后 resolve。会发出 bot.login.pending 事件,未消费前可被 listPending 拉取(刷新后可继续消费)。
38
+ */
39
+ waitForInput(adapter: string, botId: string, type: LoginAssistType, payload?: PendingLoginTaskPayload): Promise<string | Record<string, unknown>>;
40
+ /**
41
+ * 消费者:提交结果,对应 waitForInput 的 Promise 会 resolve。
42
+ */
43
+ submit(id: string, value: string | Record<string, unknown>): boolean;
44
+ /**
45
+ * 消费者:取消某条待办,对应 Promise 会 reject。
46
+ */
47
+ cancel(id: string, reason?: string): boolean;
48
+ /**
49
+ * 列出未消费的待办(供 Web/CLI 展示,刷新后仍可拉取同一列表)。
50
+ */
51
+ listPending(): PendingLoginTask[];
52
+ dispose(): void;
53
+ }
54
+ declare module '../plugin.js' {
55
+ namespace Plugin {
56
+ interface Contexts {
57
+ loginAssist: LoginAssist;
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=login-assist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-assist.d.ts","sourceRoot":"","sources":["../../src/built/login-assist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAM3C,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/E,MAAM,WAAW,uBAAuB;IACtC,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,uBAAuB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAYD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,KAAK,CAAK;gBAEN,MAAM,EAAE,MAAM;IAI1B;;OAEG;IACH,YAAY,CACV,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,eAAe,EACrB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAiB5C;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO;IAQpE;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,SAAc,GAAG,OAAO;IAQjD;;OAEG;IACH,WAAW,IAAI,gBAAgB,EAAE;IAIjC,OAAO,IAAI,IAAI;CAMhB;AAMD,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,MAAM,CAAC;QACf,UAAU,QAAQ;YAChB,WAAW,EAAE,WAAW,CAAC;SAC1B;KACF;CACF"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * LoginAssist — 登录辅助生产者-消费者
3
+ *
4
+ * 适配器在需要人为辅助登录时(扫码、短信、滑块等)作为生产者投递待办;
5
+ * Web 控制台、命令行等作为消费者拉取待办并提交结果。
6
+ * 待办未消费前会一直保留,刷新页面后仍可继续消费。
7
+ *
8
+ * 事件:
9
+ * bot.login.pending — 有新待办时触发,payload: PendingLoginTask
10
+ */
11
+ // ============================================================================
12
+ // LoginAssist 服务
13
+ // ============================================================================
14
+ export class LoginAssist {
15
+ plugin;
16
+ pending = new Map();
17
+ idSeq = 0;
18
+ constructor(plugin) {
19
+ this.plugin = plugin;
20
+ }
21
+ /**
22
+ * 生产者:等待用户输入后 resolve。会发出 bot.login.pending 事件,未消费前可被 listPending 拉取(刷新后可继续消费)。
23
+ */
24
+ waitForInput(adapter, botId, type, payload = {}) {
25
+ const id = `login-${Date.now()}-${++this.idSeq}`;
26
+ const task = {
27
+ id,
28
+ adapter,
29
+ botId,
30
+ type,
31
+ payload: { message: payload.message ?? '', ...payload },
32
+ createdAt: Date.now(),
33
+ };
34
+ const promise = new Promise((resolve, reject) => {
35
+ this.pending.set(id, { task, resolve, reject });
36
+ this.plugin.emit('bot.login.pending', task);
37
+ });
38
+ return promise;
39
+ }
40
+ /**
41
+ * 消费者:提交结果,对应 waitForInput 的 Promise 会 resolve。
42
+ */
43
+ submit(id, value) {
44
+ const entry = this.pending.get(id);
45
+ if (!entry)
46
+ return false;
47
+ this.pending.delete(id);
48
+ entry.resolve(value);
49
+ return true;
50
+ }
51
+ /**
52
+ * 消费者:取消某条待办,对应 Promise 会 reject。
53
+ */
54
+ cancel(id, reason = 'cancelled') {
55
+ const entry = this.pending.get(id);
56
+ if (!entry)
57
+ return false;
58
+ this.pending.delete(id);
59
+ entry.reject(new Error(reason));
60
+ return true;
61
+ }
62
+ /**
63
+ * 列出未消费的待办(供 Web/CLI 展示,刷新后仍可拉取同一列表)。
64
+ */
65
+ listPending() {
66
+ return [...this.pending.values()].map((e) => e.task);
67
+ }
68
+ dispose() {
69
+ for (const [, entry] of this.pending) {
70
+ entry.reject(new Error('LoginAssist disposed'));
71
+ }
72
+ this.pending.clear();
73
+ }
74
+ }
75
+ //# sourceMappingURL=login-assist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-assist.js","sourceRoot":"","sources":["../../src/built/login-assist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAoCH,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,MAAM,OAAO,WAAW;IACL,MAAM,CAAS;IACf,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IACnD,KAAK,GAAG,CAAC,CAAC;IAElB,YAAY,MAAc;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,YAAY,CACV,OAAe,EACf,KAAa,EACb,IAAqB,EACrB,UAAmC,EAAE;QAErC,MAAM,EAAE,GAAG,SAAS,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACjD,MAAM,IAAI,GAAqB;YAC7B,EAAE;YACF,OAAO;YACP,KAAK;YACL,IAAI;YACJ,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE;YACvD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAmC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU,EAAE,KAAuC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU,EAAE,MAAM,GAAG,WAAW;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,OAAO;QACL,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACrC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
@@ -5,8 +5,7 @@
5
5
  * Plugin = 运行时容器(生命周期、服务注册、中间件)
6
6
  * Skill = AI 可见的能力接口(名称、描述、工具列表)
7
7
  *
8
- * 每个 Plugin 可以声明一个 Skill 描述,告诉 AI Agent
9
- * "我叫什么、我能做什么、我有哪些工具"
8
+ * Skill 记录由运行时注入(如 Agent 从磁盘 SKILL.md 同步),供 Agent 粗筛与工具关联。
10
9
  *
11
10
  * SkillFeature 全局收集所有 Skill,供 Agent 进行两级过滤:
12
11
  * 1. 粗筛:根据用户消息选择相关 Skill
@@ -38,28 +37,18 @@ export interface Skill {
38
37
  pluginName: string;
39
38
  }
40
39
  /**
41
- * Skill 元数据 开发者在插件中声明
42
- * 由 plugin.declareSkill() 注册
40
+ * SKILL.md frontmatter 常见字段(类型提示;运行时由 Agent 等同步到 SkillFeature)
43
41
  */
44
42
  export interface SkillMetadata {
45
43
  /** 技能描述(必填) */
46
44
  description: string;
47
- /** 触发关键词(可选,自动从工具中聚合) */
45
+ /** 触发关键词(可选) */
48
46
  keywords?: string[];
49
47
  /** 分类标签(可选) */
50
48
  tags?: string[];
51
49
  }
52
- export interface SkillContextExtensions {
53
- /**
54
- * 声明本插件的 Skill 元数据
55
- * 调用后,插件的工具会自动聚合为一个 Skill 注册到 SkillFeature
56
- */
57
- declareSkill(metadata: SkillMetadata): void;
58
- }
59
50
  declare module '../plugin.js' {
60
51
  namespace Plugin {
61
- interface Extensions extends SkillContextExtensions {
62
- }
63
52
  interface Contexts {
64
53
  skill: SkillFeature;
65
54
  }
@@ -107,11 +96,5 @@ export declare class SkillFeature extends Feature<Skill> {
107
96
  * 序列化为 JSON
108
97
  */
109
98
  toJSON(pluginName?: string): FeatureJSON;
110
- /**
111
- * 提供给 Plugin.prototype 的扩展方法
112
- */
113
- get extensions(): {
114
- declareSkill(metadata: SkillMetadata): void;
115
- };
116
99
  }
117
100
  //# sourceMappingURL=skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/built/skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAMxC;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IAEb,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,KAAK,EAAE,IAAI,EAAE,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,eAAe;IACf,WAAW,EAAE,MAAM,CAAC;IAEpB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,eAAe;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAMD,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;CAC7C;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,MAAM,CAAC;QACf,UAAU,UAAW,SAAQ,sBAAsB;SAAG;QACtD,UAAU,QAAQ;YAChB,KAAK,EAAE,YAAY,CAAC;SACrB;KACF;CACF;AAMD,qBAAa,YAAa,SAAQ,OAAO,CAAC,KAAK,CAAC;;IAC9C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,IAAI,kBAAQ;IAErB,YAAY;IACZ,QAAQ,CAAC,MAAM,qBAA4B;IAE3C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,IAAI;IAKjD;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAK7B;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIpC;;OAEG;IACH,MAAM,IAAI,KAAK,EAAE;IAIjB;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,EAAE;IAWjE;;OAEG;IACH,eAAe,IAAI,IAAI,EAAE;IAQzB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IA0CD;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW;IAiBxC;;OAEG;IACH,IAAI,UAAU;+BAGa,aAAa;MAgDvC;CACF"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/built/skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAMxC;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IAEb,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,KAAK,EAAE,IAAI,EAAE,CAAC;IAEd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,eAAe;IACf,WAAW,EAAE,MAAM,CAAC;IAEpB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,eAAe;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,MAAM,CAAC;QACf,UAAU,QAAQ;YAChB,KAAK,EAAE,YAAY,CAAC;SACrB;KACF;CACF;AAMD,qBAAa,YAAa,SAAQ,OAAO,CAAC,KAAK,CAAC;;IAC9C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,IAAI,kBAAQ;IAErB,YAAY;IACZ,QAAQ,CAAC,MAAM,qBAA4B;IAE3C;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,IAAI;IAKjD;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAK7B;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIpC;;OAEG;IACH,MAAM,IAAI,KAAK,EAAE;IAIjB;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,EAAE;IAWjE;;OAEG;IACH,eAAe,IAAI,IAAI,EAAE;IAQzB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IA0CD;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW;CAgBzC"}
@@ -5,15 +5,13 @@
5
5
  * Plugin = 运行时容器(生命周期、服务注册、中间件)
6
6
  * Skill = AI 可见的能力接口(名称、描述、工具列表)
7
7
  *
8
- * 每个 Plugin 可以声明一个 Skill 描述,告诉 AI Agent
9
- * "我叫什么、我能做什么、我有哪些工具"
8
+ * Skill 记录由运行时注入(如 Agent 从磁盘 SKILL.md 同步),供 Agent 粗筛与工具关联。
10
9
  *
11
10
  * SkillFeature 全局收集所有 Skill,供 Agent 进行两级过滤:
12
11
  * 1. 粗筛:根据用户消息选择相关 Skill
13
12
  * 2. 细筛:从选中 Skill 内选择具体 Tool
14
13
  */
15
14
  import { Feature } from '../feature.js';
16
- import { getPlugin } from '../plugin.js';
17
15
  // ============================================================================
18
16
  // SkillFeature 实现
19
17
  // ============================================================================
@@ -136,55 +134,5 @@ export class SkillFeature extends Feature {
136
134
  })),
137
135
  };
138
136
  }
139
- /**
140
- * 提供给 Plugin.prototype 的扩展方法
141
- */
142
- get extensions() {
143
- const feature = this;
144
- return {
145
- declareSkill(metadata) {
146
- const plugin = getPlugin();
147
- const pluginName = plugin.name;
148
- // 收集该插件注册的工具
149
- const toolService = plugin.root.inject('tool');
150
- let tools = [];
151
- if (toolService && typeof toolService.getToolsByPlugin === 'function') {
152
- tools = toolService.getToolsByPlugin(pluginName);
153
- }
154
- else {
155
- tools = plugin.getAllTools?.() || [];
156
- }
157
- // 聚合关键词:开发者声明 + 工具自带
158
- const allKeywords = new Set(metadata.keywords || []);
159
- for (const tool of tools) {
160
- if (tool.keywords) {
161
- for (const kw of tool.keywords) {
162
- allKeywords.add(kw);
163
- }
164
- }
165
- }
166
- // 聚合标签
167
- const allTags = new Set(metadata.tags || []);
168
- for (const tool of tools) {
169
- if (tool.tags) {
170
- for (const tag of tool.tags) {
171
- allTags.add(tag);
172
- }
173
- }
174
- }
175
- const skill = {
176
- name: pluginName,
177
- description: metadata.description,
178
- tools,
179
- keywords: Array.from(allKeywords),
180
- tags: Array.from(allTags),
181
- pluginName,
182
- };
183
- const dispose = feature.add(skill, pluginName);
184
- plugin.recordFeatureContribution(feature.name, pluginName);
185
- plugin.onDispose(dispose);
186
- },
187
- };
188
- }
189
137
  }
190
138
  //# sourceMappingURL=skill.js.map