Shared tiny string helpers. A dependency-free leaf so any namespace can use it without risking a cycle.
Shared tiny string helpers. A dependency-free leaf so any namespace can use it without risking a cycle.
(fence-delimiter body)Markdown fence delimiter (a backtick run) longer than any backtick run in
body. Arbitrary content — a file being read, a diff of a Markdown file, a
tool's stdout — carries Markdown fences of its own; a fixed triple-backtick
wrapper is then ambiguous and the INNER fence closes the outer block early,
so everything after it renders as prose instead of code. CommonMark permits
longer fences: pick the shortest safe one.
Markdown fence delimiter (a backtick run) longer than any backtick run in `body`. Arbitrary content — a file being read, a diff of a Markdown file, a tool's stdout — carries Markdown fences of its own; a fixed triple-backtick wrapper is then ambiguous and the INNER fence closes the outer block early, so everything after it renders as prose instead of code. CommonMark permits longer fences: pick the shortest safe one.
(fenced body)(fenced body lang)Wrap body in a fenced code block body itself cannot close early, with an
optional lang info string. Callers keep their own blank/nil guards.
Wrap `body` in a fenced code block `body` itself cannot close early, with an optional `lang` info string. Callers keep their own blank/nil guards.
(normalize-thinking-text text)Canonical thinking text for every surface — gateway SSE, poll/replay, session transcript and the TUI timeline all normalize HERE so no consumer is the first place a difference appears.
Reasoning streams arrive with paragraph-style blank-line runs and whitespace-padded blank rows; collapse those, then drop the provider's elision marker. nil when nothing is left, so a blank tick falls back to the text already on screen instead of wiping it.
Canonical thinking text for every surface — gateway SSE, poll/replay, session transcript and the TUI timeline all normalize HERE so no consumer is the first place a difference appears. Reasoning streams arrive with paragraph-style blank-line runs and whitespace-padded blank rows; collapse those, then drop the provider's elision marker. nil when nothing is left, so a blank tick falls back to the text already on screen instead of wiping it.
One CLOSED sentence or clause end in model text — ., !, ? or … with
any trailing quotes/brackets, at whitespace or end of string, or a newline.
Owned here because two rules need the same notion of "the model finished a
thought": the gateway flushes the live stream one sentence at a time
(gateway.state/sentence-closed-in-suffix?), and settled-thinking-text
clips a settled summary to the last one it closed.
One CLOSED sentence or clause end in model text — `.`, `!`, `?` or `…` with any trailing quotes/brackets, at whitespace or end of string, or a newline. Owned here because two rules need the same notion of "the model finished a thought": the gateway flushes the live stream one sentence at a time (`gateway.state/sentence-closed-in-suffix?`), and `settled-thinking-text` clips a settled summary to the last one it closed.
(settled-thinking-text text)Canonical thinking text for a SETTLED iteration — what a transcript, a timeline entry or a replayed row keeps — or nil when the provider showed nothing usable.
normalize-thinking-text, CLIPPED to the last sentence the model closed;
nil when it closed none. Anthropic writes the thinking summary with a SECOND
model that streams alongside the thinking block; when the block closes first
the summary stops wherever it stood — mid-word — and the wire terminates it
with the … marker. So the run AFTER the last closed sentence is never a
thought: it is exactly the text the summarizer was mid-way through when it
was cut. One turn of one session showed both shapes: I should…, dropped whole, and
…no sentencepiece dependency needed for Pocket models. The real bl…, which
read on screen as if Vis had truncated the model and now keeps only its
closed sentence.
LIVE ticks keep normalize-thinking-text: mid-stream every summary is still
a fragment, and the stream must paint as it arrives.
Canonical thinking text for a SETTLED iteration — what a transcript, a timeline entry or a replayed row keeps — or nil when the provider showed nothing usable. `normalize-thinking-text`, CLIPPED to the last sentence the model closed; nil when it closed none. Anthropic writes the thinking summary with a SECOND model that streams alongside the thinking block; when the block closes first the summary stops wherever it stood — mid-word — and the wire terminates it with the `…` marker. So the run AFTER the last closed sentence is never a thought: it is exactly the text the summarizer was mid-way through when it was cut. One turn of one session showed both shapes: `I should…`, dropped whole, and `…no sentencepiece dependency needed for Pocket models. The real bl…`, which read on screen as if Vis had truncated the model and now keeps only its closed sentence. LIVE ticks keep `normalize-thinking-text`: mid-stream every summary is still a fragment, and the stream must paint as it arrives.
(strip-elision-marker text)Reasoning text without its trailing provider elision marker.
Suffix-only, therefore MONOTONE: a live stream may strip on every tick and the cumulative-minus-emitted-length delta math still never loses a character.
Reasoning `text` without its trailing provider elision marker. Suffix-only, therefore MONOTONE: a live stream may strip on every tick and the cumulative-minus-emitted-length delta math still never loses a character.
(truncate s n)Head-clip s to at most n chars (no ellipsis).
Head-clip `s` to at most `n` chars (no ellipsis).
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 |