@dcrays/scheduled-task 0.3.5 → 0.3.6-beta.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/package.json +1 -1
- package/plugin/index.js +27 -4
- package/src/manager.js +9 -1
- package/src/openclaw-sqlite.js +24 -3
package/package.json
CHANGED
package/plugin/index.js
CHANGED
|
@@ -1100,6 +1100,9 @@ var CronAutomationManager = class {
|
|
|
1100
1100
|
if (patch.at !== void 0 && Date.parse(patch.at) <= now) {
|
|
1101
1101
|
throw new CronAutomationInputError("invalid_envelope", "at must be in the future");
|
|
1102
1102
|
}
|
|
1103
|
+
if (patch.enabled === true && next.schedule.kind === "at" && atTimestamp(next.schedule) <= now) {
|
|
1104
|
+
throw new CronAutomationInputError("invalid_envelope", "at must be in the future");
|
|
1105
|
+
}
|
|
1103
1106
|
if (patch.enabled !== void 0) {
|
|
1104
1107
|
next.enabled = patch.enabled;
|
|
1105
1108
|
delete next.state.runningAtMs;
|
|
@@ -1328,7 +1331,11 @@ var CronAutomationManager = class {
|
|
|
1328
1331
|
}
|
|
1329
1332
|
this.blockedAgents.delete(dshAgentIdFor(job));
|
|
1330
1333
|
this.blockedUntil.delete(dshAgentIdFor(job));
|
|
1331
|
-
if (job.
|
|
1334
|
+
if (job.schedule.kind === "at") {
|
|
1335
|
+
job.enabled = false;
|
|
1336
|
+
setNextOccurrence(job, void 0);
|
|
1337
|
+
await this.repository.upsert([job]);
|
|
1338
|
+
} else if (job.deleteAfterRun === true) {
|
|
1332
1339
|
this.jobs.delete(jobId);
|
|
1333
1340
|
await this.repository.delete(jobId);
|
|
1334
1341
|
} else {
|
|
@@ -1398,6 +1405,20 @@ import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
|
|
|
1398
1405
|
function isRecord3(value) {
|
|
1399
1406
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1400
1407
|
}
|
|
1408
|
+
var LegacySessionBindingError = class extends Error {
|
|
1409
|
+
};
|
|
1410
|
+
function decodeImportedJob(value) {
|
|
1411
|
+
if (isRecord3(value) && typeof value.sessionTarget === "string" && value.sessionTarget.startsWith("session:")) {
|
|
1412
|
+
const sessionKey = value.sessionTarget.slice("session:".length);
|
|
1413
|
+
if (!sessionKey.trim())
|
|
1414
|
+
throw new LegacySessionBindingError("OpenClaw cron session target is empty");
|
|
1415
|
+
if (value.sessionKey !== void 0 && value.sessionKey !== null && value.sessionKey !== "" && value.sessionKey !== sessionKey) {
|
|
1416
|
+
throw new LegacySessionBindingError("OpenClaw cron session target conflicts with sessionKey");
|
|
1417
|
+
}
|
|
1418
|
+
return decodeJob({ ...value, sessionTarget: "isolated", sessionKey });
|
|
1419
|
+
}
|
|
1420
|
+
return decodeJob(value);
|
|
1421
|
+
}
|
|
1401
1422
|
function parseJson(raw, label) {
|
|
1402
1423
|
try {
|
|
1403
1424
|
return JSON.parse(raw);
|
|
@@ -1476,15 +1497,17 @@ function jobFromOpenClawRow(row) {
|
|
|
1476
1497
|
const parsed = parseJson(row.job_json, "job_json");
|
|
1477
1498
|
if (!isRecord3(parsed))
|
|
1478
1499
|
throw new Error("job_json must be an object");
|
|
1479
|
-
return
|
|
1500
|
+
return decodeImportedJob({
|
|
1480
1501
|
...parsed,
|
|
1481
1502
|
id: typeof parsed.id === "string" && parsed.id ? parsed.id : row.job_id,
|
|
1482
1503
|
updatedAtMs: typeof parsed.updatedAtMs === "number" ? parsed.updatedAtMs : row.updated_at,
|
|
1483
1504
|
createdAtMs: typeof parsed.createdAtMs === "number" ? parsed.createdAtMs : row.created_at_ms,
|
|
1484
1505
|
state: overlayState(row, parsed.state, tableState)
|
|
1485
1506
|
});
|
|
1486
|
-
} catch {
|
|
1487
|
-
|
|
1507
|
+
} catch (error) {
|
|
1508
|
+
if (error instanceof LegacySessionBindingError)
|
|
1509
|
+
throw error;
|
|
1510
|
+
return decodeImportedJob(jobFromColumns(row, overlayState(row, {}, tableState)));
|
|
1488
1511
|
}
|
|
1489
1512
|
}
|
|
1490
1513
|
function loadOpenClawSqliteJobsWithDiagnostics(sqlitePath) {
|
package/src/manager.js
CHANGED
|
@@ -382,6 +382,9 @@ export class CronAutomationManager {
|
|
|
382
382
|
if (patch.at !== undefined && Date.parse(patch.at) <= now) {
|
|
383
383
|
throw new CronAutomationInputError('invalid_envelope', 'at must be in the future');
|
|
384
384
|
}
|
|
385
|
+
if (patch.enabled === true && next.schedule.kind === 'at' && atTimestamp(next.schedule) <= now) {
|
|
386
|
+
throw new CronAutomationInputError('invalid_envelope', 'at must be in the future');
|
|
387
|
+
}
|
|
385
388
|
if (patch.enabled !== undefined) {
|
|
386
389
|
next.enabled = patch.enabled;
|
|
387
390
|
delete next.state.runningAtMs;
|
|
@@ -630,7 +633,12 @@ export class CronAutomationManager {
|
|
|
630
633
|
}
|
|
631
634
|
this.blockedAgents.delete(dshAgentIdFor(job));
|
|
632
635
|
this.blockedUntil.delete(dshAgentIdFor(job));
|
|
633
|
-
if (job.
|
|
636
|
+
if (job.schedule.kind === 'at') {
|
|
637
|
+
job.enabled = false;
|
|
638
|
+
setNextOccurrence(job, undefined);
|
|
639
|
+
await this.repository.upsert([job]);
|
|
640
|
+
}
|
|
641
|
+
else if (job.deleteAfterRun === true) {
|
|
634
642
|
this.jobs.delete(jobId);
|
|
635
643
|
await this.repository.delete(jobId);
|
|
636
644
|
}
|
package/src/openclaw-sqlite.js
CHANGED
|
@@ -9,6 +9,24 @@ import { decodeJob } from './repository.js';
|
|
|
9
9
|
function isRecord(value) {
|
|
10
10
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
11
11
|
}
|
|
12
|
+
class LegacySessionBindingError extends Error {
|
|
13
|
+
}
|
|
14
|
+
/** Translate legacy execution targets without changing the task's business conversation. */
|
|
15
|
+
function decodeImportedJob(value) {
|
|
16
|
+
if (isRecord(value) && typeof value.sessionTarget === 'string' && value.sessionTarget.startsWith('session:')) {
|
|
17
|
+
const sessionKey = value.sessionTarget.slice('session:'.length);
|
|
18
|
+
if (!sessionKey.trim())
|
|
19
|
+
throw new LegacySessionBindingError('OpenClaw cron session target is empty');
|
|
20
|
+
if (value.sessionKey !== undefined &&
|
|
21
|
+
value.sessionKey !== null &&
|
|
22
|
+
value.sessionKey !== '' &&
|
|
23
|
+
value.sessionKey !== sessionKey) {
|
|
24
|
+
throw new LegacySessionBindingError('OpenClaw cron session target conflicts with sessionKey');
|
|
25
|
+
}
|
|
26
|
+
return decodeJob({ ...value, sessionTarget: 'isolated', sessionKey });
|
|
27
|
+
}
|
|
28
|
+
return decodeJob(value);
|
|
29
|
+
}
|
|
12
30
|
function parseJson(raw, label) {
|
|
13
31
|
try {
|
|
14
32
|
return JSON.parse(raw);
|
|
@@ -93,7 +111,7 @@ export function jobFromOpenClawRow(row) {
|
|
|
93
111
|
const parsed = parseJson(row.job_json, 'job_json');
|
|
94
112
|
if (!isRecord(parsed))
|
|
95
113
|
throw new Error('job_json must be an object');
|
|
96
|
-
return
|
|
114
|
+
return decodeImportedJob({
|
|
97
115
|
...parsed,
|
|
98
116
|
id: typeof parsed.id === 'string' && parsed.id ? parsed.id : row.job_id,
|
|
99
117
|
updatedAtMs: typeof parsed.updatedAtMs === 'number' ? parsed.updatedAtMs : row.updated_at,
|
|
@@ -101,8 +119,11 @@ export function jobFromOpenClawRow(row) {
|
|
|
101
119
|
state: overlayState(row, parsed.state, tableState)
|
|
102
120
|
});
|
|
103
121
|
}
|
|
104
|
-
catch {
|
|
105
|
-
|
|
122
|
+
catch (error) {
|
|
123
|
+
// Conflicting routing must not silently fall back to a different conversation.
|
|
124
|
+
if (error instanceof LegacySessionBindingError)
|
|
125
|
+
throw error;
|
|
126
|
+
return decodeImportedJob(jobFromColumns(row, overlayState(row, {}, tableState)));
|
|
106
127
|
}
|
|
107
128
|
}
|
|
108
129
|
export function loadOpenClawSqliteJobs(sqlitePath) {
|