Skip to content

run.inputs ​

What a worker body can carry over from earlier bodies.

Every run_worker body is a fresh module realm: its locals die with the worker. Until now the only bridge between bodies was the model retyping the object it had already built — 19 copies of the same site ring in one session, and a human's dock edit copied forward by hand. This module is the contract for the two objects the editor puts in scope so that stops:

inputs — every module call the editor traced, addressable by call id or by module name. inputs.last("pack.corridorRuns") is the input of the most recent corridorRuns call, byte-identical to what the module ran on (an input the user then edited on the canvas counts as a call of its own, so it returns the input they finished with). Automatic: the body cannot forget to keep it. kept — values a body asked to keep with return { …, keep: { name } }: a computed spine, a scored table, a department id. Plain data only; a handle ({ __h }) does not survive the worker and is refused.

The pure parts live here so the editor, the backend's vendored types, the docs and the tests agree on one definition: the manifest the model reads, the name rule, the size caps, the handle check, and makeInputs, which builds the inputs object from the store the editor injects.

ts
// plugin worker
import { jsonBytes, describeValue, manifestEntry, callMatches, makeInputs, trimStore } from "@snaptrude/plugin-toolkit/run-inputs";

// agent run_worker
modules.run.inputs.jsonBytes(...)
modules.run.inputs.describeValue(...)
modules.run.inputs.manifestEntry(...)

Every input carries unit ("mm" | "cm" | "m" | "ft" | "in"). All lengths in that call — input and output — are in it; angles are degrees, areas are that unit squared.

When to use it ​

Use it forNot for
Starting a body from the input an earlier body built — { ...inputs.last("pack.corridorRuns"), bandDepth: 34 } — instead of retyping itScene reads — inputs holds module inputs only; read the scene again, or keep the ids you need
Picking up the input the user finished with after editing a solution on the canvas: their call is the newest oneHandles: they die with the worker; keep the entity id or the points a handle was built from
Carrying a computed value (a spine, a scored table, an entity id) to the next body with return { …, keep: { name } } and reading kept.name

Inputs and outputs ​

The shapes every function below speaks. Each appears once; a field's note says what changing it does to the result.

ValueShape ​

Shape summary of a value the model can address without seeing it.

  • keys?: string[] — Top-level keys when the value is an object.
  • array?: number — Length when the value is an array.
  • bytes: number — JSON-encoded size.

InputsStoreEntry ​

One entry of the store the editor injects; input is the traced object.

  • id: CallId
  • call: string
  • input: unknown
  • unit?: LengthUnit
  • applied?: boolean

InputsManifestEntry ​

One retrievable module input, as the result digest lists it.

  • id: CallId
  • call: string — group.name.fn, e.g. pack.corridorRuns.corridorRuns.
  • unit?: LengthUnit
  • applied?: boolean — True when the user edited this call's input on the canvas: this is theirs.

Inputs ​

The inputs object in scope in a worker body.

KeepRequest ​

  • name: string
  • value: unknown
  • bytes: number

KeptManifestEntry ​

One kept value, as the result and get_scene_info list it.

  • name: string

Functions ​

jsonBytes(value) ​

JSON size of a value; undefined and functions count as 0.

  • Parameters:
    • value: unknown
  • Returns: number

describeValue(value) ​

Keys or length plus size — what the manifest says about a value.


manifestEntry(entry) ​

Manifest entry for one store entry.


callMatches(call, wanted) ​

True when call (group.name.fn) is the module or exact call wanted names.

  • Parameters:
    • call: string
    • wanted: string
  • Returns: boolean

makeInputs(store) ​

Build the inputs object from the store the editor injected (oldest first). Pure: reads the store, never the scene. last() and at() return the stored object itself; treat it as read-only and spread before patching.


trimStore(store, maxBytes) ​

Trim a store to the byte cap, dropping the OLDEST entries first, so the newest calls are always in scope. Returns the kept tail and how many fell.


findUnkeepable(value, path) ​

Dotted paths inside value that hold something that will not survive the worker: a plugin handle ({ __h: "<id>" }, the wire shape every handle serialises to) or a function. Empty when the value is plain data.

  • Parameters:
    • value: unknown
    • path?: string — Default "".
  • Returns: string[]

validateKeep(keep, maxBytes) ​

Validate the keep object a body returned. Names must be identifiers, values plain JSON under MAX_KEEP_BYTES, with no handles or functions.

  • Parameters:
    • keep: unknown
    • maxBytes?: number — Default MAX_KEEP_BYTES.
  • Returns: KeepRequest[]
  • Throws: InvalidKeepError — naming the first offending entry and what to keep instead (an entity id, or the points a handle was built from).

keptManifest(kept) ​

Manifest for a set of kept values, sorted by name.

Examples ​

Start the next body from the input the last body ran — or the user applied (agent)

ts
// In a worker body `inputs` is already in scope; this builds it from a store
// the way the editor does. After the user edited a solution on the canvas,
// `last` is the input they finished with — their spine, their band depth.
const inputs = makeInputs(store);
const base = inputs.last("pack.corridorRuns") as { bandDepth: number };
return { ...base, bandDepth: base.bandDepth + 2 };

Keep what the body computed: return it under keep (agent)

ts
// A body ends with `return { …, keep: { spine, departmentId } }`; the next
// body reads `kept.spine`. Plain data only — this is the check the editor runs.
return validateKeep({ spine, departmentId }).map((k) => k.name);

Errors ​

ConditionResult
validateKeep() — naming the first offending entry and what to keep instead (an entity id, or the points a handle was built from).throws InvalidKeepError