yaml-flow 5.4.2 → 7.0.0

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 (252) hide show
  1. package/board-live-cards-cli.js +6 -6
  2. package/browser/asset-integrity.json +10 -0
  3. package/browser/board-livecards-client.js +2 -0
  4. package/browser/board-livecards-client.js.map +1 -0
  5. package/browser/board-livecards-localstorage.js +10 -0
  6. package/browser/board-livecards-localstorage.js.map +1 -0
  7. package/browser/board-livegraph-engine.js +2 -1676
  8. package/browser/board-livegraph-engine.js.map +1 -1
  9. package/browser/card-compute.js +28 -28
  10. package/browser/compute-jsonata.js +5 -0
  11. package/browser/compute-jsonata.js.map +1 -0
  12. package/browser/live-cards.js +561 -129
  13. package/browser/live-cards.schema.json +418 -132
  14. package/card-store.js +37 -0
  15. package/dist/batch/index.cjs +1 -108
  16. package/dist/batch/index.cjs.map +1 -1
  17. package/dist/batch/index.js +1 -106
  18. package/dist/batch/index.js.map +1 -1
  19. package/dist/board-live-cards-lib-Bg6EvCo5.d.cts +136 -0
  20. package/dist/board-live-cards-lib-jM2uYG1v.d.ts +136 -0
  21. package/dist/board-live-cards-public-CW5074xr.d.cts +318 -0
  22. package/dist/board-live-cards-public-hnZo0mAf.d.ts +318 -0
  23. package/dist/board-livegraph-runtime/index.cjs +2 -1671
  24. package/dist/board-livegraph-runtime/index.cjs.map +1 -1
  25. package/dist/board-livegraph-runtime/index.d.cts +12 -11
  26. package/dist/board-livegraph-runtime/index.d.ts +12 -11
  27. package/dist/board-livegraph-runtime/index.js +2 -1662
  28. package/dist/board-livegraph-runtime/index.js.map +1 -1
  29. package/dist/board-livegraph-runtime/jsonata-sync.cjs +7623 -0
  30. package/dist/card-compute/index.cjs +9 -7159
  31. package/dist/card-compute/index.cjs.map +1 -1
  32. package/dist/card-compute/index.d.cts +27 -1
  33. package/dist/card-compute/index.d.ts +27 -1
  34. package/dist/card-compute/index.js +9 -7145
  35. package/dist/card-compute/index.js.map +1 -1
  36. package/dist/card-compute/jsonata-sync.cjs +7623 -0
  37. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs +3 -0
  38. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs.map +1 -0
  39. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.cts +37 -0
  40. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.ts +37 -0
  41. package/dist/cli/browser-api/board-live-cards-browser-adapter.js +3 -0
  42. package/dist/cli/browser-api/board-live-cards-browser-adapter.js.map +1 -0
  43. package/dist/cli/browser-api/card-store-browser-api.cjs +2 -0
  44. package/dist/cli/browser-api/card-store-browser-api.cjs.map +1 -0
  45. package/dist/cli/browser-api/card-store-browser-api.d.cts +26 -0
  46. package/dist/cli/browser-api/card-store-browser-api.d.ts +26 -0
  47. package/dist/cli/browser-api/card-store-browser-api.js +2 -0
  48. package/dist/cli/browser-api/card-store-browser-api.js.map +1 -0
  49. package/dist/cli/browser-api/jsonata-sync.cjs +7623 -0
  50. package/dist/cli/node/artifacts-store-cli.cjs +11 -0
  51. package/dist/cli/node/artifacts-store-cli.cjs.map +1 -0
  52. package/dist/cli/node/artifacts-store-cli.d.cts +8 -0
  53. package/dist/cli/node/artifacts-store-cli.d.ts +8 -0
  54. package/dist/cli/node/artifacts-store-cli.js +11 -0
  55. package/dist/cli/node/artifacts-store-cli.js.map +1 -0
  56. package/dist/cli/node/board-live-cards-cli.cjs +15 -0
  57. package/dist/cli/node/board-live-cards-cli.cjs.map +1 -0
  58. package/dist/cli/node/board-live-cards-cli.d.cts +20 -0
  59. package/dist/cli/node/board-live-cards-cli.d.ts +20 -0
  60. package/dist/cli/node/board-live-cards-cli.js +15 -0
  61. package/dist/cli/node/board-live-cards-cli.js.map +1 -0
  62. package/dist/cli/node/card-store-cli.cjs +8 -0
  63. package/dist/cli/node/card-store-cli.cjs.map +1 -0
  64. package/dist/cli/node/card-store-cli.d.cts +15 -0
  65. package/dist/cli/node/card-store-cli.d.ts +15 -0
  66. package/dist/cli/node/card-store-cli.js +8 -0
  67. package/dist/cli/node/card-store-cli.js.map +1 -0
  68. package/dist/cli/node/execution-adapter.cjs +3 -0
  69. package/dist/cli/node/execution-adapter.cjs.map +1 -0
  70. package/dist/cli/node/execution-adapter.d.cts +174 -0
  71. package/dist/cli/node/execution-adapter.d.ts +174 -0
  72. package/dist/cli/node/execution-adapter.js +3 -0
  73. package/dist/cli/node/execution-adapter.js.map +1 -0
  74. package/dist/cli/node/fs-board-adapter.cjs +14 -0
  75. package/dist/cli/node/fs-board-adapter.cjs.map +1 -0
  76. package/dist/cli/node/fs-board-adapter.d.cts +204 -0
  77. package/dist/cli/node/fs-board-adapter.d.ts +204 -0
  78. package/dist/cli/node/fs-board-adapter.js +14 -0
  79. package/dist/cli/node/fs-board-adapter.js.map +1 -0
  80. package/dist/cli/node/jsonata-sync.cjs +7623 -0
  81. package/dist/cli/node/source-cli-task-executor.cjs +11 -0
  82. package/dist/cli/node/source-cli-task-executor.cjs.map +1 -0
  83. package/dist/cli/node/source-cli-task-executor.d.cts +1 -0
  84. package/dist/cli/node/source-cli-task-executor.d.ts +1 -0
  85. package/dist/cli/node/source-cli-task-executor.js +11 -0
  86. package/dist/cli/node/source-cli-task-executor.js.map +1 -0
  87. package/dist/config/index.cjs +1 -79
  88. package/dist/config/index.cjs.map +1 -1
  89. package/dist/config/index.js +1 -76
  90. package/dist/config/index.js.map +1 -1
  91. package/dist/continuous-event-graph/index.cjs +2 -2129
  92. package/dist/continuous-event-graph/index.cjs.map +1 -1
  93. package/dist/continuous-event-graph/index.d.cts +81 -5
  94. package/dist/continuous-event-graph/index.d.ts +81 -5
  95. package/dist/continuous-event-graph/index.js +2 -2088
  96. package/dist/continuous-event-graph/index.js.map +1 -1
  97. package/dist/continuous-event-graph/jsonata-sync.cjs +7623 -0
  98. package/dist/event-graph/index.cjs +22 -8292
  99. package/dist/event-graph/index.cjs.map +1 -1
  100. package/dist/event-graph/index.js +22 -8237
  101. package/dist/event-graph/index.js.map +1 -1
  102. package/dist/execution-refs.cjs +3 -0
  103. package/dist/execution-refs.cjs.map +1 -0
  104. package/dist/execution-refs.d.cts +260 -0
  105. package/dist/execution-refs.d.ts +260 -0
  106. package/dist/execution-refs.js +3 -0
  107. package/dist/execution-refs.js.map +1 -0
  108. package/dist/index.cjs +29 -13221
  109. package/dist/index.cjs.map +1 -1
  110. package/dist/index.d.cts +2 -4
  111. package/dist/index.d.ts +2 -4
  112. package/dist/index.js +29 -13112
  113. package/dist/index.js.map +1 -1
  114. package/dist/inference/index.cjs +5 -617
  115. package/dist/inference/index.cjs.map +1 -1
  116. package/dist/inference/index.js +5 -610
  117. package/dist/inference/index.js.map +1 -1
  118. package/dist/jsonata-sync.cjs +7623 -0
  119. package/dist/{live-cards-bridge-x5XREkXm.d.cts → live-cards-bridge-BXbVTsna.d.cts} +27 -4
  120. package/dist/{live-cards-bridge-EQjytzI_.d.ts → live-cards-bridge-Ds28XR15.d.ts} +27 -4
  121. package/dist/server-runtime/index.cjs +9 -0
  122. package/dist/server-runtime/index.cjs.map +1 -0
  123. package/dist/server-runtime/index.d.cts +31 -0
  124. package/dist/server-runtime/index.d.ts +31 -0
  125. package/dist/server-runtime/index.js +9 -0
  126. package/dist/server-runtime/index.js.map +1 -0
  127. package/dist/server-runtime/jsonata-sync.cjs +7623 -0
  128. package/dist/step-machine/index.cjs +11 -7129
  129. package/dist/step-machine/index.cjs.map +1 -1
  130. package/dist/step-machine/index.js +11 -7113
  131. package/dist/step-machine/index.js.map +1 -1
  132. package/dist/step-machine-public/index.cjs +2 -0
  133. package/dist/step-machine-public/index.cjs.map +1 -0
  134. package/dist/step-machine-public/index.d.cts +159 -0
  135. package/dist/step-machine-public/index.d.ts +159 -0
  136. package/dist/step-machine-public/index.js +2 -0
  137. package/dist/step-machine-public/index.js.map +1 -0
  138. package/dist/step-machine-public/jsonata-sync.cjs +7623 -0
  139. package/dist/storage-refs.cjs +10 -0
  140. package/dist/storage-refs.cjs.map +1 -0
  141. package/dist/storage-refs.d.cts +93 -0
  142. package/dist/storage-refs.d.ts +93 -0
  143. package/dist/storage-refs.js +10 -0
  144. package/dist/storage-refs.js.map +1 -0
  145. package/dist/stores/file.cjs +1 -114
  146. package/dist/stores/file.cjs.map +1 -1
  147. package/dist/stores/file.js +1 -112
  148. package/dist/stores/file.js.map +1 -1
  149. package/dist/stores/index.cjs +1 -231
  150. package/dist/stores/index.cjs.map +1 -1
  151. package/dist/stores/index.js +1 -227
  152. package/dist/stores/index.js.map +1 -1
  153. package/dist/stores/localStorage.cjs +1 -76
  154. package/dist/stores/localStorage.cjs.map +1 -1
  155. package/dist/stores/localStorage.js +1 -74
  156. package/dist/stores/localStorage.js.map +1 -1
  157. package/dist/stores/memory.cjs +1 -47
  158. package/dist/stores/memory.cjs.map +1 -1
  159. package/dist/stores/memory.js +1 -45
  160. package/dist/stores/memory.js.map +1 -1
  161. package/dist/types-B1ZRa4aI.d.ts +147 -0
  162. package/dist/types-BxEFcVK9.d.cts +147 -0
  163. package/examples/browser/boards/portfolio-tracker/portfolio-t4.js +291 -0
  164. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.js +218 -0
  165. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.py +201 -0
  166. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-http-test.js +357 -0
  167. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-inference-adapter.js +25 -16
  168. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-public.js +552 -0
  169. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-server.js +300 -0
  170. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-server.py +617 -0
  171. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-sse-worker.js +48 -0
  172. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.py +366 -0
  173. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/.runtime-out +1 -0
  174. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/board-graph.json +32 -0
  175. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +70 -3
  176. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +16 -11
  177. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +9 -8
  178. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/poll-status-cli.js +49 -0
  179. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +2 -6
  180. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +4 -8
  181. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +3 -7
  182. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +9 -8
  183. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +12 -17
  184. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +2 -6
  185. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/_board_pycli.py +107 -0
  186. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/add-cards.py +51 -0
  187. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/init-board.py +45 -0
  188. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/poll-status.py +71 -0
  189. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/reset-board-dir.py +36 -0
  190. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-demo.flow.yaml +26 -0
  191. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-handlers.py +39 -0
  192. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker-pycli.flow.yaml +80 -0
  193. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +36 -187
  194. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +40 -34
  195. package/examples/cli/step-machine-cli/portfolio-tracker/run-inline-python-demo-pycli.py +43 -0
  196. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker-pycli.py +77 -0
  197. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  198. package/examples/cli/step-machine-demo/jsonata-init-board-cli.js +8 -13
  199. package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +33 -9
  200. package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +3 -1
  201. package/examples/cli/step-machine-demo/step2-double-cli.js +6 -12
  202. package/examples/cli/step-machine-demo/two-step-math.flow.yaml +66 -4
  203. package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +13 -5
  204. package/examples/example-board/agent-instructions.md +11 -5
  205. package/examples/example-board/cards/_index.json +47 -0
  206. package/examples/example-board/cards/card-market-prices.json +33 -9
  207. package/examples/example-board/cards/card-my-identity.json +30 -6
  208. package/examples/example-board/cards/card-portfolio-action.json +24 -6
  209. package/examples/example-board/cards/card-portfolio-intelligence.json +97 -0
  210. package/examples/example-board/cards/card-portfolio-risks.json +24 -6
  211. package/examples/example-board/cards/card-portfolio-value.json +38 -10
  212. package/examples/example-board/cards/card-portfolio.json +57 -13
  213. package/examples/example-board/cards/card-rebalance-impact.json +22 -6
  214. package/examples/example-board/cards/card-rebalance-sim.json +66 -15
  215. package/examples/example-board/demo-chat-handler.js +14 -4
  216. package/examples/example-board/demo-server-config.json +1 -0
  217. package/examples/example-board/demo-server.js +366 -68
  218. package/examples/example-board/demo-shell-localstorage.html +774 -0
  219. package/examples/example-board/demo-shell-with-server.html +20 -37
  220. package/examples/example-board/demo-shell.html +5 -4
  221. package/examples/example-board/demo-task-executor.js +273 -275
  222. package/examples/index.html +0 -14
  223. package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +0 -1
  224. package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  225. package/package.json +46 -8
  226. package/schema/live-cards.schema.json +418 -132
  227. package/step-machine-cli.js +43 -310
  228. package/board-livecards-server-runtime.js +0 -1574
  229. package/browser/board-livecards-runtime-client.js +0 -263
  230. package/dist/cli/board-live-cards-cli.cjs +0 -10650
  231. package/dist/cli/board-live-cards-cli.cjs.map +0 -1
  232. package/dist/cli/board-live-cards-cli.d.cts +0 -179
  233. package/dist/cli/board-live-cards-cli.d.ts +0 -179
  234. package/dist/cli/board-live-cards-cli.js +0 -10598
  235. package/dist/cli/board-live-cards-cli.js.map +0 -1
  236. package/dist/journal-9HEgs7dU.d.ts +0 -28
  237. package/dist/journal-B-JCfQnh.d.cts +0 -28
  238. package/dist/schedule-Cszq9LYY.d.ts +0 -21
  239. package/dist/schedule-qWNL0RQh.d.cts +0 -21
  240. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +0 -22
  241. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +0 -16
  242. package/examples/browser/boards/portfolio-tracker/cards/portfolio-risk-assessment.json +0 -28
  243. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +0 -15
  244. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +0 -15
  245. package/examples/browser/boards/portfolio-tracker/cards/rebalancing-strategy.json +0 -28
  246. package/examples/browser/boards/portfolio-tracker/fetch-prices.js +0 -43
  247. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +0 -96
  248. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +0 -7
  249. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +0 -351
  250. package/examples/cli/step-machine-demo/two-step-math-handlers.js +0 -32
  251. package/examples/cli/step-machine-demo/two-step-mixed-handlers.js +0 -24
  252. package/examples/example-board/demo-shell-browser.html +0 -674
