openclaw-scheduler 0.2.3 → 0.2.5

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/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.2.5] -- 2026-04-27
6
+
7
+ ### Fixed
8
+ - fix(dispatch): make completion prompts task-aware so `dispatch done` no longer implies `tests_passed:true` / `pushed:true` for tasks that explicitly should not push or do not require tests
9
+ - fix(dispatch): recover completion text conservatively from terminal assistant turns instead of treating arbitrary mid-task chatter as the final delivery payload
10
+ - fix(watcher): surface real missed-`done` final reports as interrupted diagnostics instead of silently timing out without useful delivery context
11
+ - fix(dispatch): prefer structured, human-readable completion summaries and suppress generic/internal completion noise in announce flows
12
+ - fix(dispatch): preserve embedded completion summaries, prefer explicit delivery targets for origin detection, and normalize dispatched completion delivery behavior
13
+ - fix(dispatch): harden literal-safe prompt input handling and watcher SIGTERM handoff during delivery/recovery paths
14
+
15
+ ### Added
16
+ - feat(dispatch): prefer structured human completion summaries in dispatch delivery flows
17
+ - feat(dispatch): add inbox watcher delivery guardrail to catch broken packaged-layout consumer wiring earlier
18
+
19
+ ## [0.2.4] -- 2026-04-18
20
+
21
+ ### Fixed
22
+ - fix(package): include dispatch/completion.mjs in the published npm tarball so dispatch CLI and watcher startup no longer crash with ERR_MODULE_NOT_FOUND in installed deployments
23
+
5
24
  ## [0.2.3] -- 2026-04-16
6
25
 
7
26
  ### Fixed
package/README.md CHANGED
@@ -1728,7 +1728,7 @@ npm test
1728
1728
 
1729
1729
  ## Sub-agent Dispatch
1730
1730
 
1731
- The dispatch module (`dispatch/index.mjs`) spawns and steers isolated agent sessions via the OpenClaw Gateway API and tracks them by a human-readable label. Unlike the scheduler's job/run model, dispatch calls the gateway directly -- no scheduler tick delay, no DB write required to start a session. Each session is assigned a unique session key, recorded in a local `labels.json` ledger, and auto-announces its result when the agent calls `done` as its final action. The module also supports symlink-based branding: a wrapper directory (such as `my-brand`) contains a `config.json` with a custom name and a symlink to `dispatch/index.mjs`, giving the same CLI a different identity in notifications and logs.
1731
+ The dispatch module (`dispatch/index.mjs`) spawns and steers isolated agent sessions via the OpenClaw Gateway API and tracks them by a human-readable label. Unlike the scheduler's job/run model, dispatch calls the gateway directly -- no scheduler tick delay, no DB write required to start a session. Each session is assigned a unique session key, recorded in a local `labels.json` ledger, and delivered back through a scheduler watcher when the agent calls `done` as its final action. That watcher is the only final-delivery path for dispatched jobs, and it normalizes completions into short human-readable summaries before posting them to chat. The module also supports symlink-based branding: a wrapper directory (such as `my-brand`) contains a `config.json` with a custom name and a symlink to `dispatch/index.mjs`, giving the same CLI a different identity in notifications and logs.
1732
1732
 
1733
1733
  ### Quick Example
1734
1734
 
@@ -1746,25 +1746,35 @@ openclaw-scheduler enqueue \
1746
1746
  # Fallback (if openclaw-scheduler is not in PATH):
1747
1747
  node ~/.openclaw/scheduler/dispatch/index.mjs enqueue \
1748
1748
  --label "fix-deploy-script" --message "..." --deliver-to YOUR_CHAT_ID
