yaml-flow 5.4.2 → 6.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 (199) hide show
  1. package/board-live-cards-cli.js +2 -2
  2. package/board-livecards-server-runtime.js +486 -547
  3. package/browser/asset-integrity.json +10 -0
  4. package/browser/board-livegraph-engine.js +2 -1676
  5. package/browser/board-livegraph-engine.js.map +1 -1
  6. package/browser/live-cards.js +347 -26
  7. package/browser/live-cards.schema.json +418 -132
  8. package/card-store.js +37 -0
  9. package/dist/batch/index.cjs +1 -108
  10. package/dist/batch/index.cjs.map +1 -1
  11. package/dist/batch/index.js +1 -106
  12. package/dist/batch/index.js.map +1 -1
  13. package/dist/board-live-cards-lib-Bg6EvCo5.d.cts +136 -0
  14. package/dist/board-live-cards-lib-jM2uYG1v.d.ts +136 -0
  15. package/dist/board-live-cards-public-CltXYgaY.d.cts +314 -0
  16. package/dist/board-live-cards-public-f-E-FAyp.d.ts +314 -0
  17. package/dist/board-livegraph-runtime/index.cjs +2 -1671
  18. package/dist/board-livegraph-runtime/index.cjs.map +1 -1
  19. package/dist/board-livegraph-runtime/index.d.cts +1 -2
  20. package/dist/board-livegraph-runtime/index.d.ts +1 -2
  21. package/dist/board-livegraph-runtime/index.js +2 -1662
  22. package/dist/board-livegraph-runtime/index.js.map +1 -1
  23. package/dist/board-livegraph-runtime/jsonata-sync.cjs +7587 -0
  24. package/dist/card-compute/index.cjs +9 -7159
  25. package/dist/card-compute/index.cjs.map +1 -1
  26. package/dist/card-compute/index.d.cts +22 -0
  27. package/dist/card-compute/index.d.ts +22 -0
  28. package/dist/card-compute/index.js +9 -7145
  29. package/dist/card-compute/index.js.map +1 -1
  30. package/dist/card-compute/jsonata-sync.cjs +7587 -0
  31. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs +2 -0
  32. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs.map +1 -0
  33. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.cts +24 -0
  34. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.ts +24 -0
  35. package/dist/cli/browser-api/board-live-cards-browser-adapter.js +2 -0
  36. package/dist/cli/browser-api/board-live-cards-browser-adapter.js.map +1 -0
  37. package/dist/cli/browser-api/card-store-browser-api.cjs +2 -0
  38. package/dist/cli/browser-api/card-store-browser-api.cjs.map +1 -0
  39. package/dist/cli/browser-api/card-store-browser-api.d.cts +26 -0
  40. package/dist/cli/browser-api/card-store-browser-api.d.ts +26 -0
  41. package/dist/cli/browser-api/card-store-browser-api.js +2 -0
  42. package/dist/cli/browser-api/card-store-browser-api.js.map +1 -0
  43. package/dist/cli/browser-api/jsonata-sync.cjs +7587 -0
  44. package/dist/cli/node/artifacts-store-cli.cjs +11 -0
  45. package/dist/cli/node/artifacts-store-cli.cjs.map +1 -0
  46. package/dist/cli/node/artifacts-store-cli.d.cts +8 -0
  47. package/dist/cli/node/artifacts-store-cli.d.ts +8 -0
  48. package/dist/cli/node/artifacts-store-cli.js +11 -0
  49. package/dist/cli/node/artifacts-store-cli.js.map +1 -0
  50. package/dist/cli/node/board-live-cards-cli.cjs +15 -0
  51. package/dist/cli/node/board-live-cards-cli.cjs.map +1 -0
  52. package/dist/cli/node/board-live-cards-cli.d.cts +20 -0
  53. package/dist/cli/node/board-live-cards-cli.d.ts +20 -0
  54. package/dist/cli/node/board-live-cards-cli.js +15 -0
  55. package/dist/cli/node/board-live-cards-cli.js.map +1 -0
  56. package/dist/cli/node/card-store-cli.cjs +8 -0
  57. package/dist/cli/node/card-store-cli.cjs.map +1 -0
  58. package/dist/cli/node/card-store-cli.d.cts +15 -0
  59. package/dist/cli/node/card-store-cli.d.ts +15 -0
  60. package/dist/cli/node/card-store-cli.js +8 -0
  61. package/dist/cli/node/card-store-cli.js.map +1 -0
  62. package/dist/cli/node/fs-board-adapter.cjs +14 -0
  63. package/dist/cli/node/fs-board-adapter.cjs.map +1 -0
  64. package/dist/cli/node/fs-board-adapter.d.cts +204 -0
  65. package/dist/cli/node/fs-board-adapter.d.ts +204 -0
  66. package/dist/cli/node/fs-board-adapter.js +14 -0
  67. package/dist/cli/node/fs-board-adapter.js.map +1 -0
  68. package/dist/cli/node/jsonata-sync.cjs +7587 -0
  69. package/dist/cli/node/source-cli-task-executor.cjs +11 -0
  70. package/dist/cli/node/source-cli-task-executor.cjs.map +1 -0
  71. package/dist/cli/node/source-cli-task-executor.d.cts +1 -0
  72. package/dist/cli/node/source-cli-task-executor.d.ts +1 -0
  73. package/dist/cli/node/source-cli-task-executor.js +11 -0
  74. package/dist/cli/node/source-cli-task-executor.js.map +1 -0
  75. package/dist/config/index.cjs +1 -79
  76. package/dist/config/index.cjs.map +1 -1
  77. package/dist/config/index.js +1 -76
  78. package/dist/config/index.js.map +1 -1
  79. package/dist/continuous-event-graph/index.cjs +2 -2129
  80. package/dist/continuous-event-graph/index.cjs.map +1 -1
  81. package/dist/continuous-event-graph/index.d.cts +81 -5
  82. package/dist/continuous-event-graph/index.d.ts +81 -5
  83. package/dist/continuous-event-graph/index.js +2 -2088
  84. package/dist/continuous-event-graph/index.js.map +1 -1
  85. package/dist/continuous-event-graph/jsonata-sync.cjs +7587 -0
  86. package/dist/event-graph/index.cjs +22 -8292
  87. package/dist/event-graph/index.cjs.map +1 -1
  88. package/dist/event-graph/index.js +22 -8237
  89. package/dist/event-graph/index.js.map +1 -1
  90. package/dist/execution-refs.cjs +2 -0
  91. package/dist/execution-refs.cjs.map +1 -0
  92. package/dist/execution-refs.d.cts +222 -0
  93. package/dist/execution-refs.d.ts +222 -0
  94. package/dist/execution-refs.js +2 -0
  95. package/dist/execution-refs.js.map +1 -0
  96. package/dist/index.cjs +29 -13221
  97. package/dist/index.cjs.map +1 -1
  98. package/dist/index.d.cts +2 -4
  99. package/dist/index.d.ts +2 -4
  100. package/dist/index.js +29 -13112
  101. package/dist/index.js.map +1 -1
  102. package/dist/inference/index.cjs +5 -617
  103. package/dist/inference/index.cjs.map +1 -1
  104. package/dist/inference/index.js +5 -610
  105. package/dist/inference/index.js.map +1 -1
  106. package/dist/jsonata-sync.cjs +7587 -0
  107. package/dist/{live-cards-bridge-x5XREkXm.d.cts → live-cards-bridge-BXbVTsna.d.cts} +27 -4
  108. package/dist/{live-cards-bridge-EQjytzI_.d.ts → live-cards-bridge-Ds28XR15.d.ts} +27 -4
  109. package/dist/pycli/quickjs-board-runtime.global.js +9 -0
  110. package/dist/pycli/quickjs-board-runtime.global.js.map +1 -0
  111. package/dist/pycli/quickjs-step-machine-runtime.global.js +5 -0
  112. package/dist/pycli/quickjs-step-machine-runtime.global.js.map +1 -0
  113. package/dist/step-machine/index.cjs +11 -7129
  114. package/dist/step-machine/index.cjs.map +1 -1
  115. package/dist/step-machine/index.js +11 -7113
  116. package/dist/step-machine/index.js.map +1 -1
  117. package/dist/storage-refs.cjs +10 -0
  118. package/dist/storage-refs.cjs.map +1 -0
  119. package/dist/storage-refs.d.cts +92 -0
  120. package/dist/storage-refs.d.ts +92 -0
  121. package/dist/storage-refs.js +10 -0
  122. package/dist/storage-refs.js.map +1 -0
  123. package/dist/stores/file.cjs +1 -114
  124. package/dist/stores/file.cjs.map +1 -1
  125. package/dist/stores/file.js +1 -112
  126. package/dist/stores/file.js.map +1 -1
  127. package/dist/stores/index.cjs +1 -231
  128. package/dist/stores/index.cjs.map +1 -1
  129. package/dist/stores/index.js +1 -227
  130. package/dist/stores/index.js.map +1 -1
  131. package/dist/stores/localStorage.cjs +1 -76
  132. package/dist/stores/localStorage.cjs.map +1 -1
  133. package/dist/stores/localStorage.js +1 -74
  134. package/dist/stores/localStorage.js.map +1 -1
  135. package/dist/stores/memory.cjs +1 -47
  136. package/dist/stores/memory.cjs.map +1 -1
  137. package/dist/stores/memory.js +1 -45
  138. package/dist/stores/memory.js.map +1 -1
  139. package/examples/browser/boards/portfolio-tracker/portfolio-t4.js +292 -0
  140. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.js +218 -0
  141. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.py +201 -0
  142. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-inference-adapter.js +25 -16
  143. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-public.js +553 -0
  144. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.py +365 -0
  145. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/.runtime-out +1 -0
  146. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/board-graph.json +32 -0
  147. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +53 -1
  148. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +15 -6
  149. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +6 -1
  150. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/poll-status-cli.js +57 -0
  151. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +1 -1
  152. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +1 -1
  153. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +7 -2
  154. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +6 -2
  155. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/_board_pycli.py +97 -0
  156. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/add-cards.py +50 -0
  157. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/init-board.py +44 -0
  158. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/poll-status.py +70 -0
  159. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/reset-board-dir.py +36 -0
  160. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-demo.flow.yaml +26 -0
  161. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-handlers.py +39 -0
  162. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker-pycli.flow.yaml +80 -0
  163. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +25 -172
  164. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +40 -34
  165. package/examples/cli/step-machine-cli/portfolio-tracker/run-inline-python-demo-pycli.py +46 -0
  166. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker-pycli.py +77 -0
  167. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  168. package/examples/example-board/agent-instructions.md +11 -5
  169. package/examples/example-board/demo-chat-handler.js +14 -4
  170. package/examples/example-board/demo-server-config.json +1 -0
  171. package/examples/example-board/demo-server.js +14 -7
  172. package/examples/example-board/demo-shell-browser.html +5 -4
  173. package/examples/example-board/demo-shell-with-server.html +6 -5
  174. package/examples/example-board/demo-task-executor.js +81 -35
  175. package/examples/index.html +0 -14
  176. package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +0 -1
  177. package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  178. package/package.json +39 -3
  179. package/schema/live-cards.schema.json +418 -132
  180. package/dist/cli/board-live-cards-cli.cjs +0 -10650
  181. package/dist/cli/board-live-cards-cli.cjs.map +0 -1
  182. package/dist/cli/board-live-cards-cli.d.cts +0 -179
  183. package/dist/cli/board-live-cards-cli.d.ts +0 -179
  184. package/dist/cli/board-live-cards-cli.js +0 -10598
  185. package/dist/cli/board-live-cards-cli.js.map +0 -1
  186. package/dist/journal-9HEgs7dU.d.ts +0 -28
  187. package/dist/journal-B-JCfQnh.d.cts +0 -28
  188. package/dist/schedule-Cszq9LYY.d.ts +0 -21
  189. package/dist/schedule-qWNL0RQh.d.cts +0 -21
  190. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +0 -22
  191. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +0 -16
  192. package/examples/browser/boards/portfolio-tracker/cards/portfolio-risk-assessment.json +0 -28
  193. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +0 -15
  194. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +0 -15
  195. package/examples/browser/boards/portfolio-tracker/cards/rebalancing-strategy.json +0 -28
  196. package/examples/browser/boards/portfolio-tracker/fetch-prices.js +0 -43
  197. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +0 -96
  198. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +0 -7
  199. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +0 -351
