ZEUGHAUS-NODES(7) Zeughaus Manual

NAME

zeughaus-nodes - node types, pins and settings of every zeughaus plugin

DESCRIPTION

A node is an instance of a node type, and every node type comes from a plugin. A type is named by its type id, <plugin>.<name> (transform.sin, db.table), and the catalog entry behind it carries a display name, a category, pins, settings and whether the type is a container. The editor places nodes from this catalog; the runner instantiates the same types and executes them. The editor never executes a node.

The catalog below lists the plugins in the order the runner registers them (Runner::new); the editor registers the same plugins in the same order. Plugins marked native only (capture, db, record, llm) are left out of the browser editor build; the runner always has them. job is registered in the editor detached: a job node is placed and configured there and runs only in a runner.

Each entry shows the pins of a freshly placed node. Where pins follow the wiring or a setting, the notes say so.

Pins

An input pin is either a trigger or a sample pin. A trigger pin is an event: the node acts on what arrives there. A sample pin is state: it is read whenever the node runs, for whatever reason. The editor draws a trigger pin as a square and a sample pin as a circle, and a wire into a trigger pin as a moving dash, into a sample pin as a solid line. An output pin carries one value; an output whose last run produced no value is drawn dim.

Dirty propagation is uniform: when a node emits, everything downstream of it reruns. A node that must act only on its own event asks whether its trigger pin received a value since it last ran, which is how db.insert writes one row per event and not one per pass.

A pin is coloured by its type, from the theme's ANSI slots:

typecolour
Floatgreen
Stryellow
Boolblue
Intcyan
Anybright white
everything elsewhite

A field pin belongs to neither side. db.table declares one per field; a wire between two field pins is a relation between two tables, carries no value and is kept out of execution, so two tables that reference each other are not a cycle.

Settings

Settings are the fields in a node's body and the one way to configure a node from the editor. The kind of a setting only chooses the widget: Text is one line, Multiline a taller field, Title the node's name drawn as its heading, and Fields a row editor over name:type lines with a type choice per row.

The value is always text. The editor stores it in the node's parameters and sends it 400 ms after the last keystroke; the runner hands it to the node, and the node parses it. A node that cannot use a value refuses it with a reason: the runner reports the refusal, every editor draws the reason under the field, and the node keeps its last accepted value.

Some parameters are derived by the editor and never typed: db_path from the enclosing db.database, columns of a db.insert from the wired table, relations from the wires between field pins, and renamed_from after a table's title changed. The runner applies them like any other parameter.

Derived pins

A node may reshape its pins. The variadic nodes (flow.all, the ml merges, record.writer) grow an input when the last one is wired, so there is always one free. db.table has one field pin per row of its columns setting, and db.insert one input per column of the table wired into it. Editor and runner both recompute the pins after every connection change and after a setting that shapes them.

Containers

A container (graph.sub, db.database) holds other nodes and has no pins of its own. The editor gives it one input per graph.input child and one output per graph.output child, named by that child's name setting and typed Any. A wire drawn onto a container's pin is stored against the boundary node behind it, so the store and the runner see one flat graph of real nodes; only the editor knows about nesting. A container's open button shows its contents in a tab of their own.

Sources and clocks

A node runs when something upstream of it changes. A source has nothing upstream, so it needs a clock: a node may declare an interval at which the host runs it on its own. flow.timer and record.player declare one. capture.screen does not: without a flow.timer wired to its trigger it produces one frame and stops.

Presses

flow.button and job.run also act on a press, delivered by the runner as the fire parameter. In the editor, a Button node's body is its Trigger button, and a press works from any window. Outside the editor, zeughaus-runner trigger presses any node by id, optionally with a payload; see zeughaus-runner(1).

Async work and errors

A node whose work would block a pass hands it off as async work: llm.chat (the HTTP request), job.run (the wait for the process) and capture.screen (the first Wayland capture). The node is pending until the result arrives, and its downstream is held back until then. A node that fails does not fail the pass: its message is drawn on the node, its downstream is held back, and everything unrelated runs.

PIN TYPES

