clawflowbang 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.
- package/.eslintrc.json +38 -0
- package/README.md +1 -0
- package/__tests__/config-manager.test.js +52 -0
- package/__tests__/cron-format.test.js +26 -0
- package/__tests__/cron-manager.local.test.js +65 -0
- package/__tests__/openclaw-cli.test.js +51 -0
- package/bin/clawflowhub.js +125 -0
- package/docs/clawhub-package-format.md +179 -0
- package/examples/npm-package-example/package.json +53 -0
- package/package.json +45 -0
- package/src/commands/cron.js +123 -0
- package/src/commands/init.js +112 -0
- package/src/commands/install.js +38 -0
- package/src/commands/list.js +77 -0
- package/src/commands/remove.js +27 -0
- package/src/commands/search.js +61 -0
- package/src/commands/status.js +68 -0
- package/src/core/ConfigManager.js +295 -0
- package/src/core/CronFormat.js +68 -0
- package/src/core/CronManager.js +512 -0
- package/src/core/Installer.js +352 -0
- package/src/core/NPMRegistry.js +285 -0
- package/src/core/OpenClawCLI.js +265 -0
- package/src/core/PackageResolver.js +94 -0
- package/src/core/Registry.js +400 -0
- package/src/index.js +91 -0
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CronManager - จัดการ cronjobs
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs-extra');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const cron = require('node-cron');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const OpenClawCLI = require('./OpenClawCLI');
|
|
10
|
+
const { normalizeCronExpression } = require('./CronFormat');
|
|
11
|
+
|
|
12
|
+
class CronManager {
|
|
13
|
+
constructor(configManager) {
|
|
14
|
+
this.configManager = configManager;
|
|
15
|
+
this.tasks = new Map();
|
|
16
|
+
this.jobsFile = configManager.getCronJobsFilePath();
|
|
17
|
+
this.openclawCLI = new OpenClawCLI(configManager);
|
|
18
|
+
this.useOpenClawCron = this.openclawCLI.hasOpenClaw();
|
|
19
|
+
|
|
20
|
+
if (!this.useOpenClawCron) {
|
|
21
|
+
this.ensureJobsFile();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* สร้างไฟล์ jobs ถ้ายังไม่มี
|
|
27
|
+
*/
|
|
28
|
+
ensureJobsFile() {
|
|
29
|
+
fs.ensureDirSync(path.dirname(this.jobsFile));
|
|
30
|
+
if (!fs.existsSync(this.jobsFile)) {
|
|
31
|
+
fs.writeJsonSync(this.jobsFile, { jobs: [] }, { spaces: 2 });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* อ่านรายการ jobs
|
|
37
|
+
*/
|
|
38
|
+
getJobs() {
|
|
39
|
+
if (!fs.existsSync(this.jobsFile)) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const data = fs.readJsonSync(this.jobsFile);
|
|
44
|
+
return data.jobs || [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* บันทึกรายการ jobs
|
|
49
|
+
*/
|
|
50
|
+
saveJobs(jobs) {
|
|
51
|
+
fs.writeJsonSync(this.jobsFile, { jobs }, { spaces: 2 });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* เพิ่ม cronjob
|
|
56
|
+
*/
|
|
57
|
+
async add(skillName, schedule, params = {}, description = '') {
|
|
58
|
+
const normalizedSchedule = normalizeCronExpression(schedule);
|
|
59
|
+
|
|
60
|
+
if (this.useOpenClawCron) {
|
|
61
|
+
const uniqueName = `cfh:${skillName}:${Date.now()}`;
|
|
62
|
+
const message = `Run skill "${skillName}" with params: ${JSON.stringify(params)}`;
|
|
63
|
+
const created = await this.openclawCLI.addCronJob({
|
|
64
|
+
name: uniqueName,
|
|
65
|
+
description: description || `Run ${skillName}`,
|
|
66
|
+
schedule: normalizedSchedule,
|
|
67
|
+
message,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
let jobId = created.jobId;
|
|
71
|
+
if (!jobId) {
|
|
72
|
+
const jobs = await this.openclawCLI.listCronJobs();
|
|
73
|
+
const matched = jobs.find((job) => job.name === uniqueName);
|
|
74
|
+
jobId = matched?.id || null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!jobId) {
|
|
78
|
+
throw new Error('สร้าง cronjob ผ่าน openclaw สำเร็จ แต่ไม่สามารถระบุ job id ได้');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.configManager.addCron({
|
|
82
|
+
id: jobId,
|
|
83
|
+
skill: skillName,
|
|
84
|
+
schedule: normalizedSchedule,
|
|
85
|
+
description: description || `Run ${skillName}`,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
console.log(chalk.green(`✓ เพิ่ม cronjob (openclaw): ${skillName} (${normalizedSchedule})`));
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
id: jobId,
|
|
92
|
+
skill: skillName,
|
|
93
|
+
schedule: normalizedSchedule,
|
|
94
|
+
params,
|
|
95
|
+
description: description || `Run ${skillName}`,
|
|
96
|
+
enabled: true,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const jobs = this.getJobs();
|
|
101
|
+
const jobId = `cron_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
102
|
+
|
|
103
|
+
const job = {
|
|
104
|
+
id: jobId,
|
|
105
|
+
skill: skillName,
|
|
106
|
+
schedule: normalizedSchedule,
|
|
107
|
+
params,
|
|
108
|
+
description: description || `Run ${skillName}`,
|
|
109
|
+
enabled: true,
|
|
110
|
+
createdAt: new Date().toISOString(),
|
|
111
|
+
lastRun: null,
|
|
112
|
+
nextRun: this.getNextRun(normalizedSchedule),
|
|
113
|
+
runCount: 0,
|
|
114
|
+
errorCount: 0,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
jobs.push(job);
|
|
118
|
+
this.saveJobs(jobs);
|
|
119
|
+
|
|
120
|
+
// บันทึกลง config ด้วย
|
|
121
|
+
this.configManager.addCron({
|
|
122
|
+
id: jobId,
|
|
123
|
+
skill: skillName,
|
|
124
|
+
schedule: normalizedSchedule,
|
|
125
|
+
description,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// สร้าง cron script
|
|
129
|
+
this.createCronScript(job);
|
|
130
|
+
|
|
131
|
+
// เริ่มต้น task (ถ้าเปิดใช้งาน)
|
|
132
|
+
if (job.enabled) {
|
|
133
|
+
this.startJob(job);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
console.log(chalk.green(`✓ เพิ่ม cronjob: ${skillName} (${normalizedSchedule})`));
|
|
137
|
+
|
|
138
|
+
return job;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* แก้ไข cronjob
|
|
143
|
+
*/
|
|
144
|
+
async edit(jobId, updates = {}) {
|
|
145
|
+
const normalized = { ...updates };
|
|
146
|
+
|
|
147
|
+
if (updates.schedule) {
|
|
148
|
+
normalized.schedule = normalizeCronExpression(updates.schedule);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (this.useOpenClawCron) {
|
|
152
|
+
const tracked = this.configManager.getCrons().find((c) => c.id === jobId);
|
|
153
|
+
const message =
|
|
154
|
+
Object.prototype.hasOwnProperty.call(updates, 'params') && tracked?.skill
|
|
155
|
+
? `Run skill "${tracked.skill}" with params: ${JSON.stringify(updates.params || {})}`
|
|
156
|
+
: undefined;
|
|
157
|
+
|
|
158
|
+
if (Object.prototype.hasOwnProperty.call(updates, 'params') && !tracked?.skill) {
|
|
159
|
+
throw new Error('แก้ไข params ไม่ได้ เพราะไม่พบ mapping skill ของ cron นี้ใน config');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
await this.openclawCLI.editCronJob(jobId, {
|
|
163
|
+
schedule: normalized.schedule,
|
|
164
|
+
description: normalized.description,
|
|
165
|
+
message,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
this.configManager.updateCron(jobId, {
|
|
169
|
+
...(normalized.schedule ? { schedule: normalized.schedule } : {}),
|
|
170
|
+
...(typeof normalized.description === 'string' ? { description: normalized.description } : {}),
|
|
171
|
+
...(Object.prototype.hasOwnProperty.call(updates, 'params') ? { params: updates.params } : {}),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
return { id: jobId, ...normalized };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const jobs = this.getJobs();
|
|
178
|
+
const job = jobs.find((j) => j.id === jobId);
|
|
179
|
+
|
|
180
|
+
if (!job) {
|
|
181
|
+
throw new Error(`ไม่พบ cronjob ID: ${jobId}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (normalized.schedule) {
|
|
185
|
+
job.schedule = normalized.schedule;
|
|
186
|
+
job.nextRun = this.getNextRun(normalized.schedule);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (typeof normalized.description === 'string') {
|
|
190
|
+
job.description = normalized.description;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (Object.prototype.hasOwnProperty.call(updates, 'params')) {
|
|
194
|
+
job.params = updates.params || {};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
this.saveJobs(jobs);
|
|
198
|
+
this.configManager.updateCron(jobId, {
|
|
199
|
+
...(normalized.schedule ? { schedule: normalized.schedule } : {}),
|
|
200
|
+
...(typeof normalized.description === 'string' ? { description: normalized.description } : {}),
|
|
201
|
+
...(Object.prototype.hasOwnProperty.call(updates, 'params') ? { params: updates.params } : {}),
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
return job;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* ลบ cronjob
|
|
209
|
+
*/
|
|
210
|
+
async remove(jobId) {
|
|
211
|
+
if (this.useOpenClawCron) {
|
|
212
|
+
await this.openclawCLI.removeCronJob(jobId);
|
|
213
|
+
this.configManager.removeCron(jobId);
|
|
214
|
+
console.log(chalk.green(`✓ ลบ cronjob (openclaw): ${jobId}`));
|
|
215
|
+
return { success: true, removed: { id: jobId } };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
let jobs = this.getJobs();
|
|
219
|
+
const job = jobs.find(j => j.id === jobId);
|
|
220
|
+
|
|
221
|
+
if (!job) {
|
|
222
|
+
throw new Error(`ไม่พบ cronjob ID: ${jobId}`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// หยุด task
|
|
226
|
+
this.stopJob(jobId);
|
|
227
|
+
|
|
228
|
+
// ลบไฟล์ script
|
|
229
|
+
this.removeCronScript(jobId);
|
|
230
|
+
|
|
231
|
+
// ลบจากรายการ
|
|
232
|
+
jobs = jobs.filter(j => j.id !== jobId);
|
|
233
|
+
this.saveJobs(jobs);
|
|
234
|
+
|
|
235
|
+
// ลบจาก config
|
|
236
|
+
this.configManager.removeCron(jobId);
|
|
237
|
+
|
|
238
|
+
console.log(chalk.green(`✓ ลบ cronjob: ${job.skill}`));
|
|
239
|
+
|
|
240
|
+
return { success: true, removed: job };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* แสดงรายการ cronjobs
|
|
245
|
+
*/
|
|
246
|
+
list() {
|
|
247
|
+
if (this.useOpenClawCron) {
|
|
248
|
+
return this.listViaOpenClaw();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const jobs = this.getJobs();
|
|
252
|
+
|
|
253
|
+
if (jobs.length === 0) {
|
|
254
|
+
console.log(chalk.gray('ไม่มี cronjob ที่ตั้งไว้'));
|
|
255
|
+
return [];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return jobs.map(job => ({
|
|
259
|
+
id: job.id,
|
|
260
|
+
skill: job.skill,
|
|
261
|
+
schedule: job.schedule,
|
|
262
|
+
description: job.description,
|
|
263
|
+
enabled: job.enabled,
|
|
264
|
+
lastRun: job.lastRun,
|
|
265
|
+
nextRun: job.nextRun,
|
|
266
|
+
runCount: job.runCount,
|
|
267
|
+
}));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* แสดงรายการ cronjobs ผ่าน OpenClaw CLI
|
|
272
|
+
*/
|
|
273
|
+
async listViaOpenClaw() {
|
|
274
|
+
const jobs = await this.openclawCLI.listCronJobs();
|
|
275
|
+
|
|
276
|
+
if (!jobs || jobs.length === 0) {
|
|
277
|
+
console.log(chalk.gray('ไม่มี cronjob ที่ตั้งไว้'));
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return jobs.map((job) => ({
|
|
282
|
+
id: job.id,
|
|
283
|
+
skill: job.name || 'unknown',
|
|
284
|
+
schedule: job.schedule?.expr || job.schedule?.kind || '-',
|
|
285
|
+
description: job.description || '',
|
|
286
|
+
enabled: job.enabled !== false,
|
|
287
|
+
lastRun: job.lastRunAt || null,
|
|
288
|
+
nextRun: job.nextRunAt || null,
|
|
289
|
+
runCount: job.runCount || 0,
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* เริ่มต้น job
|
|
295
|
+
*/
|
|
296
|
+
startJob(job) {
|
|
297
|
+
if (this.tasks.has(job.id)) {
|
|
298
|
+
this.stopJob(job.id);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const task = cron.schedule(job.schedule, async () => {
|
|
302
|
+
await this.executeJob(job.id);
|
|
303
|
+
}, {
|
|
304
|
+
scheduled: true,
|
|
305
|
+
timezone: process.env.TZ || 'Asia/Bangkok',
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
this.tasks.set(job.id, task);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* หยุด job
|
|
313
|
+
*/
|
|
314
|
+
stopJob(jobId) {
|
|
315
|
+
const task = this.tasks.get(jobId);
|
|
316
|
+
if (task) {
|
|
317
|
+
task.stop();
|
|
318
|
+
if (typeof task.destroy === 'function') {
|
|
319
|
+
task.destroy();
|
|
320
|
+
}
|
|
321
|
+
this.tasks.delete(jobId);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* รัน job
|
|
327
|
+
*/
|
|
328
|
+
async executeJob(jobId) {
|
|
329
|
+
const jobs = this.getJobs();
|
|
330
|
+
const job = jobs.find(j => j.id === jobId);
|
|
331
|
+
|
|
332
|
+
if (!job || !job.enabled) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const startTime = Date.now();
|
|
337
|
+
|
|
338
|
+
try {
|
|
339
|
+
// บันทึก log
|
|
340
|
+
this.logJobExecution(job, 'start');
|
|
341
|
+
|
|
342
|
+
// เรียกใช้ skill
|
|
343
|
+
await this.runSkill(job.skill, job.params);
|
|
344
|
+
|
|
345
|
+
// อัปเดตสถานะ
|
|
346
|
+
job.lastRun = new Date().toISOString();
|
|
347
|
+
job.nextRun = this.getNextRun(job.schedule);
|
|
348
|
+
job.runCount++;
|
|
349
|
+
job.lastDuration = Date.now() - startTime;
|
|
350
|
+
|
|
351
|
+
this.logJobExecution(job, 'success');
|
|
352
|
+
|
|
353
|
+
} catch (error) {
|
|
354
|
+
job.errorCount++;
|
|
355
|
+
job.lastError = error.message;
|
|
356
|
+
this.logJobExecution(job, 'error', error.message);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
this.saveJobs(jobs);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* รัน skill
|
|
364
|
+
*/
|
|
365
|
+
async runSkill(skillName, params) {
|
|
366
|
+
// ในโลกจริงจะเรียก OpenClaw API
|
|
367
|
+
// const response = await axios.post(`${baseUrl}/api/skills/execute`, {
|
|
368
|
+
// name: skillName,
|
|
369
|
+
// params,
|
|
370
|
+
// });
|
|
371
|
+
|
|
372
|
+
// สำหรับตอนนี้จำลองการทำงาน
|
|
373
|
+
console.log(chalk.gray(`[CRON] Running ${skillName} with params:`, JSON.stringify(params)));
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* สร้าง cron script file
|
|
378
|
+
*/
|
|
379
|
+
createCronScript(job) {
|
|
380
|
+
const scriptContent = `#!/usr/bin/env node
|
|
381
|
+
// Auto-generated cron script for ${job.skill}
|
|
382
|
+
// Generated at: ${new Date().toISOString()}
|
|
383
|
+
|
|
384
|
+
const axios = require('axios');
|
|
385
|
+
|
|
386
|
+
const skill = '${job.skill}';
|
|
387
|
+
const params = ${JSON.stringify(job.params, null, 2)};
|
|
388
|
+
const config = require('${this.configManager.getSkillsPath()}/${job.skill}.config.json');
|
|
389
|
+
|
|
390
|
+
async function run() {
|
|
391
|
+
try {
|
|
392
|
+
console.log(\`[\${new Date().toISOString()}] Running \${skill}...\`);
|
|
393
|
+
|
|
394
|
+
// Call OpenClaw API
|
|
395
|
+
const baseUrl = process.env.OPENCLAW_URL || 'http://localhost:3000';
|
|
396
|
+
const response = await axios.post(\`\${baseUrl}/api/skills/execute\`, {
|
|
397
|
+
name: skill,
|
|
398
|
+
params: { ...config, ...params },
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
console.log(\`[\${new Date().toISOString()}] Success:\`, response.data);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
console.error(\`[\${new Date().toISOString()}] Error:\`, error.message);
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
run();
|
|
409
|
+
`;
|
|
410
|
+
|
|
411
|
+
const scriptPath = path.join(this.configManager.getCronsPath(), `${job.id}.js`);
|
|
412
|
+
fs.writeFileSync(scriptPath, scriptContent, { mode: 0o755 });
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* ลบ cron script file
|
|
417
|
+
*/
|
|
418
|
+
removeCronScript(jobId) {
|
|
419
|
+
const scriptPath = path.join(this.configManager.getCronsPath(), `${jobId}.js`);
|
|
420
|
+
if (fs.existsSync(scriptPath)) {
|
|
421
|
+
fs.removeSync(scriptPath);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* บันทึก log การทำงาน
|
|
427
|
+
*/
|
|
428
|
+
logJobExecution(job, status, message = '') {
|
|
429
|
+
const logPath = path.join(this.configManager.getLogsPath(), `cron-${new Date().toISOString().split('T')[0]}.log`);
|
|
430
|
+
const logEntry = `[${new Date().toISOString()}] ${status.toUpperCase()} - ${job.skill} (${job.id}): ${message}\n`;
|
|
431
|
+
|
|
432
|
+
fs.appendFileSync(logPath, logEntry);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* คำนวณเวลารันครั้งถัดไป
|
|
437
|
+
*/
|
|
438
|
+
getNextRun(_schedule) {
|
|
439
|
+
// ง่ายๆ แค่ return null ตอนนี้
|
|
440
|
+
// ในอนาคตอาจใช้ library คำนวณจริง
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* เปิด/ปิด job
|
|
446
|
+
*/
|
|
447
|
+
toggleJob(jobId, enabled) {
|
|
448
|
+
if (this.useOpenClawCron) {
|
|
449
|
+
throw new Error('โหมด openclaw cron: ให้ใช้คำสั่ง "openclaw cron enable|disable <id>"');
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const jobs = this.getJobs();
|
|
453
|
+
const job = jobs.find(j => j.id === jobId);
|
|
454
|
+
|
|
455
|
+
if (!job) {
|
|
456
|
+
throw new Error(`ไม่พบ cronjob ID: ${jobId}`);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
job.enabled = enabled;
|
|
460
|
+
this.saveJobs(jobs);
|
|
461
|
+
|
|
462
|
+
if (enabled) {
|
|
463
|
+
this.startJob(job);
|
|
464
|
+
console.log(chalk.green(`✓ เปิดใช้งาน cronjob: ${job.skill}`));
|
|
465
|
+
} else {
|
|
466
|
+
this.stopJob(jobId);
|
|
467
|
+
console.log(chalk.yellow(`⏸️ ปิดใช้งาน cronjob: ${job.skill}`));
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return job;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* เริ่มต้นระบบ cron (เรียกตอน start)
|
|
475
|
+
*/
|
|
476
|
+
startAll() {
|
|
477
|
+
if (this.useOpenClawCron) {
|
|
478
|
+
console.log(chalk.green('✓ ใช้ openclaw cron scheduler (ไม่ต้อง start local tasks)'));
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const jobs = this.getJobs().filter(j => j.enabled);
|
|
483
|
+
|
|
484
|
+
for (const job of jobs) {
|
|
485
|
+
this.startJob(job);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
console.log(chalk.green(`✓ เริ่มต้นระบบ cron (${jobs.length} jobs)`));
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* หยุดระบบ cron ทั้งหมด
|
|
493
|
+
*/
|
|
494
|
+
stopAll() {
|
|
495
|
+
if (this.useOpenClawCron) {
|
|
496
|
+
console.log(chalk.yellow('⏹️ openclaw cron scheduler ยังทำงานภายนอก process นี้'));
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
for (const [, task] of this.tasks) {
|
|
501
|
+
task.stop();
|
|
502
|
+
if (typeof task.destroy === 'function') {
|
|
503
|
+
task.destroy();
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
this.tasks.clear();
|
|
507
|
+
|
|
508
|
+
console.log(chalk.yellow('⏹️ หยุดระบบ cron'));
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
module.exports = CronManager;
|