@dreb/coding-agent 2.64.0 → 2.64.1

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/docs/dashboard.md CHANGED
@@ -183,6 +183,20 @@ bytes, then browser-facing live events, replay, hydrate/resync, parent messages,
183
183
  and subagent messages carry only an ID, MIME type, and original binary size.
184
184
  Authoritative RPC/session history is not changed.
185
185
 
186
+ In dashboard mode the child applies the same reduction one boundary earlier,
187
+ before JSONL serialization: each unique image (exact MIME type plus decoded
188
+ bytes) crosses the child stdout pipe at most once per child process lifetime,
189
+ and every later occurrence — prompt re-emission, each tool-result re-delivery,
190
+ the `agent_end` transcript — becomes the small `image_reference` frame the
191
+ dashboard already understands. The dashboard's image cache holds the binary
192
+ from the first-occurrence event, so references resolve without the slow
193
+ authoritative reload. The child turns a block into a reference only when this
194
+ strict decode accepts it (allowlisted MIME type, canonical base64, matching
195
+ byte signature); anything it would reject stays inline at every occurrence and
196
+ is dropped exactly as before — never becoming an unresolvable reference.
197
+ Command responses (`get_messages`, `get_dashboard_snapshot`) always carry full
198
+ payloads because they are the authoritative source image recovery reads.
199
+
186
200
  The browser-local `dreb.dashboard.imageDisplayMode` setting has three modes:
187
201
 
188
202
  - **placeholders** — assign no image `src` and make no request until preview or
@@ -285,7 +299,7 @@ normally. Replay and resync retain their ordering guarantees below.
285
299
 
286
300
  The top bar and persistent session header expose the live-stream state as an accessible text `output`, not color alone: **connecting**, **connected**, **retrying** (including its delay), **resyncing**, **disconnected**, or **auth failed**. The session-header indicator remains visible when the session details or composer controls are collapsed. This is the state of the dashboard's single SSE connection, not the state of an individual agent.
287
301
 
288
- Events are `{seq, key, event}` envelopes. The server retains a **projected** form of reducer-relevant events in a ring bounded by both entry count and encoded bytes; a reconnect can replay only a separately byte-bounded range. Projection removes cumulative fields the browser reducer does not use, rather than silently truncating an event. If history is too old or the requested replay exceeds budget, only that reconnect receives a `dashboard_resync` barrier at the current cursor; healthy browsers are not interrupted. A projected event whose **non-image content** is itself oversized emits a global barrier because every browser missed it; image blocks have already become small references before frame sizing. A slow client's write buffer is bounded too: backpressure closes that SSE connection, then the normal recovery path takes over.
302
+ Events are `{seq, key, event}` envelopes. The server retains a **projected** form of reducer-relevant events in a ring bounded by both entry count and encoded bytes; a reconnect can replay only a separately byte-bounded range. Projection removes cumulative fields the browser reducer does not use, rather than silently truncating an event. If history is too old or the requested replay exceeds budget, only that reconnect receives a `dashboard_resync` barrier at the current cursor; healthy browsers are not interrupted. A projected event whose **non-image content** is itself oversized emits a global barrier because every browser missed it; image blocks have already become small references before frame sizing. A slow client's write buffer is bounded too: backpressure closes that SSE connection, then the normal recovery path takes over. The RPC child side is bounded as well: its stdout write queue may accumulate past **16 MiB** while a slow-but-alive consumer keeps making drain progress, and a backlog over **16 MiB** aborts the child only after **30 seconds without drain progress**, so a briefly stalled dashboard consumer survives multi-image bursts instead of losing the session.
289
303
 
290
304
  On a barrier, protocol error, reducer error, server restart, sequence gap, or stalled stream, the browser fetches the authoritative `/api/resync` snapshot. For an active runtime, its state (including the atomically replaced task list), transcript, and background-agent registry are paired with the EventHub sequence captured synchronously at the RPC snapshot marker. The HTTP response carries that `barrierSeq`; the browser discards queued envelopes through it, then applies strictly later envelopes. A viewed subagent transcript has its own earlier disk-read boundary so relays between the disk and parent snapshot are also restored. This ordering prevents duplicate or missing transcript/task changes and restores tasks after a hard refresh or recovery gap. The barrier is an ordering contract, not a timing delay; see [Dashboard snapshots](rpc.md#get_dashboard_snapshot).
291
305
 
package/docs/rpc.md CHANGED
@@ -18,6 +18,12 @@ await client.start();
18
18
 
19
19
  This enables per-user filesystem isolation by plain Unix DAC: give each authenticated user a dedicated UID and a working directory owned by that UID at mode `0700`. If the parent lacks the required capability (or the platform doesn't support `uid`/`gid`, e.g. Windows), the spawn fails and `start()` rejects rather than silently running as the parent user.
20
20
 
21
+ ### Process exit and pipe errors
22
+
23
+ `RpcClient.onExit(listener)` receives an `RpcExitInfo` when the child dies: `{ code, signal }` from a process `exit`, or `{ error }` from a spawn/runtime `error`. Process exits also carry `stderrTail` — the last **2000 characters** of the child's captured stderr — so a host that only watches for exit codes can still surface the child's own diagnostic (for example the stdout backpressure guard's abort message) instead of an opaque exit code. In-flight requests are rejected with the exit reason.
24
+
25
+ Child stdio pipe failures (e.g. an `EPIPE` when writing a large prompt to a dying child) are handled the same way: each pipe's `error` event fails in-flight requests with the pipe error and the captured stderr tail instead of crashing the host process.
26
+
21
27
 
22
28
  ## Starting RPC Mode
23
29
 
@@ -1871,6 +1877,14 @@ When the RPC server is launched with `--ui dashboard`, `message_update` events a
1871
1877
 
1872
1878
  The projection applies recursively to `message_update` events nested inside `background_agent_event` payloads. It does **not** apply to command responses — `get_dashboard_snapshot` still returns complete messages — and `message_end` always carries the full final message as the authoritative transcript record. RPC servers launched without `--ui dashboard` emit the full unprojected protocol shown above.
1873
1879
 
1880
+ The same dashboard-mode projection also dedupes images across the wire. Inline `image` blocks (PNG, JPEG, GIF, WebP) are content-identified by `sha256(mimeType + 0x00 + decodedBytes)`; the first occurrence of each unique image is sent inline, and every later occurrence anywhere in the event stream is replaced with
1881
+
1882
+ ```json
1883
+ {"type": "image_reference", "id": "<64 hex chars>", "mimeType": "image/png", "size": 12345}
1884
+ ```
1885
+
1886
+ The child process emits each unique image's bytes at most once per process lifetime, which keeps multi-image turns from filling the stdout pipe while the dashboard is busy decoding. The child only dedupes blocks the dashboard's strict decode accepts — allowlisted MIME type, canonical base64, matching byte signature; everything else is left inline at every occurrence (the dashboard rejects it, as before, so it never becomes an unresolvable reference). Command responses are untouched — `get_messages` and `get_dashboard_snapshot` always carry full base64 payloads — and the dedupe state is per-process: a restarted child re-sends. See [Transcript images](dashboard.md#transcript-images) for how the dashboard resolves these references.
1887
+
1874
1888
  ### tool_execution_start / tool_execution_update / tool_execution_end
1875
1889
 
1876
1890
  Emitted when a tool begins, streams progress, and completes execution.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreb/coding-agent",
3
- "version": "2.64.0",
3
+ "version": "2.64.1",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "drebConfig": {