1749
+
1750
+ # Literal-safe prompt input when the text contains shell metacharacters:
1751
+ cat prompt.md | openclaw-scheduler enqueue \
1752
+ --label "fix-deploy-script" \
1753
+ --message-stdin \
1754
+ --deliver-to YOUR_CHAT_ID
1749
1755
  ```
1750
1756
 
1757
+ For normal chat-triggered dispatches, always pass `--deliver-to` from the inbound metadata `chat_id`. If you omit `--origin`, dispatch now derives it from that explicit delivery target instead of guessing from whichever session was active most recently. The old active-session lookup is kept only as a manual/local fallback when both values are absent.
1758
+
1751
1759
  ### Flag Reference
1752
1760
 
1753
1761
  | Flag | Default | Description |
1754
1762
  |------|---------|-------------|
1755
1763
  | `--label` | required | Human-readable name for the session. Used for status lookups, reuse, and watchdog tracking. |
1756
1764
  | `--message` | required* | Prompt sent to the agent. |
1757
- | `--message-file` | -- | Path to a file whose contents are used as the prompt. Alternative to `--message`; avoids shell-escaping issues with long prompts. |
1765
+ | `--message-file` | -- | Path to a file whose contents are used as the prompt. Use `-` to read from stdin. Safer than inline shell quoting for prompts with backticks, quotes, or markdown. |
1766
+ | `--message-env` | -- | Environment variable name whose value is used as the prompt. Useful when the prompt contains shell-significant characters. |
1767
+ | `--message-stdin` | -- | Read the prompt from stdin explicitly. If stdin is piped and no explicit prompt source is set, dispatch auto-reads stdin. |
1758
1768
  | `--mode` | `fresh` | `fresh` creates a new session. `reuse` continues the last session recorded for this label. |
1759
1769
  | `--thinking` | -- | Reasoning budget: `low`, `high`, or `xhigh`. |
1760
1770
  | `--model` | -- | Model override, e.g. `anthropic/claude-sonnet-4-6`. |
1761
- | `--deliver-to` | -- | Delivery target (e.g. Telegram chat ID). Registers a scheduler watcher job for reliable at-least-once delivery. |
1771
+ | `--deliver-to` | -- | Delivery target (e.g. Telegram chat ID). Registers the scheduler watcher job for durable final delivery. The gateway spawn itself stays fire-and-forget so raw tool output and internal done payloads cannot leak directly to chat. Chat-triggered callers should pass inbound metadata `chat_id` here, especially for group chats. |
1762
1772
  | `--delivery-mode` | `announce` | `announce` delivers only when output is non-empty. `announce-always` delivers unconditionally. `none` suppresses delivery. |
1763
1773
  | `--timeout` | `300` | Session timeout in seconds. |
1764
1774
  | `--monitor` | on | Auto-register a watchdog job that alerts if the session goes silent past the configured threshold. |
1765
1775
  | `--no-monitor` | -- | Disable watchdog registration for this dispatch. |
1766
1776
 
1767
- *Either `--message` or `--message-file` is required.
1777
+ *One prompt source is required: `--message`, `--message-file`, `--message-env`, `--message-stdin`, or piped stdin.
1768
1778
 
1769
1779
  ### Subcommand Reference
1770
1780
 
@@ -1775,7 +1785,7 @@ node ~/.openclaw/scheduler/dispatch/index.mjs enqueue \
1775
1785
  | `stuck` | Check all running sessions against the stuck threshold. Exits 1 if genuinely stuck sessions remain after auto-resolving completed ones. |
1776
1786
  | `result` | Retrieve the last assistant reply from a session transcript via `chat.history`. |
1777
1787
  | `sync` | Reconcile `labels.json` with sessions store state. Auto-marks sessions as done or error based on idle time. Supports `--dry-run`. |
1778
- | `done` | Agent-side completion signal. The agent calls this as its final action to mark itself done immediately (push-based; no idle timeout wait). |
1788
+ | `done` | Agent-side completion signal. The agent calls this as its final action to mark itself done immediately (push-based; no idle timeout wait). The stored completion payload is normalized for channel-safe delivery, with checklist/sha metadata used as a fallback when the raw summary is generic or noisy. |
1779
1789
  | `send` | Inject a message into a running session for mid-run steering. The agent sees it as a new user turn. |
1780
1790
  | `steer` | Alias for `send`. The name makes steering intent explicit. |
1781
1791
  | `heartbeat` | Check whether a session has been active within the last 10 minutes. Accepts `--label` or `--session-key`. |
@@ -1808,7 +1818,7 @@ openclaw-scheduler enqueue \
1808
1818
  --message "Update the API docs to reflect the new /v2 endpoints" \
1809
1819
  --thinking high --timeout 600 --deliver-to YOUR_CHAT_ID
1810
1820
 
1811
- # Each worker auto-announces its result to the configured channel when done.
1821
+ # Each worker gets a watcher-delivered, channel-safe completion summary when done.
1812
1822
  # No polling needed. Watchdog jobs are auto-registered for each.
1813
1823
  ```
1814
1824
 
package/cli.js CHANGED
@@ -100,8 +100,8 @@ Queue:
100
100
  queue prune Prune old messages now
101
101
 
102
102
  Messages:
103
- messages send --from <label> [--to <agent>] [--kind <kind>] --body "<text>"
104
- Send a checkpoint/status message (kind defaults to 'status', to defaults to 'main')
103
+ messages send --from <label> [--to <agent>] [--kind <kind>] [--channel <channel>] [--delivery-to <target>] --body "<text>"
104
+ Send a checkpoint/status message (kind defaults to 'status', to defaults to 'main'; channel/delivery-to override inbox-consumer defaults)
105
105
  msg send <from> <to> <body> Send a message (positional form)
106
106
  msg inbox <agent-id> [limit] Get inbox (unread)
107
107
  msg team-inbox <team-id> [limit] [member-id] [task-id] Get team mailbox
