yaml-flow 8.0.1 → 8.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/browser/asset-integrity.json +2 -2
  2. package/browser/board-livecards-localstorage.js +3 -3
  3. package/cli/browser-api/board-live-cards-browser-adapter.d.ts +1 -1
  4. package/cli/node/board-live-cards-cli.js +6 -6
  5. package/cli/node/fs-board-adapter.d.ts +2 -2
  6. package/cli/node/fs-board-adapter.js +6 -6
  7. package/cli/{types-C2YQXFwo.d.ts → types-D2XnLbBj.d.ts} +15 -0
  8. package/examples/ARCHITECTURE.md +188 -0
  9. package/examples/board/demo-shell-with-server.html +2 -2
  10. package/examples/board/demo-task-executor.js +29 -32
  11. package/examples/board-local/demo-shell-localstorage.html +3 -3
  12. package/examples/step-machine-cli/json/double-handler.js +20 -0
  13. package/examples/step-machine-cli/json/mixed-handlers.flow.json +118 -0
  14. package/examples/step-machine-cli/json/mixed-handlers.input.json +5 -0
  15. package/examples/step-machine-cli/json/scale-handler.js +13 -0
  16. package/examples/step-machine-cli/yaml/double-handler.js +20 -0
  17. package/examples/step-machine-cli/yaml/mixed-handlers.flow.yaml +94 -0
  18. package/examples/step-machine-cli/yaml/mixed-handlers.input.json +5 -0
  19. package/examples/step-machine-cli/yaml/scale-handler.js +13 -0
  20. package/lib/{artifacts-store-lib-public-BABrgFkV.d.ts → artifacts-store-lib-public-BWC3YuLa.d.ts} +1 -1
  21. package/lib/{artifacts-store-lib-public-DGa8BpJT.d.cts → artifacts-store-lib-public-DBICnGL6.d.cts} +1 -1
  22. package/lib/artifacts-store-public.d.cts +2 -2
  23. package/lib/artifacts-store-public.d.ts +2 -2
  24. package/lib/board-live-cards-node.cjs +6 -6
  25. package/lib/board-live-cards-node.d.cts +5 -5
  26. package/lib/board-live-cards-node.d.ts +5 -5
  27. package/lib/board-live-cards-node.js +6 -6
  28. package/lib/{board-live-cards-public-BnmRAbQV.d.cts → board-live-cards-public-BF9FP0mL.d.cts} +15 -0
  29. package/lib/{board-live-cards-public-CsmYrvpd.d.ts → board-live-cards-public-dJAl5IL-.d.ts} +15 -0
  30. package/lib/board-live-cards-public.cjs +1 -1
  31. package/lib/board-live-cards-public.d.cts +1 -1
  32. package/lib/board-live-cards-public.d.ts +1 -1
  33. package/lib/board-live-cards-public.js +1 -1
  34. package/lib/board-live-cards-server-runtime.cjs +4 -4
  35. package/lib/board-live-cards-server-runtime.d.cts +2 -2
  36. package/lib/board-live-cards-server-runtime.d.ts +2 -2
  37. package/lib/board-live-cards-server-runtime.js +4 -4
  38. package/lib/card-store-public.d.cts +1 -1
  39. package/lib/card-store-public.d.ts +1 -1
  40. package/lib/server-runtime/index.cjs +4 -4
  41. package/lib/server-runtime/index.d.cts +3 -3
  42. package/lib/server-runtime/index.d.ts +3 -3
  43. package/lib/server-runtime/index.js +4 -4
  44. package/lib/{types-DkFvgxwq.d.cts → types-CXBzvC0s.d.cts} +1 -1
  45. package/lib/{types-CBxkYuLY.d.ts → types-D48hpnTR.d.ts} +1 -1
  46. package/package.json +4 -4
  47. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/gandalf-runtime/.config/card-store-ref.json +0 -1
  48. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/gandalf-runtime/.config/chat-handler.json +0 -1
  49. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/gandalf-runtime/.config/outputs-store-ref.json +0 -1
  50. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/gandalf-runtime/.config/task-executor.json +0 -1
  51. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/gandalf-runtime/.state-snapshot/board/graph.json +0 -29
  52. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/gandalf-runtime/.state-snapshot/board/lastJournalProcessedId.json +0 -1
  53. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/gandalf-runtime-out/.outputs/status.json +0 -25
  54. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/runtime-out/.outputs/cards/card-market-prices/computed_values.json +0 -67
  55. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/runtime-out/.outputs/cards/card-portfolio/computed_values.json +0 -1
  56. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/runtime-out/.outputs/cards/card-portfolio-value/computed_values.json +0 -52
  57. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/runtime-out/.outputs/data-objects/holdings.json +0 -22
  58. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/runtime-out/.outputs/data-objects/positions.json +0 -46
  59. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/runtime-out/.outputs/data-objects/quotes.json +0 -35
  60. package/examples/board/.demo-setup/run-1778665078572-3466-a8ay4k/board-default/runtime-out/.outputs/status.json +0 -113
