openclaw-scheduler 0.2.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 (70) hide show
  1. package/AGENTS.md +302 -0
  2. package/BEST-PRACTICES.md +506 -0
  3. package/CHANGELOG.md +82 -0
  4. package/CODE_OF_CONDUCT.md +22 -0
  5. package/CONTEXT.md +26 -0
  6. package/CONTRIBUTING.md +73 -0
  7. package/IMPLEMENTATION_SPEC.md +170 -0
  8. package/INSTALL-ADDITIONAL-HOST.md +333 -0
  9. package/INSTALL-LINUX.md +419 -0
  10. package/INSTALL-WINDOWS.md +305 -0
  11. package/INSTALL.md +364 -0
  12. package/JOB-QUICK-REF.md +222 -0
  13. package/LICENSE +21 -0
  14. package/QUICK-START.md +256 -0
  15. package/README.md +2170 -0
  16. package/SECURITY.md +34 -0
  17. package/UNINSTALL.md +129 -0
  18. package/UPGRADING.md +436 -0
  19. package/agents.js +67 -0
  20. package/approval.js +107 -0
  21. package/backup.js +390 -0
  22. package/bin/openclaw-scheduler.js +138 -0
  23. package/cli.js +1083 -0
  24. package/db.js +122 -0
  25. package/dispatch/529-recovery.mjs +204 -0
  26. package/dispatch/README.md +372 -0
  27. package/dispatch/config.example.json +24 -0
  28. package/dispatch/deliver-watcher.sh +57 -0
  29. package/dispatch/hooks.mjs +171 -0
  30. package/dispatch/index.mjs +1836 -0
  31. package/dispatch/watcher.mjs +1396 -0
  32. package/dispatch-queue.js +112 -0
  33. package/dispatcher-approvals.js +96 -0
  34. package/dispatcher-delivery.js +43 -0
  35. package/dispatcher-maintenance.js +242 -0
  36. package/dispatcher-shell.js +29 -0
  37. package/dispatcher-strategies.js +1280 -0
  38. package/dispatcher-utils.js +81 -0
  39. package/dispatcher.js +855 -0
  40. package/docs/adr-schedule-ownership.md +73 -0
  41. package/docs/gateway-contract.md +904 -0
  42. package/docs/plans/2026-03-09-fix-typescript-types.md +91 -0
  43. package/docs/plans/2026-03-09-test-coverage-gaps.md +83 -0
  44. package/docs/plans/2026-03-10-dispatcher-refactor.md +801 -0
  45. package/docs/trust-architecture.md +266 -0
  46. package/gateway.js +473 -0
  47. package/idempotency.js +119 -0
  48. package/index.d.ts +864 -0
  49. package/index.js +17 -0
  50. package/jobs.js +1224 -0
  51. package/messages.js +357 -0
  52. package/migrate-consolidate.js +694 -0
  53. package/migrate.js +125 -0
  54. package/package.json +130 -0
  55. package/paths.js +79 -0
  56. package/prompt-context.js +94 -0
  57. package/retrieval.js +176 -0
  58. package/runs.js +270 -0
  59. package/scheduler-schema.js +101 -0
  60. package/schema.sql +480 -0
  61. package/scripts/dispatch-cli-utils.mjs +65 -0
  62. package/scripts/inbox-consumer.mjs +288 -0
  63. package/scripts/stuck-detector.sh +18 -0
  64. package/scripts/stuck-run-detector.mjs +333 -0
  65. package/scripts/telegram-webhook-check.mjs +238 -0
  66. package/setup.mjs +724 -0
  67. package/shell-result.js +214 -0
  68. package/task-tracker.js +300 -0
  69. package/team-adapter.js +335 -0
  70. package/v02-runtime.js +599 -0