@@ -2,11 +2,31 @@
2
2
 
3
3
  import * as fs from 'node:fs';
4
4
  import * as path from 'node:path';
5
- import { pathToFileURL } from 'node:url';
5
+ import { fileURLToPath } from 'node:url';
6
6
  import { spawnSync } from 'node:child_process';
7
- import jsonata from 'jsonata';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const srcCli = path.join(__dirname, 'src', 'cli', 'node', 'step-machine-cli.ts');
10
+ const tsxCli = path.join(__dirname, 'node_modules', 'tsx', 'dist', 'cli.mjs');
11
+
12
+ if (fs.existsSync(srcCli)) {
13
+ const result = spawnSync(process.execPath, [tsxCli, srcCli, ...process.argv.slice(2)], {
14
+ stdio: 'inherit',
15
+ shell: false,
16
+ windowsHide: true,
17
+ });
18
+
19
+ if (result.error) {
20
+ console.error(`[step-machine-cli] Failed to launch dev fallback: ${result.error.message}`);
21
+ process.exit(1);
22
+ }
23
+
24
+ process.exit(result.status ?? 0);
25
+ }
8
26
 
9
27
  const { loadStepFlow, createStepMachine, MemoryStore, FileStore } = await import('./dist/index.js');
28
+ const { buildStepHandlersForFlow } = await import('./dist/step-machine-public/index.js');
29
+ const { invokeRefSync } = await import('./dist/cli/node/execution-adapter.js');
10
30
  const PAUSE_FILE_NAME = '.pause';