@@ -1,1677 +1,3 @@
1
- var BoardLiveGraph = (function (exports) {
2
- 'use strict';
3
-
4
- var __defProp = Object.defineProperty;
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
- var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
7
-
8
- // jsonata-global-shim:jsonata-shim
9
- var _jsonata = typeof globalThis !== "undefined" && globalThis.jsonata || typeof window !== "undefined" && window.jsonata;
10
- var jsonata_shim_default = _jsonata;
11
-
12
- // src/card-compute/index.ts
13
- function deepGet(obj, path) {
14
- if (!path || !obj) return void 0;
15
- const parts = path.split(".");
16
- let cur = obj;
17
- for (let i = 0; i < parts.length; i++) {
18
- if (cur == null) return void 0;
19
- cur = cur[parts[i]];
20
- }
21
- return cur;
22
- }
23
- function deepSet(obj, path, value) {
24
- const parts = path.split(".");
25
- let cur = obj;
26
- for (let i = 0; i < parts.length - 1; i++) {
27
- if (cur[parts[i]] == null || typeof cur[parts[i]] !== "object") cur[parts[i]] = {};
28
- cur = cur[parts[i]];
29
- }
30
- cur[parts[parts.length - 1]] = value;
31
- }
32
- async function run(node, options) {
33
- if (!node?.compute?.length) return node;
34
- if (!node.card_data) node.card_data = {};
35
- node.computed_values = {};
36
- node._sourcesData = options?.sourcesData ?? {};
37
- const ctx = {
38
- card_data: node.card_data,
39
- requires: node.requires ?? {},
40
- fetched_sources: node._sourcesData,
41
- computed_values: node.computed_values
42
- };
43
- for (const step of node.compute) {
44
- try {
45
- const val = await jsonata_shim_default(step.expr).evaluate(ctx);
46
- deepSet(node.computed_values, step.bindTo, val);
47
- ctx.computed_values = node.computed_values;
48
- } catch (err) {
49
- console.error(`CardCompute.run error on "${node.id ?? "?"}.${step.bindTo}":`, err);
50
- }
51
- }
52
- return node;
53
- }
54
- async function evalExpr(expr, node) {
55
- const ctx = {
56
- card_data: node.card_data ?? {},
57
- requires: node.requires ?? {},
58
- fetched_sources: node._sourcesData ?? {},
59
- computed_values: node.computed_values ?? {}
60
- };
61
- return jsonata_shim_default(expr).evaluate(ctx);
62
- }
63
- function resolve(node, path) {
64
- if (path.startsWith("fetched_sources.")) {
65
- return deepGet(node._sourcesData ?? {}, path.slice("fetched_sources.".length));
66
- }
67
- return deepGet(node, path);
68
- }
69
- var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
70
- "metric",
71
- "table",
72
- "editable-table",
73
- "chart",
74
- "form",
75
- "filter",
76
- "list",
77
- "notes",
78
- "todo",
79
- "alert",
80
- "narrative",
81
- "badge",
82
- "text",
83
- "markdown",
84
- "ref",
85
- "custom",
86
- "actions"
87
- ]);
88
- var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "card_data", "compute", "source_defs"]);
89
- function validateNode(node) {
90
- const errors = [];
91
- if (!node || typeof node !== "object" || Array.isArray(node)) {
92
- return { ok: false, errors: ["Node must be a non-null object"] };
93
- }
94
- const n = node;
95
- if (typeof n.id !== "string" || !n.id) errors.push("id: required, must be a non-empty string");
96
- for (const key of Object.keys(n)) {
97
- if (!ALLOWED_KEYS.has(key)) errors.push(`Unknown top-level key: "${key}"`);
98
- }
99
- if (n.card_data == null || typeof n.card_data !== "object" || Array.isArray(n.card_data)) {
100
- errors.push("card_data: required, must be an object");
101
- }
102
- if (n.meta != null) {
103
- if (typeof n.meta !== "object" || Array.isArray(n.meta)) {
104
- errors.push("meta: must be an object");
105
- } else {
106
- const meta = n.meta;
107
- if (meta.title != null && typeof meta.title !== "string") errors.push("meta.title: must be a string");
108
- if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
109
- }
110
- }
111
- if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
112
- if (n.provides != null) {
113
- if (!Array.isArray(n.provides)) {
114
- errors.push("provides: must be an array of { bindTo, ref } bindings");
115
- } else {
116
- n.provides.forEach((p, i) => {
117
- if (!p || typeof p !== "object" || Array.isArray(p)) {
118
- errors.push(`provides[${i}]: must be an object with bindTo and ref`);
119
- } else {
120
- const b = p;
121
- if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
122
- if (typeof b.ref !== "string" || !b.ref) errors.push(`provides[${i}]: missing required "ref" string`);
123
- }
124
- });
125
- }
126
- }
127
- if (n.compute != null) {
128
- if (!Array.isArray(n.compute)) {
129
- errors.push("compute: must be an array of compute steps");
130
- } else {
131
- n.compute.forEach((step, i) => {
132
- if (!step || typeof step !== "object" || Array.isArray(step)) {
133
- errors.push(`compute[${i}]: must be a compute step object`);
134
- } else {
135
- const s = step;
136
- if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`compute[${i}]: missing required "bindTo" property`);
137
- if (typeof s.expr !== "string" || !s.expr) errors.push(`compute[${i}]: missing required "expr" string (JSONata expression)`);
138
- }
139
- });
140
- }
141
- }
142
- if (n.source_defs != null) {
143
- if (!Array.isArray(n.source_defs)) {
144
- errors.push("source_defs: must be an array");
145
- } else {
146
- const bindTos = /* @__PURE__ */ new Set();
147
- const outputFiles = /* @__PURE__ */ new Set();
148
- n.source_defs.forEach((src, i) => {
149
- if (!src || typeof src !== "object" || Array.isArray(src)) {
150
- errors.push(`source_defs[${i}]: must be an object`);
151
- } else {
152
- const s = src;
153
- if (typeof s.bindTo !== "string" || !s.bindTo) {
154
- errors.push(`source_defs[${i}]: missing required "bindTo" property`);
155
- } else {
156
- if (bindTos.has(s.bindTo)) {
157
- errors.push(`source_defs[${i}]: bindTo "${s.bindTo}" is not unique across source_defs`);
158
- }
159
- bindTos.add(s.bindTo);
160
- }
161
- if (typeof s.outputFile !== "string" || !s.outputFile) {
162
- errors.push(`source_defs[${i}]: missing required "outputFile" property`);
163
- } else {
164
- if (outputFiles.has(s.outputFile)) {
165
- errors.push(`source_defs[${i}]: outputFile "${s.outputFile}" is not unique across source_defs`);
166
- }
167
- outputFiles.add(s.outputFile);
168
- }
169
- if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
170
- errors.push(`source_defs[${i}]: optionalForCompletionGating must be a boolean`);
171
- }
172
- }
173
- });
174
- }
175
- }
176
- if (n.view != null) {
177
- if (typeof n.view !== "object" || Array.isArray(n.view)) {
178
- errors.push("view: must be an object");
179
- } else {
180
- const view = n.view;
181
- if (!Array.isArray(view.elements) || view.elements.length === 0) {
182
- errors.push("view.elements: required, must be a non-empty array");
183
- } else {
184
- view.elements.forEach((elem, i) => {
185
- if (!elem || typeof elem !== "object") {
186
- errors.push(`view.elements[${i}]: must be an object`);
187
- return;
188
- }
189
- if (!elem.kind || typeof elem.kind !== "string") {
190
- errors.push(`view.elements[${i}].kind: required, must be a string`);
191
- } else if (!VALID_ELEMENT_KINDS.has(elem.kind)) {
192
- errors.push(`view.elements[${i}].kind: unknown kind "${elem.kind}". Valid: ${[...VALID_ELEMENT_KINDS].join(", ")}`);
193
- }
194
- if (elem.data != null && (typeof elem.data !== "object" || Array.isArray(elem.data))) {
195
- errors.push(`view.elements[${i}].data: must be an object`);
196
- }
197
- });
198
- }
199
- if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) errors.push("view.layout: must be an object");
200
- if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) errors.push("view.features: must be an object");
201
- }
202
- }
203
- return { ok: errors.length === 0, errors };
204
- }
205
- async function enrichSources(source_defs, context) {
206
- if (!source_defs || source_defs.length === 0) return [];
207
- const evalCtx = {
208
- card_data: context.card_data ?? {},
209
- requires: context.requires ?? {}
210
- };
211
- return Promise.all(
212
- source_defs.map(async (src) => {
213
- const _projections = {};
214
- if (src.projections && typeof src.projections === "object" && !Array.isArray(src.projections)) {
215
- for (const [key, expr] of Object.entries(src.projections)) {
216
- if (typeof expr === "string" && expr.trim().length > 0) {
217
- try {
218
- _projections[key] = await jsonata_shim_default(expr).evaluate(evalCtx);
219
- } catch {
220
- _projections[key] = void 0;
221
- }
222
- }
223
- }
224
- }
225
- return { ...src, _projections };
226
- })
227
- );
228
- }
229
- var CardCompute = {
230
- run,
231
- eval: evalExpr,
232
- resolve,
233
- validate: validateNode,
234
- enrichSources
235
- };
236
-
237
- // src/event-graph/constants.ts
238
- var TASK_STATUS = {
239
- RUNNING: "running",
240
- COMPLETED: "completed",
241
- FAILED: "failed",
242
- INACTIVATED: "inactivated"
243
- };
244
-
245
- // src/event-graph/graph-helpers.ts
246
- function getProvides(task) {
247
- if (!task) return [];
248
- if (Array.isArray(task.provides)) return task.provides;
249
- return [];
250
- }
251
- function getRequires(task) {
252
- if (!task) return [];
253
- if (Array.isArray(task.requires)) return task.requires;
254
- return [];
255
- }
256
- function getAllTasks(graph) {
257
- return graph.tasks ?? {};
258
- }
259
- function isNonActiveTask(taskState) {
260
- if (!taskState) return false;
261
- return taskState.status === TASK_STATUS.FAILED || taskState.status === TASK_STATUS.INACTIVATED;
262
- }
263
- function getRefreshStrategy(taskConfig, graphSettings) {
264
- return taskConfig.refreshStrategy ?? graphSettings?.refreshStrategy ?? "data-changed";
265
- }
266
- function getMaxExecutions(taskConfig) {
267
- return taskConfig.maxExecutions;
268
- }
269
- function computeAvailableOutputs(graph, taskStates) {
270
- const outputs = /* @__PURE__ */ new Set();
271
- for (const [taskName, taskState] of Object.entries(taskStates)) {
272
- if (taskState.status === TASK_STATUS.COMPLETED) {
273
- const taskConfig = graph.tasks[taskName];
274
- if (taskConfig) {
275
- const provides = getProvides(taskConfig);
276
- provides.forEach((output) => outputs.add(output));
277
- }
278
- }
279
- }
280
- return Array.from(outputs);
281
- }
282
- function groupTasksByProvides(candidateTaskNames, tasks) {
283
- const outputGroups = {};
284
- candidateTaskNames.forEach((taskName) => {
285
- const task = tasks[taskName];
286
- if (!task) return;
287
- const provides = getProvides(task);
288
- provides.forEach((output) => {
289
- if (!outputGroups[output]) {
290
- outputGroups[output] = [];
291
- }
292
- outputGroups[output].push(taskName);
293
- });
294
- });
295
- return outputGroups;
296
- }
297
-
298
- // src/event-graph/task-transitions.ts
299
- function applyTaskStart(state, taskName, graph) {
300
- const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore();
301
- const startConsumedHashes = {};
302
- if (graph) {
303
- const taskConfig = graph.tasks[taskName];
304
- const requires = getRequires(taskConfig);
305
- for (const token of requires) {
306
- for (const [otherName, otherConfig] of Object.entries(graph.tasks)) {
307
- if (getProvides(otherConfig).includes(token)) {
308
- const otherState = state.tasks[otherName];
309
- if (otherState?.lastDataHash) startConsumedHashes[token] = otherState.lastDataHash;
310
- break;
311
- }
312
- }
313
- }
314
- }
315
- const updatedTask = {
316
- ...existingTask,
317
- status: "running",
318
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
319
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
320
- progress: 0,
321
- error: void 0,
322
- startConsumedHashes
323
- };
324
- return {
325
- ...state,
326
- tasks: { ...state.tasks, [taskName]: updatedTask },
327
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
328
- };
329
- }
330
- function applyTaskCompletion(state, graph, taskName, result, dataHash, data) {
331
- const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore();
332
- const taskConfig = graph.tasks[taskName];
333
- if (!taskConfig) {
334
- throw new Error(`Task "${taskName}" not found in graph`);
335
- }
336
- let outputTokens;
337
- if (result && taskConfig.on && taskConfig.on[result]) {
338
- outputTokens = taskConfig.on[result];
339
- } else {
340
- outputTokens = getProvides(taskConfig);
341
- }
342
- const lastConsumedHashes = existingTask.startConsumedHashes ? { ...existingTask.startConsumedHashes } : { ...existingTask.lastConsumedHashes };
343
- if (!existingTask.startConsumedHashes) {
344
- const requires = taskConfig.requires ?? [];
345
- for (const token of requires) {
346
- for (const [otherName, otherConfig] of Object.entries(graph.tasks)) {
347
- if (getProvides(otherConfig).includes(token)) {
348
- const otherState = state.tasks[otherName];
349
- if (otherState?.lastDataHash) {
350
- lastConsumedHashes[token] = otherState.lastDataHash;
351
- }
352
- break;
353
- }
354
- }
355
- }
356
- }
357
- const updatedTask = {
358
- ...existingTask,
359
- status: "completed",
360
- completedAt: (/* @__PURE__ */ new Date()).toISOString(),
361
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
362
- executionCount: existingTask.executionCount + 1,
363
- lastEpoch: existingTask.executionCount + 1,
364
- lastDataHash: dataHash,
365
- data,
366
- lastConsumedHashes,
367
- error: void 0
368
- };
369
- const newOutputs = [.../* @__PURE__ */ new Set([...state.availableOutputs, ...outputTokens])];
370
- return {
371
- ...state,
372
- tasks: { ...state.tasks, [taskName]: updatedTask },
373
- availableOutputs: newOutputs,
374
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
375
- };
376
- }
377
- function applyTaskFailure(state, graph, taskName, error) {
378
- const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore();
379
- const taskConfig = graph.tasks[taskName];
380
- if (taskConfig?.retry) {
381
- const retryCount = existingTask.retryCount + 1;
382
- if (retryCount <= taskConfig.retry.max_attempts) {
383
- const updatedTask2 = {
384
- ...existingTask,
385
- status: "not-started",
386
- retryCount,
387
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
388
- error
389
- };
390
- return {
391
- ...state,
392
- tasks: { ...state.tasks, [taskName]: updatedTask2 },
393
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
394
- };
395
- }
396
- }
397
- const updatedTask = {
398
- ...existingTask,
399
- status: "failed",
400
- failedAt: (/* @__PURE__ */ new Date()).toISOString(),
401
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
402
- error,
403
- executionCount: existingTask.executionCount + 1
404
- };
405
- let newOutputs = state.availableOutputs;
406
- if (taskConfig?.on_failure && taskConfig.on_failure.length > 0) {
407
- newOutputs = [.../* @__PURE__ */ new Set([...state.availableOutputs, ...taskConfig.on_failure])];
408
- }
409
- if (taskConfig?.circuit_breaker && updatedTask.executionCount >= taskConfig.circuit_breaker.max_executions) {
410
- const breakTokens = taskConfig.circuit_breaker.on_break;
411
- newOutputs = [.../* @__PURE__ */ new Set([...newOutputs, ...breakTokens])];
412
- }
413
- return {
414
- ...state,
415
- tasks: { ...state.tasks, [taskName]: updatedTask },
416
- availableOutputs: newOutputs,
417
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
418
- };
419
- }
420
- function applyTaskProgress(state, taskName, message, progress) {
421
- const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore();
422
- const updatedTask = {
423
- ...existingTask,
424
- progress: typeof progress === "number" ? progress : existingTask.progress,
425
- messages: [
426
- ...existingTask.messages ?? [],
427
- ...message ? [{ message, timestamp: (/* @__PURE__ */ new Date()).toISOString(), status: existingTask.status }] : []
428
- ],
429
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
430
- };
431
- return {
432
- ...state,
433
- tasks: { ...state.tasks, [taskName]: updatedTask },
434
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
435
- };
436
- }
437
- function applyTaskRestart(state, taskName) {
438
- const existingTask = state.tasks[taskName];
439
- if (!existingTask) return state;
440
- const updatedTask = {
441
- ...existingTask,
442
- status: "not-started",
443
- startedAt: void 0,
444
- completedAt: void 0,
445
- failedAt: void 0,
446
- error: void 0,
447
- data: void 0,
448
- progress: null,
449
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
450
- };
451
- return {
452
- ...state,
453
- tasks: { ...state.tasks, [taskName]: updatedTask },
454
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
455
- };
456
- }
457
- function createDefaultGraphEngineStore() {
458
- return {
459
- status: "not-started",
460
- executionCount: 0,
461
- retryCount: 0,
462
- lastEpoch: 0,
463
- messages: [],
464
- progress: null
465
- };
466
- }
467
-
468
- // src/continuous-event-graph/core.ts
469
- function createLiveGraph(config, executionId) {
470
- const id = executionId ?? `live-${Date.now()}`;
471
- const tasks = {};
472
- for (const taskName of Object.keys(config.tasks)) {
473
- tasks[taskName] = createDefaultGraphEngineStore2();
474
- }
475
- const state = {
476
- status: "running",
477
- tasks,
478
- availableOutputs: [],
479
- stuckDetection: { is_stuck: false, stuck_description: null, outputs_unresolvable: [], tasks_blocked: [] },
480
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
481
- executionId: id,
482
- executionConfig: {
483
- executionMode: config.settings.execution_mode ?? "eligibility-mode",
484
- conflictStrategy: config.settings.conflict_strategy ?? "alphabetical",
485
- completionStrategy: config.settings.completion
486
- }
487
- };
488
- return { config, state };
489
- }
490
- function applyEvent(live, event) {
491
- const { config, state } = live;
492
- if ("executionId" in event && event.executionId && event.executionId !== state.executionId) {
493
- return live;
494
- }
495
- switch (event.type) {
496
- // --- Execution state transitions ---
497
- case "task-started":
498
- return { config, state: applyTaskStart(state, event.taskName, config) };
499
- case "task-completed":
500
- return { config, state: applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash, event.data) };
501
- case "task-failed":
502
- return { config, state: applyTaskFailure(state, config, event.taskName, event.error) };
503
- case "task-progress":
504
- return { config, state: applyTaskProgress(state, event.taskName, event.message, event.progress) };
505
- case "task-restart":
506
- return { config, state: applyTaskRestart(state, event.taskName) };
507
- case "inject-tokens":
508
- return {
509
- config,
510
- state: {
511
- ...state,
512
- availableOutputs: [.../* @__PURE__ */ new Set([...state.availableOutputs, ...event.tokens])],
513
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
514
- }
515
- };
516
- case "agent-action":
517
- return { config, state: applyAgentAction(state, event.action) };
518
- // --- Structural mutations ---
519
- case "task-upsert":
520
- return addNode(live, event.taskName, event.taskConfig);
521
- case "task-removal":
522
- return removeNode(live, event.taskName);
523
- case "node-requires-add":
524
- return addRequires(live, event.nodeName, event.tokens);
525
- case "node-requires-remove":
526
- return removeRequires(live, event.nodeName, event.tokens);
527
- case "node-provides-add":
528
- return addProvides(live, event.nodeName, event.tokens);
529
- case "node-provides-remove":
530
- return removeProvides(live, event.nodeName, event.tokens);
531
- default:
532
- return live;
533
- }
534
- }
535
- function applyEvents(live, events) {
536
- return events.reduce((current, event) => applyEvent(current, event), live);
537
- }
538
- function addNode(live, name, taskConfig) {
539
- const exists = !!live.config.tasks[name];
540
- return {
541
- config: {
542
- ...live.config,
543
- tasks: { ...live.config.tasks, [name]: taskConfig }
544
- },
545
- state: {
546
- ...live.state,
547
- tasks: {
548
- ...live.state.tasks,
549
- [name]: exists ? live.state.tasks[name] : createDefaultGraphEngineStore2()
550
- },
551
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
552
- }
553
- };
554
- }
555
- function removeNode(live, name) {
556
- if (!live.config.tasks[name]) return live;
557
- const { [name]: _removedConfig, ...remainingTasks } = live.config.tasks;
558
- const { [name]: _removedState, ...remainingStates } = live.state.tasks;
559
- return {
560
- config: {
561
- ...live.config,
562
- tasks: remainingTasks
563
- },
564
- state: {
565
- ...live.state,
566
- tasks: remainingStates,
567
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
568
- }
569
- };
570
- }
571
- function addRequires(live, nodeName, tokens) {
572
- const task = live.config.tasks[nodeName];
573
- if (!task) return live;
574
- const current = getRequires(task);
575
- const toAdd = tokens.filter((t) => !current.includes(t));
576
- if (toAdd.length === 0) return live;
577
- return {
578
- config: {
579
- ...live.config,
580
- tasks: {
581
- ...live.config.tasks,
582
- [nodeName]: { ...task, requires: [...current, ...toAdd] }
583
- }
584
- },
585
- state: live.state
586
- };
587
- }
588
- function removeRequires(live, nodeName, tokens) {
589
- const task = live.config.tasks[nodeName];
590
- if (!task) return live;
591
- const current = getRequires(task);
592
- const remaining = current.filter((t) => !tokens.includes(t));
593
- if (remaining.length === current.length) return live;
594
- return {
595
- config: {
596
- ...live.config,
597
- tasks: {
598
- ...live.config.tasks,
599
- [nodeName]: { ...task, requires: remaining }
600
- }
601
- },
602
- state: live.state
603
- };
604
- }
605
- function addProvides(live, nodeName, tokens) {
606
- const task = live.config.tasks[nodeName];
607
- if (!task) return live;
608
- const current = getProvides(task);
609
- const toAdd = tokens.filter((t) => !current.includes(t));
610
- if (toAdd.length === 0) return live;
611
- return {
612
- config: {
613
- ...live.config,
614
- tasks: {
615
- ...live.config.tasks,
616
- [nodeName]: { ...task, provides: [...current, ...toAdd] }
617
- }
618
- },
619
- state: live.state
620
- };
621
- }
622
- function removeProvides(live, nodeName, tokens) {
623
- const task = live.config.tasks[nodeName];
624
- if (!task) return live;
625
- const current = getProvides(task);
626
- const remaining = current.filter((t) => !tokens.includes(t));
627
- if (remaining.length === current.length) return live;
628
- return {
629
- config: {
630
- ...live.config,
631
- tasks: {
632
- ...live.config.tasks,
633
- [nodeName]: { ...task, provides: remaining }
634
- }
635
- },
636
- state: live.state
637
- };
638
- }
639
- function snapshot(live) {
640
- return {
641
- version: 1,
642
- config: live.config,
643
- state: live.state,
644
- snapshotAt: (/* @__PURE__ */ new Date()).toISOString()
645
- };
646
- }
647
- function createDefaultGraphEngineStore2() {
648
- return {
649
- status: "not-started",
650
- executionCount: 0,
651
- retryCount: 0,
652
- lastEpoch: 0,
653
- messages: [],
654
- progress: null
655
- };
656
- }
657
- function applyAgentAction(state, action) {
658
- const now = (/* @__PURE__ */ new Date()).toISOString();
659
- switch (action) {
660
- case "stop":
661
- return { ...state, status: "stopped", lastUpdated: now };
662
- case "pause":
663
- return { ...state, status: "paused", lastUpdated: now };
664
- case "resume":
665
- return { ...state, status: "running", lastUpdated: now };
666
- default:
667
- return state;
668
- }
669
- }
670
-
671
- // src/continuous-event-graph/schedule.ts
672
- function schedule(live) {
673
- const { config, state } = live;
674
- const graphTasks = getAllTasks(config);
675
- const taskNames = Object.keys(graphTasks);
676
- if (taskNames.length === 0) {
677
- return { eligible: [], pending: [], unresolved: [], blocked: [], conflicts: {} };
678
- }
679
- const producerMap = buildProducerMap(graphTasks);
680
- const computedOutputs = computeAvailableOutputs(config, state.tasks);
681
- const availableOutputs = /* @__PURE__ */ new Set([...computedOutputs, ...state.availableOutputs]);
682
- const eligible = [];
683
- const pending = [];
684
- const unresolved = [];
685
- const blocked = [];
686
- for (const [taskName, taskConfig] of Object.entries(graphTasks)) {
687
- const taskState = state.tasks[taskName];
688
- const strategy = getRefreshStrategy(taskConfig, config.settings);
689
- const rerunnable = strategy !== "once";
690
- if (taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
691
- continue;
692
- }
693
- const maxExec = getMaxExecutions(taskConfig);
694
- if (maxExec !== void 0 && taskState && taskState.executionCount >= maxExec) {
695
- continue;
696
- }
697
- if (taskConfig.circuit_breaker && taskState && taskState.executionCount >= taskConfig.circuit_breaker.max_executions) {
698
- continue;
699
- }
700
- if (!rerunnable && taskState?.status === TASK_STATUS.COMPLETED) {
701
- continue;
702
- }
703
- if (rerunnable && taskState?.status === TASK_STATUS.COMPLETED) {
704
- const requires2 = getRequires(taskConfig);
705
- let shouldSkip = false;
706
- switch (strategy) {
707
- case "data-changed": {
708
- if (requires2.length > 0) {
709
- const hasChangedData = requires2.some((req) => {
710
- for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
711
- if (getProvides(otherConfig).includes(req)) {
712
- const otherState = state.tasks[otherName];
713
- if (!otherState) continue;
714
- const consumed = taskState.lastConsumedHashes?.[req];
715
- if (otherState.lastDataHash == null) {
716
- return otherState.executionCount > taskState.lastEpoch;
717
- }
718
- return otherState.lastDataHash !== consumed;
719
- }
720
- }
721
- return false;
722
- });
723
- if (!hasChangedData) shouldSkip = true;
724
- } else {
725
- shouldSkip = true;
726
- }
727
- break;
728
- }
729
- case "epoch-changed": {
730
- if (requires2.length > 0) {
731
- const hasRefreshed = requires2.some((req) => {
732
- for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
733
- if (getProvides(otherConfig).includes(req)) {
734
- const otherState = state.tasks[otherName];
735
- if (otherState && otherState.executionCount > taskState.lastEpoch) return true;
736
- }
737
- }
738
- return false;
739
- });
740
- if (!hasRefreshed) shouldSkip = true;
741
- } else {
742
- shouldSkip = true;
743
- }
744
- break;
745
- }
746
- case "time-based": {
747
- const interval = taskConfig.refreshInterval ?? 0;
748
- if (interval <= 0) {
749
- shouldSkip = true;
750
- break;
751
- }
752
- const completedAt = taskState.completedAt;
753
- if (!completedAt) {
754
- shouldSkip = true;
755
- break;
756
- }
757
- const elapsedSec = (Date.now() - Date.parse(completedAt)) / 1e3;
758
- if (elapsedSec < interval) shouldSkip = true;
759
- break;
760
- }
761
- case "manual":
762
- shouldSkip = true;
763
- break;
764
- }
765
- if (shouldSkip) continue;
766
- }
767
- const requires = getRequires(taskConfig);
768
- if (requires.length === 0) {
769
- eligible.push(taskName);
770
- continue;
771
- }
772
- const missingTokens = [];
773
- const pendingTokens = [];
774
- const failedTokenInfo = [];
775
- for (const token of requires) {
776
- if (availableOutputs.has(token)) continue;
777
- const producers = producerMap[token] || [];
778
- if (producers.length === 0) {
779
- missingTokens.push(token);
780
- } else {
781
- const allFailed = producers.every((p) => isNonActiveTask(state.tasks[p]));
782
- if (allFailed) {
783
- failedTokenInfo.push({ token, failedProducer: producers[0] });
784
- } else {
785
- pendingTokens.push(token);
786
- }
787
- }
788
- }
789
- if (missingTokens.length > 0) {
790
- unresolved.push({ taskName, missingTokens });
791
- } else if (failedTokenInfo.length > 0) {
792
- blocked.push({
793
- taskName,
794
- failedTokens: failedTokenInfo.map((f) => f.token),
795
- failedProducers: [...new Set(failedTokenInfo.map((f) => f.failedProducer))]
796
- });
797
- } else if (pendingTokens.length > 0) {
798
- pending.push({ taskName, waitingOn: pendingTokens });
799
- } else {
800
- eligible.push(taskName);
801
- }
802
- }
803
- const conflicts = {};
804
- if (eligible.length > 1) {
805
- const outputGroups = groupTasksByProvides(eligible, graphTasks);
806
- for (const [outputKey, groupTasks] of Object.entries(outputGroups)) {
807
- if (groupTasks.length > 1) {
808
- conflicts[outputKey] = groupTasks;
809
- }
810
- }
811
- }
812
- return { eligible, pending, unresolved, blocked, conflicts };
813
- }
814
- function buildProducerMap(tasks) {
815
- const map = {};
816
- for (const [name, config] of Object.entries(tasks)) {
817
- for (const token of getProvides(config)) {
818
- if (!map[token]) map[token] = [];
819
- map[token].push(name);
820
- }
821
- if (config.on) {
822
- for (const tokens of Object.values(config.on)) {
823
- for (const token of tokens) {
824
- if (!map[token]) map[token] = [];
825
- if (!map[token].includes(name)) map[token].push(name);
826
- }
827
- }
828
- }
829
- if (config.on_failure) {
830
- for (const token of config.on_failure) {
831
- if (!map[token]) map[token] = [];
832
- if (!map[token].includes(name)) map[token].push(name);
833
- }
834
- }
835
- }
836
- return map;
837
- }
838
-
839
- // src/continuous-event-graph/journal.ts
840
- var MemoryJournal = class {
841
- constructor() {
842
- __publicField(this, "buffer", []);
843
- }
844
- append(event) {
845
- this.buffer.push(event);
846
- }
847
- drain() {
848
- const events = this.buffer;
849
- this.buffer = [];
850
- return events;
851
- }
852
- get size() {
853
- return this.buffer.length;
854
- }
855
- };
856
-
857
- // src/continuous-event-graph/reactive.ts
858
- function computeDataHash(data) {
859
- const json = stableStringify(data);
860
- return fnv1a64Hex(json);
861
- }
862
- function stableStringify(value) {
863
- if (value === null || value === void 0 || typeof value !== "object") {
864
- return JSON.stringify(value);
865
- }
866
- if (Array.isArray(value)) {
867
- return "[" + value.map(stableStringify).join(",") + "]";
868
- }
869
- const obj = value;
870
- const keys = Object.keys(obj).sort();
871
- return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
872
- }
873
- function fnv1a64Hex(input) {
874
- let hash = 0xcbf29ce484222325n;
875
- const prime = 0x100000001b3n;
876
- const mod = 0xffffffffffffffffn;
877
- for (let i = 0; i < input.length; i++) {
878
- hash ^= BigInt(input.charCodeAt(i));
879
- hash = hash * prime & mod;
880
- }
881
- return hash.toString(16).padStart(16, "0");
882
- }
883
- function base64UrlEncode(input) {
884
- if (typeof Buffer !== "undefined") {
885
- return Buffer.from(input, "utf8").toString("base64url");
886
- }
887
- if (typeof btoa === "function") {
888
- const bytes = new TextEncoder().encode(input);
889
- let binary = "";
890
- for (const b of bytes) binary += String.fromCharCode(b);
891
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
892
- }
893
- throw new Error("No base64 encoder available in this runtime");
894
- }
895
- function base64UrlDecode(input) {
896
- if (typeof Buffer !== "undefined") {
897
- return Buffer.from(input, "base64url").toString("utf8");
898
- }
899
- if (typeof atob === "function") {
900
- const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
901
- const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
902
- const binary = atob(padded);
903
- const bytes = new Uint8Array(binary.length);
904
- for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
905
- return new TextDecoder().decode(bytes);
906
- }
907
- throw new Error("No base64 decoder available in this runtime");
908
- }
909
- function encodeCallbackToken(taskName) {
910
- const payload = JSON.stringify({ t: taskName, n: Date.now().toString(36) + Math.random().toString(36).slice(2, 6) });
911
- return base64UrlEncode(payload);
912
- }
913
- function decodeCallbackToken(token) {
914
- try {
915
- const payload = JSON.parse(base64UrlDecode(token));
916
- if (typeof payload?.t === "string") return { taskName: payload.t };
917
- return null;
918
- } catch {
919
- return null;
920
- }
921
- }
922
- function createReactiveGraph(configOrLive, options, executionId) {
923
- const {
924
- handlers: initialHandlers,
925
- onDrain
926
- } = options;
927
- const inputQueue = new MemoryJournal();
928
- let live = "state" in configOrLive && "config" in configOrLive ? configOrLive : createLiveGraph(configOrLive, executionId);
929
- let disposed = false;
930
- const pendingHandlers = /* @__PURE__ */ new Set();
931
- const handlers = new Map(Object.entries(initialHandlers));
932
- const internalJournal = new MemoryJournal();
933
- let draining = false;
934
- let drainQueued = false;
935
- function drain() {
936
- if (disposed) return;
937
- if (draining) {
938
- drainQueued = true;
939
- return;
940
- }
941
- draining = true;
942
- try {
943
- do {
944
- drainQueued = false;
945
- drainOnce();
946
- } while (drainQueued);
947
- } finally {
948
- draining = false;
949
- }
950
- }
951
- function drainOnce() {
952
- const internalEvents = internalJournal.drain();
953
- const inputEvents = inputQueue.drain();
954
- const events = [...internalEvents, ...inputEvents];
955
- if (events.length > 0) {
956
- live = applyEvents(live, events);
957
- }
958
- const result = schedule(live);
959
- if (events.length > 0) {
960
- onDrain?.(events, live, result);
961
- }
962
- for (const taskName of result.eligible) {
963
- dispatchTask(taskName);
964
- }
965
- for (const event of events) {
966
- if (event.type === "task-progress") {
967
- const { taskName, update } = event;
968
- const taskConfig = live.config.tasks[taskName];
969
- if (!taskConfig) continue;
970
- const taskState = live.state.tasks[taskName];
971
- if (!taskState || taskState.status !== "running") continue;
972
- const callbackToken = encodeCallbackToken(taskName);
973
- const p = runPipeline(taskName, callbackToken, update).catch((error) => {
974
- if (disposed) return;
975
- internalJournal.append({
976
- type: "task-failed",
977
- taskName,
978
- error: error.message ?? String(error),
979
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
980
- });
981
- drain();
982
- }).finally(() => {
983
- pendingHandlers.delete(p);
984
- });
985
- pendingHandlers.add(p);
986
- }
987
- }
988
- }
989
- function resolveUpstreamState(taskName) {
990
- const taskConfig = live.config.tasks[taskName];
991
- const requires = taskConfig.requires ?? [];
992
- const tokenToTask = /* @__PURE__ */ new Map();
993
- for (const [name, cfg] of Object.entries(live.config.tasks)) {
994
- for (const token of cfg.provides ?? []) {
995
- tokenToTask.set(token, name);
996
- }
997
- }
998
- const state = {};
999
- for (const token of requires) {
1000
- const producerTask = tokenToTask.get(token);
1001
- if (producerTask) {
1002
- state[token] = live.state.tasks[producerTask]?.data;
1003
- } else {
1004
- state[token] = void 0;
1005
- }
1006
- }
1007
- return state;
1008
- }
1009
- async function runPipeline(taskName, callbackToken, update) {
1010
- const taskConfig = live.config.tasks[taskName];
1011
- const handlerNames = taskConfig.taskHandlers ?? [];
1012
- const upstreamState = resolveUpstreamState(taskName);
1013
- for (const handlerName of handlerNames) {
1014
- const handler = handlers.get(handlerName);
1015
- if (!handler) {
1016
- throw new Error(`Handler '${handlerName}' not found in registry (task '${taskName}')`);
1017
- }
1018
- const input = {
1019
- nodeId: taskName,
1020
- state: upstreamState,
1021
- taskState: live.state.tasks[taskName],
1022
- config: taskConfig,
1023
- callbackToken,
1024
- update
1025
- };
1026
- const status = await handler(input);
1027
- if (status === "task-initiate-failure") {
1028
- throw new Error(`Handler '${handlerName}' returned task-initiate-failure (task '${taskName}')`);
1029
- }
1030
- }
1031
- }
1032
- function dispatchTask(taskName) {
1033
- const taskConfig = live.config.tasks[taskName];
1034
- const handlerNames = taskConfig?.taskHandlers;
1035
- if (!handlerNames || handlerNames.length === 0) {
1036
- return;
1037
- }
1038
- internalJournal.append({
1039
- type: "task-started",
1040
- taskName,
1041
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1042
- });
1043
- drain();
1044
- const callbackToken = encodeCallbackToken(taskName);
1045
- const p = runPipeline(taskName, callbackToken).catch((error) => {
1046
- if (disposed) return;
1047
- internalJournal.append({
1048
- type: "task-failed",
1049
- taskName,
1050
- error: error.message ?? String(error),
1051
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1052
- });
1053
- drain();
1054
- }).finally(() => {
1055
- pendingHandlers.delete(p);
1056
- });
1057
- pendingHandlers.add(p);
1058
- }
1059
- return {
1060
- push(event) {
1061
- if (disposed) return;
1062
- if (event.type === "task-completed" && event.data && !event.dataHash) {
1063
- event = { ...event, dataHash: computeDataHash(event.data) };
1064
- }
1065
- inputQueue.append(event);
1066
- drain();
1067
- },
1068
- pushAll(events) {
1069
- if (disposed) return;
1070
- for (const event of events) {
1071
- if (event.type === "task-completed" && event.data && !event.dataHash) {
1072
- inputQueue.append({ ...event, dataHash: computeDataHash(event.data) });
1073
- } else {
1074
- inputQueue.append(event);
1075
- }
1076
- }
1077
- drain();
1078
- },
1079
- resolveCallback(callbackToken, data, errors) {
1080
- if (disposed) return;
1081
- const decoded = decodeCallbackToken(callbackToken);
1082
- if (!decoded) return;
1083
- const { taskName } = decoded;
1084
- if (!live.config.tasks[taskName]) return;
1085
- if (errors && errors.length > 0) {
1086
- inputQueue.append({
1087
- type: "task-failed",
1088
- taskName,
1089
- error: errors.join("; "),
1090
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1091
- });
1092
- } else {
1093
- const dataHash = data && Object.keys(data).length > 0 ? computeDataHash(data) : void 0;
1094
- inputQueue.append({
1095
- type: "task-completed",
1096
- taskName,
1097
- data,
1098
- dataHash,
1099
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1100
- });
1101
- }
1102
- drain();
1103
- },
1104
- addNode(name, taskConfig) {
1105
- if (disposed) return;
1106
- inputQueue.append({ type: "task-upsert", taskName: name, taskConfig, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1107
- drain();
1108
- },
1109
- removeNode(name) {
1110
- if (disposed) return;
1111
- inputQueue.append({ type: "task-removal", taskName: name, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1112
- drain();
1113
- },
1114
- addRequires(nodeName, tokens) {
1115
- if (disposed) return;
1116
- inputQueue.append({ type: "node-requires-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1117
- drain();
1118
- },
1119
- removeRequires(nodeName, tokens) {
1120
- if (disposed) return;
1121
- inputQueue.append({ type: "node-requires-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1122
- drain();
1123
- },
1124
- addProvides(nodeName, tokens) {
1125
- if (disposed) return;
1126
- inputQueue.append({ type: "node-provides-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1127
- drain();
1128
- },
1129
- removeProvides(nodeName, tokens) {
1130
- if (disposed) return;
1131
- inputQueue.append({ type: "node-provides-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1132
- drain();
1133
- },
1134
- registerHandler(name, fn) {
1135
- handlers.set(name, fn);
1136
- },
1137
- unregisterHandler(name) {
1138
- handlers.delete(name);
1139
- },
1140
- retrigger(taskName) {
1141
- if (disposed) return;
1142
- if (!live.config.tasks[taskName]) return;
1143
- inputQueue.append({
1144
- type: "task-restart",
1145
- taskName,
1146
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1147
- });
1148
- drain();
1149
- },
1150
- retriggerAll(taskNames) {
1151
- if (disposed) return;
1152
- for (const name of taskNames) {
1153
- if (!live.config.tasks[name]) continue;
1154
- inputQueue.append({
1155
- type: "task-restart",
1156
- taskName: name,
1157
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1158
- });
1159
- }
1160
- drain();
1161
- },
1162
- snapshot() {
1163
- return snapshot(live);
1164
- },
1165
- getState() {
1166
- return live;
1167
- },
1168
- getSchedule() {
1169
- return schedule(live);
1170
- },
1171
- async dispose(options2) {
1172
- if (options2?.wait && pendingHandlers.size > 0) {
1173
- await Promise.allSettled([...pendingHandlers]);
1174
- }
1175
- disposed = true;
1176
- }
1177
- };
1178
- }
1179
-
1180
- // src/board-livegraph-runtime/index.ts
1181
- function deepClone(value) {
1182
- return JSON.parse(JSON.stringify(value));
1183
- }
1184
- function toTaskConfig(card) {
1185
- const provides = card.provides && card.provides.length > 0 ? card.provides.map((p) => p.bindTo) : [card.id];
1186
- return {
1187
- requires: card.requires && card.requires.length > 0 ? [...card.requires] : void 0,
1188
- provides,
1189
- taskHandlers: [card.id],
1190
- description: card.meta?.title ?? card.id
1191
- };
1192
- }
1193
- function buildTokenProviders(cards) {
1194
- const tokenToCardId = /* @__PURE__ */ new Map();
1195
- for (const [cardId, card] of cards.entries()) {
1196
- const bindings = card.provides && card.provides.length > 0 ? card.provides : [{ bindTo: cardId, ref: "card_data" }];
1197
- for (const binding of bindings) tokenToCardId.set(binding.bindTo, cardId);
1198
- }
1199
- return tokenToCardId;
1200
- }
1201
- function validateRequires(cards, changedCardId) {
1202
- const tokenProviders = buildTokenProviders(cards);
1203
- const card = cards.get(changedCardId);
1204
- if (!card) return;
1205
- for (const req of card.requires ?? []) {
1206
- if (!tokenProviders.has(req)) {
1207
- throw new Error(`Card "${changedCardId}" requires token "${req}" but no card provides it`);
1208
- }
1209
- }
1210
- }
1211
- var LocalStorageService = {
1212
- // Keys
1213
- CARD_PREFIX: "yf:cards:",
1214
- RUNTIME_OUT_PREFIX: "yf:runtime-out:cards:",
1215
- STATUS_KEY: "yf:runtime-out:status",
1216
- // Read/write cards (mirrors tmp/cards/<id>.json)
1217
- writeCard(cardId, cardObject) {
1218
- try {
1219
- localStorage.setItem(this.CARD_PREFIX + cardId, JSON.stringify(cardObject));
1220
- } catch (e) {
1221
- console.warn(`Failed to write card ${cardId} to localStorage:`, e);
1222
- }
1223
- },
1224
- readCard(cardId) {
1225
- try {
1226
- const raw = localStorage.getItem(this.CARD_PREFIX + cardId);
1227
- return raw ? JSON.parse(raw) : null;
1228
- } catch (e) {
1229
- console.warn(`Failed to read card ${cardId} from localStorage:`, e);
1230
- return null;
1231
- }
1232
- },
1233
- readAllCards(cardIds) {
1234
- const result = {};
1235
- for (const id of cardIds) {
1236
- const card = this.readCard(id);
1237
- if (card) result[id] = card;
1238
- }
1239
- return result;
1240
- },
1241
- // Read/write computed artifacts (mirrors runtime-out/cards/<id>.computed.json)
1242
- writeComputedArtifact(artifact) {
1243
- if (!artifact || !artifact.card_id) return;
1244
- try {
1245
- localStorage.setItem(
1246
- this.RUNTIME_OUT_PREFIX + String(artifact.card_id),
1247
- JSON.stringify(artifact)
1248
- );
1249
- } catch (e) {
1250
- console.warn(`Failed to write computed artifact ${artifact.card_id}:`, e);
1251
- }
1252
- },
1253
- readComputedArtifact(cardId) {
1254
- try {
1255
- const raw = localStorage.getItem(this.RUNTIME_OUT_PREFIX + cardId);
1256
- return raw ? JSON.parse(raw) : null;
1257
- } catch (e) {
1258
- console.warn(`Failed to read computed artifact ${cardId}:`, e);
1259
- return null;
1260
- }
1261
- },
1262
- readAllComputedArtifacts(cardIds) {
1263
- const result = {};
1264
- for (const id of cardIds) {
1265
- const artifact = this.readComputedArtifact(id);
1266
- if (artifact) result[id] = artifact;
1267
- }
1268
- return result;
1269
- },
1270
- // Read/write board status snapshot (mirrors runtime-out/board-livegraph-status.json)
1271
- writeStatusSnapshot(snapshot2) {
1272
- try {
1273
- localStorage.setItem(this.STATUS_KEY, JSON.stringify(snapshot2));
1274
- } catch (e) {
1275
- console.warn("Failed to write status snapshot to localStorage:", e);
1276
- }
1277
- },
1278
- readStatusSnapshot() {
1279
- try {
1280
- const raw = localStorage.getItem(this.STATUS_KEY);
1281
- return raw ? JSON.parse(raw) : null;
1282
- } catch (e) {
1283
- console.warn("Failed to read status snapshot from localStorage:", e);
1284
- return null;
1285
- }
1286
- },
1287
- // Clear all (useful for reset/demo)
1288
- clear() {
1289
- const keysToDelete = [];
1290
- for (let i = 0; i < localStorage.length; i++) {
1291
- const key = localStorage.key(i);
1292
- if (key && (key.startsWith(this.CARD_PREFIX) || key.startsWith(this.RUNTIME_OUT_PREFIX) || key === this.STATUS_KEY)) {
1293
- keysToDelete.push(key);
1294
- }
1295
- }
1296
- for (const key of keysToDelete) {
1297
- localStorage.removeItem(key);
1298
- }
1299
- }
1300
- };
1301
- function createBoardLiveGraphRuntime(input, options = {}) {
1302
- const boardMeta = Array.isArray(input) ? {} : {
1303
- id: input.id,
1304
- title: input.title,
1305
- mode: input.mode,
1306
- positions: input.positions,
1307
- settings: input.settings
1308
- };
1309
- const initialCards = Array.isArray(input) ? input : input.nodes;
1310
- const cards = /* @__PURE__ */ new Map();
1311
- for (const card of initialCards) {
1312
- if (cards.has(card.id)) throw new Error(`Duplicate card ID: "${card.id}"`);
1313
- cards.set(card.id, deepClone(card));
1314
- }
1315
- const listeners = /* @__PURE__ */ new Set();
1316
- const taskExecutor = options.taskExecutor;
1317
- const sourceAdapters = options.sourceAdapters ?? {};
1318
- const defaultSourceAdapter = options.defaultSourceAdapter;
1319
- let graphRef = null;
1320
- const notifyListeners = (events, graph2) => {
1321
- const update = {
1322
- events,
1323
- graph: graph2,
1324
- nodes: getRenderableNodes()
1325
- };
1326
- for (const listener of listeners) listener(update);
1327
- };
1328
- const makeHandler = (cardId) => {
1329
- return async (inputArgs) => {
1330
- const card = cards.get(cardId);
1331
- if (!card) return "task-initiate-failure";
1332
- const requiresData = {};
1333
- for (const token of card.requires ?? []) {
1334
- const upstream = inputArgs.state[token];
1335
- if (!upstream || typeof upstream !== "object") continue;
1336
- const providesData2 = upstream.provides_data;
1337
- if (!providesData2 || typeof providesData2 !== "object") continue;
1338
- if (!Object.prototype.hasOwnProperty.call(providesData2, token)) continue;
1339
- requiresData[token] = providesData2[token];
1340
- }
1341
- const sourcesData = {};
1342
- if (card.source_defs && card.source_defs.length > 0) {
1343
- const adapter = sourceAdapters[cardId] ?? defaultSourceAdapter;
1344
- const fetched = taskExecutor ? await taskExecutor({ card, input: inputArgs }) : adapter ? await adapter({ card, input: inputArgs }) : void 0;
1345
- if (fetched && typeof fetched === "object") {
1346
- for (const src of card.source_defs) {
1347
- if (Object.prototype.hasOwnProperty.call(fetched, src.bindTo)) {
1348
- sourcesData[src.bindTo] = fetched[src.bindTo];
1349
- } else if (card.source_defs.length === 1) {
1350
- sourcesData[src.bindTo] = fetched;
1351
- }
1352
- }
1353
- }
1354
- }
1355
- const computeNode = {
1356
- id: card.id,
1357
- card_data: deepClone(card.card_data ?? {}),
1358
- requires: requiresData,
1359
- source_defs: card.source_defs,
1360
- compute: card.compute
1361
- };
1362
- computeNode._sourcesData = sourcesData;
1363
- if (computeNode.compute && computeNode.compute.length > 0) {
1364
- await CardCompute.run(computeNode, { sourcesData });
1365
- }
1366
- const providesData = {};
1367
- if (card.provides && card.provides.length > 0) {
1368
- for (const { bindTo, ref } of card.provides) {
1369
- providesData[bindTo] = CardCompute.resolve(computeNode, ref);
1370
- }
1371
- } else {
1372
- providesData[card.id] = {
1373
- ...computeNode.card_data ?? {},
1374
- ...computeNode.computed_values ?? {},
1375
- ...computeNode._sourcesData ?? {}
1376
- };
1377
- }
1378
- const resultData = {
1379
- provides_data: providesData,
1380
- card_data: computeNode.card_data ?? {},
1381
- computed_values: computeNode.computed_values ?? {},
1382
- fetched_sources: sourcesData,
1383
- requires: requiresData
1384
- };
1385
- graphRef?.resolveCallback(inputArgs.callbackToken, resultData);
1386
- return "task-initiated";
1387
- };
1388
- };
1389
- const tasks = {};
1390
- const handlers = {};
1391
- for (const [cardId, card] of cards.entries()) {
1392
- validateRequires(cards, cardId);
1393
- tasks[cardId] = toTaskConfig(card);
1394
- handlers[cardId] = makeHandler(cardId);
1395
- }
1396
- const config = {
1397
- id: boardMeta.id ?? `browser-board-${Date.now()}`,
1398
- settings: {
1399
- completion: "manual",
1400
- execution_mode: "eligibility-mode",
1401
- ...boardMeta.settings ?? {},
1402
- ...options.graphSettings ?? {}
1403
- },
1404
- tasks
1405
- };
1406
- const userOnDrain = options.reactiveOptions?.onDrain;
1407
- const graph = createReactiveGraph(
1408
- config,
1409
- {
1410
- ...options.reactiveOptions ?? {},
1411
- handlers,
1412
- onDrain: (events, live, scheduleResult) => {
1413
- userOnDrain?.(events, live, scheduleResult);
1414
- notifyListeners(events, live);
1415
- }
1416
- },
1417
- options.executionId
1418
- );
1419
- graphRef = graph;
1420
- function getRenderableNodes() {
1421
- const live = graph.getState();
1422
- const out = [];
1423
- for (const [cardId, baseCard] of cards.entries()) {
1424
- const data = live.state.tasks[cardId]?.data;
1425
- const runtimeState = live.state.tasks[cardId];
1426
- const mergedCardData = {
1427
- ...baseCard.card_data ?? {},
1428
- ...data && typeof data.card_data === "object" ? data.card_data : {}
1429
- };
1430
- const cardStatus = runtimeState?.status === "running" ? "loading" : runtimeState?.status;
1431
- const cardDataForView = {
1432
- ...mergedCardData,
1433
- ...cardStatus ? { status: cardStatus } : {},
1434
- ...runtimeState?.lastUpdated ? { lastRun: runtimeState.lastUpdated } : {},
1435
- ...runtimeState?.status === "failed" && runtimeState.error ? { error: runtimeState.error } : {}
1436
- };
1437
- out.push({
1438
- id: cardId,
1439
- card: deepClone(baseCard),
1440
- card_data: cardDataForView,
1441
- fetched_sources: data && typeof data.fetched_sources === "object" ? deepClone(data.fetched_sources) : {},
1442
- requires: data && typeof data.requires === "object" ? deepClone(data.requires) : {},
1443
- computed_values: data && typeof data.computed_values === "object" ? deepClone(data.computed_values) : {},
1444
- runtime_state: runtimeState ? deepClone(runtimeState) : {}
1445
- });
1446
- }
1447
- return out;
1448
- }
1449
- const runtime = {
1450
- getGraph: () => graph,
1451
- getState: () => graph.getState(),
1452
- getSchedule: () => graph.getSchedule(),
1453
- getNodes: () => getRenderableNodes(),
1454
- getBoard: () => ({
1455
- ...boardMeta,
1456
- nodes: getRenderableNodes()
1457
- }),
1458
- subscribe(listener) {
1459
- listeners.add(listener);
1460
- listener({ events: [], graph: graph.getState(), nodes: getRenderableNodes() });
1461
- return () => listeners.delete(listener);
1462
- },
1463
- addCard(card) {
1464
- if (cards.has(card.id)) throw new Error(`Card "${card.id}" already exists`);
1465
- cards.set(card.id, deepClone(card));
1466
- validateRequires(cards, card.id);
1467
- graph.registerHandler(card.id, makeHandler(card.id));
1468
- graph.addNode(card.id, toTaskConfig(card));
1469
- },
1470
- upsertCard(card) {
1471
- cards.set(card.id, deepClone(card));
1472
- validateRequires(cards, card.id);
1473
- graph.registerHandler(card.id, makeHandler(card.id));
1474
- graph.addNode(card.id, toTaskConfig(card));
1475
- },
1476
- removeCard(cardId) {
1477
- cards.delete(cardId);
1478
- graph.unregisterHandler(cardId);
1479
- graph.removeNode(cardId);
1480
- },
1481
- patchCardState(cardId, patch) {
1482
- const card = cards.get(cardId);
1483
- if (!card) throw new Error(`Card "${cardId}" not found`);
1484
- card.card_data = { ...card.card_data ?? {}, ...patch };
1485
- graph.retrigger(cardId);
1486
- },
1487
- retrigger(cardId) {
1488
- graph.retrigger(cardId);
1489
- },
1490
- retriggerAll() {
1491
- graph.retriggerAll(Array.from(cards.keys()));
1492
- },
1493
- push(event) {
1494
- graph.push(event);
1495
- },
1496
- pushAll(events) {
1497
- graph.pushAll(events);
1498
- },
1499
- dispose() {
1500
- listeners.clear();
1501
- graph.dispose();
1502
- }
1503
- };
1504
- return runtime;
1505
- }
1506
- function taskStatusToCardStatus(taskStatus) {
1507
- if (taskStatus === "running" || taskStatus === "in-progress") return "loading";
1508
- if (taskStatus === "failed") return "error";
1509
- if (taskStatus === "completed") return "fresh";
1510
- return "fresh";
1511
- }
1512
- function cardStatusToTaskStatus(cardStatus) {
1513
- if (cardStatus === "loading") return "in-progress";
1514
- if (cardStatus === "error") return "failed";
1515
- if (cardStatus === "stale") return "pending";
1516
- if (cardStatus === "fresh") return "completed";
1517
- return "pending";
1518
- }
1519
- function normalizeCardRuntimeArtifact(cardId, artifact) {
1520
- const safe = artifact && typeof artifact === "object" && !Array.isArray(artifact) ? artifact : {};
1521
- return {
1522
- schema_version: safe.schema_version || "v1",
1523
- card_id: typeof safe.card_id === "string" ? safe.card_id : cardId,
1524
- card_data: safe.card_data && typeof safe.card_data === "object" && !Array.isArray(safe.card_data) ? structuredClone(safe.card_data) : {},
1525
- computed_values: safe.computed_values && typeof safe.computed_values === "object" && !Array.isArray(safe.computed_values) ? structuredClone(safe.computed_values) : {},
1526
- fetched_sources: safe.fetched_sources && typeof safe.fetched_sources === "object" && !Array.isArray(safe.fetched_sources) ? structuredClone(safe.fetched_sources) : {},
1527
- requires: safe.requires && typeof safe.requires === "object" && !Array.isArray(safe.requires) ? structuredClone(safe.requires) : {}
1528
- };
1529
- }
1530
- function buildLiveCardModelsFromArtifacts(payload) {
1531
- if (!payload || typeof payload !== "object") throw new Error("payload must be an object");
1532
- const cardDefinitions = Array.isArray(payload.cardDefinitions) ? payload.cardDefinitions : [];
1533
- const statusSnapshot = payload.statusSnapshot && typeof payload.statusSnapshot === "object" ? payload.statusSnapshot : {};
1534
- const cardRuntimeById = payload.cardRuntimeById && typeof payload.cardRuntimeById === "object" ? payload.cardRuntimeById : {};
1535
- const dataObjectsByToken = payload.dataObjectsByToken && typeof payload.dataObjectsByToken === "object" ? payload.dataObjectsByToken : {};
1536
- const statusCards = Array.isArray(statusSnapshot.cards) ? statusSnapshot.cards : [];
1537
- const statusById = new Map(statusCards.map((c) => [c.name, c]));
1538
- return cardDefinitions.map((cardDefinition) => {
1539
- const card = structuredClone(cardDefinition);
1540
- const cardId = card.id;
1541
- if (!cardId) throw new Error("cardDefinitions entry missing id");
1542
- const statusCard = statusById.get(cardId);
1543
- const runtimeArtifact = normalizeCardRuntimeArtifact(cardId, cardRuntimeById[cardId]);
1544
- const baseCardData = card.card_data && typeof card.card_data === "object" && !Array.isArray(card.card_data) ? card.card_data : {};
1545
- const card_data = {
1546
- ...baseCardData,
1547
- ...runtimeArtifact.card_data || {},
1548
- status: taskStatusToCardStatus(statusCard?.status),
1549
- lastRun: statusCard?.runtime?.last_transition_at ?? null
1550
- };
1551
- if (statusCard?.error?.message) card_data["error"] = statusCard.error.message;
1552
- const runtime_state = statusCard ? {
1553
- task_status: statusCard.status ?? null,
1554
- card_status: taskStatusToCardStatus(statusCard.status),
1555
- runtime: structuredClone(statusCard.runtime ?? {}),
1556
- error: statusCard.error ? structuredClone(statusCard.error) : null,
1557
- blocked_by: Array.isArray(statusCard.blocked_by) ? structuredClone(statusCard.blocked_by) : [],
1558
- requires_missing: Array.isArray(statusCard.requires_missing) ? structuredClone(statusCard.requires_missing) : []
1559
- } : {
1560
- task_status: null,
1561
- card_status: card_data["status"] ?? "fresh",
1562
- runtime: { last_transition_at: card_data["lastRun"] ?? null },
1563
- error: card_data["error"] ? { message: card_data["error"] } : null,
1564
- blocked_by: [],
1565
- requires_missing: []
1566
- };
1567
- const requiresTokens = Array.isArray(card.requires) ? card.requires : [];
1568
- const requires = {};
1569
- for (const token of requiresTokens) {
1570
- if (Object.prototype.hasOwnProperty.call(dataObjectsByToken, token)) {
1571
- requires[token] = structuredClone(dataObjectsByToken[token]);
1572
- }
1573
- }
1574
- return {
1575
- id: cardId,
1576
- card,
1577
- card_data,
1578
- fetched_sources: runtimeArtifact.fetched_sources,
1579
- requires,
1580
- computed_values: runtimeArtifact.computed_values,
1581
- runtime_state
1582
- };
1583
- });
1584
- }
1585
- function buildBrowserArtifactsFromRuntime({
1586
- boardPath,
1587
- cardDefinitions,
1588
- runtimeModels,
1589
- graphState
1590
- }) {
1591
- const safeCardDefs = Array.isArray(cardDefinitions) ? cardDefinitions : [];
1592
- const safeModels = Array.isArray(runtimeModels) ? runtimeModels : [];
1593
- const runtimeModelById = new Map(safeModels.map((m) => [m.id, m]));
1594
- const graphStateAny = graphState;
1595
- const taskStates = graphStateAny.state?.tasks ?? {};
1596
- const cardRuntimeById = {};
1597
- for (const model of safeModels) {
1598
- if (!model?.id) continue;
1599
- cardRuntimeById[model.id] = {
1600
- schema_version: "v1",
1601
- card_id: model.id,
1602
- card_data: structuredClone(model.card_data ?? {}),
1603
- computed_values: structuredClone(model.computed_values ?? {}),
1604
- fetched_sources: structuredClone(model.fetched_sources ?? {}),
1605
- requires: structuredClone(model.requires ?? {})
1606
- };
1607
- }
1608
- const dataObjectsByToken = {};
1609
- for (const taskName of Object.keys(taskStates)) {
1610
- const providesData = taskStates[taskName]?.data?.provides_data;
1611
- if (providesData && typeof providesData === "object") {
1612
- for (const token of Object.keys(providesData)) {
1613
- dataObjectsByToken[token] = structuredClone(providesData[token]);
1614
- }
1615
- }
1616
- }
1617
- const statusCards = safeCardDefs.map((cardDef) => {
1618
- const model = runtimeModelById.get(cardDef.id) ?? {};
1619
- const taskState = taskStates[cardDef.id];
1620
- const taskStatus = typeof taskState?.status === "string" ? taskState.status : cardStatusToTaskStatus(model.card_data?.["status"]);
1621
- const errorMessage = typeof taskState?.error === "string" ? taskState.error : typeof model.card_data?.["error"] === "string" ? model.card_data["error"] : null;
1622
- return {
1623
- name: cardDef.id,
1624
- status: taskStatus,
1625
- ...errorMessage ? { error: { message: errorMessage, code: "TASK_FAILED", at: taskState?.failedAt ?? null, source: "browser-runtime" } } : {},
1626
- requires: Array.isArray(cardDef.requires) ? cardDef.requires : [],
1627
- requires_satisfied: [],
1628
- requires_missing: [],
1629
- provides_declared: Array.isArray(cardDef.provides) ? cardDef.provides.map((e) => e.bindTo) : [cardDef.id],
1630
- provides_runtime: Object.keys(taskState?.data?.provides_data ?? {}).sort(),
1631
- blocked_by: [],
1632
- unblocks: [],
1633
- runtime: {
1634
- attempt_count: taskState?.executionCount ?? 0,
1635
- restart_count: taskState?.retryCount ?? 0,
1636
- in_progress_since: taskStatus === "in-progress" ? taskState?.startedAt ?? null : null,
1637
- last_transition_at: taskState?.lastUpdated ?? model.card_data?.["lastRun"] ?? null,
1638
- last_completed_at: taskState?.completedAt ?? null,
1639
- last_restarted_at: taskState?.startedAt ?? null,
1640
- status_age_ms: null
1641
- }
1642
- };
1643
- });
1644
- return {
1645
- cardDefinitions: structuredClone(safeCardDefs),
1646
- cardRuntimeById,
1647
- dataObjectsByToken,
1648
- statusSnapshot: {
1649
- schema_version: "v1",
1650
- meta: { board: { path: boardPath ?? "browser-runtime" } },
1651
- summary: {
1652
- card_count: statusCards.length,
1653
- completed: statusCards.filter((c) => c.status === "completed").length,
1654
- eligible: 0,
1655
- pending: statusCards.filter((c) => c.status === "pending").length,
1656
- blocked: 0,
1657
- unresolved: 0,
1658
- failed: statusCards.filter((c) => c.status === "failed").length,
1659
- in_progress: statusCards.filter((c) => c.status === "in-progress").length,
1660
- orphan_cards: 0,
1661
- topology: { edge_count: 0, max_fan_out_card: null, max_fan_out: 0 }
1662
- },
1663
- cards: statusCards
1664
- }
1665
- };
1666
- }
1667
-
1668
- exports.LocalStorageService = LocalStorageService;
1669
- exports.buildBrowserArtifactsFromRuntime = buildBrowserArtifactsFromRuntime;
1670
- exports.buildLiveCardModelsFromArtifacts = buildLiveCardModelsFromArtifacts;
1671
- exports.createBoardLiveGraphRuntime = createBoardLiveGraphRuntime;
1672
-
1673
- return exports;
1674
-
1675
- })({});
1676
- //# sourceMappingURL=board-livegraph-engine.js.map
1
+ var BoardLiveGraph=(function(exports){'use strict';var Re=Object.defineProperty;var Te=(e,t,r)=>t in e?Re(e,t,{enumerable:true,configurable:true,writable:true,value:r}):e[t]=r;var te=(e,t,r)=>Te(e,t+"",r);var Se=typeof globalThis<"u"&&globalThis.jsonata||typeof window<"u"&&window.jsonata,j=Se;function re(){return function(e){if(e==="./jsonata-sync.cjs")return typeof globalThis<"u"&&globalThis.__jsonataSync||typeof globalThis<"u"&&globalThis.jsonata;throw new Error("Unsupported require in browser bundle: "+e)}}var we=re(),oe=we("./jsonata-sync.cjs")??j;function ne(e,t){if(!t||!e)return;let r=t.split("."),n=e;for(let s=0;s<r.length;s++){if(n==null)return;n=n[r[s]];}return n}function ae(e,t,r){let n=t.split("."),s=e;for(let o=0;o<n.length-1;o++)(s[n[o]]==null||typeof s[n[o]]!="object")&&(s[n[o]]={}),s=s[n[o]];s[n[n.length-1]]=r;}async function Ce(e,t){if(!e?.compute?.length)return e;e.card_data||(e.card_data={}),e.computed_values={},e._sourcesData=t?.sourcesData??{};let r={card_data:e.card_data,requires:e.requires??{},fetched_sources:e._sourcesData,computed_values:e.computed_values};for(let n of e.compute)try{let s=await j(n.expr).evaluate(r);ae(e.computed_values,n.bindTo,s),r.computed_values=e.computed_values;}catch(s){console.error(`CardCompute.run error on "${e.id??"?"}.${n.bindTo}":`,s);}return e}function _e(e,t){if(!e?.compute?.length)return {ok:true,node:e};e.card_data||(e.card_data={}),e.computed_values={},e._sourcesData=t?.sourcesData??{};let r={card_data:e.card_data,requires:e.requires??{},fetched_sources:e._sourcesData,computed_values:e.computed_values};for(let n of e.compute)try{let s=oe(n.expr).evaluate(r);ae(e.computed_values,n.bindTo,s),r.computed_values=e.computed_values;}catch(s){console.error(`CardCompute.runSync error on "${e.id??"?"}.${n.bindTo}":`,s);}return {ok:true,node:e}}async function xe(e,t){let r={card_data:t.card_data??{},requires:t.requires??{},fetched_sources:t._sourcesData??{},computed_values:t.computed_values??{}};return j(e).evaluate(r)}function Ae(e,t){return t.startsWith("fetched_sources.")?ne(e._sourcesData??{},t.slice(16)):ne(e,t)}var se=new Set(["metric","table","editable-table","chart","form","filter","list","notes","todo","alert","narrative","badge","text","markdown","ref","custom","actions"]),Ee=new Set(["id","meta","requires","provides","view","card_data","compute","source_defs"]);function Oe(e){let t=[];if(!e||typeof e!="object"||Array.isArray(e))return {ok:false,errors:["Node must be a non-null object"]};let r=e;(typeof r.id!="string"||!r.id)&&t.push("id: required, must be a non-empty string");for(let n of Object.keys(r))Ee.has(n)||t.push(`Unknown top-level key: "${n}"`);if((r.card_data==null||typeof r.card_data!="object"||Array.isArray(r.card_data))&&t.push("card_data: required, must be an object"),r.meta!=null)if(typeof r.meta!="object"||Array.isArray(r.meta))t.push("meta: must be an object");else {let n=r.meta;n.title!=null&&typeof n.title!="string"&&t.push("meta.title: must be a string"),n.tags!=null&&!Array.isArray(n.tags)&&t.push("meta.tags: must be an array");}if(r.requires!=null&&!Array.isArray(r.requires)&&t.push("requires: must be an array of strings"),r.provides!=null&&(Array.isArray(r.provides)?r.provides.forEach((n,s)=>{if(!n||typeof n!="object"||Array.isArray(n))t.push(`provides[${s}]: must be an object with bindTo and ref`);else {let o=n;(typeof o.bindTo!="string"||!o.bindTo)&&t.push(`provides[${s}]: missing required "bindTo" string`),(typeof o.ref!="string"||!o.ref)&&t.push(`provides[${s}]: missing required "ref" string`);}}):t.push("provides: must be an array of { bindTo, ref } bindings")),r.compute!=null&&(Array.isArray(r.compute)?r.compute.forEach((n,s)=>{if(!n||typeof n!="object"||Array.isArray(n))t.push(`compute[${s}]: must be a compute step object`);else {let o=n;(typeof o.bindTo!="string"||!o.bindTo)&&t.push(`compute[${s}]: missing required "bindTo" property`),(typeof o.expr!="string"||!o.expr)&&t.push(`compute[${s}]: missing required "expr" string (JSONata expression)`);}}):t.push("compute: must be an array of compute steps")),r.source_defs!=null)if(!Array.isArray(r.source_defs))t.push("source_defs: must be an array");else {let n=new Set,s=new Set;r.source_defs.forEach((o,i)=>{if(!o||typeof o!="object"||Array.isArray(o))t.push(`source_defs[${i}]: must be an object`);else {let d=o;typeof d.bindTo!="string"||!d.bindTo?t.push(`source_defs[${i}]: missing required "bindTo" property`):(n.has(d.bindTo)&&t.push(`source_defs[${i}]: bindTo "${d.bindTo}" is not unique across source_defs`),n.add(d.bindTo)),typeof d.outputFile!="string"||!d.outputFile?t.push(`source_defs[${i}]: missing required "outputFile" property`):(s.has(d.outputFile)&&t.push(`source_defs[${i}]: outputFile "${d.outputFile}" is not unique across source_defs`),s.add(d.outputFile)),d.optionalForCompletionGating!=null&&typeof d.optionalForCompletionGating!="boolean"&&t.push(`source_defs[${i}]: optionalForCompletionGating must be a boolean`);}});}if(r.view!=null)if(typeof r.view!="object"||Array.isArray(r.view))t.push("view: must be an object");else {let n=r.view;!Array.isArray(n.elements)||n.elements.length===0?t.push("view.elements: required, must be a non-empty array"):n.elements.forEach((s,o)=>{if(!s||typeof s!="object"){t.push(`view.elements[${o}]: must be an object`);return}!s.kind||typeof s.kind!="string"?t.push(`view.elements[${o}].kind: required, must be a string`):se.has(s.kind)||t.push(`view.elements[${o}].kind: unknown kind "${s.kind}". Valid: ${[...se].join(", ")}`),s.data!=null&&(typeof s.data!="object"||Array.isArray(s.data))&&t.push(`view.elements[${o}].data: must be an object`);}),n.layout!=null&&(typeof n.layout!="object"||Array.isArray(n.layout))&&t.push("view.layout: must be an object"),n.features!=null&&(typeof n.features!="object"||Array.isArray(n.features))&&t.push("view.features: must be an object");}return {ok:t.length===0,errors:t}}async function Ge(e,t){if(!e||e.length===0)return [];let r={card_data:t.card_data??{},requires:t.requires??{}};return Promise.all(e.map(async n=>{let s={};if(n.projections&&typeof n.projections=="object"&&!Array.isArray(n.projections)){for(let[o,i]of Object.entries(n.projections))if(typeof i=="string"&&i.trim().length>0)try{s[o]=await j(i).evaluate(r);}catch{s[o]=void 0;}}return {...n,_projections:s}}))}function Ne(e,t){if(!e||e.length===0)return [];let r={card_data:t.card_data??{},requires:t.requires??{}};return e.map(n=>{let s={};if(n.projections&&typeof n.projections=="object"&&!Array.isArray(n.projections)){for(let[o,i]of Object.entries(n.projections))if(typeof i=="string"&&i.trim().length>0)try{s[o]=oe(i).evaluate(r);}catch{s[o]=void 0;}}return {...n,_projections:s}})}var D={run:Ce,runSync:_e,eval:xe,resolve:Ae,validate:Oe,enrichSources:Ge,enrichSourcesSync:Ne};var G={RUNNING:"running",COMPLETED:"completed",FAILED:"failed",INACTIVATED:"inactivated"};function O(e){return e?Array.isArray(e.provides)?e.provides:[]:[]}function N(e){return e?Array.isArray(e.requires)?e.requires:[]:[]}function H(e){return e.tasks??{}}function P(e){return e?e.status===G.FAILED||e.status===G.INACTIVATED:false}function ie(e,t){return e.refreshStrategy??t?.refreshStrategy??"data-changed"}function ce(e){return e.maxExecutions}function de(e,t){let r=new Set;for(let[n,s]of Object.entries(t))if(s.status===G.COMPLETED){let o=e.tasks[n];o&&O(o).forEach(d=>r.add(d));}return Array.from(r)}function ue(e,t){let r={};return e.forEach(n=>{let s=t[n];if(!s)return;O(s).forEach(i=>{r[i]||(r[i]=[]),r[i].push(n);});}),r}function pe(e,t,r){let n=e.tasks[t]??q(),s={};if(r){let i=r.tasks[t],d=N(i);for(let m of d)for(let[S,y]of Object.entries(r.tasks))if(O(y).includes(m)){let R=e.tasks[S];R?.lastDataHash&&(s[m]=R.lastDataHash);break}}let o={...n,status:"running",startedAt:new Date().toISOString(),lastUpdated:new Date().toISOString(),progress:0,error:void 0,startConsumedHashes:s};return {...e,tasks:{...e.tasks,[t]:o},lastUpdated:new Date().toISOString()}}function fe(e,t,r,n,s,o){let i=e.tasks[r]??q(),d=t.tasks[r];if(!d)throw new Error(`Task "${r}" not found in graph`);let m;n&&d.on&&d.on[n]?m=d.on[n]:m=O(d);let S=i.startConsumedHashes?{...i.startConsumedHashes}:{...i.lastConsumedHashes};if(!i.startConsumedHashes){let g=d.requires??[];for(let p of g)for(let[h,T]of Object.entries(t.tasks))if(O(T).includes(p)){let v=e.tasks[h];v?.lastDataHash&&(S[p]=v.lastDataHash);break}}let y={...i,status:"completed",completedAt:new Date().toISOString(),lastUpdated:new Date().toISOString(),executionCount:i.executionCount+1,lastEpoch:i.executionCount+1,lastDataHash:s,data:o,lastConsumedHashes:S,error:void 0},R=[...new Set([...e.availableOutputs,...m])];return {...e,tasks:{...e.tasks,[r]:y},availableOutputs:R,lastUpdated:new Date().toISOString()}}function le(e,t,r,n){let s=e.tasks[r]??q(),o=t.tasks[r];if(o?.retry){let m=s.retryCount+1;if(m<=o.retry.max_attempts){let S={...s,status:"not-started",retryCount:m,lastUpdated:new Date().toISOString(),error:n};return {...e,tasks:{...e.tasks,[r]:S},lastUpdated:new Date().toISOString()}}}let i={...s,status:"failed",failedAt:new Date().toISOString(),lastUpdated:new Date().toISOString(),error:n,executionCount:s.executionCount+1},d=e.availableOutputs;if(o?.on_failure&&o.on_failure.length>0&&(d=[...new Set([...e.availableOutputs,...o.on_failure])]),o?.circuit_breaker&&i.executionCount>=o.circuit_breaker.max_executions){let m=o.circuit_breaker.on_break;d=[...new Set([...d,...m])];}return {...e,tasks:{...e.tasks,[r]:i},availableOutputs:d,lastUpdated:new Date().toISOString()}}function ge(e,t,r,n){let s=e.tasks[t]??q(),o={...s,progress:typeof n=="number"?n:s.progress,messages:[...s.messages??[],...r?[{message:r,timestamp:new Date().toISOString(),status:s.status}]:[]],lastUpdated:new Date().toISOString()};return {...e,tasks:{...e.tasks,[t]:o},lastUpdated:new Date().toISOString()}}function me(e,t){let r=e.tasks[t];if(!r)return e;let n={...r,status:"not-started",startedAt:void 0,completedAt:void 0,failedAt:void 0,error:void 0,data:void 0,progress:null,lastUpdated:new Date().toISOString()};return {...e,tasks:{...e.tasks,[t]:n},lastUpdated:new Date().toISOString()}}function q(){return {status:"not-started",executionCount:0,retryCount:0,lastEpoch:0,messages:[],progress:null}}function B(e,t){let r=t??`live-${Date.now()}`,n={};for(let o of Object.keys(e.tasks))n[o]=he();let s={status:"running",tasks:n,availableOutputs:[],stuckDetection:{is_stuck:false,stuck_description:null,outputs_unresolvable:[],tasks_blocked:[]},lastUpdated:new Date().toISOString(),executionId:r,executionConfig:{executionMode:e.settings.execution_mode??"eligibility-mode",conflictStrategy:e.settings.conflict_strategy??"alphabetical",completionStrategy:e.settings.completion}};return {config:e,state:s}}function ke(e,t){let{config:r,state:n}=e;if("executionId"in t&&t.executionId&&t.executionId!==n.executionId)return e;switch(t.type){case "task-started":return {config:r,state:pe(n,t.taskName,r)};case "task-completed":return {config:r,state:fe(n,r,t.taskName,t.result,t.dataHash,t.data)};case "task-failed":return {config:r,state:le(n,r,t.taskName,t.error)};case "task-progress":return {config:r,state:ge(n,t.taskName,t.message,t.progress)};case "task-restart":return {config:r,state:me(n,t.taskName)};case "inject-tokens":return {config:r,state:{...n,availableOutputs:[...new Set([...n.availableOutputs,...t.tokens])],lastUpdated:new Date().toISOString()}};case "agent-action":return {config:r,state:Ie(n,t.action)};case "task-upsert":return K(e,t.taskName,t.taskConfig);case "task-removal":return V(e,t.taskName);case "node-requires-add":return W(e,t.nodeName,t.tokens);case "node-requires-remove":return J(e,t.nodeName,t.tokens);case "node-provides-add":return X(e,t.nodeName,t.tokens);case "node-provides-remove":return Y(e,t.nodeName,t.tokens);default:return e}}function M(e,t){return t.reduce((r,n)=>ke(r,n),e)}function K(e,t,r){let n=!!e.config.tasks[t];return {config:{...e.config,tasks:{...e.config.tasks,[t]:r}},state:{...e.state,tasks:{...e.state.tasks,[t]:n?e.state.tasks[t]:he()},lastUpdated:new Date().toISOString()}}}function V(e,t){if(!e.config.tasks[t])return e;let{[t]:r,...n}=e.config.tasks,{[t]:s,...o}=e.state.tasks;return {config:{...e.config,tasks:n},state:{...e.state,tasks:o,lastUpdated:new Date().toISOString()}}}function W(e,t,r){let n=e.config.tasks[t];if(!n)return e;let s=N(n),o=r.filter(i=>!s.includes(i));return o.length===0?e:{config:{...e.config,tasks:{...e.config.tasks,[t]:{...n,requires:[...s,...o]}}},state:e.state}}function J(e,t,r){let n=e.config.tasks[t];if(!n)return e;let s=N(n),o=s.filter(i=>!r.includes(i));return o.length===s.length?e:{config:{...e.config,tasks:{...e.config.tasks,[t]:{...n,requires:o}}},state:e.state}}function X(e,t,r){let n=e.config.tasks[t];if(!n)return e;let s=O(n),o=r.filter(i=>!s.includes(i));return o.length===0?e:{config:{...e.config,tasks:{...e.config.tasks,[t]:{...n,provides:[...s,...o]}}},state:e.state}}function Y(e,t,r){let n=e.config.tasks[t];if(!n)return e;let s=O(n),o=s.filter(i=>!r.includes(i));return o.length===s.length?e:{config:{...e.config,tasks:{...e.config.tasks,[t]:{...n,provides:o}}},state:e.state}}function z(e){return {version:1,config:e.config,state:e.state,snapshotAt:new Date().toISOString()}}function he(){return {status:"not-started",executionCount:0,retryCount:0,lastEpoch:0,messages:[],progress:null}}function Ie(e,t){let r=new Date().toISOString();switch(t){case "stop":return {...e,status:"stopped",lastUpdated:r};case "pause":return {...e,status:"paused",lastUpdated:r};case "resume":return {...e,status:"running",lastUpdated:r};default:return e}}function F(e){let{config:t,state:r}=e,n=H(t);if(Object.keys(n).length===0)return {eligible:[],pending:[],unresolved:[],blocked:[],conflicts:{}};let o=je(n),i=de(t,r.tasks),d=new Set([...i,...r.availableOutputs]),m=[],S=[],y=[],R=[];for(let[p,h]of Object.entries(n)){let T=r.tasks[p],v=ie(h,t.settings),E=v!=="once";if(T?.status===G.RUNNING||P(T))continue;let c=ce(h);if(c!==void 0&&T&&T.executionCount>=c||h.circuit_breaker&&T&&T.executionCount>=h.circuit_breaker.max_executions||!E&&T?.status===G.COMPLETED)continue;if(E&&T?.status===G.COMPLETED){let u=N(h),l=false;switch(v){case "data-changed":{u.length>0&&u.some(C=>{for(let[_,x]of Object.entries(n))if(O(x).includes(C)){let w=r.tasks[_];if(!w)continue;let be=T.lastConsumedHashes?.[C];return w.lastDataHash==null?w.executionCount>T.lastEpoch:w.lastDataHash!==be}return false})||(l=true);break}case "epoch-changed":{u.length>0&&u.some(C=>{for(let[_,x]of Object.entries(n))if(O(x).includes(C)){let w=r.tasks[_];if(w&&w.executionCount>T.lastEpoch)return true}return false})||(l=true);break}case "time-based":{let A=h.refreshInterval??0;if(A<=0){l=true;break}let C=T.completedAt;if(!C){l=true;break}(Date.now()-Date.parse(C))/1e3<A&&(l=true);break}case "manual":l=true;break}if(l)continue}let a=N(h);if(a.length===0){m.push(p);continue}let k=[],f=[],b=[];for(let u of a){if(d.has(u))continue;let l=o[u]||[];l.length===0?k.push(u):l.every(C=>P(r.tasks[C]))?b.push({token:u,failedProducer:l[0]}):f.push(u);}k.length>0?y.push({taskName:p,missingTokens:k}):b.length>0?R.push({taskName:p,failedTokens:b.map(u=>u.token),failedProducers:[...new Set(b.map(u=>u.failedProducer))]}):f.length>0?S.push({taskName:p,waitingOn:f}):m.push(p);}let g={};if(m.length>1){let p=ue(m,n);for(let[h,T]of Object.entries(p))T.length>1&&(g[h]=T);}return {eligible:m,pending:S,unresolved:y,blocked:R,conflicts:g}}function je(e){let t={};for(let[r,n]of Object.entries(e)){for(let s of O(n))t[s]||(t[s]=[]),t[s].push(r);if(n.on)for(let s of Object.values(n.on))for(let o of s)t[o]||(t[o]=[]),t[o].includes(r)||t[o].push(r);if(n.on_failure)for(let s of n.on_failure)t[s]||(t[s]=[]),t[s].includes(r)||t[s].push(r);}return t}var L=class{constructor(){te(this,"buffer",[]);}append(t){this.buffer.push(t);}drain(){let t=this.buffer;return this.buffer=[],t}get size(){return this.buffer.length}};function U(e){let t=Q(e);return Le(t)}function Q(e){if(e==null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return "["+e.map(Q).join(",")+"]";let t=e;return "{"+Object.keys(t).sort().map(n=>JSON.stringify(n)+":"+Q(t[n])).join(",")+"}"}function Le(e){let t=0xcbf29ce484222325n,r=0x100000001b3n,n=0xffffffffffffffffn;for(let s=0;s<e.length;s++)t^=BigInt(e.charCodeAt(s)),t=t*r&n;return t.toString(16).padStart(16,"0")}function De(e){if(typeof Buffer<"u")return Buffer.from(e,"utf8").toString("base64url");if(typeof btoa=="function"){let t=new TextEncoder().encode(e),r="";for(let n of t)r+=String.fromCharCode(n);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}throw new Error("No base64 encoder available in this runtime")}function He(e){if(typeof Buffer<"u")return Buffer.from(e,"base64url").toString("utf8");if(typeof atob=="function"){let t=e.replace(/-/g,"+").replace(/_/g,"/"),r=t+"=".repeat((4-t.length%4)%4),n=atob(r),s=new Uint8Array(n.length);for(let o=0;o<n.length;o++)s[o]=n.charCodeAt(o);return new TextDecoder().decode(s)}throw new Error("No base64 decoder available in this runtime")}function ve(e){let t=JSON.stringify({t:e,n:Date.now().toString(36)+Math.random().toString(36).slice(2,6)});return De(t)}function Pe(e){try{let t=JSON.parse(He(e));return typeof t?.t=="string"?{taskName:t.t}:null}catch{return null}}function $(e,t,r){let{handlers:n,onDrain:s}=t,o=new L,i="state"in e&&"config"in e?e:B(e,r),d=false,m=new Set,S=new Map(Object.entries(n)),y=new L,R=false,g=false;function p(){if(!d){if(R){g=true;return}R=true;try{do g=!1,h();while(g)}finally{R=false;}}}function h(){let c=y.drain(),a=o.drain(),k=[...c,...a];k.length>0&&(i=M(i,k));let f=F(i);k.length>0&&s?.(k,i,f);for(let b of f.eligible)E(b);for(let b of k)if(b.type==="task-progress"){let{taskName:u,update:l}=b;if(!i.config.tasks[u])continue;let C=i.state.tasks[u];if(!C||C.status!=="running")continue;let _=ve(u),x=v(u,_,l).catch(w=>{d||(y.append({type:"task-failed",taskName:u,error:w.message??String(w),timestamp:new Date().toISOString()}),p());}).finally(()=>{m.delete(x);});m.add(x);}}function T(c){let k=i.config.tasks[c].requires??[],f=new Map;for(let[u,l]of Object.entries(i.config.tasks))for(let A of l.provides??[])f.set(A,u);let b={};for(let u of k){let l=f.get(u);l?b[u]=i.state.tasks[l]?.data:b[u]=void 0;}return b}async function v(c,a,k){let f=i.config.tasks[c],b=f.taskHandlers??[],u=T(c);for(let l of b){let A=S.get(l);if(!A)throw new Error(`Handler '${l}' not found in registry (task '${c}')`);let C={nodeId:c,state:u,taskState:i.state.tasks[c],config:f,callbackToken:a,update:k};if(await A(C)==="task-initiate-failure")throw new Error(`Handler '${l}' returned task-initiate-failure (task '${c}')`)}}function E(c){let k=i.config.tasks[c]?.taskHandlers;if(!k||k.length===0)return;y.append({type:"task-started",taskName:c,timestamp:new Date().toISOString()}),p();let f=ve(c),b=v(c,f).catch(u=>{d||(y.append({type:"task-failed",taskName:c,error:u.message??String(u),timestamp:new Date().toISOString()}),p());}).finally(()=>{m.delete(b);});m.add(b);}return {push(c){d||(c.type==="task-completed"&&c.data&&!c.dataHash&&(c={...c,dataHash:U(c.data)}),o.append(c),p());},pushAll(c){if(!d){for(let a of c)a.type==="task-completed"&&a.data&&!a.dataHash?o.append({...a,dataHash:U(a.data)}):o.append(a);p();}},resolveCallback(c,a,k){if(d)return;let f=Pe(c);if(!f)return;let{taskName:b}=f;if(i.config.tasks[b]){if(k&&k.length>0)o.append({type:"task-failed",taskName:b,error:k.join("; "),timestamp:new Date().toISOString()});else {let u=a&&Object.keys(a).length>0?U(a):void 0;o.append({type:"task-completed",taskName:b,data:a,dataHash:u,timestamp:new Date().toISOString()});}p();}},addNode(c,a){d||(o.append({type:"task-upsert",taskName:c,taskConfig:a,timestamp:new Date().toISOString()}),p());},removeNode(c){d||(o.append({type:"task-removal",taskName:c,timestamp:new Date().toISOString()}),p());},addRequires(c,a){d||(o.append({type:"node-requires-add",nodeName:c,tokens:a,timestamp:new Date().toISOString()}),p());},removeRequires(c,a){d||(o.append({type:"node-requires-remove",nodeName:c,tokens:a,timestamp:new Date().toISOString()}),p());},addProvides(c,a){d||(o.append({type:"node-provides-add",nodeName:c,tokens:a,timestamp:new Date().toISOString()}),p());},removeProvides(c,a){d||(o.append({type:"node-provides-remove",nodeName:c,tokens:a,timestamp:new Date().toISOString()}),p());},registerHandler(c,a){S.set(c,a);},unregisterHandler(c){S.delete(c);},retrigger(c){d||i.config.tasks[c]&&(o.append({type:"task-restart",taskName:c,timestamp:new Date().toISOString()}),p());},retriggerAll(c){if(!d){for(let a of c)i.config.tasks[a]&&o.append({type:"task-restart",taskName:a,timestamp:new Date().toISOString()});p();}},snapshot(){return z(i)},getState(){return i},getSchedule(){return F(i)},async waitForHandlers(){m.size>0&&await Promise.allSettled([...m]);},async dispose(c){c?.wait&&m.size>0&&await Promise.allSettled([...m]),d=true;}}}function I(e){return JSON.parse(JSON.stringify(e))}function Z(e){let t=e.provides&&e.provides.length>0?e.provides.map(r=>r.bindTo):[e.id];return {requires:e.requires&&e.requires.length>0?[...e.requires]:void 0,provides:t,taskHandlers:[e.id],description:e.meta?.title??e.id}}function Be(e){let t=new Map;for(let[r,n]of e.entries()){let s=n.provides&&n.provides.length>0?n.provides:[{bindTo:r,ref:"card_data"}];for(let o of s)t.set(o.bindTo,r);}return t}function ee(e,t){let r=Be(e),n=e.get(t);if(n){for(let s of n.requires??[])if(!r.has(s))throw new Error(`Card "${t}" requires token "${s}" but no card provides it`)}}var Rr={CARD_PREFIX:"yf:cards:",RUNTIME_OUT_PREFIX:"yf:runtime-out:cards:",STATUS_KEY:"yf:runtime-out:status",writeCard(e,t){try{localStorage.setItem(this.CARD_PREFIX+e,JSON.stringify(t));}catch(r){console.warn(`Failed to write card ${e} to localStorage:`,r);}},readCard(e){try{let t=localStorage.getItem(this.CARD_PREFIX+e);return t?JSON.parse(t):null}catch(t){return console.warn(`Failed to read card ${e} from localStorage:`,t),null}},readAllCards(e){let t={};for(let r of e){let n=this.readCard(r);n&&(t[r]=n);}return t},writeComputedArtifact(e){if(!(!e||!e.card_id))try{localStorage.setItem(this.RUNTIME_OUT_PREFIX+String(e.card_id),JSON.stringify(e));}catch(t){console.warn(`Failed to write computed artifact ${e.card_id}:`,t);}},readComputedArtifact(e){try{let t=localStorage.getItem(this.RUNTIME_OUT_PREFIX+e);return t?JSON.parse(t):null}catch(t){return console.warn(`Failed to read computed artifact ${e}:`,t),null}},readAllComputedArtifacts(e){let t={};for(let r of e){let n=this.readComputedArtifact(r);n&&(t[r]=n);}return t},writeStatusSnapshot(e){try{localStorage.setItem(this.STATUS_KEY,JSON.stringify(e));}catch(t){console.warn("Failed to write status snapshot to localStorage:",t);}},readStatusSnapshot(){try{let e=localStorage.getItem(this.STATUS_KEY);return e?JSON.parse(e):null}catch(e){return console.warn("Failed to read status snapshot from localStorage:",e),null}},clear(){let e=[];for(let t=0;t<localStorage.length;t++){let r=localStorage.key(t);r&&(r.startsWith(this.CARD_PREFIX)||r.startsWith(this.RUNTIME_OUT_PREFIX)||r===this.STATUS_KEY)&&e.push(r);}for(let t of e)localStorage.removeItem(t);}};function Tr(e,t={}){let r=Array.isArray(e)?{}:{id:e.id,title:e.title,mode:e.mode,positions:e.positions,settings:e.settings},n=Array.isArray(e)?e:e.nodes,s=new Map;for(let a of n){if(s.has(a.id))throw new Error(`Duplicate card ID: "${a.id}"`);s.set(a.id,I(a));}let o=new Set,i=t.taskExecutor,d=t.sourceAdapters??{},m=t.defaultSourceAdapter,S=null,y=(a,k)=>{let f={events:a,graph:k,nodes:E()};for(let b of o)b(f);},R=a=>async k=>{let f=s.get(a);if(!f)return "task-initiate-failure";let b={};for(let _ of f.requires??[]){let x=k.state[_];if(!x||typeof x!="object")continue;let w=x.provides_data;!w||typeof w!="object"||Object.prototype.hasOwnProperty.call(w,_)&&(b[_]=w[_]);}let u={};if(f.source_defs&&f.source_defs.length>0){let _=d[a]??m,x=i?await i({card:f,input:k}):_?await _({card:f,input:k}):void 0;if(x&&typeof x=="object")for(let w of f.source_defs)Object.prototype.hasOwnProperty.call(x,w.bindTo)?u[w.bindTo]=x[w.bindTo]:f.source_defs.length===1&&(u[w.bindTo]=x);}let l={id:f.id,card_data:I(f.card_data??{}),requires:b,source_defs:f.source_defs,compute:f.compute};l._sourcesData=u,l.compute&&l.compute.length>0&&await D.run(l,{sourcesData:u});let A={};if(f.provides&&f.provides.length>0)for(let{bindTo:_,ref:x}of f.provides)A[_]=D.resolve(l,x);else A[f.id]={...l.card_data??{},...l.computed_values??{},...l._sourcesData??{}};let C={provides_data:A,card_data:l.card_data??{},computed_values:l.computed_values??{},fetched_sources:u,requires:b};return S?.resolveCallback(k.callbackToken,C),"task-initiated"},g={},p={};for(let[a,k]of s.entries())ee(s,a),g[a]=Z(k),p[a]=R(a);let h={id:r.id??`browser-board-${Date.now()}`,settings:{completion:"manual",execution_mode:"eligibility-mode",...r.settings??{},...t.graphSettings??{}},tasks:g},T=t.reactiveOptions?.onDrain,v=$(h,{...t.reactiveOptions??{},handlers:p,onDrain:(a,k,f)=>{T?.(a,k,f),y(a,k);}},t.executionId);S=v;function E(){let a=v.getState(),k=[];for(let[f,b]of s.entries()){let u=a.state.tasks[f]?.data,l=a.state.tasks[f],A={...b.card_data??{},...u&&typeof u.card_data=="object"?u.card_data:{}},C=l?.status==="running"?"loading":l?.status,_={...A,...C?{status:C}:{},...l?.lastUpdated?{lastRun:l.lastUpdated}:{},...l?.status==="failed"&&l.error?{error:l.error}:{}};k.push({id:f,card:I(b),card_data:_,fetched_sources:u&&typeof u.fetched_sources=="object"?I(u.fetched_sources):{},requires:u&&typeof u.requires=="object"?I(u.requires):{},computed_values:u&&typeof u.computed_values=="object"?I(u.computed_values):{},runtime_state:l?I(l):{}});}return k}return {getGraph:()=>v,getState:()=>v.getState(),getSchedule:()=>v.getSchedule(),getNodes:()=>E(),getBoard:()=>({...r,nodes:E()}),subscribe(a){return o.add(a),a({events:[],graph:v.getState(),nodes:E()}),()=>o.delete(a)},addCard(a){if(s.has(a.id))throw new Error(`Card "${a.id}" already exists`);s.set(a.id,I(a)),ee(s,a.id),v.registerHandler(a.id,R(a.id)),v.addNode(a.id,Z(a));},upsertCard(a){s.set(a.id,I(a)),ee(s,a.id),v.registerHandler(a.id,R(a.id)),v.addNode(a.id,Z(a));},removeCard(a){s.delete(a),v.unregisterHandler(a),v.removeNode(a);},patchCardState(a,k){let f=s.get(a);if(!f)throw new Error(`Card "${a}" not found`);f.card_data={...f.card_data??{},...k},v.retrigger(a);},retrigger(a){v.retrigger(a);},retriggerAll(){v.retriggerAll(Array.from(s.keys()));},push(a){v.push(a);},pushAll(a){v.pushAll(a);},dispose(){o.clear(),v.dispose();}}}function ye(e){return e==="running"||e==="in-progress"?"loading":e==="failed"?"error":"fresh"}function Ke(e){return e==="loading"?"in-progress":e==="error"?"failed":e==="stale"?"pending":e==="fresh"?"completed":"pending"}function Ve(e,t){let r=t&&typeof t=="object"&&!Array.isArray(t)?t:{};return {schema_version:r.schema_version||"v1",card_id:typeof r.card_id=="string"?r.card_id:e,card_data:r.card_data&&typeof r.card_data=="object"&&!Array.isArray(r.card_data)?structuredClone(r.card_data):{},computed_values:r.computed_values&&typeof r.computed_values=="object"&&!Array.isArray(r.computed_values)?structuredClone(r.computed_values):{},fetched_sources:r.fetched_sources&&typeof r.fetched_sources=="object"&&!Array.isArray(r.fetched_sources)?structuredClone(r.fetched_sources):{},requires:r.requires&&typeof r.requires=="object"&&!Array.isArray(r.requires)?structuredClone(r.requires):{}}}function Sr(e){if(!e||typeof e!="object")throw new Error("payload must be an object");let t=Array.isArray(e.cardDefinitions)?e.cardDefinitions:[],r=e.statusSnapshot&&typeof e.statusSnapshot=="object"?e.statusSnapshot:{},n=e.cardRuntimeById&&typeof e.cardRuntimeById=="object"?e.cardRuntimeById:{},s=e.dataObjectsByToken&&typeof e.dataObjectsByToken=="object"?e.dataObjectsByToken:{},o=Array.isArray(r.cards)?r.cards:[],i=new Map(o.map(d=>[d.name,d]));return t.map(d=>{let m=structuredClone(d),S=m.id;if(!S)throw new Error("cardDefinitions entry missing id");let y=i.get(S),R=Ve(S,n[S]),p={...m.card_data&&typeof m.card_data=="object"&&!Array.isArray(m.card_data)?m.card_data:{},...R.card_data||{},status:ye(y?.status),lastRun:y?.runtime?.last_transition_at??null};y?.error?.message&&(p.error=y.error.message);let h=y?{task_status:y.status??null,card_status:ye(y.status),runtime:structuredClone(y.runtime??{}),error:y.error?structuredClone(y.error):null,blocked_by:Array.isArray(y.blocked_by)?structuredClone(y.blocked_by):[],requires_missing:Array.isArray(y.requires_missing)?structuredClone(y.requires_missing):[]}:{task_status:null,card_status:p.status??"fresh",runtime:{last_transition_at:p.lastRun??null},error:p.error?{message:p.error}:null,blocked_by:[],requires_missing:[]},T=Array.isArray(m.requires)?m.requires:[],v={};for(let E of T)Object.prototype.hasOwnProperty.call(s,E)&&(v[E]=structuredClone(s[E]));return {id:S,card:m,card_data:p,fetched_sources:R.fetched_sources,requires:v,computed_values:R.computed_values,runtime_state:h}})}function wr({boardPath:e,cardDefinitions:t,runtimeModels:r,graphState:n}){let s=Array.isArray(t)?t:[],o=Array.isArray(r)?r:[],i=new Map(o.map(g=>[g.id,g])),m=n.state?.tasks??{},S={};for(let g of o)g?.id&&(S[g.id]={schema_version:"v1",card_id:g.id,card_data:structuredClone(g.card_data??{}),computed_values:structuredClone(g.computed_values??{}),fetched_sources:structuredClone(g.fetched_sources??{}),requires:structuredClone(g.requires??{})});let y={};for(let g of Object.keys(m)){let p=m[g]?.data?.provides_data;if(p&&typeof p=="object")for(let h of Object.keys(p))y[h]=structuredClone(p[h]);}let R=s.map(g=>{let p=i.get(g.id)??{},h=m[g.id],T=typeof h?.status=="string"?h.status:Ke(p.card_data?.status),v=typeof h?.error=="string"?h.error:typeof p.card_data?.error=="string"?p.card_data.error:null;return {name:g.id,status:T,...v?{error:{message:v,code:"TASK_FAILED",at:h?.failedAt??null,source:"browser-runtime"}}:{},requires:Array.isArray(g.requires)?g.requires:[],requires_satisfied:[],requires_missing:[],provides_declared:Array.isArray(g.provides)?g.provides.map(E=>E.bindTo):[g.id],provides_runtime:Object.keys(h?.data?.provides_data??{}).sort(),blocked_by:[],unblocks:[],runtime:{attempt_count:h?.executionCount??0,restart_count:h?.retryCount??0,in_progress_since:T==="in-progress"?h?.startedAt??null:null,last_transition_at:h?.lastUpdated??p.card_data?.lastRun??null,last_completed_at:h?.completedAt??null,last_restarted_at:h?.startedAt??null,status_age_ms:null}}});return {cardDefinitions:structuredClone(s),cardRuntimeById:S,dataObjectsByToken:y,statusSnapshot:{schema_version:"v1",meta:{board:{path:e??"browser-runtime"}},summary:{card_count:R.length,completed:R.filter(g=>g.status==="completed").length,eligible:0,pending:R.filter(g=>g.status==="pending").length,blocked:0,unresolved:0,failed:R.filter(g=>g.status==="failed").length,in_progress:R.filter(g=>g.status==="in-progress").length,orphan_cards:0,topology:{edge_count:0,max_fan_out_card:null,max_fan_out:0}},cards:R}}}
2
+ exports.LocalStorageService=Rr;exports.buildBrowserArtifactsFromRuntime=wr;exports.buildLiveCardModelsFromArtifacts=Sr;exports.createBoardLiveGraphRuntime=Tr;return exports;})({});//# sourceMappingURL=board-livegraph-engine.js.map
1677
3
  //# sourceMappingURL=board-livegraph-engine.js.map