Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.channel.events

Process-local channel event bus.

Extensions use this to talk to mounted channels without depending on their implementation namespaces. Channels subscribe while running and translate events into their local state/events. No listener failure may take down the publisher or sibling listeners.

Process-local channel event bus.

Extensions use this to talk to mounted channels without depending on their
implementation namespaces. Channels subscribe while running and translate
events into their local state/events. No listener failure may take down the
publisher or sibling listeners.
raw docstring

com.blockether.vis.internal.channel.file-picker

Backend for file-picking UIs (the @ mention picker, TUI + web).

Everything here rides the ONE canonical pooled fff index (internal.fff-index) that the grep tool use: fff owns the tree walk, the gitignore policy, the git-status metadata and the frecency-ranked fuzzy match. This namespace only leases that index and turns fff rows into display rows.

There is deliberately NO Clojure-side directory walk, git-status subprocess, ignore matcher or scoring heuristic left in here — reintroducing one means the picker and the search tools would rank and see different files.

Backend for file-picking UIs (the `@` mention picker, TUI + web).

Everything here rides the ONE canonical pooled fff index
(`internal.fff-index`) that the `grep` tool use: fff owns the
tree walk, the gitignore policy, the git-status metadata and the
frecency-ranked fuzzy match. This namespace only leases that index and turns
fff rows into display rows.

There is deliberately NO Clojure-side directory walk, git-status subprocess,
ignore matcher or scoring heuristic left in here — reintroducing one means the
picker and the search tools would rank and see different files.
raw docstring

com.blockether.vis.internal.channel.form

The canonical per-form DISPLAY contract — ONE source of truth for the fields a channel reads to render an executed form, live (via the gateway) and restored (via the DB).

Why this exists: the SAME field set used to be hand-listed in independent allowlists across the loop, persistence, gateway, progress, and restored display paths. Now every layer projects the WHOLE set through ->display (outbound) / <-wire (inbound), so a new display field is a ONE-line change to display-keys and form-roundtrip-test fails if a boundary stops carrying it.

Transformed fields (:stdout/:error bounded, :silent/:duration_ms renamed) stay as explicit gateway overrides — they are not carried verbatim, so they are NOT in this set.

The canonical per-form DISPLAY contract — ONE source of truth for the fields a
channel reads to render an executed form, live (via the gateway) and restored
(via the DB).

Why this exists: the SAME field set used to be hand-listed in independent
allowlists across the loop, persistence, gateway, progress, and restored display
paths. Now every layer projects the WHOLE set through `->display` (outbound) /
`<-wire` (inbound), so a new display field is a ONE-line change to
`display-keys` and `form-roundtrip-test` fails if a boundary stops carrying it.

Transformed fields (`:stdout`/`:error` bounded, `:silent`/`:duration_ms`
renamed) stay as explicit gateway overrides — they are not carried verbatim, so
they are NOT in this set.
raw docstring

com.blockether.vis.internal.channel.header

Channel-agnostic header layout & content spec.

Every channel — the terminal TUI and future surfaces — renders the same conceptual header band:

[LEFT 30%]   [CENTER 40% workspace switcher]   [RIGHT 30%]

The decisions a channel cannot make on its own (slot ratios, workspace switcher sizing/visibility caps, default labels, copy id length, glyphs) live here as plain Clojure data. A channel imports this namespace, reads the values, and projects them onto its medium — TextGraphics cells for Lanterna, and so on.

No graphics. No I/O. No channel-specific deps. Pure data + tiny pure helpers, written as .cljc so a future ClojureScript client can require it directly.

Channel-agnostic header layout & content spec.

Every channel — the terminal TUI and future surfaces —
renders the same conceptual header band:

    [LEFT 30%]   [CENTER 40% workspace switcher]   [RIGHT 30%]

The decisions a channel cannot make on its own (slot ratios, workspace
switcher sizing/visibility caps, default labels, copy id length, glyphs)
live here as plain Clojure data. A channel imports this namespace,
reads the values, and projects them onto its medium — TextGraphics
cells for Lanterna, and so on.

No graphics. No I/O. No channel-specific deps. Pure data + tiny
pure helpers, written as `.cljc` so a future ClojureScript client can
require it directly.
raw docstring

com.blockether.vis.internal.channel.notifications

Cross-channel ephemeral notifications.

A single in-memory pub-sub the host runtime, every extension, and every channel can use to surface a transient signal - "copied to clipboard", "tests passed", "provider switched" - without embedding it in the answer body or polluting Telemere logs.

Surface (re-exported on com.blockether.vis.core):

(notify! text) (notify! text :level :info|:success|:warn|:error :ttl-ms <long>|nil) (notifications) ;; vec of currently-active entries (dismiss! id) ;; force-clear by id (clear-expired!) ;; prune; called on every read (watch! key (fn [vec] ...)) ;; cross-channel reactivity (unwatch! key)

