flashclaw 1.0.0

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 (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +305 -0
  3. package/config/plugins.json +23 -0
  4. package/dist/agent-runner.d.ts +103 -0
  5. package/dist/agent-runner.d.ts.map +1 -0
  6. package/dist/agent-runner.js +530 -0
  7. package/dist/agent-runner.js.map +1 -0
  8. package/dist/cli.d.ts +7 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +497 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands.d.ts +68 -0
  13. package/dist/commands.d.ts.map +1 -0
  14. package/dist/commands.js +252 -0
  15. package/dist/commands.js.map +1 -0
  16. package/dist/config-schema.d.ts +21 -0
  17. package/dist/config-schema.d.ts.map +1 -0
  18. package/dist/config-schema.js +26 -0
  19. package/dist/config-schema.js.map +1 -0
  20. package/dist/config.d.ts +11 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +36 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/core/api-client.d.ts +236 -0
  25. package/dist/core/api-client.d.ts.map +1 -0
  26. package/dist/core/api-client.js +369 -0
  27. package/dist/core/api-client.js.map +1 -0
  28. package/dist/core/memory.d.ts +291 -0
  29. package/dist/core/memory.d.ts.map +1 -0
  30. package/dist/core/memory.js +754 -0
  31. package/dist/core/memory.js.map +1 -0
  32. package/dist/core/model-capabilities.d.ts +45 -0
  33. package/dist/core/model-capabilities.d.ts.map +1 -0
  34. package/dist/core/model-capabilities.js +85 -0
  35. package/dist/core/model-capabilities.js.map +1 -0
  36. package/dist/db.d.ts +103 -0
  37. package/dist/db.d.ts.map +1 -0
  38. package/dist/db.js +380 -0
  39. package/dist/db.js.map +1 -0
  40. package/dist/errors.d.ts +22 -0
  41. package/dist/errors.d.ts.map +1 -0
  42. package/dist/errors.js +44 -0
  43. package/dist/errors.js.map +1 -0
  44. package/dist/health.d.ts +27 -0
  45. package/dist/health.d.ts.map +1 -0
  46. package/dist/health.js +55 -0
  47. package/dist/health.js.map +1 -0
  48. package/dist/index.d.ts +11 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +1181 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/logger.d.ts +9 -0
  53. package/dist/logger.d.ts.map +1 -0
  54. package/dist/logger.js +19 -0
  55. package/dist/logger.js.map +1 -0
  56. package/dist/message-queue.d.ts +69 -0
  57. package/dist/message-queue.d.ts.map +1 -0
  58. package/dist/message-queue.js +198 -0
  59. package/dist/message-queue.js.map +1 -0
  60. package/dist/metrics.d.ts +46 -0
  61. package/dist/metrics.d.ts.map +1 -0
  62. package/dist/metrics.js +101 -0
  63. package/dist/metrics.js.map +1 -0
  64. package/dist/paths.d.ts +81 -0
  65. package/dist/paths.d.ts.map +1 -0
  66. package/dist/paths.js +127 -0
  67. package/dist/paths.js.map +1 -0
  68. package/dist/plugins/index.d.ts +9 -0
  69. package/dist/plugins/index.d.ts.map +1 -0
  70. package/dist/plugins/index.js +13 -0
  71. package/dist/plugins/index.js.map +1 -0
  72. package/dist/plugins/installer.d.ts +120 -0
  73. package/dist/plugins/installer.d.ts.map +1 -0
  74. package/dist/plugins/installer.js +1008 -0
  75. package/dist/plugins/installer.js.map +1 -0
  76. package/dist/plugins/loader.d.ts +37 -0
  77. package/dist/plugins/loader.d.ts.map +1 -0
  78. package/dist/plugins/loader.js +429 -0
  79. package/dist/plugins/loader.js.map +1 -0
  80. package/dist/plugins/manager.d.ts +72 -0
  81. package/dist/plugins/manager.d.ts.map +1 -0
  82. package/dist/plugins/manager.js +187 -0
  83. package/dist/plugins/manager.js.map +1 -0
  84. package/dist/plugins/types.d.ts +101 -0
  85. package/dist/plugins/types.d.ts.map +1 -0
  86. package/dist/plugins/types.js +12 -0
  87. package/dist/plugins/types.js.map +1 -0
  88. package/dist/session-tracker.d.ts +81 -0
  89. package/dist/session-tracker.d.ts.map +1 -0
  90. package/dist/session-tracker.js +228 -0
  91. package/dist/session-tracker.js.map +1 -0
  92. package/dist/task-scheduler.d.ts +47 -0
  93. package/dist/task-scheduler.d.ts.map +1 -0
  94. package/dist/task-scheduler.js +331 -0
  95. package/dist/task-scheduler.js.map +1 -0
  96. package/dist/types.d.ts +57 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +2 -0
  99. package/dist/types.js.map +1 -0
  100. package/dist/utils/env-substitute.d.ts +63 -0
  101. package/dist/utils/env-substitute.d.ts.map +1 -0
  102. package/dist/utils/env-substitute.js +133 -0
  103. package/dist/utils/env-substitute.js.map +1 -0
  104. package/dist/utils/log-rotate.d.ts +19 -0
  105. package/dist/utils/log-rotate.d.ts.map +1 -0
  106. package/dist/utils/log-rotate.js +85 -0
  107. package/dist/utils/log-rotate.js.map +1 -0
  108. package/dist/utils/rate-limiter.d.ts +38 -0
  109. package/dist/utils/rate-limiter.d.ts.map +1 -0
  110. package/dist/utils/rate-limiter.js +79 -0
  111. package/dist/utils/rate-limiter.js.map +1 -0
  112. package/dist/utils/retry.d.ts +10 -0
  113. package/dist/utils/retry.d.ts.map +1 -0
  114. package/dist/utils/retry.js +47 -0
  115. package/dist/utils/retry.js.map +1 -0
  116. package/dist/utils.d.ts +86 -0
  117. package/dist/utils.d.ts.map +1 -0
  118. package/dist/utils.js +218 -0
  119. package/dist/utils.js.map +1 -0
  120. package/package.json +78 -0
  121. package/plugins/cancel-task/index.ts +161 -0
  122. package/plugins/cancel-task/plugin.json +9 -0
  123. package/plugins/feishu/index.ts +944 -0
  124. package/plugins/feishu/plugin.json +29 -0
  125. package/plugins/list-tasks/index.ts +150 -0
  126. package/plugins/list-tasks/plugin.json +9 -0
  127. package/plugins/memory/index.ts +190 -0
  128. package/plugins/memory/plugin.json +7 -0
  129. package/plugins/pause-task/index.ts +95 -0
  130. package/plugins/pause-task/plugin.json +8 -0
  131. package/plugins/register-group/index.ts +147 -0
  132. package/plugins/register-group/plugin.json +7 -0
  133. package/plugins/resume-task/index.ts +92 -0
  134. package/plugins/resume-task/plugin.json +8 -0
  135. package/plugins/schedule-task/index.ts +248 -0
  136. package/plugins/schedule-task/plugin.json +9 -0
  137. package/plugins/send-message/index.ts +75 -0
  138. package/plugins/send-message/plugin.json +9 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * FlashClaw 插件 - 恢复定时任务
3
+ */
4
+
5
+ import { ToolPlugin, ToolContext, ToolResult } from '../../src/plugins/types.js';
6
+ import { getTaskById, updateTask } from '../../src/db.js';
7
+ import { MAIN_GROUP_FOLDER } from '../../src/config.js';
8
+ import { wake } from '../../src/task-scheduler.js';
9
+
10
+ interface ResumeTaskParams {
11
+ task_id: string;
12
+ }
13
+
14
+ const plugin: ToolPlugin = {
15
+ name: 'resume_task',
16
+ version: '1.0.0',
17
+ description: '恢复已暂停的定时任务',
18
+
19
+ schema: {
20
+ name: 'resume_task',
21
+ description: '恢复一个已暂停的定时任务。任务将在下一个调度时间执行。',
22
+ input_schema: {
23
+ type: 'object',
24
+ properties: {
25
+ task_id: {
26
+ type: 'string',
27
+ description: '要恢复的任务 ID,可以通过 list_tasks 获取'
28
+ }
29
+ },
30
+ required: ['task_id']
31
+ }
32
+ },
33
+
34
+ async execute(params: unknown, context: ToolContext): Promise<ToolResult> {
35
+ const { task_id } = params as ResumeTaskParams;
36
+
37
+ if (!task_id || typeof task_id !== 'string') {
38
+ return {
39
+ success: false,
40
+ error: '任务 ID 不能为空'
41
+ };
42
+ }
43
+
44
+ const task = getTaskById(task_id);
45
+
46
+ if (!task) {
47
+ return {
48
+ success: false,
49
+ error: `任务不存在: ${task_id}`
50
+ };
51
+ }
52
+
53
+ // 权限检查
54
+ const isMainGroup = context.groupId === MAIN_GROUP_FOLDER;
55
+ const isOwnTask = task.group_folder === context.groupId;
56
+
57
+ if (!isMainGroup && !isOwnTask) {
58
+ return {
59
+ success: false,
60
+ error: '无权操作其他群组的任务'
61
+ };
62
+ }
63
+
64
+ if (task.status !== 'paused') {
65
+ return {
66
+ success: false,
67
+ error: '只能恢复已暂停的任务'
68
+ };
69
+ }
70
+
71
+ try {
72
+ updateTask(task_id, { status: 'active' });
73
+ // 唤醒调度器重新计算定时器
74
+ wake();
75
+ return {
76
+ success: true,
77
+ data: {
78
+ task_id,
79
+ next_run: task.next_run,
80
+ message: '任务已恢复,将在下一个调度时间执行'
81
+ }
82
+ };
83
+ } catch (error) {
84
+ return {
85
+ success: false,
86
+ error: `恢复任务失败: ${error instanceof Error ? error.message : String(error)}`
87
+ };
88
+ }
89
+ }
90
+ };
91
+
92
+ export default plugin;
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "resume_task",
3
+ "version": "1.0.0",
4
+ "description": "恢复已暂停的定时任务",
5
+ "type": "tool",
6
+ "main": "index.ts",
7
+ "dependencies": []
8
+ }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * FlashClaw 插件 - 创建定时任务
3
+ * 允许 AI Agent 创建定时执行的任务
4
+ */
5
+
6
+ import { ToolPlugin, ToolContext, ToolResult } from '../../src/plugins/types.js';
7
+ import { createTask } from '../../src/db.js';
8
+ import { wake } from '../../src/task-scheduler.js';
9
+ import { CronExpressionParser } from 'cron-parser';
10
+ import { TIMEZONE } from '../../src/config.js';
11
+
12
+ /**
13
+ * 创建任务参数
14
+ */
15
+ interface ScheduleTaskParams {
16
+ /** 任务执行时的提示词 */
17
+ prompt: string;
18
+ /** 调度类型:cron(定时表达式)、interval(间隔执行)、once(一次性) */
19
+ scheduleType: 'cron' | 'interval' | 'once';
20
+ /** 调度值:cron 表达式、毫秒数、或 ISO 时间字符串 */
21
+ scheduleValue: string;
22
+ /** 上下文模式:group(共享群组会话)或 isolated(独立会话) */
23
+ contextMode?: 'group' | 'isolated';
24
+ /** 最大重试次数(默认 3) */
25
+ maxRetries?: number;
26
+ /** 任务执行超时时间(毫秒,默认 300000 = 5分钟) */
27
+ timeoutMs?: number;
28
+ }
29
+
30
+ /**
31
+ * 生成唯一任务 ID
32
+ */
33
+ function generateTaskId(): string {
34
+ return `task_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
35
+ }
36
+
37
+ /**
38
+ * 计算下一次运行时间
39
+ */
40
+ function calculateNextRun(scheduleType: string, scheduleValue: string): string | null {
41
+ const now = new Date();
42
+
43
+ switch (scheduleType) {
44
+ case 'cron': {
45
+ // 解析 cron 表达式,计算下一次运行时间
46
+ const interval = CronExpressionParser.parse(scheduleValue, { tz: TIMEZONE });
47
+ return interval.next().toISOString();
48
+ }
49
+ case 'interval': {
50
+ // 间隔执行,从现在开始计算
51
+ const ms = parseInt(scheduleValue, 10);
52
+ if (isNaN(ms) || ms < 1000) {
53
+ throw new Error('间隔时间必须是大于 1000 的毫秒数');
54
+ }
55
+ return new Date(now.getTime() + ms).toISOString();
56
+ }
57
+ case 'once': {
58
+ // 一次性任务,直接使用指定的时间
59
+ const runTime = new Date(scheduleValue);
60
+ if (isNaN(runTime.getTime())) {
61
+ throw new Error('无效的时间格式,请使用 ISO 8601 格式');
62
+ }
63
+ if (runTime <= now) {
64
+ throw new Error('任务时间必须是将来的时间');
65
+ }
66
+ return runTime.toISOString();
67
+ }
68
+ default:
69
+ throw new Error(`不支持的调度类型: ${scheduleType}`);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * 验证 cron 表达式
75
+ */
76
+ function validateCronExpression(expression: string): boolean {
77
+ try {
78
+ CronExpressionParser.parse(expression);
79
+ return true;
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+
85
+ const plugin: ToolPlugin = {
86
+ name: 'schedule_task',
87
+ version: '1.0.0',
88
+ description: '创建定时任务,支持 cron 表达式、固定间隔或一次性执行',
89
+
90
+ schema: {
91
+ name: 'schedule_task',
92
+ description: `创建定时任务。支持三种调度方式:
93
+ 1. cron - 使用 cron 表达式(如 "0 9 * * *" 每天 9 点)
94
+ 2. interval - 固定间隔(毫秒数,如 "3600000" 每小时)
95
+ 3. once - 一次性任务(ISO 时间,如 "2024-12-31T23:59:59Z")
96
+
97
+ 常用 cron 示例:
98
+ - "0 9 * * *" - 每天早上 9 点
99
+ - "0 9 * * 1" - 每周一早上 9 点
100
+ - "0 0 1 * *" - 每月 1 日零点
101
+ - "*/30 * * * *" - 每 30 分钟`,
102
+ input_schema: {
103
+ type: 'object',
104
+ properties: {
105
+ prompt: {
106
+ type: 'string',
107
+ description: '任务执行时的提示词,描述需要 AI 做什么'
108
+ },
109
+ scheduleType: {
110
+ type: 'string',
111
+ enum: ['cron', 'interval', 'once'],
112
+ description: '调度类型:cron(定时表达式)、interval(固定间隔)、once(一次性)'
113
+ },
114
+ scheduleValue: {
115
+ type: 'string',
116
+ description: '调度值。cron 类型填 cron 表达式;interval 类型填毫秒数;once 类型填 ISO 8601 时间'
117
+ },
118
+ contextMode: {
119
+ type: 'string',
120
+ enum: ['group', 'isolated'],
121
+ description: '上下文模式。group 表示共享群组会话历史,isolated 表示独立会话(默认)'
122
+ },
123
+ maxRetries: {
124
+ type: 'number',
125
+ description: '最大重试次数(默认 3)。任务失败后会自动重试,使用指数退避策略'
126
+ },
127
+ timeoutMs: {
128
+ type: 'number',
129
+ description: '任务执行超时时间(毫秒,默认 300000 = 5分钟)。超时后任务会被标记为失败并触发重试'
130
+ }
131
+ },
132
+ required: ['prompt', 'scheduleType', 'scheduleValue']
133
+ }
134
+ },
135
+
136
+ async execute(params: unknown, context: ToolContext): Promise<ToolResult> {
137
+ const {
138
+ prompt,
139
+ scheduleType,
140
+ scheduleValue,
141
+ contextMode = 'isolated',
142
+ maxRetries = 3,
143
+ timeoutMs = 300000
144
+ } = params as ScheduleTaskParams;
145
+
146
+ // 参数验证
147
+ if (!prompt || typeof prompt !== 'string') {
148
+ return {
149
+ success: false,
150
+ error: '任务提示词不能为空'
151
+ };
152
+ }
153
+
154
+ if (!['cron', 'interval', 'once'].includes(scheduleType)) {
155
+ return {
156
+ success: false,
157
+ error: '调度类型必须是 cron、interval 或 once'
158
+ };
159
+ }
160
+
161
+ if (!scheduleValue || typeof scheduleValue !== 'string') {
162
+ return {
163
+ success: false,
164
+ error: '调度值不能为空'
165
+ };
166
+ }
167
+
168
+ // 验证 cron 表达式
169
+ if (scheduleType === 'cron' && !validateCronExpression(scheduleValue)) {
170
+ return {
171
+ success: false,
172
+ error: `无效的 cron 表达式: ${scheduleValue}`
173
+ };
174
+ }
175
+
176
+ // 验证 maxRetries 范围
177
+ if (maxRetries < 0 || maxRetries > 10) {
178
+ return {
179
+ success: false,
180
+ error: '最大重试次数必须在 0-10 之间'
181
+ };
182
+ }
183
+
184
+ // 验证 timeoutMs 范围
185
+ if (timeoutMs < 1000 || timeoutMs > 30 * 60 * 1000) {
186
+ return {
187
+ success: false,
188
+ error: '超时时间必须在 1秒 到 30分钟 之间'
189
+ };
190
+ }
191
+
192
+ try {
193
+ // 计算下一次运行时间
194
+ const nextRun = calculateNextRun(scheduleType, scheduleValue);
195
+
196
+ // 生成任务 ID
197
+ const taskId = generateTaskId();
198
+
199
+ // 创建任务
200
+ createTask({
201
+ id: taskId,
202
+ group_folder: context.groupId,
203
+ chat_jid: context.chatId,
204
+ prompt,
205
+ schedule_type: scheduleType,
206
+ schedule_value: scheduleValue,
207
+ context_mode: contextMode,
208
+ next_run: nextRun,
209
+ status: 'active',
210
+ created_at: new Date().toISOString(),
211
+ retry_count: 0,
212
+ max_retries: maxRetries,
213
+ timeout_ms: timeoutMs
214
+ });
215
+
216
+ // 唤醒调度器,重新计算定时器
217
+ wake();
218
+
219
+ // 格式化下一次运行时间的友好显示
220
+ const nextRunDate = nextRun ? new Date(nextRun) : null;
221
+ const nextRunDisplay = nextRunDate
222
+ ? nextRunDate.toLocaleString('zh-CN', { timeZone: TIMEZONE })
223
+ : '未知';
224
+
225
+ return {
226
+ success: true,
227
+ data: {
228
+ taskId,
229
+ prompt,
230
+ scheduleType,
231
+ scheduleValue,
232
+ contextMode,
233
+ maxRetries,
234
+ timeoutMs,
235
+ nextRun: nextRunDisplay,
236
+ status: 'active'
237
+ }
238
+ };
239
+ } catch (error) {
240
+ return {
241
+ success: false,
242
+ error: `创建任务失败: ${error instanceof Error ? error.message : String(error)}`
243
+ };
244
+ }
245
+ }
246
+ };
247
+
248
+ export default plugin;
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "schedule-task",
3
+ "version": "1.0.0",
4
+ "type": "tool",
5
+ "description": "创建定时任务",
6
+ "main": "index.ts"
7
+ }
8
+
9
+
@@ -0,0 +1,75 @@
1
+ /**
2
+ * FlashClaw 插件 - 发送消息
3
+ * 允许 AI Agent 主动发送消息到聊天
4
+ */
5
+
6
+ import { ToolPlugin, ToolContext, ToolResult } from '../../src/plugins/types.js';
7
+
8
+ /**
9
+ * 发送消息参数
10
+ */
11
+ interface SendMessageParams {
12
+ /** 要发送的消息内容 */
13
+ content: string;
14
+ }
15
+
16
+ const plugin: ToolPlugin = {
17
+ name: 'send_message',
18
+ version: '1.0.0',
19
+ description: '发送消息到当前聊天',
20
+
21
+ schema: {
22
+ name: 'send_message',
23
+ description: '发送消息到当前聊天。用于主动通知用户、回复消息或发送执行结果。',
24
+ input_schema: {
25
+ type: 'object',
26
+ properties: {
27
+ content: {
28
+ type: 'string',
29
+ description: '要发送的消息内容,支持文本格式'
30
+ }
31
+ },
32
+ required: ['content']
33
+ }
34
+ },
35
+
36
+ async execute(params: unknown, context: ToolContext): Promise<ToolResult> {
37
+ const { content } = params as SendMessageParams;
38
+
39
+ // 验证参数
40
+ if (!content || typeof content !== 'string') {
41
+ return {
42
+ success: false,
43
+ error: '消息内容不能为空'
44
+ };
45
+ }
46
+
47
+ if (content.length > 10000) {
48
+ return {
49
+ success: false,
50
+ error: '消息内容过长,最大支持 10000 字符'
51
+ };
52
+ }
53
+
54
+ try {
55
+ // 使用上下文提供的 sendMessage 方法发送消息到当前聊天
56
+ await context.sendMessage(content);
57
+
58
+ return {
59
+ success: true,
60
+ data: {
61
+ chatId: context.chatId,
62
+ contentLength: content.length,
63
+ sent: true
64
+ }
65
+ };
66
+ } catch (error) {
67
+ return {
68
+ success: false,
69
+ error: `发送消息失败: ${error instanceof Error ? error.message : String(error)}`
70
+ };
71
+ }
72
+ }
73
+ };
74
+
75
+ export default plugin;
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "send-message",
3
+ "version": "1.0.0",
4
+ "type": "tool",
5
+ "description": "发送消息到聊天",
6
+ "main": "index.ts"
7
+ }
8
+
9
+