openclaw-agentmail-listener 0.4.2 → 0.4.3
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/README.md +30 -4
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,19 +63,45 @@ Subject: Hello there
|
|
|
63
63
|
Preview: This is the first 200 chars of the email body...
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
The event is keyed with `contextKey: agentmail:<messageId>`
|
|
66
|
+
The event is keyed with `contextKey: cron:agentmail:<messageId>` so it is both deduplicated and surfaced in the heartbeat prompt (see [How wake works](#how-wake-works) for details).
|
|
67
67
|
|
|
68
68
|
## How wake works
|
|
69
69
|
|
|
70
|
-
After enqueuing a system event, the plugin calls `requestHeartbeatNow()`
|
|
70
|
+
After enqueuing a system event, the plugin calls `requestHeartbeatNow()` with reason `"exec-event"`. This does two things:
|
|
71
|
+
|
|
72
|
+
1. **Bypasses file gates** — the heartbeat fires immediately without requiring HEARTBEAT.md
|
|
73
|
+
2. **Inspects pending events** — the enqueued system event is included in the heartbeat prompt
|
|
74
|
+
|
|
75
|
+
The `cron:` prefix on the contextKey ensures the event passes through OpenClaw's `hasTaggedCronEvents` check, which enables event inspection and renders the email content via `buildCronEventPrompt`. Without this prefix, the event would be enqueued but silently discarded from the prompt.
|
|
76
|
+
|
|
77
|
+
> **Why not `reason: "wake"`?** The `"wake"` reason bypasses file gates but does _not_ enable `shouldInspectPendingEvents` in the heartbeat runner, so system events are ignored. `"exec-event"` enables both.
|
|
78
|
+
|
|
79
|
+
**Important config for proactive delivery:**
|
|
80
|
+
|
|
81
|
+
The heartbeat `target` must be set to a channel (e.g. `"whatsapp"`, `"telegram"`) or `"last"` — otherwise the agent processes the email but the response is silently dropped (default target is `"none"`).
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"agents": {
|
|
86
|
+
"defaults": {
|
|
87
|
+
"heartbeat": {
|
|
88
|
+
"every": "1h",
|
|
89
|
+
"target": "whatsapp"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Note:** The `requests-in-flight` check is global — if any conversation is active on any channel, the wake is deferred (retries every 1s until the queue clears).
|
|
71
97
|
|
|
72
98
|
## Architecture
|
|
73
99
|
|
|
74
100
|
- **Raw WebSocket** — connects directly to `wss://ws.agentmail.to/v0` with API key as query param (no SDK dependency for the WebSocket layer)
|
|
75
101
|
- **Reconnection** — exponential backoff (1s → 2s → 4s → ... → 60s max) with ±10% jitter
|
|
76
102
|
- **Keepalive** — sends WebSocket pings every 30 seconds
|
|
77
|
-
- **In-process wake** — uses `api.runtime.system.requestHeartbeatNow()` (no HTTP round-trips)
|
|
78
|
-
- **System events** — uses `api.runtime.system.enqueueSystemEvent()`
|
|
103
|
+
- **In-process wake** — uses `api.runtime.system.requestHeartbeatNow()` with `reason: "exec-event"` (no HTTP round-trips)
|
|
104
|
+
- **System events** — uses `api.runtime.system.enqueueSystemEvent()` with `cron:`-prefixed contextKey to ensure prompt visibility
|
|
79
105
|
|
|
80
106
|
## Dependencies
|
|
81
107
|
|
package/dist/index.js
CHANGED
|
@@ -192,10 +192,10 @@ function handleEventInner(api, cfg, event) {
|
|
|
192
192
|
const sessionKey = cfg.sessionKey ?? "agent:main:main";
|
|
193
193
|
api.runtime.system.enqueueSystemEvent(eventText, {
|
|
194
194
|
sessionKey,
|
|
195
|
-
contextKey: `agentmail:${messageId}`
|
|
195
|
+
contextKey: `cron:agentmail:${messageId}`
|
|
196
196
|
});
|
|
197
197
|
api.runtime.system.requestHeartbeatNow({
|
|
198
|
-
reason: "
|
|
198
|
+
reason: "exec-event",
|
|
199
199
|
sessionKey
|
|
200
200
|
});
|
|
201
201
|
api.logger.info("agentmail-listener: heartbeat wake requested");
|