Context and inputs
The ctx argument to run(ctx) is built once per run. It carries metadata and handles to the parent node’s output(s). Full bytes load only when you call open*Reader().
ArbexContext fields
| Field | Use |
|---|---|
apiVersion | Host contract version (currently "1.0") |
session | id, projectId, simulationName, template, configuration, nodes[] (no email or display name) |
session.nodes[] | Every node in the session: instanceId, instanceName, templateName, lastState, statusDetails (truncated) |
node | instanceId, instanceName, templateName, taskId, configuration (your script and parent settings) |
parent | Resolved parent read block: nodeInstanceName, mode, historyLimit, historyOrder, readerHint, tabularOptions |
parents | All graph parents as { name, templateName, instanceId }[] (metadata only) |
inputs | Latest or history handles (see below) |
system | Operator triage when enabled (default on system-arbex-js). version (platform build), live K8s lists, optional platform config. See system-arbex-js. |
Use ctx.node.configuration for thresholds, feature flags, or JMESPath paths defined on the node instance. Use ctx.session.configuration for session-level settings.
ctx.inputs
Controlled by node config parent.mode:
mode | Field | Behaviour |
|---|---|---|
latest | inputs.latest | One handle or null |
history | inputs.history | Iterable handles (bounded by parent.historyLimit) |
Each handle exposes:
| Member | Description |
|---|---|
descriptor | outputId, createdAtUtc, dataPath, contentType, detectedKind, sizeBytes |
detectedKind | json, tabular, or binary |
openJsonReader() | Async; { kind: 'json', root, dispose() } |
openTabularReader(opts?) | Async; headers + readRow() or async iteration |
openBinaryReader() | Async; byteLength, base64, contentType, dispose() |
Why async: readers fetch and parse parent storage via a C# bridge. Call dispose() when finished. Only one reader should be open per handle at a time.
HEAT_ARBEX guards
After open*Reader(), narrow types before use:
const reader = await item.openJsonReader();
if (!HEAT_ARBEX.isJsonReader(reader)) throw new Error("expected json");
const root = reader.root;
await reader.dispose();| Guard | When |
|---|---|
isJsonReader(r) | JSON root object or array |
isTabularReader(r) | CSV/TSV rows |
isBinaryReader(r) | Raw bytes as base64 |
isInputHandle(h) | Valid handle in history loops |
heat helpers (reading data)
| API | Why use it |
|---|---|
heat.getPath(obj, "a.b.c") | Safe dotted path without throwing |
heat.coerceNumber(v, fallback?) | Parse numbers from tabular strings |
heat.parseIso8601(s) | Parse timestamps for timeMs |
heat.jmespath.search(expr, data) | Query nested JSON from parent roots |
Example: latest JSON and session threshold
Reads the latest parent JSON, extracts a subtree with JMESPath, and compares to a session config threshold:
async function run(ctx) {
const item = ctx.inputs.latest;
if (!item) return { empty: true };
const reader = await item.openJsonReader();
if (!HEAT_ARBEX.isJsonReader(reader)) throw new Error("expected json");
const metrics = heat.jmespath.search("metrics", reader.root);
const threshold = heat.getPath(ctx.session.configuration, "alerts.cpuThreshold") ?? 0.8;
await reader.dispose();
return {
metrics,
overThreshold:
metrics &&
typeof metrics === "object" &&
"cpu" in metrics &&
metrics.cpu > threshold,
};
}Full sample: latest-json-transform.js.
Related
- Arbex API reference (overview)
- Dataservice API
- system-arbex-js (parent config, history limits)