flashclaw 1.7.1 → 1.9.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.
- package/README.md +115 -45
- package/dist/agent-registry.d.ts.map +1 -0
- package/dist/agent-registry.js.map +1 -0
- package/dist/agent-runner.d.ts +2 -0
- package/dist/agent-runner.d.ts.map +1 -1
- package/dist/agent-runner.js +280 -36
- package/dist/agent-runner.js.map +1 -1
- package/dist/channel-manager.d.ts.map +1 -1
- package/dist/channel-manager.js +17 -9
- package/dist/channel-manager.js.map +1 -1
- package/dist/cli-ink.d.ts +11 -0
- package/dist/cli-ink.d.ts.map +1 -0
- package/dist/cli-ink.js +495 -0
- package/dist/cli-ink.js.map +1 -0
- package/dist/cli.js +18 -355
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +2 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +92 -4
- package/dist/commands.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/context-guard.d.ts +3 -3
- package/dist/core/context-guard.d.ts.map +1 -1
- package/dist/core/context-guard.js +32 -18
- package/dist/core/context-guard.js.map +1 -1
- package/dist/core/memory.d.ts +54 -31
- package/dist/core/memory.d.ts.map +1 -1
- package/dist/core/memory.js +233 -97
- package/dist/core/memory.js.map +1 -1
- package/dist/core/model-capabilities.d.ts.map +1 -1
- package/dist/core/model-capabilities.js +4 -2
- package/dist/core/model-capabilities.js.map +1 -1
- package/dist/core-api.d.ts +117 -0
- package/dist/core-api.d.ts.map +1 -0
- package/dist/core-api.js +218 -0
- package/dist/core-api.js.map +1 -0
- package/dist/health.js +1 -1
- package/dist/health.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +160 -78
- package/dist/index.js.map +1 -1
- package/dist/message-queue.js +1 -1
- package/dist/message-queue.js.map +1 -1
- package/dist/paths.d.ts +4 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +7 -0
- package/dist/paths.js.map +1 -1
- package/dist/plugins/loader.js +4 -4
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/manager.d.ts.map +1 -1
- package/dist/plugins/manager.js +34 -13
- package/dist/plugins/manager.js.map +1 -1
- package/dist/plugins/types.d.ts +3 -0
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/plugins/types.js.map +1 -1
- package/dist/soul-manager.d.ts +42 -0
- package/dist/soul-manager.d.ts.map +1 -0
- package/dist/soul-manager.js +203 -0
- package/dist/soul-manager.js.map +1 -0
- package/dist/task-scheduler.d.ts.map +1 -1
- package/dist/task-scheduler.js +41 -24
- package/dist/task-scheduler.js.map +1 -1
- package/dist/tool-params.d.ts +13 -0
- package/dist/tool-params.d.ts.map +1 -0
- package/dist/tool-params.js +239 -0
- package/dist/tool-params.js.map +1 -0
- package/dist/types.d.ts +33 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/plugins/anthropic-provider/index.ts +188 -6
- package/plugins/memory/index.ts +68 -35
- package/plugins/cancel-task/index.ts +0 -161
- package/plugins/cancel-task/plugin.json +0 -9
- package/plugins/cli-channel/index.ts +0 -51
- package/plugins/cli-channel/plugin.json +0 -8
- package/plugins/list-tasks/index.ts +0 -150
- package/plugins/list-tasks/plugin.json +0 -9
- package/plugins/pause-task/index.ts +0 -95
- package/plugins/pause-task/plugin.json +0 -8
- package/plugins/register-group/index.ts +0 -147
- package/plugins/register-group/plugin.json +0 -7
- package/plugins/resume-task/index.ts +0 -92
- package/plugins/resume-task/plugin.json +0 -8
- package/plugins/schedule-task/index.ts +0 -248
- package/plugins/schedule-task/plugin.json +0 -9
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FlashClaw 插件 - 列出定时任务
|
|
3
|
-
* 查看当前群组或所有群组的定时任务
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ToolPlugin, ToolContext, ToolResult } from '../../src/plugins/types.js';
|
|
7
|
-
import { getTasksForGroup, getAllTasks, getTaskRunLogs } from '../../src/db.js';
|
|
8
|
-
import { TIMEZONE, MAIN_GROUP_FOLDER } from '../../src/config.js';
|
|
9
|
-
import { ScheduledTask } from '../../src/types.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 列出任务参数
|
|
13
|
-
*/
|
|
14
|
-
interface ListTasksParams {
|
|
15
|
-
/** 是否列出所有群组的任务(仅 main 群组可用) */
|
|
16
|
-
all?: boolean;
|
|
17
|
-
/** 任务状态过滤 */
|
|
18
|
-
status?: 'active' | 'paused' | 'completed' | 'all';
|
|
19
|
-
/** 是否包含最近运行记录 */
|
|
20
|
-
includeRunLogs?: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 格式化任务信息
|
|
25
|
-
*/
|
|
26
|
-
function formatTask(task: ScheduledTask, includeRunLogs: boolean = false): Record<string, unknown> {
|
|
27
|
-
const formatted: Record<string, unknown> = {
|
|
28
|
-
id: task.id,
|
|
29
|
-
prompt: task.prompt.length > 100 ? task.prompt.slice(0, 100) + '...' : task.prompt,
|
|
30
|
-
scheduleType: task.schedule_type,
|
|
31
|
-
scheduleValue: task.schedule_value,
|
|
32
|
-
status: task.status,
|
|
33
|
-
groupFolder: task.group_folder,
|
|
34
|
-
chatId: task.chat_jid,
|
|
35
|
-
contextMode: task.context_mode,
|
|
36
|
-
createdAt: formatDateTime(task.created_at)
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
if (task.next_run) {
|
|
40
|
-
formatted.nextRun = formatDateTime(task.next_run);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (task.last_run) {
|
|
44
|
-
formatted.lastRun = formatDateTime(task.last_run);
|
|
45
|
-
formatted.lastResult = task.last_result;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// 获取最近运行记录
|
|
49
|
-
if (includeRunLogs) {
|
|
50
|
-
const logs = getTaskRunLogs(task.id, 3);
|
|
51
|
-
if (logs.length > 0) {
|
|
52
|
-
formatted.recentRuns = logs.map(log => ({
|
|
53
|
-
runAt: formatDateTime(log.run_at),
|
|
54
|
-
status: log.status,
|
|
55
|
-
durationMs: log.duration_ms,
|
|
56
|
-
result: log.result ? (log.result.length > 50 ? log.result.slice(0, 50) + '...' : log.result) : null,
|
|
57
|
-
error: log.error
|
|
58
|
-
}));
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return formatted;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 格式化日期时间为可读格式
|
|
67
|
-
*/
|
|
68
|
-
function formatDateTime(isoString: string): string {
|
|
69
|
-
const date = new Date(isoString);
|
|
70
|
-
return date.toLocaleString('zh-CN', { timeZone: TIMEZONE });
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const plugin: ToolPlugin = {
|
|
74
|
-
name: 'list_tasks',
|
|
75
|
-
version: '1.0.0',
|
|
76
|
-
description: '列出定时任务,查看任务状态和运行记录',
|
|
77
|
-
|
|
78
|
-
schema: {
|
|
79
|
-
name: 'list_tasks',
|
|
80
|
-
description: '列出定时任务。默认只显示当前群组的任务,main 群组可以查看所有任务。',
|
|
81
|
-
input_schema: {
|
|
82
|
-
type: 'object',
|
|
83
|
-
properties: {
|
|
84
|
-
all: {
|
|
85
|
-
type: 'boolean',
|
|
86
|
-
description: '是否列出所有群组的任务(仅 main 群组有权限)'
|
|
87
|
-
},
|
|
88
|
-
status: {
|
|
89
|
-
type: 'string',
|
|
90
|
-
enum: ['active', 'paused', 'completed', 'all'],
|
|
91
|
-
description: '按状态过滤任务。默认显示所有状态'
|
|
92
|
-
},
|
|
93
|
-
includeRunLogs: {
|
|
94
|
-
type: 'boolean',
|
|
95
|
-
description: '是否包含最近 3 次运行记录'
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
async execute(params: unknown, context: ToolContext): Promise<ToolResult> {
|
|
102
|
-
const { all = false, status = 'all', includeRunLogs = false } = (params || {}) as ListTasksParams;
|
|
103
|
-
|
|
104
|
-
const isMainGroup = context.groupId === MAIN_GROUP_FOLDER;
|
|
105
|
-
|
|
106
|
-
// 获取任务列表
|
|
107
|
-
let tasks: ScheduledTask[];
|
|
108
|
-
|
|
109
|
-
if (all && isMainGroup) {
|
|
110
|
-
// main 群组可以查看所有任务
|
|
111
|
-
tasks = getAllTasks();
|
|
112
|
-
} else if (all && !isMainGroup) {
|
|
113
|
-
return {
|
|
114
|
-
success: false,
|
|
115
|
-
error: '只有 main 群组可以查看所有群组的任务'
|
|
116
|
-
};
|
|
117
|
-
} else {
|
|
118
|
-
// 只查看当前群组的任务
|
|
119
|
-
tasks = getTasksForGroup(context.groupId);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// 按状态过滤
|
|
123
|
-
if (status !== 'all') {
|
|
124
|
-
tasks = tasks.filter(task => task.status === status);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// 格式化任务列表
|
|
128
|
-
const formattedTasks = tasks.map(task => formatTask(task, includeRunLogs));
|
|
129
|
-
|
|
130
|
-
// 统计信息
|
|
131
|
-
const stats = {
|
|
132
|
-
total: tasks.length,
|
|
133
|
-
active: tasks.filter(t => t.status === 'active').length,
|
|
134
|
-
paused: tasks.filter(t => t.status === 'paused').length,
|
|
135
|
-
completed: tasks.filter(t => t.status === 'completed').length
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
success: true,
|
|
140
|
-
data: {
|
|
141
|
-
tasks: formattedTasks,
|
|
142
|
-
stats,
|
|
143
|
-
scope: all ? 'all_groups' : 'current_group',
|
|
144
|
-
groupId: context.groupId
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export default plugin;
|
|
@@ -1,95 +0,0 @@
|
|
|
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
|
-
|
|
9
|
-
interface PauseTaskParams {
|
|
10
|
-
task_id: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const plugin: ToolPlugin = {
|
|
14
|
-
name: 'pause_task',
|
|
15
|
-
version: '1.0.0',
|
|
16
|
-
description: '暂停定时任务',
|
|
17
|
-
|
|
18
|
-
schema: {
|
|
19
|
-
name: 'pause_task',
|
|
20
|
-
description: '暂停一个定时任务。暂停后任务不会执行,直到使用 resume_task 恢复。',
|
|
21
|
-
input_schema: {
|
|
22
|
-
type: 'object',
|
|
23
|
-
properties: {
|
|
24
|
-
task_id: {
|
|
25
|
-
type: 'string',
|
|
26
|
-
description: '要暂停的任务 ID,可以通过 list_tasks 获取'
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
required: ['task_id']
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
async execute(params: unknown, context: ToolContext): Promise<ToolResult> {
|
|
34
|
-
const { task_id } = params as PauseTaskParams;
|
|
35
|
-
|
|
36
|
-
if (!task_id || typeof task_id !== 'string') {
|
|
37
|
-
return {
|
|
38
|
-
success: false,
|
|
39
|
-
error: '任务 ID 不能为空'
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const task = getTaskById(task_id);
|
|
44
|
-
|
|
45
|
-
if (!task) {
|
|
46
|
-
return {
|
|
47
|
-
success: false,
|
|
48
|
-
error: `任务不存在: ${task_id}`
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 权限检查
|
|
53
|
-
const isMainGroup = context.groupId === MAIN_GROUP_FOLDER;
|
|
54
|
-
const isOwnTask = task.group_folder === context.groupId;
|
|
55
|
-
|
|
56
|
-
if (!isMainGroup && !isOwnTask) {
|
|
57
|
-
return {
|
|
58
|
-
success: false,
|
|
59
|
-
error: '无权操作其他群组的任务'
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (task.status === 'paused') {
|
|
64
|
-
return {
|
|
65
|
-
success: false,
|
|
66
|
-
error: '任务已经是暂停状态'
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (task.status === 'completed') {
|
|
71
|
-
return {
|
|
72
|
-
success: false,
|
|
73
|
-
error: '已完成的任务无法暂停'
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
updateTask(task_id, { status: 'paused' });
|
|
79
|
-
return {
|
|
80
|
-
success: true,
|
|
81
|
-
data: {
|
|
82
|
-
task_id,
|
|
83
|
-
message: '任务已暂停,使用 resume_task 可以恢复执行'
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
} catch (error) {
|
|
87
|
-
return {
|
|
88
|
-
success: false,
|
|
89
|
-
error: `暂停任务失败: ${error instanceof Error ? error.message : String(error)}`
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
export default plugin;
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FlashClaw 插件 - 注册群组
|
|
3
|
-
* 允许 AI Agent 注册新的聊天群组
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ToolPlugin, ToolContext, ToolResult } from '../../src/plugins/types.js';
|
|
7
|
-
import { MAIN_GROUP_FOLDER } from '../../src/config.js';
|
|
8
|
-
import * as fs from 'node:fs';
|
|
9
|
-
import * as path from 'node:path';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 注册群组参数
|
|
13
|
-
*/
|
|
14
|
-
interface RegisterGroupParams {
|
|
15
|
-
/** 聊天 ID(如 "oc_xxxxxxxx") */
|
|
16
|
-
jid: string;
|
|
17
|
-
/** 群组显示名称 */
|
|
18
|
-
name: string;
|
|
19
|
-
/** 群组文件夹名称(小写,用连字符分隔) */
|
|
20
|
-
folder: string;
|
|
21
|
-
/** 触发词(如 "@Andy") */
|
|
22
|
-
trigger: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const plugin: ToolPlugin = {
|
|
26
|
-
name: 'register_group',
|
|
27
|
-
version: '1.0.0',
|
|
28
|
-
description: '注册新的聊天群组',
|
|
29
|
-
|
|
30
|
-
schema: {
|
|
31
|
-
name: 'register_group',
|
|
32
|
-
description: `注册新的聊天群组,使机器人可以响应该群组的消息。
|
|
33
|
-
仅限 main 群组使用。文件夹名称应使用小写字母和连字符(如 "family-chat")。`,
|
|
34
|
-
input_schema: {
|
|
35
|
-
type: 'object',
|
|
36
|
-
properties: {
|
|
37
|
-
jid: {
|
|
38
|
-
type: 'string',
|
|
39
|
-
description: '聊天 ID(如 "oc_xxxxxxxx")'
|
|
40
|
-
},
|
|
41
|
-
name: {
|
|
42
|
-
type: 'string',
|
|
43
|
-
description: '群组显示名称'
|
|
44
|
-
},
|
|
45
|
-
folder: {
|
|
46
|
-
type: 'string',
|
|
47
|
-
description: '群组文件夹名称(小写,用连字符分隔)'
|
|
48
|
-
},
|
|
49
|
-
trigger: {
|
|
50
|
-
type: 'string',
|
|
51
|
-
description: '触发词(如 "@Andy")'
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
required: ['jid', 'name', 'folder', 'trigger']
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
async execute(params: unknown, context: ToolContext): Promise<ToolResult> {
|
|
59
|
-
const { jid, name, folder, trigger } = params as RegisterGroupParams;
|
|
60
|
-
|
|
61
|
-
// 权限检查:只有 main 群组可以注册新群组
|
|
62
|
-
if (context.groupId !== MAIN_GROUP_FOLDER) {
|
|
63
|
-
return {
|
|
64
|
-
success: false,
|
|
65
|
-
error: '只有 main 群组可以注册新群组'
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 参数验证
|
|
70
|
-
if (!jid || typeof jid !== 'string') {
|
|
71
|
-
return {
|
|
72
|
-
success: false,
|
|
73
|
-
error: 'jid(聊天 ID)不能为空'
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (!name || typeof name !== 'string') {
|
|
78
|
-
return {
|
|
79
|
-
success: false,
|
|
80
|
-
error: 'name(群组名称)不能为空'
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!folder || typeof folder !== 'string') {
|
|
85
|
-
return {
|
|
86
|
-
success: false,
|
|
87
|
-
error: 'folder(文件夹名称)不能为空'
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (!trigger || typeof trigger !== 'string') {
|
|
92
|
-
return {
|
|
93
|
-
success: false,
|
|
94
|
-
error: 'trigger(触发词)不能为空'
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 验证 folder 格式
|
|
99
|
-
if (!/^[a-z0-9-]+$/.test(folder)) {
|
|
100
|
-
return {
|
|
101
|
-
success: false,
|
|
102
|
-
error: 'folder 只能包含小写字母、数字和连字符'
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// 通过 IPC 写入注册请求
|
|
107
|
-
const ipcDir = path.join(process.cwd(), 'data', 'ipc', context.groupId, 'tasks');
|
|
108
|
-
fs.mkdirSync(ipcDir, { recursive: true });
|
|
109
|
-
|
|
110
|
-
const data = {
|
|
111
|
-
type: 'register_group',
|
|
112
|
-
jid,
|
|
113
|
-
name,
|
|
114
|
-
folder,
|
|
115
|
-
trigger,
|
|
116
|
-
timestamp: new Date().toISOString()
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const filename = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`;
|
|
120
|
-
const filepath = path.join(ipcDir, filename);
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
// 原子写入
|
|
124
|
-
const tempPath = `${filepath}.tmp`;
|
|
125
|
-
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2));
|
|
126
|
-
fs.renameSync(tempPath, filepath);
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
success: true,
|
|
130
|
-
data: {
|
|
131
|
-
jid,
|
|
132
|
-
name,
|
|
133
|
-
folder,
|
|
134
|
-
trigger,
|
|
135
|
-
message: `群组 "${name}" 已注册,机器人将开始响应该群组的消息`
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
} catch (error) {
|
|
139
|
-
return {
|
|
140
|
-
success: false,
|
|
141
|
-
error: `注册失败: ${error instanceof Error ? error.message : String(error)}`
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
export default plugin;
|
|
@@ -1,92 +0,0 @@
|
|
|
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;
|