yaml-flow 4.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/browser/board-livegraph-runtime.js +1453 -0
  2. package/browser/board-livegraph-runtime.js.map +1 -0
  3. package/browser/card-compute.js +36 -17
  4. package/browser/live-cards.js +848 -109
  5. package/browser/live-cards.schema.json +46 -21
  6. package/dist/board-livegraph-runtime/index.cjs +1448 -0
  7. package/dist/board-livegraph-runtime/index.cjs.map +1 -0
  8. package/dist/board-livegraph-runtime/index.d.cts +101 -0
  9. package/dist/board-livegraph-runtime/index.d.ts +101 -0
  10. package/dist/board-livegraph-runtime/index.js +1441 -0
  11. package/dist/board-livegraph-runtime/index.js.map +1 -0
  12. package/dist/card-compute/index.cjs +159 -44
  13. package/dist/card-compute/index.cjs.map +1 -1
  14. package/dist/card-compute/index.d.cts +36 -11
  15. package/dist/card-compute/index.d.ts +36 -11
  16. package/dist/card-compute/index.js +156 -44
  17. package/dist/card-compute/index.js.map +1 -1
  18. package/dist/cli/board-live-cards-cli.cjs +476 -105
  19. package/dist/cli/board-live-cards-cli.cjs.map +1 -1
  20. package/dist/cli/board-live-cards-cli.d.cts +8 -16
  21. package/dist/cli/board-live-cards-cli.d.ts +8 -16
  22. package/dist/cli/board-live-cards-cli.js +476 -106
  23. package/dist/cli/board-live-cards-cli.js.map +1 -1
  24. package/dist/continuous-event-graph/index.cjs +74 -33
  25. package/dist/continuous-event-graph/index.cjs.map +1 -1
  26. package/dist/continuous-event-graph/index.d.cts +7 -23
  27. package/dist/continuous-event-graph/index.d.ts +7 -23
  28. package/dist/continuous-event-graph/index.js +73 -32
  29. package/dist/continuous-event-graph/index.js.map +1 -1
  30. package/dist/index.cjs +1440 -56
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +21 -3
  33. package/dist/index.d.ts +21 -3
  34. package/dist/index.js +1434 -56
  35. package/dist/index.js.map +1 -1
  36. package/dist/journal-DRfJiheM.d.cts +28 -0
  37. package/dist/journal-NLYuqege.d.ts +28 -0
  38. package/dist/{journal-B_2JnBMF.d.ts → live-cards-bridge-Or7fdEJV.d.ts} +5 -32
  39. package/dist/{journal-BJDjWb5Q.d.cts → live-cards-bridge-vGJ6tMzN.d.cts} +5 -32
  40. package/dist/schedule-CMcZe5Ny.d.ts +21 -0
  41. package/dist/schedule-CiucyCan.d.cts +21 -0
  42. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +1 -1
  43. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +3 -3
  44. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +1 -1
  45. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +3 -3
  46. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
  47. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +33 -5
  48. package/examples/browser/livecards-browser/index.html +37 -684
  49. package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
  50. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +3 -3
  51. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
  52. package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +3 -3
  53. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +2 -2
  54. package/examples/example-board/board.yaml +23 -0
  55. package/examples/example-board/bootstrap_payload.json +1 -0
  56. package/examples/example-board/cards/card-chain-region-alert.json +39 -0
  57. package/examples/example-board/cards/card-chain-region-totals.json +26 -0
  58. package/examples/example-board/cards/card-chain-top-region.json +24 -0
  59. package/examples/example-board/cards/card-ex-actions.json +32 -0
  60. package/examples/example-board/cards/card-ex-chart.json +30 -0
  61. package/examples/example-board/cards/card-ex-filter.json +36 -0
  62. package/examples/example-board/cards/card-ex-filtered-by-preference.json +59 -0
  63. package/examples/example-board/cards/card-ex-form.json +91 -0
  64. package/examples/example-board/cards/card-ex-list.json +22 -0
  65. package/examples/example-board/cards/card-ex-markdown.json +17 -0
  66. package/examples/example-board/cards/card-ex-metric.json +19 -0
  67. package/examples/example-board/cards/card-ex-narrative.json +36 -0
  68. package/examples/example-board/cards/card-ex-source-http.json +28 -0
  69. package/examples/example-board/cards/card-ex-source.json +21 -0
  70. package/examples/example-board/cards/card-ex-status.json +35 -0
  71. package/examples/example-board/cards/card-ex-table.json +30 -0
  72. package/examples/example-board/cards/card-ex-todo.json +29 -0
  73. package/examples/example-board/demo-chat-handler.js +69 -0
  74. package/examples/example-board/demo-server.js +87 -0
  75. package/examples/example-board/demo-shell-browser.html +806 -0
  76. package/examples/example-board/demo-shell-with-server.html +280 -0
  77. package/examples/example-board/demo-shell.html +62 -0
  78. package/examples/example-board/demo-task-executor.js +255 -0
  79. package/examples/example-board/mock.db +15 -0
  80. package/examples/example-board/reusable-board-runtime-client.js +265 -0
  81. package/examples/example-board/reusable-runtime-artifacts-adapter.js +233 -0
  82. package/examples/example-board/reusable-server-runtime.js +1284 -0
  83. package/examples/index.html +16 -9
  84. package/examples/npm-libs/continuous-event-graph/live-cards-board.ts +17 -17
  85. package/examples/npm-libs/continuous-event-graph/live-portfolio-dashboard.ts +23 -23
  86. package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
  87. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +3 -3
  88. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
  89. package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +1 -1
  90. package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
  91. package/package.json +16 -2
  92. package/schema/card-runtime.schema.json +25 -0
  93. package/schema/live-cards.schema.json +46 -21
  94. package/browser/ingest-board.js +0 -296
  95. package/examples/ingest.js +0 -733
@@ -350,15 +350,15 @@
350
350
  </div>
351
351
  <div class="section-body">
352
352
  <div class="quickstart-grid">
353
- <article class="card example-card" data-surface="browser" data-model="livecards" data-search="livecards browser demo board canvas interactive renderer open browser/livecards-browser/index.html">
353
+ <article class="card example-card" data-surface="browser" data-model="livecards" data-search="livecards example board demo shell board canvas interactive renderer open example-board/demo-shell.html">
354
354
  <div class="chip-row">
355
355
  <span class="chip">Browser</span>
356
356
  <span class="chip">LiveCards</span>
357
357
  <span class="chip starter">Starter</span>
358
358
  </div>
359
- <h3><a href="browser/livecards-browser/index.html">LiveCards browser demo</a></h3>
360
- <p>Fastest way to see the LiveCards browser renderer, element kinds, and board/canvas views in one place.</p>
361
- <div class="command"><code>Open browser/livecards-browser/index.html</code><button class="copy-btn" data-copy="browser/livecards-browser/index.html">Copy path</button></div>
359
+ <h3><a href="example-board/demo-shell.html">LiveCards example board demo</a></h3>
360
+ <p>Fastest way to see the maintained LiveCards browser renderer, board/canvas views, refresh flows, and JSONata-backed example cards in one place.</p>
361
+ <div class="command"><code>Open example-board/demo-shell.html</code><button class="copy-btn" data-copy="example-board/demo-shell.html">Copy path</button></div>
362
362
  </article>
363
363
 
364
364
  <article class="card example-card" data-surface="browser" data-model="step-machine" data-search="step machine browser demo flowengine open browser/step-machine-browser/index.html">
@@ -440,11 +440,11 @@
440
440
  </div>
441
441
  <div class="section-body">
442
442
  <div class="example-grid">
443
- <article class="example-card" data-surface="browser" data-model="livecards" data-search="livecards browser demo page interactive board canvas showcase">
443
+ <article class="example-card" data-surface="browser" data-model="livecards" data-search="livecards example board demo shell interactive board canvas showcase">
444
444
  <div class="chip-row"><span class="chip">Browser</span><span class="chip">LiveCards</span></div>
445
- <h3><a href="browser/livecards-browser/index.html">LiveCards Browser Demo</a></h3>
446
- <p>Interactive showcase for the browser runtime, including board/canvas views, element demos, and API reference material.</p>
447
- <div class="command"><code>Open browser/livecards-browser/index.html</code><button class="copy-btn" data-copy="browser/livecards-browser/index.html">Copy path</button></div>
445
+ <h3><a href="example-board/demo-shell.html">LiveCards Example Board Demo</a></h3>
446
+ <p>Interactive example-board shell for the browser runtime, including board/canvas views, refresh flows, and compute-backed example cards.</p>
447
+ <div class="command"><code>Open example-board/demo-shell.html</code><button class="copy-btn" data-copy="example-board/demo-shell.html">Copy path</button></div>
448
448
  </article>
449
449
 
450
450
  <article class="example-card" data-surface="browser" data-model="step-machine" data-search="step machine browser greeting demo flowengine inlined">
@@ -460,6 +460,13 @@
460
460
  <p>Node-driven portfolio tracker demo that exercises end-to-end board-live-cards orchestration for a browser-facing board workflow.</p>
