yaml-flow 5.2.5 → 5.2.8

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 +57 -32
  4. package/browser/board-livegraph-engine.js.map +1 -1
  5. package/browser/card-compute.js +17 -17
  6. package/browser/live-cards.js +139 -12
  7. package/browser/live-cards.schema.json +14 -9
  8. package/dist/board-livegraph-runtime/index.cjs +57 -32
  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 +57 -32
  13. package/dist/board-livegraph-runtime/index.js.map +1 -1
  14. package/dist/card-compute/index.cjs +96 -38
  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 +96 -38
  19. package/dist/card-compute/index.js.map +1 -1
  20. package/dist/cli/board-live-cards-cli.cjs +7200 -201
  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 +7199 -201
  25. package/dist/cli/board-live-cards-cli.js.map +1 -1
  26. package/dist/continuous-event-graph/index.cjs +55 -30
  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 +55 -30
  31. package/dist/continuous-event-graph/index.js.map +1 -1
  32. package/dist/index.cjs +121 -53
  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 +121 -53
  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 +1 -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 +57 -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 +79 -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 +436 -246
  69. package/examples/example-board/scripts/copilot_wrapper.bat +157 -0
  70. package/examples/example-board/scripts/copilot_wrapper_helper.ps1 +190 -0
  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 +14 -9
