yaml-flow 5.2.6 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +6 -6
  2. package/board-livecards-server-runtime.js +260 -35
  3. package/browser/board-livegraph-engine.js +61 -33
  4. package/browser/board-livegraph-engine.js.map +1 -1
  5. package/browser/card-compute.js +18 -18
  6. package/browser/live-cards.js +317 -156
  7. package/browser/live-cards.schema.json +15 -10
  8. package/dist/board-livegraph-runtime/index.cjs +61 -33
  9. package/dist/board-livegraph-runtime/index.cjs.map +1 -1
  10. package/dist/board-livegraph-runtime/index.d.cts +1 -1
  11. package/dist/board-livegraph-runtime/index.d.ts +1 -1
  12. package/dist/board-livegraph-runtime/index.js +61 -33
  13. package/dist/board-livegraph-runtime/index.js.map +1 -1
  14. package/dist/card-compute/index.cjs +101 -39
  15. package/dist/card-compute/index.cjs.map +1 -1
  16. package/dist/card-compute/index.d.cts +13 -8
  17. package/dist/card-compute/index.d.ts +13 -8
  18. package/dist/card-compute/index.js +101 -39
  19. package/dist/card-compute/index.js.map +1 -1
  20. package/dist/cli/board-live-cards-cli.cjs +7205 -202
  21. package/dist/cli/board-live-cards-cli.cjs.map +1 -1
  22. package/dist/cli/board-live-cards-cli.d.cts +6 -6
  23. package/dist/cli/board-live-cards-cli.d.ts +6 -6
  24. package/dist/cli/board-live-cards-cli.js +7204 -202
  25. package/dist/cli/board-live-cards-cli.js.map +1 -1
  26. package/dist/continuous-event-graph/index.cjs +59 -31
  27. package/dist/continuous-event-graph/index.cjs.map +1 -1
  28. package/dist/continuous-event-graph/index.d.cts +2 -2
  29. package/dist/continuous-event-graph/index.d.ts +2 -2
  30. package/dist/continuous-event-graph/index.js +59 -31
  31. package/dist/continuous-event-graph/index.js.map +1 -1
  32. package/dist/index.cjs +126 -54
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +1 -1
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.js +126 -54
  37. package/dist/index.js.map +1 -1
  38. package/dist/{live-cards-bridge-CeNxiVcm.d.ts → live-cards-bridge-EQjytzI_.d.ts} +10 -5
  39. package/dist/{live-cards-bridge-z_rJCSbi.d.cts → live-cards-bridge-x5XREkXm.d.cts} +10 -5
  40. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +1 -1
  41. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +1 -1
  42. package/examples/browser/boards/portfolio-tracker/cards/portfolio-risk-assessment.json +1 -1
  43. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +1 -1
  44. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +2 -2
  45. package/examples/browser/boards/portfolio-tracker/cards/rebalancing-strategy.json +1 -1
  46. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +10 -10
  47. package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
  48. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +1 -1
  49. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
  50. package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +2 -2
  51. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +1 -1
  52. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +1 -1
  53. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +1 -1
  54. package/examples/example-board/agent-instructions-cardlayout.md +29 -1
  55. package/examples/example-board/agent-instructions.md +271 -45
  56. package/examples/example-board/cards/card-concentration.json +8 -5
  57. package/examples/example-board/cards/card-market-prices.json +14 -9
  58. package/examples/example-board/cards/card-my-identity.json +28 -0
  59. package/examples/example-board/cards/card-portfolio-value.json +1 -1
  60. package/examples/example-board/cards/card-portfolio.json +1 -1
  61. package/examples/example-board/cards/card-rebalance-impact.json +65 -0
  62. package/examples/example-board/cards/card-rebalance-sim.json +67 -0
  63. package/examples/example-board/demo-chat-handler.js +2 -1
  64. package/examples/example-board/demo-server-config.json +6 -1
  65. package/examples/example-board/demo-server.js +91 -8
  66. package/examples/example-board/demo-shell-browser.html +6 -6
  67. package/examples/example-board/demo-shell-with-server.html +4 -4
  68. package/examples/example-board/demo-task-executor.js +457 -246
  69. package/examples/example-board/scripts/copilot_wrapper.bat +16 -0
  70. package/examples/example-board/scripts/copilot_wrapper_helper.ps1 +19 -10
  71. package/examples/example-board/scripts/workiq_wrapper.mjs +66 -0
  72. package/examples/npm-libs/continuous-event-graph/live-cards-board.ts +5 -5
  73. package/examples/npm-libs/continuous-event-graph/soc-incident-board.ts +3 -3
  74. package/examples/npm-libs/event-graph/research-pipeline.ts +5 -5
  75. package/examples/npm-libs/graph-of-graphs/multi-stage-etl.ts +9 -9
  76. package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
  77. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +1 -1
  78. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
  79. package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +3 -3
  80. package/examples/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +1 -1
  81. package/examples/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +1 -1
  82. package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +1 -1
  83. package/package.json +2 -2
  84. package/schema/live-cards.schema.json +15 -10
