yaml-flow 3.1.1 → 5.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 (194) hide show
  1. package/README.md +81 -20
  2. package/board-live-cards-cli.js +37 -0
  3. package/browser/board-livegraph-runtime.js +1453 -0
  4. package/browser/board-livegraph-runtime.js.map +1 -0
  5. package/browser/card-compute.js +153 -433
  6. package/browser/live-cards.js +868 -115
  7. package/browser/live-cards.schema.json +90 -83
  8. package/dist/board-livegraph-runtime/index.cjs +1448 -0
  9. package/dist/board-livegraph-runtime/index.cjs.map +1 -0
  10. package/dist/board-livegraph-runtime/index.d.cts +101 -0
  11. package/dist/board-livegraph-runtime/index.d.ts +101 -0
  12. package/dist/board-livegraph-runtime/index.js +1441 -0
  13. package/dist/board-livegraph-runtime/index.js.map +1 -0
  14. package/dist/card-compute/index.cjs +266 -431
  15. package/dist/card-compute/index.cjs.map +1 -1
  16. package/dist/card-compute/index.d.cts +77 -49
  17. package/dist/card-compute/index.d.ts +77 -49
  18. package/dist/card-compute/index.js +263 -432
  19. package/dist/card-compute/index.js.map +1 -1
  20. package/dist/cli/board-live-cards-cli.cjs +2750 -0
  21. package/dist/cli/board-live-cards-cli.cjs.map +1 -0
  22. package/dist/cli/board-live-cards-cli.d.cts +205 -0
  23. package/dist/cli/board-live-cards-cli.d.ts +205 -0
  24. package/dist/cli/board-live-cards-cli.js +2702 -0
  25. package/dist/cli/board-live-cards-cli.js.map +1 -0
  26. package/dist/{constants-B2zqu10b.d.ts → constants-DuzE5n03.d.ts} +2 -2
  27. package/dist/{constants-DJZU1pwJ.d.cts → constants-ozjf1Ejw.d.cts} +2 -2
  28. package/dist/continuous-event-graph/index.cjs +258 -464
  29. package/dist/continuous-event-graph/index.cjs.map +1 -1
  30. package/dist/continuous-event-graph/index.d.cts +18 -358
  31. package/dist/continuous-event-graph/index.d.ts +18 -358
  32. package/dist/continuous-event-graph/index.js +255 -464
  33. package/dist/continuous-event-graph/index.js.map +1 -1
  34. package/dist/event-graph/index.cjs +4 -4
  35. package/dist/event-graph/index.cjs.map +1 -1
  36. package/dist/event-graph/index.d.cts +5 -5
  37. package/dist/event-graph/index.d.ts +5 -5
  38. package/dist/event-graph/index.js +4 -4
  39. package/dist/event-graph/index.js.map +1 -1
  40. package/dist/index.cjs +1684 -555
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +26 -7
  43. package/dist/index.d.ts +26 -7
  44. package/dist/index.js +1678 -555
  45. package/dist/index.js.map +1 -1
  46. package/dist/inference/index.cjs +138 -19
  47. package/dist/inference/index.cjs.map +1 -1
  48. package/dist/inference/index.d.cts +2 -2
  49. package/dist/inference/index.d.ts +2 -2
  50. package/dist/inference/index.js +138 -19
  51. package/dist/inference/index.js.map +1 -1
  52. package/dist/journal-DRfJiheM.d.cts +28 -0
  53. package/dist/journal-NLYuqege.d.ts +28 -0
  54. package/dist/live-cards-bridge-Or7fdEJV.d.ts +316 -0
  55. package/dist/live-cards-bridge-vGJ6tMzN.d.cts +316 -0
  56. package/dist/schedule-CMcZe5Ny.d.ts +21 -0
  57. package/dist/schedule-CiucyCan.d.cts +21 -0
  58. package/dist/step-machine/index.cjs +18 -1
  59. package/dist/step-machine/index.cjs.map +1 -1
  60. package/dist/step-machine/index.d.cts +2 -2
  61. package/dist/step-machine/index.d.ts +2 -2
  62. package/dist/step-machine/index.js +18 -1
  63. package/dist/step-machine/index.js.map +1 -1
  64. package/dist/stores/file.d.cts +1 -1
  65. package/dist/stores/file.d.ts +1 -1
  66. package/dist/stores/index.d.cts +1 -1
  67. package/dist/stores/index.d.ts +1 -1
  68. package/dist/stores/localStorage.d.cts +1 -1
  69. package/dist/stores/localStorage.d.ts +1 -1
  70. package/dist/stores/memory.d.cts +1 -1
  71. package/dist/stores/memory.d.ts +1 -1
  72. package/dist/{types-BwvgvlOO.d.cts → types-BzLD8bjb.d.cts} +1 -1
  73. package/dist/{types-ClRA8hzC.d.ts → types-C2eJ7DAV.d.ts} +1 -1
  74. package/dist/{types-DEj7OakX.d.cts → types-CMFSIjpc.d.cts} +39 -4
  75. package/dist/{types-DEj7OakX.d.ts → types-CMFSIjpc.d.ts} +39 -4
  76. package/dist/{types-FZ_eyErS.d.cts → types-ycun84cq.d.cts} +1 -0
  77. package/dist/{types-FZ_eyErS.d.ts → types-ycun84cq.d.ts} +1 -0
  78. package/dist/{validate-DEZ2Ymdb.d.ts → validate-DJQTQ6bP.d.ts} +1 -1
  79. package/dist/{validate-DqKTZg_o.d.cts → validate-ke92Cleg.d.cts} +1 -1
  80. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +22 -0
  81. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +16 -0
  82. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +15 -0
  83. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +15 -0
  84. package/examples/browser/boards/portfolio-tracker/fetch-prices.js +43 -0
  85. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
  86. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +7 -0
  87. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +217 -0
  88. package/examples/browser/livecards-browser/index.html +41 -0
  89. package/examples/browser/{index.html → step-machine-browser/index.html} +53 -53
  90. package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
  91. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
  92. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
  93. package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
  94. package/examples/cli/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
  95. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
  96. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
  97. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
  98. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
  99. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
  100. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
  101. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
  102. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
  103. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
  104. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
  105. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
  106. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
  107. package/examples/cli/step-machine-demo/jsonata-init-board-cli.js +36 -0
  108. package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +30 -0
  109. package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +19 -0
  110. package/examples/cli/step-machine-demo/step-cli-echo-y.js +15 -0
  111. package/examples/cli/step-machine-demo/step2-double-cli.js +39 -0
  112. package/examples/cli/step-machine-demo/two-step-math-handlers.js +32 -0
  113. package/examples/cli/step-machine-demo/two-step-math.flow.yaml +31 -0
  114. package/examples/cli/step-machine-demo/two-step-mixed-handlers.js +24 -0
  115. package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +35 -0
  116. package/examples/example-board/board.yaml +23 -0
  117. package/examples/example-board/bootstrap_payload.json +1 -0
  118. package/examples/example-board/cards/card-chain-region-alert.json +39 -0
  119. package/examples/example-board/cards/card-chain-region-totals.json +26 -0
  120. package/examples/example-board/cards/card-chain-top-region.json +24 -0
  121. package/examples/example-board/cards/card-ex-actions.json +32 -0
  122. package/examples/example-board/cards/card-ex-chart.json +30 -0
  123. package/examples/example-board/cards/card-ex-filter.json +36 -0
  124. package/examples/example-board/cards/card-ex-filtered-by-preference.json +59 -0
  125. package/examples/example-board/cards/card-ex-form.json +91 -0
  126. package/examples/example-board/cards/card-ex-list.json +22 -0
  127. package/examples/example-board/cards/card-ex-markdown.json +17 -0
  128. package/examples/example-board/cards/card-ex-metric.json +19 -0
  129. package/examples/example-board/cards/card-ex-narrative.json +36 -0
  130. package/examples/example-board/cards/card-ex-source-http.json +28 -0
  131. package/examples/example-board/cards/card-ex-source.json +21 -0
  132. package/examples/example-board/cards/card-ex-status.json +35 -0
  133. package/examples/example-board/cards/card-ex-table.json +30 -0
  134. package/examples/example-board/cards/card-ex-todo.json +29 -0
  135. package/examples/example-board/demo-chat-handler.js +69 -0
  136. package/examples/example-board/demo-server.js +87 -0
  137. package/examples/example-board/demo-shell-browser.html +806 -0
  138. package/examples/example-board/demo-shell-with-server.html +280 -0
  139. package/examples/example-board/demo-shell.html +62 -0
  140. package/examples/example-board/demo-task-executor.js +255 -0
  141. package/examples/example-board/mock.db +15 -0
  142. package/examples/example-board/reusable-board-runtime-client.js +265 -0
  143. package/examples/example-board/reusable-runtime-artifacts-adapter.js +233 -0
  144. package/examples/example-board/reusable-server-runtime.js +1284 -0
  145. package/examples/index.html +799 -0
  146. package/examples/{batch → npm-libs/batch}/batch-step-machine.ts +1 -1
  147. package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/live-cards-board.ts +18 -18
  148. package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/live-portfolio-dashboard.ts +24 -24
  149. package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/portfolio-tracker.ts +1 -1
  150. package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/reactive-monitoring.ts +1 -1
  151. package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/reactive-pipeline.ts +1 -1
  152. package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/soc-incident-board.ts +1 -1
  153. package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/stock-dashboard.ts +1 -1
  154. package/examples/{event-graph → npm-libs/event-graph}/ci-cd-pipeline.ts +1 -1
  155. package/examples/{event-graph → npm-libs/event-graph}/executor-diamond.ts +1 -1
  156. package/examples/{event-graph → npm-libs/event-graph}/executor-pipeline.ts +1 -1
  157. package/examples/{event-graph → npm-libs/event-graph}/research-pipeline.ts +1 -1
  158. package/examples/{graph-of-graphs → npm-libs/graph-of-graphs}/multi-stage-etl.ts +1 -1
  159. package/examples/{graph-of-graphs → npm-libs/graph-of-graphs}/url-processing-pipeline.ts +1 -1
  160. package/examples/{inference → npm-libs/inference}/azure-deployment.ts +1 -1
  161. package/examples/{inference → npm-libs/inference}/copilot-cli.ts +1 -1
  162. package/examples/{inference → npm-libs/inference}/data-pipeline.ts +1 -1
  163. package/examples/{inference → npm-libs/inference}/pluggable-adapters.ts +1 -1
  164. package/examples/{node → npm-libs/node}/ai-conversation.ts +1 -1
  165. package/examples/{node → npm-libs/node}/simple-greeting.ts +2 -2
  166. package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
  167. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
  168. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
  169. package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
  170. package/examples/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
  171. package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
  172. package/examples/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
  173. package/examples/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
  174. package/examples/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
  175. package/examples/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
  176. package/examples/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
  177. package/examples/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
  178. package/examples/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
  179. package/examples/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
  180. package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
  181. package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
  182. package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
  183. package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
  184. package/package.json +27 -2
  185. package/schema/board-status.schema.json +118 -0
  186. package/schema/card-runtime.schema.json +25 -0
  187. package/schema/flow.schema.json +5 -0
  188. package/schema/live-cards.schema.json +90 -83
  189. package/step-machine-cli.js +674 -0
  190. package/browser/ingest-board.js +0 -296
  191. package/examples/ingest.js +0 -733
  192. /package/examples/{flows → npm-libs/flows}/ai-conversation.yaml +0 -0
  193. /package/examples/{flows → npm-libs/flows}/order-processing.yaml +0 -0
  194. /package/examples/{flows → npm-libs/flows}/simple-greeting.yaml +0 -0
