Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.foundation.mpl-capture

SINK for artifacts the sandbox PRODUCES — matplotlib figures (plt.show() / plt.savefig()), anything a tool hands to vis_attach, AND anything written into the per-context OUTBOX directory ($VIS_OUTBOX) — so the engine OWNS the bytes (a session_iteration_attachment row) captured AT THE SOURCE, with NO re-parsing of the model-facing stdout fence.

The old flow rendered each figure to a $TMPDIR/vis-mpl temp file, printed a vis-image fence carrying just that PATH, then at persist time re-parsed the fence out of stdout and re-read the (possibly already-gone) file. We control the whole boundary, so that round-trip is gone: a producer renders/reads the bytes HOST-side (matplotlib's __vis_mpl_render_file__ Java2D backend; vis_attach's sandbox-confined open; the outbox filesystem tap in sandbox-fs) and, right where it already holds the bytes, calls record-attachment! (or record-file!). run-python-block binds *attachment-sink* to a fresh collector around each block's eval and drains it into the block outcome's :attachments; the loop stamps each with the block's tool-call-id and hands them to db-store-iteration!'s :attachments. The stdout fence now serves ONLY the inline TUI/web display + ASCII fallback — never persistence.

Deliberately dependency-free (no AWT, no vis.core): safe to require from BOTH a render shim and the hot engine loop without dragging Java2D or a require cycle.

SINK for artifacts the sandbox PRODUCES — matplotlib figures (`plt.show()` /
`plt.savefig()`), anything a tool hands to `vis_attach`, AND anything written
into the per-context OUTBOX directory (`$VIS_OUTBOX`) — so the engine OWNS the
bytes (a `session_iteration_attachment` row) captured AT THE SOURCE, with NO
re-parsing of the model-facing stdout fence.

The old flow rendered each figure to a `$TMPDIR/vis-mpl` temp file, printed a
`vis-image` fence carrying just that PATH, then at persist time re-parsed the
fence out of stdout and re-read the (possibly already-gone) file. We control the
whole boundary, so that round-trip is gone: a producer renders/reads the bytes
HOST-side (matplotlib's `__vis_mpl_render_file__` Java2D backend; `vis_attach`'s
sandbox-confined `open`; the outbox filesystem tap in `sandbox-fs`) and, right
where it already holds the bytes, calls `record-attachment!` (or `record-file!`).
`run-python-block` binds `*attachment-sink*` to a fresh collector around each
block's eval and drains it into the block outcome's `:attachments`; the loop
stamps each with the block's tool-call-id and hands them to `db-store-iteration!`'s
`:attachments`. The stdout fence now serves ONLY the inline TUI/web display +
ASCII fallback — never persistence.

Deliberately dependency-free (no AWT, no `vis.core`): safe to require from BOTH
a render shim and the hot engine loop without dragging Java2D or a require
cycle.
raw docstring

*attachment-reader*clj

Per-block READ-BACK accessor for artifacts already persisted in THIS session, bound by run-python-code around one block's eval (else nil). A map {:list (fn [] [{:id :filename :media-type :kind :size :position :tool-call-id :iteration-id} …]) :read (fn [attachment-id] {:id :base64 :media-type …}|nil)} closing over the session's db-info + id. Lets the vis_attachments / vis_read_attachment sandbox shims re-fetch an artifact a tool (or an earlier turn) produced. Nil outside a driven block ⇒ the shim surfaces a clear RuntimeError instead of silently returning nothing.

Per-block READ-BACK accessor for artifacts already persisted in THIS session,
bound by `run-python-code` around one block's eval (else nil). A map
`{:list (fn [] [{:id :filename :media-type :kind :size :position :tool-call-id
:iteration-id} …]) :read (fn [attachment-id] {:id :base64 :media-type …}|nil)}`
closing over the session's db-info + id. Lets the `vis_attachments` /
`vis_read_attachment` sandbox shims re-fetch an artifact a tool (or an earlier
turn) produced. Nil outside a driven block ⇒ the shim surfaces a clear
`RuntimeError` instead of silently returning nothing.
sourceraw docstring

*attachment-sink*clj

Per-block artifact collector: an atom holding a vector of attachment maps, bound by run-python-block around ONE block's eval (else nil). Producers append into it via record-attachment!; the block drains @*attachment-sink* into its :attachments.

Per-block artifact collector: an atom holding a vector of attachment maps, bound
by `run-python-block` around ONE block's eval (else nil). Producers append into
it via `record-attachment!`; the block drains `@*attachment-sink*` into its
`:attachments`.
sourceraw docstring

*outbox-seen*clj

Per-block set of canonical outbox paths ALREADY captured by the filesystem tap, bound (an atom #{}) alongside *attachment-sink* so a file re-closed in the same block is not recorded twice. Nil outside a driven block.

Per-block set of canonical outbox paths ALREADY captured by the filesystem tap,
bound (an atom `#{}`) alongside `*attachment-sink*` so a file re-closed in the
same block is not recorded twice. Nil outside a driven block.
sourceraw docstring

drainclj

(drain sink)

The attachments collected in sink (an atom vector) as a plain vector, or nil when empty — the value run-python-block folds into a block outcome's :attachments.

The attachments collected in `sink` (an atom vector) as a plain vector, or nil
when empty — the value `run-python-block` folds into a block outcome's
`:attachments`.
sourceraw docstring

record-attachment!clj

(record-attachment! m)

Append ONE produced-artifact attachment map to the active per-block *attachment-sink* (a silent no-op when unbound — e.g. a call outside a driven block). Shape mirrors ONE element of db-store-iteration!'s :attachments, minus :tool-call-id which the loop stamps from the block that produced it: {:kind <"image"|"file"|…> :media-type <mime> :base64 <b64> :size <bytes> :filename <name> :dims <"WxH", images only>}. NEVER throws — capture must not break a turn.

Append ONE produced-artifact attachment map to the active per-block
`*attachment-sink*` (a silent no-op when unbound — e.g. a call outside a driven
block). Shape mirrors ONE element of `db-store-iteration!`'s `:attachments`,
minus `:tool-call-id` which the loop stamps from the block that produced it:
`{:kind <"image"|"file"|…> :media-type <mime> :base64 <b64> :size <bytes>
  :filename <name> :dims <"WxH", images only>}`. NEVER throws — capture must not
break a turn.
sourceraw docstring

record-file!clj

(record-file! path)

Read the bytes of a just-written file at path (a java.nio.file.Path), sniff its media-type, base64-encode, and record-attachment! it — the host side of the filesystem OUTBOX tap. De-dups per block via *outbox-seen* (a file re-closed in the same block records once). Skips a file larger than max-capture-bytes, a directory, or one already seen. NEVER throws — an outbox write must not break a turn.

Read the bytes of a just-written file at `path` (a `java.nio.file.Path`), sniff
its media-type, base64-encode, and `record-attachment!` it — the host side of
the filesystem OUTBOX tap. De-dups per block via `*outbox-seen*` (a file
re-closed in the same block records once). Skips a file larger than
`max-capture-bytes`, a directory, or one already seen. NEVER throws — an outbox
write must not break a turn.
sourceraw docstring

sniff-media-typeclj

(sniff-media-type data filename)

Best-effort media-type for produced bytes: magic-byte signatures first, then a filename-extension fallback, then a utf-8 probe (text/plain), else application/octet-stream. NEVER throws.

Best-effort media-type for produced bytes: magic-byte signatures first, then a
filename-extension fallback, then a utf-8 probe (`text/plain`), else
`application/octet-stream`. NEVER throws.
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