461
461
  <div class="command"><code>node examples/browser/boards/portfolio-tracker/portfolio-tracker.js</code><button class="copy-btn" data-copy="node examples/browser/boards/portfolio-tracker/portfolio-tracker.js">Copy</button></div>
462
462
  </article>
463
+
464
+ <article class="example-card" data-surface="browser" data-model="livecards" data-search="portfolio tracker task-executor external source cli delegation custom">
465
+ <div class="chip-row"><span class="chip">Browser support</span><span class="chip">LiveCards</span><span class="chip">Task-Executor</span></div>
466
+ <h3>Portfolio Tracker with Task-Executor</h3>
467
+ <p>Portfolio tracker with external source execution via task-executor. Demonstrates delegating source.cli execution to a custom executor script.</p>
468
+ <div class="command"><code>node examples/browser/boards/portfolio-tracker/portfolio-tracker.js --task-executor "node C:\path\to\portfolio-tracker-task-executor.cjs"</code><button class="copy-btn" data-copy="node examples/browser/boards/portfolio-tracker/portfolio-tracker.js --task-executor &quot;node C:\path\to\portfolio-tracker-task-executor.cjs&quot;">Copy</button></div>
469
+ </article>
463
470
  </div>
464
471
  </div>
465
472
  </section>
@@ -699,7 +706,7 @@
699
706
  </tr>
700
707
  </thead>
701
708
  <tbody>
702
- <tr data-surface="browser" data-model="livecards"><td><a href="browser/livecards-browser/index.html"><code>examples/browser/livecards-browser/index.html</code></a></td><td>Browser</td><td>LiveCards</td><td><code>Open browser/livecards-browser/index.html</code></td><td>Interactive board/canvas renderer showcase</td></tr>
709
+ <tr data-surface="browser" data-model="livecards"><td><a href="example-board/demo-shell.html"><code>examples/example-board/demo-shell.html</code></a></td><td>Browser</td><td>LiveCards</td><td><code>Open example-board/demo-shell.html</code></td><td>Maintained example-board browser demo for board/canvas rendering and compute-backed cards</td></tr>
703
710
  <tr data-surface="browser" data-model="step-machine"><td><a href="browser/step-machine-browser/index.html"><code>examples/browser/step-machine-browser/index.html</code></a></td><td>Browser</td><td>Step Machine</td><td><code>Open browser/step-machine-browser/index.html</code></td><td>Simple browser-side step-machine demo</td></tr>
704
711
  <tr data-surface="browser" data-model="livecards"><td><code>examples/browser/boards/portfolio-tracker/portfolio-tracker.js</code></td><td>Browser support</td><td>LiveCards</td><td><code>node examples/browser/boards/portfolio-tracker/portfolio-tracker.js</code></td><td>End-to-end board-live-cards portfolio driver</td></tr>
705
712
  <tr data-surface="cli" data-model="step-machine"><td><code>examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat</code></td><td>CLI</td><td>Step Machine</td><td><code>run-portfolio-tracker.bat</code></td><td>Portfolio tracker YAML flow orchestration</td></tr>
@@ -36,31 +36,31 @@ const cards: LiveCard[] = [
36
36
  id: 'market-feed',
37
37
  type: 'source',
38
38
  meta: { title: 'Live Market Prices' },
39
- state: { prices: [142.5, 305.8, 89.2, 211.0, 178.3] },
40
- source: { kind: 'static', bindTo: 'state.prices' },
39
+ card_data: { prices: [142.5, 305.8, 89.2, 211.0, 178.3] },
40
+ source: { kind: 'static', bindTo: 'card_data.prices' },
41
41
  },
42
42
  {
43
43
  id: 'stats',
44
44
  type: 'card',
45
45
  meta: { title: 'Price Statistics' },
46
- state: {},
46
+ card_data: {},
47
47
  data: { requires: ['market-feed'] },
48
48
  compute: {
49
- total: { fn: 'sum', input: 'state.market-feed.prices' },
50
- avg: { fn: 'avg', input: 'state.market-feed.prices' },
51
- count: { fn: 'count', input: 'state.market-feed.prices' },
49
+ total: { fn: 'sum', input: 'sources.market-feed.prices' },
50
+ avg: { fn: 'avg', input: 'sources.market-feed.prices' },
51
+ count: { fn: 'count', input: 'sources.market-feed.prices' },
52
52
  },
53
53
  },