A pin type is a runtime value, not a compile-time label, so a node can derive types from data (a table's fields). The variants:

Any
The wildcard. Connects to anything and is never coerced: the type is whatever flows through (flow.hold, the graph boundaries, transform.display).
Bool, Int, Float, Str
The scalars, one to one with the Rust types bool, i64, f64 and String. Narrower numeric types are not pin types; a node converts where it emits.
List<T>, Option<T>
Composites of another type, built at runtime. No node in the current catalog declares one.
Record
A named type with ordered fields, built at runtime. No node in the current catalog declares one.
Opaque types
A plugin's own Rust type, matched by name: image (a frame; shared by capture and record), KerasModel (ml), Conversation (llm), db.table (db).

An output may connect to an input when the two types are equal, when either side is Any, or when a converter joins them. The one built-in converter is Int -> Float; no plugin registers another, and there is none from Float to Int. Editor and runner build the same converter registry from the same plugins, so what may connect and what is coerced agree. The editor refuses a wire that nothing converts and says why, for example nothing converts db.table into int. Two field pins connect only when their types are equal.

TRANSFORM

Crate zeughaus-transform. Constants, arithmetic, trigonometry, comparison, logic and string operations over scalar pins, and a display sink.

transform.const_f64 Const (f64) Const

Emits the number typed into its value setting.

out value Float

settings value Text, default 0

Text that does not parse as a number is refused ("is not a number"); the node keeps emitting its last accepted value.

transform.const_bool Const (bool) Const

Emits the boolean typed into its value setting.

out value Bool

settings value Text, default false

Accepts true, 1, false, 0; an empty field reads as false. Anything else is refused ("is not true or false").

transform.const_string Const (String) Const

Emits the text of its value setting exactly as typed, untrimmed.

out value Str

settings value Text

transform.add Add Math

Emits a + b.

in a Float (trigger)b Float (trigger)out result Float

An unwired input reads as 0.

transform.subtract Subtract Math

Emits a - b.

in a Float (trigger)b Float (trigger)out result Float

An unwired input reads as 0.

transform.multiply Multiply Math

Emits a * b.

in a Float (trigger)b Float (trigger)out result Float

An unwired input reads as 0.

transform.divide Divide Math

Emits a / b.

in a Float (trigger)b Float (trigger)out result Float

a defaults to 0 and b to 1. Division by zero emits infinity.

transform.negate Negate Math

Emits -input.

in input Float (trigger)out result Float

An unwired input reads as 0.

transform.abs Abs Math

Emits the absolute value of input.

in input Float (trigger)out result Float

transform.clamp Clamp Math

Emits input limited to the range [min, max].

in input Float (trigger)min Floatmax Floatout result Float

An unwired bound is open: min defaults to negative infinity, max to infinity.

transform.modulo Modulo Math

Emits the remainder a % b, with the sign of a.

in a Float (trigger)b Float (trigger)out result Float

b defaults to 1. A zero divisor emits NaN.

transform.power Power Math

Emits base raised to exp.

in base Float (trigger)exp Float (trigger)out result Float

base defaults to 0, exp to 1.

transform.min Min Math

Emits the smaller of a and b.

in a Float (trigger)b Float (trigger)out result Float

transform.max Max Math

Emits the larger of a and b.

in a Float (trigger)b Float (trigger)out result Float

transform.lerp Lerp Math

Linear interpolation: emits a + (b - a) * t.

in a Float (trigger)b Float (trigger)t Floatout result Float

Unwired inputs default to a = 0, b = 1, t = 0.5.

transform.sqrt Sqrt Math

Emits the square root of input; a negative input gives NaN.

in input Float (trigger)out result Float

transform.floor Floor Math

Rounds input down to the nearest integer value.

in input Float (trigger)out result Float

transform.ceil Ceil Math

Rounds input up to the nearest integer value.

in input Float (trigger)out result Float

transform.round Round Math

Rounds input to the nearest integer value, halves away from zero.

in input Float (trigger)out result Float

transform.log2 Log2 Math

Emits the base-2 logarithm of input.

in input Float (trigger)out result Float

transform.ln Ln Math

Emits the natural logarithm of input.

in input Float (trigger)out result Float

transform.sin Sin Trig

Emits the sine of input, in radians.

in input Float (trigger)out result Float

transform.cos Cos Trig

Emits the cosine of input, in radians.

in input Float (trigger)out result Float

transform.tan Tan Trig

Emits the tangent of input, in radians.

in input Float (trigger)out result Float

transform.greater_than Greater Than Logic

Emits whether a > b.

in a Float (trigger)b Float (trigger)out result Bool

An unwired input reads as 0.

transform.equal Equal Logic

Emits whether a and b differ by less than epsilon.

in a Float (trigger)b Float (trigger)epsilon Floatout result Bool

epsilon defaults to 1e-10.

transform.select Select Logic

Emits true_val when condition is true, otherwise false_val.

in condition Bool (trigger)true_val Floatfalse_val Floatout result Float

An unwired condition reads as false; unwired values read as 0.

transform.not Not Logic

Emits the negation of input.

in input Bool (trigger)out result Bool

transform.and And Logic

Emits a && b.

in a Bool (trigger)b Bool (trigger)out result Bool

An unwired input reads as false.

transform.or Or Logic

Emits a || b.

in a Bool (trigger)b Bool (trigger)out result Bool

An unwired input reads as false.

transform.map_range Map Range Utility

Remaps value from [in_min, in_max] onto [out_min, out_max].

in value Float (trigger)in_min Floatin_max Floatout_min Floatout_max Floatout result Float

The ranges default to 0..1 on both sides. The result is not clamped. An empty input range emits out_min.

transform.to_string To String String

Formats a value of any type as the text the editor shows for it.

in input Any (trigger)out result Str

A plugin type with no text form formats as its type name in angle brackets, e.g. <KerasModel>. An unwired input emits the empty string.

transform.concat Concat String

Joins a and b, with sep between them when it is not empty.

in a Str (trigger)b Str (trigger)sep Strout result Str

transform.string_len String Length String

Emits the length of input in bytes, as a Float.

in input Str (trigger)out result Float

transform.display Display Output

Shows the last value it received in its body.

in input Any (trigger)

Has no outputs. The one node whose body shows data: an image arriving here is drawn from the runner's sample feed.

ML

Crate zeughaus-ml. Keras layers as nodes: a KerasModel value is extended one step per node, branches merge, and the result is exported as functional-API Python.

ml.input Input ML

Starts a model branch with layers.Input(...).

in model KerasModelout out KerasModel

settings shape Text, default (28, 28, 1)

shape is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default. ml.export requires every branch of a model to start with this node.

ml.dense Dense ML

Appends a layers.Dense(...) step to the incoming model.

in model KerasModelout out KerasModel

settings units Text, default 64activation Text, default relu

activation is emitted as a quoted Python string; units is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.conv2d Conv2D ML

Appends a layers.Conv2D(...) step to the incoming model.

in model KerasModelout out KerasModel

settings filters Text, default 32kernel_size Text, default (3, 3)strides Textpadding Textactivation Text, default relu

padding, activation are emitted as a quoted Python string; filters, kernel_size, strides are emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.conv1d Conv1D ML

Appends a layers.Conv1D(...) step to the incoming model.

in model KerasModelout out KerasModel

settings filters Text, default 32kernel_size Text, default 3activation Text, default relu

activation is emitted as a quoted Python string; filters, kernel_size are emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.maxpool2d MaxPooling2D ML

Appends a layers.MaxPooling2D(...) step to the incoming model.

in model KerasModelout out KerasModel

settings pool_size Text, default (2, 2)

pool_size is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.avgpool2d AveragePooling2D ML

Appends a layers.AveragePooling2D(...) step to the incoming model.

in model KerasModelout out KerasModel

settings pool_size Text, default (2, 2)

pool_size is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.global_avgpool2d GlobalAveragePooling2D ML

Appends a layers.GlobalAveragePooling2D(...) step to the incoming model.

in model KerasModelout out KerasModel

No parameters.

ml.flatten Flatten ML

Appends a layers.Flatten(...) step to the incoming model.

in model KerasModelout out KerasModel

No parameters.

ml.dropout Dropout ML

Appends a layers.Dropout(...) step to the incoming model.

in model KerasModelout out KerasModel

settings rate Text, default 0.5

rate is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.batchnorm BatchNormalization ML

Appends a layers.BatchNormalization(...) step to the incoming model.

in model KerasModelout out KerasModel

No parameters.

ml.layernorm LayerNormalization ML

Appends a layers.LayerNormalization(...) step to the incoming model.

in model KerasModelout out KerasModel

No parameters.

ml.activation Activation ML

Appends a layers.Activation(...) step to the incoming model.

in model KerasModelout out KerasModel

settings activation Text, default relu

activation is emitted as a quoted Python string. A blank setting is left out of the call, so Keras applies its own default.

ml.lstm LSTM ML

Appends a layers.LSTM(...) step to the incoming model.

in model KerasModelout out KerasModel

settings units Text, default 64return_sequences Text

units, return_sequences are emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.gru GRU ML

Appends a layers.GRU(...) step to the incoming model.

in model KerasModelout out KerasModel

settings units Text, default 64return_sequences Text

units, return_sequences are emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.embedding Embedding ML

Appends a layers.Embedding(...) step to the incoming model.

in model KerasModelout out KerasModel

settings input_dim Text, default 10000output_dim Text, default 128

input_dim, output_dim are emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.reshape Reshape ML

Appends a layers.Reshape(...) step to the incoming model.

in model KerasModelout out KerasModel

settings target_shape Text, default (28, 28, 1)

target_shape is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.concatenate Concatenate ML Merge

Joins the incoming branches into one model with layers.Concatenate()([...]).

in a KerasModelb KerasModelout out KerasModel

settings axis Text

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Concatenate needs at least two connected model inputs" when fewer than two non-empty models arrive. axis is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.add Add ML Merge

Joins the incoming branches into one model with layers.Add()([...]).

in a KerasModelb KerasModelout out KerasModel

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Add needs at least two connected model inputs" when fewer than two non-empty models arrive.

ml.subtract Subtract ML Merge

Joins the incoming branches into one model with layers.Subtract()([...]).

in a KerasModelb KerasModelout out KerasModel

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Subtract needs at least two connected model inputs" when fewer than two non-empty models arrive.

ml.multiply Multiply ML Merge

Joins the incoming branches into one model with layers.Multiply()([...]).

in a KerasModelb KerasModelout out KerasModel

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Multiply needs at least two connected model inputs" when fewer than two non-empty models arrive.

ml.average Average ML Merge

Joins the incoming branches into one model with layers.Average()([...]).

in a KerasModelb KerasModelout out KerasModel

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Average needs at least two connected model inputs" when fewer than two non-empty models arrive.

ml.maximum Maximum ML Merge

Joins the incoming branches into one model with layers.Maximum()([...]).

in a KerasModelb KerasModelout out KerasModel

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Maximum needs at least two connected model inputs" when fewer than two non-empty models arrive.

ml.minimum Minimum ML Merge

Joins the incoming branches into one model with layers.Minimum()([...]).

in a KerasModelb KerasModelout out KerasModel

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Minimum needs at least two connected model inputs" when fewer than two non-empty models arrive.

ml.dot Dot ML Merge

Joins the incoming branches into one model with layers.Dot()([...]).

in a KerasModelb KerasModelout out KerasModel

settings axes Text, default -1

Variadic: inputs a, b, ... grow as they are wired, always one spare after the highest wired input, at least 2 and at most 26 (a to z). Fails with "Dot needs at least two connected model inputs" when fewer than two non-empty models arrive. axes is emitted verbatim. A blank setting is left out of the call, so Keras applies its own default.

ml.compile Compile ML

Attaches a training configuration that ml.export renders as model.compile(...).

in model KerasModelout out KerasModel

settings optimizer Text, default adamloss Text, default categorical_crossentropymetrics Text, default accuracy

metrics is a comma-separated list and becomes a Python list of strings. A blank setting is left out of the call.

ml.export Export Code ML

Renders the incoming model as a runnable Keras functional-API Python program.

in model KerasModel (trigger)out code Str

The program imports keras, assigns one variable per step, builds keras.Model(inputs, outputs), compiles when a Compile step is present and calls model.summary(). Fails on an empty model and when a branch does not start with an Input layer.

FLOW

Crate zeughaus-flow. Primitives between events and state: latch, manual press, clock and fan-in.

flow.hold Hold Flow

Latches the most recent event of any type and keeps emitting it as state.

in in Any (trigger)out out Any

The event-to-state adapter. Emits nothing before the first value arrives.

flow.button Button Flow

Emits one true event per press.

out out Bool

A press arrives as the fire parameter: the Trigger button in the node body, from any editor, or zeughaus-runner trigger. Between presses out carries no value, so downstream trigger pins stay quiet.

flow.timer Timer Flow

The clock: emits tick = true every 1/hz seconds.

out tick Bool

settings hz Text, default 30

Declares its interval through tick_interval; the host schedules it. A rate that is not a finite number is refused and the previous rate stays; a finite rate is clamped to 0.01..240.

flow.all All Flow

Fan-in: fires out once every wired input has fired since it last fired.

in a Any (trigger)b Any (trigger)out out Bool

Variadic: inputs a, b, ... grow as they are wired, one spare after the highest wired input, up to 26. Unwired inputs are not waited for, and unwiring an input forgets what it fired. With nothing wired it never fires.

GRAPH

Crate zeughaus-graph. Subgraphs: a container node and the boundary nodes that give it pins.

graph.sub Subgraph Graph container

A container that holds other nodes.

Declares no pins: the editor synthesizes one input per graph.input child and one output per graph.output child, named by that child's name setting, all typed Any. A wire on such a pin is stored against the boundary node, so the executor sees one flat graph. The open button shows the contents in a tab of their own.

graph.input Input Graph

A subgraph's input boundary: passes what arrives on in to out.

in in Any (trigger)out out Any

settings name Text, default in

name names the container pin it contributes. It is trimmed; an empty name keeps the previous one. Emits nothing while the outside is unwired.

graph.output Output Graph

A subgraph's output boundary: passes what arrives on in to out.

in in Any (trigger)out out Any

settings name Text, default out

name names the container pin it contributes. It is trimmed; an empty name keeps the previous one.

CAPTURE

Crate zeughaus-capture, native only: the runner executes it, the browser editor cannot place it. Screen capture as an image source.

capture.screen Screen Capture Capture

Captures the primary screen once per execution.

in trigger Any (trigger)out frame imagewidth Floatheight Floatframe_size Floatcaptured Boolerror Str

A source: wire a flow.timer to trigger for a live feed. On success it emits frame, width, height, frame_size and captured = true; on failure only captured = false and error. On Wayland it uses the xdg-desktop-portal ScreenCast stream (the first capture is async work and may show a consent dialog, later ones sample the running stream) and falls back to the Screenshot portal; on X11, Windows and macOS it uses scrap.

DB

Crate zeughaus-db, native only: the runner executes it, the browser editor cannot place it. SQLite databases drawn as subgraphs: tables are schemas, wires between fields are foreign keys.

db.database Database Database container

A container whose path setting names the SQLite file every node inside it works on.

settings path Text, default zeughaus.sqlite

Executes nothing. The editor passes path to each child as the derived db_path parameter; a db.* node outside a database fails with "not inside a database". Its pins come from graph.input/graph.output children, as for graph.sub. Connections are shared per file, with foreign keys enforced and WAL journaling.

db.table Table Database

A table schema: creates the table and keeps the file in step with the declared fields.

out table db.tableddl Strfields id Intvalue Float

settings name Title, default tablecolumns Fields, default id:int value:float

columns is one name:type row per field, types int, float, str, bool; each row is a field pin of that type (the fields listed are the defaults). A wire between two field pins of equal type is a relation and becomes a FOREIGN KEY; the end whose field is id is referenced. id:int becomes INTEGER PRIMARY KEY. On each run it renames the table after a title change, renames a renamed field, adds new fields and drops removed ones; a changed column type is refused. A malformed row, a duplicate field or an empty name is refused. ddl is the CREATE TABLE statement.

db.insert Insert Database

Writes one row into the wired table each time insert fires.

in table db.tableinsert Any (trigger)out id Intcount Int

Derived pins: one Sample input per column of the wired table, typed like the column, except id, which SQLite assigns. The editor derives the column list from the wired db.table. id is the last inserted rowid, count the rows this node has written. A pass without an insert event writes nothing.

db.query Query Database

Selects rows from the wired table when run fires.

in table db.tablerun Any (trigger)out rows Strcount Int

settings where Textorder Text, default id DESClimit Text, default 100

where and order are raw SQL fragments. limit must be a positive row count, is capped at 10000, and anything else is refused. rows is a JSON array of objects, one per row; the last result stays on the pins between runs.

db.sql SQL Database

Runs the SQL statement in its sql setting when run fires.

in run Any (trigger)out rows Strcount Int

settings sql Multiline

A statement starting with SELECT, WITH, PRAGMA or EXPLAIN returns its rows as JSON on rows; any other statement reports the number of changed rows on count. Fails on an empty statement.

RECORD

Crate zeughaus-record, native only: the runner executes it, the browser editor cannot place it. Recorder and player: frames and values as PNG files plus a JSON-lines index on disk.

record.writer Recorder Record

Writes every frame it is triggered with, and the values wired beside it, to a recording directory.

in frame image (trigger)v0 Anyout count Intsession Strpath Str

settings dir Text, default recordingssession Text

Writes <dir>/<session>/<seq:06>.png plus one line per frame in index.jsonl (seq, ts, file, width, height, values). An empty session is named by the first frame, in unix seconds. Derived pins: value inputs v0, v1, ... always one more than are wired. Changing dir or session starts a new recording. A pass without a new frame writes nothing.

record.player Player Record

Replays a recording, one frame per tick, in write order.

out frame imageseq Intts Floatvalues Str

settings dir Text, default recordingssession Texthz Text, default 10loop Text, default true

A clocked source: runs every 1/hz seconds on its own. hz is clamped to 0.1..120; text that is not a number keeps the previous rate. loop accepts true, 1, false, 0 and refuses anything else; without it playback ends after the last frame and the pins go empty. values is the JSON object the recorder wrote. Fails when session is empty or its index cannot be read.

LLM

Crate zeughaus-llm, native only: the runner executes it, the browser editor cannot place it. LLM conversations against LM Studio's OpenAI-compatible endpoint: each node extends a Conversation value by one message.

llm.system System Message LLM

Appends a system message to the incoming conversation, or starts one.

in conv Conversationout out Conversation

settings text Multiline, default You are a helpful assistant.

llm.user User Message LLM

Appends a user message to the incoming conversation, or starts one.

in conv Conversationtext Strout out Conversation

settings text Multiline

A wired text input wins over the text setting.

llm.chat Chat (LM Studio) LLM

Sends the conversation to an OpenAI-compatible endpoint and appends the reply.

in conv Conversation (trigger)out out Conversationreply Strtok_per_s Float

settings base_url Text, default http://localhost:1234/v1model Text

Async work: the request runs off the pass and its outputs arrive when the reply does. An empty model uses the first model the endpoint lists; an empty base_url uses the default. Fails on an empty conversation.

llm.last_reply Last Reply LLM

Emits the content of the conversation's last message as text.

in conv Conversationout text Str

llm.merge Merge LLM

Concatenates conversation a and then b into one.

in a Conversationb Conversationout out Conversation

JOB

Crate zeughaus-job. Jobs: processes with a beginning and an end, run in runner-owned terminals with a log per run. Registered detached in the editor.

job.run Job Job

Runs a process in a terminal the runner owns, on a run event or a press.

in run Any (trigger)cwd Strout ok Boolfailed Intdir Str

settings command Textenv Textcwd Textartifacts Textkeep_on_failure Text, default true

command, env and artifacts are split like shell words (quotes group, nothing expands, no shell runs); an unbalanced quote, an env word without = or a keep_on_failure other than true or false is refused. A wired cwd wins over the setting. A press (zeughaus-runner trigger, delivered as the fire parameter) starts a run like an event on run; its payload text, or a string arriving on run, reaches the program as ZEUGHAUS_PAYLOAD. The program also sees ZEUGHAUS_RUN_DIR. The wait is async work: ok fires on exit 0, failed carries the exit code (-1 for a signal or kill), dir is the run directory. One run at a time; refuses while a run is live, while the runner is held, and in a process that does not execute. The editor registers this plugin detached: the node is drawn and configured there and runs only in a runner.

SEE ALSO

zeughaus-architecture(7), zeughaus-runner(1), zeughaus(1), zeughaus-keys(7), zeughaus-glossary(7)

install(8)source