Entry shape: {:id <uuid> :text <string> :level :info | :success | :warn | :error :created-at <inst> :until <epoch-ms> | nil ;; nil = sticky / manual dismiss

Levels are advisory metadata for channels: TUI uses them for colour, the CLI could prefix [notice] / [warn]. The host stores them but never interprets them.

Why a flat module instead of a generic event bus: notifications are a single, narrow concern. A 50-line atom + watcher map serves it without introducing a generic pub-sub abstraction nobody asked for. If we ever grow more event types, this becomes one consumer of a richer system.

Cross-channel ephemeral notifications.

A single in-memory pub-sub the host runtime, every extension, and
every channel can use to surface a transient signal - "copied to
clipboard", "tests passed", "provider switched" - without
embedding it in the answer body or polluting Telemere logs.

Surface (re-exported on `com.blockether.vis.core`):

  (notify! text)
  (notify! text :level :info|:success|:warn|:error
                :ttl-ms <long>|nil)
  (notifications)              ;; vec of currently-active entries
  (dismiss! id)                ;; force-clear by id
  (clear-expired!)             ;; prune; called on every read
  (watch! key (fn [vec] ...))    ;; cross-channel reactivity
  (unwatch! key)

Entry shape:
  {:id          <uuid>
   :text        <string>
   :level       :info | :success | :warn | :error
   :created-at  <inst>
   :until       <epoch-ms> | nil   ;; nil = sticky / manual dismiss

Levels are advisory metadata for channels: TUI uses them for
colour, the CLI could prefix `[notice]` /
`[warn]`. The host stores them but never interprets them.

Why a flat module instead of a generic event bus: notifications
are a single, narrow concern. A 50-line atom + watcher map serves
it without introducing a generic pub-sub abstraction nobody asked
for. If we ever grow more event types, this becomes one consumer
of a richer system.
raw docstring

com.blockether.vis.internal.channel.render

Transient Markdown parsing and renderer projections.

Canonical answers are role-labelled, string-keyed content blocks from com.blockether.vis.internal.content. Parsed Markdown trees are created only inside renderers and are never transported or persisted.

markdown->ast parses prose for renderer-local layout. render, extract-code, extract-text, and session->markdown are disposable projections; none of their intermediate trees are canonical message data.

Transient Markdown parsing and renderer projections.

Canonical answers are role-labelled, string-keyed content blocks from
`com.blockether.vis.internal.content`. Parsed Markdown trees are created only
inside renderers and are never transported or persisted.

`markdown->ast` parses prose for renderer-local layout. `render`,
`extract-code`, `extract-text`, and `session->markdown` are disposable
projections; none of their intermediate trees are canonical message data.
raw docstring

com.blockether.vis.internal.channel.slash

Channel-agnostic slash dispatch.

Slashes are DECLARATIVE: every extension carries :ext/slash-commands on its manifest; the engine derives the active slash set by walking (active-extensions environment) at lookup time. NO global atom, NO register-slash! imperative call.

Public surface (re-exported through core.clj):

(active-slashes env) -> vec of slash specs (slash-by-path env path) -> slash spec or nil (slash-children env parent) -> vec of slash specs whose :slash/parent = parent (parse text) -> {:path :args :raw} | nil (raw tokenisation only; does NOT consult any registry) (dispatch env ctx text) -> envelope (see below)

The dispatch envelope is the contract every channel renders against:

{:handled? true :result <slash result map> :path path} {:handled? true :error msg :reason :unknown :tokens tokens} {:handled? true :error msg :reason :requires-failed :missing #{} :path} {:handled? true :error msg :reason :unavailable :path} {:handled? true :error msg :reason :no-run-fn :path} {:handled? true :error msg :reason :run-failed :ex t :path} {:handled? false} -- text was not a slash; channel forwards to LLM.

A slash text is any non-blank string starting with / followed by at least one word. Plain prose without the leading / is ALWAYS {:handled? false}.

Slash run-fns may return an EXTENDED :slash/* envelope that carries a rendered result card back to the channel:

{:slash/status :ok | :error | :nothing-to-commit | :ff-failed :slash/title short headline (string, plain) :slash/body IR (vector starting with :ir ...) OR Markdown string :slash/actions [{:label :slash}] ;; optional follow-ups :slash/data arbitrary payload (workspace-id, sha, ...)}

Channel-agnostic slash dispatch.

Slashes are DECLARATIVE: every extension carries `:ext/slash-commands`
on its manifest; the engine derives the active slash set by walking
`(active-extensions environment)` at lookup time. NO global atom, NO
`register-slash!` imperative call.

Public surface (re-exported through `core.clj`):

  (active-slashes  env)              -> vec of slash specs
  (slash-by-path   env path)         -> slash spec or nil
  (slash-children  env parent)       -> vec of slash specs whose
                                        `:slash/parent` = parent
  (parse           text)             -> {:path :args :raw} | nil
                                        (raw tokenisation only;
                                         does NOT consult any registry)
  (dispatch        env ctx text)     -> envelope (see below)

The dispatch envelope is the contract every channel renders against:

  {:handled? true  :result <slash result map> :path path}
  {:handled? true  :error msg :reason :unknown :tokens tokens}
  {:handled? true  :error msg :reason :requires-failed :missing #{} :path}
  {:handled? true  :error msg :reason :unavailable :path}
  {:handled? true  :error msg :reason :no-run-fn :path}
  {:handled? true  :error msg :reason :run-failed :ex t :path}
  {:handled? false}  -- text was not a slash; channel forwards to LLM.

A slash text is any non-blank string starting with `/` followed by
at least one word. Plain prose without the leading `/` is ALWAYS
{:handled? false}.

Slash run-fns may return an EXTENDED `:slash/*` envelope that carries
a rendered result card back to the channel:

  {:slash/status :ok | :error | :nothing-to-commit | :ff-failed
   :slash/title  short headline (string, plain)
   :slash/body   IR (vector starting with :ir ...) OR Markdown string
   :slash/actions [{:label :slash}]   ;; optional follow-ups
   :slash/data    arbitrary payload (workspace-id, sha, ...)}
raw 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