@zhin.js/core 1.1.0 → 1.1.2
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/lib/adapter.d.ts +1 -26
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +20 -117
- package/lib/adapter.js.map +1 -1
- package/lib/built/adapter-process.d.ts +0 -4
- package/lib/built/adapter-process.d.ts.map +1 -1
- package/lib/built/adapter-process.js +0 -95
- package/lib/built/adapter-process.js.map +1 -1
- package/lib/built/agent-preset.d.ts +2 -0
- package/lib/built/agent-preset.d.ts.map +1 -1
- package/lib/built/agent-preset.js +4 -0
- package/lib/built/agent-preset.js.map +1 -1
- package/lib/built/command.d.ts +4 -0
- package/lib/built/command.d.ts.map +1 -1
- package/lib/built/command.js +6 -0
- package/lib/built/command.js.map +1 -1
- package/lib/built/component.d.ts.map +1 -1
- package/lib/built/component.js +1 -0
- package/lib/built/component.js.map +1 -1
- package/lib/built/dispatcher.d.ts.map +1 -1
- package/lib/built/dispatcher.js +0 -13
- package/lib/built/dispatcher.js.map +1 -1
- package/lib/built/message-filter.d.ts +2 -0
- package/lib/built/message-filter.d.ts.map +1 -1
- package/lib/built/message-filter.js +5 -0
- package/lib/built/message-filter.js.map +1 -1
- package/lib/built/skill.d.ts +11 -0
- package/lib/built/skill.d.ts.map +1 -1
- package/lib/built/skill.js +14 -0
- package/lib/built/skill.js.map +1 -1
- package/lib/built/tool.d.ts +11 -44
- package/lib/built/tool.d.ts.map +1 -1
- package/lib/built/tool.js +14 -353
- package/lib/built/tool.js.map +1 -1
- package/lib/plugin.d.ts +1 -25
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +1 -77
- package/lib/plugin.js.map +1 -1
- package/lib/types.d.ts +0 -25
- package/lib/types.d.ts.map +1 -1
- package/package.json +10 -7
- package/CHANGELOG.md +0 -561
- package/REFACTORING_COMPLETE.md +0 -178
- package/REFACTORING_STATUS.md +0 -263
- package/src/adapter.ts +0 -275
- package/src/ai/index.ts +0 -55
- package/src/ai/providers/anthropic.ts +0 -379
- package/src/ai/providers/base.ts +0 -175
- package/src/ai/providers/index.ts +0 -13
- package/src/ai/providers/ollama.ts +0 -302
- package/src/ai/providers/openai.ts +0 -174
- package/src/ai/types.ts +0 -348
- package/src/bot.ts +0 -37
- package/src/built/adapter-process.ts +0 -177
- package/src/built/agent-preset.ts +0 -136
- package/src/built/ai-trigger.ts +0 -259
- package/src/built/command.ts +0 -108
- package/src/built/common-adapter-tools.ts +0 -242
- package/src/built/component.ts +0 -130
- package/src/built/config.ts +0 -335
- package/src/built/cron.ts +0 -156
- package/src/built/database.ts +0 -134
- package/src/built/dispatcher.ts +0 -496
- package/src/built/login-assist.ts +0 -131
- package/src/built/message-filter.ts +0 -390
- package/src/built/permission.ts +0 -151
- package/src/built/schema-feature.ts +0 -190
- package/src/built/skill.ts +0 -221
- package/src/built/tool.ts +0 -948
- package/src/command.ts +0 -87
- package/src/component.ts +0 -565
- package/src/cron.ts +0 -4
- package/src/errors.ts +0 -46
- package/src/feature.ts +0 -7
- package/src/index.ts +0 -53
- package/src/jsx-dev-runtime.ts +0 -2
- package/src/jsx-runtime.ts +0 -12
- package/src/jsx.ts +0 -135
- package/src/message.ts +0 -48
- package/src/models/system-log.ts +0 -20
- package/src/models/user.ts +0 -15
- package/src/notice.ts +0 -98
- package/src/plugin.ts +0 -896
- package/src/prompt.ts +0 -293
- package/src/request.ts +0 -95
- package/src/scheduler/index.ts +0 -19
- package/src/scheduler/scheduler.ts +0 -372
- package/src/scheduler/types.ts +0 -74
- package/src/tool-zod.ts +0 -115
- package/src/types-generator.ts +0 -78
- package/src/types.ts +0 -505
- package/src/utils.ts +0 -227
- package/tests/adapter.test.ts +0 -638
- package/tests/ai/ai-trigger.test.ts +0 -368
- package/tests/ai/providers.integration.test.ts +0 -227
- package/tests/ai/setup.ts +0 -308
- package/tests/ai/tool.test.ts +0 -800
- package/tests/bot.test.ts +0 -151
- package/tests/command.test.ts +0 -737
- package/tests/component-new.test.ts +0 -361
- package/tests/config.test.ts +0 -372
- package/tests/cron.test.ts +0 -82
- package/tests/dispatcher.test.ts +0 -293
- package/tests/errors.test.ts +0 -21
- package/tests/expression-evaluation.test.ts +0 -258
- package/tests/features-builtin.test.ts +0 -191
- package/tests/jsx-runtime.test.ts +0 -45
- package/tests/jsx.test.ts +0 -319
- package/tests/message-filter.test.ts +0 -566
- package/tests/message.test.ts +0 -402
- package/tests/notice.test.ts +0 -198
- package/tests/plugin.test.ts +0 -779
- package/tests/prompt.test.ts +0 -78
- package/tests/redos-protection.test.ts +0 -198
- package/tests/request.test.ts +0 -221
- package/tests/schema.test.ts +0 -248
- package/tests/skill-feature.test.ts +0 -179
- package/tests/test-utils.ts +0 -59
- package/tests/tool-feature.test.ts +0 -254
- package/tests/types.test.ts +0 -162
- package/tests/utils.test.ts +0 -135
- package/tsconfig.json +0 -24
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SchemaFeature — 插件配置 Schema 注册表
|
|
3
|
-
*
|
|
4
|
-
* 插件通过 declareConfig(key, schema) 声明配置项及其 Schema,
|
|
5
|
-
* SchemaFeature 全局收集后供 Web 控制台渲染配置编辑表单。
|
|
6
|
-
*
|
|
7
|
-
* 与 ConfigFeature 协作:
|
|
8
|
-
* - declareConfig 内部调用 addConfig(key, defaults) 写入默认值
|
|
9
|
-
* - Schema.toJSON() 传给前端驱动 PluginConfigForm
|
|
10
|
-
* - reloadable 标记决定保存后是否自动重载插件
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { Feature, FeatureJSON } from '../feature.js';
|
|
14
|
-
import { Schema } from '@zhin.js/schema';
|
|
15
|
-
import { Plugin, getPlugin } from '../plugin.js';
|
|
16
|
-
|
|
17
|
-
// ============================================================================
|
|
18
|
-
// 类型
|
|
19
|
-
// ============================================================================
|
|
20
|
-
|
|
21
|
-
export interface SchemaRecord {
|
|
22
|
-
/** 配置 key(对应 zhin.config.yml 中的顶级字段) */
|
|
23
|
-
key: string;
|
|
24
|
-
/** Schema 实例 */
|
|
25
|
-
schema: Schema;
|
|
26
|
-
/** 保存后是否支持热重载(http/database 等底层服务应为 false) */
|
|
27
|
-
reloadable: boolean;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface SchemaContextExtensions {
|
|
31
|
-
/**
|
|
32
|
-
* 声明插件配置 Schema
|
|
33
|
-
* @param key 配置 key,如 "rss"
|
|
34
|
-
* @param schema Schema.object({...}) 定义
|
|
35
|
-
* @param options.reloadable 保存后是否自动重载,默认 true
|
|
36
|
-
* @returns 当前配置值(已合并默认值)
|
|
37
|
-
*/
|
|
38
|
-
declareConfig<T extends Record<string, any>>(
|
|
39
|
-
key: string,
|
|
40
|
-
schema: Schema<T>,
|
|
41
|
-
options?: { reloadable?: boolean },
|
|
42
|
-
): Required<T>;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
declare module '../plugin.js' {
|
|
46
|
-
namespace Plugin {
|
|
47
|
-
interface Extensions extends SchemaContextExtensions {}
|
|
48
|
-
interface Contexts {
|
|
49
|
-
schema: SchemaFeature;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// ============================================================================
|
|
55
|
-
// SchemaFeature
|
|
56
|
-
// ============================================================================
|
|
57
|
-
|
|
58
|
-
export class SchemaFeature extends Feature<SchemaRecord> {
|
|
59
|
-
readonly name = 'schema' as const;
|
|
60
|
-
readonly icon = 'FileCode';
|
|
61
|
-
readonly desc = '配置模型';
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 按配置 key 查找 Schema
|
|
65
|
-
*/
|
|
66
|
-
getByKey(key: string): SchemaRecord | null {
|
|
67
|
-
return this.items.find(r => r.key === key) ?? null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 获取指定插件名注册的 Schema
|
|
72
|
-
*/
|
|
73
|
-
getByPluginName(pluginName: string): SchemaRecord | null {
|
|
74
|
-
const list = this.getByPlugin(pluginName);
|
|
75
|
-
return list.length > 0 ? list[0] : null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* 获取某个 key 的 Schema 实例(WebSocket handler 使用)
|
|
80
|
-
*/
|
|
81
|
-
get(keyOrPlugin: string): Schema | null {
|
|
82
|
-
const byKey = this.getByKey(keyOrPlugin);
|
|
83
|
-
if (byKey) return byKey.schema;
|
|
84
|
-
const byPlugin = this.getByPluginName(keyOrPlugin);
|
|
85
|
-
return byPlugin?.schema ?? null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* 判断某个 key 对应的插件是否支持热重载
|
|
90
|
-
*/
|
|
91
|
-
isReloadable(keyOrPlugin: string): boolean {
|
|
92
|
-
const byKey = this.getByKey(keyOrPlugin);
|
|
93
|
-
if (byKey) return byKey.reloadable;
|
|
94
|
-
const byPlugin = this.getByPluginName(keyOrPlugin);
|
|
95
|
-
return byPlugin?.reloadable ?? true;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* 通过 pluginName 获取对应的 config key
|
|
100
|
-
*/
|
|
101
|
-
resolveConfigKey(pluginName: string): string | null {
|
|
102
|
-
const byKey = this.getByKey(pluginName);
|
|
103
|
-
if (byKey) return byKey.key;
|
|
104
|
-
const byPlugin = this.getByPluginName(pluginName);
|
|
105
|
-
return byPlugin?.key ?? null;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* 返回 pluginName → configKey 的映射
|
|
110
|
-
*/
|
|
111
|
-
getPluginKeyMap(): Map<string, string> {
|
|
112
|
-
const map = new Map<string, string>();
|
|
113
|
-
for (const [pluginName, records] of this.pluginItems) {
|
|
114
|
-
if (records.length > 0) {
|
|
115
|
-
map.set(pluginName, records[0].key);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return map;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
toJSON(pluginName?: string): FeatureJSON {
|
|
122
|
-
const list = pluginName ? this.getByPlugin(pluginName) : this.items;
|
|
123
|
-
return {
|
|
124
|
-
name: this.name,
|
|
125
|
-
icon: this.icon,
|
|
126
|
-
desc: this.desc,
|
|
127
|
-
count: list.length,
|
|
128
|
-
items: list.map(r => ({
|
|
129
|
-
name: r.key,
|
|
130
|
-
reloadable: r.reloadable,
|
|
131
|
-
schema: r.schema.toJSON(),
|
|
132
|
-
})),
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
get extensions() {
|
|
137
|
-
const feature = this;
|
|
138
|
-
return {
|
|
139
|
-
declareConfig<T extends Record<string, any>>(
|
|
140
|
-
key: string,
|
|
141
|
-
schema: Schema<T>,
|
|
142
|
-
options?: { reloadable?: boolean },
|
|
143
|
-
): Required<T> {
|
|
144
|
-
const plugin = getPlugin() as Plugin;
|
|
145
|
-
const reloadable = options?.reloadable ?? true;
|
|
146
|
-
|
|
147
|
-
// 从 Schema 提取默认值
|
|
148
|
-
const defaults = extractDefaults(schema);
|
|
149
|
-
|
|
150
|
-
// 注册到 ConfigFeature(写入 config.yml 的默认值)
|
|
151
|
-
if (typeof plugin.addConfig === 'function') {
|
|
152
|
-
plugin.addConfig(key, defaults);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// 注册到 SchemaFeature
|
|
156
|
-
const record: SchemaRecord = { key, schema, reloadable };
|
|
157
|
-
const dispose = feature.add(record, plugin.name);
|
|
158
|
-
plugin.recordFeatureContribution(feature.name, key);
|
|
159
|
-
plugin.onDispose(dispose);
|
|
160
|
-
|
|
161
|
-
// 读取当前配置并与默认值合并
|
|
162
|
-
const root = plugin.root ?? plugin;
|
|
163
|
-
const configService = root.inject('config') as any;
|
|
164
|
-
const appConfig = configService?.get?.('zhin.config.yml') ?? {};
|
|
165
|
-
const current = appConfig[key] ?? {};
|
|
166
|
-
|
|
167
|
-
return { ...defaults, ...current } as Required<T>;
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// ============================================================================
|
|
174
|
-
// 辅助:从 Schema 提取默认值
|
|
175
|
-
// ============================================================================
|
|
176
|
-
|
|
177
|
-
function extractDefaults(schema: Schema): Record<string, any> {
|
|
178
|
-
const json = schema.toJSON();
|
|
179
|
-
const result: Record<string, any> = {};
|
|
180
|
-
|
|
181
|
-
const fields = json.object || json.properties || json.dict || {};
|
|
182
|
-
for (const [fieldKey, fieldSchema] of Object.entries(fields)) {
|
|
183
|
-
const field = fieldSchema as Record<string, any>;
|
|
184
|
-
if (field.default !== undefined) {
|
|
185
|
-
result[fieldKey] = field.default;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return result;
|
|
190
|
-
}
|
package/src/built/skill.ts
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SkillFeature — AI 可见能力描述层
|
|
3
|
-
*
|
|
4
|
-
* 核心概念:
|
|
5
|
-
* Plugin = 运行时容器(生命周期、服务注册、中间件)
|
|
6
|
-
* Skill = AI 可见的能力接口(名称、描述、工具列表)
|
|
7
|
-
*
|
|
8
|
-
* Skill 记录由运行时注入(如 Agent 从磁盘 SKILL.md 同步),供 Agent 粗筛与工具关联。
|
|
9
|
-
*
|
|
10
|
-
* SkillFeature 全局收集所有 Skill,供 Agent 进行两级过滤:
|
|
11
|
-
* 1. 粗筛:根据用户消息选择相关 Skill
|
|
12
|
-
* 2. 细筛:从选中 Skill 内选择具体 Tool
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { Feature, FeatureJSON } from '../feature.js';
|
|
16
|
-
import type { Tool } from '../types.js';
|
|
17
|
-
|
|
18
|
-
// ============================================================================
|
|
19
|
-
// Skill 接口
|
|
20
|
-
// ============================================================================
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Skill — AI 可见的能力描述
|
|
24
|
-
*/
|
|
25
|
-
export interface Skill {
|
|
26
|
-
/** 技能名称(通常与插件名一致) */
|
|
27
|
-
name: string;
|
|
28
|
-
|
|
29
|
-
/** 技能描述(AI 用来理解这个 Skill 的用途) */
|
|
30
|
-
description: string;
|
|
31
|
-
|
|
32
|
-
/** 该 Skill 提供的工具列表 */
|
|
33
|
-
tools: Tool[];
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* 触发关键词
|
|
37
|
-
* 当用户消息包含这些关键词时,优先选择此 Skill
|
|
38
|
-
*/
|
|
39
|
-
keywords?: string[];
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 分类标签
|
|
43
|
-
* 用于按领域分组(如 'news', 'weather', 'entertainment')
|
|
44
|
-
*/
|
|
45
|
-
tags?: string[];
|
|
46
|
-
|
|
47
|
-
/** 来源插件名 */
|
|
48
|
-
pluginName: string;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* SKILL.md 文件的绝对路径
|
|
52
|
-
* 存在时 activate_skill 可按需加载完整指令内容
|
|
53
|
-
*/
|
|
54
|
-
filePath?: string;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 是否常驻注入 system prompt
|
|
58
|
-
* 仅在 filePath 存在时有效
|
|
59
|
-
*/
|
|
60
|
-
always?: boolean;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* SKILL.md frontmatter 常见字段(类型提示;运行时由 Agent 等同步到 SkillFeature)
|
|
65
|
-
*/
|
|
66
|
-
export interface SkillMetadata {
|
|
67
|
-
/** 技能描述(必填) */
|
|
68
|
-
description: string;
|
|
69
|
-
|
|
70
|
-
/** 触发关键词(可选) */
|
|
71
|
-
keywords?: string[];
|
|
72
|
-
|
|
73
|
-
/** 分类标签(可选) */
|
|
74
|
-
tags?: string[];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
declare module '../plugin.js' {
|
|
78
|
-
namespace Plugin {
|
|
79
|
-
interface Contexts {
|
|
80
|
-
skill: SkillFeature;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ============================================================================
|
|
86
|
-
// SkillFeature 实现
|
|
87
|
-
// ============================================================================
|
|
88
|
-
|
|
89
|
-
export class SkillFeature extends Feature<Skill> {
|
|
90
|
-
readonly name = 'skill' as const;
|
|
91
|
-
readonly icon = 'Brain';
|
|
92
|
-
readonly desc = '技能';
|
|
93
|
-
|
|
94
|
-
/** 按名称索引 */
|
|
95
|
-
readonly byName = new Map<string, Skill>();
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* 添加 Skill
|
|
99
|
-
*/
|
|
100
|
-
add(skill: Skill, pluginName: string): () => void {
|
|
101
|
-
this.byName.set(skill.name, skill);
|
|
102
|
-
return super.add(skill, pluginName);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* 移除 Skill
|
|
107
|
-
*/
|
|
108
|
-
remove(skill: Skill): boolean {
|
|
109
|
-
this.byName.delete(skill.name);
|
|
110
|
-
return super.remove(skill);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* 按名称获取 Skill
|
|
115
|
-
*/
|
|
116
|
-
get(name: string): Skill | undefined {
|
|
117
|
-
return this.byName.get(name);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* 获取所有已注册 Skill
|
|
122
|
-
*/
|
|
123
|
-
getAll(): Skill[] {
|
|
124
|
-
return [...this.items];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* 按关键词/标签搜索相关 Skill
|
|
129
|
-
* 返回按相关性排序的 Skill 列表
|
|
130
|
-
*/
|
|
131
|
-
search(query: string, options?: { maxResults?: number }): Skill[] {
|
|
132
|
-
const maxResults = options?.maxResults ?? 5;
|
|
133
|
-
const scored = this.items
|
|
134
|
-
.map(skill => ({ skill, score: this.#scoreSkill(skill, query) }))
|
|
135
|
-
.filter(({ score }) => score > 0)
|
|
136
|
-
.sort((a, b) => b.score - a.score)
|
|
137
|
-
.slice(0, maxResults);
|
|
138
|
-
|
|
139
|
-
return scored.map(({ skill }) => skill);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* 获取所有 Skill 的工具(扁平化)
|
|
144
|
-
*/
|
|
145
|
-
collectAllTools(): Tool[] {
|
|
146
|
-
const tools: Tool[] = [];
|
|
147
|
-
for (const skill of this.items) {
|
|
148
|
-
tools.push(...skill.tools);
|
|
149
|
-
}
|
|
150
|
-
return tools;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* 已注册 Skill 数量
|
|
155
|
-
*/
|
|
156
|
-
get size(): number {
|
|
157
|
-
return this.items.length;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* 简单的关键词匹配评分
|
|
162
|
-
*/
|
|
163
|
-
#scoreSkill(skill: Skill, query: string): number {
|
|
164
|
-
const lowerQuery = query.toLowerCase();
|
|
165
|
-
let score = 0;
|
|
166
|
-
|
|
167
|
-
// 关键词精确匹配
|
|
168
|
-
if (skill.keywords) {
|
|
169
|
-
for (const kw of skill.keywords) {
|
|
170
|
-
if (lowerQuery.includes(kw.toLowerCase())) score += 1.0;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 标签匹配
|
|
175
|
-
if (skill.tags) {
|
|
176
|
-
for (const tag of skill.tags) {
|
|
177
|
-
if (lowerQuery.includes(tag.toLowerCase())) score += 0.5;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// 名称匹配
|
|
182
|
-
if (lowerQuery.includes(skill.name.toLowerCase())) score += 0.3;
|
|
183
|
-
|
|
184
|
-
// 描述匹配(双向)
|
|
185
|
-
const lowerDesc = skill.description.toLowerCase();
|
|
186
|
-
if (lowerDesc.includes(lowerQuery)) score += 0.2;
|
|
187
|
-
if (lowerQuery.includes(lowerDesc)) score += 0.15;
|
|
188
|
-
|
|
189
|
-
// 工具名/描述匹配
|
|
190
|
-
for (const tool of skill.tools) {
|
|
191
|
-
if (lowerQuery.includes(tool.name.toLowerCase())) score += 0.4;
|
|
192
|
-
if (tool.description && lowerQuery.includes(tool.description.toLowerCase().slice(0, 10))) {
|
|
193
|
-
score += 0.1;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return score;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* 序列化为 JSON
|
|
202
|
-
*/
|
|
203
|
-
toJSON(pluginName?: string): FeatureJSON {
|
|
204
|
-
const list = pluginName ? this.getByPlugin(pluginName) : this.items;
|
|
205
|
-
return {
|
|
206
|
-
name: this.name,
|
|
207
|
-
icon: this.icon,
|
|
208
|
-
desc: this.desc,
|
|
209
|
-
count: list.length,
|
|
210
|
-
items: list.map(s => ({
|
|
211
|
-
name: s.name,
|
|
212
|
-
desc: s.description,
|
|
213
|
-
toolCount: s.tools.length,
|
|
214
|
-
keywords: s.keywords,
|
|
215
|
-
tags: s.tags,
|
|
216
|
-
})),
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|