@@ -1,6 +1,5 @@
1
- import { existsSync, writeFileSync, appendFileSync, readFileSync } from 'fs';
2
- import { createHash } from 'crypto';
3
1
  import { exec } from 'child_process';
2
+ import jsonata2 from 'jsonata';
4
3
  import 'ajv-formats';
5
4
 
6
5
  // src/event-graph/constants.ts
@@ -245,43 +244,51 @@ function applyEvent(live, event) {
245
244
  if ("executionId" in event && event.executionId && event.executionId !== state.executionId) {
246
245
  return live;
247
246
  }
248
- let newState;
249
247
  switch (event.type) {
248
+ // --- Execution state transitions ---
250
249
  case "task-started":
251
- newState = applyTaskStart(state, event.taskName);
252
- break;
250
+ return { config, state: applyTaskStart(state, event.taskName) };
253
251
  case "task-completed":
254
- newState = applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash, event.data);
255
- break;
252
+ return { config, state: applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash, event.data) };
256
253
  case "task-failed":
257
- newState = applyTaskFailure(state, config, event.taskName, event.error);
258
- break;
254
+ return { config, state: applyTaskFailure(state, config, event.taskName, event.error) };
259
255
  case "task-progress":
260
- newState = applyTaskProgress(state, event.taskName, event.message, event.progress);
261
- break;
256
+ return { config, state: applyTaskProgress(state, event.taskName, event.message, event.progress) };
262
257
  case "task-restart":
263
- newState = applyTaskRestart(state, event.taskName);
264
- break;
258
+ return { config, state: applyTaskRestart(state, event.taskName) };
265
259
  case "inject-tokens":
266
- newState = {
267
- ...state,
268
- availableOutputs: [.../* @__PURE__ */ new Set([...state.availableOutputs, ...event.tokens])],
269
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
260
+ return {
261
+ config,
262
+ state: {
263
+ ...state,
264
+ availableOutputs: [.../* @__PURE__ */ new Set([...state.availableOutputs, ...event.tokens])],
265
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
266
+ }
270
267
  };
271
- break;
272
268
  case "agent-action":
273
- newState = applyAgentAction(state, event.action);
274
- break;
269
+ return { config, state: applyAgentAction(state, event.action) };
270
+ // --- Structural mutations ---
271
+ case "task-upsert":
272
+ return addNode(live, event.taskName, event.taskConfig);
273
+ case "task-removal":
274
+ return removeNode(live, event.taskName);
275
+ case "node-requires-add":
276
+ return addRequires(live, event.nodeName, event.tokens);
277
+ case "node-requires-remove":
278
+ return removeRequires(live, event.nodeName, event.tokens);
279
+ case "node-provides-add":
280
+ return addProvides(live, event.nodeName, event.tokens);
281
+ case "node-provides-remove":
282
+ return removeProvides(live, event.nodeName, event.tokens);
275
283
  default:
276
284
  return live;
277
285
  }
278
- return { config, state: newState };
279
286
  }
280
287
  function applyEvents(live, events) {
281
288
  return events.reduce((current, event) => applyEvent(current, event), live);
282
289
  }
