yaml-flow 3.1.0 → 4.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/README.md +81 -20
- package/board-live-cards-cli.js +37 -0
- package/browser/card-compute.js +132 -431
- package/browser/live-cards.js +41 -27
- package/browser/live-cards.schema.json +59 -77
- package/dist/card-compute/index.cjs +135 -415
- package/dist/card-compute/index.cjs.map +1 -1
- package/dist/card-compute/index.d.cts +52 -49
- package/dist/card-compute/index.d.ts +52 -49
- package/dist/card-compute/index.js +134 -415
- package/dist/card-compute/index.js.map +1 -1
- package/dist/cli/board-live-cards-cli.cjs +2379 -0
- package/dist/cli/board-live-cards-cli.cjs.map +1 -0
- package/dist/cli/board-live-cards-cli.d.cts +213 -0
- package/dist/cli/board-live-cards-cli.d.ts +213 -0
- package/dist/cli/board-live-cards-cli.js +2332 -0
- package/dist/cli/board-live-cards-cli.js.map +1 -0
- package/dist/{constants-B2zqu10b.d.ts → constants-DuzE5n03.d.ts} +2 -2
- package/dist/{constants-DJZU1pwJ.d.cts → constants-ozjf1Ejw.d.cts} +2 -2
- package/dist/continuous-event-graph/index.cjs +201 -448
- package/dist/continuous-event-graph/index.cjs.map +1 -1
- package/dist/continuous-event-graph/index.d.cts +16 -340
- package/dist/continuous-event-graph/index.d.ts +16 -340
- package/dist/continuous-event-graph/index.js +198 -448
- package/dist/continuous-event-graph/index.js.map +1 -1
- package/dist/event-graph/index.cjs +4 -4
- 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 +4 -4
- package/dist/event-graph/index.js.map +1 -1
- package/dist/index.cjs +278 -533
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +278 -533
- package/dist/index.js.map +1 -1
- package/dist/inference/index.cjs +138 -19
- 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 +138 -19
- package/dist/inference/index.js.map +1 -1
- package/dist/journal-BJDjWb5Q.d.cts +343 -0
- package/dist/journal-B_2JnBMF.d.ts +343 -0
- package/dist/step-machine/index.cjs +18 -1
- package/dist/step-machine/index.cjs.map +1 -1
- package/dist/step-machine/index.d.cts +2 -2
- package/dist/step-machine/index.d.ts +2 -2
- package/dist/step-machine/index.js +18 -1
- package/dist/step-machine/index.js.map +1 -1
- package/dist/stores/file.d.cts +1 -1
- package/dist/stores/file.d.ts +1 -1
- package/dist/stores/index.d.cts +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/localStorage.d.cts +1 -1
- package/dist/stores/localStorage.d.ts +1 -1
- package/dist/stores/memory.d.cts +1 -1
- package/dist/stores/memory.d.ts +1 -1
- package/dist/{types-BwvgvlOO.d.cts → types-BzLD8bjb.d.cts} +1 -1
- package/dist/{types-ClRA8hzC.d.ts → types-C2eJ7DAV.d.ts} +1 -1
- package/dist/{types-DEj7OakX.d.cts → types-CMFSIjpc.d.cts} +39 -4
- package/dist/{types-DEj7OakX.d.ts → types-CMFSIjpc.d.ts} +39 -4
- package/dist/{types-FZ_eyErS.d.cts → types-ycun84cq.d.cts} +1 -0
- package/dist/{types-FZ_eyErS.d.ts → types-ycun84cq.d.ts} +1 -0
- package/dist/{validate-DEZ2Ymdb.d.ts → validate-DJQTQ6bP.d.ts} +1 -1
- package/dist/{validate-DqKTZg_o.d.cts → validate-ke92Cleg.d.cts} +1 -1
- package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +16 -0
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/browser/boards/portfolio-tracker/fetch-prices.js +43 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +7 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +189 -0
- package/examples/browser/livecards-browser/index.html +688 -0
- package/examples/browser/step-machine-browser/index.html +367 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
- package/examples/cli/step-machine-demo/jsonata-init-board-cli.js +36 -0
- package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +30 -0
- package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +19 -0
- package/examples/cli/step-machine-demo/step-cli-echo-y.js +15 -0
- package/examples/cli/step-machine-demo/step2-double-cli.js +39 -0
- package/examples/cli/step-machine-demo/two-step-math-handlers.js +32 -0
- package/examples/cli/step-machine-demo/two-step-math.flow.yaml +31 -0
- package/examples/cli/step-machine-demo/two-step-mixed-handlers.js +24 -0
- package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +35 -0
- package/examples/index.html +792 -0
- package/examples/ingest.js +733 -0
- package/examples/npm-libs/batch/batch-step-machine.ts +121 -0
- package/examples/npm-libs/continuous-event-graph/live-cards-board.ts +215 -0
- package/examples/npm-libs/continuous-event-graph/live-portfolio-dashboard.ts +555 -0
- package/examples/npm-libs/continuous-event-graph/portfolio-tracker.ts +287 -0
- package/examples/npm-libs/continuous-event-graph/reactive-monitoring.ts +265 -0
- package/examples/npm-libs/continuous-event-graph/reactive-pipeline.ts +168 -0
- package/examples/npm-libs/continuous-event-graph/soc-incident-board.ts +287 -0
- package/examples/npm-libs/continuous-event-graph/stock-dashboard.ts +229 -0
- package/examples/npm-libs/event-graph/ci-cd-pipeline.ts +243 -0
- package/examples/npm-libs/event-graph/executor-diamond.ts +165 -0
- package/examples/npm-libs/event-graph/executor-pipeline.ts +161 -0
- package/examples/npm-libs/event-graph/research-pipeline.ts +137 -0
- package/examples/npm-libs/flows/ai-conversation.yaml +116 -0
- package/examples/npm-libs/flows/order-processing.yaml +143 -0
- package/examples/npm-libs/flows/simple-greeting.yaml +54 -0
- package/examples/npm-libs/graph-of-graphs/multi-stage-etl.ts +307 -0
- package/examples/npm-libs/graph-of-graphs/url-processing-pipeline.ts +254 -0
- package/examples/npm-libs/inference/azure-deployment.ts +149 -0
- package/examples/npm-libs/inference/copilot-cli.ts +138 -0
- package/examples/npm-libs/inference/data-pipeline.ts +145 -0
- package/examples/npm-libs/inference/pluggable-adapters.ts +254 -0
- package/examples/npm-libs/node/ai-conversation.ts +195 -0
- package/examples/npm-libs/node/simple-greeting.ts +101 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
- package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
- package/package.json +14 -2
- package/schema/board-status.schema.json +118 -0
- package/schema/flow.schema.json +5 -0
- package/schema/live-cards.schema.json +59 -77
- package/step-machine-cli.js +674 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import addFormats from 'ajv-formats';
|
|
2
|
-
import { existsSync, writeFileSync, appendFileSync, readFileSync } from 'fs';
|
|
3
2
|
import { createHash } from 'crypto';
|
|
4
3
|
import { exec, execFile } from 'child_process';
|
|
4
|
+
import jsonata from 'jsonata';
|
|
5
5
|
|
|
6
6
|
var __create = Object.create;
|
|
7
7
|
var __defProp = Object.defineProperty;
|
|
@@ -6439,7 +6439,7 @@ function applyStepResult(flow, state, stepName, stepResult) {
|
|
|
6439
6439
|
};
|
|
6440
6440
|
}
|
|
6441
6441
|
}
|
|
6442
|
-
const nextStep = stepConfig.transitions[stepResult.result];
|
|
6442
|
+
const nextStep = stepConfig.failure_transitions?.[stepResult.result] ?? stepConfig.transitions[stepResult.result];
|
|
6443
6443
|
if (!nextStep) {
|
|
6444
6444
|
throw new Error(
|
|
6445
6445
|
`No transition defined for result "${stepResult.result}" in step "${stepName}"`
|
|
@@ -6644,6 +6644,15 @@ var StepMachine = class {
|
|
|
6644
6644
|
);
|
|
6645
6645
|
}
|
|
6646
6646
|
}
|
|
6647
|
+
if (stepConfig.failure_transitions) {
|
|
6648
|
+
for (const [result, target] of Object.entries(stepConfig.failure_transitions)) {
|
|
6649
|
+
if (!steps[target] && !terminal_states[target]) {
|
|
6650
|
+
throw new Error(
|
|
6651
|
+
`Step "${stepName}" failure_transition "${result}" points to unknown step "${target}"`
|
|
6652
|
+
);
|
|
6653
|
+
}
|
|
6654
|
+
}
|
|
6655
|
+
}
|
|
6647
6656
|
}
|
|
6648
6657
|
}
|
|
6649
6658
|
on(eventType, listener) {
|
|
@@ -6873,6 +6882,9 @@ function validateStepFlowConfig(flow) {
|
|
|
6873
6882
|
if (!step.transitions || typeof step.transitions !== "object") {
|
|
6874
6883
|
errors.push(`Step "${stepName}" must have a "transitions" object`);
|
|
6875
6884
|
}
|
|
6885
|
+
if (step.failure_transitions !== void 0 && typeof step.failure_transitions !== "object") {
|
|
6886
|
+
errors.push(`Step "${stepName}" failure_transitions must be an object when provided`);
|
|
6887
|
+
}
|
|
6876
6888
|
}
|
|
6877
6889
|
}
|
|
6878
6890
|
if (!f.terminal_states || typeof f.terminal_states !== "object") {
|
|
@@ -6993,6 +7005,11 @@ var flow_schema_default = {
|
|
|
6993
7005
|
additionalProperties: { type: "string" },
|
|
6994
7006
|
minProperties: 1
|
|
6995
7007
|
},
|
|
7008
|
+
failure_transitions: {
|
|
7009
|
+
type: "object",
|
|
7010
|
+
description: "Mapping of failure-like results (e.g. failure, timeout) -> next step name",
|
|
7011
|
+
additionalProperties: { type: "string" }
|
|
7012
|
+
},
|
|
6996
7013
|
retry: {
|
|
6997
7014
|
$ref: "#/definitions/retry_config"
|
|
6998
7015
|
},
|
|
@@ -7931,8 +7948,8 @@ function apply(state, event, graph) {
|
|
|
7931
7948
|
return applyInjectTokens(state, event.tokens);
|
|
7932
7949
|
case "agent-action":
|
|
7933
7950
|
return applyAgentAction(state, event.action, graph, event.config);
|
|
7934
|
-
case "task-
|
|
7935
|
-
return
|
|
7951
|
+
case "task-upsert":
|
|
7952
|
+
return applyTaskUpsert(state, event.taskName, event.taskConfig);
|
|
7936
7953
|
default:
|
|
7937
7954
|
return state;
|
|
7938
7955
|
}
|
|
@@ -7989,7 +8006,7 @@ function applyAgentAction(state, action, graph, config) {
|
|
|
7989
8006
|
return state;
|
|
7990
8007
|
}
|
|
7991
8008
|
}
|
|
7992
|
-
function
|
|
8009
|
+
function applyTaskUpsert(state, taskName, taskConfig) {
|
|
7993
8010
|
if (!taskName || !taskConfig || !Array.isArray(taskConfig.provides)) {
|
|
7994
8011
|
return state;
|
|
7995
8012
|
}
|
|
@@ -7997,7 +8014,7 @@ function applyTaskCreation(state, taskName, taskConfig) {
|
|
|
7997
8014
|
...state,
|
|
7998
8015
|
tasks: {
|
|
7999
8016
|
...state.tasks,
|
|
8000
|
-
[taskName]: createDefaultGraphEngineStore()
|
|
8017
|
+
[taskName]: state.tasks[taskName] ?? createDefaultGraphEngineStore()
|
|
8001
8018
|
},
|
|
8002
8019
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
8003
8020
|
};
|
|
@@ -9269,43 +9286,51 @@ function applyEvent(live, event) {
|
|
|
9269
9286
|
if ("executionId" in event && event.executionId && event.executionId !== state.executionId) {
|
|
9270
9287
|
return live;
|
|
9271
9288
|
}
|
|
9272
|
-
let newState;
|
|
9273
9289
|
switch (event.type) {
|
|
9290
|
+
// --- Execution state transitions ---
|
|
9274
9291
|
case "task-started":
|
|
9275
|
-
|
|
9276
|
-
break;
|
|
9292
|
+
return { config, state: applyTaskStart(state, event.taskName) };
|
|
9277
9293
|
case "task-completed":
|
|
9278
|
-
|
|
9279
|
-
break;
|
|
9294
|
+
return { config, state: applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash, event.data) };
|
|
9280
9295
|
case "task-failed":
|
|
9281
|
-
|
|
9282
|
-
break;
|
|
9296
|
+
return { config, state: applyTaskFailure(state, config, event.taskName, event.error) };
|
|
9283
9297
|
case "task-progress":
|
|
9284
|
-
|
|
9285
|
-
break;
|
|
9298
|
+
return { config, state: applyTaskProgress(state, event.taskName, event.message, event.progress) };
|
|
9286
9299
|
case "task-restart":
|
|
9287
|
-
|
|
9288
|
-
break;
|
|
9300
|
+
return { config, state: applyTaskRestart(state, event.taskName) };
|
|
9289
9301
|
case "inject-tokens":
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9302
|
+
return {
|
|
9303
|
+
config,
|
|
9304
|
+
state: {
|
|
9305
|
+
...state,
|
|
9306
|
+
availableOutputs: [.../* @__PURE__ */ new Set([...state.availableOutputs, ...event.tokens])],
|
|
9307
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
9308
|
+
}
|
|
9294
9309
|
};
|
|
9295
|
-
break;
|
|
9296
9310
|
case "agent-action":
|
|
9297
|
-
|
|
9298
|
-
|
|
9311
|
+
return { config, state: applyAgentAction2(state, event.action) };
|
|
9312
|
+
// --- Structural mutations ---
|
|
9313
|
+
case "task-upsert":
|
|
9314
|
+
return addNode(live, event.taskName, event.taskConfig);
|
|
9315
|
+
case "task-removal":
|
|
9316
|
+
return removeNode(live, event.taskName);
|
|
9317
|
+
case "node-requires-add":
|
|
9318
|
+
return addRequires(live, event.nodeName, event.tokens);
|
|
9319
|
+
case "node-requires-remove":
|
|
9320
|
+
return removeRequires(live, event.nodeName, event.tokens);
|
|
9321
|
+
case "node-provides-add":
|
|
9322
|
+
return addProvides(live, event.nodeName, event.tokens);
|
|
9323
|
+
case "node-provides-remove":
|
|
9324
|
+
return removeProvides(live, event.nodeName, event.tokens);
|
|
9299
9325
|
default:
|
|
9300
9326
|
return live;
|
|
9301
9327
|
}
|
|
9302
|
-
return { config, state: newState };
|
|
9303
9328
|
}
|
|
9304
9329
|
function applyEvents(live, events) {
|
|
9305
9330
|
return events.reduce((current, event) => applyEvent(current, event), live);
|
|
9306
9331
|
}
|
|
9307
9332
|
function addNode(live, name, taskConfig) {
|
|
9308
|
-
|
|
9333
|
+
const exists = !!live.config.tasks[name];
|
|
9309
9334
|
return {
|
|
9310
9335
|
config: {
|
|
9311
9336
|
...live.config,
|
|
@@ -9313,7 +9338,10 @@ function addNode(live, name, taskConfig) {
|
|
|
9313
9338
|
},
|
|
9314
9339
|
state: {
|
|
9315
9340
|
...live.state,
|
|
9316
|
-
tasks: {
|
|
9341
|
+
tasks: {
|
|
9342
|
+
...live.state.tasks,
|
|
9343
|
+
[name]: exists ? live.state.tasks[name] : createDefaultGraphEngineStore3()
|
|
9344
|
+
},
|
|
9317
9345
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
9318
9346
|
}
|
|
9319
9347
|
};
|
|
@@ -10020,6 +10048,8 @@ function getDownstream(live, nodeName) {
|
|
|
10020
10048
|
}));
|
|
10021
10049
|
return { nodeName, nodes, tokens: [...tokenSet] };
|
|
10022
10050
|
}
|
|
10051
|
+
|
|
10052
|
+
// src/continuous-event-graph/journal.ts
|
|
10023
10053
|
var MemoryJournal = class {
|
|
10024
10054
|
buffer = [];
|
|
10025
10055
|
append(event) {
|
|
@@ -10034,36 +10064,6 @@ var MemoryJournal = class {
|
|
|
10034
10064
|
return this.buffer.length;
|
|
10035
10065
|
}
|
|
10036
10066
|
};
|
|
10037
|
-
var FileJournal = class {
|
|
10038
|
-
constructor(path) {
|
|
10039
|
-
this.path = path;
|
|
10040
|
-
if (!existsSync(path)) {
|
|
10041
|
-
writeFileSync(path, "", "utf-8");
|
|
10042
|
-
}
|
|
10043
|
-
}
|
|
10044
|
-
path;
|
|
10045
|
-
pending = 0;
|
|
10046
|
-
append(event) {
|
|
10047
|
-
appendFileSync(this.path, JSON.stringify(event) + "\n", "utf-8");
|
|
10048
|
-
this.pending++;
|
|
10049
|
-
}
|
|
10050
|
-
drain() {
|
|
10051
|
-
const content = readFileSync(this.path, "utf-8").trim();
|
|
10052
|
-
writeFileSync(this.path, "", "utf-8");
|
|
10053
|
-
this.pending = 0;
|
|
10054
|
-
if (!content) return [];
|
|
10055
|
-
return content.split("\n").map((line) => JSON.parse(line));
|
|
10056
|
-
}
|
|
10057
|
-
get size() {
|
|
10058
|
-
try {
|
|
10059
|
-
const content = readFileSync(this.path, "utf-8").trim();
|
|
10060
|
-
if (!content) return 0;
|
|
10061
|
-
return content.split("\n").length;
|
|
10062
|
-
} catch {
|
|
10063
|
-
return this.pending;
|
|
10064
|
-
}
|
|
10065
|
-
}
|
|
10066
|
-
};
|
|
10067
10067
|
function computeDataHash(data) {
|
|
10068
10068
|
const json = stableStringify(data);
|
|
10069
10069
|
return createHash("sha256").update(json).digest("hex").slice(0, 16);
|
|
@@ -10092,15 +10092,16 @@ function decodeCallbackToken(token) {
|
|
|
10092
10092
|
return null;
|
|
10093
10093
|
}
|
|
10094
10094
|
}
|
|
10095
|
-
function createReactiveGraph(
|
|
10095
|
+
function createReactiveGraph(configOrLive, options, executionId) {
|
|
10096
10096
|
const {
|
|
10097
10097
|
handlers: initialHandlers,
|
|
10098
|
-
journal = new MemoryJournal(),
|
|
10099
10098
|
onDrain
|
|
10100
10099
|
} = options;
|
|
10101
|
-
|
|
10100
|
+
const inputQueue = new MemoryJournal();
|
|
10101
|
+
let live = "state" in configOrLive && "config" in configOrLive ? configOrLive : createLiveGraph(configOrLive, executionId);
|
|
10102
10102
|
let disposed = false;
|
|
10103
10103
|
const handlers = new Map(Object.entries(initialHandlers));
|
|
10104
|
+
const internalJournal = new MemoryJournal();
|
|
10104
10105
|
let draining = false;
|
|
10105
10106
|
let drainQueued = false;
|
|
10106
10107
|
function drain() {
|
|
@@ -10120,7 +10121,9 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10120
10121
|
}
|
|
10121
10122
|
}
|
|
10122
10123
|
function drainOnce() {
|
|
10123
|
-
const
|
|
10124
|
+
const internalEvents = internalJournal.drain();
|
|
10125
|
+
const inputEvents = inputQueue.drain();
|
|
10126
|
+
const events = [...internalEvents, ...inputEvents];
|
|
10124
10127
|
if (events.length > 0) {
|
|
10125
10128
|
live = applyEvents(live, events);
|
|
10126
10129
|
}
|
|
@@ -10131,6 +10134,26 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10131
10134
|
for (const taskName of result.eligible) {
|
|
10132
10135
|
dispatchTask(taskName);
|
|
10133
10136
|
}
|
|
10137
|
+
for (const event of events) {
|
|
10138
|
+
if (event.type === "task-progress") {
|
|
10139
|
+
const { taskName, update } = event;
|
|
10140
|
+
const taskConfig = live.config.tasks[taskName];
|
|
10141
|
+
if (!taskConfig) continue;
|
|
10142
|
+
const taskState = live.state.tasks[taskName];
|
|
10143
|
+
if (!taskState || taskState.status !== "running") continue;
|
|
10144
|
+
const callbackToken = encodeCallbackToken(taskName);
|
|
10145
|
+
runPipeline(taskName, callbackToken, update).catch((error) => {
|
|
10146
|
+
if (disposed) return;
|
|
10147
|
+
internalJournal.append({
|
|
10148
|
+
type: "task-failed",
|
|
10149
|
+
taskName,
|
|
10150
|
+
error: error.message ?? String(error),
|
|
10151
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
10152
|
+
});
|
|
10153
|
+
drain();
|
|
10154
|
+
});
|
|
10155
|
+
}
|
|
10156
|
+
}
|
|
10134
10157
|
}
|
|
10135
10158
|
function resolveUpstreamState(taskName) {
|
|
10136
10159
|
const taskConfig = live.config.tasks[taskName];
|
|
@@ -10152,7 +10175,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10152
10175
|
}
|
|
10153
10176
|
return state;
|
|
10154
10177
|
}
|
|
10155
|
-
async function runPipeline(taskName, callbackToken) {
|
|
10178
|
+
async function runPipeline(taskName, callbackToken, update) {
|
|
10156
10179
|
const taskConfig = live.config.tasks[taskName];
|
|
10157
10180
|
const handlerNames = taskConfig.taskHandlers ?? [];
|
|
10158
10181
|
const upstreamState = resolveUpstreamState(taskName);
|
|
@@ -10166,7 +10189,8 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10166
10189
|
state: upstreamState,
|
|
10167
10190
|
taskState: live.state.tasks[taskName],
|
|
10168
10191
|
config: taskConfig,
|
|
10169
|
-
callbackToken
|
|
10192
|
+
callbackToken,
|
|
10193
|
+
update
|
|
10170
10194
|
};
|
|
10171
10195
|
const status = await handler(input);
|
|
10172
10196
|
if (status === "task-initiate-failure") {
|
|
@@ -10180,15 +10204,16 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10180
10204
|
if (!handlerNames || handlerNames.length === 0) {
|
|
10181
10205
|
return;
|
|
10182
10206
|
}
|
|
10183
|
-
|
|
10207
|
+
internalJournal.append({
|
|
10184
10208
|
type: "task-started",
|
|
10185
10209
|
taskName,
|
|
10186
10210
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
10187
10211
|
});
|
|
10212
|
+
drain();
|
|
10188
10213
|
const callbackToken = encodeCallbackToken(taskName);
|
|
10189
10214
|
runPipeline(taskName, callbackToken).catch((error) => {
|
|
10190
10215
|
if (disposed) return;
|
|
10191
|
-
|
|
10216
|
+
internalJournal.append({
|
|
10192
10217
|
type: "task-failed",
|
|
10193
10218
|
taskName,
|
|
10194
10219
|
error: error.message ?? String(error),
|
|
@@ -10203,16 +10228,16 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10203
10228
|
if (event.type === "task-completed" && event.data && !event.dataHash) {
|
|
10204
10229
|
event = { ...event, dataHash: computeDataHash(event.data) };
|
|
10205
10230
|
}
|
|
10206
|
-
|
|
10231
|
+
inputQueue.append(event);
|
|
10207
10232
|
drain();
|
|
10208
10233
|
},
|
|
10209
10234
|
pushAll(events) {
|
|
10210
10235
|
if (disposed) return;
|
|
10211
10236
|
for (const event of events) {
|
|
10212
10237
|
if (event.type === "task-completed" && event.data && !event.dataHash) {
|
|
10213
|
-
|
|
10238
|
+
inputQueue.append({ ...event, dataHash: computeDataHash(event.data) });
|
|
10214
10239
|
} else {
|
|
10215
|
-
|
|
10240
|
+
inputQueue.append(event);
|
|
10216
10241
|
}
|
|
10217
10242
|
}
|
|
10218
10243
|
drain();
|
|
@@ -10224,7 +10249,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10224
10249
|
const { taskName } = decoded;
|
|
10225
10250
|
if (!live.config.tasks[taskName]) return;
|
|
10226
10251
|
if (errors && errors.length > 0) {
|
|
10227
|
-
|
|
10252
|
+
inputQueue.append({
|
|
10228
10253
|
type: "task-failed",
|
|
10229
10254
|
taskName,
|
|
10230
10255
|
error: errors.join("; "),
|
|
@@ -10232,7 +10257,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10232
10257
|
});
|
|
10233
10258
|
} else {
|
|
10234
10259
|
const dataHash = data && Object.keys(data).length > 0 ? computeDataHash(data) : void 0;
|
|
10235
|
-
|
|
10260
|
+
inputQueue.append({
|
|
10236
10261
|
type: "task-completed",
|
|
10237
10262
|
taskName,
|
|
10238
10263
|
data,
|
|
@@ -10244,31 +10269,33 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10244
10269
|
},
|
|
10245
10270
|
addNode(name, taskConfig) {
|
|
10246
10271
|
if (disposed) return;
|
|
10247
|
-
|
|
10272
|
+
inputQueue.append({ type: "task-upsert", taskName: name, taskConfig, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10248
10273
|
drain();
|
|
10249
10274
|
},
|
|
10250
10275
|
removeNode(name) {
|
|
10251
10276
|
if (disposed) return;
|
|
10252
|
-
|
|
10277
|
+
inputQueue.append({ type: "task-removal", taskName: name, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10278
|
+
drain();
|
|
10253
10279
|
},
|
|
10254
10280
|
addRequires(nodeName, tokens) {
|
|
10255
10281
|
if (disposed) return;
|
|
10256
|
-
|
|
10282
|
+
inputQueue.append({ type: "node-requires-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10257
10283
|
drain();
|
|
10258
10284
|
},
|
|
10259
10285
|
removeRequires(nodeName, tokens) {
|
|
10260
10286
|
if (disposed) return;
|
|
10261
|
-
|
|
10287
|
+
inputQueue.append({ type: "node-requires-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10262
10288
|
drain();
|
|
10263
10289
|
},
|
|
10264
10290
|
addProvides(nodeName, tokens) {
|
|
10265
10291
|
if (disposed) return;
|
|
10266
|
-
|
|
10292
|
+
inputQueue.append({ type: "node-provides-add", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10267
10293
|
drain();
|
|
10268
10294
|
},
|
|
10269
10295
|
removeProvides(nodeName, tokens) {
|
|
10270
10296
|
if (disposed) return;
|
|
10271
|
-
|
|
10297
|
+
inputQueue.append({ type: "node-provides-remove", nodeName, tokens, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10298
|
+
drain();
|
|
10272
10299
|
},
|
|
10273
10300
|
registerHandler(name, fn) {
|
|
10274
10301
|
handlers.set(name, fn);
|
|
@@ -10279,7 +10306,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10279
10306
|
retrigger(taskName) {
|
|
10280
10307
|
if (disposed) return;
|
|
10281
10308
|
if (!live.config.tasks[taskName]) return;
|
|
10282
|
-
|
|
10309
|
+
inputQueue.append({
|
|
10283
10310
|
type: "task-restart",
|
|
10284
10311
|
taskName,
|
|
10285
10312
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -10290,7 +10317,7 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10290
10317
|
if (disposed) return;
|
|
10291
10318
|
for (const name of taskNames) {
|
|
10292
10319
|
if (!live.config.tasks[name]) continue;
|
|
10293
|
-
|
|
10320
|
+
inputQueue.append({
|
|
10294
10321
|
type: "task-restart",
|
|
10295
10322
|
taskName: name,
|
|
10296
10323
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -10298,6 +10325,9 @@ function createReactiveGraph(config, options, executionId) {
|
|
|
10298
10325
|
}
|
|
10299
10326
|
drain();
|
|
10300
10327
|
},
|
|
10328
|
+
snapshot() {
|
|
10329
|
+
return snapshot(live);
|
|
10330
|
+
},
|
|
10301
10331
|
getState() {
|
|
10302
10332
|
return live;
|
|
10303
10333
|
},
|
|
@@ -10669,9 +10699,9 @@ var live_cards_schema_default = {
|
|
|
10669
10699
|
description: "Schema for Card and ExternalSource nodes in the LiveCards Board/Canvas engine",
|
|
10670
10700
|
definitions: {
|
|
10671
10701
|
bind_ref: {
|
|
10672
|
-
description: "A state path reference, e.g. 'state.raw_quotes' or '
|
|
10702
|
+
description: "A state path reference, e.g. 'state.raw_quotes' or 'requires.upstream'",
|
|
10673
10703
|
type: "string",
|
|
10674
|
-
pattern: "^state\\."
|
|
10704
|
+
pattern: "^(state|requires|computed_values)\\."
|
|
10675
10705
|
},
|
|
10676
10706
|
bind_or_literal: {
|
|
10677
10707
|
description: "A literal value or a bind reference object",
|
|
@@ -10764,38 +10794,43 @@ var live_cards_schema_default = {
|
|
|
10764
10794
|
tags: { type: "array", items: { type: "string" } }
|
|
10765
10795
|
}
|
|
10766
10796
|
},
|
|
10767
|
-
|
|
10797
|
+
requires: {
|
|
10798
|
+
type: "array",
|
|
10799
|
+
items: { type: "string" },
|
|
10800
|
+
description: "IDs of upstream nodes this node depends on"
|
|
10801
|
+
},
|
|
10802
|
+
provides: {
|
|
10803
|
+
type: "array",
|
|
10804
|
+
items: {
|
|
10805
|
+
type: "object",
|
|
10806
|
+
required: ["bindTo", "src"],
|
|
10807
|
+
properties: {
|
|
10808
|
+
bindTo: { type: "string", description: "Token name published downstream" },
|
|
10809
|
+
src: { type: "string", description: "Path to read value from (state.*, requires.*, computed_values.*)" }
|
|
10810
|
+
}
|
|
10811
|
+
},
|
|
10812
|
+
description: "Explicit bindings exposing computed/state values downstream as named tokens"
|
|
10813
|
+
},
|
|
10814
|
+
compute_step: {
|
|
10815
|
+
description: "A single ordered compute step: reads state.*/requires.*/computed_values.*, writes to computed_values[bindTo]",
|
|
10768
10816
|
type: "object",
|
|
10817
|
+
required: ["bindTo", "expr"],
|
|
10769
10818
|
properties: {
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
items: { type: "string" },
|
|
10773
|
-
description: "IDs of upstream nodes this node depends on"
|
|
10774
|
-
},
|
|
10775
|
-
provides: {
|
|
10776
|
-
type: "object",
|
|
10777
|
-
description: "Subset of state exposed downstream. Keys are published names, values are bind refs.",
|
|
10778
|
-
additionalProperties: { $ref: "#/definitions/bind_or_literal" }
|
|
10779
|
-
}
|
|
10819
|
+
bindTo: { type: "string", description: "Key in computed_values to write result" },
|
|
10820
|
+
expr: { type: "string", description: "JSONata expression evaluated against { state, requires, sources, computed_values }" }
|
|
10780
10821
|
}
|
|
10781
10822
|
},
|
|
10782
10823
|
source_def: {
|
|
10824
|
+
description: "One source entry. The engine only cares about 'bindTo' (compute namespace key) and 'outputFile' (delivery signal). Every other property is yours \u2014 add whatever your task-executor needs: kind, url, headers, mailbox, channel, model, query, etc. The full object is passed verbatim as the --in JSON to the executor.",
|
|
10783
10825
|
type: "object",
|
|
10784
|
-
required: ["
|
|
10826
|
+
required: ["bindTo"],
|
|
10827
|
+
additionalProperties: true,
|
|
10785
10828
|
properties: {
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
body_template: { type: "object", description: "Request body with {{var}} placeholders or bind refs" },
|
|
10792
|
-
template_vars: {
|
|
10793
|
-
type: "object",
|
|
10794
|
-
additionalProperties: { $ref: "#/definitions/bind_or_literal" },
|
|
10795
|
-
description: "Variables for url/body templates \u2014 static values or bind refs"
|
|
10796
|
-
},
|
|
10797
|
-
poll_interval: { type: "integer", minimum: 0, description: "Auto-refresh in seconds (0 = manual)" },
|
|
10798
|
-
transform: { type: "string", description: "Dot-path to extract from response, e.g. 'data.items'" }
|
|
10829
|
+
bindTo: { type: "string", description: "Key under sources.* available in compute expressions" },
|
|
10830
|
+
outputFile: { type: "string", description: "Board-relative path the executor writes its JSON result to. Presence of this file signals delivery." },
|
|
10831
|
+
optionalForCompletionGating: { type: "boolean", default: false, description: "When true this source does not gate card completion. Default false when absent, so sources are completion-gating by default." },
|
|
10832
|
+
timeout: { type: "integer", minimum: 0, default: 12e4, description: "Executor/script timeout in ms. Default: 120 000 (2 min)." },
|
|
10833
|
+
script: { type: "string", description: "Legacy direct-run: shell command executed when no .task-executor is registered. stdout is captured as the result." }
|
|
10799
10834
|
}
|
|
10800
10835
|
},
|
|
10801
10836
|
render_element: {
|
|
@@ -10913,64 +10948,37 @@ var live_cards_schema_default = {
|
|
|
10913
10948
|
}
|
|
10914
10949
|
}
|
|
10915
10950
|
},
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10951
|
+
title: "LiveCard",
|
|
10952
|
+
description: "A unified card node. Behavior depends on which sections are present (sources, compute, view, etc.)",
|
|
10953
|
+
type: "object",
|
|
10954
|
+
required: ["id"],
|
|
10955
|
+
additionalProperties: false,
|
|
10956
|
+
properties: {
|
|
10957
|
+
id: { type: "string" },
|
|
10958
|
+
requires: { $ref: "#/definitions/requires" },
|
|
10959
|
+
provides: { $ref: "#/definitions/provides" },
|
|
10960
|
+
meta: { $ref: "#/definitions/meta" },
|
|
10961
|
+
view: { $ref: "#/definitions/view" },
|
|
10962
|
+
state: {
|
|
10920
10963
|
type: "object",
|
|
10921
|
-
|
|
10922
|
-
additionalProperties: false,
|
|
10964
|
+
additionalProperties: true,
|
|
10923
10965
|
properties: {
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
data: { $ref: "#/definitions/data" },
|
|
10928
|
-
view: { $ref: "#/definitions/view" },
|
|
10929
|
-
state: {
|
|
10930
|
-
type: "object",
|
|
10931
|
-
additionalProperties: true,
|
|
10932
|
-
properties: {
|
|
10933
|
-
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
10934
|
-
lastRun: { type: "string", format: "date-time" },
|
|
10935
|
-
error: { type: "string" }
|
|
10936
|
-
}
|
|
10937
|
-
},
|
|
10938
|
-
compute: {
|
|
10939
|
-
type: "object",
|
|
10940
|
-
description: "Derived state: key = state path to write, value = compute_expr",
|
|
10941
|
-
additionalProperties: { $ref: "#/definitions/compute_expr" }
|
|
10942
|
-
}
|
|
10966
|
+
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
10967
|
+
lastRun: { type: "string", format: "date-time" },
|
|
10968
|
+
error: { type: "string" }
|
|
10943
10969
|
}
|
|
10944
10970
|
},
|
|
10945
|
-
{
|
|
10946
|
-
|
|
10947
|
-
description: "
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
meta: { $ref: "#/definitions/meta" },
|
|
10955
|
-
data: { $ref: "#/definitions/data" },
|
|
10956
|
-
source: { $ref: "#/definitions/source_def" },
|
|
10957
|
-
state: {
|
|
10958
|
-
type: "object",
|
|
10959
|
-
additionalProperties: true,
|
|
10960
|
-
properties: {
|
|
10961
|
-
status: { enum: ["fresh", "stale", "loading", "error"] },
|
|
10962
|
-
lastRun: { type: "string", format: "date-time" },
|
|
10963
|
-
error: { type: "string" }
|
|
10964
|
-
}
|
|
10965
|
-
},
|
|
10966
|
-
compute: {
|
|
10967
|
-
type: "object",
|
|
10968
|
-
description: "Derived state: key = state path to write, value = compute_expr",
|
|
10969
|
-
additionalProperties: { $ref: "#/definitions/compute_expr" }
|
|
10970
|
-
}
|
|
10971
|
-
}
|
|
10971
|
+
sources: {
|
|
10972
|
+
type: "array",
|
|
10973
|
+
description: "Source entries. Each entry is passed verbatim to the board's .task-executor (registered via init --task-executor) as the --in JSON file. The executor fetches/generates the data and writes JSON to --out. If no executor is registered, the built-in executor runs the entry's 'cli' command directly. Sources gate completion by default. Set optionalForCompletionGating: true for enrichment-only sources that should not block task-completed.",
|
|
10974
|
+
items: { $ref: "#/definitions/source_def" }
|
|
10975
|
+
},
|
|
10976
|
+
compute: {
|
|
10977
|
+
type: "array",
|
|
10978
|
+
description: "Ordered array of compute steps. Each reads state.*/requires.*/sources.*/computed_values.* and writes to ephemeral computed_values[bindTo].",
|
|
10979
|
+
items: { $ref: "#/definitions/compute_step" }
|
|
10972
10980
|
}
|
|
10973
|
-
|
|
10981
|
+
}
|
|
10974
10982
|
};
|
|
10975
10983
|
|
|
10976
10984
|
// src/card-compute/schema-validator.ts
|
|
@@ -11014,288 +11022,43 @@ function deepSet(obj, path, value) {
|
|
|
11014
11022
|
}
|
|
11015
11023
|
cur[parts[parts.length - 1]] = value;
|
|
11016
11024
|
}
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
const a = Array.isArray(input) ? input : [];
|
|
11020
|
-
return opts.field ? a.reduce((s, r) => s + (Number(r[opts.field]) || 0), 0) : a.reduce((s, v) => s + (Number(v) || 0), 0);
|
|
11021
|
-
};
|
|
11022
|
-
_fns.avg = (input, _e, opts) => {
|
|
11023
|
-
const s = _fns.sum(input, _e, opts);
|
|
11024
|
-
const n = Array.isArray(input) ? input.length : 1;
|
|
11025
|
-
return n ? s / n : 0;
|
|
11026
|
-
};
|
|
11027
|
-
_fns.min = (input, _e, opts) => {
|
|
11028
|
-
const a = Array.isArray(input) ? input : [];
|
|
11029
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
11030
|
-
return vals.length ? Math.min(...vals) : 0;
|
|
11031
|
-
};
|
|
11032
|
-
_fns.max = (input, _e, opts) => {
|
|
11033
|
-
const a = Array.isArray(input) ? input : [];
|
|
11034
|
-
const vals = opts.field ? a.map((r) => Number(r[opts.field])) : a.map(Number);
|
|
11035
|
-
return vals.length ? Math.max(...vals) : 0;
|
|
11036
|
-
};
|
|
11037
|
-
_fns.count = (input) => Array.isArray(input) ? input.length : input != null ? 1 : 0;
|
|
11038
|
-
_fns.first = (input) => Array.isArray(input) ? input[0] : input;
|
|
11039
|
-
_fns.last = (input) => Array.isArray(input) ? input[input.length - 1] : input;
|
|
11040
|
-
_fns.add = (input) => {
|
|
11041
|
-
const a = Array.isArray(input) ? input : [];
|
|
11042
|
-
return a.reduce((s, v) => s + Number(v), 0);
|
|
11043
|
-
};
|
|
11044
|
-
_fns.sub = (input) => {
|
|
11045
|
-
const a = Array.isArray(input) ? input : [];
|
|
11046
|
-
return a.length >= 2 ? Number(a[0]) - Number(a[1]) : 0;
|
|
11047
|
-
};
|
|
11048
|
-
_fns.mul = (input) => {
|
|
11049
|
-
const a = Array.isArray(input) ? input : [];
|
|
11050
|
-
return a.reduce((s, v) => s * Number(v), 1);
|
|
11051
|
-
};
|
|
11052
|
-
_fns.div = (input) => {
|
|
11053
|
-
const a = Array.isArray(input) ? input : [];
|
|
11054
|
-
return a.length >= 2 && Number(a[1]) !== 0 ? Number(a[0]) / Number(a[1]) : 0;
|
|
11055
|
-
};
|
|
11056
|
-
_fns.round = (input, _e, opts) => {
|
|
11057
|
-
const decimals = opts.decimals != null ? opts.decimals : 0;
|
|
11058
|
-
const factor = Math.pow(10, decimals);
|
|
11059
|
-
return Math.round(Number(input) * factor) / factor;
|
|
11060
|
-
};
|
|
11061
|
-
_fns.abs = (input) => Math.abs(Number(input));
|
|
11062
|
-
_fns.mod = (input) => {
|
|
11063
|
-
const a = Array.isArray(input) ? input : [];
|
|
11064
|
-
return a.length >= 2 ? Number(a[0]) % Number(a[1]) : 0;
|
|
11065
|
-
};
|
|
11066
|
-
_fns.gt = (input) => {
|
|
11067
|
-
const a = Array.isArray(input) ? input : [];
|
|
11068
|
-
return a.length >= 2 && Number(a[0]) > Number(a[1]);
|
|
11069
|
-
};
|
|
11070
|
-
_fns.gte = (input) => {
|
|
11071
|
-
const a = Array.isArray(input) ? input : [];
|
|
11072
|
-
return a.length >= 2 && Number(a[0]) >= Number(a[1]);
|
|
11073
|
-
};
|
|
11074
|
-
_fns.lt = (input) => {
|
|
11075
|
-
const a = Array.isArray(input) ? input : [];
|
|
11076
|
-
return a.length >= 2 && Number(a[0]) < Number(a[1]);
|
|
11077
|
-
};
|
|
11078
|
-
_fns.lte = (input) => {
|
|
11079
|
-
const a = Array.isArray(input) ? input : [];
|
|
11080
|
-
return a.length >= 2 && Number(a[0]) <= Number(a[1]);
|
|
11081
|
-
};
|
|
11082
|
-
_fns.eq = (input) => {
|
|
11083
|
-
const a = Array.isArray(input) ? input : [];
|
|
11084
|
-
return a.length >= 2 && a[0] === a[1];
|
|
11085
|
-
};
|
|
11086
|
-
_fns.neq = (input) => {
|
|
11087
|
-
const a = Array.isArray(input) ? input : [];
|
|
11088
|
-
return a.length >= 2 && a[0] !== a[1];
|
|
11089
|
-
};
|
|
11090
|
-
_fns.and = (input) => {
|
|
11091
|
-
const a = Array.isArray(input) ? input : [];
|
|
11092
|
-
return a.every(Boolean);
|
|
11093
|
-
};
|
|
11094
|
-
_fns.or = (input) => {
|
|
11095
|
-
const a = Array.isArray(input) ? input : [];
|
|
11096
|
-
return a.some(Boolean);
|
|
11097
|
-
};
|
|
11098
|
-
_fns.not = (input) => !input;
|
|
11099
|
-
_fns.concat = (input) => {
|
|
11100
|
-
const a = Array.isArray(input) ? input : [];
|
|
11101
|
-
return a.map((v) => v != null ? String(v) : "").join("");
|
|
11102
|
-
};
|
|
11103
|
-
_fns.upper = (input) => String(input || "").toUpperCase();
|
|
11104
|
-
_fns.lower = (input) => String(input || "").toLowerCase();
|
|
11105
|
-
_fns.template = (input, _e, opts) => {
|
|
11106
|
-
let t = String(opts.format || "");
|
|
11107
|
-
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
11108
|
-
for (const k of Object.keys(input)) {
|
|
11109
|
-
const v = input[k];
|
|
11110
|
-
t = t.split("{{" + k + "}}").join(v != null ? String(v) : "");
|
|
11111
|
-
}
|
|
11112
|
-
}
|
|
11113
|
-
return t;
|
|
11114
|
-
};
|
|
11115
|
-
_fns.join = (input, _e, opts) => {
|
|
11116
|
-
const a = Array.isArray(input) ? input : [];
|
|
11117
|
-
const sep = opts.separator != null ? String(opts.separator) : ", ";
|
|
11118
|
-
return a.map((v) => v != null ? String(v) : "").join(sep);
|
|
11119
|
-
};
|
|
11120
|
-
_fns.split = (input, _e, opts) => {
|
|
11121
|
-
const sep = opts.separator != null ? String(opts.separator) : ",";
|
|
11122
|
-
return String(input || "").split(sep).map((s) => s.trim());
|
|
11123
|
-
};
|
|
11124
|
-
_fns.trim = (input) => String(input || "").trim();
|
|
11125
|
-
_fns.pluck = (input, _e, opts) => Array.isArray(input) ? input.map((r) => r[opts.field]) : [];
|
|
11126
|
-
_fns.filter = (input, _e, opts) => {
|
|
11127
|
-
if (!Array.isArray(input)) return [];
|
|
11128
|
-
if (opts.field) return input.filter((r) => !!r[opts.field]);
|
|
11129
|
-
return input.filter(Boolean);
|
|
11130
|
-
};
|
|
11131
|
-
_fns.map = (input) => Array.isArray(input) ? input.slice() : [];
|
|
11132
|
-
_fns.sort = (input, _e, opts) => {
|
|
11133
|
-
const a = Array.isArray(input) ? input.slice() : [];
|
|
11134
|
-
const f = opts.field;
|
|
11135
|
-
const dir = opts.direction === "desc" ? -1 : 1;
|
|
11136
|
-
if (f) return a.sort((x, y) => x[f] > y[f] ? dir : x[f] < y[f] ? -dir : 0);
|
|
11137
|
-
return a.sort((x, y) => x > y ? dir : x < y ? -dir : 0);
|
|
11138
|
-
};
|
|
11139
|
-
_fns.slice = (input, _e, opts) => Array.isArray(input) ? input.slice(opts.start || 0, opts.end) : input;
|
|
11140
|
-
_fns.flat = (input, _e, opts) => {
|
|
11141
|
-
const depth = opts.depth != null ? opts.depth : 1;
|
|
11142
|
-
return Array.isArray(input) ? input.flat(depth) : [input];
|
|
11143
|
-
};
|
|
11144
|
-
_fns.unique = (input) => {
|
|
11145
|
-
if (!Array.isArray(input)) return [input];
|
|
11146
|
-
const seen = /* @__PURE__ */ new Set();
|
|
11147
|
-
return input.filter((v) => {
|
|
11148
|
-
const key = typeof v === "object" ? JSON.stringify(v) : v;
|
|
11149
|
-
if (seen.has(key)) return false;
|
|
11150
|
-
seen.add(key);
|
|
11151
|
-
return true;
|
|
11152
|
-
});
|
|
11153
|
-
};
|
|
11154
|
-
_fns.group = (input, _e, opts) => {
|
|
11155
|
-
const a = Array.isArray(input) ? input : [];
|
|
11156
|
-
const g = {};
|
|
11157
|
-
a.forEach((r) => {
|
|
11158
|
-
const k = String(r[opts.field] || "");
|
|
11159
|
-
if (!g[k]) g[k] = [];
|
|
11160
|
-
g[k].push(r);
|
|
11161
|
-
});
|
|
11162
|
-
return g;
|
|
11163
|
-
};
|
|
11164
|
-
_fns.flatten_keys = (input) => {
|
|
11165
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
11166
|
-
const result = [];
|
|
11167
|
-
for (const k of Object.keys(input)) {
|
|
11168
|
-
const vals = Array.isArray(input[k]) ? input[k] : [input[k]];
|
|
11169
|
-
vals.forEach((v) => result.push({ key: k, value: v }));
|
|
11170
|
-
}
|
|
11171
|
-
return result;
|
|
11172
|
-
};
|
|
11173
|
-
_fns.entries = (input) => {
|
|
11174
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return [];
|
|
11175
|
-
return Object.keys(input).map((k) => ({ key: k, value: input[k] }));
|
|
11176
|
-
};
|
|
11177
|
-
_fns.from_entries = (input) => {
|
|
11178
|
-
if (!Array.isArray(input)) return {};
|
|
11179
|
-
const obj = {};
|
|
11180
|
-
input.forEach((item) => {
|
|
11181
|
-
if (item.key != null) obj[item.key] = item.value;
|
|
11182
|
-
});
|
|
11183
|
-
return obj;
|
|
11184
|
-
};
|
|
11185
|
-
_fns.length = (input) => {
|
|
11186
|
-
if (Array.isArray(input)) return input.length;
|
|
11187
|
-
if (typeof input === "string") return input.length;
|
|
11188
|
-
if (input && typeof input === "object") return Object.keys(input).length;
|
|
11189
|
-
return 0;
|
|
11190
|
-
};
|
|
11191
|
-
_fns.get = (input, _e, opts) => deepGet(input, opts.field || opts.path || "");
|
|
11192
|
-
_fns.default = (input, _e, opts) => input != null ? input : opts.value;
|
|
11193
|
-
_fns.coalesce = (input) => {
|
|
11194
|
-
const a = Array.isArray(input) ? input : [];
|
|
11195
|
-
for (let i = 0; i < a.length; i++) {
|
|
11196
|
-
if (a[i] != null) return a[i];
|
|
11197
|
-
}
|
|
11198
|
-
return null;
|
|
11199
|
-
};
|
|
11200
|
-
_fns.now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
11201
|
-
_fns.diff_days = (input) => {
|
|
11202
|
-
const a = Array.isArray(input) ? input : [];
|
|
11203
|
-
return a.length >= 2 ? Math.floor((new Date(a[0]).getTime() - new Date(a[1]).getTime()) / 864e5) : 0;
|
|
11204
|
-
};
|
|
11205
|
-
_fns.format_date = (input, _e, opts) => {
|
|
11206
|
-
try {
|
|
11207
|
-
const d = new Date(input);
|
|
11208
|
-
if (opts.format === "iso") return d.toISOString();
|
|
11209
|
-
if (opts.format === "date") return d.toLocaleDateString();
|
|
11210
|
-
if (opts.format === "time") return d.toLocaleTimeString();
|
|
11211
|
-
return d.toLocaleDateString();
|
|
11212
|
-
} catch {
|
|
11213
|
-
return String(input);
|
|
11214
|
-
}
|
|
11215
|
-
};
|
|
11216
|
-
_fns.parse_date = (input) => {
|
|
11217
|
-
try {
|
|
11218
|
-
return new Date(input).toISOString();
|
|
11219
|
-
} catch {
|
|
11220
|
-
return null;
|
|
11221
|
-
}
|
|
11222
|
-
};
|
|
11223
|
-
_fns.to_number = (input) => Number(input) || 0;
|
|
11224
|
-
_fns.to_string = (input) => input != null ? String(input) : "";
|
|
11225
|
-
_fns.to_bool = (input) => !!input;
|
|
11226
|
-
_fns.type_of = (input) => Array.isArray(input) ? "array" : typeof input;
|
|
11227
|
-
_fns.is_null = (input) => input == null;
|
|
11228
|
-
_fns.is_empty = (input) => {
|
|
11229
|
-
if (input == null) return true;
|
|
11230
|
-
if (Array.isArray(input)) return input.length === 0;
|
|
11231
|
-
if (typeof input === "string") return input.length === 0;
|
|
11232
|
-
if (typeof input === "object") return Object.keys(input).length === 0;
|
|
11233
|
-
return false;
|
|
11234
|
-
};
|
|
11235
|
-
var _customFns = {};
|
|
11236
|
-
function evalExpr(expr, node) {
|
|
11237
|
-
if (expr == null) return expr;
|
|
11238
|
-
if (typeof expr !== "object" || Array.isArray(expr)) return expr;
|
|
11239
|
-
const e = expr;
|
|
11240
|
-
if (!e.fn) return expr;
|
|
11241
|
-
let input = e.input;
|
|
11242
|
-
if (typeof input === "string" && input.startsWith("state.")) {
|
|
11243
|
-
input = deepGet(node, input);
|
|
11244
|
-
} else if (Array.isArray(input)) {
|
|
11245
|
-
input = input.map((v) => {
|
|
11246
|
-
if (typeof v === "string" && v.startsWith("state.")) return deepGet(node, v);
|
|
11247
|
-
if (v && typeof v === "object" && v.fn) return evalExpr(v, node);
|
|
11248
|
-
return v;
|
|
11249
|
-
});
|
|
11250
|
-
} else if (input && typeof input === "object" && input.fn) {
|
|
11251
|
-
input = evalExpr(input, node);
|
|
11252
|
-
}
|
|
11253
|
-
if (e.fn === "if") {
|
|
11254
|
-
const cond = evalExpr(e.cond, node);
|
|
11255
|
-
if (cond) {
|
|
11256
|
-
return e.then && typeof e.then === "object" && e.then.fn ? evalExpr(e.then, node) : e.then;
|
|
11257
|
-
} else {
|
|
11258
|
-
return e.else && typeof e.else === "object" && e.else.fn ? evalExpr(e.else, node) : e.else;
|
|
11259
|
-
}
|
|
11260
|
-
}
|
|
11261
|
-
if (e.fn === "filter" && Array.isArray(input) && e.where) {
|
|
11262
|
-
return input.filter((item) => {
|
|
11263
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
11264
|
-
return evalExpr(e.where, tmp);
|
|
11265
|
-
});
|
|
11266
|
-
}
|
|
11267
|
-
if (e.fn === "map" && Array.isArray(input) && e.apply) {
|
|
11268
|
-
return input.map((item) => {
|
|
11269
|
-
const tmp = { state: { ...node.state, $: item } };
|
|
11270
|
-
return evalExpr(e.apply, tmp);
|
|
11271
|
-
});
|
|
11272
|
-
}
|
|
11273
|
-
const fn = _customFns[e.fn] || _fns[e.fn];
|
|
11274
|
-
if (!fn) {
|
|
11275
|
-
console.warn('CardCompute: unknown function "' + e.fn + '"');
|
|
11276
|
-
return void 0;
|
|
11277
|
-
}
|
|
11278
|
-
return fn(input, evalExpr, e);
|
|
11279
|
-
}
|
|
11280
|
-
function run(node) {
|
|
11281
|
-
if (!node || !node.compute) return node;
|
|
11025
|
+
async function run(node, options) {
|
|
11026
|
+
if (!node?.compute?.length) return node;
|
|
11282
11027
|
if (!node.state) node.state = {};
|
|
11283
|
-
|
|
11028
|
+
node.computed_values = {};
|
|
11029
|
+
node._sourcesData = options?.sourcesData ?? {};
|
|
11030
|
+
const ctx = {
|
|
11031
|
+
state: node.state,
|
|
11032
|
+
requires: node.requires ?? {},
|
|
11033
|
+
sources: node._sourcesData,
|
|
11034
|
+
computed_values: node.computed_values
|
|
11035
|
+
};
|
|
11036
|
+
for (const step of node.compute) {
|
|
11284
11037
|
try {
|
|
11285
|
-
const val =
|
|
11286
|
-
deepSet(node.
|
|
11038
|
+
const val = await jsonata(step.expr).evaluate(ctx);
|
|
11039
|
+
deepSet(node.computed_values, step.bindTo, val);
|
|
11040
|
+
ctx.computed_values = node.computed_values;
|
|
11287
11041
|
} catch (err) {
|
|
11288
|
-
console.error(`CardCompute.run error on "${node.id
|
|
11042
|
+
console.error(`CardCompute.run error on "${node.id ?? "?"}.${step.bindTo}":`, err);
|
|
11289
11043
|
}
|
|
11290
11044
|
}
|
|
11291
11045
|
return node;
|
|
11292
11046
|
}
|
|
11047
|
+
async function evalExpr(expr, node) {
|
|
11048
|
+
const ctx = {
|
|
11049
|
+
state: node.state ?? {},
|
|
11050
|
+
requires: node.requires ?? {},
|
|
11051
|
+
sources: node._sourcesData ?? {},
|
|
11052
|
+
computed_values: node.computed_values ?? {}
|
|
11053
|
+
};
|
|
11054
|
+
return jsonata(expr).evaluate(ctx);
|
|
11055
|
+
}
|
|
11293
11056
|
function resolve(node, path) {
|
|
11057
|
+
if (path.startsWith("sources.")) {
|
|
11058
|
+
return deepGet(node._sourcesData ?? {}, path.slice("sources.".length));
|
|
11059
|
+
}
|
|
11294
11060
|
return deepGet(node, path);
|
|
11295
11061
|
}
|
|
11296
|
-
function registerFunction(name, fn) {
|
|
11297
|
-
_customFns[name] = fn;
|
|
11298
|
-
}
|
|
11299
11062
|
var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
11300
11063
|
"metric",
|
|
11301
11064
|
"table",
|
|
@@ -11312,26 +11075,17 @@ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
|
11312
11075
|
"markdown",
|
|
11313
11076
|
"custom"
|
|
11314
11077
|
]);
|
|
11315
|
-
var VALID_SOURCE_KINDS = /* @__PURE__ */ new Set(["api", "websocket", "static", "llm"]);
|
|
11316
11078
|
var VALID_STATUSES = /* @__PURE__ */ new Set(["fresh", "stale", "loading", "error"]);
|
|
11317
|
-
var
|
|
11318
|
-
var SOURCE_ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "type", "meta", "data", "source", "state", "compute"]);
|
|
11079
|
+
var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "state", "compute", "sources"]);
|
|
11319
11080
|
function validateNode(node) {
|
|
11320
11081
|
const errors = [];
|
|
11321
11082
|
if (!node || typeof node !== "object" || Array.isArray(node)) {
|
|
11322
11083
|
return { ok: false, errors: ["Node must be a non-null object"] };
|
|
11323
11084
|
}
|
|
11324
11085
|
const n = node;
|
|
11325
|
-
if (typeof n.id !== "string" || !n.id)
|
|
11326
|
-
errors.push("id: required, must be a non-empty string");
|
|
11327
|
-
}
|
|
11328
|
-
if (n.type !== "card" && n.type !== "source") {
|
|
11329
|
-
errors.push('type: must be "card" or "source"');
|
|
11330
|
-
return { ok: false, errors };
|
|
11331
|
-
}
|
|
11332
|
-
const allowed = n.type === "card" ? CARD_ALLOWED_KEYS : SOURCE_ALLOWED_KEYS;
|
|
11086
|
+
if (typeof n.id !== "string" || !n.id) errors.push("id: required, must be a non-empty string");
|
|
11333
11087
|
for (const key of Object.keys(n)) {
|
|
11334
|
-
if (!
|
|
11088
|
+
if (!ALLOWED_KEYS.has(key)) errors.push(`Unknown top-level key: "${key}"`);
|
|
11335
11089
|
}
|
|
11336
11090
|
if (n.state == null || typeof n.state !== "object" || Array.isArray(n.state)) {
|
|
11337
11091
|
errors.push("state: required, must be an object");
|
|
@@ -11350,37 +11104,58 @@ function validateNode(node) {
|
|
|
11350
11104
|
if (meta.tags != null && !Array.isArray(meta.tags)) errors.push("meta.tags: must be an array");
|
|
11351
11105
|
}
|
|
11352
11106
|
}
|
|
11353
|
-
if (n.
|
|
11354
|
-
|
|
11355
|
-
|
|
11107
|
+
if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
|
|
11108
|
+
if (n.provides != null) {
|
|
11109
|
+
if (!Array.isArray(n.provides)) {
|
|
11110
|
+
errors.push("provides: must be an array of { bindTo, src } bindings");
|
|
11356
11111
|
} else {
|
|
11357
|
-
|
|
11358
|
-
|
|
11359
|
-
|
|
11112
|
+
n.provides.forEach((p, i) => {
|
|
11113
|
+
if (!p || typeof p !== "object" || Array.isArray(p)) {
|
|
11114
|
+
errors.push(`provides[${i}]: must be an object with bindTo and src`);
|
|
11115
|
+
} else {
|
|
11116
|
+
const b = p;
|
|
11117
|
+
if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
|
|
11118
|
+
if (typeof b.src !== "string" || !b.src) errors.push(`provides[${i}]: missing required "src" string`);
|
|
11119
|
+
}
|
|
11120
|
+
});
|
|
11360
11121
|
}
|
|
11361
11122
|
}
|
|
11362
11123
|
if (n.compute != null) {
|
|
11363
|
-
if (
|
|
11364
|
-
errors.push("compute: must be an
|
|
11124
|
+
if (!Array.isArray(n.compute)) {
|
|
11125
|
+
errors.push("compute: must be an array of compute steps");
|
|
11126
|
+
} else {
|
|
11127
|
+
n.compute.forEach((step, i) => {
|
|
11128
|
+
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
11129
|
+
errors.push(`compute[${i}]: must be a compute step object`);
|
|
11130
|
+
} else {
|
|
11131
|
+
const s = step;
|
|
11132
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`compute[${i}]: missing required "bindTo" property`);
|
|
11133
|
+
if (typeof s.expr !== "string" || !s.expr) errors.push(`compute[${i}]: missing required "expr" string (JSONata expression)`);
|
|
11134
|
+
}
|
|
11135
|
+
});
|
|
11136
|
+
}
|
|
11137
|
+
}
|
|
11138
|
+
if (n.sources != null) {
|
|
11139
|
+
if (!Array.isArray(n.sources)) {
|
|
11140
|
+
errors.push("sources: must be an array");
|
|
11365
11141
|
} else {
|
|
11366
|
-
|
|
11367
|
-
if (!
|
|
11368
|
-
errors.push(`
|
|
11369
|
-
} else if (!expr.fn) {
|
|
11370
|
-
errors.push(`compute.${key}: missing required "fn" property`);
|
|
11142
|
+
n.sources.forEach((src, i) => {
|
|
11143
|
+
if (!src || typeof src !== "object" || Array.isArray(src)) {
|
|
11144
|
+
errors.push(`sources[${i}]: must be an object`);
|
|
11371
11145
|
} else {
|
|
11372
|
-
const
|
|
11373
|
-
if (!
|
|
11374
|
-
|
|
11146
|
+
const s = src;
|
|
11147
|
+
if (typeof s.bindTo !== "string" || !s.bindTo) errors.push(`sources[${i}]: missing required "bindTo" property`);
|
|
11148
|
+
if (s.outputFile != null && typeof s.outputFile !== "string") errors.push(`sources[${i}]: outputFile must be a string`);
|
|
11149
|
+
if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
|
|
11150
|
+
errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
|
|
11375
11151
|
}
|
|
11376
11152
|
}
|
|
11377
|
-
}
|
|
11153
|
+
});
|
|
11378
11154
|
}
|
|
11379
11155
|
}
|
|
11380
|
-
if (n.
|
|
11381
|
-
if (n.
|
|
11382
|
-
|
|
11383
|
-
errors.push("view: required for card nodes, must be an object");
|
|
11156
|
+
if (n.view != null) {
|
|
11157
|
+
if (typeof n.view !== "object" || Array.isArray(n.view)) {
|
|
11158
|
+
errors.push("view: must be an object");
|
|
11384
11159
|
} else {
|
|
11385
11160
|
const view = n.view;
|
|
11386
11161
|
if (!Array.isArray(view.elements) || view.elements.length === 0) {
|
|
@@ -11401,28 +11176,8 @@ function validateNode(node) {
|
|
|
11401
11176
|
}
|
|
11402
11177
|
});
|
|
11403
11178
|
}
|
|
11404
|
-
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout)))
|
|
11405
|
-
|
|
11406
|
-
}
|
|
11407
|
-
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) {
|
|
11408
|
-
errors.push("view.features: must be an object");
|
|
11409
|
-
}
|
|
11410
|
-
}
|
|
11411
|
-
}
|
|
11412
|
-
if (n.type === "source") {
|
|
11413
|
-
if (n.view != null) errors.push('Source nodes must not have "view" \u2014 use type "card" instead');
|
|
11414
|
-
if (n.source == null || typeof n.source !== "object" || Array.isArray(n.source)) {
|
|
11415
|
-
errors.push("source: required for source nodes, must be an object");
|
|
11416
|
-
} else {
|
|
11417
|
-
const src = n.source;
|
|
11418
|
-
if (!src.kind || !VALID_SOURCE_KINDS.has(src.kind)) {
|
|
11419
|
-
errors.push(`source.kind: required, must be one of: ${[...VALID_SOURCE_KINDS].join(", ")}`);
|
|
11420
|
-
}
|
|
11421
|
-
if (typeof src.bindTo !== "string" || !src.bindTo) {
|
|
11422
|
-
errors.push("source.bindTo: required, must be a state path string");
|
|
11423
|
-
} else if (!src.bindTo.startsWith("state.")) {
|
|
11424
|
-
errors.push('source.bindTo: must start with "state."');
|
|
11425
|
-
}
|
|
11179
|
+
if (view.layout != null && (typeof view.layout !== "object" || Array.isArray(view.layout))) errors.push("view.layout: must be an object");
|
|
11180
|
+
if (view.features != null && (typeof view.features !== "object" || Array.isArray(view.features))) errors.push("view.features: must be an object");
|
|
11426
11181
|
}
|
|
11427
11182
|
}
|
|
11428
11183
|
return { ok: errors.length === 0, errors };
|
|
@@ -11431,14 +11186,7 @@ var CardCompute = {
|
|
|
11431
11186
|
run,
|
|
11432
11187
|
eval: evalExpr,
|
|
11433
11188
|
resolve,
|
|
11434
|
-
validate: validateNode
|
|
11435
|
-
registerFunction,
|
|
11436
|
-
get functions() {
|
|
11437
|
-
const all = {};
|
|
11438
|
-
for (const k of Object.keys(_fns)) all[k] = _fns[k];
|
|
11439
|
-
for (const k of Object.keys(_customFns)) all[k] = _customFns[k];
|
|
11440
|
-
return all;
|
|
11441
|
-
}
|
|
11189
|
+
validate: validateNode
|
|
11442
11190
|
};
|
|
11443
11191
|
|
|
11444
11192
|
// src/continuous-event-graph/live-cards-bridge.ts
|
|
@@ -11471,19 +11219,26 @@ function liveCardsToReactiveGraph(input, options = {}) {
|
|
|
11471
11219
|
}
|
|
11472
11220
|
const sharedState = options.sharedState ?? /* @__PURE__ */ new Map();
|
|
11473
11221
|
const tasks = {};
|
|
11222
|
+
const allTokens = /* @__PURE__ */ new Set();
|
|
11223
|
+
const tokenToCardId = /* @__PURE__ */ new Map();
|
|
11224
|
+
for (const card of cards) {
|
|
11225
|
+
for (const binding of card.provides ?? [{ bindTo: card.id, src: `state.${card.id}` }]) {
|
|
11226
|
+
allTokens.add(binding.bindTo);
|
|
11227
|
+
tokenToCardId.set(binding.bindTo, card.id);
|
|
11228
|
+
}
|
|
11229
|
+
}
|
|
11474
11230
|
for (const card of cards) {
|
|
11475
|
-
const requires = card.
|
|
11231
|
+
const requires = card.requires ?? [];
|
|
11476
11232
|
for (const req of requires) {
|
|
11477
|
-
if (!
|
|
11478
|
-
throw new Error(`Card "${card.id}" requires "${req}" but no card
|
|
11233
|
+
if (!allTokens.has(req)) {
|
|
11234
|
+
throw new Error(`Card "${card.id}" requires "${req}" but no card provides that token`);
|
|
11479
11235
|
}
|
|
11480
11236
|
}
|
|
11481
11237
|
tasks[card.id] = {
|
|
11482
11238
|
requires: requires.length > 0 ? requires : void 0,
|
|
11483
|
-
provides: [card.id],
|
|
11239
|
+
provides: (card.provides ?? [{ bindTo: card.id, src: `state.${card.id}` }]).map((p) => p.bindTo),
|
|
11484
11240
|
taskHandlers: [card.id],
|
|
11485
|
-
|
|
11486
|
-
description: card.meta?.title ?? `${card.type}: ${card.id}`
|
|
11241
|
+
description: card.meta?.title ?? card.id
|
|
11487
11242
|
};
|
|
11488
11243
|
}
|
|
11489
11244
|
const config = {
|
|
@@ -11502,10 +11257,10 @@ function liveCardsToReactiveGraph(input, options = {}) {
|
|
|
11502
11257
|
graphRef.resolveCallback(token, data, errors);
|
|
11503
11258
|
};
|
|
11504
11259
|
for (const card of cards) {
|
|
11505
|
-
if (card.
|
|
11260
|
+
if (card.sources && card.sources.length > 0) {
|
|
11506
11261
|
handlers[card.id] = buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedState, getResolve);
|
|
11507
11262
|
} else {
|
|
11508
|
-
handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve);
|
|
11263
|
+
handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, tokenToCardId, getResolve);
|
|
11509
11264
|
}
|
|
11510
11265
|
}
|
|
11511
11266
|
const graph = createReactiveGraph(
|
|
@@ -11539,7 +11294,7 @@ function buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedSt
|
|
|
11539
11294
|
return "task-initiated";
|
|
11540
11295
|
};
|
|
11541
11296
|
}
|
|
11542
|
-
function buildCardHandler(card, cardHandlers, sharedState,
|
|
11297
|
+
function buildCardHandler(card, cardHandlers, sharedState, _cardMap, tokenToCardId, getResolve) {
|
|
11543
11298
|
if (cardHandlers[card.id]) {
|
|
11544
11299
|
const userHandler = cardHandlers[card.id];
|
|
11545
11300
|
return async (input) => {
|
|
@@ -11547,47 +11302,37 @@ function buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve)
|
|
|
11547
11302
|
};
|
|
11548
11303
|
}
|
|
11549
11304
|
return async (input) => {
|
|
11305
|
+
const requiresData = {};
|
|
11306
|
+
const requires = card.requires ?? [];
|
|
11307
|
+
for (const token of requires) {
|
|
11308
|
+
const producerId = tokenToCardId.get(token) ?? token;
|
|
11309
|
+
const upstreamState = sharedState.get(producerId);
|
|
11310
|
+
if (upstreamState) {
|
|
11311
|
+
requiresData[token] = upstreamState[token] ?? upstreamState;
|
|
11312
|
+
}
|
|
11313
|
+
}
|
|
11550
11314
|
const computeNode = {
|
|
11551
11315
|
id: card.id,
|
|
11552
11316
|
state: { ...card.state },
|
|
11317
|
+
requires: requiresData,
|
|
11553
11318
|
compute: card.compute
|
|
11554
11319
|
};
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
const upstreamCard = cardMap.get(upstreamId);
|
|
11562
|
-
if (upstreamCard?.data?.provides && upstreamState) {
|
|
11563
|
-
for (const [key, bindRef] of Object.entries(upstreamCard.data.provides)) {
|
|
11564
|
-
if (typeof bindRef === "string" && bindRef.startsWith("state.")) {
|
|
11565
|
-
const path = bindRef.slice(6);
|
|
11566
|
-
const value = deepGet2(upstreamState, path);
|
|
11567
|
-
if (value !== void 0) {
|
|
11568
|
-
computeNode.state[key] = value;
|
|
11569
|
-
}
|
|
11570
|
-
}
|
|
11571
|
-
}
|
|
11320
|
+
await CardCompute.run(computeNode);
|
|
11321
|
+
let resultData;
|
|
11322
|
+
if (card.provides && card.provides.length > 0) {
|
|
11323
|
+
resultData = {};
|
|
11324
|
+
for (const { bindTo, src } of card.provides) {
|
|
11325
|
+
resultData[bindTo] = CardCompute.resolve(computeNode, src);
|
|
11572
11326
|
}
|
|
11327
|
+
} else {
|
|
11328
|
+
resultData = { ...computeNode.state, ...computeNode.computed_values };
|
|
11573
11329
|
}
|
|
11574
|
-
|
|
11575
|
-
const resultState = { ...computeNode.state };
|
|
11330
|
+
const resultState = { ...computeNode.state, ...computeNode.computed_values };
|
|
11576
11331
|
sharedState.set(card.id, resultState);
|
|
11577
|
-
getResolve()(input.callbackToken,
|
|
11332
|
+
getResolve()(input.callbackToken, resultData);
|
|
11578
11333
|
return "task-initiated";
|
|
11579
11334
|
};
|
|
11580
11335
|
}
|
|
11581
|
-
function deepGet2(obj, path) {
|
|
11582
|
-
if (!path || !obj) return void 0;
|
|
11583
|
-
const parts = path.split(".");
|
|
11584
|
-
let cur = obj;
|
|
11585
|
-
for (const part of parts) {
|
|
11586
|
-
if (cur == null) return void 0;
|
|
11587
|
-
cur = cur[part];
|
|
11588
|
-
}
|
|
11589
|
-
return cur;
|
|
11590
|
-
}
|
|
11591
11336
|
|
|
11592
11337
|
// src/inference/core.ts
|
|
11593
11338
|
var DEFAULT_THRESHOLD = 0.5;
|
|
@@ -11840,6 +11585,6 @@ function createHttpAdapter(opts) {
|
|
|
11840
11585
|
};
|
|
11841
11586
|
}
|
|
11842
11587
|
|
|
11843
|
-
export { COMPLETION_STRATEGIES, CONFLICT_STRATEGIES, CardCompute, DEFAULTS, EXECUTION_MODES, EXECUTION_STATUS,
|
|
11588
|
+
export { COMPLETION_STRATEGIES, CONFLICT_STRATEGIES, CardCompute, DEFAULTS, EXECUTION_MODES, EXECUTION_STATUS, FileStore, StepMachine as FlowEngine, LocalStorageStore, MemoryJournal, MemoryStore, StepMachine, TASK_STATUS, addDynamicTask, addNode, addProvides, addRequires, apply, applyAll, applyEvent, applyEvents, applyInferences, applyStepResult, batch, buildInferencePrompt, checkCircuitBreaker, computeAvailableOutputs, computeStepInput, createCallbackHandler, createCliAdapter, createDefaultGraphEngineStore, createStepMachine as createEngine, createFireAndForgetHandler, createHttpAdapter, createInitialExecutionState, createInitialState, createLiveGraph, createNoopHandler, createReactiveGraph, createScriptHandler, createShellHandler, createStepMachine, createWebhookHandler, detectStuckState, disableNode, drainTokens, enableNode, exportGraphConfig, exportGraphConfigToFile, extractReturnData, flowToMermaid, getAllTasks, getCandidateTasks, getDownstream, getMaxExecutions, getNode, getProvides, getRefreshStrategy, getRequires, getTask, getUnreachableNodes, getUnreachableTokens, getUpstream, graphToMermaid, hasTask, inferAndApply, inferCompletions, injectTokens, inspect, isExecutionComplete, isNonActiveTask, isRerunnable, isTaskCompleted, isTaskRunning, liveCardsToReactiveGraph, loadGraphConfig, loadStepFlow, mutateGraph, next, planExecution, removeNode, removeProvides, removeRequires, resetNode, resolveConfigTemplates, resolveVariables, restore, schedule, snapshot, validateFlowSchema, validateGraph, validateGraphConfig, validateGraphSchema, validateLiveCardSchema, validateLiveGraph, validateReactiveGraph, validateStepFlowConfig };
|
|
11844
11589
|
//# sourceMappingURL=index.js.map
|
|
11845
11590
|
//# sourceMappingURL=index.js.map
|