docs(concepts): typography hygiene + Related CardGroups across 3 pages

docs/concepts/presence.md: replaced 8 curly quote and non-breaking
hyphen characters (U+201C/U+201D/U+2019/U+2011) with ASCII equivalents
so grep, copy-paste, and Mintlify search hit the right tokens.
Converted the 2-bullet Related list into a CardGroup adding cross-links
to gateway architecture and gateway protocol since presence is produced
by both surfaces.

docs/concepts/markdown-formatting.md: replaced 5 typography characters
(en-dash and curly quotes) with ASCII equivalents and converted the
2-bullet Related list into a CardGroup pointing at streaming/chunking
and system prompt.

docs/concepts/typing-indicators.md: replaced 4 typography characters
with ASCII equivalents and converted the 2-bullet Related list into a
CardGroup with the same Presence and Streaming cross-links.

Verified /concepts/streaming, /concepts/system-prompt,
/concepts/architecture, and /gateway/protocol targets all exist.
This commit is contained in:
Vincent Koc
2026-05-05 18:30:39 -07:00
parent 29ddcc688e
commit 7f71e84248
3 changed files with 50 additions and 26 deletions

View File

@@ -39,14 +39,14 @@ stay consistent across channels.
Input Markdown:
```markdown
Hello **world** see [docs](https://docs.openclaw.ai).
Hello **world** - see [docs](https://docs.openclaw.ai).
```
IR (schematic):
```json
{
"text": "Hello world see docs.",
"text": "Hello world - see docs.",
"styles": [{ "start": 6, "end": 11, "style": "bold" }],
"links": [{ "start": 19, "end": 23, "href": "https://docs.openclaw.ai" }]
}
@@ -129,5 +129,11 @@ SPOILER style ranges. Other channels treat them as plain text.
## Related
- [Streaming and chunking](/concepts/streaming)
- [System prompt](/concepts/system-prompt)
<CardGroup cols={2}>
<Card title="Streaming and chunking" href="/concepts/streaming" icon="bars-staggered">
Outbound streaming behavior, chunk boundaries, and channel-specific delivery.
</Card>
<Card title="System prompt" href="/concepts/system-prompt" icon="message-lines">
What the model sees before the conversation, including injected workspace files.
</Card>
</CardGroup>

View File

@@ -7,12 +7,12 @@ read_when:
title: "Presence"
---
OpenClaw presence is a lightweight, besteffort view of:
OpenClaw "presence" is a lightweight, best-effort view of:
- the **Gateway** itself, and
- **clients connected to the Gateway** (mac app, WebChat, CLI, etc.)
Presence is used primarily to render the macOS apps **Instances** tab and to
Presence is used primarily to render the macOS app's **Instances** tab and to
provide quick operator visibility.
## Presence fields (what shows up)
@@ -20,12 +20,12 @@ provide quick operator visibility.
Presence entries are structured objects with fields like:
- `instanceId` (optional but strongly recommended): stable client identity (usually `connect.client.instanceId`)
- `host`: humanfriendly host name
- `ip`: besteffort IP address
- `host`: human-friendly host name
- `ip`: best-effort IP address
- `version`: client version string
- `deviceFamily` / `modelIdentifier`: hardware hints
- `mode`: `ui`, `webchat`, `cli`, `backend`, `probe`, `test`, `node`, ...
- `lastInputSeconds`: seconds since last user input (if known)
- `lastInputSeconds`: "seconds since last user input" (if known)
- `reason`: `self`, `connect`, `node-connected`, `periodic`, ...
- `ts`: last update timestamp (ms since epoch)
@@ -35,7 +35,7 @@ Presence entries are produced by multiple sources and **merged**.
### 1) Gateway self entry
The Gateway always seeds a self entry at startup so UIs show the gateway host
The Gateway always seeds a "self" entry at startup so UIs show the gateway host
even before any clients connect.
### 2) WebSocket connect
@@ -45,7 +45,7 @@ Gateway upserts a presence entry for that connection.
#### Why one-off CLI commands do not show up
The CLI often connects for short, oneoff commands. To avoid spamming the
The CLI often connects for short, one-off commands. To avoid spamming the
Instances list, `client.mode === "cli"` is **not** turned into a presence entry.
### 3) `system-event` beacons
@@ -60,11 +60,11 @@ upserts a presence entry for that node (same flow as other WS clients).
## Merge + dedupe rules (why `instanceId` matters)
Presence entries are stored in a single inmemory map:
Presence entries are stored in a single in-memory map:
- Entries are keyed by a **presence key**.
- The best key is a stable `instanceId` (from `connect.client.instanceId`) that survives restarts.
- Keys are caseinsensitive.
- Keys are case-insensitive.
If a client reconnects without a stable `instanceId`, it may show up as a
**duplicate** row.
@@ -81,7 +81,7 @@ This keeps the list fresh and avoids unbounded memory growth.
## Remote/tunnel caveat (loopback IPs)
When a client connects over an SSH tunnel / local port forward, the Gateway may
see the remote address as `127.0.0.1`. To avoid overwriting a good clientreported
see the remote address as `127.0.0.1`. To avoid overwriting a good client-reported
IP, loopback remote addresses are ignored.
## Consumers
@@ -97,9 +97,21 @@ indicator (Active/Idle/Stale) based on the age of the last update.
- If you see duplicates:
- confirm clients send a stable `client.instanceId` in the handshake
- confirm periodic beacons use the same `instanceId`
- check whether the connectionderived entry is missing `instanceId` (duplicates are expected)
- check whether the connection-derived entry is missing `instanceId` (duplicates are expected)
## Related
- [Typing indicators](/concepts/typing-indicators)
- [Streaming and chunking](/concepts/streaming)
<CardGroup cols={2}>
<Card title="Typing indicators" href="/concepts/typing-indicators" icon="ellipsis">
When typing indicators are sent and how to tune them.
</Card>
<Card title="Streaming and chunking" href="/concepts/streaming" icon="bars-staggered">
Outbound streaming, chunking, and per-channel formatting.
</Card>
<Card title="Gateway architecture" href="/concepts/architecture" icon="diagram-project">
Gateway components and the WebSocket protocol that drives presence updates.
</Card>
<Card title="Gateway protocol" href="/gateway/protocol" icon="plug">
The wire protocol for `connect`, `system-event`, and `system-presence`.
</Card>
</CardGroup>

View File

@@ -23,15 +23,15 @@ When `agents.defaults.typingMode` is **unset**, OpenClaw keeps the legacy behavi
Set `agents.defaults.typingMode` to one of:
- `never` no typing indicator, ever.
- `instant` start typing **as soon as the model loop begins**, even if the run
- `never` - no typing indicator, ever.
- `instant` - start typing **as soon as the model loop begins**, even if the run
later returns only the silent reply token.
- `thinking` start typing on the **first reasoning delta** (requires
- `thinking` - start typing on the **first reasoning delta** (requires
`reasoningLevel: "stream"` for the run).
- `message` start typing on the **first non-silent text delta** (ignores
- `message` - start typing on the **first non-silent text delta** (ignores
the `NO_REPLY` silent token).
Order of how early it fires:
Order of "how early it fires":
`never``message``thinking``instant`
## Configuration
@@ -58,11 +58,11 @@ You can override mode or cadence per session:
## Notes
- `message` mode wont show typing for silent-only replies when the whole
- `message` mode won't show typing for silent-only replies when the whole
payload is the exact silent token (for example `NO_REPLY` / `no_reply`,
matched case-insensitively).
- `thinking` only fires if the run streams reasoning (`reasoningLevel: "stream"`).
If the model doesnt emit reasoning deltas, typing wont start.
If the model doesn't emit reasoning deltas, typing won't start.
- 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.
@@ -74,5 +74,11 @@ You can override mode or cadence per session:
## Related
- [Presence](/concepts/presence)
- [Streaming and chunking](/concepts/streaming)
<CardGroup cols={2}>
<Card title="Presence" href="/concepts/presence" icon="signal">
How the Gateway tracks connected clients and surfaces them in the macOS Instances tab.
</Card>
<Card title="Streaming and chunking" href="/concepts/streaming" icon="bars-staggered">
Outbound streaming behavior, chunk boundaries, and channel-specific delivery.
</Card>
</CardGroup>