@zhin.js/core 1.0.24 → 1.0.26
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/CHANGELOG.md +22 -0
- package/README.md +84 -342
- package/lib/adapter.d.ts +45 -1
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +182 -1
- package/lib/adapter.js.map +1 -1
- package/lib/ai/agent.d.ts +126 -0
- package/lib/ai/agent.d.ts.map +1 -0
- package/lib/ai/agent.js +645 -0
- package/lib/ai/agent.js.map +1 -0
- package/lib/ai/context-manager.d.ts +213 -0
- package/lib/ai/context-manager.d.ts.map +1 -0
- package/lib/ai/context-manager.js +313 -0
- package/lib/ai/context-manager.js.map +1 -0
- package/lib/ai/conversation-memory.d.ts +181 -0
- package/lib/ai/conversation-memory.d.ts.map +1 -0
- package/lib/ai/conversation-memory.js +581 -0
- package/lib/ai/conversation-memory.js.map +1 -0
- package/lib/ai/follow-up.d.ts +131 -0
- package/lib/ai/follow-up.d.ts.map +1 -0
- package/lib/ai/follow-up.js +265 -0
- package/lib/ai/follow-up.js.map +1 -0
- package/lib/ai/index.d.ts +29 -0
- package/lib/ai/index.d.ts.map +1 -0
- package/lib/ai/index.js +34 -0
- package/lib/ai/index.js.map +1 -0
- package/lib/ai/init.d.ts +30 -0
- package/lib/ai/init.d.ts.map +1 -0
- package/lib/ai/init.js +424 -0
- package/lib/ai/init.js.map +1 -0
- package/lib/ai/output.d.ts +93 -0
- package/lib/ai/output.d.ts.map +1 -0
- package/lib/ai/output.js +176 -0
- package/lib/ai/output.js.map +1 -0
- package/lib/ai/providers/anthropic.d.ts +23 -0
- package/lib/ai/providers/anthropic.d.ts.map +1 -0
- package/lib/ai/providers/anthropic.js +322 -0
- package/lib/ai/providers/anthropic.js.map +1 -0
- package/lib/ai/providers/base.d.ts +43 -0
- package/lib/ai/providers/base.d.ts.map +1 -0
- package/lib/ai/providers/base.js +135 -0
- package/lib/ai/providers/base.js.map +1 -0
- package/lib/ai/providers/index.d.ts +12 -0
- package/lib/ai/providers/index.d.ts.map +1 -0
- package/lib/ai/providers/index.js +9 -0
- package/lib/ai/providers/index.js.map +1 -0
- package/lib/ai/providers/ollama.d.ts +25 -0
- package/lib/ai/providers/ollama.d.ts.map +1 -0
- package/lib/ai/providers/ollama.js +243 -0
- package/lib/ai/providers/ollama.js.map +1 -0
- package/lib/ai/providers/openai.d.ts +46 -0
- package/lib/ai/providers/openai.d.ts.map +1 -0
- package/lib/ai/providers/openai.js +132 -0
- package/lib/ai/providers/openai.js.map +1 -0
- package/lib/ai/rate-limiter.d.ts +38 -0
- package/lib/ai/rate-limiter.d.ts.map +1 -0
- package/lib/ai/rate-limiter.js +86 -0
- package/lib/ai/rate-limiter.js.map +1 -0
- package/lib/ai/service.d.ts +81 -0
- package/lib/ai/service.d.ts.map +1 -0
- package/lib/ai/service.js +274 -0
- package/lib/ai/service.js.map +1 -0
- package/lib/ai/session.d.ts +186 -0
- package/lib/ai/session.d.ts.map +1 -0
- package/lib/ai/session.js +443 -0
- package/lib/ai/session.js.map +1 -0
- package/lib/ai/tone-detector.d.ts +19 -0
- package/lib/ai/tone-detector.d.ts.map +1 -0
- package/lib/ai/tone-detector.js +72 -0
- package/lib/ai/tone-detector.js.map +1 -0
- package/lib/ai/tools.d.ts +45 -0
- package/lib/ai/tools.d.ts.map +1 -0
- package/lib/ai/tools.js +206 -0
- package/lib/ai/tools.js.map +1 -0
- package/lib/ai/types.d.ts +264 -0
- package/lib/ai/types.d.ts.map +1 -0
- package/lib/ai/types.js +6 -0
- package/lib/ai/types.js.map +1 -0
- package/lib/ai/user-profile.d.ts +56 -0
- package/lib/ai/user-profile.d.ts.map +1 -0
- package/lib/ai/user-profile.js +130 -0
- package/lib/ai/user-profile.js.map +1 -0
- package/lib/ai/zhin-agent.d.ts +165 -0
- package/lib/ai/zhin-agent.d.ts.map +1 -0
- package/lib/ai/zhin-agent.js +707 -0
- package/lib/ai/zhin-agent.js.map +1 -0
- package/lib/built/adapter-process.d.ts +4 -0
- package/lib/built/adapter-process.d.ts.map +1 -1
- package/lib/built/adapter-process.js +94 -0
- package/lib/built/adapter-process.js.map +1 -1
- package/lib/built/ai-trigger.d.ts +89 -0
- package/lib/built/ai-trigger.d.ts.map +1 -0
- package/lib/built/ai-trigger.js +166 -0
- package/lib/built/ai-trigger.js.map +1 -0
- package/lib/built/command.d.ts +33 -17
- package/lib/built/command.d.ts.map +1 -1
- package/lib/built/command.js +71 -44
- package/lib/built/command.js.map +1 -1
- package/lib/built/component.d.ts +42 -15
- package/lib/built/component.d.ts.map +1 -1
- package/lib/built/component.js +84 -52
- package/lib/built/component.js.map +1 -1
- package/lib/built/config.d.ts +54 -5
- package/lib/built/config.d.ts.map +1 -1
- package/lib/built/config.js +76 -10
- package/lib/built/config.js.map +1 -1
- package/lib/built/cron.d.ts +41 -18
- package/lib/built/cron.d.ts.map +1 -1
- package/lib/built/cron.js +106 -63
- package/lib/built/cron.js.map +1 -1
- package/lib/built/database.d.ts +55 -6
- package/lib/built/database.d.ts.map +1 -1
- package/lib/built/database.js +93 -22
- package/lib/built/database.js.map +1 -1
- package/lib/built/dispatcher.d.ts +118 -0
- package/lib/built/dispatcher.d.ts.map +1 -0
- package/lib/built/dispatcher.js +196 -0
- package/lib/built/dispatcher.js.map +1 -0
- package/lib/built/permission.d.ts +45 -5
- package/lib/built/permission.d.ts.map +1 -1
- package/lib/built/permission.js +56 -11
- package/lib/built/permission.js.map +1 -1
- package/lib/built/skill.d.ts +117 -0
- package/lib/built/skill.d.ts.map +1 -0
- package/lib/built/skill.js +191 -0
- package/lib/built/skill.js.map +1 -0
- package/lib/built/tool.d.ts +188 -0
- package/lib/built/tool.d.ts.map +1 -0
- package/lib/built/tool.js +749 -0
- package/lib/built/tool.js.map +1 -0
- package/lib/feature.d.ts +75 -0
- package/lib/feature.d.ts.map +1 -0
- package/lib/feature.js +69 -0
- package/lib/feature.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +11 -0
- package/lib/index.js.map +1 -1
- package/lib/plugin.d.ts +53 -18
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +301 -31
- package/lib/plugin.js.map +1 -1
- package/lib/types.d.ts +248 -9
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +38 -12
- package/lib/utils.js.map +1 -1
- package/package.json +4 -4
- package/src/adapter.ts +206 -2
- package/src/ai/agent.ts +772 -0
- package/src/ai/context-manager.ts +440 -0
- package/src/ai/conversation-memory.ts +774 -0
- package/src/ai/follow-up.ts +357 -0
- package/src/ai/index.ts +128 -0
- package/src/ai/init.ts +502 -0
- package/src/ai/output.ts +261 -0
- package/src/ai/providers/anthropic.ts +375 -0
- package/src/ai/providers/base.ts +173 -0
- package/src/ai/providers/index.ts +13 -0
- package/src/ai/providers/ollama.ts +292 -0
- package/src/ai/providers/openai.ts +167 -0
- package/src/ai/rate-limiter.ts +129 -0
- package/src/ai/service.ts +319 -0
- package/src/ai/session.ts +544 -0
- package/src/ai/tone-detector.ts +89 -0
- package/src/ai/tools.ts +218 -0
- package/src/ai/types.ts +296 -0
- package/src/ai/user-profile.ts +181 -0
- package/src/ai/zhin-agent.ts +845 -0
- package/src/built/adapter-process.ts +99 -0
- package/src/built/ai-trigger.ts +259 -0
- package/src/built/command.ts +75 -69
- package/src/built/component.ts +94 -76
- package/src/built/config.ts +238 -128
- package/src/built/cron.ts +117 -101
- package/src/built/database.ts +128 -33
- package/src/built/dispatcher.ts +332 -0
- package/src/built/permission.ts +146 -54
- package/src/built/skill.ts +280 -0
- package/src/built/tool.ts +928 -0
- package/src/feature.ts +113 -0
- package/src/index.ts +11 -0
- package/src/plugin.ts +359 -69
- package/src/types.ts +306 -11
- package/src/utils.ts +37 -13
- package/tests/adapter.test.ts +153 -1
- package/tests/ai/agent.test.ts +614 -0
- package/tests/ai/ai-trigger.test.ts +368 -0
- package/tests/ai/context-manager.test.ts +413 -0
- package/tests/ai/conversation-memory.test.ts +128 -0
- package/tests/ai/follow-up.test.ts +175 -0
- package/tests/ai/integration.test.ts +584 -0
- package/tests/ai/output.test.ts +128 -0
- package/tests/ai/providers.integration.test.ts +227 -0
- package/tests/ai/rate-limiter.test.ts +108 -0
- package/tests/ai/session.test.ts +375 -0
- package/tests/ai/setup.ts +308 -0
- package/tests/ai/tone-detector.test.ts +80 -0
- package/tests/ai/tool.test.ts +800 -0
- package/tests/ai/tools-builtin.test.ts +346 -0
- package/tests/ai/user-profile.test.ts +73 -0
- package/tests/ai/zhin-agent.test.ts +177 -0
- package/tests/component-new.test.ts +17 -6
- package/tests/config.test.ts +46 -0
- package/tests/cron.test.ts +94 -5
- package/tests/dispatcher.test.ts +146 -0
- package/tests/feature.test.ts +145 -0
- package/tests/features-builtin.test.ts +191 -0
- package/tests/plugin.test.ts +88 -14
- package/tests/skill-feature.test.ts +179 -0
- package/tests/tool-feature.test.ts +254 -0
package/src/adapter.ts
CHANGED
|
@@ -2,15 +2,23 @@ import { Bot } from "./bot.js";
|
|
|
2
2
|
import { Plugin } from "./plugin.js";
|
|
3
3
|
import { EventEmitter } from "events";
|
|
4
4
|
import { Message } from "./message.js";
|
|
5
|
-
import { BeforeSendHandler, SendOptions } from "./types.js";
|
|
5
|
+
import { BeforeSendHandler, SendOptions, Tool, ToolContext } from "./types.js";
|
|
6
6
|
import { segment } from "./utils.js";
|
|
7
|
+
import { ZhinTool, isZhinTool, type ToolInput } from "./built/tool.js";
|
|
8
|
+
import type { Skill, SkillFeature } from "./built/skill.js";
|
|
7
9
|
/**
|
|
8
10
|
* Adapter类:适配器抽象,管理多平台Bot实例。
|
|
9
11
|
* 负责根据配置启动/关闭各平台机器人,统一异常处理。
|
|
12
|
+
*
|
|
13
|
+
* 适配器可以提供 AI 工具,供 AI 服务调用。
|
|
10
14
|
*/
|
|
11
15
|
export abstract class Adapter<R extends Bot = Bot> extends EventEmitter<Adapter.Lifecycle> {
|
|
12
16
|
/** 当前适配器下所有Bot实例,key为bot名称 */
|
|
13
17
|
public bots: Map<string, R> = new Map<string, R>();
|
|
18
|
+
/** 适配器提供的工具 */
|
|
19
|
+
public tools: Map<string, Tool> = new Map<string, Tool>();
|
|
20
|
+
/** Skill 注销函数(declareSkill 时设置) */
|
|
21
|
+
private _skillDispose?: () => void;
|
|
14
22
|
/**
|
|
15
23
|
* 构造函数
|
|
16
24
|
* @param name 适配器名称(如 'process'、'qq' 等)
|
|
@@ -30,7 +38,19 @@ export abstract class Adapter<R extends Bot = Bot> extends EventEmitter<Adapter.
|
|
|
30
38
|
})
|
|
31
39
|
this.on('message.receive', (message) => {
|
|
32
40
|
this.logger.info(`${message.$bot} recv ${message.$channel.type}(${message.$channel.id}):${segment.raw(message.$content)}`);
|
|
33
|
-
this.plugin?.
|
|
41
|
+
const rootPlugin = this.plugin?.root || this.plugin;
|
|
42
|
+
// 优先使用 MessageDispatcher(新架构),回退到旧中间件链(兼容)
|
|
43
|
+
const dispatcher = rootPlugin?.inject('dispatcher' as any) as any;
|
|
44
|
+
if (dispatcher && typeof dispatcher.dispatch === 'function') {
|
|
45
|
+
void dispatcher.dispatch(message).catch((err: unknown) => {
|
|
46
|
+
this.logger.error('dispatcher.dispatch(message) failed', err);
|
|
47
|
+
});
|
|
48
|
+
} else {
|
|
49
|
+
// 旧中间件链回退
|
|
50
|
+
void Promise.resolve(rootPlugin?.middleware(message, async () => {})).catch((err: unknown) => {
|
|
51
|
+
this.logger.error('rootPlugin.middleware(message, next) failed', err);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
34
54
|
});
|
|
35
55
|
}
|
|
36
56
|
abstract createBot(config: Adapter.BotConfig<R>): R;
|
|
@@ -85,6 +105,10 @@ export abstract class Adapter<R extends Bot = Bot> extends EventEmitter<Adapter.
|
|
|
85
105
|
}
|
|
86
106
|
// 清理 bots Map
|
|
87
107
|
this.bots.clear();
|
|
108
|
+
|
|
109
|
+
// 清理 Skill
|
|
110
|
+
this._skillDispose?.();
|
|
111
|
+
this._skillDispose = undefined;
|
|
88
112
|
|
|
89
113
|
// 从 adapters 数组中移除
|
|
90
114
|
const idx = this.plugin.root.adapters.indexOf(this.name);
|
|
@@ -101,6 +125,186 @@ export abstract class Adapter<R extends Bot = Bot> extends EventEmitter<Adapter.
|
|
|
101
125
|
throw error;
|
|
102
126
|
}
|
|
103
127
|
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 注册工具
|
|
131
|
+
* @param input 工具定义(支持 Tool 对象或 ZhinTool 实例)
|
|
132
|
+
* @returns 返回一个移除工具的函数
|
|
133
|
+
*/
|
|
134
|
+
addTool(input: ToolInput): () => void {
|
|
135
|
+
// 如果是 ZhinTool 实例,转换为 Tool 对象
|
|
136
|
+
const tool: Tool = isZhinTool(input) ? input.toTool() : input;
|
|
137
|
+
|
|
138
|
+
// 自动添加适配器源标识
|
|
139
|
+
const toolWithSource: Tool = {
|
|
140
|
+
...tool,
|
|
141
|
+
source: tool.source || `adapter:${this.name}`,
|
|
142
|
+
tags: [...(tool.tags || []), 'adapter', this.name],
|
|
143
|
+
};
|
|
144
|
+
this.tools.set(tool.name, toolWithSource);
|
|
145
|
+
|
|
146
|
+
// 同步到全局 ToolFeature(如果可用),使适配器工具出现在插件 features 统计中
|
|
147
|
+
let globalDispose: (() => void) | undefined;
|
|
148
|
+
const toolFeature = this.plugin?.root?.inject('tool' as any) as any;
|
|
149
|
+
if (toolFeature && typeof toolFeature.addTool === 'function') {
|
|
150
|
+
const adapterPluginName = this.plugin?.name || `adapter:${this.name}`;
|
|
151
|
+
globalDispose = toolFeature.addTool(toolWithSource, adapterPluginName, false);
|
|
152
|
+
// 记录到宿主插件的 feature 贡献
|
|
153
|
+
this.plugin?.recordFeatureContribution('tool', tool.name);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return () => {
|
|
157
|
+
this.tools.delete(tool.name);
|
|
158
|
+
globalDispose?.();
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 获取所有注册的工具
|
|
164
|
+
* @returns 工具数组
|
|
165
|
+
*/
|
|
166
|
+
getTools(): Tool[] {
|
|
167
|
+
return Array.from(this.tools.values());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 根据名称获取工具
|
|
172
|
+
* @param name 工具名称
|
|
173
|
+
* @returns 工具定义或 undefined
|
|
174
|
+
*/
|
|
175
|
+
getTool(name: string): Tool | undefined {
|
|
176
|
+
return this.tools.get(name);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 声明适配器的 Skill(将 this.tools 聚合为一个 Skill 注册到 SkillFeature)
|
|
181
|
+
*
|
|
182
|
+
* @param metadata Skill 元数据
|
|
183
|
+
* - description: 平台级能力描述
|
|
184
|
+
* - keywords: 额外的触发关键词(可选,会自动从工具中聚合)
|
|
185
|
+
* - tags: 额外的分类标签(可选,会自动从工具中聚合)
|
|
186
|
+
* - conventions: 平台调用约定(可选,拼接到 description 末尾)
|
|
187
|
+
*/
|
|
188
|
+
declareSkill(metadata: {
|
|
189
|
+
description: string;
|
|
190
|
+
keywords?: string[];
|
|
191
|
+
tags?: string[];
|
|
192
|
+
conventions?: string;
|
|
193
|
+
}): void {
|
|
194
|
+
const skillFeature = this.plugin?.root?.inject('skill' as any) as SkillFeature | undefined;
|
|
195
|
+
if (!skillFeature) {
|
|
196
|
+
this.logger.debug(`declareSkill: SkillFeature 不可用,跳过 Skill 注册`);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 收集适配器所有工具
|
|
201
|
+
const tools = this.getTools();
|
|
202
|
+
|
|
203
|
+
// 聚合关键词:metadata 声明 + 工具自带
|
|
204
|
+
const allKeywords = new Set<string>(metadata.keywords || []);
|
|
205
|
+
for (const tool of tools) {
|
|
206
|
+
if (tool.keywords) {
|
|
207
|
+
for (const kw of tool.keywords) {
|
|
208
|
+
allKeywords.add(kw);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 聚合标签:metadata 声明 + 工具自带
|
|
214
|
+
const allTags = new Set<string>(metadata.tags || []);
|
|
215
|
+
for (const tool of tools) {
|
|
216
|
+
if (tool.tags) {
|
|
217
|
+
for (const tag of tool.tags) {
|
|
218
|
+
allTags.add(tag);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// 拼接描述:基础描述 + 调用约定
|
|
224
|
+
let description = metadata.description;
|
|
225
|
+
if (metadata.conventions) {
|
|
226
|
+
description += `\n\n调用约定:${metadata.conventions}`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const pluginName = this.plugin?.name || `adapter:${this.name}`;
|
|
230
|
+
const skill: Skill = {
|
|
231
|
+
name: `adapter:${this.name}`,
|
|
232
|
+
description,
|
|
233
|
+
tools,
|
|
234
|
+
keywords: Array.from(allKeywords),
|
|
235
|
+
tags: Array.from(allTags),
|
|
236
|
+
pluginName,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// 清理旧的 Skill(如果有)
|
|
240
|
+
this._skillDispose?.();
|
|
241
|
+
|
|
242
|
+
// 注册到 SkillFeature
|
|
243
|
+
this._skillDispose = skillFeature.add(skill, pluginName);
|
|
244
|
+
this.plugin?.recordFeatureContribution('skill', `adapter:${this.name}`);
|
|
245
|
+
|
|
246
|
+
this.logger.debug(`declareSkill: 已注册 Skill "${skill.name}",包含 ${tools.length} 个工具`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* 提供默认的适配器工具(子类可覆盖)
|
|
251
|
+
* 包含发送消息、撤回消息等基础能力
|
|
252
|
+
*/
|
|
253
|
+
protected registerDefaultTools(): void {
|
|
254
|
+
// 发送消息工具
|
|
255
|
+
this.addTool({
|
|
256
|
+
name: `${this.name}_send_message`,
|
|
257
|
+
description: `使用 ${this.name} 适配器发送消息到指定目标`,
|
|
258
|
+
parameters: {
|
|
259
|
+
type: 'object',
|
|
260
|
+
properties: {
|
|
261
|
+
bot: {
|
|
262
|
+
type: 'string',
|
|
263
|
+
description: 'Bot 名称/ID',
|
|
264
|
+
},
|
|
265
|
+
id: {
|
|
266
|
+
type: 'string',
|
|
267
|
+
description: '目标 ID(用户/群/频道)',
|
|
268
|
+
},
|
|
269
|
+
type: {
|
|
270
|
+
type: 'string',
|
|
271
|
+
description: '消息类型',
|
|
272
|
+
},
|
|
273
|
+
content: {
|
|
274
|
+
type: 'string',
|
|
275
|
+
description: '消息内容',
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
required: ['bot', 'id', 'type', 'content'],
|
|
279
|
+
},
|
|
280
|
+
execute: async (args) => {
|
|
281
|
+
const { bot, id, type, content } = args;
|
|
282
|
+
return await this.sendMessage({
|
|
283
|
+
context: this.name,
|
|
284
|
+
bot,
|
|
285
|
+
id,
|
|
286
|
+
type: type as 'private' | 'group' | 'channel',
|
|
287
|
+
content,
|
|
288
|
+
});
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// 获取 Bot 列表工具
|
|
293
|
+
this.addTool({
|
|
294
|
+
name: `${this.name}_list_bots`,
|
|
295
|
+
description: `获取 ${this.name} 适配器下所有已连接的 Bot 列表`,
|
|
296
|
+
parameters: {
|
|
297
|
+
type: 'object',
|
|
298
|
+
properties: {},
|
|
299
|
+
},
|
|
300
|
+
execute: async () => {
|
|
301
|
+
return Array.from(this.bots.entries()).map(([id, bot]) => ({
|
|
302
|
+
id,
|
|
303
|
+
connected: bot.$connected,
|
|
304
|
+
}));
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
}
|
|
104
308
|
}
|
|
105
309
|
export interface Adapters {}
|
|
106
310
|
export namespace Adapter {
|