Wire encoding for the HTTP gateway.
One dumb, deterministic boundary: engine EDN -> JSON. Keyword/symbol
keys become snake_case strings (namespace dropped), keyword VALUES keep
their full ns/name (a badge role like :tool-color/search must survive
the hop — dropping the namespace made the remote TUI see :search while
the hop), non-JSON leaves fall back to str. The walker makes zero semantic
or rendering decisions. Canonical message content is already a string-keyed
vector of typed block maps before it reaches this boundary.
canonical is the SAME shape on the Clojure side: by definition what
parse-json ∘ json-str yields — snake_case STRING keys — serve it from
a facade and in-process readers see exactly what a remote client sees.
Wire encoding for the HTTP gateway. One dumb, deterministic boundary: engine EDN -> JSON. Keyword/symbol keys become snake_case strings (namespace dropped), keyword VALUES keep their full `ns/name` (a badge role like `:tool-color/search` must survive the hop — dropping the namespace made the remote TUI see `:search` while the hop), non-JSON leaves fall back to `str`. The walker makes zero semantic or rendering decisions. Canonical message content is already a string-keyed vector of typed block maps before it reaches this boundary. `canonical` is the SAME shape on the Clojure side: by definition what `parse-json` ∘ `json-str` yields — snake_case STRING keys — serve it from a facade and in-process readers see exactly what a remote client sees.
(->wire x)Recursively convert an engine value into JSON-encodable data.
Recursively convert an engine value into JSON-encodable data.
(bounded-pr x limit)Bounded pr-str for tool results / errors riding events. Protects the
event log and SSE frames from multi-megabyte values.
Bounded `pr-str` for tool results / errors riding events. Protects the event log and SSE frames from multi-megabyte values.
(bounded-str s limit)Bounded plain-string clamp for an ALREADY-rendered value (e.g. the
model-facing render-form-value string) — same megabyte protection as
bounded-pr but WITHOUT re-pr-str'ing, so the string rides the wire
verbatim instead of quoted/escaped.
Bounded plain-string clamp for an ALREADY-rendered value (e.g. the model-facing `render-form-value` string) — same megabyte protection as `bounded-pr` but WITHOUT re-`pr-str`'ing, so the string rides the wire verbatim instead of quoted/escaped.
(canonical x)THE canonical gateway value shape — snake_case STRING map keys, exactly
what a remote client holds after parse-json ∘ json-str. In-process and
remote consumers therefore read the same role-labelled messages and typed
content blocks.
Invariant: (canonical x) equals (parse-json (json-str x)).
THE canonical gateway value shape — snake_case STRING map keys, exactly what a remote client holds after `parse-json` ∘ `json-str`. In-process and remote consumers therefore read the same role-labelled messages and typed content blocks. Invariant: `(canonical x)` equals `(parse-json (json-str x))`.
(json-str x)Encode any engine value as a JSON string via ->wire.
Encode any engine value as a JSON string via [[->wire]].
(json-str-pretty x)Pretty-printed (2-space indent) JSON via ->wire — for
HUMAN-facing surfaces (the web ctx rail's trailer view), never the
wire itself.
Pretty-printed (2-space indent) JSON via [[->wire]] — for HUMAN-facing surfaces (the web ctx rail's trailer view), never the wire itself.
(parse-json s)Parse a JSON string into the canonical wire shape: snake_case STRING map
keys, identical to canonical. Returns nil on blank or malformed input
(callers map that to 400).
Parse a JSON string into the canonical wire shape: snake_case STRING map keys, identical to [[canonical]]. Returns nil on blank or malformed input (callers map that to 400).
Queue lifecycle event types every attached channel mirrors LIVE even when
they belong to a DIFFERENT (queued) turn of the same session — the ONE set
both transports forward (the in-process gateway.state subscriptions AND
the SSE loop in gateway.client), so a message queued/edited/deleted in
one channel shows up in every sibling. turn.queued.drained marks the
queue head leaving the queue because the gateway auto-STARTED it, so
mirrors drop the entry and a replayed history nets to zero
(turn.queued … turn.queued.drained). queue.paused/queue.resumed carry
the provider-health lane state (held count, breaker) so every sibling shows
the same paused banner and unpauses together.
Queue lifecycle event types every attached channel mirrors LIVE even when they belong to a DIFFERENT (queued) turn of the same session — the ONE set both transports forward (the in-process `gateway.state` subscriptions AND the SSE loop in `gateway.client`), so a message queued/edited/deleted in one channel shows up in every sibling. `turn.queued.drained` marks the queue head leaving the queue because the gateway auto-STARTED it, so mirrors drop the entry and a replayed history nets to zero (`turn.queued` … `turn.queued.drained`). `queue.paused`/`queue.resumed` carry the provider-health lane state (held count, breaker) so every sibling shows the same paused banner and unpauses together.
(sse-frame event)Render one canonical (string-keyed) event map as an SSE frame. The event's
"seq" doubles as the SSE id: so Last-Event-ID reconnects resume
losslessly.
Render one canonical (string-keyed) event map as an SSE frame. The event's `"seq"` doubles as the SSE `id:` so `Last-Event-ID` reconnects resume losslessly.
Wire keys of a settled turn's META (usage/routing/timing) — the fields
terminal-event->result (both the in-process gateway.state impl and the
SSE gateway.client twin) resolves for the sync submit/attach result.
Terminal events are deliberately LEAN ({:turn_id :status}), so these are
read primarily from the registry's turn row (merged by finish-turn!),
with any event-carried value winning. ONE list so the two impls can't
drift.
Wire keys of a settled turn's META (usage/routing/timing) — the fields
`terminal-event->result` (both the in-process `gateway.state` impl and the
SSE `gateway.client` twin) resolves for the sync submit/attach result.
Terminal events are deliberately LEAN (`{:turn_id :status}`), so these are
read primarily from the registry's turn row (merged by `finish-turn!`),
with any event-carried value winning. ONE list so the two impls can't
drift.(wire-key k)Keyword/symbol map key -> snake_case string. A boolean-style foo? key
becomes is_foo (already-is- prefixed keys just drop the ?). String
keys (fact keys, scope strings, file paths) pass VERBATIM - rewriting
them could corrupt user data that legitimately contains hyphens.
Keyword/symbol map key -> snake_case string. A boolean-style `foo?` key becomes `is_foo` (already-`is-` prefixed keys just drop the `?`). String keys (fact keys, scope strings, file paths) pass VERBATIM - rewriting them could corrupt user data that legitimately contains hyphens.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |