yaml-flow 5.1.0 → 5.2.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 (105) hide show
  1. package/{examples/example-board/reusable-server-runtime.js → board-livecards-server-runtime.js} +42 -20
  2. package/{examples/example-board/reusable-board-runtime-client.js → browser/board-livecards-runtime-client.js} +6 -2
  3. package/browser/{board-livegraph-runtime.js → board-livegraph-engine.js} +212 -16
  4. package/browser/board-livegraph-engine.js.map +1 -0
  5. package/browser/live-cards.js +362 -38
  6. package/browser/live-cards.schema.json +20 -4
  7. package/dist/board-livegraph-runtime/index.cjs +210 -14
  8. package/dist/board-livegraph-runtime/index.cjs.map +1 -1
  9. package/dist/board-livegraph-runtime/index.d.cts +49 -5
  10. package/dist/board-livegraph-runtime/index.d.ts +49 -5
  11. package/dist/board-livegraph-runtime/index.js +209 -15
  12. package/dist/board-livegraph-runtime/index.js.map +1 -1
  13. package/dist/card-compute/index.cjs +63 -7
  14. package/dist/card-compute/index.cjs.map +1 -1
  15. package/dist/card-compute/index.d.cts +2 -2
  16. package/dist/card-compute/index.d.ts +2 -2
  17. package/dist/card-compute/index.js +63 -7
  18. package/dist/card-compute/index.js.map +1 -1
  19. package/dist/cli/board-live-cards-cli.cjs +664 -75
  20. package/dist/cli/board-live-cards-cli.cjs.map +1 -1
  21. package/dist/cli/board-live-cards-cli.d.cts +33 -5
  22. package/dist/cli/board-live-cards-cli.d.ts +33 -5
  23. package/dist/cli/board-live-cards-cli.js +661 -76
  24. package/dist/cli/board-live-cards-cli.js.map +1 -1
  25. package/dist/{constants-ozjf1Ejw.d.cts → constants-BzZUyYlp.d.cts} +1 -1
  26. package/dist/{constants-DuzE5n03.d.ts → constants-oCEbNpul.d.ts} +1 -1
  27. package/dist/continuous-event-graph/index.cjs +47 -14
  28. package/dist/continuous-event-graph/index.cjs.map +1 -1
  29. package/dist/continuous-event-graph/index.d.cts +9 -9
  30. package/dist/continuous-event-graph/index.d.ts +9 -9
  31. package/dist/continuous-event-graph/index.js +47 -14
  32. package/dist/continuous-event-graph/index.js.map +1 -1
  33. package/dist/event-graph/index.cjs +29 -12
  34. package/dist/event-graph/index.cjs.map +1 -1
  35. package/dist/event-graph/index.d.cts +5 -5
  36. package/dist/event-graph/index.d.ts +5 -5
  37. package/dist/event-graph/index.js +29 -12
  38. package/dist/event-graph/index.js.map +1 -1
  39. package/dist/index.cjs +93 -20
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +7 -7
  42. package/dist/index.d.ts +7 -7
  43. package/dist/index.js +93 -20
  44. package/dist/index.js.map +1 -1
  45. package/dist/inference/index.cjs +29 -12
  46. package/dist/inference/index.cjs.map +1 -1
  47. package/dist/inference/index.d.cts +2 -2
  48. package/dist/inference/index.d.ts +2 -2
  49. package/dist/inference/index.js +29 -12
  50. package/dist/inference/index.js.map +1 -1
  51. package/dist/{journal-NLYuqege.d.ts → journal-9HEgs7dU.d.ts} +1 -1
  52. package/dist/{journal-DRfJiheM.d.cts → journal-B-JCfQnh.d.cts} +1 -1
  53. package/dist/{live-cards-bridge-Or7fdEJV.d.ts → live-cards-bridge-CeNxiVcm.d.ts} +6 -2
  54. package/dist/{live-cards-bridge-vGJ6tMzN.d.cts → live-cards-bridge-z_rJCSbi.d.cts} +6 -2
  55. package/dist/{schedule-CMcZe5Ny.d.ts → schedule-Cszq9LYY.d.ts} +1 -1
  56. package/dist/{schedule-CiucyCan.d.cts → schedule-qWNL0RQh.d.cts} +1 -1
  57. package/dist/{types-CMFSIjpc.d.cts → types-BBhqYGhE.d.cts} +4 -0
  58. package/dist/{types-CMFSIjpc.d.ts → types-BBhqYGhE.d.ts} +4 -0
  59. package/dist/{types-BzLD8bjb.d.cts → types-CHSdoAAA.d.cts} +1 -1
  60. package/dist/{types-C2eJ7DAV.d.ts → types-CoW0gQl3.d.ts} +1 -1
  61. package/dist/{validate-DJQTQ6bP.d.ts → validate-BAVzUJWa.d.ts} +1 -1
  62. package/dist/{validate-ke92Cleg.d.cts → validate-Dbu7ygys.d.cts} +1 -1
  63. package/examples/browser/boards/portfolio-tracker/cards/portfolio-risk-assessment.json +28 -0
  64. package/examples/browser/boards/portfolio-tracker/cards/rebalancing-strategy.json +28 -0
  65. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-inference-adapter.js +187 -0
  66. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +139 -5
  67. package/examples/example-board/agent-instructions-cardlayout.md +28 -0
  68. package/examples/example-board/agent-instructions.md +603 -0
  69. package/examples/example-board/cards/card-concentration.json +42 -0
  70. package/examples/example-board/cards/card-market-prices.json +51 -0
  71. package/examples/example-board/cards/card-portfolio-action.json +19 -0
  72. package/examples/example-board/cards/card-portfolio-risks.json +19 -0
  73. package/examples/example-board/cards/card-portfolio-value.json +62 -0
  74. package/examples/example-board/cards/card-portfolio.json +44 -0
  75. package/examples/example-board/demo-chat-handler.js +373 -33
  76. package/examples/example-board/demo-server-config.json +0 -2
  77. package/examples/example-board/demo-server.js +46 -7
  78. package/examples/example-board/demo-shell-browser.html +75 -207
  79. package/examples/example-board/demo-shell-with-server.html +14 -9
  80. package/examples/example-board/demo-shell.html +1 -1
  81. package/examples/example-board/demo-task-executor.js +259 -41
  82. package/package.json +6 -2
  83. package/schema/live-cards.schema.json +20 -4
  84. package/browser/board-livegraph-runtime.js.map +0 -1
  85. package/examples/example-board/board.yaml +0 -23
  86. package/examples/example-board/bootstrap_payload.json +0 -1
  87. package/examples/example-board/cards/card-chain-region-alert.json +0 -39
  88. package/examples/example-board/cards/card-chain-region-totals.json +0 -26
  89. package/examples/example-board/cards/card-chain-top-region.json +0 -24
  90. package/examples/example-board/cards/card-ex-actions.json +0 -32
  91. package/examples/example-board/cards/card-ex-chart.json +0 -30
  92. package/examples/example-board/cards/card-ex-filter.json +0 -36
  93. package/examples/example-board/cards/card-ex-filtered-by-preference.json +0 -59
  94. package/examples/example-board/cards/card-ex-form.json +0 -91
  95. package/examples/example-board/cards/card-ex-list.json +0 -22
  96. package/examples/example-board/cards/card-ex-markdown.json +0 -17
  97. package/examples/example-board/cards/card-ex-metric.json +0 -19
  98. package/examples/example-board/cards/card-ex-narrative.json +0 -36
  99. package/examples/example-board/cards/card-ex-source-http.json +0 -28
  100. package/examples/example-board/cards/card-ex-source.json +0 -21
  101. package/examples/example-board/cards/card-ex-status.json +0 -35
  102. package/examples/example-board/cards/card-ex-table.json +0 -30
  103. package/examples/example-board/cards/card-ex-todo.json +0 -29
  104. package/examples/example-board/mock.db +0 -15
  105. package/examples/example-board/reusable-runtime-artifacts-adapter.js +0 -233
@@ -144,6 +144,9 @@ export function createMultiBoardServerRuntime(options = {}) {
144
144
  const defaultChatHandlerPath = typeof entry.chatHandlerPath === 'string'
145
145
  ? entry.chatHandlerPath
146
146
  : options.defaultChatHandlerPath;
147
+ const defaultInferenceAdapterPath = typeof entry.inferenceAdapterPath === 'string'
148
+ ? entry.inferenceAdapterPath
149
+ : options.defaultInferenceAdapterPath;
147
150
 
148
151
  const service = createExampleBoardServerRuntime({
149
152
  apiBasePath: `${apiBasePath}/${boardId}`,
@@ -156,6 +159,7 @@ export function createMultiBoardServerRuntime(options = {}) {
156
159
  defaultTaskExecutorPath,
157
160
  defaultStepMachineCliPath,
158
161
  defaultChatHandlerPath,
162
+ defaultInferenceAdapterPath,
159
163
  boardLiveCardsCliJs: options.boardLiveCardsCliJs,
160
164
  });
161
165
 
@@ -207,6 +211,9 @@ export function createMultiBoardServerRuntime(options = {}) {
207
211
  const entry = { id, label };
208
212
  if (typeof body.cardsDir === 'string') entry.cardsDir = body.cardsDir;
209
213
  if (typeof body.stepMachineCliPath === 'string') entry.stepMachineCliPath = body.stepMachineCliPath;
214
+ if (typeof body.taskExecutorPath === 'string') entry.taskExecutorPath = body.taskExecutorPath;
215
+ if (typeof body.chatHandlerPath === 'string') entry.chatHandlerPath = body.chatHandlerPath;
216
+ if (typeof body.inferenceAdapterPath === 'string') entry.inferenceAdapterPath = body.inferenceAdapterPath;
210
217
  config.boards.push(entry);
211
218
  writeBoardsConfig(config);
212
219
 
@@ -255,27 +262,17 @@ export function createMultiBoardServerRuntime(options = {}) {
255
262
  return false;
256
263
  }
257
264
 
258
- // Exposed for host transport layers to execute demo-setup for a specific board.
259
- function performDemoSetup(boardId, reset = false) {
265
+ // Exposed so host layers (e.g. demo-server) can reach a board's service and root path.
266
+ // Throws a 404 error if the board is not registered.
267
+ function requireBoardService(boardId) {
260
268
  const config = readBoardsConfig();
261
269
  if (!config.boards.some((b) => b.id === boardId)) {
262
270
  const err = new Error(`Board "${boardId}" not registered`);
263
271
  err.statusCode = 404;
264
272
  throw err;
265
273
  }
266
-
267
- const service = getBoardService(boardId);
268
- let setupPerformed = false;
269
-
270
- if (reset) {
271
- service.demoPrepSetup();
272
- setupPerformed = true;
273
- } else if (!fs.existsSync(service.tmpCardsDir)) {
274
- service.ensureDemoSetup();
275
- setupPerformed = true;
276
- }
277
-
278
- return { ok: true, setupPerformed, reset, tmpCardsDir: service.tmpCardsDir };
274
+ const boardRoot = path.join(setupDir, `board-${boardId}`);
275
+ return { service: getBoardService(boardId), boardRoot };
279
276
  }
280
277
 
281
278
  return {
@@ -287,7 +284,7 @@ export function createMultiBoardServerRuntime(options = {}) {
287
284
  handleBoardsRegistryApi,
288
285
  handleBoardApi,
289
286
  handleApi,
290
- performDemoSetup,
287
+ requireBoardService,
291
288
  };
292
289
  }
293
290
 
@@ -338,6 +335,12 @@ export function createExampleBoardServerRuntime(options = {}) {
338
335
  ? options.defaultChatHandlerPath
339
336
  : path.resolve(process.cwd(), options.defaultChatHandlerPath))
340
337
  : null;
338
+ const configuredInferenceAdapterPath = typeof options.defaultInferenceAdapterPath === 'string'
339
+ && options.defaultInferenceAdapterPath.trim()
340
+ ? (path.isAbsolute(options.defaultInferenceAdapterPath)
341
+ ? options.defaultInferenceAdapterPath
342
+ : path.resolve(process.cwd(), options.defaultInferenceAdapterPath))
343
+ : null;
341
344
 
342
345
  const statusSnapshotFile = path.join(runtimeOutDir, 'board-livegraph-status.json');
343
346
  const boardFile = path.join(boardDir, 'board-graph.json');
@@ -679,18 +682,37 @@ export function createExampleBoardServerRuntime(options = {}) {
679
682
  return resolved;
680
683
  }
681
684
 
682
- function initBoard(taskExecutorPathParam, chatHandlerPathParam) {
685
+ function resolveInferenceAdapterPath(inferenceAdapterPathParam) {
686
+ const raw = typeof inferenceAdapterPathParam === 'string' ? inferenceAdapterPathParam.trim() : '';
687
+ const resolved = raw
688
+ ? (path.isAbsolute(raw) ? raw : path.resolve(__dirname, raw))
689
+ : configuredInferenceAdapterPath;
690
+ if (!resolved) return null;
691
+ if (!fs.existsSync(resolved)) {
692
+ const err = new Error(`Inference adapter script not found: ${resolved}`);
693
+ err.statusCode = 400;
694
+ throw err;
695
+ }
696
+ return resolved;
697
+ }
698
+
699
+ function initBoard(taskExecutorPathParam, chatHandlerPathParam, inferenceAdapterPathParam) {
683
700
  fs.mkdirSync(boardDir, { recursive: true });
684
701
 
685
702
  const taskExecutorPath = resolveTaskExecutorPath(taskExecutorPathParam);
686
703
  const chatHandlerPath = resolveChatHandlerPath(chatHandlerPathParam);
704
+ const inferenceAdapterPath = resolveInferenceAdapterPath(inferenceAdapterPathParam);
687
705
  const taskExecutorCmd = `${shellQuote(process.execPath)} ${shellQuote(taskExecutorPath)}`;
688
706
  const chatHandlerCmd = chatHandlerPath
689
707
  ? `${shellQuote(process.execPath)} ${shellQuote(chatHandlerPath)}`
690
708
  : null;
709
+ const inferenceAdapterCmd = inferenceAdapterPath
710
+ ? `${shellQuote(process.execPath)} ${shellQuote(inferenceAdapterPath)}`
711
+ : null;
691
712
 
692
713
  const initArgs = ['init', boardDir, '--task-executor', taskExecutorCmd];
693
714
  if (chatHandlerCmd) initArgs.push('--chat-handler', chatHandlerCmd);
715
+ if (inferenceAdapterCmd) initArgs.push('--inference-adapter', inferenceAdapterCmd);
694
716
  initArgs.push('--runtime-out', runtimeOutDir);
695
717
 
696
718
  try {
@@ -705,11 +727,11 @@ export function createExampleBoardServerRuntime(options = {}) {
705
727
  }
706
728
  }
707
729
 
708
- function initBoardAndSetup(taskExecutorPathParam, chatHandlerPathParam) {
730
+ function initBoardAndSetup(taskExecutorPathParam, chatHandlerPathParam, inferenceAdapterPathParam) {
709
731
  ensureDemoSetup();
710
732
 
711
733
  if (!fs.existsSync(boardFile)) {
712
- initBoard(taskExecutorPathParam, chatHandlerPathParam);
734
+ initBoard(taskExecutorPathParam, chatHandlerPathParam, inferenceAdapterPathParam);
713
735
  }
714
736
 
715
737
  const expectedCardsRoot = path.resolve(tmpCardsDir);
@@ -721,7 +743,7 @@ export function createExampleBoardServerRuntime(options = {}) {
721
743
 
722
744
  if (hasStaleMapping) {
723
745
  clearDirContents(boardDir);
724
- initBoard(taskExecutorPathParam, chatHandlerPathParam);
746
+ initBoard(taskExecutorPathParam, chatHandlerPathParam, inferenceAdapterPathParam);
725
747
  }
726
748
  }
727
749
 
@@ -19,13 +19,14 @@
19
19
 
20
20
  const fetchServer = options.fetchServer;
21
21
  const boardPaths = options.boardPaths;
22
- const buildLiveCardModelsFromArtifacts = options.buildLiveCardModelsFromArtifacts;
22
+ const buildLiveCardModelsFromArtifacts = options.buildLiveCardModelsFromArtifacts
23
+ || (typeof window !== 'undefined' && window.BoardLiveGraph && window.BoardLiveGraph.buildLiveCardModelsFromArtifacts);
23
24
  const getServerOrigin = options.getServerOrigin;
24
25
 
25
26
  if (typeof fetchServer !== 'function') throw new Error('options.fetchServer is required');
26
27
  if (typeof boardPaths !== 'function') throw new Error('options.boardPaths is required');
27
28
  if (typeof buildLiveCardModelsFromArtifacts !== 'function') {
28
- throw new Error('options.buildLiveCardModelsFromArtifacts is required');
29
+ throw new Error('options.buildLiveCardModelsFromArtifacts is required (or load board-livegraph-engine.js first)');
29
30
  }
30
31
  if (typeof getServerOrigin !== 'function') throw new Error('options.getServerOrigin is required');
31
32
 
@@ -155,6 +156,9 @@
155
156
 
156
157
  const engine = LiveCard.init({
157
158
  resolve: (id) => nodesById[id],
159
+ markdown: (typeof marked !== 'undefined')
160
+ ? (text) => marked.parse(text)
161
+ : null,
158
162
  onPatchState: async (id, patch) => {
159
163
  await fetchServer(paths.patchCard(id), {
160
164
  method: 'PATCH',
@@ -140,13 +140,29 @@ var BoardLiveGraph = (function (exports) {
140
140
  if (!Array.isArray(n.sources)) {
141
141
  errors.push("sources: must be an array");
142
142
  } else {
143
+ const bindTos = /* @__PURE__ */ new Set();
144
+ const outputFiles = /* @__PURE__ */ new Set();
143
145
  n.sources.forEach((src, i) => {
144
146
  if (!src || typeof src !== "object" || Array.isArray(src)) {
145
147
  errors.push(`sources[${i}]: must be an object`);
146
148
  } else {
147
149
  const s = src;
148
- if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`sources[${i}]: missing required "bindTo" property`);
149
- if (s.outputFile != null && typeof s.outputFile !== "string") errors.push(`sources[${i}]: outputFile must be a string`);
150
+ if (typeof s.bindTo !== "string" || !s.bindTo) {
151
+ errors.push(`sources[${i}]: missing required "bindTo" property`);
152
+ } else {
153
+ if (bindTos.has(s.bindTo)) {
154
+ errors.push(`sources[${i}]: bindTo "${s.bindTo}" is not unique across sources`);
155
+ }
156
+ bindTos.add(s.bindTo);
157
+ }
158
+ if (typeof s.outputFile !== "string" || !s.outputFile) {
159
+ errors.push(`sources[${i}]: missing required "outputFile" property`);
160
+ } else {
161
+ if (outputFiles.has(s.outputFile)) {
162
+ errors.push(`sources[${i}]: outputFile "${s.outputFile}" is not unique across sources`);
163
+ }
164
+ outputFiles.add(s.outputFile);
165
+ }
150
166
  if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
151
167
  errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
152
168
  }
@@ -262,15 +278,30 @@ var BoardLiveGraph = (function (exports) {
262
278
  }
263
279
 
264
280
  // src/event-graph/task-transitions.ts
265
- function applyTaskStart(state, taskName) {
281
+ function applyTaskStart(state, taskName, graph) {
266
282
  const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore();
283
+ const startConsumedHashes = {};
284
+ if (graph) {
285
+ const taskConfig = graph.tasks[taskName];
286
+ const requires = getRequires(taskConfig);
287
+ for (const token of requires) {
288
+ for (const [otherName, otherConfig] of Object.entries(graph.tasks)) {
289
+ if (getProvides(otherConfig).includes(token)) {
290
+ const otherState = state.tasks[otherName];
291
+ if (otherState?.lastDataHash) startConsumedHashes[token] = otherState.lastDataHash;
292
+ break;
293
+ }
294
+ }
295
+ }
296
+ }
267
297
  const updatedTask = {
268
298
  ...existingTask,
269
299
  status: "running",
270
300
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
271
301
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
272
302
  progress: 0,
273
- error: void 0
303
+ error: void 0,
304
+ startConsumedHashes
274
305
  };
275
306
  return {
276
307
  ...state,
@@ -290,16 +321,18 @@ var BoardLiveGraph = (function (exports) {
290
321
  } else {
291
322
  outputTokens = getProvides(taskConfig);
292
323
  }
293
- const lastConsumedHashes = { ...existingTask.lastConsumedHashes };
294
- const requires = taskConfig.requires ?? [];
295
- for (const token of requires) {
296
- for (const [otherName, otherConfig] of Object.entries(graph.tasks)) {
297
- if (getProvides(otherConfig).includes(token)) {
298
- const otherState = state.tasks[otherName];
299
- if (otherState?.lastDataHash) {
300
- lastConsumedHashes[token] = otherState.lastDataHash;
324
+ const lastConsumedHashes = existingTask.startConsumedHashes ? { ...existingTask.startConsumedHashes } : { ...existingTask.lastConsumedHashes };
325
+ if (!existingTask.startConsumedHashes) {
326
+ const requires = taskConfig.requires ?? [];
327
+ for (const token of requires) {
328
+ for (const [otherName, otherConfig] of Object.entries(graph.tasks)) {
329
+ if (getProvides(otherConfig).includes(token)) {
330
+ const otherState = state.tasks[otherName];
331
+ if (otherState?.lastDataHash) {
332
+ lastConsumedHashes[token] = otherState.lastDataHash;
333
+ }
334
+ break;
301
335
  }
302
- break;
303
336
  }
304
337
  }
305
338
  }
@@ -444,7 +477,7 @@ var BoardLiveGraph = (function (exports) {
444
477
  switch (event.type) {
445
478
  // --- Execution state transitions ---
446
479
  case "task-started":
447
- return { config, state: applyTaskStart(state, event.taskName) };
480
+ return { config, state: applyTaskStart(state, event.taskName, config) };
448
481
  case "task-completed":
449
482
  return { config, state: applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash, event.data) };
450
483
  case "task-failed":
@@ -1442,12 +1475,175 @@ var BoardLiveGraph = (function (exports) {
1442
1475
  };
1443
1476
  return runtime;
1444
1477
  }
1478
+ function taskStatusToCardStatus(taskStatus) {
1479
+ if (taskStatus === "running" || taskStatus === "in-progress") return "loading";
1480
+ if (taskStatus === "failed") return "error";
1481
+ if (taskStatus === "completed") return "fresh";
1482
+ return "fresh";
1483
+ }
1484
+ function cardStatusToTaskStatus(cardStatus) {
1485
+ if (cardStatus === "loading") return "in-progress";
1486
+ if (cardStatus === "error") return "failed";
1487
+ if (cardStatus === "stale") return "pending";
1488
+ if (cardStatus === "fresh") return "completed";
1489
+ return "pending";
1490
+ }
1491
+ function normalizeCardRuntimeArtifact(cardId, artifact) {
1492
+ const safe = artifact && typeof artifact === "object" && !Array.isArray(artifact) ? artifact : {};
1493
+ return {
1494
+ schema_version: safe.schema_version || "v1",
1495
+ card_id: typeof safe.card_id === "string" ? safe.card_id : cardId,
1496
+ card_data: safe.card_data && typeof safe.card_data === "object" && !Array.isArray(safe.card_data) ? structuredClone(safe.card_data) : {},
1497
+ computed_values: safe.computed_values && typeof safe.computed_values === "object" && !Array.isArray(safe.computed_values) ? structuredClone(safe.computed_values) : {},
1498
+ fetched_sources: safe.fetched_sources && typeof safe.fetched_sources === "object" && !Array.isArray(safe.fetched_sources) ? structuredClone(safe.fetched_sources) : {},
1499
+ requires: safe.requires && typeof safe.requires === "object" && !Array.isArray(safe.requires) ? structuredClone(safe.requires) : {}
1500
+ };
1501
+ }
1502
+ function buildLiveCardModelsFromArtifacts(payload) {
1503
+ if (!payload || typeof payload !== "object") throw new Error("payload must be an object");
1504
+ const cardDefinitions = Array.isArray(payload.cardDefinitions) ? payload.cardDefinitions : [];
1505
+ const statusSnapshot = payload.statusSnapshot && typeof payload.statusSnapshot === "object" ? payload.statusSnapshot : {};
1506
+ const cardRuntimeById = payload.cardRuntimeById && typeof payload.cardRuntimeById === "object" ? payload.cardRuntimeById : {};
1507
+ const dataObjectsByToken = payload.dataObjectsByToken && typeof payload.dataObjectsByToken === "object" ? payload.dataObjectsByToken : {};
1508
+ const statusCards = Array.isArray(statusSnapshot.cards) ? statusSnapshot.cards : [];
1509
+ const statusById = new Map(statusCards.map((c) => [c.name, c]));
1510
+ return cardDefinitions.map((cardDefinition) => {
1511
+ const card = structuredClone(cardDefinition);
1512
+ const cardId = card.id;
1513
+ if (!cardId) throw new Error("cardDefinitions entry missing id");
1514
+ const statusCard = statusById.get(cardId);
1515
+ const runtimeArtifact = normalizeCardRuntimeArtifact(cardId, cardRuntimeById[cardId]);
1516
+ const baseCardData = card.card_data && typeof card.card_data === "object" && !Array.isArray(card.card_data) ? card.card_data : {};
1517
+ const card_data = {
1518
+ ...baseCardData,
1519
+ ...runtimeArtifact.card_data || {},
1520
+ status: taskStatusToCardStatus(statusCard?.status),
1521
+ lastRun: statusCard?.runtime?.last_transition_at ?? null
1522
+ };
1523
+ if (statusCard?.error?.message) card_data["error"] = statusCard.error.message;
1524
+ const runtime_state = statusCard ? {
1525
+ task_status: statusCard.status ?? null,
1526
+ card_status: taskStatusToCardStatus(statusCard.status),
1527
+ runtime: structuredClone(statusCard.runtime ?? {}),
1528
+ error: statusCard.error ? structuredClone(statusCard.error) : null,
1529
+ blocked_by: Array.isArray(statusCard.blocked_by) ? structuredClone(statusCard.blocked_by) : [],
1530
+ requires_missing: Array.isArray(statusCard.requires_missing) ? structuredClone(statusCard.requires_missing) : []
1531
+ } : {
1532
+ task_status: null,
1533
+ card_status: card_data["status"] ?? "fresh",
1534
+ runtime: { last_transition_at: card_data["lastRun"] ?? null },
1535
+ error: card_data["error"] ? { message: card_data["error"] } : null,
1536
+ blocked_by: [],
1537
+ requires_missing: []
1538
+ };
1539
+ const requiresTokens = Array.isArray(card.requires) ? card.requires : [];
1540
+ const requires = {};
1541
+ for (const token of requiresTokens) {
1542
+ if (Object.prototype.hasOwnProperty.call(dataObjectsByToken, token)) {
1543
+ requires[token] = structuredClone(dataObjectsByToken[token]);
1544
+ }
1545
+ }
1546
+ return {
1547
+ id: cardId,
1548
+ card,
1549
+ card_data,
1550
+ fetched_sources: runtimeArtifact.fetched_sources,
1551
+ requires,
1552
+ computed_values: runtimeArtifact.computed_values,
1553
+ runtime_state
1554
+ };
1555
+ });
1556
+ }
1557
+ function buildBrowserArtifactsFromRuntime({
1558
+ boardPath,
1559
+ cardDefinitions,
1560
+ runtimeModels,
1561
+ graphState
1562
+ }) {
1563
+ const safeCardDefs = Array.isArray(cardDefinitions) ? cardDefinitions : [];
1564
+ const safeModels = Array.isArray(runtimeModels) ? runtimeModels : [];
1565
+ const runtimeModelById = new Map(safeModels.map((m) => [m.id, m]));
1566
+ const graphStateAny = graphState;
1567
+ const taskStates = graphStateAny.state?.tasks ?? {};
1568
+ const cardRuntimeById = {};
1569
+ for (const model of safeModels) {
1570
+ if (!model?.id) continue;
1571
+ cardRuntimeById[model.id] = {
1572
+ schema_version: "v1",
1573
+ card_id: model.id,
1574
+ card_data: structuredClone(model.card_data ?? {}),
1575
+ computed_values: structuredClone(model.computed_values ?? {}),
1576
+ fetched_sources: structuredClone(model.fetched_sources ?? {}),
1577
+ requires: structuredClone(model.requires ?? {})
1578
+ };
1579
+ }
1580
+ const dataObjectsByToken = {};
1581
+ for (const taskName of Object.keys(taskStates)) {
1582
+ const providesData = taskStates[taskName]?.data?.provides_data;
1583
+ if (providesData && typeof providesData === "object") {
1584
+ for (const token of Object.keys(providesData)) {
1585
+ dataObjectsByToken[token] = structuredClone(providesData[token]);
1586
+ }
1587
+ }
1588
+ }
1589
+ const statusCards = safeCardDefs.map((cardDef) => {
1590
+ const model = runtimeModelById.get(cardDef.id) ?? {};
1591
+ const taskState = taskStates[cardDef.id];
1592
+ const taskStatus = typeof taskState?.status === "string" ? taskState.status : cardStatusToTaskStatus(model.card_data?.["status"]);
1593
+ const errorMessage = typeof taskState?.error === "string" ? taskState.error : typeof model.card_data?.["error"] === "string" ? model.card_data["error"] : null;
1594
+ return {
1595
+ name: cardDef.id,
1596
+ status: taskStatus,
1597
+ ...errorMessage ? { error: { message: errorMessage, code: "TASK_FAILED", at: taskState?.failedAt ?? null, source: "browser-runtime" } } : {},
1598
+ requires: Array.isArray(cardDef.requires) ? cardDef.requires : [],
1599
+ requires_satisfied: [],
1600
+ requires_missing: [],
1601
+ provides_declared: Array.isArray(cardDef.provides) ? cardDef.provides.map((e) => e.bindTo) : [cardDef.id],
1602
+ provides_runtime: Object.keys(taskState?.data?.provides_data ?? {}).sort(),
1603
+ blocked_by: [],
1604
+ unblocks: [],
1605
+ runtime: {
1606
+ attempt_count: taskState?.executionCount ?? 0,
1607
+ restart_count: taskState?.retryCount ?? 0,
1608
+ in_progress_since: taskStatus === "in-progress" ? taskState?.startedAt ?? null : null,
1609
+ last_transition_at: taskState?.lastUpdated ?? model.card_data?.["lastRun"] ?? null,
1610
+ last_completed_at: taskState?.completedAt ?? null,
1611
+ last_restarted_at: taskState?.startedAt ?? null,
1612
+ status_age_ms: null
1613
+ }
1614
+ };
1615
+ });
1616
+ return {
1617
+ cardDefinitions: structuredClone(safeCardDefs),
1618
+ cardRuntimeById,
1619
+ dataObjectsByToken,
1620
+ statusSnapshot: {
1621
+ schema_version: "v1",
1622
+ meta: { board: { path: boardPath ?? "browser-runtime" } },
1623
+ summary: {
1624
+ card_count: statusCards.length,
1625
+ completed: statusCards.filter((c) => c.status === "completed").length,
1626
+ eligible: 0,
1627
+ pending: statusCards.filter((c) => c.status === "pending").length,
1628
+ blocked: 0,
1629
+ unresolved: 0,
1630
+ failed: statusCards.filter((c) => c.status === "failed").length,
1631
+ in_progress: statusCards.filter((c) => c.status === "in-progress").length,
1632
+ orphan_cards: 0,
1633
+ topology: { edge_count: 0, max_fan_out_card: null, max_fan_out: 0 }
1634
+ },
1635
+ cards: statusCards
1636
+ }
1637
+ };
1638
+ }
1445
1639
 
1446
1640
  exports.LocalStorageService = LocalStorageService;
1641
+ exports.buildBrowserArtifactsFromRuntime = buildBrowserArtifactsFromRuntime;
1642
+ exports.buildLiveCardModelsFromArtifacts = buildLiveCardModelsFromArtifacts;
1447
1643
  exports.createBoardLiveGraphRuntime = createBoardLiveGraphRuntime;
1448
1644
 
1449
1645
  return exports;
1450
1646
 
1451
1647
  })({});
1452
- //# sourceMappingURL=board-livegraph-runtime.js.map
1453
- //# sourceMappingURL=board-livegraph-runtime.js.map
1648
+ //# sourceMappingURL=board-livegraph-engine.js.map
1649
+ //# sourceMappingURL=board-livegraph-engine.js.map