@@ -277,6 +277,21 @@ interface BoardNonCorePlatformAdapter extends BoardPlatformAdapter {
277
277
  makeTempFilePath(label: string, ext?: string): string;
278
278
  /** Absolute-path blob I/O for temp files and card file references. */
279
279
  absoluteBlob: BlobStorage;
280
+ /**
281
+ * Default timeouts (ms) for synchronous executor invocations.
282
+ * Each field can also be overridden per-source via source_def.timeout.
283
+ *
284
+ * validationMs — validate-source-def, validate-card-preflight (structural, fast). Default: 10_000.
285
+ * preflightMs — probe-source-preflight (runs a real source fetch). Default: 60_000.
286
+ * probeMs — run-source-fetch in probe/simulation paths. Default: 60_000.
287
+ * describeMs — describe-capabilities introspection. Default: 10_000.
288
+ */
289
+ executorTimeouts?: {
290
+ validationMs?: number;
291
+ preflightMs?: number;
292
+ probeMs?: number;
293
+ describeMs?: number;
294
+ };
280
295
  }
281
296
  interface BoardLiveCardsNonCorePublic {
282
297
  /** params: cardId? or all?; returns array even for single card */
@@ -0,0 +1,188 @@
1
+ # yaml-flow — Architecture & Reuse Guide
2
+
3
+ A quick reference for anyone integrating yaml-flow into their own stack,
4
+ or adapting it to different infrastructure.
5
+
6
+ ---
7
+
8
+ ## Package exports — layered architecture
9
+
10
+ ```
11
+ ┌──────────────────────────────────────────────────────────────────┐
12
+ │ YOUR HOST SHIM (thin, you write — a few dozen lines) │
13
+ │ Adapt your platform's request/response → RuntimeRequest/ │
14
+ │ RuntimeResponse. Wire SSE streaming. Construct adapters. │
15
+ ├──────────────────────────────────────────────────────────────────┤
16
+ │ PLATFORM ADAPTER → board-live-cards-node │
17
+ │ FS + local-process reference implementation. │
18
+ │ Replace this layer for different storage/invocation infra. │
19
+ │ Implement: BoardPlatformAdapter, CardStore, ArtifactsStore, ... │
20
+ ├──────────────────────────────────────────────────────────────────┤
21
+ │ SERVER ORCHESTRATION → board-live-cards-server-runtime │
22
+ │ Routes, board lifecycle, chat/file orchestration. │
23
+ │ Platform-free — all I/O injected via adapters. │
24
+ │ Works on Node HTTP, Azure Functions, Cloudflare Workers, etc. │
25
+ ├──────────────────────────────────────────────────────────────────┤
26
+ │ STORAGE CONTRACTS → card-store-public, artifacts-store-public │
27
+ │ Interfaces only. No implementations. Code against these. │
28
+ ├──────────────────────────────────────────────────────────────────┤
29
+ │ CORE LOGIC → . / board-live-cards-public, step-machine-public │
30
+ │ Pure computation — card graph, event engine, step machine. │
31
+ │ No FS, no Node, no HTTP. Works anywhere (browser included). │
32
+ └──────────────────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ **Reuse everything except the platform adapter layer.**
36
+ To move from Node+FS to Azure Functions+Cosmos DB:
37
+ - Implement your own `BoardPlatformAdapter` backed by Cosmos/Azure Blob
38
+ - Write a thin host shim that maps Azure `HttpRequest` → `RuntimeRequest`
39
+ - Extend ref dispatch for new `howToRun` kinds via `createExecutionRefInvoker({ transports, syncTransports })` — no layer replacement needed
40
+ - Everything else — server runtime, core logic, client bundles — is unchanged
41
+
42
+ ---
43
+
44
+ ## Worker side — board-worker-adapter
45
+
46
+ Used by any **external process** the board dispatches work to:
47
+ task executors, chat handlers, inference workers, etc.
48
+
49
+ Provides the full worker contract in a single zero-dependency file:
50
+ - `parseRef` / `serializeRef` — wire-format ref decoding
51
+ - `blobStorageForRef` — resolve a ref to its storage backend (`read`/`write`)
52
+ - `reportComplete` / `reportFailed` — call back to the board on completion
53
+ - `ExecutionRef`, `TaskCallback`, `BlobStorage` — the stable protocol types
54
+
55
+ **Adapting to different infrastructure:**
56
+
57
+ | What changes | What to do |
58
+ |---|---|
59
+ | Storage backend (Cosmos, Azure Blob, S3) | Add a new `case` in `blobStorageForRef()` for the new `KindValueRef.kind` |
60
+ | Callback transport (Service Bus, queue) | Add a new `case` in `reportComplete`/`reportFailed` for the new `howToRun` value |
61
+ | Worker hosting (Azure Functions, Lambda) | Nothing here — the worker reads its inRef and calls `reportComplete`; hosting is transparent |
62
+
63
+ Tip: copy this file into your worker project and extend locally.
64
+ The interfaces are the stable contract; backends are just switch cases.
65
+
66
+ ---
67
+
68
+ ## Browser bundles
69
+
70
+ All browser bundles are standalone IIFE files — no bundler required.
71
+ Include them with a `<script>` tag. Each sets a global on `window`.
72
+
73
+ ### compute-jsonata.js → `window.jsonataSync`
74
+
75
+ Vendored jsonata engine for in-browser card computation.
76
+ **Must be loaded before** `board-livecards-localstorage.js`.
77
+
78
+ ```html
79
+ <script src="compute-jsonata.js"></script>
80
+ ```
81
+
82
+ No public API — just sets `window.jsonataSync` for the other bundles to pick up.
83
+
84
+ ---
85
+
86
+ ### board-livecards-localstorage.js → `window.BoardLiveCardsLocalStorage`
87
+
88
+ **Drop-in full board engine for the browser** — no server required.
89
+
90
+ Bundles: board engine + card computation + localStorage adapter.
91
+ Ideal for demos, offline use, or prototyping before wiring up a server.
92
+
93
+ ```html
94
+ <script src="compute-jsonata.js"></script>
95
+ <script src="board-livecards-localstorage.js"></script>
96
+ <script>
97
+ const app = BoardLiveCardsLocalStorage.create('my-board', {
98
+ cards: [ /* card JSON objects */ ],
99
+ taskExecutor: async (ref, args) => { /* your async task handler */ },
100
+ });
101
+ await app.bootstrap();
102
+ const state = app.getState();
103
+ // → feed to live-cards.js via LiveCard.init(...)
104
+ </script>
105
+ ```
106
+
107
+ Key exports: `create()`, `selectLiveCardModel()`, `selectAllLiveCardModels()`
108
+
109
+ ---
110
+
111
+ ### board-livecards-client.js → `window.BoardLiveCardsClient`
112
+
113
+ **Client for a yaml-flow HTTP/SSE server.** Two modes in one bundle:
114
+
115
+ 1. **SSE/HTTP mode** — connects to a `board-live-cards-server-runtime` host:
116
+ ```html
117
+ <script src="board-livecards-client.js"></script>
118
+ <script>
119
+ const client = BoardLiveCardsClient.createBoardRuntimeClient({
120
+ fetchServer,
121
+ boardPaths: BoardLiveCardsClient.defaultBoardPaths('my-board'),
122
+ getServerOrigin,
123
+ });
124
+ await client.bootstrapBoard({ boardId: 'my-board', rootElement: el });
125
+ </script>
126
+ ```
127
+
128
+ 2. **Custom transport mode** — use the platform-free state layer with Firebase,
129
+ WebSocket, or any other transport. Import `buildBoardState`, `applyNotification`,
130
+ `selectAllLiveCardModels` and drive them yourself.
131
+
132
+ Key exports: `createBoardRuntimeClient`, `defaultBoardPaths`, `singleBoardPaths`,
133
+ `buildBoardState`, `applyNotification`, `selectLiveCardModel`, `selectAllLiveCardModels`
134
+
135
+ ---
136
+
137
+ ### live-cards.js → `window.LiveCard`
138
+
139
+ **UI rendering engine** — turns board state (card models) into interactive HTML.
140
+
141
+ Renders card view definitions (tables, metrics, charts, markdown, forms, badges, etc.)
142
+ into DOM elements. Handles card-to-card `requires`/`provides` token wiring,
143
+ action buttons, chat panels, file attachments, and editable fields.
144
+
145
+ ```html
146
+ <script src="live-cards.js"></script>
147
+ <script>
148
+ const engine = LiveCard.init({
149
+ resolve, // (nodeId) → card model
150
+ onPatch, // called when user edits a field
151
+ onAction, // called on action button click
152
+ getChatMessages, // () → messages for chat panel
153
+ markdown, // optional: (text) → html (e.g. marked.parse)
154
+ sanitize, // optional: (html) → safe html (e.g. DOMPurify.sanitize)
155
+ chartLib, // optional: Chart.js constructor
156
+ });
157
+ </script>
158
+ ```
159
+
160
+ **Optional external JS** — all injected, none bundled:
161
+
162
+ | Library | Purpose | Inject via |
163
+ |---|---|---|
164
+ | [Bootstrap 5](https://getbootstrap.com/) | Layout, forms, badges | `<link>` + `<script>` (CSS + JS) |
165
+ | [Chart.js](https://www.chartjs.org/) | Chart rendering in cards | `chartLib` config param |
166
+ | [marked](https://marked.js.org/) | Markdown → HTML | `markdown` config param |
167
+ | [DOMPurify](https://github.com/cure53/DOMPurify) | Sanitize markdown output | `sanitize` config param |
168
+
169
+ Bootstrap CSS is required for layout. Everything else is optional — if not provided,
170
+ charts fall back to tables and markdown renders as escaped plain text.
171
+
172
+ ---
173
+
174
+ ## Typical script load order (full browser setup)
175
+
176
+ ```html
177
+ <!-- 1. Optional external libs -->
178
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css">
179
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.bundle.min.js"></script>
180
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
181
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
182
+ <script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
183
+
184
+ <!-- 2. yaml-flow bundles — order matters -->
185
+ <script src="compute-jsonata.js"></script> <!-- sets window.jsonataSync -->
186
+ <script src="board-livecards-localstorage.js"></script> <!-- or board-livecards-client.js -->
187
+ <script src="live-cards.js"></script> <!-- sets window.LiveCard -->
188
+ ```
@@ -19,8 +19,8 @@
19
19
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
20
20
  <script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
21
21
  <script src="https://cdn.jsdelivr.net/npm/leader-line/leader-line.min.js"></script>
22
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.1/browser/live-cards.js"></script>
23
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.1/browser/board-livecards-client.js"></script>
22
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.4/browser/live-cards.js"></script>
23
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.4/browser/board-livecards-client.js"></script>
24
24
  </head>
25
25
  <body class="bg-light">
26
26
  <div class="container-fluid py-3">
@@ -7,24 +7,23 @@
7
7
  * run-source-fetch — fetch data for one source entry
8
8
  * describe-capabilities — print supported source kinds + schemas to stdout (JSON)
9
9
  *
10
- * CLI args:
11
- * --in <source.json> Required. Path to a temp JSON file containing the source definition.
12
- * --out <result.json> Required. Path where this executor must write its JSON result.
13
- * --err <error.txt> Optional. Path where this executor writes an error message on failure.
14
- * --extra <base64json> Optional. Base64-encoded JSON with board topology context
15
- * (baked into .task-executor at board init time, passed blindly by the CLI).
10
+ * Subcommand CLI args:
16
11
  *
17
- * --in payload (source definition):
18
- * {
19
- * "bindTo": "token_name",
20
- * "outputFile": "relative/path.json",
21
- * "cwd": "<card directory>", // injected by CLI
22
- * "boardDir":"<board runtime directory>", // injected by CLI
23
- * "_projections": { "refKey": <resolvedValue> }, // named projections from card_data/requires,
24
- * // declared in source_defs[].projections and resolved
25
- * // by the engine before invoking the executor
26
- * // ...plus any custom fields authored on the source entry (bindTo, outputFile, projections, etc.)
27
- * }
12
+ * run-source-fetch
13
+ * --in-ref <b64ref> Required. Ref to a temp JSON envelope: { source_def, callback? }
14
+ * --out-ref <b64ref> Required. Ref where this executor writes its JSON result.
15
+ * --err-ref <b64ref> Optional. Ref where this executor writes an error message on failure.
16
+ * --extra <base64json> Optional. Base64-encoded JSON with board topology context.
17
+ *
18
+ * validate-source-def source def JSON on stdin; stdout: { ok, errors[] }
19
+ * validate-card-preflight card JSON on stdin; stdout: { ok, errors[] }
20
+ * probe-source-preflight — source def JSON (with _projections) on stdin;
21
+ * stdout: { ok, reachable, latencyMs, error? }
22
+ * describe-capabilities — no stdin; stdout: capability manifest JSON
23
+ *
24
+ * run-source-fetch --in-ref envelope payload:
25
+ * { "source_def": { ... }, "callback": { ... } }
26
+ * or legacy: raw source_def object (no callback field)
28
27
  *
29
28
  * --extra (decoded):
30
29
  * {
@@ -506,27 +505,25 @@ async function probeSourcePreflightSubcommand(argv) {
506
505
  }
507
506
 
508
507
  // ---------------------------------------------------------------------------
509
- // validate-source-def — structural validation of a source definition
508
+ // validate-source-def — structural validation of a source definition.
509
+ // Source def JSON arrives on stdin (board-live-cards-public sends it via input:).
510
510
  // ---------------------------------------------------------------------------
511
- function validateSourceDefSubcommand(argv) {
512
- const inIdx = argv.indexOf('--in');
513
- const inFile = inIdx !== -1 ? argv[inIdx + 1] : undefined;
514
-
515
- if (!inFile) {
516
- console.error('[demo-task-executor] Usage: validate-source-def --in <source.json>');
517
- process.exit(1);
518
- }
519
-
520
- if (!fs.existsSync(inFile)) {
521
- console.log(JSON.stringify({ ok: false, errors: [`Input file not found: ${inFile}`] }));
511
+ async function validateSourceDefSubcommand() {
512
+ const chunks = [];
513
+ for await (const chunk of process.stdin) {
514
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
515
+ }
516
+ const raw = Buffer.concat(chunks).toString('utf-8').trim();
517
+ if (!raw) {
518
+ console.log(JSON.stringify({ ok: false, errors: ['No input provided on stdin'] }));
522
519
  process.exit(1);
523
520
  }
524
521
 
525
522
  let sourceDef;
526
523
  try {
527
- sourceDef = readJson(inFile);
524
+ sourceDef = JSON.parse(raw);
528
525
  } catch (err) {
529
- console.log(JSON.stringify({ ok: false, errors: [`Cannot parse source file: ${err && err.message || err}`] }));
526
+ console.log(JSON.stringify({ ok: false, errors: [`Cannot parse input: ${err && err.message || err}`] }));
530
527
  process.exit(1);
531
528
  }
532
529
 
@@ -710,7 +707,7 @@ async function main() {
710
707
  return;
711
708
  }
712
709
  if (sub === 'validate-source-def') {
713
- validateSourceDefSubcommand(process.argv.slice(3));
710
+ await validateSourceDefSubcommand();
714
711
  return;
715
712
  }
716
713
 
@@ -6,13 +6,13 @@
6
6
  <title>Example Board Demo (LocalStorage Runtime)</title>
7
7
  <link rel="icon" type="image/svg+xml" href="../../browser/favicon.svg" />
8
8
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
9
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.1/browser/compute-jsonata.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.4/browser/compute-jsonata.js"></script>
10
10
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
11
11
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
12
12
  <script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
13
13
  <script src="https://cdn.jsdelivr.net/npm/leader-line/leader-line.min.js"></script>
14
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.1/browser/live-cards.js"></script>
15
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.1/browser/board-livecards-localstorage.js"></script>
14
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.4/browser/live-cards.js"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.0.4/browser/board-livecards-localstorage.js"></script>
16
16
  </head>
17
17
  <body class="bg-light">
18
18
  <div class="container-fluid py-3">
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ // Ref handler: reads JSON from stdin, doubles the "sum" field, writes JSON to stdout.
3
+
4
+ let raw = '';
5
+ process.stdin.setEncoding('utf-8');
6
+ process.stdin.on('data', (chunk) => { raw += chunk; });
7
+ process.stdin.on('end', () => {
8
+ try {
9
+ const input = JSON.parse(raw || '{}');
10
+ const sum = Number(input.sum);
11
+ if (!Number.isFinite(sum)) {
12
+ process.stderr.write('double-handler requires numeric sum\n');
13
+ process.exit(1);
14
+ }
15
+ process.stdout.write(JSON.stringify({ doubled: sum * 2 }));
16
+ } catch (err) {
17
+ process.stderr.write(String(err) + '\n');
18
+ process.exit(1);
19
+ }
20
+ });
@@ -0,0 +1,118 @@
1
+ {
2
+ "id": "mixed-handlers-demo",
3
+ "settings": {
4
+ "start_step": "step1_compute",
5
+ "max_total_steps": 15,
6
+ "timeout_ms": 15000
7
+ },
8
+ "steps": {
9
+ "step1_compute": {
10
+ "description": "Inline compute — adds two numbers using JSONata",
11
+ "expects_data": ["a", "b"],
12
+ "produces_data": ["sum"],
13
+ "input_validations": [
14
+ "$type(a) = \"number\"",
15
+ "$type(b) = \"number\""
16
+ ],
17
+ "handler": {
18
+ "type": "compute-jsonata",
19
+ "expr": [
20
+ "data.sum = expects_data.a + expects_data.b",
21
+ "result = \"success\""
22
+ ]
23
+ },
24
+ "transitions": {
25
+ "success": "step2_ref",
26
+ "failure": "failed_state"
27
+ }
28
+ },
29
+ "step2_ref": {
30
+ "description": "Ref handler — doubles the sum via an external Node script",
31
+ "expects_data": ["sum"],
32
+ "produces_data": ["doubled"],
33
+ "handler": {
34
+ "type": "ref",
35
+ "howToRun": "local-node",
36
+ "whatToRun": { "kind": "fs-path", "value": "./double-handler.js" }
37
+ },
38
+ "transitions": {
39
+ "success": "step3_scale_each",
40
+ "failure": "failed_state"
41
+ }
42
+ },
43
+ "step3_scale_each": {
44
+ "description": "forEach + compute-jsonata — scale doubled value by each multiplier",
45
+ "expects_data": ["doubled", "multipliers"],
46
+ "produces_data": ["scaled_values"],
47
+ "forEach": {
48
+ "items": "multipliers",
49
+ "as": "multiplier",
50
+ "concurrency": 3,
51
+ "collectAs": "scaled_values"
52
+ },
53
+ "handler": {
54
+ "type": "compute-jsonata",
55
+ "expr": [
56
+ "data.value = expects_data.doubled * expects_data.multiplier",
57
+ "result = \"success\""
58
+ ]
59
+ },
60
+ "transitions": {
61
+ "success": "step4_ref_each",
62
+ "failure": "failed_state"
63
+ }
64
+ },
65
+ "step4_ref_each": {
66
+ "description": "forEach + ref — re-scale each value via an external Node script",
67
+ "expects_data": ["scaled_values"],
68
+ "produces_data": ["final_values"],
69
+ "forEach": {
70
+ "items": "scaled_values",
71
+ "as": "item",
72
+ "concurrency": 3,
73
+ "collectAs": "final_values"
74
+ },
75
+ "handler": {
76
+ "type": "ref",
77
+ "howToRun": "local-node",
78
+ "whatToRun": { "kind": "fs-path", "value": "./scale-handler.js" },
79
+ "argsMassaging": {
80
+ "cmdTemplate": [
81
+ "$string(item.value)",
82
+ "'2'"
83
+ ]
84
+ }
85
+ },
86
+ "transitions": {
87
+ "success": "step5_grade",
88
+ "failure": "failed_state"
89
+ }
90
+ },
91
+ "step5_grade": {
92
+ "description": "Inline compute — classifies whether any final value exceeds 200",
93
+ "expects_data": ["final_values"],
94
+ "produces_data": ["grade"],
95
+ "handler": {
96
+ "type": "compute-jsonata",
97
+ "expr": [
98
+ "data.grade = $max(expects_data.final_values.scaled) >= 200 ? \"large\" : \"small\"",
99
+ "result = \"success\""
100
+ ]
101
+ },
102
+ "transitions": {
103
+ "success": "success_state",
104
+ "failure": "failed_state"
105
+ }
106
+ }
107
+ },
108
+ "terminal_states": {
109
+ "success_state": {
110
+ "return_intent": "success",
111
+ "return_artifacts": ["a", "b", "sum", "doubled", "scaled_values", "final_values", "grade"]
112
+ },
113
+ "failed_state": {
114
+ "return_intent": "failure",
115
+ "return_artifacts": ["error"]
116
+ }
117
+ }
118
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "a": 25,
3
+ "b": 30,
4
+ "multipliers": [1, 2, 3]
5
+ }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ // Ref handler: takes value and multiplier as CLI args, writes JSON to stdout.
3
+ // Usage: node scale-handler.js <value> <multiplier>
4
+
5
+ const value = Number(process.argv[2]);
6
+ const multiplier = Number(process.argv[3]);
7
+
8
+ if (!Number.isFinite(value) || !Number.isFinite(multiplier)) {
9
+ process.stderr.write('scale-handler requires numeric value and multiplier as CLI args\n');
10
+ process.exit(1);
11
+ }
12
+
13
+ process.stdout.write(JSON.stringify({ scaled: value * multiplier }));
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ // Ref handler: reads JSON from stdin, doubles the "sum" field, writes JSON to stdout.
3
+
4
+ let raw = '';
5
+ process.stdin.setEncoding('utf-8');
6
+ process.stdin.on('data', (chunk) => { raw += chunk; });
7
+ process.stdin.on('end', () => {
8
+ try {
9
+ const input = JSON.parse(raw || '{}');
10
+ const sum = Number(input.sum);
11
+ if (!Number.isFinite(sum)) {
12
+ process.stderr.write('double-handler requires numeric sum\n');
13
+ process.exit(1);
14
+ }
15
+ process.stdout.write(JSON.stringify({ doubled: sum * 2 }));
16
+ } catch (err) {
17
+ process.stderr.write(String(err) + '\n');
18
+ process.exit(1);
19
+ }
20
+ });
@@ -0,0 +1,94 @@
1
+ id: mixed-handlers-demo
2
+ settings:
3
+ start_step: step1_compute
4
+ max_total_steps: 15
5
+ timeout_ms: 15000
6
+
7
+ steps:
8
+ step1_compute:
9
+ description: Inline compute — adds two numbers using JSONata
10
+ expects_data: [a, b]
11
+ produces_data: [sum]
12
+ input_validations:
13
+ - $type(a) = "number"
14
+ - $type(b) = "number"
15
+ handler:
16
+ type: compute-jsonata
17
+ expr:
18
+ - data.sum = expects_data.a + expects_data.b
19
+ - result = "success"
20
+ transitions:
21
+ success: step2_ref
22
+ failure: failed_state
23
+
24
+ step2_ref:
25
+ description: Ref handler — doubles the sum via an external Node script
26
+ expects_data: [sum]
27
+ produces_data: [doubled]
28
+ handler:
29
+ type: ref
30
+ howToRun: local-node
31
+ whatToRun: {kind: fs-path, value: ./double-handler.js}
32
+ transitions:
33
+ success: step3_scale_each
34
+ failure: failed_state
35
+
36
+ step3_scale_each:
37
+ description: forEach + compute-jsonata — scale doubled value by each multiplier
38
+ expects_data: [doubled, multipliers]
39
+ produces_data: [scaled_values]
40
+ forEach:
41
+ items: multipliers
42
+ as: multiplier
43
+ concurrency: 3
44
+ collectAs: scaled_values
45
+ handler:
46
+ type: compute-jsonata
47
+ expr:
48
+ - data.value = expects_data.doubled * expects_data.multiplier
49
+ - result = "success"
50
+ transitions:
51
+ success: step4_ref_each
52
+ failure: failed_state
53
+
54
+ step4_ref_each:
55
+ description: forEach + ref — re-scale each value via an external Node script
56
+ expects_data: [scaled_values]
57
+ produces_data: [final_values]
58
+ forEach:
59
+ items: scaled_values
60
+ as: item
61
+ concurrency: 3
62
+ collectAs: final_values
63
+ handler:
64
+ type: ref
65
+ howToRun: local-node
66
+ whatToRun: {kind: fs-path, value: ./scale-handler.js}
67
+ argsMassaging:
68
+ cmdTemplate:
69
+ - "$string(item.value)"
70
+ - "'2'"
71
+ transitions:
72
+ success: step5_grade
73
+ failure: failed_state
74
+
75
+ step5_grade:
76
+ description: Inline compute — classifies whether any final value exceeds 200
77
+ expects_data: [final_values]
78
+ produces_data: [grade]
79
+ handler:
80
+ type: compute-jsonata
81
+ expr:
82
+ - 'data.grade = $max(expects_data.final_values.scaled) >= 200 ? "large" : "small"'
83
+ - result = "success"
84
+ transitions:
85
+ success: success_state
86
+ failure: failed_state
87
+
88
+ terminal_states:
89
+ success_state:
90
+ return_intent: success
91
+ return_artifacts: [a, b, sum, doubled, scaled_values, final_values, grade]
92
+ failed_state:
93
+ return_intent: failure
94
+ return_artifacts: [error]
@@ -0,0 +1,5 @@
1
+ {
2
+ "a": 25,
3
+ "b": 30,
4
+ "multipliers": [1, 2, 3]
5
+ }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ // Ref handler: takes value and multiplier as CLI args, writes JSON to stdout.
3
+ // Usage: node scale-handler.js <value> <multiplier>
4
+
5
+ const value = Number(process.argv[2]);
6
+ const multiplier = Number(process.argv[3]);
7
+
8
+ if (!Number.isFinite(value) || !Number.isFinite(multiplier)) {
9
+ process.stderr.write('scale-handler requires numeric value and multiplier as CLI args\n');
10
+ process.exit(1);
11
+ }
12
+
13
+ process.stdout.write(JSON.stringify({ scaled: value * multiplier }));
@@ -1,4 +1,4 @@
1
- import { C as CommandInput, a as CommandResult } from './board-live-cards-public-CsmYrvpd.js';
1
+ import { C as CommandInput, a as CommandResult } from './board-live-cards-public-dJAl5IL-.js';
2
2
  import { B as BlobStorage } from './storage-interface-BhAON-gW.js';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as CommandInput, a as CommandResult } from './board-live-cards-public-BnmRAbQV.cjs';
1
+ import { C as CommandInput, a as CommandResult } from './board-live-cards-public-BF9FP0mL.cjs';
2
2
  import { B as BlobStorage } from './storage-interface-BhAON-gW.cjs';
3
3
 
4
4
  /**
@@ -1,5 +1,5 @@
1
- import './board-live-cards-public-BnmRAbQV.cjs';
2
- export { A as ArtifactsStorePublic, a as createArtifactsStorePublic } from './artifacts-store-lib-public-DGa8BpJT.cjs';
1
+ import './board-live-cards-public-BF9FP0mL.cjs';
2
+ export { A as ArtifactsStorePublic, a as createArtifactsStorePublic } from './artifacts-store-lib-public-DBICnGL6.cjs';
3
3
  import './storage-interface-BhAON-gW.cjs';
4
4
  import './execution-refs.cjs';
5
5
  import './types-BBhqYGhE.cjs';
@@ -1,5 +1,5 @@
1
- import './board-live-cards-public-CsmYrvpd.js';
2
- export { A as ArtifactsStorePublic, a as createArtifactsStorePublic } from './artifacts-store-lib-public-BABrgFkV.js';
1
+ import './board-live-cards-public-dJAl5IL-.js';
2
+ export { A as ArtifactsStorePublic, a as createArtifactsStorePublic } from './artifacts-store-lib-public-BWC3YuLa.js';
3
3
  import './storage-interface-BhAON-gW.js';
4
4
  import './execution-refs.js';
5
5
  import './types-BBhqYGhE.js';