Show typing while heartbeats are running (#69963)

* Heartbeat: show typing during runs

* Heartbeat: fix typing review issues

* Discord: preserve heartbeat typing config
This commit is contained in:
pashpashpash
2026-04-21 21:50:27 -07:00
committed by GitHub
parent d4f91a354e
commit 89932593bb
21 changed files with 554 additions and 13 deletions

View File

@@ -1,2 +1,2 @@
cf3b7869a6870b51bfab5543a27f5f55a2754c59c268906d33b4da91352ab9bb plugin-sdk-api-baseline.json
6938561c972c419925ac17eb10d5d857502d339603de2cf4ece127827676da5f plugin-sdk-api-baseline.jsonl
10f07ebae3910cfe7639c54fb97ec4011c5f8be8a5444b86d23f075f9a49cc4c plugin-sdk-api-baseline.json
fdc165b2d06f00d195e326c2d28176da5cdeb8f8b05df4ec28466d384d57a07b plugin-sdk-api-baseline.jsonl

View File

@@ -18,7 +18,8 @@ When `agents.defaults.typingMode` is **unset**, OpenClaw keeps the legacy behavi
- **Direct chats**: typing starts immediately once the model loop begins.
- **Group chats with a mention**: typing starts immediately.
- **Group chats without a mention**: typing starts only when message text begins streaming.
- **Heartbeat runs**: typing is disabled.
- **Heartbeat runs**: typing starts when the heartbeat run begins if the
resolved heartbeat target is a typing-capable chat and typing is not disabled.
## Modes
@@ -64,6 +65,11 @@ You can override mode or cadence per session:
matched case-insensitively).
- `thinking` only fires if the run streams reasoning (`reasoningLevel: "stream"`).
If the model doesnt emit reasoning deltas, typing wont start.
- Heartbeats never show typing, regardless of mode.
- Heartbeat typing is a liveness signal for the resolved delivery target. It
starts at heartbeat run start instead of following `message` or `thinking`
stream timing. Set `typingMode: "never"` to disable it.
- Heartbeats do not show typing when `target: "none"`, when the target cannot
be resolved, when chat delivery is disabled for the heartbeat, or when the
channel does not support typing.
- `typingIntervalSeconds` controls the **refresh cadence**, not the start time.
The default is 6 seconds.

View File

@@ -262,6 +262,9 @@ Use `accountId` to target a specific account on multi-account channels like Tele
outbound message is sent.
- If `showOk`, `showAlerts`, and `useIndicator` are all disabled, the run is skipped up front as `reason=alerts-disabled`.
- If only alert delivery is disabled, OpenClaw can still run the heartbeat, update due-task timestamps, restore the session idle timestamp, and suppress the outward alert payload.
- If the resolved heartbeat target supports typing, OpenClaw shows typing while
the heartbeat run is active. This uses the same target the heartbeat would
send chat output to, and it is disabled by `typingMode: "never"`.
- Heartbeat-only replies do **not** keep the session alive; the last `updatedAt`
is restored so idle expiry behaves normally.
- Detached [background tasks](/automation/tasks) can enqueue a system event and wake heartbeat when the main session should notice something quickly. That wake does not make the heartbeat run a background task.

View File

@@ -31,10 +31,17 @@ shared `message` tool in core. Your plugin owns:
- **Session grammar** — how provider-specific conversation ids map to base chats, thread ids, and parent fallbacks
- **Outbound** — sending text, media, and polls to the platform
- **Threading** — how replies are threaded
- **Heartbeat typing** — optional typing/busy signals for heartbeat delivery targets
Core owns the shared message tool, prompt wiring, the outer session-key shape,
generic `:thread:` bookkeeping, and dispatch.
If your channel supports typing indicators outside inbound replies, expose
`heartbeat.sendTyping(...)` on the channel plugin. Core calls it with the
resolved heartbeat delivery target before the heartbeat model run starts and
uses the shared typing keepalive/cleanup lifecycle. Add `heartbeat.clearTyping(...)`
when the platform needs an explicit stop signal.
If your channel adds message-tool params that carry media sources, expose those
param names through `describeMessageTool(...).mediaSourceParams`. Core uses
that explicit list for sandbox path normalization and outbound media-access