283
290
  function addNode(live, name, taskConfig) {
284
- if (live.config.tasks[name]) return live;
291
+ const exists = !!live.config.tasks[name];
285
292
  return {
286
293
  config: {
287
294
  ...live.config,
@@ -289,7 +296,10 @@ function addNode(live, name, taskConfig) {
289
296
  },
290
297
  state: {
291
298
  ...live.state,
292
- tasks: { ...live.state.tasks, [name]: createDefaultGraphEngineStore2() },
299
+ tasks: {
300
+ ...live.state.tasks,
301
+ [name]: exists ? live.state.tasks[name] : createDefaultGraphEngineStore2()
302
+ },
293
303
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
294
304
  }
295
305
  };
@@ -996,6 +1006,8 @@ function getDownstream(live, nodeName) {
996
1006
  }));
997
1007
  return { nodeName, nodes, tokens: [...tokenSet] };
998
1008
  }
1009
+
1010
+ // src/continuous-event-graph/journal.ts
999
1011
  var MemoryJournal = class {
1000
1012
  buffer = [];
1001
1013
  append(event) {
@@ -1010,39 +1022,11 @@ var MemoryJournal = class {
1010
1022
  return this.buffer.length;
1011
1023
  }
1012
1024
  };
1013
- var FileJournal = class {
1014
- constructor(path) {
1015
- this.path = path;
1016
- if (!existsSync(path)) {
1017
- writeFileSync(path, "", "utf-8");
1018
- }
1019
- }
1020
- path;
1021
- pending = 0;
1022
- append(event) {
1023
- appendFileSync(this.path, JSON.stringify(event) + "\n", "utf-8");
1024
- this.pending++;
1025
- }
1026
- drain() {
1027
- const content = readFileSync(this.path, "utf-8").trim();
1028
- writeFileSync(this.path, "", "utf-8");
1029
- this.pending = 0;
1030
- if (!content) return [];
1031
- return content.split("\n").map((line) => JSON.parse(line));
1032
- }
1033
- get size() {
1034
- try {
1035
- const content = readFileSync(this.path, "utf-8").trim();
1036
- if (!content) return 0;
1037
- return content.split("\n").length;
1038
- } catch {
1039
- return this.pending;
1040
- }
1041
- }
1042
- };
1025
+
1026
+ // src/continuous-event-graph/reactive.ts
1043
1027
  function computeDataHash(data) {
1044
1028
  const json = stableStringify(data);
1045
- return createHash("sha256").update(json).digest("hex").slice(0, 16);
1029
+ return fnv1a64Hex(json);
1046
1030
  }
1047
1031
  function stableStringify(value) {
1048
1032
  if (value === null || value === void 0 || typeof value !== "object") {
@@ -1055,28 +1039,65 @@ function stableStringify(value) {
1055
1039
  const keys = Object.keys(obj).sort();
1056
1040
  return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
1057
1041
  }
1042
+ function fnv1a64Hex(input) {
1043
+ let hash = 0xcbf29ce484222325n;
1044
+ const prime = 0x100000001b3n;
1045
+ const mod = 0xffffffffffffffffn;
1046
+ for (let i = 0; i < input.length; i++) {
1047
+ hash ^= BigInt(input.charCodeAt(i));
1048
+ hash = hash * prime & mod;
1049
+ }
1050
+ return hash.toString(16).padStart(16, "0");
1051
+ }
1052
+ function base64UrlEncode(input) {
1053
+ if (typeof Buffer !== "undefined") {
1054
+ return Buffer.from(input, "utf8").toString("base64url");
1055
+ }
1056
+ if (typeof btoa === "function") {
1057
+ const bytes = new TextEncoder().encode(input);
1058
+ let binary = "";
1059
+ for (const b of bytes) binary += String.fromCharCode(b);
1060
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
1061
+ }
1062
+ throw new Error("No base64 encoder available in this runtime");
1063
+ }
1064
+ function base64UrlDecode(input) {
1065
+ if (typeof Buffer !== "undefined") {
1066
+ return Buffer.from(input, "base64url").toString("utf8");
1067
+ }
1068
+ if (typeof atob === "function") {
1069
+ const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
1070
+ const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
1071
+ const binary = atob(padded);
1072
+ const bytes = new Uint8Array(binary.length);
1073
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
1074
+ return new TextDecoder().decode(bytes);
1075
+ }
1076
+ throw new Error("No base64 decoder available in this runtime");
1077
+ }
1058
1078
  function encodeCallbackToken(taskName) {
1059
1079
  const payload = JSON.stringify({ t: taskName, n: Date.now().toString(36) + Math.random().toString(36).slice(2, 6) });
1060
- return Buffer.from(payload).toString("base64url");
1080
+ return base64UrlEncode(payload);
1061
1081
  }
1062
1082
  function decodeCallbackToken(token) {
1063
1083
  try {
1064
- const payload = JSON.parse(Buffer.from(token, "base64url").toString());
1084
+ const payload = JSON.parse(base64UrlDecode(token));
1065
1085
  if (typeof payload?.t === "string") return { taskName: payload.t };
1066
1086
  return null;
1067
1087
  } catch {
1068
1088
  return null;
1069
1089
  }
1070
1090
  }
1071
- function createReactiveGraph(config, options, executionId) {
1091
+ function createReactiveGraph(configOrLive, options, executionId) {
1072
1092
  const {
1073
1093
  handlers: initialHandlers,
1074
- journal = new MemoryJournal(),
1075
1094
  onDrain
1076
1095
  } = options;
1077
- let live = createLiveGraph(config, executionId);
1096
+ const inputQueue = new MemoryJournal();
1097
+ let live = "state" in configOrLive && "config" in configOrLive ? configOrLive : createLiveGraph(configOrLive, executionId);
1078
1098
  let disposed = false;
1079
1099
  const handlers = new Map(Object.entries(initialHandlers));
1100
+ const internalJournal = new MemoryJournal();
1080
1101
  let draining = false;
1081
1102
  let drainQueued = false;
1082
1103
  function drain() {
@@ -1096,7 +1117,9 @@ function createReactiveGraph(config, options, executionId) {
1096
1117
  }
1097
1118
  }
1098
1119
  function drainOnce() {
1099
- const events = journal.drain();
1120
+ const internalEvents = internalJournal.drain();
1121
+ const inputEvents = inputQueue.drain();
1122
+ const events = [...internalEvents, ...inputEvents];
1100
1123
  if (events.length > 0) {
1101
1124
  live = applyEvents(live, events);
1102
1125
  }
@@ -1107,6 +1130,26 @@ function createReactiveGraph(config, options, executionId) {
1107
1130
  for (const taskName of result.eligible) {
1108
1131
  dispatchTask(taskName);
1109
1132
  }
1133
+ for (const event of events) {
1134
+ if (event.type === "task-progress") {
1135
+ const { taskName, update } = event;
1136
+ const taskConfig = live.config.tasks[taskName];
1137
+ if (!taskConfig) continue;
1138
+ const taskState = live.state.tasks[taskName];
1139
+ if (!taskState || taskState.status !== "running") continue;
1140
+ const callbackToken = encodeCallbackToken(taskName);
1141
+ runPipeline(taskName, callbackToken, update).catch((error) => {
1142
+ if (disposed) return;
1143
+ internalJournal.append({
1144
+ type: "task-failed",
1145
+ taskName,
1146
+ error: error.message ?? String(error),
1147
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1148
+ });
1149
+ drain();
1150
+ });
1151
+ }
1152
+ }
1110
1153
  }
1111
1154
  function resolveUpstreamState(taskName) {
1112
1155
  const taskConfig = live.config.tasks[taskName];
@@ -1128,7 +1171,7 @@ function createReactiveGraph(config, options, executionId) {
1128
1171
  }
1129
1172
  return state;
1130
1173
  }
1131
- async function runPipeline(taskName, callbackToken) {
1174
+ async function runPipeline(taskName, callbackToken, update) {
1132
1175
  const taskConfig = live.config.tasks[taskName];
1133
1176
  const handlerNames = taskConfig.taskHandlers ?? [];
1134
1177
  const upstreamState = resolveUpstreamState(taskName);
@@ -1142,7 +1185,8 @@ function createReactiveGraph(config, options, executionId) {
1142
1185
  state: upstreamState,
1143
1186
  taskState: live.state.tasks[taskName],
1144
1187
  config: taskConfig,
1145
- callbackToken
1188
+ callbackToken,
1189
+ update
1146
1190
  };
1147
1191
  const status = await handler(input);
1148
1192
  if (status === "task-initiate-failure") {
@@ -1156,15 +1200,16 @@ function createReactiveGraph(config, options, executionId) {
1156
1200
  if (!handlerNames || handlerNames.length === 0) {
1157
1201
  return;
1158
1202
  }
1159
- journal.append({
1203
+ internalJournal.append({
1160
1204
  type: "task-started",
1161
1205
  taskName,
1162
1206
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1163
1207
  });
1208
+ drain();
1164
1209
  const callbackToken = encodeCallbackToken(taskName);
1165
1210
  runPipeline(taskName, callbackToken).catch((error) => {
1166
1211
  if (disposed) return;
1167
- journal.append({
1212
+ internalJournal.append({
1168
1213
  type: "task-failed",
1169
1214
  taskName,
1170
1215
  error: error.message ?? String(error),
@@ -1179,16 +1224,16 @@ function createReactiveGraph(config, options, executionId) {
1179
1224
  if (event.type === "task-completed" && event.data && !event.dataHash) {
1180
1225
  event = { ...event, dataHash: computeDataHash(event.data) };
1181
1226
  }
1182
- journal.append(event);
1227
+ inputQueue.append(event);
1183
1228
  drain();
1184
1229
  },
1185
1230
  pushAll(events) {
1186
1231
  if (disposed) return;
1187
1232
  for (const event of events) {
1188
1233
  if (event.type === "task-completed" && event.data && !event.dataHash) {
1189
- journal.append({ ...event, dataHash: computeDataHash(event.data) });
1234
+ inputQueue.append({ ...event, dataHash: computeDataHash(event.data) });
1190
1235
  } else {
1191
- journal.append(event);
1236
+ inputQueue.append(event);
1192
1237
  }
1193
1238
  }
1194
1239
  drain();
@@ -1200,7 +1245,7 @@ function createReactiveGraph(config, options, executionId) {
1200
1245
  const { taskName } = decoded;
1201
1246
  if (!live.config.tasks[taskName]) return;
1202
1247
  if (errors && errors.length > 0) {
1203
- journal.append({
1248
+ inputQueue.append({
1204
1249
  type: "task-failed",
1205
1250
  taskName,
1206
1251
  error: errors.join("; "),
@@ -1208,7 +1253,7 @@ function createReactiveGraph(config, options, executionId) {
1208
1253
  });
1209
1254
  } else {
1210
1255
  const dataHash = data && Object.keys(data).length > 0 ? computeDataHash(data) : void 0;
1211
- journal.append({
1256
+ inputQueue.append({
1212
1257
  type: "task-completed",
1213
1258
  taskName,
1214
1259
  data,
@@ -1220,31 +1265,33 @@ function createReactiveGraph(config, options, executionId) {
1220
1265
  },
1221
1266
  addNode(name, taskConfig) {
1222
1267
  if (disposed) return;
1223
- live = addNode(live, name, taskConfig);
1268
+ inputQueue.append({ type: "task-upsert", taskName: name, taskConfig, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1224
1269
  drain();
1225
1270
  },
1226
1271
  removeNode(name) {
1227
1272
  if (disposed) return;
1228
- live = removeNode(live, name);
1273
+ inputQueue.append({ type: "task-removal", taskName: name, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1274
+ drain();
1229
1275
  },
1230
1276
  addRequires(nodeName, tokens) {
1231
1277
  if (disposed) return;
1232
- live = addRequires(live, nodeName, tokens);
1278
+ inputQueue.append({ type: "node-requires-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1233
1279
  drain();
1234
1280
  },
1235
1281
  removeRequires(nodeName, tokens) {
1236
1282
  if (disposed) return;
1237
- live = removeRequires(live, nodeName, tokens);
1283
+ inputQueue.append({ type: "node-requires-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1238
1284
  drain();
1239
1285
  },
1240
1286
  addProvides(nodeName, tokens) {
1241
1287
  if (disposed) return;
1242
- live = addProvides(live, nodeName, tokens);
1288
+ inputQueue.append({ type: "node-provides-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1243
1289
  drain();
1244
1290
  },
1245
1291
  removeProvides(nodeName, tokens) {
1246
1292
  if (disposed) return;
1247
- live = removeProvides(live, nodeName, tokens);
1293
+ inputQueue.append({ type: "node-provides-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1294
+ drain();
1248
1295
  },
1249
1296
  registerHandler(name, fn) {
1250
1297
  handlers.set(name, fn);
@@ -1255,7 +1302,7 @@ function createReactiveGraph(config, options, executionId) {
1255
1302
  retrigger(taskName) {
1256
1303
  if (disposed) return;
1257
1304
  if (!live.config.tasks[taskName]) return;
1258
- journal.append({
1305
+ inputQueue.append({
1259
1306
  type: "task-restart",
1260
1307
  taskName,
1261
1308
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
@@ -1266,7 +1313,7 @@ function createReactiveGraph(config, options, executionId) {
1266
1313
  if (disposed) return;
1267
1314
  for (const name of taskNames) {
1268
1315
  if (!live.config.tasks[name]) continue;
1269
- journal.append({
1316
+ inputQueue.append({
1270
1317
  type: "task-restart",
1271
1318
  taskName: name,
1272
1319
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
@@ -1274,6 +1321,9 @@ function createReactiveGraph(config, options, executionId) {
1274
1321
  }
1275
1322
  drain();
1276
1323
  },
1324
+ snapshot() {
1325
+ return snapshot(live);
1326
+ },
1277
1327
  getState() {
1278
1328
  return live;
1279
1329
  },
@@ -1657,288 +1707,43 @@ function deepSet(obj, path, value) {
1657
1707
  }
1658
1708
  cur[parts[parts.length - 1]] = value;
1659
1709
  }
1660
- var _fns = {};
1661
- _fns.sum = (input, _e, opts) => {
1662
- const a = Array.isArray(input) ? input : [];
1663
- return opts.field ? a.reduce((s, r) => s + (Number(r[opts.field]) || 0), 0) : a.reduce((s, v) => s + (Number(v) || 0), 0);
1664
- };
1665
- _fns.avg = (input, _e, opts) => {
1666
- const s = _fns.sum(input, _e, opts);
1667
- const n = Array.isArray(input) ? input.length : 1;
1668
- return n ? s / n : 0;
1669
- };
1670
- _fns.min = (input, _e, opts) => {
1671
- const a = Array.isArray(input) ? input : [];
1672
- const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
1673
- return vals.length ? Math.min(...vals) : 0;
1674
- };
1675
- _fns.max = (input, _e, opts) => {
1676
- const a = Array.isArray(input) ? input : [];
1677
- const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
1678
- return vals.length ? Math.max(...vals) : 0;
1679
- };
1680
- _fns.count = (input) => Array.isArray(input) ? input.length : input != null ? 1 : 0;
1681
- _fns.first = (input) => Array.isArray(input) ? input[0] : input;
1682
- _fns.last = (input) => Array.isArray(input) ? input[input.length - 1] : input;
1683
- _fns.add = (input) => {
1684
- const a = Array.isArray(input) ? input : [];
1685
- return a.reduce((s, v) => s + Number(v), 0);
1686
- };
1687
- _fns.sub = (input) => {
1688
- const a = Array.isArray(input) ? input : [];
1689
- return a.length >= 2 ? Number(a[0]) - Number(a[1]) : 0;
1690
- };
1691
- _fns.mul = (input) => {
1692
- const a = Array.isArray(input) ? input : [];
1693
- return a.reduce((s, v) => s * Number(v), 1);
1694
- };
1695
- _fns.div = (input) => {
1696
- const a = Array.isArray(input) ? input : [];
1697
- return a.length >= 2 && Number(a[1]) !== 0 ? Number(a[0]) / Number(a[1]) : 0;
1698
- };
1699
- _fns.round = (input, _e, opts) => {
1700
- const decimals = opts.decimals != null ? opts.decimals : 0;
1701
- const factor = Math.pow(10, decimals);
1702
- return Math.round(Number(input) * factor) / factor;
1703
- };
1704
- _fns.abs = (input) => Math.abs(Number(input));
1705
- _fns.mod = (input) => {
1706
- const a = Array.isArray(input) ? input : [];
1707
- return a.length >= 2 ? Number(a[0]) % Number(a[1]) : 0;
1708
- };
1709
- _fns.gt = (input) => {
1710
- const a = Array.isArray(input) ? input : [];
1711
- return a.length >= 2 && Number(a[0]) > Number(a[1]);
1712
- };
1713
- _fns.gte = (input) => {
1714
- const a = Array.isArray(input) ? input : [];
1715
- return a.length >= 2 && Number(a[0]) >= Number(a[1]);
1716
- };
1717
- _fns.lt = (input) => {
1718
- const a = Array.isArray(input) ? input : [];
1719
- return a.length >= 2 && Number(a[0]) < Number(a[1]);
1720
- };
1721
- _fns.lte = (input) => {
1722
- const a = Array.isArray(input) ? input : [];
1723
- return a.length >= 2 && Number(a[0]) <= Number(a[1]);
1724
- };
1725
- _fns.eq = (input) => {
1726
- const a = Array.isArray(input) ? input : [];
1727
- return a.length >= 2 && a[0] === a[1];
1728
- };
1729
- _fns.neq = (input) => {
1730
- const a = Array.isArray(input) ? input : [];
1731
- return a.length >= 2 && a[0] !== a[1];
1732
- };
1733
- _fns.and = (input) => {
1734
- const a = Array.isArray(input) ? input : [];
1735
- return a.every(Boolean);
1736
- };
1737
- _fns.or = (input) => {
1738
- const a = Array.isArray(input) ? input : [];
1739
- return a.some(Boolean);
1740
- };
1741
- _fns.not = (input) => !input;
1742
- _fns.concat = (input) => {
1743
- const a = Array.isArray(input) ? input : [];
1744
- return a.map((v) => v != null ? String(v) : "").join("");
1745
- };
1746
- _fns.upper = (input) => String(input || "").toUpperCase();
1747
- _fns.lower = (input) => String(input || "").toLowerCase();
1748
- _fns.template = (input, _e, opts) => {
1749
- let t = String(opts.format || "");
1750
- if (input && typeof input === "object" && !Array.isArray(input)) {
1751
- for (const k of Object.keys(input)) {
1752
- const v = input[k];
1753
- t = t.split("{{" + k + "}}").join(v != null ? String(v) : "");
1754
- }
1755
- }
1756
- return t;
1757
- };
1758
- _fns.join = (input, _e, opts) => {
1759
- const a = Array.isArray(input) ? input : [];
1760
- const sep = opts.separator != null ? String(opts.separator) : ", ";
1761
- return a.map((v) => v != null ? String(v) : "").join(sep);
1762
- };
1763
- _fns.split = (input, _e, opts) => {
1764
- const sep = opts.separator != null ? String(opts.separator) : ",";
1765
- return String(input || "").split(sep).map((s) => s.trim());
1766
- };
1767
- _fns.trim = (input) => String(input || "").trim();
1768
- _fns.pluck = (input, _e, opts) => Array.isArray(input) ? input.map((r) => r[opts.field]) : [];
1769
- _fns.filter = (input, _e, opts) => {
1770
- if (!Array.isArray(input)) return [];
1771
- if (opts.field) return input.filter((r) => !!r[opts.field]);
1772
- return input.filter(Boolean);
1773
- };
1774
- _fns.map = (input) => Array.isArray(input) ? input.slice() : [];
1775
- _fns.sort = (input, _e, opts) => {
1776
- const a = Array.isArray(input) ? input.slice() : [];
1777
- const f = opts.field;
1778
- const dir = opts.direction === "desc" ? -1 : 1;
1779
- if (f) return a.sort((x, y) => x[f] > y[f] ? dir : x[f] < y[f] ? -dir : 0);
1780
- return a.sort((x, y) => x > y ? dir : x < y ? -dir : 0);
1781
- };
1782
- _fns.slice = (input, _e, opts) => Array.isArray(input) ? input.slice(opts.start || 0, opts.end) : input;
1783
- _fns.flat = (input, _e, opts) => {
1784
- const depth = opts.depth != null ? opts.depth : 1;
1785
- return Array.isArray(input) ? input.flat(depth) : [input];
1786
- };
1787
- _fns.unique = (input) => {
1788
- if (!Array.isArray(input)) return [input];
1789
- const seen = /* @__PURE__ */ new Set();
1790
- return input.filter((v) => {
1791
- const key = typeof v === "object" ? JSON.stringify(v) : v;
1792
- if (seen.has(key)) return false;
1793
- seen.add(key);
1794
- return true;
1795
- });
1796
- };
1797
- _fns.group = (input, _e, opts) => {
1798
- const a = Array.isArray(input) ? input : [];
1799
- const g = {};
1800
- a.forEach((r) => {
1801
- const k = String(r[opts.field] || "");
1802
- if (!g[k]) g[k] = [];
1803
- g[k].push(r);
1804
- });
1805
- return g;
1806
- };
1807
- _fns.flatten_keys = (input) => {
1808
- if (!input || typeof input !== "object" || Array.isArray(input)) return [];
1809
- const result = [];
1810
- for (const k of Object.keys(input)) {
1811
- const vals = Array.isArray(input[k]) ? input[k] : [input[k]];
1812
- vals.forEach((v) => result.push({ key: k, value: v }));
1813
- }
1814
- return result;
1815
- };
1816
- _fns.entries = (input) => {
1817
- if (!input || typeof input !== "object" || Array.isArray(input)) return [];
1818
- return Object.keys(input).map((k) => ({ key: k, value: input[k] }));
1819
- };
1820
- _fns.from_entries = (input) => {
1821
- if (!Array.isArray(input)) return {};
1822
- const obj = {};
1823
- input.forEach((item) => {
1824
- if (item.key != null) obj[item.key] = item.value;
1825
- });
1826
- return obj;
1827
- };
1828
- _fns.length = (input) => {
1829
- if (Array.isArray(input)) return input.length;
1830
- if (typeof input === "string") return input.length;
1831
- if (input && typeof input === "object") return Object.keys(input).length;
1832
- return 0;
1833
- };
1834
- _fns.get = (input, _e, opts) => deepGet(input, opts.field || opts.path || "");
1835
- _fns.default = (input, _e, opts) => input != null ? input : opts.value;
1836
- _fns.coalesce = (input) => {
1837
- const a = Array.isArray(input) ? input : [];
1838
- for (let i = 0; i < a.length; i++) {
1839
- if (a[i] != null) return a[i];
1840
- }
1841
- return null;
1842
- };
1843
- _fns.now = () => (/* @__PURE__ */ new Date()).toISOString();
1844
- _fns.diff_days = (input) => {
1845
- const a = Array.isArray(input) ? input : [];
1846
- return a.length >= 2 ? Math.floor((new Date(a[0]).getTime() - new Date(a[1]).getTime()) / 864e5) : 0;
1847
- };
1848
- _fns.format_date = (input, _e, opts) => {
1849
- try {
1850
- const d = new Date(input);
1851
- if (opts.format === "iso") return d.toISOString();
1852
- if (opts.format === "date") return d.toLocaleDateString();
1853
- if (opts.format === "time") return d.toLocaleTimeString();
1854
- return d.toLocaleDateString();
1855
- } catch {
1856
- return String(input);
1857
- }
1858
- };
1859
- _fns.parse_date = (input) => {
1860
- try {
1861
- return new Date(input).toISOString();
1862
- } catch {
1863
- return null;
1864
- }
1865
- };
1866
- _fns.to_number = (input) => Number(input) || 0;
1867
- _fns.to_string = (input) => input != null ? String(input) : "";
1868
- _fns.to_bool = (input) => !!input;
1869
- _fns.type_of = (input) => Array.isArray(input) ? "array" : typeof input;
1870
- _fns.is_null = (input) => input == null;
1871
- _fns.is_empty = (input) => {
1872
- if (input == null) return true;
1873
- if (Array.isArray(input)) return input.length === 0;
1874
- if (typeof input === "string") return input.length === 0;
1875
- if (typeof input === "object") return Object.keys(input).length === 0;
1876
- return false;
1877
- };
1878
- var _customFns = {};
1879
- function evalExpr(expr, node) {
1880
- if (expr == null) return expr;
1881
- if (typeof expr !== "object" || Array.isArray(expr)) return expr;
1882
- const e = expr;
1883
- if (!e.fn) return expr;
1884
- let input = e.input;
1885
- if (typeof input === "string" && input.startsWith("state.")) {
1886
- input = deepGet(node, input);
1887
- } else if (Array.isArray(input)) {
1888
- input = input.map((v) => {
1889
- if (typeof v === "string" && v.startsWith("state.")) return deepGet(node, v);
1890
- if (v && typeof v === "object" && v.fn) return evalExpr(v, node);
1891
- return v;
1892
- });
1893
- } else if (input && typeof input === "object" && input.fn) {
1894
- input = evalExpr(input, node);
1895
- }
1896
- if (e.fn === "if") {
1897
- const cond = evalExpr(e.cond, node);
1898
- if (cond) {
1899
- return e.then && typeof e.then === "object" && e.then.fn ? evalExpr(e.then, node) : e.then;
1900
- } else {
1901
- return e.else && typeof e.else === "object" && e.else.fn ? evalExpr(e.else, node) : e.else;
1902
- }
1903
- }
1904
- if (e.fn === "filter" && Array.isArray(input) && e.where) {
1905
- return input.filter((item) => {
1906
- const tmp = { state: { ...node.state, $: item } };
1907
- return evalExpr(e.where, tmp);
1908
- });
1909
- }
1910
- if (e.fn === "map" && Array.isArray(input) && e.apply) {
1911
- return input.map((item) => {
1912
- const tmp = { state: { ...node.state, $: item } };
1913
- return evalExpr(e.apply, tmp);
1914
- });
1915
- }
1916
- const fn = _customFns[e.fn] || _fns[e.fn];
1917
- if (!fn) {
1918
- console.warn('CardCompute: unknown function "' + e.fn + '"');
1919
- return void 0;
1920
- }
1921
- return fn(input, evalExpr, e);
1922
- }
1923
- function run(node) {
1924
- if (!node || !node.compute) return node;
1925
- if (!node.state) node.state = {};
1926
- for (const key of Object.keys(node.compute)) {
1710
+ async function run(node, options) {
1711
+ if (!node?.compute?.length) return node;
1712
+ if (!node.card_data) node.card_data = {};
1713
+ node.computed_values = {};
1714
+ node._sourcesData = options?.sourcesData ?? {};
1715
+ const ctx = {
1716
+ card_data: node.card_data,
1717
+ requires: node.requires ?? {},
1718
+ fetched_sources: node._sourcesData,
1719
+ computed_values: node.computed_values
1720
+ };
1721
+ for (const step of node.compute) {
1927
1722
  try {
1928
- const val = evalExpr(node.compute[key], node);
1929
- deepSet(node.state, key, val);
1723
+ const val = await jsonata2(step.expr).evaluate(ctx);
1724
+ deepSet(node.computed_values, step.bindTo, val);
1725
+ ctx.computed_values = node.computed_values;
1930
1726
  } catch (err) {
1931
- console.error(`CardCompute.run error on "${node.id || "?"}.${key}":`, err);
1727
+ console.error(`CardCompute.run error on "${node.id ?? "?"}.${step.bindTo}":`, err);
1932
1728
  }
1933
1729
  }
1934
1730
  return node;
1935
1731
  }
1732
+ async function evalExpr(expr, node) {
1733
+ const ctx = {
1734
+ card_data: node.card_data ?? {},
1735
+ requires: node.requires ?? {},
1736
+ fetched_sources: node._sourcesData ?? {},
1737
+ computed_values: node.computed_values ?? {}
1738
+ };
1739
+ return jsonata2(expr).evaluate(ctx);
1740
+ }
1936
1741
  function resolve(node, path) {
1742
+ if (path.startsWith("fetched_sources.")) {
1743
+ return deepGet(node._sourcesData ?? {}, path.slice("fetched_sources.".length));
1744
+ }
1937
1745
  return deepGet(node, path);
1938
1746
  }
1939
- function registerFunction(name, fn) {
1940
- _customFns[name] = fn;
1941
- }
1942
1747
  var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
1943
1748
  "metric",
1944
1749
  "table",
@@ -1955,34 +1760,19 @@ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
1955
1760
  "markdown",
1956
1761
  "custom"
1957
1762
  ]);
1958
- var VALID_SOURCE_KINDS = /* @__PURE__ */ new Set(["api", "websocket", "static", "llm"]);
1959
- var VALID_STATUSES = /* @__PURE__ */ new Set(["fresh", "stale", "loading", "error"]);
1960
- var CARD_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "view", "state", "compute"]);
1961
- var SOURCE_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "source", "state", "compute"]);
1763
+ var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "card_data", "compute", "sources"]);
1962
1764
  function validateNode(node) {
1963
1765
  const errors = [];
1964
1766
  if (!node || typeof node !== "object" || Array.isArray(node)) {
1965
1767
  return { ok: false, errors: ["Node must be a non-null object"] };
1966
1768
  }
1967
1769
  const n = node;
1968
- if (typeof n.id !== "string" || !n.id) {
1969
- errors.push("id: required, must be a non-empty string");
1970
- }
1971
- if (n.type !== "card" && n.type !== "source") {
1972
- errors.push('type: must be "card" or "source"');
1973
- return { ok: false, errors };
1974
- }
1975
- const allowed = n.type === "card" ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;
1770
+ if (typeof n.id !== "string" || !n.id) errors.push("id: required, must be a non-empty string");
1976
1771
  for (const key of Object.keys(n)) {
1977
- if (!allowed.has(key)) errors.push(`Unknown top-level key: "${key}"`);
1772
+ if (!ALLOWED_KEYS.has(key)) errors.push(`Unknown top-level key: "${key}"`);
1978
1773
  }
1979
- if (n.state == null || typeof n.state !== "object" || Array.isArray(n.state)) {
1980
- errors.push("state: required, must be an object");
1981
- } else {
1982
- const state = n.state;
1983
- if (state.status != null && !VALID_STATUSES.has(state.status)) {
1984
- errors.push(`state.status: must be one of: ${[...VALID_STATUSES].join(", ")}`);
1985
- }
1774
+ if (n.card_data == null || typeof n.card_data !== "object" || Array.isArray(n.card_data)) {
1775
+ errors.push("card_data: required, must be an object");
1986
1776
  }
1987
1777
  if (n.meta != null) {
1988
1778
  if (typeof n.meta !== "object" || Array.isArray(n.meta)) {
@@ -1993,37 +1783,58 @@ function validateNode(node) {
1993
1783
  if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
1994
1784
  }
1995
1785
  }
1996
- if (n.data != null) {
1997
- if (typeof n.data !== "object" || Array.isArray(n.data)) {
1998
- errors.push("data: must be an object");
1786
+ if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
1787
+ if (n.provides != null) {
1788
+ if (!Array.isArray(n.provides)) {
1789
+ errors.push("provides: must be an array of { bindTo, src } bindings");
1999
1790
  } else {
2000
- const data = n.data;
2001
- if (data.requires != null && !Array.isArray(data.requires)) errors.push("data.requires: must be an array of strings");
2002
- if (data.provides != null && (typeof data.provides !== "object" || Array.isArray(data.provides))) errors.push("data.provides: must be an object");
1791
+ n.provides.forEach((p, i) => {
1792
+ if (!p || typeof p !== "object" || Array.isArray(p)) {
1793
+ errors.push(`provides[${i}]: must be an object with bindTo and src`);
1794
+ } else {
1795
+ const b = p;
1796
+ if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
1797
+ if (typeof b.src !== "string" || !b.src) errors.push(`provides[${i}]: missing required "src" string`);
1798
+ }
1799
+ });
2003
1800
  }
2004
1801
  }
2005
1802
  if (n.compute != null) {
2006
- if (typeof n.compute !== "object" || Array.isArray(n.compute)) {
2007
- errors.push("compute: must be an object");
1803
+ if (!Array.isArray(n.compute)) {
1804
+ errors.push("compute: must be an array of compute steps");
2008
1805
  } else {
2009
- for (const [key, expr] of Object.entries(n.compute)) {
2010
- if (!expr || typeof expr !== "object" || Array.isArray(expr)) {
2011
- errors.push(`compute.${key}: must be a compute expression object`);
2012
- } else if (!expr.fn) {
2013
- errors.push(`compute.${key}: missing required "fn" property`);
1806
+ n.compute.forEach((step, i) => {
1807
+ if (!step || typeof step !== "object" || Array.isArray(step)) {
1808
+ errors.push(`compute[${i}]: must be a compute step object`);
2014
1809
  } else {
2015
- const fn = expr.fn;
2016
- if (!_fns[fn] && !_customFns[fn]) {
2017
- errors.push(`compute.${key}: unknown function "${fn}"`);
1810
+ const s = step;
1811
+ if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`compute[${i}]: missing required "bindTo" property`);
1812
+ if (typeof s.expr !== "string" || !s.expr) errors.push(`compute[${i}]: missing required "expr" string (JSONata expression)`);
1813
+ }
1814
+ });
1815
+ }
1816
+ }
1817
+ if (n.sources != null) {
1818
+ if (!Array.isArray(n.sources)) {
1819
+ errors.push("sources: must be an array");
1820
+ } else {
1821
+ n.sources.forEach((src, i) => {
1822
+ if (!src || typeof src !== "object" || Array.isArray(src)) {
1823
+ errors.push(`sources[${i}]: must be an object`);
1824
+ } else {
1825
+ const s = src;
1826
+ if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`sources[${i}]: missing required "bindTo" property`);
1827
+ if (s.outputFile != null && typeof s.outputFile !== "string") errors.push(`sources[${i}]: outputFile must be a string`);
1828
+ if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
1829
+ errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
2018
1830
  }
2019
1831
  }
2020
- }
1832
+ });
2021
1833
  }
2022
1834
  }
2023
- if (n.type === "card") {
2024
- if (n.source != null) errors.push('Card nodes must not have "source" \u2014 use type "source" instead');
2025
- if (n.view == null || typeof n.view !== "object" || Array.isArray(n.view)) {
2026
- errors.push("view: required for card nodes, must be an object");
1835
+ if (n.view != null) {
1836
+ if (typeof n.view !== "object" || Array.isArray(n.view)) {
1837
+ errors.push("view: must be an object");
2027
1838
  } else {
2028
1839
  const view = n.view;
2029
1840
  if (!Array.isArray(view.elements) || view.elements.length === 0) {
@@ -2044,44 +1855,27 @@ function validateNode(node) {
2044
1855
  }
2045
1856
  });
2046
1857
  }
2047
- if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) {
2048
- errors.push("view.layout: must be an object");
2049
- }
2050
- if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) {
2051
- errors.push("view.features: must be an object");
2052
- }
2053
- }
2054
- }
2055
- if (n.type === "source") {
2056
- if (n.view != null) errors.push('Source nodes must not have "view" \u2014 use type "card" instead');
2057
- if (n.source == null || typeof n.source !== "object" || Array.isArray(n.source)) {
2058
- errors.push("source: required for source nodes, must be an object");
2059
- } else {
2060
- const src = n.source;
2061
- if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind)) {
2062
- errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(", ")}`);
2063
- }
2064
- if (typeof src.bindTo !== "string" || !src.bindTo) {
2065
- errors.push("source.bindTo: required, must be a state path string");
2066
- } else if (!src.bindTo.startsWith("state.")) {
2067
- errors.push('source.bindTo: must start with "state."');
2068
- }
1858
+ if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) errors.push("view.layout: must be an object");
1859
+ if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) errors.push("view.features: must be an object");
2069
1860
  }
2070
1861
  }
2071
1862
  return { ok: errors.length === 0, errors };
2072
1863
  }
1864
+ function enrichSources(sources, context) {
1865
+ if (!sources || sources.length === 0) return [];
1866
+ return sources.map((src) => ({
1867
+ ...src,
1868
+ _requires: context.requires ?? {},
1869
+ _sourcesData: context.sourcesData ?? {},
1870
+ _computed_values: context.computed_values ?? {}
1871
+ }));
1872
+ }
2073
1873
  var CardCompute = {
2074
1874
  run,
2075
1875
  eval: evalExpr,
2076
1876
  resolve,
2077
1877
  validate: validateNode,
2078
- registerFunction,
2079
- get functions() {
2080
- const all = {};
2081
- for (const k of Object.keys(_fns)) all[k] = _fns[k];
2082
- for (const k of Object.keys(_customFns)) all[k] = _customFns[k];
2083
- return all;
2084
- }
1878
+ enrichSources
2085
1879
  };
2086
1880
 
2087
1881
  // src/continuous-event-graph/live-cards-bridge.ts
@@ -2114,19 +1908,26 @@ function liveCardsToReactiveGraph(input, options = {}) {
2114
1908
  }
2115
1909
  const sharedState = options.sharedState ?? /* @__PURE__ */ new Map();
2116
1910
  const tasks = {};
1911
+ const allTokens = /* @__PURE__ */ new Set();
1912
+ const tokenToCardId = /* @__PURE__ */ new Map();
2117
1913
  for (const card of cards) {
2118
- const requires = card.data?.requires ?? [];
1914
+ for (const binding of card.provides ?? [{ bindTo: card.id, src: "card_data" }]) {
1915
+ allTokens.add(binding.bindTo);
1916
+ tokenToCardId.set(binding.bindTo, card.id);
1917
+ }
1918
+ }
1919
+ for (const card of cards) {
1920
+ const requires = card.requires ?? [];
2119
1921
  for (const req of requires) {
2120
- if (!cardMap.has(req)) {
2121
- throw new Error(`Card "${card.id}" requires "${req}" but no card with that ID exists`);
1922
+ if (!allTokens.has(req)) {
1923
+ throw new Error(`Card "${card.id}" requires "${req}" but no card provides that token`);
2122
1924
  }
2123
1925
  }
2124
1926
  tasks[card.id] = {
2125
1927
  requires: requires.length > 0 ? requires : void 0,
2126
- provides: [card.id],
1928
+ provides: (card.provides ?? [{ bindTo: card.id, src: "card_data" }]).map((p) => p.bindTo),
2127
1929
  taskHandlers: [card.id],
2128
- // each card has a named handler matching its ID
2129
- description: card.meta?.title ?? `${card.type}: ${card.id}`
1930
+ description: card.meta?.title ?? card.id
2130
1931
  };
2131
1932
  }
2132
1933
  const config = {
@@ -2145,10 +1946,10 @@ function liveCardsToReactiveGraph(input, options = {}) {
2145
1946
  graphRef.resolveCallback(token, data, errors);
2146
1947
  };
2147
1948
  for (const card of cards) {
2148
- if (card.type === "source") {
1949
+ if (card.sources && card.sources.length > 0) {
2149
1950
  handlers[card.id] = buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedState, getResolve);
2150
1951
  } else {
2151
- handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve);
1952
+ handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, tokenToCardId, getResolve);
2152
1953
  }
2153
1954
  }
2154
1955
  const graph = createReactiveGraph(
@@ -2176,13 +1977,13 @@ function buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedSt
2176
1977
  };
2177
1978
  }
2178
1979
  return async (input) => {
2179
- const state = { ...card.state };
2180
- sharedState.set(card.id, state);
2181
- getResolve()(input.callbackToken, state);
1980
+ const data = { ...card.card_data };
1981
+ sharedState.set(card.id, data);
1982
+ getResolve()(input.callbackToken, data);
2182
1983
  return "task-initiated";
2183
1984
  };
2184
1985
  }
2185
- function buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve) {
1986
+ function buildCardHandler(card, cardHandlers, sharedState, _cardMap, tokenToCardId, getResolve) {
2186
1987
  if (cardHandlers[card.id]) {
2187
1988
  const userHandler = cardHandlers[card.id];
2188
1989
  return async (input) => {
@@ -2190,48 +1991,38 @@ function buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve)
2190
1991
  };
2191
1992
  }
2192
1993
  return async (input) => {
1994
+ const requiresData = {};
1995
+ const requires = card.requires ?? [];
1996
+ for (const token of requires) {
1997
+ const producerId = tokenToCardId.get(token) ?? token;
1998
+ const upstreamState = sharedState.get(producerId);
1999
+ if (upstreamState) {
2000
+ requiresData[token] = upstreamState[token] ?? upstreamState;
2001
+ }
2002
+ }
2193
2003
  const computeNode = {
2194
2004
  id: card.id,
2195
- state: { ...card.state },
2005
+ card_data: { ...card.card_data },
2006
+ requires: requiresData,
2196
2007
  compute: card.compute
2197
2008
  };
2198
- const requires = card.data?.requires ?? [];
2199
- for (const upstreamId of requires) {
2200
- const upstreamState = sharedState.get(upstreamId);
2201
- if (upstreamState) {
2202
- computeNode.state[upstreamId] = upstreamState;
2203
- }
2204
- const upstreamCard = cardMap.get(upstreamId);
2205
- if (upstreamCard?.data?.provides && upstreamState) {
2206
- for (const [key, bindRef] of Object.entries(upstreamCard.data.provides)) {
2207
- if (typeof bindRef === "string" && bindRef.startsWith("state.")) {
2208
- const path = bindRef.slice(6);
2209
- const value = deepGet2(upstreamState, path);
2210
- if (value !== void 0) {
2211
- computeNode.state[key] = value;
2212
- }
2213
- }
2214
- }
2009
+ await CardCompute.run(computeNode);
2010
+ let resultData;
2011
+ if (card.provides && card.provides.length > 0) {
2012
+ resultData = {};
2013
+ for (const { bindTo, src } of card.provides) {
2014
+ resultData[bindTo] = CardCompute.resolve(computeNode, src);
2215
2015
  }
2016
+ } else {
2017
+ resultData = { ...computeNode.card_data, ...computeNode.computed_values };
2216
2018
  }
2217
- CardCompute.run(computeNode);
2218
- const resultState = { ...computeNode.state };
2019
+ const resultState = { ...computeNode.card_data, ...computeNode.computed_values };
2219
2020
  sharedState.set(card.id, resultState);
2220
- getResolve()(input.callbackToken, resultState);
2021
+ getResolve()(input.callbackToken, resultData);
2221
2022
  return "task-initiated";
2222
2023
  };
2223
2024
  }
2224
- function deepGet2(obj, path) {
2225
- if (!path || !obj) return void 0;
2226
- const parts = path.split(".");
2227
- let cur = obj;
2228
- for (const part of parts) {
2229
- if (cur == null) return void 0;
2230
- cur = cur[part];
2231
- }
2232
- return cur;
2233
- }
2234
2025
 
2235
- export { FileJournal, MemoryJournal, addNode, addProvides, addRequires, applyEvent, applyEvents, computeDataHash, createCallbackHandler, createFireAndForgetHandler, createLiveGraph, createNoopHandler, createReactiveGraph, createScriptHandler, createShellHandler, createWebhookHandler, disableNode, drainTokens, enableNode, getDownstream, getNode, getUnreachableNodes, getUnreachableTokens, getUpstream, injectTokens, inspect, liveCardsToReactiveGraph, mutateGraph, removeNode, removeProvides, removeRequires, resetNode, restore, schedule, snapshot, validateLiveGraph, validateReactiveGraph };
2026
+ export { MemoryJournal, addNode, addProvides, addRequires, applyEvent, applyEvents, computeDataHash, createCallbackHandler, createFireAndForgetHandler, createLiveGraph, createNoopHandler, createReactiveGraph, createScriptHandler, createShellHandler, createWebhookHandler, disableNode, drainTokens, enableNode, getDownstream, getNode, getUnreachableNodes, getUnreachableTokens, getUpstream, injectTokens, inspect, liveCardsToReactiveGraph, mutateGraph, removeNode, removeProvides, removeRequires, resetNode, restore, schedule, snapshot, validateLiveGraph, validateReactiveGraph };
2236
2027
  //# sourceMappingURL=index.js.map
2237
2028
  //# sourceMappingURL=index.js.map