yaml-flow 5.0.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.
- package/{examples/example-board/reusable-server-runtime.js → board-livecards-server-runtime.js} +103 -24
- package/{examples/example-board/reusable-board-runtime-client.js → browser/board-livecards-runtime-client.js} +6 -2
- package/browser/{board-livegraph-runtime.js → board-livegraph-engine.js} +212 -16
- package/browser/board-livegraph-engine.js.map +1 -0
- package/browser/live-cards.js +362 -38
- package/browser/live-cards.schema.json +20 -4
- package/dist/board-livegraph-runtime/index.cjs +210 -14
- package/dist/board-livegraph-runtime/index.cjs.map +1 -1
- package/dist/board-livegraph-runtime/index.d.cts +49 -5
- package/dist/board-livegraph-runtime/index.d.ts +49 -5
- package/dist/board-livegraph-runtime/index.js +209 -15
- package/dist/board-livegraph-runtime/index.js.map +1 -1
- package/dist/card-compute/index.cjs +63 -7
- package/dist/card-compute/index.cjs.map +1 -1
- package/dist/card-compute/index.d.cts +2 -2
- package/dist/card-compute/index.d.ts +2 -2
- package/dist/card-compute/index.js +63 -7
- package/dist/card-compute/index.js.map +1 -1
- package/dist/cli/board-live-cards-cli.cjs +664 -75
- package/dist/cli/board-live-cards-cli.cjs.map +1 -1
- package/dist/cli/board-live-cards-cli.d.cts +33 -5
- package/dist/cli/board-live-cards-cli.d.ts +33 -5
- package/dist/cli/board-live-cards-cli.js +661 -76
- package/dist/cli/board-live-cards-cli.js.map +1 -1
- package/dist/{constants-ozjf1Ejw.d.cts → constants-BzZUyYlp.d.cts} +1 -1
- package/dist/{constants-DuzE5n03.d.ts → constants-oCEbNpul.d.ts} +1 -1
- package/dist/continuous-event-graph/index.cjs +47 -14
- package/dist/continuous-event-graph/index.cjs.map +1 -1
- package/dist/continuous-event-graph/index.d.cts +9 -9
- package/dist/continuous-event-graph/index.d.ts +9 -9
- package/dist/continuous-event-graph/index.js +47 -14
- package/dist/continuous-event-graph/index.js.map +1 -1
- package/dist/event-graph/index.cjs +29 -12
- package/dist/event-graph/index.cjs.map +1 -1
- package/dist/event-graph/index.d.cts +5 -5
- package/dist/event-graph/index.d.ts +5 -5
- package/dist/event-graph/index.js +29 -12
- package/dist/event-graph/index.js.map +1 -1
- package/dist/index.cjs +93 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +93 -20
- package/dist/index.js.map +1 -1
- package/dist/inference/index.cjs +29 -12
- package/dist/inference/index.cjs.map +1 -1
- package/dist/inference/index.d.cts +2 -2
- package/dist/inference/index.d.ts +2 -2
- package/dist/inference/index.js +29 -12
- package/dist/inference/index.js.map +1 -1
- package/dist/{journal-NLYuqege.d.ts → journal-9HEgs7dU.d.ts} +1 -1
- package/dist/{journal-DRfJiheM.d.cts → journal-B-JCfQnh.d.cts} +1 -1
- package/dist/{live-cards-bridge-Or7fdEJV.d.ts → live-cards-bridge-CeNxiVcm.d.ts} +6 -2
- package/dist/{live-cards-bridge-vGJ6tMzN.d.cts → live-cards-bridge-z_rJCSbi.d.cts} +6 -2
- package/dist/{schedule-CMcZe5Ny.d.ts → schedule-Cszq9LYY.d.ts} +1 -1
- package/dist/{schedule-CiucyCan.d.cts → schedule-qWNL0RQh.d.cts} +1 -1
- package/dist/{types-CMFSIjpc.d.cts → types-BBhqYGhE.d.cts} +4 -0
- package/dist/{types-CMFSIjpc.d.ts → types-BBhqYGhE.d.ts} +4 -0
- package/dist/{types-BzLD8bjb.d.cts → types-CHSdoAAA.d.cts} +1 -1
- package/dist/{types-C2eJ7DAV.d.ts → types-CoW0gQl3.d.ts} +1 -1
- package/dist/{validate-DJQTQ6bP.d.ts → validate-BAVzUJWa.d.ts} +1 -1
- package/dist/{validate-ke92Cleg.d.cts → validate-Dbu7ygys.d.cts} +1 -1
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-risk-assessment.json +28 -0
- package/examples/browser/boards/portfolio-tracker/cards/rebalancing-strategy.json +28 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-inference-adapter.js +187 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +139 -5
- package/examples/example-board/agent-instructions-cardlayout.md +28 -0
- package/examples/example-board/agent-instructions.md +603 -0
- package/examples/example-board/cards/card-concentration.json +42 -0
- package/examples/example-board/cards/card-market-prices.json +51 -0
- package/examples/example-board/cards/card-portfolio-action.json +19 -0
- package/examples/example-board/cards/card-portfolio-risks.json +19 -0
- package/examples/example-board/cards/card-portfolio-value.json +62 -0
- package/examples/example-board/cards/card-portfolio.json +44 -0
- package/examples/example-board/demo-chat-handler.js +373 -33
- package/examples/example-board/demo-server-config.json +5 -0
- package/examples/example-board/demo-server.js +83 -7
- package/examples/example-board/demo-shell-browser.html +75 -207
- package/examples/example-board/demo-shell-with-server.html +14 -9
- package/examples/example-board/demo-shell.html +1 -1
- package/examples/example-board/demo-task-executor.js +259 -41
- package/package.json +6 -2
- package/schema/live-cards.schema.json +20 -4
- package/browser/board-livegraph-runtime.js.map +0 -1
- package/examples/example-board/board.yaml +0 -23
- package/examples/example-board/bootstrap_payload.json +0 -1
- package/examples/example-board/cards/card-chain-region-alert.json +0 -39
- package/examples/example-board/cards/card-chain-region-totals.json +0 -26
- package/examples/example-board/cards/card-chain-top-region.json +0 -24
- package/examples/example-board/cards/card-ex-actions.json +0 -32
- package/examples/example-board/cards/card-ex-chart.json +0 -30
- package/examples/example-board/cards/card-ex-filter.json +0 -36
- package/examples/example-board/cards/card-ex-filtered-by-preference.json +0 -59
- package/examples/example-board/cards/card-ex-form.json +0 -91
- package/examples/example-board/cards/card-ex-list.json +0 -22
- package/examples/example-board/cards/card-ex-markdown.json +0 -17
- package/examples/example-board/cards/card-ex-metric.json +0 -19
- package/examples/example-board/cards/card-ex-narrative.json +0 -36
- package/examples/example-board/cards/card-ex-source-http.json +0 -28
- package/examples/example-board/cards/card-ex-source.json +0 -21
- package/examples/example-board/cards/card-ex-status.json +0 -35
- package/examples/example-board/cards/card-ex-table.json +0 -30
- package/examples/example-board/cards/card-ex-todo.json +0 -29
- package/examples/example-board/mock.db +0 -15
- package/examples/example-board/reusable-runtime-artifacts-adapter.js +0 -233
package/{examples/example-board/reusable-server-runtime.js → board-livecards-server-runtime.js}
RENAMED
|
@@ -138,6 +138,15 @@ export function createMultiBoardServerRuntime(options = {}) {
|
|
|
138
138
|
const defaultTaskExecutorPath = typeof entry.taskExecutorPath === 'string'
|
|
139
139
|
? entry.taskExecutorPath
|
|
140
140
|
: options.defaultTaskExecutorPath;
|
|
141
|
+
const defaultStepMachineCliPath = typeof entry.stepMachineCliPath === 'string'
|
|
142
|
+
? entry.stepMachineCliPath
|
|
143
|
+
: options.defaultStepMachineCliPath;
|
|
144
|
+
const defaultChatHandlerPath = typeof entry.chatHandlerPath === 'string'
|
|
145
|
+
? entry.chatHandlerPath
|
|
146
|
+
: options.defaultChatHandlerPath;
|
|
147
|
+
const defaultInferenceAdapterPath = typeof entry.inferenceAdapterPath === 'string'
|
|
148
|
+
? entry.inferenceAdapterPath
|
|
149
|
+
: options.defaultInferenceAdapterPath;
|
|
141
150
|
|
|
142
151
|
const service = createExampleBoardServerRuntime({
|
|
143
152
|
apiBasePath: `${apiBasePath}/${boardId}`,
|
|
@@ -148,6 +157,10 @@ export function createMultiBoardServerRuntime(options = {}) {
|
|
|
148
157
|
tmpSurfaceDir: path.join(boardRoot, 'surface'),
|
|
149
158
|
runtimeOutDir: path.join(boardRoot, 'runtime-out'),
|
|
150
159
|
defaultTaskExecutorPath,
|
|
160
|
+
defaultStepMachineCliPath,
|
|
161
|
+
defaultChatHandlerPath,
|
|
162
|
+
defaultInferenceAdapterPath,
|
|
163
|
+
boardLiveCardsCliJs: options.boardLiveCardsCliJs,
|
|
151
164
|
});
|
|
152
165
|
|
|
153
166
|
boardServiceCache.set(boardId, service);
|
|
@@ -197,6 +210,10 @@ export function createMultiBoardServerRuntime(options = {}) {
|
|
|
197
210
|
const label = typeof body.label === 'string' && body.label.trim() ? body.label.trim() : id;
|
|
198
211
|
const entry = { id, label };
|
|
199
212
|
if (typeof body.cardsDir === 'string') entry.cardsDir = body.cardsDir;
|
|
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;
|
|
200
217
|
config.boards.push(entry);
|
|
201
218
|
writeBoardsConfig(config);
|
|
202
219
|
|
|
@@ -245,27 +262,17 @@ export function createMultiBoardServerRuntime(options = {}) {
|
|
|
245
262
|
return false;
|
|
246
263
|
}
|
|
247
264
|
|
|
248
|
-
// Exposed
|
|
249
|
-
|
|
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) {
|
|
250
268
|
const config = readBoardsConfig();
|
|
251
269
|
if (!config.boards.some((b) => b.id === boardId)) {
|
|
252
270
|
const err = new Error(`Board "${boardId}" not registered`);
|
|
253
271
|
err.statusCode = 404;
|
|
254
272
|
throw err;
|
|
255
273
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
let setupPerformed = false;
|
|
259
|
-
|
|
260
|
-
if (reset) {
|
|
261
|
-
service.demoPrepSetup();
|
|
262
|
-
setupPerformed = true;
|
|
263
|
-
} else if (!fs.existsSync(service.tmpCardsDir)) {
|
|
264
|
-
service.ensureDemoSetup();
|
|
265
|
-
setupPerformed = true;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return { ok: true, setupPerformed, reset, tmpCardsDir: service.tmpCardsDir };
|
|
274
|
+
const boardRoot = path.join(setupDir, `board-${boardId}`);
|
|
275
|
+
return { service: getBoardService(boardId), boardRoot };
|
|
269
276
|
}
|
|
270
277
|
|
|
271
278
|
return {
|
|
@@ -277,7 +284,7 @@ export function createMultiBoardServerRuntime(options = {}) {
|
|
|
277
284
|
handleBoardsRegistryApi,
|
|
278
285
|
handleBoardApi,
|
|
279
286
|
handleApi,
|
|
280
|
-
|
|
287
|
+
requireBoardService,
|
|
281
288
|
};
|
|
282
289
|
}
|
|
283
290
|
|
|
@@ -310,6 +317,30 @@ export function createExampleBoardServerRuntime(options = {}) {
|
|
|
310
317
|
? options.defaultTaskExecutorPath
|
|
311
318
|
: path.resolve(process.cwd(), options.defaultTaskExecutorPath))
|
|
312
319
|
: null;
|
|
320
|
+
const configuredStepMachineCliPath = typeof options.defaultStepMachineCliPath === 'string'
|
|
321
|
+
&& options.defaultStepMachineCliPath.trim()
|
|
322
|
+
? (path.isAbsolute(options.defaultStepMachineCliPath)
|
|
323
|
+
? options.defaultStepMachineCliPath
|
|
324
|
+
: path.resolve(process.cwd(), options.defaultStepMachineCliPath))
|
|
325
|
+
: null;
|
|
326
|
+
const configuredBoardLiveCardsCliJs = typeof options.boardLiveCardsCliJs === 'string'
|
|
327
|
+
&& options.boardLiveCardsCliJs.trim()
|
|
328
|
+
? (path.isAbsolute(options.boardLiveCardsCliJs)
|
|
329
|
+
? options.boardLiveCardsCliJs
|
|
330
|
+
: path.resolve(process.cwd(), options.boardLiveCardsCliJs))
|
|
331
|
+
: null;
|
|
332
|
+
const configuredChatHandlerPath = typeof options.defaultChatHandlerPath === 'string'
|
|
333
|
+
&& options.defaultChatHandlerPath.trim()
|
|
334
|
+
? (path.isAbsolute(options.defaultChatHandlerPath)
|
|
335
|
+
? options.defaultChatHandlerPath
|
|
336
|
+
: path.resolve(process.cwd(), options.defaultChatHandlerPath))
|
|
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;
|
|
313
344
|
|
|
314
345
|
const statusSnapshotFile = path.join(runtimeOutDir, 'board-livegraph-status.json');
|
|
315
346
|
const boardFile = path.join(boardDir, 'board-graph.json');
|
|
@@ -318,6 +349,8 @@ export function createExampleBoardServerRuntime(options = {}) {
|
|
|
318
349
|
let didDemoSetup = false;
|
|
319
350
|
|
|
320
351
|
function resolveCliJsPath() {
|
|
352
|
+
if (configuredBoardLiveCardsCliJs && fs.existsSync(configuredBoardLiveCardsCliJs)) return configuredBoardLiveCardsCliJs;
|
|
353
|
+
|
|
321
354
|
const envOverride = process.env.BOARD_LIVE_CARDS_CLI_JS;
|
|
322
355
|
if (envOverride && fs.existsSync(envOverride)) return envOverride;
|
|
323
356
|
|
|
@@ -341,6 +374,10 @@ export function createExampleBoardServerRuntime(options = {}) {
|
|
|
341
374
|
|
|
342
375
|
const cliJs = resolveCliJsPath();
|
|
343
376
|
|
|
377
|
+
if (!process.env.DEMO_STEP_MACHINE_CLI_PATH && configuredStepMachineCliPath && fs.existsSync(configuredStepMachineCliPath)) {
|
|
378
|
+
process.env.DEMO_STEP_MACHINE_CLI_PATH = configuredStepMachineCliPath;
|
|
379
|
+
}
|
|
380
|
+
|
|
344
381
|
function ensureCardStorageDirs(cardId) {
|
|
345
382
|
const safeCardId = String(cardId || '').replace(/[^a-zA-Z0-9_-]/g, '_') || 'unknown-card';
|
|
346
383
|
const cardDir = path.join(tmpCardsDir, safeCardId);
|
|
@@ -417,7 +454,7 @@ export function createExampleBoardServerRuntime(options = {}) {
|
|
|
417
454
|
function ensureBuilt() {
|
|
418
455
|
if (!cliJs || !fs.existsSync(cliJs)) {
|
|
419
456
|
throw new Error(
|
|
420
|
-
'Unable to locate board-live-cards CLI. Set BOARD_LIVE_CARDS_CLI_JS or install yaml-flow in this project.'
|
|
457
|
+
'Unable to locate board-live-cards CLI. Set boardLiveCardsCliJs option, BOARD_LIVE_CARDS_CLI_JS, or install yaml-flow in this project.'
|
|
421
458
|
);
|
|
422
459
|
}
|
|
423
460
|
}
|
|
@@ -631,29 +668,70 @@ export function createExampleBoardServerRuntime(options = {}) {
|
|
|
631
668
|
return resolved;
|
|
632
669
|
}
|
|
633
670
|
|
|
634
|
-
function
|
|
671
|
+
function resolveChatHandlerPath(chatHandlerPathParam) {
|
|
672
|
+
const raw = typeof chatHandlerPathParam === 'string' ? chatHandlerPathParam.trim() : '';
|
|
673
|
+
const resolved = raw
|
|
674
|
+
? (path.isAbsolute(raw) ? raw : path.resolve(__dirname, raw))
|
|
675
|
+
: configuredChatHandlerPath;
|
|
676
|
+
if (!resolved) return null;
|
|
677
|
+
if (!fs.existsSync(resolved)) {
|
|
678
|
+
const err = new Error(`Chat handler script not found: ${resolved}`);
|
|
679
|
+
err.statusCode = 400;
|
|
680
|
+
throw err;
|
|
681
|
+
}
|
|
682
|
+
return resolved;
|
|
683
|
+
}
|
|
684
|
+
|
|
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) {
|
|
635
700
|
fs.mkdirSync(boardDir, { recursive: true });
|
|
636
701
|
|
|
637
702
|
const taskExecutorPath = resolveTaskExecutorPath(taskExecutorPathParam);
|
|
703
|
+
const chatHandlerPath = resolveChatHandlerPath(chatHandlerPathParam);
|
|
704
|
+
const inferenceAdapterPath = resolveInferenceAdapterPath(inferenceAdapterPathParam);
|
|
638
705
|
const taskExecutorCmd = `${shellQuote(process.execPath)} ${shellQuote(taskExecutorPath)}`;
|
|
706
|
+
const chatHandlerCmd = chatHandlerPath
|
|
707
|
+
? `${shellQuote(process.execPath)} ${shellQuote(chatHandlerPath)}`
|
|
708
|
+
: null;
|
|
709
|
+
const inferenceAdapterCmd = inferenceAdapterPath
|
|
710
|
+
? `${shellQuote(process.execPath)} ${shellQuote(inferenceAdapterPath)}`
|
|
711
|
+
: null;
|
|
712
|
+
|
|
713
|
+
const initArgs = ['init', boardDir, '--task-executor', taskExecutorCmd];
|
|
714
|
+
if (chatHandlerCmd) initArgs.push('--chat-handler', chatHandlerCmd);
|
|
715
|
+
if (inferenceAdapterCmd) initArgs.push('--inference-adapter', inferenceAdapterCmd);
|
|
716
|
+
initArgs.push('--runtime-out', runtimeOutDir);
|
|
639
717
|
|
|
640
718
|
try {
|
|
641
|
-
runCli(
|
|
719
|
+
runCli(initArgs);
|
|
642
720
|
} catch (err) {
|
|
643
721
|
const msg = String((err && err.message) || err);
|
|
644
722
|
if (!msg.includes('no valid board-graph.json')) throw err;
|
|
645
723
|
|
|
646
724
|
clearDirContents(boardDir);
|
|
647
725
|
fs.mkdirSync(boardDir, { recursive: true });
|
|
648
|
-
runCli(
|
|
726
|
+
runCli(initArgs);
|
|
649
727
|
}
|
|
650
728
|
}
|
|
651
729
|
|
|
652
|
-
function initBoardAndSetup(taskExecutorPathParam) {
|
|
730
|
+
function initBoardAndSetup(taskExecutorPathParam, chatHandlerPathParam, inferenceAdapterPathParam) {
|
|
653
731
|
ensureDemoSetup();
|
|
654
732
|
|
|
655
733
|
if (!fs.existsSync(boardFile)) {
|
|
656
|
-
initBoard(taskExecutorPathParam);
|
|
734
|
+
initBoard(taskExecutorPathParam, chatHandlerPathParam, inferenceAdapterPathParam);
|
|
657
735
|
}
|
|
658
736
|
|
|
659
737
|
const expectedCardsRoot = path.resolve(tmpCardsDir);
|
|
@@ -665,7 +743,7 @@ export function createExampleBoardServerRuntime(options = {}) {
|
|
|
665
743
|
|
|
666
744
|
if (hasStaleMapping) {
|
|
667
745
|
clearDirContents(boardDir);
|
|
668
|
-
initBoard(taskExecutorPathParam);
|
|
746
|
+
initBoard(taskExecutorPathParam, chatHandlerPathParam, inferenceAdapterPathParam);
|
|
669
747
|
}
|
|
670
748
|
}
|
|
671
749
|
|
|
@@ -1095,7 +1173,8 @@ export function createExampleBoardServerRuntime(options = {}) {
|
|
|
1095
1173
|
try {
|
|
1096
1174
|
if (method === 'GET' && p === `${apiBasePath}/init-board`) {
|
|
1097
1175
|
const taskExecutorPathParam = url.searchParams.get('taskExecutorPath') || '';
|
|
1098
|
-
|
|
1176
|
+
const chatHandlerPathParam = url.searchParams.get('chatHandlerPath') || '';
|
|
1177
|
+
initBoardAndSetup(taskExecutorPathParam, chatHandlerPathParam);
|
|
1099
1178
|
json(res, 200, buildPublishedRuntimePayload());
|
|
1100
1179
|
return true;
|
|
1101
1180
|
}
|
|
@@ -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)
|
|
149
|
-
|
|
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
|
-
|
|
295
|
-
|
|
296
|
-
for (const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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-
|
|
1453
|
-
//# sourceMappingURL=board-livegraph-
|
|
1648
|
+
//# sourceMappingURL=board-livegraph-engine.js.map
|
|
1649
|
+
//# sourceMappingURL=board-livegraph-engine.js.map
|