54
54
  {
55
55
  id: 'summary',
56
56
  type: 'card',
57
57
  meta: { title: 'Summary Label' },
58
- state: {},
58
+ card_data: {},
59
59
  data: { requires: ['stats'] },
60
60
  compute: {
61
61
  label: {
62
62
  fn: 'template',
63
- input: 'state.stats',
63
+ input: 'computed_values.stats',
64
64
  format: '{{count}} stocks — total ${{total}}, avg ${{avg}}',
65
65
  },
66
66
  },
@@ -115,37 +115,37 @@ const board: LiveBoard = {
115
115
  id: 'equity-feed',
116
116
  type: 'source',
117
117
  meta: { title: 'Equity Prices' },
118
- state: {},
119
- source: { kind: 'api', bindTo: 'state.raw', url_template: 'https://api.example.com/equity' },
118
+ card_data: {},
119
+ source: { kind: 'api', bindTo: 'card_data.raw', url_template: 'https://api.example.com/equity' },
120
120
  },
121
121
  {
122
122
  id: 'bond-feed',
123
123
  type: 'source',
124
124
  meta: { title: 'Bond Yields' },
125
- state: { yields: [3.2, 4.1, 2.8, 5.0] },
126
- source: { kind: 'static', bindTo: 'state.yields' },
125
+ card_data: { yields: [3.2, 4.1, 2.8, 5.0] },
126
+ source: { kind: 'static', bindTo: 'card_data.yields' },
127
127
  },
128
128
  {
129
129
  id: 'portfolio-mix',
130
130
  type: 'card',
131
131
  meta: { title: 'Portfolio Mix Calculator' },
132
- state: {},
132
+ card_data: {},
133
133
  data: { requires: ['equity-feed', 'bond-feed'] },
134
134
  compute: {
135
- equity_total: { fn: 'sum', input: 'state.equity-feed.prices' },
136
- bond_total: { fn: 'sum', input: 'state.bond-feed.yields' },
135
+ equity_total: { fn: 'sum', input: 'sources.equity-feed.prices' },
136
+ bond_total: { fn: 'sum', input: 'sources.bond-feed.yields' },
137
137
  },
138
138
  },
139
139
  {
140
140
  id: 'risk-summary',
141
141
  type: 'card',
142
142
  meta: { title: 'Risk Summary' },
143
- state: {},
143
+ card_data: {},
144
144
  data: { requires: ['portfolio-mix'] },
145
145
  compute: {
146
146
  label: {
147
147
  fn: 'template',
148
- input: 'state.portfolio-mix',
148
+ input: 'computed_values.portfolio-mix',
149
149
  format: 'Equities: ${{equity_total}} | Bonds: {{bond_total}}%',
150
150
  },
151
151
  },
@@ -69,8 +69,8 @@ const cards: LiveCard[] = [
69
69
  {
70
70
  id: 'holdings', type: 'source',
71
71
  meta: { title: 'Portfolio Holdings' },
72
- data: { provides: { holdings: 'state.holdings' } },
73
- state: {
72
+ data: { provides: { holdings: 'card_data.holdings' } },
73
+ card_data: {
74
74
  holdings: [
75
75
  { symbol: 'AAPL', shares: 50, sector: 'tech' },
76
76
  { symbol: 'MSFT', shares: 30, sector: 'tech' },
@@ -83,13 +83,13 @@ const cards: LiveCard[] = [
83
83
  {
84
84
  id: 'price-feed', type: 'source',
85
85
  meta: { title: 'Live Price Feed' },
86
- data: { provides: { prices: 'state.prices' } },
87
- state: { prices: { AAPL: 195.50, MSFT: 420.10, GOOG: 176.30, JPM: 198.20, JNJ: 155.80 } },
86
+ data: { provides: { prices: 'card_data.prices' } },
87
+ card_data: { prices: { AAPL: 195.50, MSFT: 420.10, GOOG: 176.30, JPM: 198.20, JNJ: 155.80 } },
88
88
  },
89
89
  {
90
90
  id: 'news-feed', type: 'source',
91
91
  meta: { title: 'Market News Feed' },
92
- state: {
92
+ card_data: {
93
93
  headlines: [
94
94
  { symbol: 'AAPL', headline: 'Apple beats Q4 estimates', sentiment: 0.8 },
95
95
  { symbol: 'JPM', headline: 'JPMorgan raises dividend', sentiment: 0.6 },
@@ -100,32 +100,32 @@ const cards: LiveCard[] = [
100
100
  {
101
101
  id: 'benchmark', type: 'source',
102
102
  meta: { title: 'S&P 500 Benchmark' },
103
- state: { index: 'SPY', value: 5280.50, dailyReturn: 0.45 },
103
+ card_data: { index: 'SPY', value: 5280.50, dailyReturn: 0.45 },
104
104
  },
105
105
  // Compute cards
106
106
  {
107
107
  id: 'valuator', type: 'card',
108
108
  meta: { title: 'Position Valuator' },
109
109
  data: { requires: ['holdings', 'price-feed'] },
110
- state: {},
110
+ card_data: {},
111
111
  },
112
112
  {
113
113
  id: 'portfolio-value', type: 'card',
114
114
  meta: { title: 'Total Portfolio Value' },
115
115
  data: { requires: ['valuator'] },
116
- state: {},
116
+ card_data: {},
117
117
  },
118
118
  {
119
119
  id: 'sector-breakdown', type: 'card',
120
120
  meta: { title: 'Sector Breakdown' },
121
121
  data: { requires: ['valuator'] },
122
- state: {},
122
+ card_data: {},
123
123
  },
124
124
  {
125
125
  id: 'sentiment', type: 'card',
126
126
  meta: { title: 'News Sentiment Score' },
127
127
  data: { requires: ['news-feed'] },
128
- state: {},
128
+ card_data: {},
129
129
  },
130
130
  ];
131
131
 
@@ -144,7 +144,7 @@ function makeHandler(
144
144
  const result = computeFn(graphRef!.getState());
145
145
  try {
146
146
  const diskCard = readCard(dir, id);
147
- diskCard.state = { ...diskCard.state, ...result };
147
+ diskCard.card_data = { ...diskCard.card_data, ...result };
148
148
  writeCard(dir, diskCard);
149
149
  } catch { /* card may not exist yet */ }
150
150
  graphRef!.resolveCallback(input.callbackToken, result);
@@ -225,7 +225,7 @@ async function main() {
225
225
  if (taskState.data && Object.keys(taskState.data).length > 0) {
226
226
  try {
227
227
  const diskCard = readCard(tmpDir, taskName);
228
- diskCard.state = { ...diskCard.state, ...taskState.data };
228
+ diskCard.card_data = { ...diskCard.card_data, ...taskState.data };
229
229
  writeCard(tmpDir, diskCard);
230
230
  } catch { /* not on disk yet */ }
231
231
  }
@@ -251,7 +251,7 @@ async function main() {
251
251
  log('PHASE 2', 'Adding 7 dynamic cards → 15 total');
252
252
 
253
253
  addDynamicCard(rg, tmpDir, {
254
- id: 'allocation-chart', type: 'card', data: { requires: ['valuator', 'portfolio-value'] }, state: {},
254
+ id: 'allocation-chart', type: 'card', data: { requires: ['valuator', 'portfolio-value'] }, card_data: {},
255
255
  }, (e) => {
256
256
  const pos = (e.state.tasks.valuator?.data as any)?.positions ?? [];
257
257
  const tot = (e.state.tasks['portfolio-value']?.data as any)?.totalValue ?? 0;
@@ -259,7 +259,7 @@ async function main() {
259
259
  }, { requires: ['valuator', 'portfolio-value'] });
260
260
 
261
261
  addDynamicCard(rg, tmpDir, {
262
- id: 'risk-score', type: 'card', data: { requires: ['valuator'] }, state: {},
262
+ id: 'risk-score', type: 'card', data: { requires: ['valuator'] }, card_data: {},
263
263
  }, (e) => {
264
264
  const pos = (e.state.tasks.valuator?.data as any)?.positions ?? [];
265
265
  const vals = pos.map((p: any) => p.value);
@@ -269,7 +269,7 @@ async function main() {
269
269
  }, { requires: ['valuator'] });
270
270
 
271
271
  addDynamicCard(rg, tmpDir, {
272
- id: 'daily-pnl', type: 'card', data: { requires: ['portfolio-value', 'benchmark'] }, state: {},
272
+ id: 'daily-pnl', type: 'card', data: { requires: ['portfolio-value', 'benchmark'] }, card_data: {},
273
273
  }, (e) => {
274
274
  const tv = (e.state.tasks['portfolio-value']?.data as any)?.totalValue ?? 0;
275
275
  const benchReturn = (e.state.tasks.benchmark?.data as any)?.dailyReturn ?? 0;
@@ -278,14 +278,14 @@ async function main() {
278
278
  }, { requires: ['portfolio-value', 'benchmark'] });
279
279
 
280
280
  addDynamicCard(rg, tmpDir, {
281
- id: 'value-alert', type: 'card', data: { requires: ['portfolio-value'] }, state: {},
281
+ id: 'value-alert', type: 'card', data: { requires: ['portfolio-value'] }, card_data: {},
282
282
  }, (e) => {
283
283
  const tv = (e.state.tasks['portfolio-value']?.data as any)?.totalValue ?? 0;
284
284
  return { triggered: tv > 25000, threshold: 25000, currentValue: tv };
285
285
  }, { requires: ['portfolio-value'] });
286
286
 
287
287
  addDynamicCard(rg, tmpDir, {
288
- id: 'summary', type: 'card', data: { requires: ['portfolio-value', 'sentiment'] }, state: {},
288
+ id: 'summary', type: 'card', data: { requires: ['portfolio-value', 'sentiment'] }, card_data: {},
289
289
  }, (e) => {
290
290
  const tv = (e.state.tasks['portfolio-value']?.data as any)?.totalValue ?? 0;
291
291
  const mood = (e.state.tasks.sentiment?.data as any)?.bullish ? 'bullish' : 'bearish';
@@ -293,7 +293,7 @@ async function main() {
293
293
  }, { requires: ['portfolio-value', 'sentiment'] });
294
294
 
295
295
  addDynamicCard(rg, tmpDir, {
296
- id: 'correlation', type: 'card', data: { requires: ['valuator', 'benchmark'] }, state: {},
296
+ id: 'correlation', type: 'card', data: { requires: ['valuator', 'benchmark'] }, card_data: {},
297
297
  }, (e) => {
298
298
  const pos = (e.state.tasks.valuator?.data as any)?.positions ?? [];
299
299
  const techVal = pos.filter((p: any) => p.sector === 'tech').reduce((s: number, p: any) => s + p.value, 0);
@@ -302,7 +302,7 @@ async function main() {
302
302
  }, { requires: ['valuator', 'benchmark'] });
303
303
 
304
304
  addDynamicCard(rg, tmpDir, {
305
- id: 'combined-view', type: 'card', data: { requires: ['summary', 'sector-breakdown', 'risk-score'] }, state: {},
305
+ id: 'combined-view', type: 'card', data: { requires: ['summary', 'sector-breakdown', 'risk-score'] }, card_data: {},
306
306
  }, (e) => ({
307
307
  summaryMood: (e.state.tasks.summary?.data as any)?.mood ?? '?',
308
308
  sectors: (e.state.tasks['sector-breakdown']?.data as any)?.sectorCount ?? 0,
@@ -326,7 +326,7 @@ async function main() {
326
326
  console.log(' benchmark provides:', rg.getState().config.tasks.benchmark.provides);
327
327
 
328
328
  addDynamicCard(rg, tmpDir, {
329
- id: 'market-context', type: 'card', data: { requires: ['market-data'] }, state: {},
329
+ id: 'market-context', type: 'card', data: { requires: ['market-data'] }, card_data: {},
330
330
  }, (e) => {
331
331
  const bench = e.state.tasks.benchmark?.data as any ?? {};
332
332
  return { indexValue: bench.value ?? 0, context: 'provided via market-data token' };
@@ -409,7 +409,7 @@ async function main() {
409
409
  console.log(' combined-view requires:', rg.getState().config.tasks['combined-view'].requires);
410
410
 
411
411
  addDynamicCard(rg, tmpDir, {
412
- id: 'allocation-chart', type: 'card', data: { requires: ['valuator'] }, state: {},
412
+ id: 'allocation-chart', type: 'card', data: { requires: ['valuator'] }, card_data: {},
413
413
  }, (e) => {
414
414
  const pos = (e.state.tasks.valuator?.data as any)?.positions ?? [];
415
415
  const total = pos.reduce((s: number, p: any) => s + p.value, 0);
@@ -436,7 +436,7 @@ async function main() {
436
436
  id: 'watchlist', type: 'source',
437
437
  meta: { title: 'Watchlist (User Input)' },
438
438
  data: { provides: { watchlist: 'state.symbols' } },
439
- state: { symbols: ['NVDA', 'AMD', 'AMZN'] },
439
+ card_data: { symbols: ['NVDA', 'AMD', 'AMZN'] },
440
440
  };
441
441
  writeCard(tmpDir, watchlistCard);
442
442
  rg.registerHandler('watchlist', makeHandler('watchlist', (engine) => {
@@ -463,7 +463,7 @@ async function main() {
463
463
  addDynamicCard(rg, tmpDir, {
464
464
  id: 'watchlist-prices', type: 'card',
465
465
  meta: { title: 'Watchlist Latest Prices' },
466
- data: { requires: ['watchlist', 'price-feed'] }, state: {},
466
+ data: { requires: ['watchlist', 'price-feed'] }, card_data: {},
467
467
  }, (engine) => {
468
468
  const symbols: string[] = (engine.state.tasks.watchlist?.data as any)?.symbols ?? [];
469
469
  const allPrices: Record<string, number> = (engine.state.tasks['price-feed']?.data as any)?.prices ?? {};
@@ -3,7 +3,7 @@
3
3
  "meta": { "title": "Holdings Table" },
4
4
  "requires": ["holdings", "prices"],
5
5
  "provides": [{ "bindTo": "table", "src": "computed_values.table" }],
6
- "state": {},
6
+ "card_data": {},
7
7
  "compute": [
8
8
  {
9
9
  "bindTo": "table",
@@ -6,10 +6,10 @@
6
6
  "provides": [
7
7
  {
8
8
  "bindTo": "holdings",
9
- "src": "state.holdings"
9
+ "src": "card_data.holdings"
10
10
  }
11
11
  ],
12
- "state": {
12
+ "card_data": {
13
13
  "holdings": [
14
14
  {
15
15
  "symbol": "AAPL",
@@ -31,7 +31,7 @@
31
31
  "kind": "table",
32
32
  "label": "Holdings",
33
33
  "data": {
34
- "bind": "state.holdings",
34
+ "bind": "card_data.holdings",
35
35
  "columns": [
36
36
  "symbol",
37
37
  "qty"
@@ -3,7 +3,7 @@
3
3
  "meta": { "title": "Portfolio Total Value" },
4
4
  "requires": ["table"],
5
5
  "provides": [{ "bindTo": "totalValue", "src": "computed_values.totalValue" }],
6
- "state": {},
6
+ "card_data": {},
7
7
  "compute": [
8
8
  { "bindTo": "totalValue", "expr": "$sum(requires.table.rows.value)" }
9
9
  ],
@@ -3,7 +3,7 @@
3
3
  "meta": { "title": "Fetch Market Prices" },
4
4
  "requires": ["holdings"],
5
5
  "provides": [{ "bindTo": "prices", "src": "sources.prices" }],
6
- "state": {},
6
+ "card_data": {},
7
7
  "sources": [
8
8
  { "cli": "node ../fetch-prices.js --tmp-file-name tmp_file1", "bindTo": "prices", "outputFile": "prices.json" }
9
9
  ],
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Portfolio Tracker Task-Executor
4
+ *
5
+ * Implements the run-source-fetch protocol for board-live-cards.
6
+ * This script acts as an external task-executor that can be registered via .task-executor file.
7
+ *
8
+ * Contract:
9
+ * portfolio-tracker-task-executor.js run-source-fetch --in <defFile> --out <resultFile> --err <errFile>
10
+ *
11
+ * Input (--in file):
12
+ * JSON source definition with { cli: "...", bindTo: "...", outputFile: "...", ... }
13
+ *
14
+ * Output (on success):
15
+ * --out file contains the execution result
16
+ * Exit code: 0
17
+ *
18
+ * Output (on error):
19
+ * --err file contains error message
20
+ * Exit code: 1
21
+ */
22
+
23
+ const fs = require('fs');
24
+ const path = require('path');
25
+ const { execSync } = require('child_process');
26
+
27
+ // Parse command line arguments
28
+ const args = process.argv.slice(2);
29
+ let subcommand = '';
30
+ let inFile = '';
31
+ let outFile = '';
32
+ let errFile = '';
33
+
34
+ for (let i = 0; i < args.length; i++) {
35
+ if (args[i] === 'run-source-fetch') {
36
+ subcommand = 'run-source-fetch';
37
+ } else if (args[i] === '--in' && i + 1 < args.length) {
38
+ inFile = args[i + 1];
39
+ } else if (args[i] === '--out' && i + 1 < args.length) {
40
+ outFile = args[i + 1];
41
+ } else if (args[i] === '--err' && i + 1 < args.length) {
42
+ errFile = args[i + 1];
43
+ }
44
+ }
45
+
46
+ if (subcommand !== 'run-source-fetch' || !inFile || !outFile || !errFile) {
47
+ console.error('Usage: portfolio-tracker-task-executor.js run-source-fetch --in <defFile> --out <resultFile> --err <errFile>');
48
+ process.exit(1);
49
+ }
50
+
51
+ try {
52
+ // 1. Read source definition from --in file
53
+ console.log(`[portfolio-tracker-task-executor] Reading source definition from ${inFile}`);
54
+ const sourceDefStr = fs.readFileSync(inFile, 'utf-8');
55
+ const sourceDef = JSON.parse(sourceDefStr);
56
+
57
+ // 2. Extract cli command from source definition
58
+ const { cli: sourceCliCommand } = sourceDef;
59
+ if (!sourceCliCommand) {
60
+ throw new Error('cli is required in source definition');
61
+ }
62
+
63
+ console.log(`[portfolio-tracker-task-executor] Executing: ${sourceCliCommand}`);
64
+
65
+ // 3. Execute source.cli synchronously and capture output
66
+ let output;
67
+ try {
68
+ output = execSync(sourceCliCommand, {
69
+ encoding: 'utf-8',
70
+ timeout: (sourceDef.timeout ?? 120) * 1000, // Convert to ms
71
+ cwd: sourceDef.cwd,
72
+ shell: true,
73
+ stdio: ['pipe', 'pipe', 'pipe'], // Capture stdout/stderr
74
+ });
75
+ } catch (execErr) {
76
+ // Even on error, try to use what output we got
77
+ output = execErr.stdout || '';
78
+ if (!output) {
79
+ throw new Error(`Command execution failed: ${execErr.message}`);
80
+ }
81
+ }
82
+
83
+ // 4. Write output to --out file
84
+ console.log(`[portfolio-tracker-task-executor] Writing result to ${outFile}`);
85
+ fs.writeFileSync(outFile, output.trim(), 'utf-8');
86
+
87
+ console.log(`[portfolio-tracker-task-executor] Success`);
88
+ process.exit(0);
89
+ } catch (error) {
90
+ // 3a. On error: write error message to --err file and exit non-zero
91
+ const errorMsg = error instanceof Error ? error.message : String(error);
92
+ console.error(`[portfolio-tracker-task-executor] Error:`, errorMsg);
93
+
94
+ fs.writeFileSync(errFile, errorMsg, 'utf-8');
95
+ process.exit(1);
96
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml-flow",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Unified workflow engine: step-machine (sequential) + event-graph (stateless DAG) with pluggable storage",
5
5
  "author": "",
6
6
  "license": "MIT",
@@ -63,6 +63,11 @@
63
63
  "import": "./dist/continuous-event-graph/index.js",
64
64
  "require": "./dist/continuous-event-graph/index.cjs"
65
65
  },
66
+ "./board-livegraph-runtime": {
67
+ "types": "./dist/board-livegraph-runtime/index.d.ts",
68
+ "import": "./dist/board-livegraph-runtime/index.js",
69
+ "require": "./dist/board-livegraph-runtime/index.cjs"
70
+ },
66
71
  "./inference": {
67
72
  "types": "./dist/inference/index.d.ts",
68
73
  "import": "./dist/inference/index.js",
@@ -72,6 +77,11 @@
72
77
  "types": "./dist/card-compute/index.d.ts",
73
78
  "import": "./dist/card-compute/index.js",
74
79
  "require": "./dist/card-compute/index.cjs"
80
+ },
81
+ "./runtime-artifacts": {
82
+ "types": "./dist/runtime-artifacts/index.d.ts",
83
+ "import": "./dist/runtime-artifacts/index.js",
84
+ "require": "./dist/runtime-artifacts/index.cjs"
75
85
  }
76
86
  },
77
87
  "browser": {
@@ -87,12 +97,16 @@
87
97
  ],
88
98
  "scripts": {
89
99
  "build": "tsup",
100
+ "build:browser": "tsup --config tsup.browser.config.ts",
90
101
  "dev": "tsup --watch",
91
102
  "test": "vitest",
92
103
  "test:run": "vitest run",
104
+ "test:example-board": "vitest run tests/examples/example-board.test.ts",
105
+ "check:example-board": "npm run test:example-board && npm run validate:cards -- \"examples/example-board/cards/*.json\"",
106
+ "validate:cards": "tsx scripts/validate-live-cards.ts",
93
107
  "lint": "eslint src/",
94
108
  "typecheck": "tsc --noEmit",
95
- "prepublishOnly": "npm run build"
109
+ "prepublishOnly": "npm run build && npm run build:browser"
96
110
  },
97
111
  "devDependencies": {
98
112
  "@types/node": "^20.10.0",
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://yaml-flow.dev/schema/card-runtime.schema.json",
4
+ "title": "Card Runtime Computed Artifact",
5
+ "description": "Published per-card runtime artifact written to runtime-out/cards/<card-id>.computed.json. Contains only values produced by the compute step.",
6
+ "type": "object",
7
+ "required": ["schema_version", "card_id", "computed_values"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema_version": {
11
+ "type": "string",
12
+ "const": "v1",
13
+ "description": "Artifact schema version."
14
+ },
15
+ "card_id": {
16
+ "type": "string",
17
+ "description": "The ID of the card this artifact belongs to."
18
+ },
19
+ "computed_values": {
20
+ "type": "object",
21
+ "description": "Key/value map of outputs produced by the card's JSONata compute steps.",
22
+ "additionalProperties": true
23
+ }
24
+ }
25
+ }