@zhin.js/core 1.0.57 → 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.
Files changed (126) hide show
  1. package/lib/adapter.d.ts +1 -26
  2. package/lib/adapter.d.ts.map +1 -1
  3. package/lib/adapter.js +20 -117
  4. package/lib/adapter.js.map +1 -1
  5. package/lib/ai/index.d.ts +2 -0
  6. package/lib/ai/index.d.ts.map +1 -1
  7. package/lib/ai/index.js +1 -0
  8. package/lib/ai/index.js.map +1 -1
  9. package/lib/built/adapter-process.d.ts +0 -4
  10. package/lib/built/adapter-process.d.ts.map +1 -1
  11. package/lib/built/adapter-process.js +0 -95
  12. package/lib/built/adapter-process.js.map +1 -1
  13. package/lib/built/agent-preset.d.ts +2 -0
  14. package/lib/built/agent-preset.d.ts.map +1 -1
  15. package/lib/built/agent-preset.js +4 -0
  16. package/lib/built/agent-preset.js.map +1 -1
  17. package/lib/built/command.d.ts +4 -0
  18. package/lib/built/command.d.ts.map +1 -1
  19. package/lib/built/command.js +6 -0
  20. package/lib/built/command.js.map +1 -1
  21. package/lib/built/component.d.ts.map +1 -1
  22. package/lib/built/component.js +1 -0
  23. package/lib/built/component.js.map +1 -1
  24. package/lib/built/dispatcher.d.ts.map +1 -1
  25. package/lib/built/dispatcher.js +0 -13
  26. package/lib/built/dispatcher.js.map +1 -1
  27. package/lib/built/message-filter.d.ts +2 -0
  28. package/lib/built/message-filter.d.ts.map +1 -1
  29. package/lib/built/message-filter.js +5 -0
  30. package/lib/built/message-filter.js.map +1 -1
  31. package/lib/built/skill.d.ts +11 -0
  32. package/lib/built/skill.d.ts.map +1 -1
  33. package/lib/built/skill.js +14 -0
  34. package/lib/built/skill.js.map +1 -1
  35. package/lib/built/tool.d.ts +11 -44
  36. package/lib/built/tool.d.ts.map +1 -1
  37. package/lib/built/tool.js +14 -353
  38. package/lib/built/tool.js.map +1 -1
  39. package/lib/plugin.d.ts +1 -25
  40. package/lib/plugin.d.ts.map +1 -1
  41. package/lib/plugin.js +1 -77
  42. package/lib/plugin.js.map +1 -1
  43. package/lib/types.d.ts +0 -25
  44. package/lib/types.d.ts.map +1 -1
  45. package/package.json +10 -7
  46. package/CHANGELOG.md +0 -538
  47. package/REFACTORING_COMPLETE.md +0 -178
  48. package/REFACTORING_STATUS.md +0 -263
  49. package/src/adapter.ts +0 -275
  50. package/src/ai/index.ts +0 -52
  51. package/src/ai/providers/anthropic.ts +0 -379
  52. package/src/ai/providers/base.ts +0 -175
  53. package/src/ai/providers/index.ts +0 -13
  54. package/src/ai/providers/ollama.ts +0 -302
  55. package/src/ai/providers/openai.ts +0 -174
  56. package/src/ai/types.ts +0 -348
  57. package/src/bot.ts +0 -37
  58. package/src/built/adapter-process.ts +0 -177
  59. package/src/built/agent-preset.ts +0 -136
  60. package/src/built/ai-trigger.ts +0 -259
  61. package/src/built/command.ts +0 -108
  62. package/src/built/common-adapter-tools.ts +0 -242
  63. package/src/built/component.ts +0 -130
  64. package/src/built/config.ts +0 -335
  65. package/src/built/cron.ts +0 -156
  66. package/src/built/database.ts +0 -134
  67. package/src/built/dispatcher.ts +0 -496
  68. package/src/built/login-assist.ts +0 -131
  69. package/src/built/message-filter.ts +0 -390
  70. package/src/built/permission.ts +0 -151
  71. package/src/built/schema-feature.ts +0 -190
  72. package/src/built/skill.ts +0 -221
  73. package/src/built/tool.ts +0 -948
  74. package/src/command.ts +0 -87
  75. package/src/component.ts +0 -565
  76. package/src/cron.ts +0 -4
  77. package/src/errors.ts +0 -46
  78. package/src/feature.ts +0 -7
  79. package/src/index.ts +0 -53
  80. package/src/jsx-dev-runtime.ts +0 -2
  81. package/src/jsx-runtime.ts +0 -12
  82. package/src/jsx.ts +0 -135
  83. package/src/message.ts +0 -48
  84. package/src/models/system-log.ts +0 -20
  85. package/src/models/user.ts +0 -15
  86. package/src/notice.ts +0 -98
  87. package/src/plugin.ts +0 -896
  88. package/src/prompt.ts +0 -293
  89. package/src/request.ts +0 -95
  90. package/src/scheduler/index.ts +0 -19
  91. package/src/scheduler/scheduler.ts +0 -372
  92. package/src/scheduler/types.ts +0 -74
  93. package/src/tool-zod.ts +0 -115
  94. package/src/types-generator.ts +0 -78
  95. package/src/types.ts +0 -505
  96. package/src/utils.ts +0 -227
  97. package/tests/adapter.test.ts +0 -638
  98. package/tests/ai/ai-trigger.test.ts +0 -368
  99. package/tests/ai/providers.integration.test.ts +0 -227
  100. package/tests/ai/setup.ts +0 -308
  101. package/tests/ai/tool.test.ts +0 -800
  102. package/tests/bot.test.ts +0 -151
  103. package/tests/command.test.ts +0 -737
  104. package/tests/component-new.test.ts +0 -361
  105. package/tests/config.test.ts +0 -372
  106. package/tests/cron.test.ts +0 -82
  107. package/tests/dispatcher.test.ts +0 -293
  108. package/tests/errors.test.ts +0 -21
  109. package/tests/expression-evaluation.test.ts +0 -258
  110. package/tests/features-builtin.test.ts +0 -191
  111. package/tests/jsx-runtime.test.ts +0 -45
  112. package/tests/jsx.test.ts +0 -319
  113. package/tests/message-filter.test.ts +0 -566
  114. package/tests/message.test.ts +0 -402
  115. package/tests/notice.test.ts +0 -198
  116. package/tests/plugin.test.ts +0 -779
  117. package/tests/prompt.test.ts +0 -78
  118. package/tests/redos-protection.test.ts +0 -198
  119. package/tests/request.test.ts +0 -221
  120. package/tests/schema.test.ts +0 -248
  121. package/tests/skill-feature.test.ts +0 -179
  122. package/tests/test-utils.ts +0 -59
  123. package/tests/tool-feature.test.ts +0 -254
  124. package/tests/types.test.ts +0 -162
  125. package/tests/utils.test.ts +0 -135
  126. package/tsconfig.json +0 -24