@@ -610,10 +610,19 @@ switch (command) {
610
610
  const mTo = mFlags.to || 'main';
611
611
  const mKind = mFlags.kind || 'status';
612
612
  const mBody = mFlags.body;
613
+ const mChannel = mFlags.channel || null;
614
+ const mDeliveryTo = mFlags['delivery-to'] || null;
613
615
  if (!mFrom || !mBody) {
614
- fail('Usage: messages send --from <label> [--to <agent>] [--kind <kind>] --body "<text>"');
616
+ fail('Usage: messages send --from <label> [--to <agent>] [--kind <kind>] [--channel <channel>] [--delivery-to <target>] --body "<text>"');
615
617
  }
616
- const msg = sendMessage({ from_agent: mFrom, to_agent: mTo, kind: mKind, body: mBody });
618
+ const msg = sendMessage({
619
+ from_agent: mFrom,
620
+ to_agent: mTo,
621
+ kind: mKind,
622
+ body: mBody,
623
+ channel: mChannel,
624
+ delivery_to: mDeliveryTo,
625
+ });
617
626
  emit({ ok: true, message: msg }, `Sent: ${fmt(msg)}`);
618
627
  break;
619
628
  }
@@ -68,27 +68,38 @@ node dispatch/index.mjs enqueue \
68
68
  --deliver-to YOUR_CHAT_ID \
69
69
  --deliver-channel telegram \
70
70
  --delivery-mode announce
71
+
72
+ # Literal-safe prompt input for shell-sensitive text:
73
+ cat prompt.md | node dispatch/index.mjs enqueue \
74
+ --label "ticket-43" \
75
+ --message-stdin \
76
+ --delivery-mode none
71
77
  ```
72
78
 
73
79
  | Flag | Default | Description |
74
80
  |---|---|---|
75
81
  | `--label` | required | Human name — used for lookup/reuse |
76
- | `--message` | required | Prompt sent to the agent |
82
+ | `--message` | required* | Prompt sent to the agent |
83
+ | `--message-file` | — | Read prompt text from a file. Use `-` to read from stdin. Safer than inline shell quoting for prompts with backticks, quotes, or markdown. |
84
+ | `--message-env` | — | Read prompt text from an environment variable. |
85
+ | `--message-stdin` | — | Read prompt text from stdin explicitly. If stdin is piped and no explicit source is set, dispatch auto-reads stdin. |
77
86
  | `--mode` | `fresh` | `fresh` = new session; `reuse` = continue last session for this label |
78
87
  | `--session-key` | — | Explicit session key (bypasses ledger lookup) |
79
88
  | `--agent` | `main` | Agent ID |
80
89
  | `--model` | — | Model override (e.g. `anthropic/claude-sonnet-4-6`) |
81
90
  | `--thinking` | — | Reasoning level: `low`, `high`, `xhigh` |
82
91
  | `--timeout` | `300` | Seconds before run times out |
83
- | `--deliver-to` | — | Delivery target (chat ID, channel ID, handle, etc.). Enables `deliver:true` on the gateway call |
92
+ | `--deliver-to` | — | Delivery target (chat ID, channel ID, handle, etc.). Enables `deliver:true` on the gateway call. Chat-triggered callers should pass inbound metadata `chat_id` here, especially for group chats. |
84
93
  | `--deliver-channel` | `telegram` | Delivery channel for `--deliver-to` (telegram, slack, etc.) |
85
94
  | `--delivery-mode` | `announce` | `announce`, `announce-always`, `none` |
86
- | `--origin` | -- | Dispatch origin (e.g. `telegram:12345`) |
95
+ | `--origin` | -- | Dispatch origin (e.g. `telegram:12345`). If omitted but `--deliver-to` is explicit, dispatch derives origin from that target. Active-session auto-detect is fallback for manual/local use only. |
87
96
  | `--no-monitor` | false | Skip watcher monitoring |
88
97
  | `--monitor-interval` | -- | Watcher cron expression |
89
98
  | `--monitor-timeout` | -- | Watcher timeout in minutes |
90
99
  | `--verify-cmd` | -- | Post-completion verification command |
91
100
 
101
+ *One prompt source is required: `--message`, `--message-file`, `--message-env`, `--message-stdin`, or piped stdin.
102
+
92
103
  ### `status` — session status for a label
93
104
 
94
105
  ```bash
@@ -151,6 +162,10 @@ Notes:
151
162
  node dispatch/index.mjs send \
152
163
  --label "ticket-42" \
153
164
  --message "Tests still failing on line 42, focus on the edge case"
165
+
166
+ cat <<'EOF' | node dispatch/index.mjs send --label "ticket-42" --message-stdin
167
+ Use literal `code`, quotes, and $(examples) safely
168
+ EOF
154
169
  ```
155
170
 
156
171
  Sends a message directly into the running session. The agent sees it as a new