Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.gateway.state

Gateway session manager.

One process-global registry over the live session fleet: per-session ordered event log (monotonic :seq, ring-buffered), SSE subscriber fan-out, async turn submission with idempotency keys, cancellation, and turn/cost metrics.

The engine is reached ONLY through the same internal surfaces the TUI/Telegram channels use: loop/create!-send!-close! for the lifecycle, :hooks {:on-chunk ...} phased chunks for the live stream, ctx-loop/session-snapshot for the context. No engine state lives here - this namespace owns wire bookkeeping (events, turn records, subscribers), nothing else.

Gateway session manager.

One process-global registry over the live session fleet: per-session
ordered event log (monotonic `:seq`, ring-buffered), SSE subscriber
fan-out, async turn submission with idempotency keys, cancellation,
and turn/cost metrics.

The engine is reached ONLY through the same internal surfaces the
TUI/Telegram channels use: `loop/create!`-`send!`-`close!` for the
lifecycle, `:hooks {:on-chunk ...}` phased chunks for the live
stream, `ctx-loop/session-snapshot` for the context. No engine state
lives here - this namespace owns wire bookkeeping (events, turn
records, subscribers), nothing else.
raw docstring

add-filesystem-root!clj

(add-filesystem-root! sid path)

Add path as an extra filesystem root for the session pinned to sid, then return the refreshed session-workspace-info. Runs SERVER-SIDE in the daemon so the draft backend-fork and DB write land where the session actually lives; every channel (web footer, TUI picker/footer) then reads the same roots back over the gateway. Channel-agnostic twin of set-session-model!.

Add `path` as an extra filesystem root for the session pinned to `sid`, then
return the refreshed `session-workspace-info`. Runs SERVER-SIDE in the daemon
so the draft backend-fork and DB write land where the session actually lives;
every channel (web footer, TUI picker/footer) then reads the same roots back
over the gateway. Channel-agnostic twin of `set-session-model!`.
sourceraw docstring

append-event!clj

(append-event! sid type payload)
(append-event! sid type payload {:keys [store?]})

Append one event for sid, fan it out to LOCAL subscribers, and publish it on the cross-process bus so watchers in OTHER processes stream it too.

Assigns the next monotonic :seq atomically. :store? false events are fanned out live but kept OUT of the replay ring, so neither a cursor replay nor a /poll pull (both read the ring) re-delivers them - reserve it for genuinely ephemeral fan-out where SSE/poll divergence is acceptable (no current caller; :store? defaults true). A subscriber sink that throws is dropped - one dead SSE connection must never poison the appender or sibling subscribers.

Append one event for `sid`, fan it out to LOCAL subscribers, and publish
it on the cross-process bus so watchers in OTHER processes stream it too.

Assigns the next monotonic `:seq` atomically. `:store? false` events
are fanned out live but kept OUT of the replay ring, so neither a
cursor replay nor a `/poll` pull (both read the ring) re-delivers
them - reserve it for genuinely ephemeral fan-out where SSE/poll
divergence is acceptable (no current caller; `:store?` defaults true).
A subscriber sink that throws is dropped - one dead SSE connection
must never poison the appender or sibling subscribers.
sourceraw docstring

assign-group!clj

(assign-group! sid gid)

Assign a session to gid (nil clears / ungroups). Returns the refreshed soul.

Assign a session to `gid` (nil clears / ungroups). Returns the refreshed soul.
sourceraw docstring

attach-turn-sync!clj

(attach-turn-sync! sid tid {:keys [on-event]})

Attach to an ALREADY-submitted turn tid on sid and block until it reaches a terminal event, returning the same engine-shaped result as submit-turn-sync!.

Creates NO new turn: it drives in-process (TUI) rendering for a turn the gateway queued and then auto-drains, so a busy-time submission becomes a real gateway queued record instead of a client-side shadow queue. Optional :on-event fires for every replay/live event of tid.

