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.
- package/AGENTS.md +302 -0
- package/BEST-PRACTICES.md +506 -0
- package/CHANGELOG.md +82 -0
- package/CODE_OF_CONDUCT.md +22 -0
- package/CONTEXT.md +26 -0
- package/CONTRIBUTING.md +73 -0
- package/IMPLEMENTATION_SPEC.md +170 -0
- package/INSTALL-ADDITIONAL-HOST.md +333 -0
- package/INSTALL-LINUX.md +419 -0
- package/INSTALL-WINDOWS.md +305 -0
- package/INSTALL.md +364 -0
- package/JOB-QUICK-REF.md +222 -0
- package/LICENSE +21 -0
- package/QUICK-START.md +256 -0
- package/README.md +2170 -0
- package/SECURITY.md +34 -0
- package/UNINSTALL.md +129 -0
- package/UPGRADING.md +436 -0
- package/agents.js +67 -0
- package/approval.js +107 -0
- package/backup.js +390 -0
- package/bin/openclaw-scheduler.js +138 -0
- package/cli.js +1083 -0
- package/db.js +122 -0
- package/dispatch/529-recovery.mjs +204 -0
- package/dispatch/README.md +372 -0
- package/dispatch/config.example.json +24 -0
- package/dispatch/deliver-watcher.sh +57 -0
- package/dispatch/hooks.mjs +171 -0
- package/dispatch/index.mjs +1836 -0
- package/dispatch/watcher.mjs +1396 -0
- package/dispatch-queue.js +112 -0
- package/dispatcher-approvals.js +96 -0
- package/dispatcher-delivery.js +43 -0
- package/dispatcher-maintenance.js +242 -0
- package/dispatcher-shell.js +29 -0
- package/dispatcher-strategies.js +1280 -0
- package/dispatcher-utils.js +81 -0
- package/dispatcher.js +855 -0
- package/docs/adr-schedule-ownership.md +73 -0
- package/docs/gateway-contract.md +904 -0
- package/docs/plans/2026-03-09-fix-typescript-types.md +91 -0
- package/docs/plans/2026-03-09-test-coverage-gaps.md +83 -0
- package/docs/plans/2026-03-10-dispatcher-refactor.md +801 -0
- package/docs/trust-architecture.md +266 -0
- package/gateway.js +473 -0
- package/idempotency.js +119 -0
- package/index.d.ts +864 -0
- package/index.js +17 -0
- package/jobs.js +1224 -0
- package/messages.js +357 -0
- package/migrate-consolidate.js +694 -0
- package/migrate.js +125 -0
- package/package.json +130 -0
- package/paths.js +79 -0
- package/prompt-context.js +94 -0
- package/retrieval.js +176 -0
- package/runs.js +270 -0
- package/scheduler-schema.js +101 -0
- package/schema.sql +480 -0
- package/scripts/dispatch-cli-utils.mjs +65 -0
- package/scripts/inbox-consumer.mjs +288 -0
- package/scripts/stuck-detector.sh +18 -0
- package/scripts/stuck-run-detector.mjs +333 -0
- package/scripts/telegram-webhook-check.mjs +238 -0
- package/setup.mjs +724 -0
- package/shell-result.js +214 -0
- package/task-tracker.js +300 -0
- package/team-adapter.js +335 -0
- package/v02-runtime.js +599 -0
package/SECURITY.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting
|
|
4
|
+
|
|
5
|
+
Report security issues privately to the maintainers instead of opening a public issue.
|
|
6
|
+
|
|
7
|
+
Preferred channel:
|
|
8
|
+
|
|
9
|
+
- GitHub private vulnerability reporting: https://github.com/amittell/openclaw-scheduler/security/advisories/new
|
|
10
|
+
|
|
11
|
+
Include:
|
|
12
|
+
|
|
13
|
+
- affected version
|
|
14
|
+
- deployment mode
|
|
15
|
+
- reproduction steps
|
|
16
|
+
- impact
|
|
17
|
+
- suggested mitigation if known
|
|
18
|
+
|
|
19
|
+
## Scope
|
|
20
|
+
|
|
21
|
+
Security-sensitive areas include:
|
|
22
|
+
|
|
23
|
+
- shell job execution
|
|
24
|
+
- gateway credential handling
|
|
25
|
+
- delivery adapters
|
|
26
|
+
- approval flows
|
|
27
|
+
- installation and service configuration
|
|
28
|
+
|
|
29
|
+
Please report unsafe defaults, credential leaks, or privilege boundary issues.
|
|
30
|
+
|
|
31
|
+
## Response Timeline
|
|
32
|
+
|
|
33
|
+
- **Acknowledgment:** within 7 days of receipt.
|
|
34
|
+
- **Resolution:** within 30--90 days depending on severity and complexity.
|
package/UNINSTALL.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Uninstalling OpenClaw Scheduler
|
|
2
|
+
|
|
3
|
+
Two levels of removal:
|
|
4
|
+
|
|
5
|
+
1. **Stop the scheduler** and re-enable OpenClaw's built-in cron/heartbeat — reversible
|
|
6
|
+
2. **Full removal** — delete all scheduler files and data — irreversible
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Step 1: Stop the Scheduler Service
|
|
11
|
+
|
|
12
|
+
### macOS
|
|
13
|
+
|
|
14
|
+
Remove the launchd mode you actually used:
|
|
15
|
+
|
|
16
|
+
**LaunchAgent**
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
launchctl bootout gui/$UID/ai.openclaw.scheduler
|
|
20
|
+
rm ~/Library/LaunchAgents/ai.openclaw.scheduler.plist
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**LaunchDaemon**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
sudo launchctl bootout system/ai.openclaw.scheduler
|
|
27
|
+
sudo rm /Library/LaunchDaemons/ai.openclaw.scheduler.plist
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Linux
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
systemctl --user stop openclaw-scheduler
|
|
34
|
+
systemctl --user disable openclaw-scheduler
|
|
35
|
+
rm ~/.config/systemd/user/openclaw-scheduler.service
|
|
36
|
+
systemctl --user daemon-reload
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Windows (PM2)
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
pm2 stop openclaw-scheduler
|
|
43
|
+
pm2 delete openclaw-scheduler
|
|
44
|
+
pm2 save # persist the removal
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 2: Re-enable OpenClaw Built-ins
|
|
50
|
+
|
|
51
|
+
### Re-enable cron (if you had OC cron jobs before)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
openclaw config set cron.enabled true
|
|
55
|
+
openclaw cron list
|
|
56
|
+
openclaw cron edit <job-id> --enable # repeat for each job you want back
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Also remove `OPENCLAW_SKIP_CRON=1` from your OpenClaw gateway service environment, then restart the gateway.
|
|
60
|
+
|
|
61
|
+
### Re-enable heartbeat (if you had one)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
openclaw config set agents.defaults.heartbeat.every "5m"
|
|
65
|
+
# If you had per-agent heartbeat overrides, restore those too:
|
|
66
|
+
# agents.list[].heartbeat.every = "5m"
|
|
67
|
+
openclaw gateway restart
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Step 3: Full Removal (optional)
|
|
73
|
+
|
|
74
|
+
> ⚠️ **This permanently deletes your job definitions, run history, log files, and all scheduler data. This cannot be undone.**
|
|
75
|
+
|
|
76
|
+
**Export your jobs first (optional):**
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
node ~/.openclaw/scheduler/cli.js jobs list > ~/scheduler-jobs-backup.txt
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Remove the scheduler directory:**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# macOS / Linux
|
|
86
|
+
rm -rf ~/.openclaw/scheduler/
|
|
87
|
+
|
|
88
|
+
# Windows (PowerShell)
|
|
89
|
+
Remove-Item -Recurse -Force "$env:USERPROFILE\.openclaw\scheduler"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Remove log files:**
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# macOS / Linux
|
|
96
|
+
rm -f /tmp/openclaw-scheduler.log
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
On Windows, PM2 stores logs in `~/.pm2/logs/`. Remove if desired:
|
|
100
|
+
|
|
101
|
+
```powershell
|
|
102
|
+
Remove-Item -Force "$env:USERPROFILE\.pm2\logs\openclaw-scheduler-out.log"
|
|
103
|
+
Remove-Item -Force "$env:USERPROFILE\.pm2\logs\openclaw-scheduler-error.log"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## About the Chat Completions Endpoint
|
|
109
|
+
|
|
110
|
+
The scheduler enabled the OpenClaw gateway's chat completions endpoint (`/v1/chat/completions`). This endpoint is also used by Claude Code, other AI tools, and the OpenClaw API. **You probably want to leave it enabled.**
|
|
111
|
+
|
|
112
|
+
If you specifically want to disable it:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
openclaw config set gateway.http.endpoints.chatCompletions.enabled false
|
|
116
|
+
openclaw gateway restart
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Linger (Linux only)
|
|
122
|
+
|
|
123
|
+
If you enabled linger to keep the service running without a login session, you can disable it:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
loginctl disable-linger $USER
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
This stops systemd user services from running when you're not logged in. Only do this if you don't need other user services running persistently.
|
package/UPGRADING.md
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# Upgrading OpenClaw Scheduler
|
|
2
|
+
|
|
3
|
+
How to update an existing OpenClaw Scheduler installation to the latest version.
|
|
4
|
+
|
|
5
|
+
This guide covers both git-clone and npm-based installs. Each host is independent -- upgrade them one at a time and verify before moving on.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Quick Reference
|
|
10
|
+
|
|
11
|
+
### macOS (launchd, git-clone install)
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cd ~/.openclaw/scheduler
|
|
15
|
+
git pull
|
|
16
|
+
npm install
|
|
17
|
+
SCHEDULER_DB=:memory: node test.js
|
|
18
|
+
launchctl kickstart -k gui/$(id -u)/ai.openclaw.scheduler
|
|
19
|
+
sleep 3 && tail -5 /tmp/openclaw-scheduler.log
|
|
20
|
+
node cli.js status
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Linux / Windows WSL2 (systemd, git-clone install)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
cd ~/.openclaw/scheduler
|
|
27
|
+
git pull
|
|
28
|
+
npm install
|
|
29
|
+
SCHEDULER_DB=:memory: node test.js
|
|
30
|
+
systemctl --user restart openclaw-scheduler
|
|
31
|
+
sleep 3 && systemctl --user --no-pager --full status openclaw-scheduler
|
|
32
|
+
node cli.js status
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Windows native (PM2, git-clone install)
|
|
36
|
+
|
|
37
|
+
```powershell
|
|
38
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
39
|
+
git pull
|
|
40
|
+
npm install
|
|
41
|
+
$env:SCHEDULER_DB=":memory:"; node test.js
|
|
42
|
+
pm2 restart openclaw-scheduler
|
|
43
|
+
Start-Sleep 3
|
|
44
|
+
pm2 logs openclaw-scheduler --lines 5 --nostream
|
|
45
|
+
node cli.js status
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
That is the whole process for a routine update. The rest of this document explains each step, covers edge cases, and documents both git-clone and npm install paths.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Before You Start
|
|
53
|
+
|
|
54
|
+
1. **Check the [CHANGELOG](CHANGELOG.md)** for breaking changes or new schema migrations.
|
|
55
|
+
2. **Check current version:**
|
|
56
|
+
```bash
|
|
57
|
+
cd ~/.openclaw/scheduler
|
|
58
|
+
node -e "console.log(JSON.parse(require('fs').readFileSync('package.json','utf8')).version)"
|
|
59
|
+
# or for npm installs:
|
|
60
|
+
npm ls --prefix ~/.openclaw/scheduler openclaw-scheduler
|
|
61
|
+
```
|
|
62
|
+
3. **Check current schema version:**
|
|
63
|
+
```bash
|
|
64
|
+
node -e "const db=require('better-sqlite3')('scheduler.db');console.log(db.prepare('SELECT MAX(version) as v FROM schema_migrations').get());db.close()"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Step 1: Pull or Install the Update
|
|
70
|
+
|
|
71
|
+
### Git-clone installs
|
|
72
|
+
|
|
73
|
+
#### macOS / Linux / Windows WSL2
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
cd ~/.openclaw/scheduler
|
|
77
|
+
git pull
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Windows native (PowerShell)
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
84
|
+
git pull
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
If you have local modifications, stash them first:
|
|
88
|
+
```bash
|
|
89
|
+
git stash
|
|
90
|
+
git pull
|
|
91
|
+
git stash pop
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### npm installs
|
|
95
|
+
|
|
96
|
+
#### macOS / Linux / Windows WSL2
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm install --prefix ~/.openclaw/scheduler openclaw-scheduler@latest
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Windows native (PowerShell)
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
npm install --prefix $env:USERPROFILE\.openclaw\scheduler openclaw-scheduler@latest
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Step 2: Install Dependencies
|
|
111
|
+
|
|
112
|
+
### macOS / Linux / Windows WSL2
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
cd ~/.openclaw/scheduler
|
|
116
|
+
npm install
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Windows native (PowerShell)
|
|
120
|
+
|
|
121
|
+
```powershell
|
|
122
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
123
|
+
npm install
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
If you upgraded Node.js since the last install, also rebuild the native module:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npm rebuild better-sqlite3
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Common triggers for needing a rebuild:
|
|
133
|
+
- `brew upgrade node` on macOS
|
|
134
|
+
- Switching Node major versions with `nvm`, `fnm`, or `asdf`
|
|
135
|
+
- Distro package upgrades that replace the Node binary
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Step 3: Run Tests
|
|
140
|
+
|
|
141
|
+
### macOS / Linux / Windows WSL2
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
cd ~/.openclaw/scheduler
|
|
145
|
+
SCHEDULER_DB=:memory: node test.js
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Windows native (PowerShell)
|
|
149
|
+
|
|
150
|
+
```powershell
|
|
151
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
152
|
+
$env:SCHEDULER_DB=":memory:"; node test.js
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
All tests must pass before restarting the service. If tests fail, do not restart -- investigate the failure first and check the CHANGELOG for any required manual steps.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Step 4: Schema Migrations
|
|
160
|
+
|
|
161
|
+
The dispatcher runs pending schema migrations automatically on startup. No manual migration step is needed.
|
|
162
|
+
|
|
163
|
+
Note: `migrate.js` is the OC cron importer (for importing jobs from the old OC cron system), not the schema migrator. Do not run it expecting schema changes.
|
|
164
|
+
|
|
165
|
+
To verify the current schema version:
|
|
166
|
+
|
|
167
|
+
### macOS / Linux / Windows WSL2
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
cd ~/.openclaw/scheduler
|
|
171
|
+
node -e "const db=require('better-sqlite3')('scheduler.db');console.log(db.prepare('SELECT MAX(version) as v FROM schema_migrations').get());db.close()"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Windows native (PowerShell)
|
|
175
|
+
|
|
176
|
+
```powershell
|
|
177
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
178
|
+
node -e "const db=require('better-sqlite3')('scheduler.db');console.log(db.prepare('SELECT MAX(version) as v FROM schema_migrations').get());db.close()"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Step 5: Restart the Service
|
|
184
|
+
|
|
185
|
+
### macOS (launchd)
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# LaunchAgent (most common)
|
|
189
|
+
launchctl kickstart -k gui/$(id -u)/ai.openclaw.scheduler
|
|
190
|
+
|
|
191
|
+
# LaunchDaemon (headless hosts)
|
|
192
|
+
sudo launchctl kickstart -k system/ai.openclaw.scheduler
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Linux (systemd)
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
systemctl --user restart openclaw-scheduler
|
|
199
|
+
# or if running as a system service:
|
|
200
|
+
sudo systemctl restart openclaw-scheduler
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Windows WSL2 (systemd inside WSL)
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
systemctl --user restart openclaw-scheduler
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Windows native (PM2)
|
|
210
|
+
|
|
211
|
+
```powershell
|
|
212
|
+
pm2 restart openclaw-scheduler
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Step 6: Verify
|
|
218
|
+
|
|
219
|
+
### macOS (launchd)
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
launchctl list | grep ai.openclaw.scheduler
|
|
223
|
+
tail -10 /tmp/openclaw-scheduler.log
|
|
224
|
+
cd ~/.openclaw/scheduler && node cli.js status
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Linux / Windows WSL2 (systemd)
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
systemctl --user --no-pager --full status openclaw-scheduler
|
|
231
|
+
journalctl --user -u openclaw-scheduler -n 20 --no-pager
|
|
232
|
+
cd ~/.openclaw/scheduler && node cli.js status
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Windows native (PM2)
|
|
236
|
+
|
|
237
|
+
```powershell
|
|
238
|
+
pm2 status
|
|
239
|
+
pm2 logs openclaw-scheduler --lines 20 --nostream
|
|
240
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
241
|
+
node cli.js status
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
A healthy startup log looks like:
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
[scheduler] [info] Starting OpenClaw Scheduler v0.2.0 {"tickMs":10000,...}
|
|
248
|
+
[scheduler] [info] Database initialized
|
|
249
|
+
[scheduler] [info] Pruned old runs + messages
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
If you see `Gateway unreachable`, isolated agent jobs will be deferred until the gateway is back. Shell jobs and main-session jobs continue unaffected.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Upgrading Multiple Hosts
|
|
257
|
+
|
|
258
|
+
Each host has its own independent SQLite database and service. Upgrade hosts one at a time:
|
|
259
|
+
|
|
260
|
+
1. Upgrade the first host following the steps above.
|
|
261
|
+
2. Verify it is healthy (`node cli.js status`, check logs).
|
|
262
|
+
3. Move on to the next host.
|
|
263
|
+
|
|
264
|
+
There is no required upgrade order. Hosts do not share state and can run different versions temporarily. However, keeping all hosts on the same version avoids confusion.
|
|
265
|
+
|
|
266
|
+
### Remote upgrade examples
|
|
267
|
+
|
|
268
|
+
#### macOS host over SSH
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
HOST=youruser@your-mac-host.lan
|
|
272
|
+
|
|
273
|
+
ssh $HOST "cd ~/.openclaw/scheduler && git pull && npm install"
|
|
274
|
+
ssh $HOST "cd ~/.openclaw/scheduler && SCHEDULER_DB=:memory: node test.js" 2>&1 | tail -5
|
|
275
|
+
ssh $HOST "launchctl kickstart -k gui/\$(id -u)/ai.openclaw.scheduler"
|
|
276
|
+
sleep 3
|
|
277
|
+
ssh $HOST "tail -5 /tmp/openclaw-scheduler.log && cd ~/.openclaw/scheduler && node cli.js status"
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### Linux / Windows WSL2 host over SSH
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
HOST=youruser@your-linux-host.lan
|
|
284
|
+
|
|
285
|
+
ssh $HOST "cd ~/.openclaw/scheduler && git pull && npm install"
|
|
286
|
+
ssh $HOST "cd ~/.openclaw/scheduler && SCHEDULER_DB=:memory: node test.js" 2>&1 | tail -5
|
|
287
|
+
ssh $HOST "systemctl --user restart openclaw-scheduler"
|
|
288
|
+
sleep 3
|
|
289
|
+
ssh $HOST "systemctl --user --no-pager --full status openclaw-scheduler && cd ~/.openclaw/scheduler && node cli.js status"
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### Windows native host via PowerShell Remoting
|
|
293
|
+
|
|
294
|
+
```powershell
|
|
295
|
+
$HOST = "your-windows-host"
|
|
296
|
+
|
|
297
|
+
Invoke-Command -ComputerName $HOST -ScriptBlock {
|
|
298
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
299
|
+
git pull
|
|
300
|
+
npm install
|
|
301
|
+
$env:SCHEDULER_DB=":memory:"
|
|
302
|
+
node test.js
|
|
303
|
+
pm2 restart openclaw-scheduler
|
|
304
|
+
Start-Sleep 3
|
|
305
|
+
pm2 logs openclaw-scheduler --lines 5 --nostream
|
|
306
|
+
node cli.js status
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Rollback
|
|
313
|
+
|
|
314
|
+
If the new version causes problems:
|
|
315
|
+
|
|
316
|
+
### Git-clone installs
|
|
317
|
+
|
|
318
|
+
#### macOS (launchd)
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
cd ~/.openclaw/scheduler
|
|
322
|
+
git log --oneline -5 # find the previous good commit
|
|
323
|
+
git checkout <commit-hash> # revert to it
|
|
324
|
+
npm install # restore matching dependencies
|
|
325
|
+
launchctl kickstart -k gui/$(id -u)/ai.openclaw.scheduler
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### Linux / Windows WSL2 (systemd)
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
cd ~/.openclaw/scheduler
|
|
332
|
+
git log --oneline -5
|
|
333
|
+
git checkout <commit-hash>
|
|
334
|
+
npm install
|
|
335
|
+
systemctl --user restart openclaw-scheduler
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
#### Windows native (PM2)
|
|
339
|
+
|
|
340
|
+
```powershell
|
|
341
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
342
|
+
git log --oneline -5
|
|
343
|
+
git checkout <commit-hash>
|
|
344
|
+
npm install
|
|
345
|
+
pm2 restart openclaw-scheduler
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### npm installs
|
|
349
|
+
|
|
350
|
+
#### macOS (launchd)
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
npm install --prefix ~/.openclaw/scheduler openclaw-scheduler@<previous-version>
|
|
354
|
+
launchctl kickstart -k gui/$(id -u)/ai.openclaw.scheduler
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### Linux / Windows WSL2 (systemd)
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
npm install --prefix ~/.openclaw/scheduler openclaw-scheduler@<previous-version>
|
|
361
|
+
systemctl --user restart openclaw-scheduler
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### Windows native (PM2)
|
|
365
|
+
|
|
366
|
+
```powershell
|
|
367
|
+
npm install --prefix $env:USERPROFILE\.openclaw\scheduler openclaw-scheduler@<previous-version>
|
|
368
|
+
pm2 restart openclaw-scheduler
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Schema rollback:** Downgrading the code does not undo schema migrations. New columns added by migrations are ignored by older code -- they use `DEFAULT` values and do not cause errors. If a migration added a new table, older code simply does not reference it. In practice, schema changes are forward-compatible and do not require manual rollback.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Provider plugins (v0.2)
|
|
376
|
+
|
|
377
|
+
If you use provider-backed identity, authorization, or proof verification, set
|
|
378
|
+
`SCHEDULER_PROVIDER_PATH` to a directory containing your provider `*.js` files.
|
|
379
|
+
This is a high-trust boundary: every file in that directory is dynamically imported
|
|
380
|
+
at scheduler startup. The directory must not be world-writable. See
|
|
381
|
+
`docs/gateway-contract.md` for the full provider plugin contract.
|
|
382
|
+
|
|
383
|
+
### Adopting jobs under agentcli
|
|
384
|
+
|
|
385
|
+
If you install agentcli after upgrading, you can adopt existing scheduler jobs
|
|
386
|
+
into declarative manifests. See [AGENTS.md](AGENTS.md#adding-agentcli-later-adopting-existing-jobs)
|
|
387
|
+
for the adoption flow and [README.md](README.md#adopting-existing-scheduler-jobs)
|
|
388
|
+
for detailed examples.
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Troubleshooting
|
|
393
|
+
|
|
394
|
+
### Tests fail after update
|
|
395
|
+
|
|
396
|
+
- Check the CHANGELOG for breaking changes or new prerequisites.
|
|
397
|
+
- Make sure `npm install` completed without errors.
|
|
398
|
+
- If `better-sqlite3` fails to load, run `npm rebuild better-sqlite3`.
|
|
399
|
+
|
|
400
|
+
### Service won't start after update
|
|
401
|
+
|
|
402
|
+
- Check the error log: `tail -20 /tmp/openclaw-scheduler.log`
|
|
403
|
+
- If the error is a missing module, run `npm install` again.
|
|
404
|
+
- If the error is a database issue, check the schema version matches what the new code expects.
|
|
405
|
+
|
|
406
|
+
### Gateway unreachable after update
|
|
407
|
+
|
|
408
|
+
The scheduler update does not affect the OpenClaw gateway. If the gateway is down, that is a separate issue. The scheduler logs `Gateway unreachable` on startup but continues running shell and main-session jobs.
|
|
409
|
+
|
|
410
|
+
### Node version changed
|
|
411
|
+
|
|
412
|
+
If Node was upgraded alongside the scheduler (e.g., `brew upgrade` updated both), the native `better-sqlite3` module needs rebuilding:
|
|
413
|
+
|
|
414
|
+
### macOS (launchd)
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
cd ~/.openclaw/scheduler
|
|
418
|
+
npm rebuild better-sqlite3
|
|
419
|
+
launchctl kickstart -k gui/$(id -u)/ai.openclaw.scheduler
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Linux / Windows WSL2 (systemd)
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
cd ~/.openclaw/scheduler
|
|
426
|
+
npm rebuild better-sqlite3
|
|
427
|
+
systemctl --user restart openclaw-scheduler
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Windows native (PM2)
|
|
431
|
+
|
|
432
|
+
```powershell
|
|
433
|
+
cd $env:USERPROFILE\.openclaw\scheduler
|
|
434
|
+
npm rebuild better-sqlite3
|
|
435
|
+
pm2 restart openclaw-scheduler
|
|
436
|
+
```
|
package/agents.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Agent registry -- track agent status and capabilities
|
|
2
|
+
import { getDb } from './db.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Register or update an agent.
|
|
6
|
+
*/
|
|
7
|
+
export function upsertAgent(id, opts = {}) {
|
|
8
|
+
if (!id || typeof id !== 'string') throw new Error('Agent id must be a non-empty string');
|
|
9
|
+
const db = getDb();
|
|
10
|
+
db.prepare(`
|
|
11
|
+
INSERT INTO agents (id, name, status, session_key, capabilities)
|
|
12
|
+
VALUES (?, ?, ?, ?, ?)
|
|
13
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
14
|
+
name = COALESCE(excluded.name, agents.name),
|
|
15
|
+
status = COALESCE(excluded.status, agents.status),
|
|
16
|
+
session_key = COALESCE(excluded.session_key, agents.session_key),
|
|
17
|
+
capabilities = COALESCE(excluded.capabilities, agents.capabilities),
|
|
18
|
+
last_seen_at = datetime('now')
|
|
19
|
+
`).run(
|
|
20
|
+
id,
|
|
21
|
+
opts.name || null,
|
|
22
|
+
opts.status || 'idle',
|
|
23
|
+
opts.session_key || null,
|
|
24
|
+
opts.capabilities ? JSON.stringify(opts.capabilities) : null
|
|
25
|
+
);
|
|
26
|
+
return getAgent(id);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get an agent by ID.
|
|
31
|
+
*/
|
|
32
|
+
export function getAgent(id) {
|
|
33
|
+
const agent = getDb().prepare('SELECT * FROM agents WHERE id = ?').get(id);
|
|
34
|
+
if (agent && agent.capabilities) {
|
|
35
|
+
try { agent.capabilities = JSON.parse(agent.capabilities); } catch (e) { process.stderr.write('Warning: failed to parse capabilities JSON: ' + e.message + '\n'); }
|
|
36
|
+
}
|
|
37
|
+
return agent;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* List all agents.
|
|
42
|
+
*/
|
|
43
|
+
export function listAgents() {
|
|
44
|
+
return getDb().prepare('SELECT * FROM agents ORDER BY id').all().map(a => {
|
|
45
|
+
if (a.capabilities) try { a.capabilities = JSON.parse(a.capabilities); } catch (e) { process.stderr.write('Warning: failed to parse capabilities JSON: ' + e.message + '\n'); }
|
|
46
|
+
return a;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Update agent status.
|
|
52
|
+
*/
|
|
53
|
+
export function setAgentStatus(id, status, sessionKey) {
|
|
54
|
+
getDb().prepare(`
|
|
55
|
+
UPDATE agents SET status = ?, session_key = ?, last_seen_at = datetime('now')
|
|
56
|
+
WHERE id = ?
|
|
57
|
+
`).run(status, sessionKey || null, id);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Mark agent as seen (heartbeat).
|
|
62
|
+
*/
|
|
63
|
+
export function touchAgent(id) {
|
|
64
|
+
getDb().prepare(`
|
|
65
|
+
UPDATE agents SET last_seen_at = datetime('now') WHERE id = ?
|
|
66
|
+
`).run(id);
|
|
67
|
+
}
|