@zhin.js/core 1.0.44 → 1.0.46
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 +25 -0
- package/lib/adapter.d.ts +3 -13
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +3 -63
- package/lib/adapter.js.map +1 -1
- package/lib/ai/providers/base.d.ts.map +1 -1
- package/lib/ai/providers/base.js +4 -2
- package/lib/ai/providers/base.js.map +1 -1
- package/lib/ai/types.d.ts +4 -0
- package/lib/ai/types.d.ts.map +1 -1
- package/lib/built/common-adapter-tools.d.ts +10 -14
- package/lib/built/common-adapter-tools.d.ts.map +1 -1
- package/lib/built/common-adapter-tools.js +47 -21
- package/lib/built/common-adapter-tools.js.map +1 -1
- package/lib/built/message-filter.d.ts +175 -0
- package/lib/built/message-filter.d.ts.map +1 -0
- package/lib/built/message-filter.js +236 -0
- package/lib/built/message-filter.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/package.json +6 -6
- package/src/adapter.ts +3 -81
- package/src/ai/providers/base.ts +4 -2
- package/src/ai/types.ts +4 -0
- package/src/built/common-adapter-tools.ts +54 -25
- package/src/built/message-filter.ts +390 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageFilterFeature — 消息过滤引擎
|
|
3
|
+
*
|
|
4
|
+
* 设计理念:
|
|
5
|
+
* 将过滤规则视为 Feature Item,与命令 (CommandFeature)、权限 (PermissionFeature) 同构,
|
|
6
|
+
* 遵循框架的 add/remove/extensions/toJSON 范式,支持插件级 CRUD 和生命周期自动回收。
|
|
7
|
+
*
|
|
8
|
+
* 核心特性:
|
|
9
|
+
* - 基于优先级的规则引擎(first-match-wins,类似防火墙规则)
|
|
10
|
+
* - 多维匹配:scope / adapter / bot / channel / sender
|
|
11
|
+
* - 支持精确匹配、通配符 `*`、正则 `/pattern/`
|
|
12
|
+
* - 通过 Dispatcher Guardrail 集成,在消息调度第一阶段拦截
|
|
13
|
+
* - 插件通过 `addFilterRule()` 动态注册规则,卸载时自动清理
|
|
14
|
+
*/
|
|
15
|
+
import { Feature, FeatureJSON } from '../feature.js';
|
|
16
|
+
import type { Message, MessageType } from '../message.js';
|
|
17
|
+
/** 过滤动作 */
|
|
18
|
+
export type FilterAction = 'allow' | 'deny';
|
|
19
|
+
/** 匹配模式:精确字符串 / 正则表达式 */
|
|
20
|
+
export type FilterPattern = string | RegExp;
|
|
21
|
+
/** 消息作用域 */
|
|
22
|
+
export type FilterScope = MessageType;
|
|
23
|
+
/**
|
|
24
|
+
* 过滤规则
|
|
25
|
+
*
|
|
26
|
+
* 每条规则描述一组匹配条件和对应的动作。
|
|
27
|
+
* 所有条件之间为 AND 关系(必须全部满足),每个条件内部的多个值为 OR 关系(满足任一即可)。
|
|
28
|
+
* 未设置的条件视为匹配所有。
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // 拒绝特定群的消息
|
|
32
|
+
* { name: 'block-spam', action: 'deny', scopes: ['group'], channels: ['123456'] }
|
|
33
|
+
*
|
|
34
|
+
* // 放行 VIP 用户(高优先级)
|
|
35
|
+
* { name: 'allow-vip', action: 'allow', priority: 100, senders: ['admin001'] }
|
|
36
|
+
*
|
|
37
|
+
* // 正则匹配:拒绝所有 test- 开头的频道
|
|
38
|
+
* { name: 'block-test', action: 'deny', scopes: ['channel'], channels: [/^test-/] }
|
|
39
|
+
*/
|
|
40
|
+
export interface FilterRule {
|
|
41
|
+
/** 规则名称(唯一标识) */
|
|
42
|
+
name: string;
|
|
43
|
+
/** 规则描述 */
|
|
44
|
+
description?: string;
|
|
45
|
+
/** 过滤动作:allow 放行 / deny 拦截 */
|
|
46
|
+
action: FilterAction;
|
|
47
|
+
/** 优先级,数值越大越先匹配(默认 0) */
|
|
48
|
+
priority?: number;
|
|
49
|
+
/** 是否启用(默认 true) */
|
|
50
|
+
enabled?: boolean;
|
|
51
|
+
/** 匹配的消息作用域,未设置则匹配所有 */
|
|
52
|
+
scopes?: FilterScope[];
|
|
53
|
+
/** 匹配的适配器名称 */
|
|
54
|
+
adapters?: FilterPattern[];
|
|
55
|
+
/** 匹配的 Bot 名称 */
|
|
56
|
+
bots?: FilterPattern[];
|
|
57
|
+
/** 匹配的频道/群/会话 ID */
|
|
58
|
+
channels?: FilterPattern[];
|
|
59
|
+
/** 匹配的发送者 ID */
|
|
60
|
+
senders?: FilterPattern[];
|
|
61
|
+
}
|
|
62
|
+
/** 过滤检测结果 */
|
|
63
|
+
export interface FilterResult {
|
|
64
|
+
/** 是否允许处理 */
|
|
65
|
+
allowed: boolean;
|
|
66
|
+
/** 匹配到的规则名称(null 表示无规则匹配,走默认策略) */
|
|
67
|
+
matchedRule: string | null;
|
|
68
|
+
/** 结果原因 */
|
|
69
|
+
reason: string;
|
|
70
|
+
}
|
|
71
|
+
/** 配置文件中的规则(pattern 均为 string,正则用 /pattern/ 表示) */
|
|
72
|
+
export interface FilterRuleConfig {
|
|
73
|
+
name: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
action: FilterAction;
|
|
76
|
+
priority?: number;
|
|
77
|
+
enabled?: boolean;
|
|
78
|
+
scopes?: FilterScope[];
|
|
79
|
+
adapters?: string[];
|
|
80
|
+
bots?: string[];
|
|
81
|
+
channels?: string[];
|
|
82
|
+
senders?: string[];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 消息过滤配置
|
|
86
|
+
*
|
|
87
|
+
* ```yaml
|
|
88
|
+
* message_filter:
|
|
89
|
+
* default_policy: allow
|
|
90
|
+
* rules:
|
|
91
|
+
* - name: block-spam
|
|
92
|
+
* action: deny
|
|
93
|
+
* scopes: [group]
|
|
94
|
+
* channels: ['123456']
|
|
95
|
+
* - name: vip-pass
|
|
96
|
+
* action: allow
|
|
97
|
+
* priority: 100
|
|
98
|
+
* senders: ['admin001']
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export interface MessageFilterConfig {
|
|
102
|
+
/** 默认策略:无规则匹配时的行为(默认 'allow') */
|
|
103
|
+
default_policy?: FilterAction;
|
|
104
|
+
/** 规则列表 */
|
|
105
|
+
rules?: FilterRuleConfig[];
|
|
106
|
+
}
|
|
107
|
+
export interface MessageFilterContextExtensions {
|
|
108
|
+
/** 添加过滤规则,返回 dispose 函数 */
|
|
109
|
+
addFilterRule(rule: FilterRule): () => void;
|
|
110
|
+
/** 检测消息是否应被处理 */
|
|
111
|
+
testFilter(message: Message<any>): FilterResult;
|
|
112
|
+
/** 设置默认过滤策略 */
|
|
113
|
+
setDefaultFilterPolicy(policy: FilterAction): void;
|
|
114
|
+
}
|
|
115
|
+
declare module '../plugin.js' {
|
|
116
|
+
namespace Plugin {
|
|
117
|
+
interface Extensions extends MessageFilterContextExtensions {
|
|
118
|
+
}
|
|
119
|
+
interface Contexts {
|
|
120
|
+
'message-filter': MessageFilterFeature;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export declare namespace FilterRules {
|
|
125
|
+
/** 创建拒绝规则 */
|
|
126
|
+
function deny(name: string, conditions: Omit<FilterRule, 'name' | 'action'>): FilterRule;
|
|
127
|
+
/** 创建放行规则 */
|
|
128
|
+
function allow(name: string, conditions: Omit<FilterRule, 'name' | 'action'>): FilterRule;
|
|
129
|
+
/**
|
|
130
|
+
* 创建黑名单规则组
|
|
131
|
+
* @returns 一条 deny 规则
|
|
132
|
+
*/
|
|
133
|
+
function blacklist(scope: FilterScope, ids: string[], name?: string): FilterRule;
|
|
134
|
+
/**
|
|
135
|
+
* 创建白名单规则组
|
|
136
|
+
* @returns [allow 规则, deny-catch-all 规则]
|
|
137
|
+
*/
|
|
138
|
+
function whitelist(scope: FilterScope, ids: string[], name?: string): [FilterRule, FilterRule];
|
|
139
|
+
}
|
|
140
|
+
export declare class MessageFilterFeature extends Feature<FilterRule> {
|
|
141
|
+
#private;
|
|
142
|
+
readonly name: "message-filter";
|
|
143
|
+
readonly icon = "Filter";
|
|
144
|
+
readonly desc = "\u6D88\u606F\u8FC7\u6EE4";
|
|
145
|
+
/** 按规则名称索引 */
|
|
146
|
+
readonly byName: Map<string, FilterRule>;
|
|
147
|
+
constructor(config?: MessageFilterConfig);
|
|
148
|
+
/** 默认策略 */
|
|
149
|
+
get defaultPolicy(): FilterAction;
|
|
150
|
+
set defaultPolicy(policy: FilterAction);
|
|
151
|
+
/** 获取按优先级排序的启用规则列表(带缓存) */
|
|
152
|
+
get sortedRules(): FilterRule[];
|
|
153
|
+
/** 按名称查询规则 */
|
|
154
|
+
getRule(name: string): FilterRule | undefined;
|
|
155
|
+
/**
|
|
156
|
+
* 检测消息是否应该被处理
|
|
157
|
+
*
|
|
158
|
+
* 遍历按优先级排序的规则列表,返回第一个匹配的规则结果。
|
|
159
|
+
* 若无规则匹配,按默认策略决定。
|
|
160
|
+
*/
|
|
161
|
+
test(message: Message<any>): FilterResult;
|
|
162
|
+
/** 添加规则,维护 byName 索引 */
|
|
163
|
+
add(rule: FilterRule, pluginName: string): () => void;
|
|
164
|
+
/** 移除规则,清理 byName 索引 */
|
|
165
|
+
remove(rule: FilterRule, pluginName?: string): boolean;
|
|
166
|
+
/** 序列化为 JSON(供 Web 控制台展示) */
|
|
167
|
+
toJSON(pluginName?: string): FeatureJSON;
|
|
168
|
+
/** 插件扩展方法 */
|
|
169
|
+
get extensions(): {
|
|
170
|
+
addFilterRule(rule: FilterRule): () => void;
|
|
171
|
+
testFilter(message: Message<any>): FilterResult;
|
|
172
|
+
setDefaultFilterPolicy(policy: FilterAction): void;
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=message-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-filter.d.ts","sourceRoot":"","sources":["../../src/built/message-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MessageFilterFeature — 消息过滤引擎
|
|
3
|
+
*
|
|
4
|
+
* 设计理念:
|
|
5
|
+
* 将过滤规则视为 Feature Item,与命令 (CommandFeature)、权限 (PermissionFeature) 同构,
|
|
6
|
+
* 遵循框架的 add/remove/extensions/toJSON 范式,支持插件级 CRUD 和生命周期自动回收。
|
|
7
|
+
*
|
|
8
|
+
* 核心特性:
|
|
9
|
+
* - 基于优先级的规则引擎(first-match-wins,类似防火墙规则)
|
|
10
|
+
* - 多维匹配:scope / adapter / bot / channel / sender
|
|
11
|
+
* - 支持精确匹配、通配符 `*`、正则 `/pattern/`
|
|
12
|
+
* - 通过 Dispatcher Guardrail 集成,在消息调度第一阶段拦截
|
|
13
|
+
* - 插件通过 `addFilterRule()` 动态注册规则,卸载时自动清理
|
|
14
|
+
*/
|
|
15
|
+
import { Feature } from '../feature.js';
|
|
16
|
+
import { getPlugin } from '../plugin.js';
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// 规则工厂
|
|
19
|
+
// ============================================================================
|
|
20
|
+
export var FilterRules;
|
|
21
|
+
(function (FilterRules) {
|
|
22
|
+
/** 创建拒绝规则 */
|
|
23
|
+
function deny(name, conditions) {
|
|
24
|
+
return { ...conditions, name, action: 'deny' };
|
|
25
|
+
}
|
|
26
|
+
FilterRules.deny = deny;
|
|
27
|
+
/** 创建放行规则 */
|
|
28
|
+
function allow(name, conditions) {
|
|
29
|
+
return { ...conditions, name, action: 'allow' };
|
|
30
|
+
}
|
|
31
|
+
FilterRules.allow = allow;
|
|
32
|
+
/**
|
|
33
|
+
* 创建黑名单规则组
|
|
34
|
+
* @returns 一条 deny 规则
|
|
35
|
+
*/
|
|
36
|
+
function blacklist(scope, ids, name) {
|
|
37
|
+
return {
|
|
38
|
+
name: name ?? `${scope}-blacklist`,
|
|
39
|
+
action: 'deny',
|
|
40
|
+
scopes: [scope],
|
|
41
|
+
channels: ids,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
FilterRules.blacklist = blacklist;
|
|
45
|
+
/**
|
|
46
|
+
* 创建白名单规则组
|
|
47
|
+
* @returns [allow 规则, deny-catch-all 规则]
|
|
48
|
+
*/
|
|
49
|
+
function whitelist(scope, ids, name) {
|
|
50
|
+
const baseName = name ?? `${scope}-whitelist`;
|
|
51
|
+
return [
|
|
52
|
+
{ name: baseName, action: 'allow', scopes: [scope], channels: ids, priority: 1 },
|
|
53
|
+
{ name: `${baseName}-deny-rest`, action: 'deny', scopes: [scope], priority: -100 },
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
FilterRules.whitelist = whitelist;
|
|
57
|
+
})(FilterRules || (FilterRules = {}));
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Feature 实现
|
|
60
|
+
// ============================================================================
|
|
61
|
+
export class MessageFilterFeature extends Feature {
|
|
62
|
+
name = 'message-filter';
|
|
63
|
+
icon = 'Filter';
|
|
64
|
+
desc = '消息过滤';
|
|
65
|
+
/** 按规则名称索引 */
|
|
66
|
+
byName = new Map();
|
|
67
|
+
#defaultPolicy = 'allow';
|
|
68
|
+
#sortedCache = null;
|
|
69
|
+
constructor(config) {
|
|
70
|
+
super();
|
|
71
|
+
if (config)
|
|
72
|
+
this.#loadConfig(config);
|
|
73
|
+
}
|
|
74
|
+
// ---- 公共 API ----
|
|
75
|
+
/** 默认策略 */
|
|
76
|
+
get defaultPolicy() { return this.#defaultPolicy; }
|
|
77
|
+
set defaultPolicy(policy) { this.#defaultPolicy = policy; }
|
|
78
|
+
/** 获取按优先级排序的启用规则列表(带缓存) */
|
|
79
|
+
get sortedRules() {
|
|
80
|
+
if (!this.#sortedCache) {
|
|
81
|
+
this.#sortedCache = [...this.items]
|
|
82
|
+
.filter(r => r.enabled !== false)
|
|
83
|
+
.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
84
|
+
}
|
|
85
|
+
return this.#sortedCache;
|
|
86
|
+
}
|
|
87
|
+
/** 按名称查询规则 */
|
|
88
|
+
getRule(name) {
|
|
89
|
+
return this.byName.get(name);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 检测消息是否应该被处理
|
|
93
|
+
*
|
|
94
|
+
* 遍历按优先级排序的规则列表,返回第一个匹配的规则结果。
|
|
95
|
+
* 若无规则匹配,按默认策略决定。
|
|
96
|
+
*/
|
|
97
|
+
test(message) {
|
|
98
|
+
for (const rule of this.sortedRules) {
|
|
99
|
+
if (this.#matchRule(rule, message)) {
|
|
100
|
+
return {
|
|
101
|
+
allowed: rule.action === 'allow',
|
|
102
|
+
matchedRule: rule.name,
|
|
103
|
+
reason: `matched rule "${rule.name}" → ${rule.action}`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
allowed: this.#defaultPolicy === 'allow',
|
|
109
|
+
matchedRule: null,
|
|
110
|
+
reason: `no rule matched → default policy: ${this.#defaultPolicy}`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// ---- Feature 重写 ----
|
|
114
|
+
/** 添加规则,维护 byName 索引 */
|
|
115
|
+
add(rule, pluginName) {
|
|
116
|
+
this.byName.set(rule.name, rule);
|
|
117
|
+
this.#sortedCache = null;
|
|
118
|
+
return super.add(rule, pluginName);
|
|
119
|
+
}
|
|
120
|
+
/** 移除规则,清理 byName 索引 */
|
|
121
|
+
remove(rule, pluginName) {
|
|
122
|
+
this.byName.delete(rule.name);
|
|
123
|
+
this.#sortedCache = null;
|
|
124
|
+
return super.remove(rule, pluginName);
|
|
125
|
+
}
|
|
126
|
+
/** 序列化为 JSON(供 Web 控制台展示) */
|
|
127
|
+
toJSON(pluginName) {
|
|
128
|
+
const list = pluginName ? this.getByPlugin(pluginName) : this.items;
|
|
129
|
+
return {
|
|
130
|
+
name: this.name,
|
|
131
|
+
icon: this.icon,
|
|
132
|
+
desc: this.desc,
|
|
133
|
+
count: list.length,
|
|
134
|
+
items: list.map(r => ({
|
|
135
|
+
name: r.name,
|
|
136
|
+
description: r.description,
|
|
137
|
+
action: r.action,
|
|
138
|
+
priority: r.priority ?? 0,
|
|
139
|
+
enabled: r.enabled !== false,
|
|
140
|
+
scopes: r.scopes,
|
|
141
|
+
adapters: r.adapters?.map(p => p instanceof RegExp ? p.source : p),
|
|
142
|
+
bots: r.bots?.map(p => p instanceof RegExp ? p.source : p),
|
|
143
|
+
channels: r.channels?.map(p => p instanceof RegExp ? p.source : p),
|
|
144
|
+
senders: r.senders?.map(p => p instanceof RegExp ? p.source : p),
|
|
145
|
+
})),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/** 插件扩展方法 */
|
|
149
|
+
get extensions() {
|
|
150
|
+
const feature = this;
|
|
151
|
+
return {
|
|
152
|
+
addFilterRule(rule) {
|
|
153
|
+
const plugin = getPlugin();
|
|
154
|
+
const dispose = feature.add(rule, plugin.name);
|
|
155
|
+
plugin.recordFeatureContribution(feature.name, rule.name);
|
|
156
|
+
plugin.onDispose(dispose);
|
|
157
|
+
return dispose;
|
|
158
|
+
},
|
|
159
|
+
testFilter(message) {
|
|
160
|
+
return feature.test(message);
|
|
161
|
+
},
|
|
162
|
+
setDefaultFilterPolicy(policy) {
|
|
163
|
+
feature.defaultPolicy = policy;
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// 配置加载
|
|
169
|
+
// ============================================================================
|
|
170
|
+
#loadConfig(config) {
|
|
171
|
+
if (config.default_policy) {
|
|
172
|
+
this.#defaultPolicy = config.default_policy;
|
|
173
|
+
}
|
|
174
|
+
if (config.rules) {
|
|
175
|
+
for (const rc of config.rules) {
|
|
176
|
+
this.add(this.#parseRuleConfig(rc), '__config__');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// 规则匹配
|
|
182
|
+
// ============================================================================
|
|
183
|
+
/** 解析配置中的规则字符串为 FilterPattern */
|
|
184
|
+
#parseRuleConfig(rc) {
|
|
185
|
+
return {
|
|
186
|
+
name: rc.name,
|
|
187
|
+
description: rc.description,
|
|
188
|
+
action: rc.action,
|
|
189
|
+
priority: rc.priority,
|
|
190
|
+
enabled: rc.enabled,
|
|
191
|
+
scopes: rc.scopes,
|
|
192
|
+
adapters: rc.adapters?.map(p => this.#parsePattern(p)),
|
|
193
|
+
bots: rc.bots?.map(p => this.#parsePattern(p)),
|
|
194
|
+
channels: rc.channels?.map(p => this.#parsePattern(p)),
|
|
195
|
+
senders: rc.senders?.map(p => this.#parsePattern(p)),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/** 解析单个 pattern:"/regex/flags" → RegExp,其余为精确字符串 */
|
|
199
|
+
#parsePattern(pattern) {
|
|
200
|
+
const match = pattern.match(/^\/(.+)\/([gimsuy]*)$/);
|
|
201
|
+
if (match) {
|
|
202
|
+
return new RegExp(match[1], match[2]);
|
|
203
|
+
}
|
|
204
|
+
return pattern;
|
|
205
|
+
}
|
|
206
|
+
/** 检查规则是否匹配消息(所有条件 AND,条件内 OR) */
|
|
207
|
+
#matchRule(rule, message) {
|
|
208
|
+
if (rule.scopes?.length && !rule.scopes.includes(message.$channel.type)) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
if (rule.adapters?.length && !this.#matchAny(rule.adapters, String(message.$adapter))) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
if (rule.bots?.length && !this.#matchAny(rule.bots, String(message.$bot))) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
if (rule.channels?.length && !this.#matchAny(rule.channels, message.$channel.id)) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
if (rule.senders?.length && !this.#matchAny(rule.senders, message.$sender.id)) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
/** 检查值是否与任一 pattern 匹配 */
|
|
226
|
+
#matchAny(patterns, value) {
|
|
227
|
+
return patterns.some(p => {
|
|
228
|
+
if (p instanceof RegExp)
|
|
229
|
+
return p.test(value);
|
|
230
|
+
if (p === '*')
|
|
231
|
+
return true;
|
|
232
|
+
return p === value;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=message-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-filter.js","sourceRoot":"","sources":["../../src/built/message-filter.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './built/permission.js';
|
|
|
15
15
|
export * from './built/adapter-process.js';
|
|
16
16
|
export * from './built/component.js';
|
|
17
17
|
export * from './built/database.js';
|
|
18
|
+
export * from './built/message-filter.js';
|
|
18
19
|
export * from './built/tool.js';
|
|
19
20
|
export * from './built/ai-trigger.js';
|
|
20
21
|
export * from './built/dispatcher.js';
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAE3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAEhC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAE3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAEhC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AAEzC,cAAc,iBAAiB,CAAA;AAE/B,cAAc,uBAAuB,CAAA;AAErC,cAAc,uBAAuB,CAAA;AAErC,cAAc,kBAAkB,CAAA;AAEhC,cAAc,2BAA2B,CAAA;AAEzC,cAAc,iCAAiC,CAAA;AAE/C,cAAc,eAAe,CAAA;AAE7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAE/B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAExC,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA"}
|
package/lib/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export * from './built/permission.js';
|
|
|
18
18
|
export * from './built/adapter-process.js';
|
|
19
19
|
export * from './built/component.js';
|
|
20
20
|
export * from './built/database.js';
|
|
21
|
+
export * from './built/message-filter.js';
|
|
21
22
|
// Tool Service (纯工具,无副作用)
|
|
22
23
|
export * from './built/tool.js';
|
|
23
24
|
// AI Trigger Service (纯工具,无副作用)
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,SAAS;AACT,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,oBAAoB;AACpB,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,0BAA0B;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,gCAAgC;AAChC,cAAc,uBAAuB,CAAA;AACrC,4BAA4B;AAC5B,cAAc,uBAAuB,CAAA;AACrC,qBAAqB;AACrB,cAAc,kBAAkB,CAAA;AAChC,sBAAsB;AACtB,cAAc,2BAA2B,CAAA;AACzC,yDAAyD;AACzD,cAAc,iCAAiC,CAAA;AAC/C,kCAAkC;AAClC,cAAc,eAAe,CAAA;AAE7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA,CAAE,WAAW;AACxC,cAAc,WAAW,CAAA;AACzB,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,SAAS;AACT,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,oBAAoB;AACpB,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA;AACzC,0BAA0B;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,gCAAgC;AAChC,cAAc,uBAAuB,CAAA;AACrC,4BAA4B;AAC5B,cAAc,uBAAuB,CAAA;AACrC,qBAAqB;AACrB,cAAc,kBAAkB,CAAA;AAChC,sBAAsB;AACtB,cAAc,2BAA2B,CAAA;AACzC,yDAAyD;AACzD,cAAc,iCAAiC,CAAA;AAC/C,kCAAkC;AAClC,cAAc,eAAe,CAAA;AAE7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA,CAAE,WAAW;AACxC,cAAc,WAAW,CAAA;AACzB,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.46",
|
|
4
4
|
"description": "Zhin机器人核心框架",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"segment-matcher": "^1.0.5",
|
|
38
38
|
"smol-toml": "^1.6.0",
|
|
39
39
|
"yaml": "^2.3.4",
|
|
40
|
-
"@zhin.js/
|
|
41
|
-
"@zhin.js/database": "1.0.
|
|
42
|
-
"@zhin.js/
|
|
43
|
-
"@zhin.js/logger": "0.1.
|
|
44
|
-
"@zhin.js/schema": "1.0.
|
|
40
|
+
"@zhin.js/kernel": "0.0.7",
|
|
41
|
+
"@zhin.js/database": "1.0.33",
|
|
42
|
+
"@zhin.js/ai": "1.0.7",
|
|
43
|
+
"@zhin.js/logger": "0.1.30",
|
|
44
|
+
"@zhin.js/schema": "1.0.30"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^24.3.0",
|
package/src/adapter.ts
CHANGED
|
@@ -6,25 +6,12 @@ import { BeforeSendHandler, SendOptions, Tool, ToolContext, ToolScope } from "./
|
|
|
6
6
|
import { segment } from "./utils.js";
|
|
7
7
|
import { ZhinTool, isZhinTool, type ToolInput } from "./built/tool.js";
|
|
8
8
|
import type { Skill, SkillFeature } from "./built/skill.js";
|
|
9
|
-
import {
|
|
10
|
-
type IGroupManagement,
|
|
11
|
-
GROUP_METHOD_SPECS,
|
|
12
|
-
GROUP_MANAGEMENT_SKILL_DESCRIPTION,
|
|
13
|
-
GROUP_MANAGEMENT_SKILL_TAGS,
|
|
14
|
-
GROUP_MANAGEMENT_SKILL_KEYWORDS,
|
|
15
|
-
buildMethodArgs,
|
|
16
|
-
} from "./built/common-adapter-tools.js";
|
|
17
9
|
/**
|
|
18
|
-
* Adapter类:适配器抽象,管理多平台Bot实例。
|
|
10
|
+
* Adapter 类:适配器抽象,管理多平台 Bot 实例。
|
|
19
11
|
* 负责根据配置启动/关闭各平台机器人,统一异常处理。
|
|
20
12
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* 群管理能力:
|
|
24
|
-
* Adapter 基类声明了 IGroupManagement 中的可选方法规范,
|
|
25
|
-
* 具体适配器(ICQQ/Discord/Telegram 等)选择性覆写。
|
|
26
|
-
* 调用 registerGroupManagementSkill() 后,基类自动检测
|
|
27
|
-
* 哪些方法已被实现,生成对应的 Tool 并注册为 "群聊管理" Skill。
|
|
13
|
+
* 适配器可提供 AI 工具并声明 Skill。群管等能力由各 IM 平台在子类中
|
|
14
|
+
* 自行实现方法并注册 Tool(如使用 createGroupManagementTools)+ declareSkill。
|
|
28
15
|
*/
|
|
29
16
|
export abstract class Adapter<R extends Bot = Bot> extends EventEmitter<Adapter.Lifecycle> {
|
|
30
17
|
/** 当前适配器下所有Bot实例,key为bot名称 */
|
|
@@ -101,8 +88,6 @@ export abstract class Adapter<R extends Bot = Bot> extends EventEmitter<Adapter.
|
|
|
101
88
|
this.bots.set(bot.$id, bot);
|
|
102
89
|
}
|
|
103
90
|
this.logger.debug(`adapter ${this.name} started`);
|
|
104
|
-
|
|
105
|
-
this._autoDetectGroupManagement();
|
|
106
91
|
}
|
|
107
92
|
/**
|
|
108
93
|
* 停止适配器,断开并移除所有Bot实例
|
|
@@ -322,69 +307,6 @@ export abstract class Adapter<R extends Bot = Bot> extends EventEmitter<Adapter.
|
|
|
322
307
|
});
|
|
323
308
|
}
|
|
324
309
|
|
|
325
|
-
// ==========================================================================
|
|
326
|
-
// 群管理自动检测 — start() 结束时自动执行
|
|
327
|
-
// ==========================================================================
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* 遍历 GROUP_METHOD_SPECS,检测子类是否覆写了对应方法。
|
|
331
|
-
* 对每个已实现的方法生成 Tool 并注册,最后聚合为 "群聊管理" Skill。
|
|
332
|
-
*/
|
|
333
|
-
private _autoDetectGroupManagement(): void {
|
|
334
|
-
const self = this as unknown as IGroupManagement;
|
|
335
|
-
const prefix = this.name as string;
|
|
336
|
-
const generatedTools: Tool[] = [];
|
|
337
|
-
|
|
338
|
-
for (const spec of GROUP_METHOD_SPECS) {
|
|
339
|
-
const fn = self[spec.method];
|
|
340
|
-
if (typeof fn !== 'function') continue;
|
|
341
|
-
|
|
342
|
-
const boundFn: (...args: any[]) => Promise<any> = fn.bind(self);
|
|
343
|
-
|
|
344
|
-
const properties: Record<string, any> = {
|
|
345
|
-
bot_id: { type: 'string', description: 'Bot ID', contextKey: 'botId' },
|
|
346
|
-
scene_id: { type: 'string', description: '群/服务器 ID', contextKey: 'sceneId' },
|
|
347
|
-
};
|
|
348
|
-
const required: string[] = ['bot_id', 'scene_id'];
|
|
349
|
-
|
|
350
|
-
for (const [name, schema] of Object.entries(spec.extraParams)) {
|
|
351
|
-
properties[name] = schema;
|
|
352
|
-
}
|
|
353
|
-
if (spec.extraRequired) {
|
|
354
|
-
required.push(...spec.extraRequired);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const tool: Tool = {
|
|
358
|
-
name: `${prefix}_${spec.toolSuffix}`,
|
|
359
|
-
description: `${spec.description} (${prefix})`,
|
|
360
|
-
parameters: { type: 'object' as const, properties, required },
|
|
361
|
-
execute: async (args: Record<string, any>) => {
|
|
362
|
-
const { bot_id, scene_id, ...rest } = args;
|
|
363
|
-
return boundFn(...buildMethodArgs(spec.method, bot_id, scene_id, rest));
|
|
364
|
-
},
|
|
365
|
-
tags: ['group', 'management', prefix],
|
|
366
|
-
keywords: spec.keywords,
|
|
367
|
-
permissionLevel: spec.permissionLevel,
|
|
368
|
-
scopes: ['group', 'channel'] as ToolScope[],
|
|
369
|
-
preExecutable: spec.preExecutable,
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
this.addTool(tool);
|
|
373
|
-
generatedTools.push(tool);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (generatedTools.length === 0) return;
|
|
377
|
-
|
|
378
|
-
this.declareSkill({
|
|
379
|
-
description: GROUP_MANAGEMENT_SKILL_DESCRIPTION,
|
|
380
|
-
keywords: GROUP_MANAGEMENT_SKILL_KEYWORDS,
|
|
381
|
-
tags: GROUP_MANAGEMENT_SKILL_TAGS,
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
this.logger.debug(
|
|
385
|
-
`自动检测到 ${generatedTools.length} 个群管理方法 → 已注册 Skill`,
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
310
|
}
|
|
389
311
|
export interface Adapters {}
|
|
390
312
|
export namespace Adapter {
|
package/src/ai/providers/base.ts
CHANGED
|
@@ -49,7 +49,8 @@ export abstract class BaseProvider implements AIProvider {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
if (this.config.apiKey) {
|
|
52
|
-
|
|
52
|
+
const scheme = this.config.authScheme !== undefined ? this.config.authScheme : 'Bearer ';
|
|
53
|
+
headers['Authorization'] = scheme + this.config.apiKey;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
const controller = new AbortController();
|
|
@@ -91,7 +92,8 @@ export abstract class BaseProvider implements AIProvider {
|
|
|
91
92
|
};
|
|
92
93
|
|
|
93
94
|
if (this.config.apiKey) {
|
|
94
|
-
|
|
95
|
+
const scheme = this.config.authScheme !== undefined ? this.config.authScheme : 'Bearer ';
|
|
96
|
+
headers['Authorization'] = scheme + this.config.apiKey;
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
const controller = new AbortController();
|
package/src/ai/types.ts
CHANGED
|
@@ -140,6 +140,10 @@ export interface ProviderCapabilities {
|
|
|
140
140
|
/** Provider 配置 */
|
|
141
141
|
export interface ProviderConfig {
|
|
142
142
|
apiKey?: string;
|
|
143
|
+
/**
|
|
144
|
+
* Authorization 头前缀。默认 `'Bearer '`;设为 `''` 时仅用 apiKey 作为值(部分 API 要求 `Authorization: <key>`)。
|
|
145
|
+
*/
|
|
146
|
+
authScheme?: string;
|
|
143
147
|
baseUrl?: string;
|
|
144
148
|
defaultModel?: string;
|
|
145
149
|
models?: string[];
|