Attach to an ALREADY-submitted turn `tid` on `sid` and block until it reaches a
terminal event, returning the same engine-shaped result as `submit-turn-sync!`.

Creates NO new turn: it drives in-process (TUI) rendering for a turn the gateway
queued and then auto-drains, so a busy-time submission becomes a real gateway
queued record instead of a client-side shadow queue. Optional `:on-event` fires
for every replay/live event of `tid`.
sourceraw docstring

bus-wiringclj

source

cancel-turn!clj

(cancel-turn! sid tid)

Fire the cancellation token of a running turn. Returns {:status "cancelling"} or {:error ...}.

Fire the cancellation token of a running turn. Returns
`{:status "cancelling"}` or `{:error ...}`.
sourceraw docstring

change-root!clj

(change-root! sid path)

Repoint the session pinned to sid at path as its PRIMARY root, then return the refreshed session-workspace-info (whose :id is the newly pinned workspace). Server-side so the change lands in the daemon that runs the turns.

Repoint the session pinned to `sid` at `path` as its PRIMARY root, then return
the refreshed `session-workspace-info` (whose `:id` is the newly pinned
workspace). Server-side so the change lands in the daemon that runs the turns.
sourceraw docstring

close-session!clj

(close-session! sid)

DELETE a session: dispose the live environment, trash the session's draft clones (primary + auto-cloned filesystem roots — only DRAFTS have clones; a trunk workspace's roots are the user's real dirs and are never touched), then delete the session tree. Idempotent. NOTE: this is the DELETE path — merely quitting/closing a session (navigating away, no server call) keeps the draft intact so it can be resumed.

DELETE a session: dispose the live environment, trash the session's draft
clones (primary + auto-cloned filesystem roots — only DRAFTS have clones; a
trunk workspace's roots are the user's real dirs and are never touched),
then delete the session tree. Idempotent. NOTE: this is the DELETE path —
merely quitting/closing a session (navigating away, no server call) keeps
the draft intact so it can be resumed.
sourceraw docstring

context-snapshotclj

(context-snapshot sid)

The read-only ctx mirror the model sees as its bound session (ctx-loop/session-snapshot), for an existing session, ENRICHED for the USER with :session/archived (the GC'd/summarized entities that are no longer in the model's live ctx). Resolving the env through lp/env-for rehydrates an evicted session on demand. nil when the session does not exist.

