yaml-flow 5.3.0 → 5.4.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.
@@ -79,14 +79,14 @@ function cliCommand() {
79
79
 
80
80
  function runCli(args, capture = false) {
81
81
  const { cmd, prefixArgs } = cliCommand();
82
+ const env = { ...process.env };
83
+ // This demo needs real worker dispatch; suppressing spawn keeps source/inference tasks in running state.
84
+ delete env.BOARD_LIVE_CARDS_NO_SPAWN;
82
85
  const result = spawnSync(cmd, [...prefixArgs, ...args], {
83
86
  stdio: capture ? 'pipe' : 'inherit',
84
87
  shell: false,
85
88
  windowsHide: true,
86
- env: {
87
- ...process.env,
88
- BOARD_LIVE_CARDS_NO_SPAWN: '1',
89
- },
89
+ env,
90
90
  encoding: capture ? 'utf-8' : undefined,
91
91
  });
92
92
 
@@ -509,11 +509,10 @@ The optional `projections` map lets a source definition declare which upstream d
509
509
  "outputFile": "quotes.json",
510
510
  "projections": {
511
511
  "holdings": "requires.holdings",
512
- "topHoldings": "requires.holdings[weight > 0.05]",
513
- "threshold": "card_data.threshold"
512
+ "url_list": "requires.holdings.ticker.('https://query1.finance.yahoo.com/v8/finance/chart/' & $ & '?interval=1d&range=1d')"
514
513
  },
515
- "chartApi": {
516
- "tickersFrom": "holdings.ticker"
514
+ "url-list": {
515
+ "cacheTimeout": 3600
517
516
  }
518
517
  }
519
518
  ]
@@ -538,7 +537,7 @@ node board-live-cards-cli.js describe-task-executor-capabilities --rg <boardDir>
538
537
  ```
539
538
 
540
539
  This invokes the executor's `describe-capabilities` subcommand and prints its capabilities JSON to stdout. The output includes:
541
- - **`sourceKinds`** — every source kind the executor handles (e.g. `mock`, `copilot`, `http`, `chartApi`), each with:
540
+ - **`sourceKinds`** — every source kind the executor handles (e.g. `mock`, `copilot`, `workiq`, `url`, `url-list`), each with:
542
541
  - `description` — what the kind does
543
542
  - `inputSchema` — the exact `customFields` the executor expects on the source entry
544
543
  - `outputShape` — the shape of the JSON written to `--out`
@@ -126,13 +126,67 @@ function jsonReply(res, status, payload) {
126
126
  res.end(body);
127
127
  }
128
128
 
129
+ // ---------------------------------------------------------------------------
130
+ // Card preparation — host-level concern, not a reusable runtime concern.
131
+ // Copies source card JSON files into the runtime's tmpCardsDir and writes
132
+ // the concatenated copilot-instructions.md at the board setup root.
133
+ // The runtime's bootstrap operations assume cards are already in tmpCardsDir;
134
+ // the host (this file) decides how and when they get there.
135
+ // ---------------------------------------------------------------------------
136
+
137
+ const _demoPrepSetupDone = new Map(); // boardId → true
138
+
139
+ function isDemoSetupDone(boardId, service) {
140
+ return _demoPrepSetupDone.get(boardId) === true && fs.existsSync(service.tmpCardsDir);
141
+ }
142
+
143
+ function demoPrepSetup(boardId, service) {
144
+ const { tmpSurfaceDir, tmpCardsDir, cardsDir, gandalfCardsDir, tmpGandalfCardsDir, boardDir } = service;
145
+
146
+ fs.mkdirSync(tmpSurfaceDir, { recursive: true });
147
+ fs.rmSync(tmpCardsDir, { recursive: true, force: true });
148
+ fs.mkdirSync(tmpCardsDir, { recursive: true });
149
+
150
+ const entries = fs.readdirSync(cardsDir, { withFileTypes: true });
151
+ for (const entry of entries) {
152
+ if (!entry.isFile()) continue;
153
+ if (!entry.name.toLowerCase().endsWith('.json')) continue;
154
+ fs.copyFileSync(path.join(cardsDir, entry.name), path.join(tmpCardsDir, entry.name));
155
+ }
156
+
157
+ // Copy gandalf-card templates if gandalfCardsDir is configured.
158
+ if (gandalfCardsDir && fs.existsSync(gandalfCardsDir)) {
159
+ fs.rmSync(tmpGandalfCardsDir, { recursive: true, force: true });
160
+ fs.mkdirSync(tmpGandalfCardsDir, { recursive: true });
161
+ for (const entry of fs.readdirSync(gandalfCardsDir, { withFileTypes: true })) {
162
+ if (!entry.isFile() || !entry.name.toLowerCase().endsWith('.json')) continue;
163
+ fs.copyFileSync(path.join(gandalfCardsDir, entry.name), path.join(tmpGandalfCardsDir, entry.name));
164
+ }
165
+ }
166
+
167
+ // Concatenate agent-instructions*.md into copilot-instructions.md at boardSetupRoot.
168
+ const boardSetupRoot = path.dirname(boardDir);
169
+ const srcDir = path.dirname(cardsDir);
170
+ const agentInstructionFiles = ['agent-instructions.md', 'agent-instructions-cardlayout.md'];
171
+ const parts = [];
172
+ for (const fname of agentInstructionFiles) {
173
+ const fpath = path.join(srcDir, fname);
174
+ if (fs.existsSync(fpath)) parts.push(fs.readFileSync(fpath, 'utf-8').trimEnd());
175
+ }
176
+ if (parts.length > 0) {
177
+ fs.writeFileSync(path.join(boardSetupRoot, 'copilot-instructions.md'), parts.join('\n\n') + '\n', 'utf-8');
178
+ }
179
+
180
+ _demoPrepSetupDone.set(boardId, true);
181
+ }
182
+
129
183
  async function handleDemoSetup(req, res, boardId) {
130
184
  try {
131
- const { service, boardRoot } = runtime.requireBoardService(boardId);
185
+ const { service } = runtime.requireBoardService(boardId);
132
186
  let setupPerformed = false;
133
187
 
134
- if (!service.isDemoSetupDone()) {
135
- service.ensureDemoSetup();
188
+ if (!isDemoSetupDone(boardId, service)) {
189
+ demoPrepSetup(boardId, service);
136
190
  setupPerformed = true;
137
191
  }
138
192
 
@@ -6,9 +6,9 @@
6
6
  <title>Example Board Demo (Browser Runtime)</title>
7
7
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
8
8
  <script src="https://cdn.jsdelivr.net/npm/jsonata/jsonata.min.js"></script>
9
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.3.0/browser/card-compute.js"></script>
10
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.3.0/browser/live-cards.js"></script>
11
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.3.0/browser/board-livegraph-engine.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.4.0/browser/card-compute.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.4.0/browser/live-cards.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.4.0/browser/board-livegraph-engine.js"></script>
12
12
  </head>
13
13
  <body class="bg-light">
14
14
  <div class="container-fluid py-3">
@@ -378,7 +378,7 @@
378
378
 
379
379
  return {
380
380
  fetchSource: async function (card, sourceDef) {
381
- // chartApi source with mock="quotes" → return mock quote data
381
+ // mock source with mock="quotes" → return mock quote data
382
382
  if (sourceDef && sourceDef.mock === 'quotes') return clone(quoteData);
383
383
  // copilot source → return mock analysis object
384
384
  if (sourceDef && sourceDef.copilot) return clone(mockAnalysis);
@@ -16,10 +16,10 @@
16
16
  </style>
17
17
  <script src="https://cdn.jsdelivr.net/npm/jsonata/jsonata.min.js"></script>
18
18
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
19
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.3.0/browser/card-compute.js"></script>
20
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.3.0/browser/live-cards.js"></script>
21
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.3.0/browser/board-livegraph-engine.js"></script>
22
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.3.0/browser/board-livecards-runtime-client.js"></script>
19
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.4.0/browser/card-compute.js"></script>
20
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.4.0/browser/live-cards.js"></script>
21
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.4.0/browser/board-livegraph-engine.js"></script>
22
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@5.4.0/browser/board-livecards-runtime-client.js"></script>
23
23
  </head>
24
24
  <body class="bg-light">
25
25
  <div class="container-fluid py-3">
@@ -45,8 +45,7 @@
45
45
  * - { "url-list": { method?, headers?, cacheTimeout? } }
46
46
  * → fan-out over _projections.url_list (string[]); returns array of responses.
47
47
  * Build url_list in projections: e.g. `requires.holdings.ticker.('https://host/' & $ & '?q=1')`
48
- * - { chartApi: { url, headers? }, tickersFrom } → removed; use url-list instead
49
- * prefer url-list for new sources
48
+ * Prefer url-list for multi-URL fan-out sources.
50
49
  * A real executor can also handle: graphapi, teams, mail, incidentdb, script, etc.
51
50
  *
52
51
  * url / url-list notes:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml-flow",
3
- "version": "5.3.0",
3
+ "version": "5.4.0",
4
4
  "description": "Unified workflow engine: step-machine (sequential) + event-graph (stateless DAG) with pluggable storage",
5
5
  "author": "",
6
6
  "license": "MIT",