@dcrays/scheduled-task 0.3.5 → 0.3.6-beta.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcrays/scheduled-task",
3
- "version": "0.3.5",
3
+ "version": "0.3.6-beta.1",
4
4
  "description": "Persistent client-facing cron automation service for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "main": "plugin/index.js",
package/plugin/index.js CHANGED
@@ -1398,6 +1398,20 @@ import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
1398
1398
  function isRecord3(value) {
1399
1399
  return typeof value === "object" && value !== null && !Array.isArray(value);
1400
1400
  }
1401
+ var LegacySessionBindingError = class extends Error {
1402
+ };
1403
+ function decodeImportedJob(value) {
1404
+ if (isRecord3(value) && typeof value.sessionTarget === "string" && value.sessionTarget.startsWith("session:")) {
1405
+ const sessionKey = value.sessionTarget.slice("session:".length);
1406
+ if (!sessionKey.trim())
1407
+ throw new LegacySessionBindingError("OpenClaw cron session target is empty");
1408
+ if (value.sessionKey !== void 0 && value.sessionKey !== null && value.sessionKey !== "" && value.sessionKey !== sessionKey) {
1409
+ throw new LegacySessionBindingError("OpenClaw cron session target conflicts with sessionKey");
1410
+ }
1411
+ return decodeJob({ ...value, sessionTarget: "isolated", sessionKey });
1412
+ }
1413
+ return decodeJob(value);
1414
+ }
1401
1415
  function parseJson(raw, label) {
1402
1416
  try {
1403
1417
  return JSON.parse(raw);
@@ -1476,15 +1490,17 @@ function jobFromOpenClawRow(row) {
1476
1490
  const parsed = parseJson(row.job_json, "job_json");
1477
1491
  if (!isRecord3(parsed))
1478
1492
  throw new Error("job_json must be an object");
1479
- return decodeJob({
1493
+ return decodeImportedJob({
1480
1494
  ...parsed,
1481
1495
  id: typeof parsed.id === "string" && parsed.id ? parsed.id : row.job_id,
1482
1496
  updatedAtMs: typeof parsed.updatedAtMs === "number" ? parsed.updatedAtMs : row.updated_at,
1483
1497
  createdAtMs: typeof parsed.createdAtMs === "number" ? parsed.createdAtMs : row.created_at_ms,
1484
1498
  state: overlayState(row, parsed.state, tableState)
1485
1499
  });
1486
- } catch {
1487
- return decodeJob(jobFromColumns(row, overlayState(row, {}, tableState)));
1500
+ } catch (error) {
1501
+ if (error instanceof LegacySessionBindingError)
1502
+ throw error;
1503
+ return decodeImportedJob(jobFromColumns(row, overlayState(row, {}, tableState)));
1488
1504
  }
1489
1505
  }
1490
1506
  function loadOpenClawSqliteJobsWithDiagnostics(sqlitePath) {
@@ -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 decodeJob({
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
- return decodeJob(jobFromColumns(row, overlayState(row, {}, tableState)));
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) {