@@ -80,10 +80,10 @@
80
80
  "type": "array",
81
81
  "items": {
82
82
  "type": "object",
83
- "required": ["bindTo", "src"],
83
+ "required": ["bindTo", "ref"],
84
84
  "properties": {
85
85
  "bindTo": { "type": "string", "description": "Token name published downstream" },
86
- "src": { "type": "string", "description": "Path to read value from (card_data.*, requires.*, fetched_sources.*, computed_values.*)" }
86
+ "ref": { "type": "string", "description": "Path to read value from (card_data.*, requires.*, fetched_sources.*, computed_values.*)" }
87
87
  }
88
88
  },
89
89
  "description": "Explicit bindings exposing computed or card_data values downstream as named tokens"
@@ -100,14 +100,19 @@
100
100
  },
101
101
 
102
102
  "source_def": {
103
- "description": "One source entry. The engine requires 'bindTo' (compute namespace key) and 'outputFile' (delivery signal path). bindTo and outputFile must be unique across all sources in a card. Every other property is yours — 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.",
103
+ "description": "One source entry. The engine requires 'bindTo' (compute namespace key) and 'outputFile' (delivery signal path). bindTo and outputFile must be unique across all source_defs in a card. Every other property is yours — 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.",
104
104
  "type": "object",
105
105
  "required": ["bindTo", "outputFile"],
106
106
  "additionalProperties": true,
107
107
  "properties": {
108
108
  "bindTo": { "type": "string", "description": "Key under fetched_sources.* available in compute expressions" },
109
109
  "outputFile": { "type": "string", "description": "Board-relative path the executor writes its JSON result to. Presence of this file signals delivery." },
110
- "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." },
110
+ "projections": {
111
+ "type": "object",
112
+ "description": "Named data projections from card_data or requires, evaluated before the executor is called. Each key is a ref name; each value is a JSONata expression rooted at card_data or requires. The resolved values are passed to the executor as _projections. fetched_sources, computed_values, and source_defs are not accessible here — sources run before those exist.",
113
+ "additionalProperties": { "type": "string" }
114
+ },
115
+ "optionalForCompletionGating": { "type": "boolean", "default": false, "description": "When true this source does not gate card completion. Default false when absent, so source_defs are completion-gating by default." },
111
116
  "timeout": { "type": "integer", "minimum": 0, "default": 120000, "description": "Executor/script timeout in ms. Default: 120 000 (2 min)." },
112
117
  "script": { "type": "string", "description": "Legacy direct-run: shell command executed when no .task-executor is registered. stdout is captured as the result." }
113
118
  }
@@ -121,7 +126,7 @@
121
126
  "kind": {
122
127
  "enum": ["metric", "table", "editable-table", "chart", "form", "filter", "list",
123
128
  "notes", "todo", "alert", "narrative", "badge", "text",
124
- "markdown", "custom", "actions"]
129
+ "markdown", "ref", "custom", "actions"]
125
130
  },
126
131
  "label": { "type": "string", "description": "Heading above this element" },
127
132
  "className": { "type": "string", "description": "Bootstrap grid class, e.g. 'col-12 col-md-6'" },
@@ -215,7 +220,7 @@
215
220
  },
216
221
 
217
222
  "title": "LiveCard",
218
- "description": "A unified card node. Behavior depends on which sections are present (sources, compute, view, etc.)",
223
+ "description": "A unified card node. Behavior depends on which sections are present (source_defs, compute, view, etc.)",
219
224
  "type": "object",
220
225
  "required": ["id"],
221
226
  "additionalProperties": false,
