yaml-flow 4.0.0 → 5.1.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.
- package/browser/board-livegraph-runtime.js +1453 -0
- package/browser/board-livegraph-runtime.js.map +1 -0
- package/browser/card-compute.js +36 -17
- package/browser/live-cards.js +848 -109
- package/browser/live-cards.schema.json +46 -21
- package/dist/board-livegraph-runtime/index.cjs +1448 -0
- package/dist/board-livegraph-runtime/index.cjs.map +1 -0
- package/dist/board-livegraph-runtime/index.d.cts +101 -0
- package/dist/board-livegraph-runtime/index.d.ts +101 -0
- package/dist/board-livegraph-runtime/index.js +1441 -0
- package/dist/board-livegraph-runtime/index.js.map +1 -0
- package/dist/card-compute/index.cjs +159 -44
- package/dist/card-compute/index.cjs.map +1 -1
- package/dist/card-compute/index.d.cts +36 -11
- package/dist/card-compute/index.d.ts +36 -11
- package/dist/card-compute/index.js +156 -44
- package/dist/card-compute/index.js.map +1 -1
- package/dist/cli/board-live-cards-cli.cjs +476 -105
- package/dist/cli/board-live-cards-cli.cjs.map +1 -1
- package/dist/cli/board-live-cards-cli.d.cts +8 -16
- package/dist/cli/board-live-cards-cli.d.ts +8 -16
- package/dist/cli/board-live-cards-cli.js +476 -106
- package/dist/cli/board-live-cards-cli.js.map +1 -1
- package/dist/continuous-event-graph/index.cjs +74 -33
- package/dist/continuous-event-graph/index.cjs.map +1 -1
- package/dist/continuous-event-graph/index.d.cts +7 -23
- package/dist/continuous-event-graph/index.d.ts +7 -23
- package/dist/continuous-event-graph/index.js +73 -32
- package/dist/continuous-event-graph/index.js.map +1 -1
- package/dist/index.cjs +1440 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +1434 -56
- package/dist/index.js.map +1 -1
- package/dist/journal-DRfJiheM.d.cts +28 -0
- package/dist/journal-NLYuqege.d.ts +28 -0
- package/dist/{journal-B_2JnBMF.d.ts → live-cards-bridge-Or7fdEJV.d.ts} +5 -32
- package/dist/{journal-BJDjWb5Q.d.cts → live-cards-bridge-vGJ6tMzN.d.cts} +5 -32
- package/dist/schedule-CMcZe5Ny.d.ts +21 -0
- package/dist/schedule-CiucyCan.d.cts +21 -0
- package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +1 -1
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +3 -3
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +1 -1
- package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +3 -3
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +33 -5
- package/examples/browser/livecards-browser/index.html +37 -684
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +3 -3
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +3 -3
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +2 -2
- package/examples/example-board/board.yaml +23 -0
- package/examples/example-board/bootstrap_payload.json +1 -0
- package/examples/example-board/cards/card-chain-region-alert.json +39 -0
- package/examples/example-board/cards/card-chain-region-totals.json +26 -0
- package/examples/example-board/cards/card-chain-top-region.json +24 -0
- package/examples/example-board/cards/card-ex-actions.json +32 -0
- package/examples/example-board/cards/card-ex-chart.json +30 -0
- package/examples/example-board/cards/card-ex-filter.json +36 -0
- package/examples/example-board/cards/card-ex-filtered-by-preference.json +59 -0
- package/examples/example-board/cards/card-ex-form.json +91 -0
- package/examples/example-board/cards/card-ex-list.json +22 -0
- package/examples/example-board/cards/card-ex-markdown.json +17 -0
- package/examples/example-board/cards/card-ex-metric.json +19 -0
- package/examples/example-board/cards/card-ex-narrative.json +36 -0
- package/examples/example-board/cards/card-ex-source-http.json +28 -0
- package/examples/example-board/cards/card-ex-source.json +21 -0
- package/examples/example-board/cards/card-ex-status.json +35 -0
- package/examples/example-board/cards/card-ex-table.json +30 -0
- package/examples/example-board/cards/card-ex-todo.json +29 -0
- package/examples/example-board/demo-chat-handler.js +69 -0
- package/examples/example-board/demo-server-config.json +7 -0
- package/examples/example-board/demo-server.js +124 -0
- package/examples/example-board/demo-shell-browser.html +806 -0
- package/examples/example-board/demo-shell-with-server.html +280 -0
- package/examples/example-board/demo-shell.html +62 -0
- package/examples/example-board/demo-task-executor.js +255 -0
- package/examples/example-board/mock.db +15 -0
- package/examples/example-board/reusable-board-runtime-client.js +265 -0
- package/examples/example-board/reusable-runtime-artifacts-adapter.js +233 -0
- package/examples/example-board/reusable-server-runtime.js +1341 -0
- package/examples/index.html +16 -9
- package/examples/npm-libs/continuous-event-graph/live-cards-board.ts +17 -17
- package/examples/npm-libs/continuous-event-graph/live-portfolio-dashboard.ts +23 -23
- package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +3 -3
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
- package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +1 -1
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
- package/package.json +16 -2
- package/schema/card-runtime.schema.json +25 -0
- package/schema/live-cards.schema.json +46 -21
- package/browser/ingest-board.js +0 -296
- package/examples/ingest.js +0 -733
package/examples/index.html
CHANGED
|
@@ -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
|
|
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="
|
|
360
|
-
<p>Fastest way to see the LiveCards browser renderer,
|
|
361
|
-
<div class="command"><code>Open
|
|
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
|
|
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="
|
|
446
|
-
<p>Interactive
|
|
447
|
-
<div class="command"><code>Open
|
|
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 "node C:\path\to\portfolio-tracker-task-executor.cjs"">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="
|
|
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
|
-
|
|
40
|
-
source: { kind: 'static', bindTo: '
|
|
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
|
-
|
|
46
|
+
card_data: {},
|
|
47
47
|
data: { requires: ['market-feed'] },
|
|
48
48
|
compute: {
|
|
49
|
-
total: { fn: 'sum', input: '
|
|
50
|
-
avg: { fn: 'avg', input: '
|
|
51
|
-
count: { fn: 'count', input: '
|
|
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
|
-
|
|
58
|
+
card_data: {},
|
|
59
59
|
data: { requires: ['stats'] },
|
|
60
60
|
compute: {
|
|
61
61
|
label: {
|
|
62
62
|
fn: 'template',
|
|
63
|
-
input: '
|
|
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
|
-
|
|
119
|
-
source: { kind: 'api', bindTo: '
|
|
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
|
-
|
|
126
|
-
source: { kind: 'static', bindTo: '
|
|
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
|
-
|
|
132
|
+
card_data: {},
|
|
133
133
|
data: { requires: ['equity-feed', 'bond-feed'] },
|
|
134
134
|
compute: {
|
|
135
|
-
equity_total: { fn: 'sum', input: '
|
|
136
|
-
bond_total: { fn: 'sum', input: '
|
|
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
|
-
|
|
143
|
+
card_data: {},
|
|
144
144
|
data: { requires: ['portfolio-mix'] },
|
|
145
145
|
compute: {
|
|
146
146
|
label: {
|
|
147
147
|
fn: 'template',
|
|
148
|
-
input: '
|
|
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: '
|
|
73
|
-
|
|
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: '
|
|
87
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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'] },
|
|
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'] },
|
|
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'] },
|
|
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'] },
|
|
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'] },
|
|
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'] },
|
|
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'] },
|
|
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'] },
|
|
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'] },
|
|
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
|
-
|
|
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'] },
|
|
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 ?? {};
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
"provides": [
|
|
7
7
|
{
|
|
8
8
|
"bindTo": "holdings",
|
|
9
|
-
"src": "
|
|
9
|
+
"src": "card_data.holdings"
|
|
10
10
|
}
|
|
11
11
|
],
|
|
12
|
-
"
|
|
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": "
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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": "
|
|
3
|
+
"version": "5.1.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
|
+
}
|