@@ -1,130 +0,0 @@
1
- /**
2
- * ComponentFeature
3
- * 管理所有插件注册的组件,继承自 Feature 抽象类
4
- */
5
- import { Feature, FeatureJSON } from "../feature.js";
6
- import { Component, renderComponents } from "../component.js";
7
- import { SendOptions, MaybePromise } from "../types.js";
8
- import { Plugin, getPlugin } from "../plugin.js";
9
- import type { PluginLike } from '@zhin.js/kernel';
10
-
11
- type Listener = (options: SendOptions) => MaybePromise<SendOptions>;
12
-
13
- /**
14
- * ComponentContext 扩展方法类型
15
- */
16
- export interface ComponentContextExtensions {
17
- /** 添加组件 */
18
- addComponent<T extends Component<any>>(component: T): () => void;
19
- }
20
-
21
- // 扩展 Plugin 接口
22
- declare module "../plugin.js" {
23
- namespace Plugin {
24
- interface Extensions extends ComponentContextExtensions {}
25
- interface Contexts {
26
- component: ComponentFeature;
27
- }
28
- }
29
- }
30
-
31
- /**
32
- * 组件服务 Feature
33
- */
34
- export class ComponentFeature extends Feature<Component<any>> {
35
- readonly name = 'component' as const;
36
- readonly icon = 'Box';
37
- readonly desc = '组件';
38
-
39
- /** 按名称索引 */
40
- readonly byName = new Map<string, Component<any>>();
41
-
42
- /** 内部状态:消息渲染监听器 & 宿主插件 */
43
- #listener?: Listener;
44
- #rootPlugin?: Plugin;
45
-
46
- /**
47
- * 添加组件
48
- */
49
- add(component: Component<any>, pluginName: string): () => void {
50
- this.byName.set(component.name, component);
51
- return super.add(component, pluginName);
52
- }
53
-
54
- /**
55
- * 移除组件
56
- */
57
- remove(component: Component<any>): boolean {
58
- this.byName.delete(component.name);
59
- return super.remove(component);
60
- }
61
-
62
- /**
63
- * 获取所有组件名称
64
- */
65
- getAllNames(): string[] {
66
- return Array.from(this.byName.keys());
67
- }
68
-
69
- /**
70
- * 按名称获取组件
71
- */
72
- get(name: string): Component<any> | undefined {
73
- return this.byName.get(name);
74
- }
75
-
76
- /**
77
- * 生命周期: 挂载时注册消息渲染监听器
78
- */
79
- mounted(plugin: PluginLike): void {
80
- const p = plugin as Plugin;
81
- this.#rootPlugin = p;
82
- this.#listener = (options: SendOptions) => {
83
- return renderComponents(this.byName, options);
84
- };
85
- p.root.on('before.sendMessage', this.#listener);
86
- }
87
-
88
- /**
89
- * 生命周期: 销毁时移除监听器
90
- */
91
- dispose(): void {
92
- if (this.#listener && this.#rootPlugin) {
93
- this.#rootPlugin.root.off('before.sendMessage', this.#listener);
94
- this.#listener = undefined;
95
- }
96
- }
97
-
98
- /**
99
- * 序列化为 JSON
100
- */
101
- toJSON(pluginName?: string): FeatureJSON {
102
- const list = pluginName ? this.getByPlugin(pluginName) : this.items;
103
- return {
104
- name: this.name,
105
- icon: this.icon,
106
- desc: this.desc,
107
- count: list.length,
108
- items: list.map(c => ({
109
- name: c.name,
110
- type: 'component',
111
- })),
112
- };
113
- }
114
-
115
- /**
116
- * 提供给 Plugin.prototype 的扩展方法
117
- */
118
- get extensions() {
119
- const feature = this;
120
- return {
121
- addComponent<T extends Component<any>>(component: T) {
122
- const plugin = getPlugin();
123
- const dispose = feature.add(component, plugin.name);
124
- plugin.recordFeatureContribution(feature.name, component.name);
125
- plugin.onDispose(dispose);
126
- return dispose;
127
- },
128
- };
129
- }
130
- }
@@ -1,335 +0,0 @@
1
- /**
2
- * ConfigFeature
3
- * 配置管理服务,继承自 Feature 抽象类
4
- * 保留原有 ConfigLoader / ConfigService 逻辑,增加 addConfig 扩展
5
- */
6
- import path from "node:path";
7
- import fs from "node:fs";
8
- import { stringify as stringifyYaml, parse as parseYaml, parseDocument } from "yaml";
9
- import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
10
- import { Schema } from "@zhin.js/schema";
11
- import { Feature, FeatureJSON } from "../feature.js";
12
- import { getPlugin } from "../plugin.js";
13
-
14
- // ============================================================================
15
- // ConfigLoader(保持不变)
16
- // ============================================================================
17
-
18
- export class ConfigLoader<T extends object> {
19
- #data: T;
20
- get data(): T {
21
- return this.#proxy(this.#data, this);
22
- }
23
- get raw(): T {
24
- return this.#data;
25
- }
26
- get extension() {
27
- return path.extname(this.filename).toLowerCase();
28
- }
29
- constructor(public filename: string, public initial: T, public schema?: Schema<T>) {
30
- this.#data = this.initial;
31
- }
32
- #proxy<R extends object>(data: R, loader: ConfigLoader<T>) {
33
- return new Proxy(data, {
34
- get(target, prop, receiver) {
35
- if (typeof prop === 'symbol' || prop === 'constructor' || prop === 'prototype') {
36
- return Reflect.get(target, prop, receiver);
37
- }
38
-
39
- const result = Reflect.get(target, prop, receiver);
40
-
41
- if (typeof result === 'function') {
42
- return result;
43
- }
44
-
45
- if (result instanceof Object && result !== null && typeof result !== 'function') {
46
- return loader.#proxy(result, loader);
47
- }
48
-
49
- if (typeof result === 'string') {
50
- if (result.startsWith('\\${') && result.endsWith('}')) return result.slice(1);
51
- if (/^\$\{(.*)\}$/.test(result)) {
52
- const content = result.slice(2, -1);
53
- // 支持 bash 风格的默认值语法:${VAR:-default} 和 ${VAR:=default}
54
- // 同时兼容简单语法 ${VAR:default}
55
- let key: string;
56
- let defaultValue: string | undefined;
57
- const bashDefaultMatch = content.match(/^([^:}]+):[-=](.*)$/);
58
- if (bashDefaultMatch) {
59
- // ${VAR:-default} 或 ${VAR:=default}
60
- key = bashDefaultMatch[1];
61
- defaultValue = bashDefaultMatch[2];
62
- } else if (content.includes(':')) {
63
- // ${VAR:default}(旧的简单语法)
64
- const [k, ...rest] = content.split(':');
65
- key = k;
66
- defaultValue = rest.join(':');
67
- } else {
68
- key = content;
69
- defaultValue = undefined;
70
- }
71
- return process.env[key] ?? defaultValue ?? (loader.initial as any)[key] ?? result;
72
- }
73
- }
74
- return result;
75
- },
76
- set(target, prop, value, receiver) {
77
- const result = Reflect.set(target, prop, value, receiver);
78
- loader.save(loader.filename);
79
- return result;
80
- },
81
- deleteProperty(target, prop) {
82
- const result = Reflect.deleteProperty(target, prop);
83
- loader.save(loader.filename);
84
- return result;
85
- }
86
- });
87
- }
88
- load() {
89
- const fullPath = path.resolve(process.cwd(), this.filename);
90
- if (!fs.existsSync(fullPath)) {
91
- this.save(fullPath);
92
- }
93
- const content = fs.readFileSync(fullPath, "utf-8");
94
- let rawConfig: any;
95
- switch (this.extension) {
96
- case ".json":
97
- rawConfig = JSON.parse(content);
98
- break;
99
- case ".yaml":
100
- case ".yml":
101
- rawConfig = parseYaml(content);
102
- break;
103
- case ".toml":
104
- rawConfig = parseToml(content);
105
- break;
106
- }
107
- if (this.schema) {
108
- this.#data = this.schema(rawConfig || this.initial) as T;
109
- } else {
110
- this.#data = rawConfig as T;
111
- }
112
- }
113
- save(fullPath: string) {
114
- switch (this.extension) {
115
- case ".json":
116
- fs.writeFileSync(fullPath, JSON.stringify(this.#data, null, 2));
117
- break;
118
- case ".yaml":
119
- case ".yml":
120
- fs.writeFileSync(fullPath, stringifyYaml(this.#data));
121
- break;
122
- case ".toml":
123
- fs.writeFileSync(fullPath, stringifyToml(this.#data as Record<string, any>));
124
- break;
125
- }
126
- }
127
- /**
128
- * 精准修改单个顶层 key 并写回文件
129
- * 保留注释、格式和未修改字段(如 ${VAR} 环境变量引用)
130
- */
131
- patchKey(key: string, value: any) {
132
- const fullPath = path.resolve(process.cwd(), this.filename);
133
- switch (this.extension) {
134
- case ".yaml":
135
- case ".yml": {
136
- const content = fs.readFileSync(fullPath, 'utf-8');
137
- const doc = parseDocument(content);
138
- doc.set(key, value);
139
- fs.writeFileSync(fullPath, doc.toString());
140
- break;
141
- }
142
- case ".json": {
143
- const content = fs.readFileSync(fullPath, 'utf-8');
144
- const obj = JSON.parse(content);
145
- obj[key] = value;
146
- fs.writeFileSync(fullPath, JSON.stringify(obj, null, 2));
147
- break;
148
- }
149
- case ".toml": {
150
- const content = fs.readFileSync(fullPath, 'utf-8');
151
- const obj = parseToml(content);
152
- (obj as Record<string, any>)[key] = value;
153
- fs.writeFileSync(fullPath, stringifyToml(obj));
154
- break;
155
- }
156
- }
157
- // 同步更新内存
158
- (this.#data as Record<string, any>)[key] = value;
159
- }
160
- }
161
-
162
- export namespace ConfigLoader {
163
- export const supportedExtensions = [".json", ".yaml", ".yml", ".toml"];
164
-
165
- /**
166
- * 自动发现配置文件(按优先级:yml > yaml > json > toml)
167
- */
168
- export function discover(basename: string): string | null {
169
- const cwd = process.cwd();
170
- for (const ext of ['.yml', '.yaml', '.json', '.toml']) {
171
- const filename = `${basename}${ext}`;
172
- if (fs.existsSync(path.resolve(cwd, filename))) {
173
- return filename;
174
- }
175
- }
176
- return null;
177
- }
178
- export function load<T extends object>(filename: string, initial?: T, schema?: Schema<T>) {
179
- const result = new ConfigLoader<T>(filename, initial ?? {} as T, schema);
180
- result.load();
181
- return result;
182
- }
183
- }
184
-
185
- // ============================================================================
186
- // ConfigFeature
187
- // ============================================================================
188
-
189
- /**
190
- * 配置项声明记录
191
- */
192
- export interface ConfigRecord {
193
- key: string;
194
- defaultValue: any;
195
- }
196
-
197
- /**
198
- * ConfigFeature 扩展方法类型
199
- */
200
- export interface ConfigContextExtensions {
201
- /** 声明插件配置项(key + 默认值),如果配置文件中不存在则写入默认值 */
202
- addConfig(key: string, defaultValue: any): () => void;
203
- }
204
-
205
- declare module "../plugin.js" {
206
- namespace Plugin {
207
- interface Extensions extends ConfigContextExtensions {}
208
- interface Contexts {
209
- config: ConfigFeature;
210
- }
211
- }
212
- }
213
-
214
- export class ConfigFeature extends Feature<ConfigRecord> {
215
- readonly name = 'config' as const;
216
- readonly icon = 'Settings';
217
- readonly desc = '配置';
218
-
219
- /** 内部配置文件管理 */
220
- readonly configs: Map<string, ConfigLoader<any>> = new Map();
221
-
222
- /** 主配置文件名(第一个加载的配置文件) */
223
- #primaryConfigFile: string = '';
224
-
225
- /** 获取主配置文件名 */
226
- get primaryFile(): string {
227
- return this.#primaryConfigFile;
228
- }
229
-
230
- /**
231
- * 加载配置文件
232
- */
233
- load<T extends object>(filename: string, initial?: Partial<T>, schema?: Schema<T>): ConfigLoader<T> {
234
- const ext = path.extname(filename).toLowerCase();
235
- if (!ConfigLoader.supportedExtensions.includes(ext)) {
236
- throw new Error(`不支持的配置文件格式: ${ext}`);
237
- }
238
- const config = ConfigLoader.load(filename, initial as T, schema);
239
- this.configs.set(filename, config);
240
- if (!this.#primaryConfigFile) {
241
- this.#primaryConfigFile = filename;
242
- }
243
- return config;
244
- }
245
-
246
- /**
247
- * 获取配置数据(代理模式,自动保存)
248
- */
249
- get<T extends object>(filename: string, initial?: Partial<T>, schema?: Schema<T>): T {
250
- if (!this.configs.has(filename)) this.load(filename, initial, schema);
251
- const config = this.configs.get(filename);
252
- if (!config) throw new Error(`配置文件 ${filename} 未加载`);
253
- return config.data as T;
254
- }
255
-
256
- /**
257
- * 获取主配置文件数据(第一个加载的配置文件)
258
- */
259
- getPrimary<T extends object>(): T {
260
- if (!this.#primaryConfigFile) throw new Error('没有加载任何配置文件');
261
- return this.get<T>(this.#primaryConfigFile);
262
- }
263
-
264
- /**
265
- * 获取原始配置数据
266
- */
267
- getRaw<T extends object>(filename: string, initial?: Partial<T>, schema?: Schema<T>): T {
268
- if (!this.configs.has(filename)) this.load(filename, initial, schema);
269
- const config = this.configs.get(filename);
270
- if (!config) throw new Error(`配置文件 ${filename} 未加载`);
271
- return config.raw as T;
272
- }
273
-
274
- /**
275
- * 更新配置文件内容
276
- */
277
- set<T extends object>(filename: string, data: T): void {
278
- const config = this.configs.get(filename);
279
- if (!config) throw new Error(`配置文件 ${filename} 未加载`);
280
- Object.assign(config.raw, data);
281
- config.save(path.resolve(process.cwd(), filename));
282
- }
283
-
284
- /**
285
- * 序列化为 JSON
286
- */
287
- toJSON(pluginName?: string): FeatureJSON {
288
- const list = pluginName ? this.getByPlugin(pluginName) : this.items;
289
- return {
290
- name: this.name,
291
- icon: this.icon,
292
- desc: this.desc,
293
- count: list.length,
294
- items: list.map(r => ({
295
- name: r.key,
296
- // 不暴露 defaultValue 以防止泄露密钥/令牌
297
- })),
298
- };
299
- }
300
-
301
- /**
302
- * 提供给 Plugin.prototype 的扩展方法
303
- */
304
- get extensions() {
305
- const feature = this;
306
- return {
307
- addConfig(key: string, defaultValue: any) {
308
- const plugin = getPlugin();
309
-
310
- // 尝试写入主配置文件(如果 key 不存在)
311
- if (feature.#primaryConfigFile) {
312
- const config = feature.configs.get(feature.#primaryConfigFile);
313
- if (config) {
314
- const raw = config.raw as Record<string, any>;
315
- if (!(key in raw)) {
316
- raw[key] = defaultValue;
317
- config.save(path.resolve(process.cwd(), feature.#primaryConfigFile));
318
- }
319
- }
320
- }
321
-
322
- const record: ConfigRecord = { key, defaultValue };
323
- const dispose = feature.add(record, plugin.name);
324
- plugin.recordFeatureContribution(feature.name, key);
325
- plugin.onDispose(dispose);
326
- return dispose;
327
- },
328
- };
329
- }
330
- }
331
-
332
- /**
333
- * @deprecated Use ConfigFeature instead
334
- */
335
- export const ConfigService = ConfigFeature;
package/src/built/cron.ts DELETED
@@ -1,156 +0,0 @@
1
- /**
2
- * CronFeature
3
- * 管理所有插件注册的定时任务,继承自 Feature 抽象类
4
- */
5
- import { Feature, FeatureJSON } from "../feature.js";
6
- import { Cron } from "../cron.js";
7
- import { Plugin, getPlugin } from "../plugin.js";
8
-
9
- /**
10
- * CronContext 扩展方法类型
11
- */
12
- export interface CronContextExtensions {
13
- /** 添加定时任务 */
14
- addCron(cron: Cron): () => void;
15
- }
16
-
17
- // 扩展 Plugin 接口
18
- declare module "../plugin.js" {
19
- namespace Plugin {
20
- interface Extensions extends CronContextExtensions {}
21
- interface Contexts {
22
- cron: CronFeature;
23
- }
24
- }
25
- }
26
-
27
- /**
28
- * 定时任务服务 Feature
29
- */
30
- export class CronFeature extends Feature<Cron> {
31
- readonly name = 'cron' as const;
32
- readonly icon = 'Clock';
33
- readonly desc = '定时任务';
34
-
35
- /** 按 ID/表达式 索引 */
36
- readonly byName = new Map<string, Cron>();
37
-
38
- /**
39
- * 添加定时任务,自动启动
40
- */
41
- add(cron: Cron, pluginName: string): () => void {
42
- this.byName.set(cron.id || cron.cronExpression, cron);
43
- // 自动启动
44
- if (!cron.running) {
45
- cron.run();
46
- }
47
- return super.add(cron, pluginName);
48
- }
49
-
50
- /**
51
- * 移除定时任务,自动停止
52
- */
53
- remove(cron: Cron): boolean {
54
- if (cron.running) {
55
- cron.stop();
56
- }
57
- this.byName.delete(cron.id || cron.cronExpression);
58
- return super.remove(cron);
59
- }
60
-
61
- /**
62
- * 按 ID/表达式 获取
63
- */
64
- get(id: string): Cron | undefined {
65
- return this.byName.get(id);
66
- }
67
-
68
- /**
69
- * 停止所有任务
70
- */
71
- stopAll(): void {
72
- for (const cron of this.items) {
73
- if (cron.running) {
74
- cron.stop();
75
- }
76
- }
77
- }
78
-
79
- /**
80
- * 启动所有任务
81
- */
82
- startAll(): void {
83
- for (const cron of this.items) {
84
- if (!cron.running && !cron.disposed) {
85
- cron.run();
86
- }
87
- }
88
- }
89
-
90
- /**
91
- * 获取所有任务状态
92
- */
93
- getStatus(): Array<{
94
- expression: string;
95
- running: boolean;
96
- nextExecution: Date | null;
97
- plugin: string;
98
- }> {
99
- return this.items.map(cron => {
100
- // 从 pluginItems 中找到对应的插件名
101
- let pluginName = 'unknown';
102
- for (const [name, items] of this.pluginItems) {
103
- if (items.includes(cron)) {
104
- pluginName = name;
105
- break;
106
- }
107
- }
108
- return {
109
- expression: cron.cronExpression,
110
- running: cron.running,
111
- nextExecution: cron.running ? cron.getNextExecutionTime() : null,
112
- plugin: pluginName,
113
- };
114
- });
115
- }
116
-
117
- /**
118
- * 生命周期: 销毁时停止所有任务
119
- */
120
- dispose(): void {
121
- this.stopAll();
122
- }
123
-
124
- /**
125
- * 序列化为 JSON
126
- */
127
- toJSON(pluginName?: string): FeatureJSON {
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(c => ({
135
- expression: c.cronExpression,
136
- running: c.running,
137
- })),
138
- };
139
- }
140
-
141
- /**
142
- * 提供给 Plugin.prototype 的扩展方法
143
- */
144
- get extensions() {
145
- const feature = this;
146
- return {
147
- addCron(cron: Cron) {
148
- const plugin = getPlugin();
149
- const dispose = feature.add(cron, plugin.name);
150
- plugin.recordFeatureContribution(feature.name, cron.id || cron.cronExpression);
151
- plugin.onDispose(dispose);
152
- return dispose;
153
- },
154
- };
155
- }
156
- }