@@ -0,0 +1,81 @@
1
+ const TRANSIENT_ERROR_PATTERNS = [
2
+ /\btemporarily overloaded\b/i,
3
+ /\bservice\s+(?:is\s+)?unavailable\b/i,
4
+ /\brate\s*limit(?:ed|s?)?\b/i,
5
+ /\btoo\s+many\s+requests\b/i,
6
+ /\b5[0-9]{2}\b\s+(?:internal\s+)?server\s+error\b/i,
7
+ /\bgateway\s+timeout\b/i,
8
+ /\bbad\s+gateway\b/i,
9
+ /\bmodel\s+(?:is\s+)?(?:overloaded|unavailable)\b/i,
10
+ /\bAPI\s+(?:error|unavailable|timeout)\b/i,
11
+ /\bcapacity\s+(?:exceeded|limit)\b/i,
12
+ /\bretry\s+(?:after|later|in\s+\d)\b/i,
13
+ /\bcontext\s+(?:length|window)\s+exceeded\b/i,
14
+ /\btoken\s+limit\s+exceeded\b/i,
15
+ /gateway\s+is\s+draining/i,
16
+ /new\s+tasks\s+are\s+not\s+accepted/i,
17
+ /gateway.*draining.*restart/i,
18
+ ];
19
+
20
+ const DRAIN_PATTERNS = [
21
+ /gateway\s+is\s+draining/i,
22
+ /new\s+tasks\s+are\s+not\s+accepted/i,
23
+ ];
24
+
25
+ export function isDrainError(errorMessage) {
26
+ const trimmed = String(errorMessage ?? '').trim();
27
+ if (!trimmed) return false;
28
+ return DRAIN_PATTERNS.some(p => p.test(trimmed));
29
+ }
30
+
31
+ export function sqliteNow(offsetMs = 0) {
32
+ return new Date(Date.now() + offsetMs).toISOString().replace('T', ' ').replace(/\.\d{3}Z$/, '');
33
+ }
34
+
35
+ export function adaptiveDeferralMs(backlogDepth, baseMs = 10000) {
36
+ const safeDepth = Number.isFinite(backlogDepth) ? backlogDepth : 0;
37
+ const multiplier = Math.max(1, Math.min(12, safeDepth + 1));
38
+ return Math.min(300000, baseMs * multiplier);
39
+ }
40
+
41
+ export function buildExecutionIntentNote(job) {
42
+ if (job.execution_intent !== 'plan' && !job.execution_read_only) return '';
43
+ const lines = [
44
+ '[SYSTEM NOTE -- execution boundary]',
45
+ job.execution_intent === 'plan'
46
+ ? 'This run is planning-only. Analyze, reason, and propose actions, but do not execute external side effects.'
47
+ : 'This run is read-only. Inspect and summarize state, but do not execute external side effects.',
48
+ ];
49
+ if (job.execution_read_only) {
50
+ lines.push('Treat every write, send, post, mutation, or shelling out for side effects as forbidden.');
51
+ }
52
+ lines.push('If a concrete change is needed, describe it as a recommendation instead of performing it.');
53
+ lines.push('[END SYSTEM NOTE]');
54
+ return lines.join('\n');
55
+ }
56
+
57
+ /**
58
+ * Check if content matches a sentinel token at the start of the string.
59
+ * Matches "TOKEN" exactly, or "TOKEN" followed by whitespace/colon.
60
+ */
61
+ export function matchesSentinel(content, token) {
62
+ if (!content) return false;
63
+ const escaped = token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
64
+ const re = new RegExp(`^${escaped}(?:$|[\\s:])`);
65
+ return re.test(content.trim());
66
+ }
67
+
68
+ export function detectTransientError(content) {
69
+ if (!content || !content.trim()) return false;
70
+ const trimmed = content.trim();
71
+ // Check only the first 500 chars: transient errors from the gateway/model API appear
72
+ // at the start of the response. Long agent responses may discuss errors in their analysis
73
+ // without being actual errors -- checking more would cause false positives.
74
+ const testStr = trimmed.length > 500 ? trimmed.slice(0, 500) : trimmed;
75
+ return TRANSIENT_ERROR_PATTERNS.some(pattern => pattern.test(testStr));
76
+ }
77
+
78
+ export function getBackoffMs(n) {
79
+ const backoff = [30_000, 60_000, 300_000, 900_000, 3_600_000];
80
+ return backoff[Math.min(Math.max(n, 1) - 1, backoff.length - 1)];
81
+ }