@@ -258,22 +263,22 @@
258
263
  },
259
264
  "llm_task_completion_inference": {
260
265
  "type": "object",
261
- "description": "Runtime state written by the inference adapter (advanced/undocumented). Prefer the standard sources → compute → provides pattern for LLM-based signals.",
266
+ "description": "Runtime state written by the inference adapter (advanced/undocumented). Prefer the standard source_defs → compute → provides pattern for LLM-based signals.",
262
267
  "properties": {
263
268
  "inferenceRequested": { "type": "string", "format": "date-time", "description": "Timestamp when the latest inference request was initiated" },
264
269
  "inferenceCompletedAt": { "type": "string", "format": "date-time", "description": "Timestamp when the latest inference request completed" },
265
270
  "isTaskCompleted": { "type": "boolean", "description": "Whether the task is considered complete by the adapter" },
266
271
  "reasoning": { "type": "string", "description": "Explanation of completion decision" },
267
- "evidence": { "type": "array", "description": "Supporting evidence from sources/compute" }
272
+ "evidence": { "type": "array", "description": "Supporting evidence from source_defs/compute" }
268
273
  },
269
274
  "additionalProperties": true
270
275
  }
271
276
  },
272
277
  "additionalProperties": true
273
278
  },
274
- "sources": {
279
+ "source_defs": {
275
280
  "type": "array",
276
- "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.",
281
+ "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 source_defs that should not block task-completed.",
277
282
  "items": { "$ref": "#/definitions/source_def" }
278
283
  },
279
284
  "compute": {
@@ -70,6 +70,7 @@ function resolve(node, path) {
70
70
  var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
71
71
  "metric",
72
72
  "table",
73
+ "editable-table",
73
74
  "chart",
74
75
  "form",
75
76
  "filter",
@@ -81,9 +82,11 @@ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
81
82
  "badge",
82
83
  "text",
83
84
  "markdown",
84
- "custom"
85
+ "ref",
86
+ "custom",
87
+ "actions"
85
88
  ]);
86
- var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "card_data", "compute", "sources"]);
89
+ var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "card_data", "compute", "source_defs"]);
87
90
  function validateNode(node) {
88
91
  const errors = [];
89
92
  if (!node || typeof node !== "object" || Array.isArray(node)) {
@@ -109,15 +112,15 @@ function validateNode(node) {
109
112
  if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
110
113
  if (n.provides != null) {
111
114
  if (!Array.isArray(n.provides)) {
112
- errors.push("provides: must be an array of { bindTo, src } bindings");
115
+ errors.push("provides: must be an array of { bindTo, ref } bindings");
113
116
  } else {
114
117
  n.provides.forEach((p, i) => {
115
118
  if (!p || typeof p !== "object" || Array.isArray(p)) {
116
- errors.push(`provides[${i}]: must be an object with bindTo and src`);
119
+ errors.push(`provides[${i}]: must be an object with bindTo and ref`);
117
120
  } else {
118
121
  const b = p;
119
122
  if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
120
- if (typeof b.src !== "string" || !b.src) errors.push(`provides[${i}]: missing required "src" string`);
123
+ if (typeof b.ref !== "string" || !b.ref) errors.push(`provides[${i}]: missing required "ref" string`);
121
124
  }
122
125
  });
123
126
  }
@@ -137,35 +140,35 @@ function validateNode(node) {
137
140
  });
138
141
  }
139
142
  }
140
- if (n.sources != null) {
141
- if (!Array.isArray(n.sources)) {
142
- errors.push("sources: must be an array");
143
+ if (n.source_defs != null) {
144
+ if (!Array.isArray(n.source_defs)) {
145
+ errors.push("source_defs: must be an array");
143
146
  } else {
144
147
  const bindTos = /* @__PURE__ */ new Set();
145
148
  const outputFiles = /* @__PURE__ */ new Set();
146
- n.sources.forEach((src, i) => {
149
+ n.source_defs.forEach((src, i) => {
147
150
  if (!src || typeof src !== "object" || Array.isArray(src)) {
148
- errors.push(`sources[${i}]: must be an object`);
151
+ errors.push(`source_defs[${i}]: must be an object`);
149
152
  } else {
150
153
  const s = src;
151
154
  if (typeof s.bindTo !== "string" || !s.bindTo) {
152
- errors.push(`sources[${i}]: missing required "bindTo" property`);
155
+ errors.push(`source_defs[${i}]: missing required "bindTo" property`);
153
156
  } else {
154
157
  if (bindTos.has(s.bindTo)) {
155
- errors.push(`sources[${i}]: bindTo "${s.bindTo}" is not unique across sources`);
158
+ errors.push(`source_defs[${i}]: bindTo "${s.bindTo}" is not unique across source_defs`);
156
159
  }
157
160
  bindTos.add(s.bindTo);
158
161
  }
159
162
  if (typeof s.outputFile !== "string" || !s.outputFile) {
160
- errors.push(`sources[${i}]: missing required "outputFile" property`);
163
+ errors.push(`source_defs[${i}]: missing required "outputFile" property`);
161
164
  } else {
162
165
  if (outputFiles.has(s.outputFile)) {
163
- errors.push(`sources[${i}]: outputFile "${s.outputFile}" is not unique across sources`);
166
+ errors.push(`source_defs[${i}]: outputFile "${s.outputFile}" is not unique across source_defs`);
164
167
  }
165
168
  outputFiles.add(s.outputFile);
166
169
  }
167
170
  if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
168
- errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
171
+ errors.push(`source_defs[${i}]: optionalForCompletionGating must be a boolean`);
169
172
  }
170
173
  }
171
174
  });
@@ -200,14 +203,29 @@ function validateNode(node) {
200
203
  }
201
204
  return { ok: errors.length === 0, errors };
202
205
  }
203
- function enrichSources(sources, context) {
204
- if (!sources || sources.length === 0) return [];
205
- return sources.map((src) => ({
206
- ...src,
207
- _requires: context.requires ?? {},
208
- _sourcesData: context.sourcesData ?? {},
209
- _computed_values: context.computed_values ?? {}
210
- }));
206
+ async function enrichSources(source_defs, context) {
207
+ if (!source_defs || source_defs.length === 0) return [];
208
+ const evalCtx = {
209
+ card_data: context.card_data ?? {},
210
+ requires: context.requires ?? {}
211
+ };
212
+ return Promise.all(
213
+ source_defs.map(async (src) => {
214
+ const _projections = {};
215
+ if (src.projections && typeof src.projections === "object" && !Array.isArray(src.projections)) {
216
+ for (const [key, expr] of Object.entries(src.projections)) {
217
+ if (typeof expr === "string" && expr.trim().length > 0) {
218
+ try {
219
+ _projections[key] = await jsonata2__default.default(expr).evaluate(evalCtx);
220
+ } catch {
221
+ _projections[key] = void 0;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ return { ...src, _projections };
227
+ })
228
+ );
211
229
  }
212
230
  var CardCompute = {
213
231
  run,
@@ -908,6 +926,7 @@ function createReactiveGraph(configOrLive, options, executionId) {
908
926
  const inputQueue = new MemoryJournal();
909
927
  let live = "state" in configOrLive && "config" in configOrLive ? configOrLive : createLiveGraph(configOrLive, executionId);
910
928
  let disposed = false;
929
+ const pendingHandlers = /* @__PURE__ */ new Set();
911
930
  const handlers = new Map(Object.entries(initialHandlers));
912
931
  const internalJournal = new MemoryJournal();
913
932
  let draining = false;
@@ -950,7 +969,7 @@ function createReactiveGraph(configOrLive, options, executionId) {
950
969
  const taskState = live.state.tasks[taskName];
951
970
  if (!taskState || taskState.status !== "running") continue;
952
971
  const callbackToken = encodeCallbackToken(taskName);
953
- runPipeline(taskName, callbackToken, update).catch((error) => {
972
+ const p = runPipeline(taskName, callbackToken, update).catch((error) => {
954
973
  if (disposed) return;
955
974
  internalJournal.append({
956
975
  type: "task-failed",
@@ -959,7 +978,10 @@ function createReactiveGraph(configOrLive, options, executionId) {
959
978
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
960
979
  });
961
980
  drain();
981
+ }).finally(() => {
982
+ pendingHandlers.delete(p);
962
983
  });
984
+ pendingHandlers.add(p);
963
985
  }
964
986
  }
965
987
  }
@@ -1019,7 +1041,7 @@ function createReactiveGraph(configOrLive, options, executionId) {
1019
1041
  });
1020
1042
  drain();
1021
1043
  const callbackToken = encodeCallbackToken(taskName);
1022
- runPipeline(taskName, callbackToken).catch((error) => {
1044
+ const p = runPipeline(taskName, callbackToken).catch((error) => {
1023
1045
  if (disposed) return;
1024
1046
  internalJournal.append({
1025
1047
  type: "task-failed",
@@ -1028,7 +1050,10 @@ function createReactiveGraph(configOrLive, options, executionId) {
1028
1050
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1029
1051
  });
1030
1052
  drain();
1053
+ }).finally(() => {
1054
+ pendingHandlers.delete(p);
1031
1055
  });
1056
+ pendingHandlers.add(p);
1032
1057
  }
1033
1058
  return {
1034
1059
  push(event) {
@@ -1142,7 +1167,10 @@ function createReactiveGraph(configOrLive, options, executionId) {
1142
1167
  getSchedule() {
1143
1168
  return schedule(live);
1144
1169
  },
1145
- dispose() {
1170
+ async dispose(options2) {
1171
+ if (options2?.wait && pendingHandlers.size > 0) {
1172
+ await Promise.allSettled([...pendingHandlers]);
1173
+ }
1146
1174
  disposed = true;
1147
1175
  }
1148
1176
  };
@@ -1164,7 +1192,7 @@ function toTaskConfig(card) {
1164
1192
  function buildTokenProviders(cards) {
1165
1193
  const tokenToCardId = /* @__PURE__ */ new Map();
1166
1194
  for (const [cardId, card] of cards.entries()) {
1167
- const bindings = card.provides && card.provides.length > 0 ? card.provides : [{ bindTo: cardId, src: "card_data" }];
1195
+ const bindings = card.provides && card.provides.length > 0 ? card.provides : [{ bindTo: cardId, ref: "card_data" }];
1168
1196
  for (const binding of bindings) tokenToCardId.set(binding.bindTo, cardId);
1169
1197
  }
1170
1198
  return tokenToCardId;
@@ -1310,14 +1338,14 @@ function createBoardLiveGraphRuntime(input, options = {}) {
1310
1338
  requiresData[token] = providesData2[token];
1311
1339
  }
1312
1340
  const sourcesData = {};
1313
- if (card.sources && card.sources.length > 0) {
1341
+ if (card.source_defs && card.source_defs.length > 0) {
1314
1342
  const adapter = sourceAdapters[cardId] ?? defaultSourceAdapter;
1315
1343
  const fetched = taskExecutor ? await taskExecutor({ card, input: inputArgs }) : adapter ? await adapter({ card, input: inputArgs }) : void 0;
1316
1344
  if (fetched && typeof fetched === "object") {
1317
- for (const src of card.sources) {
1345
+ for (const src of card.source_defs) {
1318
1346
  if (Object.prototype.hasOwnProperty.call(fetched, src.bindTo)) {
1319
1347
  sourcesData[src.bindTo] = fetched[src.bindTo];
1320
- } else if (card.sources.length === 1) {
1348
+ } else if (card.source_defs.length === 1) {
1321
1349
  sourcesData[src.bindTo] = fetched;
1322
1350
  }
1323
1351
  }
@@ -1327,7 +1355,7 @@ function createBoardLiveGraphRuntime(input, options = {}) {
1327
1355
  id: card.id,
1328
1356
  card_data: deepClone(card.card_data ?? {}),
1329
1357
  requires: requiresData,
1330
- sources: card.sources,
1358
+ source_defs: card.source_defs,
1331
1359
  compute: card.compute
1332
1360
  };
1333
1361
  computeNode._sourcesData = sourcesData;
@@ -1336,8 +1364,8 @@ function createBoardLiveGraphRuntime(input, options = {}) {
1336
1364
  }
1337
1365
  const providesData = {};
1338
1366
  if (card.provides && card.provides.length > 0) {
1339
- for (const { bindTo, src } of card.provides) {
1340
- providesData[bindTo] = CardCompute.resolve(computeNode, src);
1367
+ for (const { bindTo, ref } of card.provides) {
1368
+ providesData[bindTo] = CardCompute.resolve(computeNode, ref);
1341
1369
  }
1342
1370
  } else {
1343
1371
  providesData[card.id] = {