11
31
 
12
32
  async function main() {
@@ -20,7 +40,6 @@ async function main() {
20
40
 
21
41
  const {
22
42
  flowArg,
23
- handlersArg,
24
43
  dataArg,
25
44
  storeArg,
26
45
  storeDirArg,
@@ -29,8 +48,8 @@ async function main() {
29
48
  statusRequested,
30
49
  } = parsed;
31
50
 
32
- if ((pauseRequested || statusRequested) && (handlersArg || dataArg || resumeRequested || flowArg)) {
33
- throw new Error('[step-machine-cli] --pause and --status are store-level operations. Do not provide flow, handlers, data, or --resume.');
51
+ if ((pauseRequested || statusRequested) && (dataArg || resumeRequested || flowArg)) {
52
+ throw new Error('[step-machine-cli] --pause and --status are store-level operations. Do not provide flow, data, or --resume.');
34
53
  }
35
54
 
36
55
  if (resumeRequested && dataArg) {
@@ -55,13 +74,11 @@ async function main() {
55
74
 
56
75
  const flowPath = resolveInputPath(flowArg);
57
76
  const flowDir = path.dirname(flowPath);
58
- const handlersPath = handlersArg ? resolveInputPath(handlersArg) : undefined;
59
77
  const initialData = parseInitialData(dataArg);
60
78
  const { store } = storeContext;
61
79
 
62
80
  const flow = await loadStepFlow(flowPath);
63
- const inlineHandlers = handlersPath ? await loadHandlers(handlersPath) : {};
64
- const handlers = buildStepHandlers(flow, inlineHandlers, flowDir, flow.handler_vars);
81
+ const handlers = buildStepHandlers(flow, flowDir);
65
82
 
66
83
  // Resume/start should ignore stale pause markers from previous runs.
67
84
  clearPauseRequest(storeContext);
@@ -127,7 +144,7 @@ async function main() {
127
144
  }
128
145
 
129
146
  function parseCliArgs(args) {
130
- const valueFlags = new Set(['--handlers', '--initial-data', '--store', '--store-dir']);
147
+ const valueFlags = new Set(['--initial-data', '--store', '--store-dir']);
131
148
  const values = {};
132
149
  const positionals = [];
133
150
  let help = false;
@@ -181,7 +198,6 @@ function parseCliArgs(args) {
181
198
  return {
182
199
  help,
183
200
  flowArg: positionals[0],
184
- handlersArg: values['--handlers'],
185
201
  dataArg: values['--initial-data'],
186
202
  storeArg: String(values['--store'] ?? 'memory').toLowerCase(),
187
203
  storeDirArg: values['--store-dir'],
@@ -348,319 +364,36 @@ function parseInitialData(dataArg) {
348
364
  }
349
365
  }
350
366
 
351
- async function loadHandlers(handlersPath) {
352
- const mod = await import(pathToFileURL(handlersPath).href);
353
- const candidate = mod.default ?? mod.handlers ?? mod;
354
-
355
- if (!candidate || typeof candidate !== 'object') {
356
- throw new Error('[step-machine-cli] Handlers module must export an object map of stepName -> function.');
357
- }
358
-
359
- for (const [stepName, handler] of Object.entries(candidate)) {
360
- if (typeof handler !== 'function') {
361
- throw new Error(`[step-machine-cli] Handler for step "${stepName}" is not a function.`);
362
- }
363
- }
364
-
365
- return candidate;
366
- }
367
-
368
- function buildStepHandlers(flow, inlineHandlers, flowDir, handlerVars) {
369
- const handlers = {};
370
-
371
- for (const [stepName, stepConfig] of Object.entries(flow.steps ?? {})) {
372
- handlers[stepName] = resolveStepHandler(stepName, stepConfig, inlineHandlers, flowDir, handlerVars);
373
- }
374
-
375
- return handlers;
376
- }
377
-
378
- function resolveStepHandler(stepName, stepConfig, inlineHandlers, flowDir, handlerVars) {
379
- const produces = Array.isArray(stepConfig?.produces_data) ? stepConfig.produces_data : undefined;
380
- const spec = stepConfig?.handler;
381
-
382
- if (isCliSpec(spec)) {
383
- const base = createCliStepHandler(spec, flowDir, stepName, handlerVars);
384
- return wrapWithOutputFiltering(base, produces);
385
- }
386
-
387
- if (isInlineSpec(spec)) {
388
- const inlineName = spec.inline;
389
- const handler = inlineHandlers[inlineName];
390
- if (typeof handler !== 'function') {
391
- throw new Error(`[step-machine-cli] Inline handler "${inlineName}" for step "${stepName}" was not found in --handlers module.`);
392
- }
393
- return wrapWithOutputFiltering(handler, produces);
394
- }
395
-
396
- // Default behavior is explicit and predictable: no configured handler means passthrough.
397
- return wrapWithOutputFiltering(createPassthroughHandler(), produces);
398
- }
399
-
400
- function isCliSpec(spec) {
401
- return !!spec && typeof spec === 'object' && typeof spec.cli === 'string' && spec.cli.trim().length > 0;
402
- }
403
-
404
- function isInlineSpec(spec) {
405
- return !!spec && typeof spec === 'object' && typeof spec.inline === 'string' && spec.inline.trim().length > 0;
406
- }
407
-
408
- function createCliStepHandler(spec, flowDir, stepName, handlerVars) {
409
- return async (input) => {
410
- const stepInput = input && typeof input === 'object' && !Array.isArray(input)
411
- ? input
412
- : {};
413
-
414
- const resolvedHandlerVars = await evaluateTransforms(
415
- handlerVars,
416
- stepInput,
417
- stepName,
418
- 'handler_vars',
419
- );
420
-
421
- const inputTransforms = await evaluateTransforms(
422
- spec['input-transforms'],
423
- { ...stepInput, ...resolvedHandlerVars },
424
- stepName,
425
- 'input-transforms',
426
- );
427
-
428
- const effectiveInput = { ...stepInput, ...resolvedHandlerVars, ...inputTransforms };
429
- const command = applyCommandTemplate(spec.cli, effectiveInput, stepName);
430
-
431
- const payload = JSON.stringify(effectiveInput);
432
- const result = spawnSync(command, {
433
- cwd: flowDir,
434
- shell: true,
435
- input: payload,
436
- encoding: 'utf-8',
437
- windowsHide: true,
438
- });
439
-
440
- if (result.error) {
441
- return {
442
- result: 'failure',
443
- data: { error: `[step-machine-cli] step "${stepName}" failed to start: ${result.error.message}` },
444
- };
445
- }
446
-
447
- const stdout = result.stdout ?? '';
448
- const stderr = (result.stderr ?? '').trim();
449
- const resultMode = String(spec['result-mode'] ?? 'json').toLowerCase();
450
-
451
- if (result.status !== 0) {
452
- return {
453
- result: 'failure',
454
- data: {
455
- error: `[step-machine-cli] step "${stepName}" exited with status ${result.status}${stderr ? `: ${stderr}` : ''}`,
456
- },
457
- };
458
- }
459
-
460
- if (resultMode === 'exit-code') {
461
- const outputTransforms = await evaluateTransforms(
462
- spec['output-transforms'],
463
- {
464
- ...effectiveInput,
465
- result: 'success',
466
- stdout,
467
- stderr,
468
- },
469
- stepName,
470
- 'output-transforms',
471
- );
472
-
473
- return {
474
- result: 'success',
475
- data: outputTransforms,
476
- };
477
- }
478
-
479
- try {
480
- const parsed = parseJsonOutput(stdout);
481
- const normalized = normalizeHandlerResult(parsed, stepName);
482
- const outputTransforms = await evaluateTransforms(
483
- spec['output-transforms'],
484
- {
485
- ...effectiveInput,
486
- result: normalized.result,
487
- data: normalized.data,
488
- },
489
- stepName,
490
- 'output-transforms',
491
- );
492
-
493
- if (Object.keys(outputTransforms).length === 0) {
494
- return normalized;
495
- }
496
-
497
- return {
498
- result: normalized.result,
499
- data: outputTransforms,
500
- };
501
- } catch (error) {
502
- const msg = error instanceof Error ? error.message : String(error);
503
- return {
504
- result: 'failure',
505
- data: {
506
- error: `[step-machine-cli] step "${stepName}" returned invalid JSON on stdout: ${msg}`,
507
- },
508
- };
509
- }
510
- };
511
- }
512
-
513
- async function evaluateTransforms(transformSpec, source, stepName, label) {
514
- if (transformSpec === undefined || transformSpec === null) {
515
- return {};
516
- }
517
-
518
- if (!transformSpec || typeof transformSpec !== 'object' || Array.isArray(transformSpec)) {
519
- throw new Error(`[step-machine-cli] Step "${stepName}" ${label} must be an object map of key -> JSONata expression.`);
520
- }
521
-
522
- const result = {};
523
- for (const [key, expression] of Object.entries(transformSpec)) {
524
- if (typeof expression !== 'string') {
525
- // Non-string values are treated as literals for convenience.
526
- result[key] = expression;
527
- continue;
528
- }
529
-
530
- if (expression.trim().length === 0) {
531
- throw new Error(`[step-machine-cli] Step "${stepName}" ${label}.${key} must be a non-empty string expression.`);
532
- }
533
-
534
- // handler_vars defaults to literal strings for ergonomics; use "=..." for JSONata expressions.
535
- if (label === 'handler_vars' && !expression.startsWith('=')) {
536
- result[key] = expression;
537
- continue;
538
- }
539
-
540
- const jsonataExpression = label === 'handler_vars' && expression.startsWith('=')
541
- ? expression.slice(1)
542
- : expression;
543
-
544
- // Convenience: direct key aliasing supports non-identifier keys like BOARD-DIR-NAME.
545
- if (Object.prototype.hasOwnProperty.call(source, jsonataExpression)) {
546
- result[key] = source[jsonataExpression];
547
- continue;
548
- }
549
-
550
- try {
551
- const compiled = jsonata(jsonataExpression);
552
- result[key] = await compiled.evaluate(source);
553
- } catch (error) {
554
- const msg = error instanceof Error ? error.message : String(error);
555
- throw new Error(`[step-machine-cli] Step "${stepName}" ${label}.${key} failed: ${msg}`);
556
- }
557
- }
558
-
559
- return result;
560
- }
561
-
562
- function applyCommandTemplate(command, source, stepName) {
563
- if (typeof command !== 'string' || command.trim().length === 0) {
564
- throw new Error(`[step-machine-cli] Step "${stepName}" handler.cli must be a non-empty command string.`);
565
- }
566
-
567
- return command.replace(/%%([A-Za-z0-9_-]+)%%/g, (full, key) => {
568
- if (!Object.prototype.hasOwnProperty.call(source, key)) {
569
- throw new Error(`[step-machine-cli] Step "${stepName}" command placeholder ${full} has no matching input or input-transform value.`);
570
- }
571
-
572
- const value = source[key];
573
- if (value === undefined || value === null) {
574
- throw new Error(`[step-machine-cli] Step "${stepName}" command placeholder ${full} resolved to empty value.`);
575
- }
576
-
577
- return String(value);
578
- });
579
- }
580
-
581
- function createPassthroughHandler() {
582
- return async (input) => {
583
- const data = input && typeof input === 'object' && !Array.isArray(input)
584
- ? input
585
- : {};
586
-
587
- return {
588
- result: 'success',
589
- data,
590
- };
591
- };
592
- }
593
-
594
- function parseJsonOutput(stdout) {
595
- const trimmed = stdout.trim();
596
- if (!trimmed) {
597
- throw new Error('empty stdout');
598
- }
367
+ function normalizeExecutionRef(ref) {
368
+ if (!ref || typeof ref !== 'object') return ref;
369
+ if (typeof ref.whatToRun !== 'string' || !ref.whatToRun.startsWith('b64:')) return ref;
599
370
 
600
371
  try {
601
- return JSON.parse(trimmed);
372
+ const payload = ref.whatToRun.slice(4);
373
+ const padded = payload + '='.repeat((4 - (payload.length % 4)) % 4);
374
+ const json = Buffer.from(padded.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8');
375
+ const decoded = JSON.parse(json);
376
+ if (!decoded || typeof decoded !== 'object' || typeof decoded.value !== 'string') {
377
+ return ref;
378
+ }
379
+ return { ...ref, whatToRun: decoded.value };
602
380
  } catch {
603
- const lines = trimmed.split(/\r?\n/).filter(Boolean);
604
- const last = lines[lines.length - 1];
605
- return JSON.parse(last);
381
+ return ref;
606
382
  }
607
383
  }
608
384
 
609
- function wrapWithOutputFiltering(handler, produces) {
610
- return async (input, context) => {
611
- const raw = await handler(input, context);
612
- const normalized = normalizeHandlerResult(raw, context?.stepName ?? 'unknown');
613
- const filteredData = filterProducedData(normalized.data, produces);
614
- return {
615
- result: normalized.result,
616
- data: filteredData,
617
- };
618
- };
619
- }
620
-
621
- function normalizeHandlerResult(raw, stepName) {
622
- if (!raw || typeof raw !== 'object') {
623
- throw new Error(`[step-machine-cli] Step "${stepName}" returned a non-object result.`);
624
- }
625
-
626
- const result = raw.result ?? raw.status;
627
- if (typeof result !== 'string' || result.trim().length === 0) {
628
- throw new Error(`[step-machine-cli] Step "${stepName}" result must include a non-empty "result" (or "status") string.`);
629
- }
630
-
631
- const data = raw.data && typeof raw.data === 'object' && !Array.isArray(raw.data)
632
- ? raw.data
633
- : {};
634
-
635
- const error = typeof raw.error === 'string' ? raw.error : undefined;
636
- if (error && !('error' in data)) {
637
- data.error = error;
638
- }
639
-
640
- return { result, data };
641
- }
642
-
643
- function filterProducedData(data, produces) {
644
- if (!produces || produces.length === 0) {
645
- return data;
646
- }
647
-
648
- const filtered = {};
649
- for (const key of produces) {
650
- if (Object.prototype.hasOwnProperty.call(data, key)) {
651
- filtered[key] = data[key];
652
- }
653
- }
654
- return filtered;
385
+ function buildStepHandlers(flow, flowDir) {
386
+ const invoke = (ref, args) => invokeRefSync(normalizeExecutionRef(ref), args, { cliDir: flowDir, cwd: flowDir });
387
+ return buildStepHandlersForFlow(flow, { invoke });
655
388
  }
656
389
 
657
390
  function printUsage() {
658
- console.error('Usage: step-machine-cli <step-flow.yaml> [--handlers <step-handlers.js>] [--initial-data <json>] [--store <memory|file>] [--store-dir <directory>] [--resume]');
391
+ console.error('Usage: step-machine-cli <step-flow.yaml> [--initial-data <json>] [--store <memory|file>] [--store-dir <directory>] [--resume]');
659
392
  console.error(' step-machine-cli --store file --store-dir <directory> --pause');
660
393
  console.error(' step-machine-cli --store file --store-dir <directory> --status');
661
394
  console.error('');
662
395
  console.error('Example:');
663
- console.error(' step-machine-cli examples/step-machine-demo/two-step-mixed.flow.yaml --handlers examples/step-machine-demo/two-step-mixed-handlers.js --initial-data "{\"a\":3,\"b\":4}"');
396
+ console.error(' step-machine-cli examples/cli/step-machine-demo/two-step-math.flow.yaml --initial-data "{\"a\":3,\"b\":4}"');
664
397
  console.error(' step-machine-cli ./flow.yaml --store file --store-dir ./.runs');
665
398
  console.error(' step-machine-cli ./flow.yaml --store file --store-dir ./.runs --resume');
666
399
  console.error(' step-machine-cli --store file --store-dir ./.runs --pause');