The read-only ctx mirror the model sees as its bound `session`
(`ctx-loop/session-snapshot`), for an existing session, ENRICHED for
the USER with `:session/archived` (the GC'd/summarized entities that are
no longer in the model's live ctx). Resolving the env
through `lp/env-for` rehydrates an evicted session on demand.
nil when the session does not exist.
sourceraw docstring

create-group!clj

(create-group! opts)
source

create-session!clj

(create-session! {:keys [channel title external-id workspace-id root prewarm?]})

Create a fresh gateway-managed session. Defaults to :api, but in-process clients such as the TUI can pass :channel :tui and still use the same gateway turn/event machinery without pretending to be an HTTP client.

Create a fresh gateway-managed session. Defaults to `:api`, but in-process
clients such as the TUI can pass `:channel :tui` and still use the same
gateway turn/event machinery without pretending to be an HTTP client.
sourceraw docstring

current-seqclj

(current-seq sid)

Highest event :seq assigned for sid so far. Subscribing with this as the cursor yields a live-only stream (empty replay).

Highest event `:seq` assigned for `sid` so far. Subscribing with this
as the cursor yields a live-only stream (empty replay).
sourceraw docstring

delete-group!clj

(delete-group! gid)

Delete a group; its member sessions scatter back to ungrouped (never deleted).

Delete a group; its member sessions scatter back to ungrouped (never deleted).
sourceraw docstring

delete-queued-turn!clj

(delete-queued-turn! sid tid)

Remove a queued turn before it starts. Returns deleted status or an error.

Remove a queued turn before it starts. Returns deleted status or an error.
sourceraw docstring

events-sinceclj

(events-since sid cursor)

Read-only peek at the replay ring: stored events with :seq > cursor, oldest first. Lets a page renderer locate the running turn's turn.started seq so its SSE reconnect can replay the WHOLE in-flight turn instead of only what happens after connect.

Read-only peek at the replay ring: stored events with `:seq` > cursor,
oldest first. Lets a page renderer locate the running turn's
`turn.started` seq so its SSE reconnect can replay the WHOLE in-flight
turn instead of only what happens after connect.
sourceraw docstring

get-groupclj

(get-group gid)
source

get-turnclj

(get-turn sid tid)

Wire view of one turn record, or nil.

Wire view of one turn record, or nil.
sourceraw docstring

ingest-mirrored-event!clj

(ingest-mirrored-event! sid store? event)

Deliver a FOREIGN gateway event (produced in another process, arriving via the cross-process bus) into THIS process's registry so a web / Telegram / TUI watcher streams a turn running elsewhere in real time.

The foreign event is RE-SEQUENCED onto this process's OWN monotonic :seq, never the producer's. Each process runs an independent seq counter, but the SSE wire treats :seq as a single strictly-increasing per-connection cursor; adopting the producer's raw counter would let a watcher whose local seq is already past that value (e.g. it ran an earlier turn on this session) silently drop the entire foreign turn. Re-sequencing keeps THIS process's stream monotonic for its own subscribers regardless of the producer's counter — and is safe because only the producer persists the turn; the mirror is live-only.

Stored in the ring when store?; :current-turn mirrored so the session list lights up while the turn runs elsewhere. A running TURN ROW is materialized in :turns/:turn-order on turn.started (and marked terminal on turn.completed/turn.failed) so list-turns frames the mirrored turn exactly like a locally-started one — user bubble, running chip, correct live placement — instead of leaking bare deltas under the previous answer.

Ignores sessions this process has never touched (no local registry entry), so no state accrues for conversations nobody here is watching.

Deliver a FOREIGN gateway event (produced in another process, arriving via
the cross-process bus) into THIS process's registry so a web / Telegram /
TUI watcher streams a turn running elsewhere in real time.

The foreign event is RE-SEQUENCED onto this process's OWN monotonic `:seq`,
never the producer's. Each process runs an independent seq counter, but the
SSE wire treats `:seq` as a single strictly-increasing per-connection cursor;
adopting the producer's raw counter would let a watcher whose local seq is
already past that value (e.g. it ran an earlier turn on this session) silently
drop the entire foreign turn. Re-sequencing keeps THIS process's stream
monotonic for its own subscribers regardless of the producer's counter — and
is safe because only the producer persists the turn; the mirror is live-only.

Stored in the ring when `store?`; `:current-turn` mirrored so the session
list lights up while the turn runs elsewhere. A running TURN ROW is
materialized in `:turns`/`:turn-order` on `turn.started` (and marked terminal
on `turn.completed`/`turn.failed`) so `list-turns` frames the mirrored turn
exactly like a locally-started one — user bubble, running chip, correct live
placement — instead of leaking bare deltas under the previous answer.

Ignores sessions this process has never touched (no local registry entry), so
no state accrues for conversations nobody here is watching.
sourceraw docstring

list-groupsclj

(list-groups)
(list-groups opts)

Wire groups for one owner/channel view (see loop/groups). opts keys: :owner-id, :channel (keyword | :all/nil), :include-archived?.

Wire groups for one owner/channel view (see loop/groups). `opts` keys:
:owner-id, :channel (keyword | :all/nil), :include-archived?.
sourceraw docstring

list-sessionsclj

(list-sessions)
(list-sessions channel)

Wire souls for every persisted session.

CROSS-CHANNEL by default (channel = :all): a conversation started in the web is visible in the TUI and vice-versa. Pass a specific channel keyword only when a caller genuinely needs a single-channel slice (e.g. Telegram resolving a chat by external-id).

Wire souls for every persisted session.

CROSS-CHANNEL by default (`channel` = `:all`): a conversation started
in the web is visible in the TUI and vice-versa. Pass a specific
channel keyword only when a caller genuinely needs a single-channel
slice (e.g. Telegram resolving a chat by external-id).
sourceraw docstring

list-turnsclj

(list-turns sid)

Wire views of every turn for sid, newest first: persisted history hydrated from the engine DB (survives daemon restarts), plus only genuinely live gateway overlay rows (running/queued or terminal rows not yet visible in persistence).

DEDUP: the gateway's tid is NOT the engine's persisted row id - the engine mints its own id inside send!. Once the durable row is visible, prefer it: it owns the iteration trace. Keeping the completed gateway row alongside the persisted row rendered the last request/response twice after refresh, with the transient duplicate missing the iterations disclosure.

Wire views of every turn for `sid`, newest first: persisted history hydrated
from the engine DB (survives daemon restarts), plus only genuinely live gateway
overlay rows (running/queued or terminal rows not yet visible in persistence).

DEDUP: the gateway's `tid` is NOT the engine's persisted row id - the engine
mints its own id inside `send!`. Once the durable row is visible, prefer it:
it owns the iteration trace. Keeping the completed gateway row alongside the
persisted row rendered the last request/response twice after refresh, with the
transient duplicate missing the iterations disclosure.
sourceraw docstring

metrics-snapshotclj

(metrics-snapshot)

Global + per-session counters for /metrics.

Global + per-session counters for /metrics.
sourceraw docstring

reconcile-running-turns!clj

(reconcile-running-turns!)

Gateway facade for startup/client resume reconciliation of orphaned running turns.

Gateway facade for startup/client resume reconciliation of orphaned running turns.
sourceraw docstring

release-session!clj

(release-session! sid)

Release the live runtime for a session while keeping persisted data resumable.

This is the gateway facade for local clients that are merely closing a view (for example a TUI tab or process exit). Use close-session! for DELETE.

Background resources (shell_bg processes, managed REPLs) are STOPPED here: closing the view is the user walking away, and a bg child must not outlive that — the transcript stays resumable, the processes do not.

Release the live runtime for a session while keeping persisted data resumable.

This is the gateway facade for local clients that are merely closing a view
(for example a TUI tab or process exit). Use `close-session!` for DELETE.

Background resources (shell_bg processes, managed REPLs) are STOPPED here:
closing the view is the user walking away, and a bg child must not outlive
that — the transcript stays resumable, the processes do not.
sourceraw docstring

remove-filesystem-root!clj

(remove-filesystem-root! sid path)

Remove path from the session's extra filesystem roots and return the refreshed session-workspace-info. Server-side twin of add-filesystem-root!.

Remove `path` from the session's extra filesystem roots and return the
refreshed `session-workspace-info`. Server-side twin of `add-filesystem-root!`.
sourceraw docstring

running-turn-countclj

(running-turn-count)

Number of live turns currently owned by this gateway process. Used by the daemon lifecycle gate: the server may only self-stop when this is zero AND the client refcount is zero.

Number of live turns currently owned by this gateway process. Used by the
daemon lifecycle gate: the server may only self-stop when this is zero AND
the client refcount is zero.
sourceraw docstring

session-modelclj

(session-model sid)

The session's persisted model preference as {:provider :model} (DB-backed shared store), or nil for the router default.

The session's persisted model preference as `{:provider :model}`
(DB-backed shared store), or nil for the router default.
sourceraw docstring

session-model-cachedclj

(session-model-cached sid)

Cached variant of session-model for hot render paths. Still part of the gateway facade: callers do not reach into the session-model store directly.

Cached variant of `session-model` for hot render paths. Still part of the
gateway facade: callers do not reach into the session-model store directly.
sourceraw docstring

session-workspace-infoclj

(session-workspace-info sid)

Workspace state for a channel surface (the web footer AND the TUI directory picker): {:id :draft? :root :repo-root :label :fork-ms :filesystem-roots} for the session pinned to sid (soul id), or nil. :id is the workspace-id every filesystem-root mutation (add/remove-filesystem-root!) needs — WITHOUT it the TUI picker treats the session as read-only and C-a silently no-ops. :filesystem-roots is the normalized [{:trunk :clone :fork-ms}]. Lets the footer announce that the session — and its extra roots — are isolated drafts. Resolves soul → latest state → workspace; never throws.

Workspace state for a channel surface (the web footer AND the TUI
directory picker): `{:id :draft? :root :repo-root :label :fork-ms
:filesystem-roots}` for the session pinned to `sid` (soul id), or nil.
`:id` is the workspace-id every filesystem-root mutation
(`add/remove-filesystem-root!`) needs — WITHOUT it the TUI picker treats the
session as read-only and C-a silently no-ops. `:filesystem-roots` is the
normalized `[{:trunk :clone :fork-ms}]`. Lets the footer announce that the
session — and its extra roots — are isolated drafts. Resolves soul → latest
state → workspace; never throws.
sourceraw docstring

set-session-model!clj

(set-session-model! sid provider model)

Set (or clear, with blank model) the per-session PROVIDER + MODEL preference. Every turn submitted for sid routes through it (the engine reads it at turn start; router-for-model hoists the model, an unknown name degrades to the default order). Channel-agnostic: web + TUI + embedded callers all set it here, persisted in the DB and shared across channels.

Set (or clear, with blank model) the per-session PROVIDER + MODEL
preference. Every turn submitted for `sid` routes through it (the engine
reads it at turn start; `router-for-model` hoists the model, an unknown
name degrades to the default order). Channel-agnostic: web + TUI + embedded
callers all set it here, persisted in the DB and shared across channels.
sourceraw docstring

set-title!clj

(set-title! sid title)
source

soulclj

(soul sid)

Wire soul for one session: persisted record + live gateway status.

Wire soul for one session: persisted record + live gateway status.
sourceraw docstring

submit-turn!clj

(submit-turn! sid
              {:keys [request messages idempotency-key model reasoning-default
                      cancel-token extra-body turn-features workspace
                      engine-opts attachments]})

Submit one turn for sid. Async: starts immediately when idle, otherwise queues.

Returns {:turn record} (plus :idempotent? true on an idempotency replay) or {:error :session-not-found | :invalid-request, ...}. One engine turn still runs per session; busy submissions become visible queued records.

Submit one turn for `sid`. Async: starts immediately when idle, otherwise queues.

Returns `{:turn record}` (plus `:idempotent? true` on an idempotency
replay) or `{:error :session-not-found | :invalid-request, ...}`. One engine
turn still runs per session; busy submissions become visible queued records.
sourceraw docstring

submit-turn-sync!clj

(submit-turn-sync! sid {:keys [on-event] :as opts})

Submit one turn through the gateway and block until that turn reaches a terminal event.

Accepts the same request keys as submit-turn!; optional :on-event is called for every replay/live event for the submitted turn. Returns an engine-shaped result map for in-process clients (CLI/TUI/Telegram) that need a blocking call without bypassing the canonical gateway machinery.

Submit one turn through the gateway and block until that turn reaches a terminal event.

Accepts the same request keys as `submit-turn!`; optional `:on-event` is called
for every replay/live event for the submitted turn. Returns an engine-shaped
result map for in-process clients (CLI/TUI/Telegram) that need a blocking
call without bypassing the canonical gateway machinery.
sourceraw docstring

subscribe!clj

(subscribe! sid sub-id sink cursor)

Register an SSE sink and return the replay vector (events with :seq > cursor) ATOMICALLY with the registration, so no event can fall between replay and live fan-out. The caller serializes replay writes against live sink calls (see server.clj).

Before capturing replay, HYDRATE any turn currently running in a sibling process from the cross-process journal (bus/hydrate!) — but only when this process isn't already tracking a live turn (:current-turn unset), so an already-mirrored turn isn't re-delivered to existing subscribers. This materializes the running turn's row + ring HERE, so a watcher joining a turn in flight elsewhere replays it from turn.started (user bubble + running frame) instead of catching only the bare deltas after connect.

Register an SSE sink and return the replay vector (events with
`:seq` > `cursor`) ATOMICALLY with the registration, so no event can
fall between replay and live fan-out. The caller serializes replay
writes against live sink calls (see server.clj).

Before capturing replay, HYDRATE any turn currently running in a sibling
process from the cross-process journal (`bus/hydrate!`) — but only when this
process isn't already tracking a live turn (`:current-turn` unset), so an
already-mirrored turn isn't re-delivered to existing subscribers. This
materializes the running turn's row + ring HERE, so a watcher joining a turn
in flight elsewhere replays it from `turn.started` (user bubble + running
frame) instead of catching only the bare deltas after connect.
sourceraw docstring

title-listenerclj

source

transcriptclj

(transcript sid)

Rich persisted transcript rows for sid in THE canonical wire shape (wire/canonical): turns oldest-first, each carrying its persisted iteration rows under :iterations. Canonicalizing AT THE SOURCE makes the HTTP hop an identity — an in-process reader and a remote gateway client (TUI / web / mobile) see the SAME maps, so there is exactly ONE transcript shape and a channel can never again be written against a shape only one transport sees.

Rich persisted transcript rows for `sid` in THE canonical wire shape
(`wire/canonical`): turns oldest-first, each carrying its persisted iteration
rows under `:iterations`. Canonicalizing AT THE SOURCE makes the HTTP hop an
identity — an in-process reader and a remote gateway client (TUI / web /
mobile) see the SAME maps, so there is exactly ONE transcript shape and a
channel can never again be written against a shape only one transport sees.
sourceraw docstring

turn-traceclj

(turn-trace tid)

THE canonical wire trace of ONE persisted turn: its iteration rows (each with hydrated :attachments re-read from the attachment store) through wire/canonical, same as transcript — canonicalizing AT THE SOURCE keeps the HTTP hop an identity, so the in-process web channel and a remote client (TUI / mobile) render from the SAME maps. Returns a (possibly empty) vector for a valid turn id, nil for an unparsable id or a read failure — callers use nil to fall back / retry.

THE canonical wire trace of ONE persisted turn: its iteration rows (each
with hydrated `:attachments` re-read from the attachment store) through
`wire/canonical`, same as [[transcript]] — canonicalizing AT THE SOURCE
keeps the HTTP hop an identity, so the in-process web channel and a remote
client (TUI / mobile) render from the SAME maps. Returns a (possibly empty)
vector for a valid turn id, nil for an unparsable id or a read failure —
callers use nil to fall back / retry.
sourceraw docstring

unsubscribe!clj

(unsubscribe! sid sub-id)
source

update-group!clj

(update-group! gid opts)
source

update-queued-turn!clj

(update-queued-turn! sid tid request)

Replace the prompt text for a queued turn. Returns the updated turn or an error.

Replace the prompt text for a queued turn. Returns the updated turn or an error.
sourceraw docstring

warm-db!clj

(warm-db!)

Force the persistence backend + shared connection on the CALLER's thread. The gateway runs this on its single-threaded boot path so the heavyweight backend namespace never lazy-loads under request concurrency (see require-backend-ns! in internal/persistance.clj).

Force the persistence backend + shared connection on the CALLER's
thread. The gateway runs this on its single-threaded boot path so
the heavyweight backend namespace never lazy-loads under request
concurrency (see require-backend-ns! in internal/persistance.clj).
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close