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.
- 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.js +87 -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 +1284 -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
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { f as GraphEvent } from './types-CMFSIjpc.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Continuous Event Graph — Journal
|
|
5
|
+
*
|
|
6
|
+
* Append-only event log for the reactive layer.
|
|
7
|
+
* Handlers append events here; drain() reads and clears atomically.
|
|
8
|
+
*
|
|
9
|
+
* Adapter:
|
|
10
|
+
* - MemoryJournal: in-process array (default)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface Journal {
|
|
14
|
+
/** Append an event to the journal. Safe to call from concurrent callbacks. */
|
|
15
|
+
append(event: GraphEvent): void;
|
|
16
|
+
/** Read all pending events and clear the journal atomically. */
|
|
17
|
+
drain(): GraphEvent[];
|
|
18
|
+
/** Number of pending events (for observability). */
|
|
19
|
+
readonly size: number;
|
|
20
|
+
}
|
|
21
|
+
declare class MemoryJournal implements Journal {
|
|
22
|
+
private buffer;
|
|
23
|
+
append(event: GraphEvent): void;
|
|
24
|
+
drain(): GraphEvent[];
|
|
25
|
+
get size(): number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { type Journal as J, MemoryJournal as M };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { f as GraphEvent } from './types-CMFSIjpc.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Continuous Event Graph — Journal
|
|
5
|
+
*
|
|
6
|
+
* Append-only event log for the reactive layer.
|
|
7
|
+
* Handlers append events here; drain() reads and clears atomically.
|
|
8
|
+
*
|
|
9
|
+
* Adapter:
|
|
10
|
+
* - MemoryJournal: in-process array (default)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface Journal {
|
|
14
|
+
/** Append an event to the journal. Safe to call from concurrent callbacks. */
|
|
15
|
+
append(event: GraphEvent): void;
|
|
16
|
+
/** Read all pending events and clear the journal atomically. */
|
|
17
|
+
drain(): GraphEvent[];
|
|
18
|
+
/** Number of pending events (for observability). */
|
|
19
|
+
readonly size: number;
|
|
20
|
+
}
|
|
21
|
+
declare class MemoryJournal implements Journal {
|
|
22
|
+
private buffer;
|
|
23
|
+
append(event: GraphEvent): void;
|
|
24
|
+
drain(): GraphEvent[];
|
|
25
|
+
get size(): number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { type Journal as J, MemoryJournal as M };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { f as GraphEvent, T as TaskConfig, e as GraphEngineStore, G as GraphConfig } from './types-CMFSIjpc.js';
|
|
2
|
+
import { b as LiveGraphSnapshot, L as LiveGraph, S as ScheduleResult } from './types-C2eJ7DAV.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Continuous Event Graph — Reactive Layer
|
|
@@ -20,7 +20,7 @@ import { L as LiveGraph, S as ScheduleResult, b as LiveGraphSnapshot } from './t
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Deterministic hash of a data payload.
|
|
23
|
-
* Recursively-sorted JSON →
|
|
23
|
+
* Recursively-sorted JSON → stable 64-bit hex.
|
|
24
24
|
* Used to auto-compute dataHash when the handler doesn't provide one.
|
|
25
25
|
* Exported so handler authors can pre-compute or test hashes.
|
|
26
26
|
*/
|
|
@@ -211,7 +211,7 @@ interface LiveCard {
|
|
|
211
211
|
title?: string;
|
|
212
212
|
tags?: string[];
|
|
213
213
|
};
|
|
214
|
-
|
|
214
|
+
card_data?: Record<string, unknown>;
|
|
215
215
|
compute?: {
|
|
216
216
|
bindTo: string;
|
|
217
217
|
fn: string;
|
|
@@ -219,14 +219,12 @@ interface LiveCard {
|
|
|
219
219
|
}[];
|
|
220
220
|
sources?: {
|
|
221
221
|
cli?: string;
|
|
222
|
-
script?: string;
|
|
223
222
|
bindTo: string;
|
|
224
223
|
kind?: 'api' | 'websocket' | 'static' | 'llm';
|
|
225
224
|
[key: string]: unknown;
|
|
226
225
|
}[];
|
|
227
226
|
optionalSources?: {
|
|
228
227
|
cli?: string;
|
|
229
|
-
script?: string;
|
|
230
228
|
bindTo: string;
|
|
231
229
|
kind?: 'api' | 'websocket' | 'static' | 'llm';
|
|
232
230
|
[key: string]: unknown;
|
|
@@ -315,29 +313,4 @@ interface LiveCardsToReactiveResult {
|
|
|
315
313
|
*/
|
|
316
314
|
declare function liveCardsToReactiveGraph(input: LiveCard[] | LiveBoard, options?: LiveCardsToReactiveOptions): LiveCardsToReactiveResult;
|
|
317
315
|
|
|
318
|
-
|
|
319
|
-
* Continuous Event Graph — Journal
|
|
320
|
-
*
|
|
321
|
-
* Append-only event log for the reactive layer.
|
|
322
|
-
* Handlers append events here; drain() reads and clears atomically.
|
|
323
|
-
*
|
|
324
|
-
* Adapter:
|
|
325
|
-
* - MemoryJournal: in-process array (default)
|
|
326
|
-
*/
|
|
327
|
-
|
|
328
|
-
interface Journal {
|
|
329
|
-
/** Append an event to the journal. Safe to call from concurrent callbacks. */
|
|
330
|
-
append(event: GraphEvent): void;
|
|
331
|
-
/** Read all pending events and clear the journal atomically. */
|
|
332
|
-
drain(): GraphEvent[];
|
|
333
|
-
/** Number of pending events (for observability). */
|
|
334
|
-
readonly size: number;
|
|
335
|
-
}
|
|
336
|
-
declare class MemoryJournal implements Journal {
|
|
337
|
-
private buffer;
|
|
338
|
-
append(event: GraphEvent): void;
|
|
339
|
-
drain(): GraphEvent[];
|
|
340
|
-
get size(): number;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
export { type Journal as J, type LiveBoard as L, MemoryJournal as M, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
|
|
316
|
+
export { type LiveBoard as L, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { f as GraphEvent, T as TaskConfig, e as GraphEngineStore, G as GraphConfig } from './types-CMFSIjpc.cjs';
|
|
2
|
+
import { b as LiveGraphSnapshot, L as LiveGraph, S as ScheduleResult } from './types-BzLD8bjb.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Continuous Event Graph — Reactive Layer
|
|
@@ -20,7 +20,7 @@ import { L as LiveGraph, S as ScheduleResult, b as LiveGraphSnapshot } from './t
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Deterministic hash of a data payload.
|
|
23
|
-
* Recursively-sorted JSON →
|
|
23
|
+
* Recursively-sorted JSON → stable 64-bit hex.
|
|
24
24
|
* Used to auto-compute dataHash when the handler doesn't provide one.
|
|
25
25
|
* Exported so handler authors can pre-compute or test hashes.
|
|
26
26
|
*/
|
|
@@ -211,7 +211,7 @@ interface LiveCard {
|
|
|
211
211
|
title?: string;
|
|
212
212
|
tags?: string[];
|
|
213
213
|
};
|
|
214
|
-
|
|
214
|
+
card_data?: Record<string, unknown>;
|
|
215
215
|
compute?: {
|
|
216
216
|
bindTo: string;
|
|
217
217
|
fn: string;
|
|
@@ -219,14 +219,12 @@ interface LiveCard {
|
|
|
219
219
|
}[];
|
|
220
220
|
sources?: {
|
|
221
221
|
cli?: string;
|
|
222
|
-
script?: string;
|
|
223
222
|
bindTo: string;
|
|
224
223
|
kind?: 'api' | 'websocket' | 'static' | 'llm';
|
|
225
224
|
[key: string]: unknown;
|
|
226
225
|
}[];
|
|
227
226
|
optionalSources?: {
|
|
228
227
|
cli?: string;
|
|
229
|
-
script?: string;
|
|
230
228
|
bindTo: string;
|
|
231
229
|
kind?: 'api' | 'websocket' | 'static' | 'llm';
|
|
232
230
|
[key: string]: unknown;
|
|
@@ -315,29 +313,4 @@ interface LiveCardsToReactiveResult {
|
|
|
315
313
|
*/
|
|
316
314
|
declare function liveCardsToReactiveGraph(input: LiveCard[] | LiveBoard, options?: LiveCardsToReactiveOptions): LiveCardsToReactiveResult;
|
|
317
315
|
|
|
318
|
-
|
|
319
|
-
* Continuous Event Graph — Journal
|
|
320
|
-
*
|
|
321
|
-
* Append-only event log for the reactive layer.
|
|
322
|
-
* Handlers append events here; drain() reads and clears atomically.
|
|
323
|
-
*
|
|
324
|
-
* Adapter:
|
|
325
|
-
* - MemoryJournal: in-process array (default)
|
|
326
|
-
*/
|
|
327
|
-
|
|
328
|
-
interface Journal {
|
|
329
|
-
/** Append an event to the journal. Safe to call from concurrent callbacks. */
|
|
330
|
-
append(event: GraphEvent): void;
|
|
331
|
-
/** Read all pending events and clear the journal atomically. */
|
|
332
|
-
drain(): GraphEvent[];
|
|
333
|
-
/** Number of pending events (for observability). */
|
|
334
|
-
readonly size: number;
|
|
335
|
-
}
|
|
336
|
-
declare class MemoryJournal implements Journal {
|
|
337
|
-
private buffer;
|
|
338
|
-
append(event: GraphEvent): void;
|
|
339
|
-
drain(): GraphEvent[];
|
|
340
|
-
get size(): number;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
export { type Journal as J, type LiveBoard as L, MemoryJournal as M, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
|
|
316
|
+
export { type LiveBoard as L, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { L as LiveGraph, S as ScheduleResult } from './types-C2eJ7DAV.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Continuous Event Graph — Schedule
|
|
5
|
+
*
|
|
6
|
+
* Pure read-only projection: LiveGraph → ScheduleResult
|
|
7
|
+
*
|
|
8
|
+
* Classifies every non-terminal task into one of:
|
|
9
|
+
* - eligible: all requires satisfied, ready to dispatch
|
|
10
|
+
* - pending: requires not yet met, but a viable producer exists (normal waiting)
|
|
11
|
+
* - unresolved: requires not met, NO task in the graph can produce them (caller's problem)
|
|
12
|
+
* - blocked: requires not met because the producing task FAILED (caller's problem)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Compute the scheduling status of every task in the live graph.
|
|
17
|
+
* Pure function — no side effects.
|
|
18
|
+
*/
|
|
19
|
+
declare function schedule(live: LiveGraph): ScheduleResult;
|
|
20
|
+
|
|
21
|
+
export { schedule as s };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { L as LiveGraph, S as ScheduleResult } from './types-BzLD8bjb.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Continuous Event Graph — Schedule
|
|
5
|
+
*
|
|
6
|
+
* Pure read-only projection: LiveGraph → ScheduleResult
|
|
7
|
+
*
|
|
8
|
+
* Classifies every non-terminal task into one of:
|
|
9
|
+
* - eligible: all requires satisfied, ready to dispatch
|
|
10
|
+
* - pending: requires not yet met, but a viable producer exists (normal waiting)
|
|
11
|
+
* - unresolved: requires not met, NO task in the graph can produce them (caller's problem)
|
|
12
|
+
* - blocked: requires not met because the producing task FAILED (caller's problem)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Compute the scheduling status of every task in the live graph.
|
|
17
|
+
* Pure function — no side effects.
|
|
18
|
+
*/
|
|
19
|
+
declare function schedule(live: LiveGraph): ScheduleResult;
|
|
20
|
+
|
|
21
|
+
export { schedule as s };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "portfolio-form",
|
|
3
3
|
"meta": { "title": "Portfolio Holdings Form" },
|
|
4
|
-
"provides": [{ "bindTo": "holdings", "src": "
|
|
5
|
-
"
|
|
4
|
+
"provides": [{ "bindTo": "holdings", "src": "card_data.holdings" }],
|
|
5
|
+
"card_data": {
|
|
6
6
|
"holdings": [
|
|
7
7
|
{ "symbol": "AAPL", "qty": 50 },
|
|
8
8
|
{ "symbol": "MSFT", "qty": 30 }
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"view": {
|
|
12
12
|
"elements": [
|
|
13
|
-
{ "kind": "table", "label": "Holdings", "data": { "bind": "
|
|
13
|
+
{ "kind": "table", "label": "Holdings", "data": { "bind": "card_data.holdings", "columns": ["symbol", "qty"] } }
|
|
14
14
|
]
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -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
|
],
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
"id": "price-fetch",
|
|
3
3
|
"meta": { "title": "Fetch Market Prices" },
|
|
4
4
|
"requires": ["holdings"],
|
|
5
|
-
"provides": [{ "bindTo": "prices", "src": "
|
|
6
|
-
"
|
|
5
|
+
"provides": [{ "bindTo": "prices", "src": "fetched_sources.prices" }],
|
|
6
|
+
"card_data": {},
|
|
7
7
|
"sources": [
|
|
8
8
|
{ "cli": "node ../fetch-prices.js", "bindTo": "prices", "outputFile": "prices.json" }
|
|
9
9
|
],
|
|
10
10
|
"view": {
|
|
11
11
|
"elements": [
|
|
12
|
-
{ "kind": "table", "label": "Market Prices", "data": { "bind": "
|
|
12
|
+
{ "kind": "table", "label": "Market Prices", "data": { "bind": "fetched_sources.prices" } }
|
|
13
13
|
]
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -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
|
+
}
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
* This is a BLACK-BOX client of board-live-cards CLI.
|
|
7
7
|
* It only calls CLI commands and does NOT inspect board internals.
|
|
8
8
|
*
|
|
9
|
-
* Usage:
|
|
9
|
+
* Usage:
|
|
10
|
+
* node portfolio-tracker.js
|
|
11
|
+
* node portfolio-tracker.js --task-executor <path>
|
|
10
12
|
*/
|
|
11
13
|
|
|
12
14
|
import * as fs from 'node:fs';
|
|
@@ -30,6 +32,28 @@ const BOARD = path.join(RUNTIME_ROOT, 'board-runtime');
|
|
|
30
32
|
const CARDS = path.join(RUNTIME_ROOT, 'cards');
|
|
31
33
|
const TMP_FILE = path.join(BOARD, 'tmp_file1');
|
|
32
34
|
|
|
35
|
+
function parseArgs(argv) {
|
|
36
|
+
let taskExecutor;
|
|
37
|
+
for (let i = 0; i < argv.length; i++) {
|
|
38
|
+
const arg = argv[i];
|
|
39
|
+
if (arg === '--task-executor') {
|
|
40
|
+
const value = argv[i + 1];
|
|
41
|
+
if (!value || value.startsWith('--')) {
|
|
42
|
+
console.error('[ERROR] Missing value for --task-executor');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
taskExecutor = value;
|
|
46
|
+
i += 1;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
console.error(`[ERROR] Unknown argument: ${arg}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
return { taskExecutor };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const options = parseArgs(process.argv.slice(2));
|
|
56
|
+
|
|
33
57
|
console.log(`Runtime root: ${RUNTIME_ROOT}`);
|
|
34
58
|
|
|
35
59
|
function sleep(ms) {
|
|
@@ -131,7 +155,11 @@ function setupRuntimeCards() {
|
|
|
131
155
|
console.log('\n=== T0: Init board ===');
|
|
132
156
|
fs.rmSync(BOARD, { recursive: true, force: true });
|
|
133
157
|
|
|
134
|
-
|
|
158
|
+
if (options.taskExecutor) {
|
|
159
|
+
cli('init', BOARD, '--task-executor', options.taskExecutor);
|
|
160
|
+
} else {
|
|
161
|
+
cli('init', BOARD);
|
|
162
|
+
}
|
|
135
163
|
cli('add-cards', '--rg', BOARD, '--card-glob', path.join(CARDS, '*.json'));
|
|
136
164
|
|
|
137
165
|
console.log('\n--- T0 Status (after add-cards) ---');
|
|
@@ -149,8 +177,8 @@ function setupRuntimeCards() {
|
|
|
149
177
|
const portfolioFormV2 = {
|
|
150
178
|
id: 'portfolio-form',
|
|
151
179
|
meta: { title: 'Portfolio Holdings Form' },
|
|
152
|
-
provides: [{ bindTo: 'holdings', src: '
|
|
153
|
-
|
|
180
|
+
provides: [{ bindTo: 'holdings', src: 'card_data.holdings' }],
|
|
181
|
+
card_data: {
|
|
154
182
|
holdings: [
|
|
155
183
|
{ symbol: 'AAPL', qty: 50 },
|
|
156
184
|
{ symbol: 'MSFT', qty: 30 },
|
|
@@ -159,7 +187,7 @@ function setupRuntimeCards() {
|
|
|
159
187
|
},
|
|
160
188
|
view: {
|
|
161
189
|
elements: [
|
|
162
|
-
{ kind: 'table', label: 'Holdings', data: { bind: '
|
|
190
|
+
{ kind: 'table', label: 'Holdings', data: { bind: 'card_data.holdings', columns: ['symbol', 'qty'] } },
|
|
163
191
|
],
|
|
164
192
|
},
|
|
165
193
|
};
|