diff --git a/docs/concepts/markdown-formatting.md b/docs/concepts/markdown-formatting.md index d1b8e8ca5d5..e54833cf9fb 100644 --- a/docs/concepts/markdown-formatting.md +++ b/docs/concepts/markdown-formatting.md @@ -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) + + + Outbound streaming behavior, chunk boundaries, and channel-specific delivery. + + + What the model sees before the conversation, including injected workspace files. + + diff --git a/docs/concepts/presence.md b/docs/concepts/presence.md index 3c6b1f14098..0d8f9c7261c 100644 --- a/docs/concepts/presence.md +++ b/docs/concepts/presence.md @@ -7,12 +7,12 @@ read_when: title: "Presence" --- -OpenClaw “presence” is a lightweight, best‑effort 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 app’s **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`: human‑friendly host name -- `ip`: best‑effort 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, one‑off 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 in‑memory 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 case‑insensitive. +- 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 client‑reported +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 connection‑derived 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) + + + When typing indicators are sent and how to tune them. + + + Outbound streaming, chunking, and per-channel formatting. + + + Gateway components and the WebSocket protocol that drives presence updates. + + + The wire protocol for `connect`, `system-event`, and `system-presence`. + + diff --git a/docs/concepts/typing-indicators.md b/docs/concepts/typing-indicators.md index bc1c5874468..f69d0ccdf55 100644 --- a/docs/concepts/typing-indicators.md +++ b/docs/concepts/typing-indicators.md @@ -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 won’t 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 doesn’t emit reasoning deltas, typing won’t 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) + + + How the Gateway tracks connected clients and surfaces them in the macOS Instances tab. + + + Outbound streaming behavior, chunk boundaries, and channel-specific delivery. + +