package/dist/index.cjs CHANGED
@@ -10969,6 +10969,7 @@ function createReactiveGraph(configOrLive, options, executionId) {
10969
10969
  const inputQueue = new MemoryJournal();
10970
10970
  let live = "state" in configOrLive && "config" in configOrLive ? configOrLive : createLiveGraph(configOrLive, executionId);
10971
10971
  let disposed = false;
10972
+ const pendingHandlers = /* @__PURE__ */ new Set();
10972
10973
  const handlers = new Map(Object.entries(initialHandlers));
10973
10974
  const internalJournal = new MemoryJournal();
10974
10975
  let draining = false;
@@ -11011,7 +11012,7 @@ function createReactiveGraph(configOrLive, options, executionId) {
11011
11012
  const taskState = live.state.tasks[taskName];
11012
11013
  if (!taskState || taskState.status !== "running") continue;
11013
11014
  const callbackToken = encodeCallbackToken(taskName);
11014
- runPipeline(taskName, callbackToken, update).catch((error) => {
11015
+ const p = runPipeline(taskName, callbackToken, update).catch((error) => {
11015
11016
  if (disposed) return;
11016
11017
  internalJournal.append({
11017
11018
  type: "task-failed",
@@ -11020,7 +11021,10 @@ function createReactiveGraph(configOrLive, options, executionId) {
11020
11021
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
11021
11022
  });
11022
11023
  drain();
11024
+ }).finally(() => {
11025
+ pendingHandlers.delete(p);
11023
11026
  });
11027
+ pendingHandlers.add(p);
11024
11028
  }
11025
11029
  }
11026
11030
  }
@@ -11080,7 +11084,7 @@ function createReactiveGraph(configOrLive, options, executionId) {
11080
11084
  });
11081
11085
  drain();
11082
11086
  const callbackToken = encodeCallbackToken(taskName);
11083
- runPipeline(taskName, callbackToken).catch((error) => {
11087
+ const p = runPipeline(taskName, callbackToken).catch((error) => {
11084
11088
  if (disposed) return;
11085
11089
  internalJournal.append({
11086
11090
  type: "task-failed",
@@ -11089,7 +11093,10 @@ function createReactiveGraph(configOrLive, options, executionId) {
11089
11093
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
11090
11094
  });
11091
11095
  drain();
11096
+ }).finally(() => {
11097
+ pendingHandlers.delete(p);
11092
11098
  });
11099
+ pendingHandlers.add(p);
11093
11100
  }
11094
11101
  return {
11095
11102
  push(event) {
@@ -11203,7 +11210,10 @@ function createReactiveGraph(configOrLive, options, executionId) {
11203
11210
  getSchedule() {
11204
11211
  return schedule(live);
11205
11212
  },
11206
- dispose() {
11213
+ async dispose(options2) {
11214
+ if (options2?.wait && pendingHandlers.size > 0) {
11215
+ await Promise.allSettled([...pendingHandlers]);
11216
+ }
11207
11217
  disposed = true;
11208
11218
  }
11209
11219
  };
@@ -11670,10 +11680,10 @@ var live_cards_schema_default = {
11670
11680
  type: "array",
11671
11681
  items: {
11672
11682
  type: "object",
11673
- required: ["bindTo", "src"],
11683
+ required: ["bindTo", "ref"],
11674
11684
  properties: {
11675
11685
  bindTo: { type: "string", description: "Token name published downstream" },
11676
- src: { type: "string", description: "Path to read value from (card_data.*, requires.*, fetched_sources.*, computed_values.*)" }
11686
+ ref: { type: "string", description: "Path to read value from (card_data.*, requires.*, fetched_sources.*, computed_values.*)" }
11677
11687
  }
11678
11688
  },
11679
11689
  description: "Explicit bindings exposing computed or card_data values downstream as named tokens"
@@ -11688,14 +11698,19 @@ var live_cards_schema_default = {
11688
11698
  }
11689
11699
  },
11690
11700
  source_def: {
11691
- 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 \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.",
11701
+ 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 \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.",
11692
11702
  type: "object",
11693
11703
  required: ["bindTo", "outputFile"],
11694
11704
  additionalProperties: true,
11695
11705
  properties: {
11696
11706
  bindTo: { type: "string", description: "Key under fetched_sources.* available in compute expressions" },
11697
11707
  outputFile: { type: "string", description: "Board-relative path the executor writes its JSON result to. Presence of this file signals delivery." },
11698
- 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." },
11708
+ projections: {
11709
+ type: "object",
11710
+ 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 \u2014 sources run before those exist.",
11711
+ additionalProperties: { type: "string" }
11712
+ },
11713
+ 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." },
11699
11714
  timeout: { type: "integer", minimum: 0, default: 12e4, description: "Executor/script timeout in ms. Default: 120 000 (2 min)." },
11700
11715
  script: { type: "string", description: "Legacy direct-run: shell command executed when no .task-executor is registered. stdout is captured as the result." }
11701
11716
  }
@@ -11815,7 +11830,7 @@ var live_cards_schema_default = {
11815
11830
  }
11816
11831
  },
11817
11832
  title: "LiveCard",
11818
- description: "A unified card node. Behavior depends on which sections are present (sources, compute, view, etc.)",
11833
+ description: "A unified card node. Behavior depends on which sections are present (source_defs, compute, view, etc.)",
11819
11834
  type: "object",
11820
11835
  required: ["id"],
11821
11836
  additionalProperties: false,
@@ -11858,22 +11873,22 @@ var live_cards_schema_default = {
11858
11873
  },
11859
11874
  llm_task_completion_inference: {
11860
11875
  type: "object",
11861
- description: "Runtime state written by the inference adapter (advanced/undocumented). Prefer the standard sources \u2192 compute \u2192 provides pattern for LLM-based signals.",
11876
+ description: "Runtime state written by the inference adapter (advanced/undocumented). Prefer the standard source_defs \u2192 compute \u2192 provides pattern for LLM-based signals.",
11862
11877
  properties: {
11863
11878
  inferenceRequested: { type: "string", format: "date-time", description: "Timestamp when the latest inference request was initiated" },
11864
11879
  inferenceCompletedAt: { type: "string", format: "date-time", description: "Timestamp when the latest inference request completed" },
11865
11880
  isTaskCompleted: { type: "boolean", description: "Whether the task is considered complete by the adapter" },
11866
11881
  reasoning: { type: "string", description: "Explanation of completion decision" },
11867
- evidence: { type: "array", description: "Supporting evidence from sources/compute" }
11882
+ evidence: { type: "array", description: "Supporting evidence from source_defs/compute" }
11868
11883
  },
11869
11884
  additionalProperties: true
11870
11885
  }
11871
11886
  },
11872
11887
  additionalProperties: true
11873
11888
  },
11874
- sources: {
11889
+ source_defs: {
11875
11890
  type: "array",
11876
- 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.",
11891
+ 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.",
11877
11892
  items: { $ref: "#/definitions/source_def" }
11878
11893
  },
11879
11894
  compute: {
@@ -11891,8 +11906,8 @@ var live_cards_schema_default = {
11891
11906
  // src/card-compute/schema-validator.ts
11892
11907
  var import_ajv3 = __toESM(require_ajv());
11893
11908
  var _compiled3 = null;
11894
- var NAMESPACE_REFERENCE_RE = /\b(card_data|requires|fetched_sources|computed_values|sources)\b/g;
11895
- var ROOT_PATH_NAMESPACE_RE = /^\s*(card_data|requires|fetched_sources|computed_values|sources)(\.|$)/;
11909
+ var NAMESPACE_REFERENCE_RE = /\b(card_data|requires|fetched_sources|computed_values|source_defs)\b/g;
11910
+ var ROOT_PATH_NAMESPACE_RE = /^\s*(card_data|requires|fetched_sources|computed_values|source_defs)(\.|$)/;
11896
11911
  function referencedNamespaces(expression) {
11897
11912
  const namespaces = /* @__PURE__ */ new Set();
11898
11913
  let match;
@@ -11957,22 +11972,22 @@ function validateLiveCardSchema(node) {
11957
11972
  return `${path}: ${e.message ?? "unknown error"}`;
11958
11973
  });
11959
11974
  if (node && typeof node === "object" && !Array.isArray(node)) {
11960
- const sources = node.sources;
11961
- if (Array.isArray(sources)) {
11975
+ const source_defs = node.source_defs;
11976
+ if (Array.isArray(source_defs)) {
11962
11977
  const bindTos = /* @__PURE__ */ new Set();
11963
11978
  const outputFiles = /* @__PURE__ */ new Set();
11964
- sources.forEach((src, i) => {
11979
+ source_defs.forEach((src, i) => {
11965
11980
  if (!src || typeof src !== "object" || Array.isArray(src)) return;
11966
11981
  const s = src;
11967
11982
  if (typeof s.bindTo === "string" && s.bindTo) {
11968
11983
  if (bindTos.has(s.bindTo)) {
11969
- errors.push(`/sources/${i}/bindTo: bindTo "${s.bindTo}" must be unique across all sources`);
11984
+ errors.push(`/source_defs/${i}/bindTo: bindTo "${s.bindTo}" must be unique across all source_defs`);
11970
11985
  }
11971
11986
  bindTos.add(s.bindTo);
11972
11987
  }
11973
11988
  if (typeof s.outputFile === "string" && s.outputFile) {
11974
11989
  if (outputFiles.has(s.outputFile)) {
11975
- errors.push(`/sources/${i}/outputFile: outputFile "${s.outputFile}" must be unique across all sources`);
11990
+ errors.push(`/source_defs/${i}/outputFile: outputFile "${s.outputFile}" must be unique across all source_defs`);
11976
11991
  }
11977
11992
  outputFiles.add(s.outputFile);
11978
11993
  }
@@ -12002,10 +12017,48 @@ function validateLiveCardRuntimeExpressions(node) {
12002
12017
  );
12003
12018
  });
12004
12019
  }
12020
+ const VALID_PROVIDES_SRC_NAMESPACES = /* @__PURE__ */ new Set([
12021
+ "card_data",
12022
+ "requires",
12023
+ "fetched_sources",
12024
+ "computed_values"
12025
+ ]);
12026
+ const provides = asRecord.provides;
12027
+ if (Array.isArray(provides)) {
12028
+ provides.forEach((entry, i) => {
12029
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return;
12030
+ const ref = entry.ref;
12031
+ if (typeof ref !== "string" || ref.trim().length === 0) return;
12032
+ const rootNamespace = parseRootPathNamespace(ref);
12033
+ if (rootNamespace === null) {
12034
+ errors.push(`/provides/${i}/ref: path "${ref}" must start with a valid namespace (${[...VALID_PROVIDES_SRC_NAMESPACES].join(", ")})`);
12035
+ } else if (!VALID_PROVIDES_SRC_NAMESPACES.has(rootNamespace)) {
12036
+ errors.push(`/provides/${i}/ref: disallowed namespace "${rootNamespace}" in path "${ref}" (valid: ${[...VALID_PROVIDES_SRC_NAMESPACES].join(", ")})`);
12037
+ }
12038
+ });
12039
+ }
12005
12040
  const view = asRecord.view;
12006
12041
  if (view && typeof view === "object" && !Array.isArray(view)) {
12007
12042
  walkViewPathReferences(view, "/view", errors);
12008
12043
  }
12044
+ const VALID_PROJECTION_NAMESPACES = /* @__PURE__ */ new Set(["card_data", "requires"]);
12045
+ const source_defs = asRecord.source_defs;
12046
+ if (Array.isArray(source_defs)) {
12047
+ source_defs.forEach((srcDef, i) => {
12048
+ if (!srcDef || typeof srcDef !== "object" || Array.isArray(srcDef)) return;
12049
+ const projections = srcDef.projections;
12050
+ if (!projections || typeof projections !== "object" || Array.isArray(projections)) return;
12051
+ for (const [key, exprVal] of Object.entries(projections)) {
12052
+ if (typeof exprVal !== "string" || exprVal.trim().length === 0) continue;
12053
+ validateJsonataExprWithNamespaces(
12054
+ exprVal,
12055
+ `/source_defs/${i}/projections/${key}`,
12056
+ VALID_PROJECTION_NAMESPACES,
12057
+ errors
12058
+ );
12059
+ }
12060
+ });
12061
+ }
12009
12062
  return { ok: errors.length === 0, errors };
12010
12063
  }
12011
12064
  function validateLiveCard(node) {
@@ -12092,7 +12145,7 @@ var VALID_ELEMENT_KINDS = /* @__PURE__ */ new Set([
12092
12145
  "markdown",
12093
12146
  "custom"
12094
12147
  ]);
12095
- var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "card_data", "compute", "sources"]);
12148
+ var ALLOWED_KEYS = /* @__PURE__ */ new Set(["id", "meta", "requires", "provides", "view", "card_data", "compute", "source_defs"]);
12096
12149
  function validateNode(node) {
12097
12150
  const errors = [];
12098
12151
  if (!node || typeof node !== "object" || Array.isArray(node)) {
@@ -12118,15 +12171,15 @@ function validateNode(node) {
12118
12171
  if (n.requires != null && !Array.isArray(n.requires)) errors.push("requires: must be an array of strings");
12119
12172
  if (n.provides != null) {
12120
12173
  if (!Array.isArray(n.provides)) {
12121
- errors.push("provides: must be an array of { bindTo, src } bindings");
12174
+ errors.push("provides: must be an array of { bindTo, ref } bindings");
12122
12175
  } else {
12123
12176
  n.provides.forEach((p, i) => {
12124
12177
  if (!p || typeof p !== "object" || Array.isArray(p)) {
12125
- errors.push(`provides[${i}]: must be an object with bindTo and src`);
12178
+ errors.push(`provides[${i}]: must be an object with bindTo and ref`);
12126
12179
  } else {
12127
12180
  const b = p;
12128
12181
  if (typeof b.bindTo !== "string" || !b.bindTo) errors.push(`provides[${i}]: missing required "bindTo" string`);
12129
- if (typeof b.src !== "string" || !b.src) errors.push(`provides[${i}]: missing required "src" string`);
12182
+ if (typeof b.ref !== "string" || !b.ref) errors.push(`provides[${i}]: missing required "ref" string`);
12130
12183
  }
12131
12184
  });
12132
12185
  }
@@ -12146,35 +12199,35 @@ function validateNode(node) {
12146
12199
  });
12147
12200
  }
12148
12201
  }
12149
- if (n.sources != null) {
12150
- if (!Array.isArray(n.sources)) {
12151
- errors.push("sources: must be an array");
12202
+ if (n.source_defs != null) {
12203
+ if (!Array.isArray(n.source_defs)) {
12204
+ errors.push("source_defs: must be an array");
12152
12205
  } else {
12153
12206
  const bindTos = /* @__PURE__ */ new Set();
12154
12207
  const outputFiles = /* @__PURE__ */ new Set();
12155
- n.sources.forEach((src, i) => {
12208
+ n.source_defs.forEach((src, i) => {
12156
12209
  if (!src || typeof src !== "object" || Array.isArray(src)) {
12157
- errors.push(`sources[${i}]: must be an object`);
12210
+ errors.push(`source_defs[${i}]: must be an object`);
12158
12211
  } else {
12159
12212
  const s = src;
12160
12213
  if (typeof s.bindTo !== "string" || !s.bindTo) {
12161
- errors.push(`sources[${i}]: missing required "bindTo" property`);
12214
+ errors.push(`source_defs[${i}]: missing required "bindTo" property`);
12162
12215
  } else {
12163
12216
  if (bindTos.has(s.bindTo)) {
12164
- errors.push(`sources[${i}]: bindTo "${s.bindTo}" is not unique across sources`);
12217
+ errors.push(`source_defs[${i}]: bindTo "${s.bindTo}" is not unique across source_defs`);
12165
12218
  }
12166
12219
  bindTos.add(s.bindTo);
12167
12220
  }
12168
12221
  if (typeof s.outputFile !== "string" || !s.outputFile) {
12169
- errors.push(`sources[${i}]: missing required "outputFile" property`);
12222
+ errors.push(`source_defs[${i}]: missing required "outputFile" property`);
12170
12223
  } else {
12171
12224
  if (outputFiles.has(s.outputFile)) {
12172
- errors.push(`sources[${i}]: outputFile "${s.outputFile}" is not unique across sources`);
12225
+ errors.push(`source_defs[${i}]: outputFile "${s.outputFile}" is not unique across source_defs`);
12173
12226
  }
12174
12227
  outputFiles.add(s.outputFile);
12175
12228
  }
12176
12229
  if (s.optionalForCompletionGating != null && typeof s.optionalForCompletionGating !== "boolean") {
12177
- errors.push(`sources[${i}]: optionalForCompletionGating must be a boolean`);
12230
+ errors.push(`source_defs[${i}]: optionalForCompletionGating must be a boolean`);
12178
12231
  }
12179
12232
  }
12180
12233
  });
@@ -12209,14 +12262,29 @@ function validateNode(node) {
12209
12262
  }
12210
12263
  return { ok: errors.length === 0, errors };
12211
12264
  }
12212
- function enrichSources(sources, context) {
12213
- if (!sources || sources.length === 0) return [];
12214
- return sources.map((src) => ({
12215
- ...src,
12216
- _requires: context.requires ?? {},
12217
- _sourcesData: context.sourcesData ?? {},
12218
- _computed_values: context.computed_values ?? {}
12219
- }));
12265
+ async function enrichSources(source_defs, context) {
12266
+ if (!source_defs || source_defs.length === 0) return [];
12267
+ const evalCtx = {
12268
+ card_data: context.card_data ?? {},
12269
+ requires: context.requires ?? {}
12270
+ };
12271
+ return Promise.all(
12272
+ source_defs.map(async (src) => {
12273
+ const _projections = {};
12274
+ if (src.projections && typeof src.projections === "object" && !Array.isArray(src.projections)) {
12275
+ for (const [key, expr] of Object.entries(src.projections)) {
12276
+ if (typeof expr === "string" && expr.trim().length > 0) {
12277
+ try {
12278
+ _projections[key] = await jsonata2__default.default(expr).evaluate(evalCtx);
12279
+ } catch {
12280
+ _projections[key] = void 0;
12281
+ }
12282
+ }
12283
+ }
12284
+ }
12285
+ return { ...src, _projections };
12286
+ })
12287
+ );
12220
12288
  }
12221
12289
  var CardCompute = {
12222
12290
  run,
@@ -12259,7 +12327,7 @@ function liveCardsToReactiveGraph(input, options = {}) {
12259
12327
  const allTokens = /* @__PURE__ */ new Set();
12260
12328
  const tokenToCardId = /* @__PURE__ */ new Map();
12261
12329
  for (const card of cards) {
12262
- for (const binding of card.provides ?? [{ bindTo: card.id, src: "card_data" }]) {
12330
+ for (const binding of card.provides ?? [{ bindTo: card.id, ref: "card_data" }]) {
12263
12331
  allTokens.add(binding.bindTo);
12264
12332
  tokenToCardId.set(binding.bindTo, card.id);
12265
12333
  }
@@ -12273,7 +12341,7 @@ function liveCardsToReactiveGraph(input, options = {}) {
12273
12341
  }
12274
12342
  tasks[card.id] = {
12275
12343
  requires: requires.length > 0 ? requires : void 0,
12276
- provides: (card.provides ?? [{ bindTo: card.id, src: "card_data" }]).map((p) => p.bindTo),
12344
+ provides: (card.provides ?? [{ bindTo: card.id, ref: "card_data" }]).map((p) => p.bindTo),
12277
12345
  taskHandlers: [card.id],
12278
12346
  description: card.meta?.title ?? card.id
12279
12347
  };
@@ -12294,7 +12362,7 @@ function liveCardsToReactiveGraph(input, options = {}) {
12294
12362
  graphRef.resolveCallback(token, data, errors);
12295
12363
  };
12296
12364
  for (const card of cards) {
12297
- if (card.sources && card.sources.length > 0) {
12365
+ if (card.source_defs && card.source_defs.length > 0) {
12298
12366
  handlers[card.id] = buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedState, getResolve);
12299
12367
  } else {
12300
12368
  handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, tokenToCardId, getResolve);
@@ -12358,8 +12426,8 @@ function buildCardHandler(card, cardHandlers, sharedState, _cardMap, tokenToCard
12358
12426
  let resultData;
12359
12427
  if (card.provides && card.provides.length > 0) {
12360
12428
  resultData = {};
12361
- for (const { bindTo, src } of card.provides) {
12362
- resultData[bindTo] = CardCompute.resolve(computeNode, src);
12429
+ for (const { bindTo, ref } of card.provides) {
12430
+ resultData[bindTo] = CardCompute.resolve(computeNode, ref);
12363
12431
  }
12364
12432
  } else {
12365
12433
  resultData = { ...computeNode.card_data, ...computeNode.computed_values };
@@ -12387,7 +12455,7 @@ function toTaskConfig(card) {
12387
12455
  function buildTokenProviders(cards) {
12388
12456
  const tokenToCardId = /* @__PURE__ */ new Map();
12389
12457
  for (const [cardId, card] of cards.entries()) {
12390
- const bindings = card.provides && card.provides.length > 0 ? card.provides : [{ bindTo: cardId, src: "card_data" }];
12458
+ const bindings = card.provides && card.provides.length > 0 ? card.provides : [{ bindTo: cardId, ref: "card_data" }];
12391
12459
  for (const binding of bindings) tokenToCardId.set(binding.bindTo, cardId);
12392
12460
  }
12393
12461
  return tokenToCardId;
@@ -12443,14 +12511,14 @@ function createBoardLiveGraphRuntime(input, options = {}) {
12443
12511
  requiresData[token] = providesData2[token];
12444
12512
  }
12445
12513
  const sourcesData = {};
12446
- if (card.sources && card.sources.length > 0) {
12514
+ if (card.source_defs && card.source_defs.length > 0) {
12447
12515
  const adapter = sourceAdapters[cardId] ?? defaultSourceAdapter;
12448
12516
  const fetched = taskExecutor ? await taskExecutor({ card, input: inputArgs }) : adapter ? await adapter({ card, input: inputArgs }) : void 0;
12449
12517
  if (fetched && typeof fetched === "object") {
12450
- for (const src of card.sources) {
12518
+ for (const src of card.source_defs) {
12451
12519
  if (Object.prototype.hasOwnProperty.call(fetched, src.bindTo)) {
12452
12520
  sourcesData[src.bindTo] = fetched[src.bindTo];
12453
- } else if (card.sources.length === 1) {
12521
+ } else if (card.source_defs.length === 1) {
12454
12522
  sourcesData[src.bindTo] = fetched;
12455
12523
  }
12456
12524
  }
@@ -12460,7 +12528,7 @@ function createBoardLiveGraphRuntime(input, options = {}) {
12460
12528
  id: card.id,
12461
12529
  card_data: deepClone(card.card_data ?? {}),
12462
12530
  requires: requiresData,
12463
- sources: card.sources,
12531
+ source_defs: card.source_defs,
12464
12532
  compute: card.compute
12465
12533
  };
12466
12534
  computeNode._sourcesData = sourcesData;
@@ -12469,8 +12537,8 @@ function createBoardLiveGraphRuntime(input, options = {}) {
12469
12537
  }
12470
12538
  const providesData = {};
12471
12539
  if (card.provides && card.provides.length > 0) {
12472
- for (const { bindTo, src } of card.provides) {
12473
- providesData[bindTo] = CardCompute.resolve(computeNode, src);
12540
+ for (const { bindTo, ref } of card.provides) {
12541
+ providesData[bindTo] = CardCompute.resolve(computeNode, ref);
12474
12542
  }
12475
12543
  } else {
12476
12544
  providesData[card.id] = {