yaml-flow 5.0.0 → 5.1.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "port": 7799,
3
+ "boardLiveCardsCliJs": "../../dist/cli/board-live-cards-cli.js",
4
+ "stepMachineCliPath": "../../step-machine-cli.js",
5
+ "taskExecutorPath": "./demo-task-executor.js",
6
+ "chatHandlerPath": "./demo-chat-handler.js"
7
+ }
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import http from 'node:http';
4
+ import fs from 'node:fs';
4
5
  import path from 'node:path';
5
6
  import { fileURLToPath } from 'node:url';
6
7
 
@@ -13,7 +14,40 @@ import {
13
14
  const __filename = fileURLToPath(import.meta.url);
14
15
  const __dirname = path.dirname(__filename);
15
16
 
16
- const PORT = Number(process.env.DEMO_SERVER_PORT || 7799);
17
+ function loadServerConfig() {
18
+ const configPath = path.join(__dirname, 'demo-server-config.json');
19
+ if (!fs.existsSync(configPath)) return {};
20
+ try {
21
+ const raw = fs.readFileSync(configPath, 'utf-8');
22
+ const parsed = JSON.parse(raw);
23
+ return parsed && typeof parsed === 'object' ? parsed : {};
24
+ } catch {
25
+ return {};
26
+ }
27
+ }
28
+
29
+ function resolveFromConfig(configValue) {
30
+ if (typeof configValue !== 'string' || !configValue.trim()) return null;
31
+ return path.resolve(__dirname, configValue);
32
+ }
33
+
34
+ const serverConfig = loadServerConfig();
35
+ const configuredCliJs = resolveFromConfig(serverConfig.boardLiveCardsCliJs);
36
+ const configuredTaskExecutorPath = resolveFromConfig(serverConfig.taskExecutorPath || serverConfig.demoTaskExecutorPath);
37
+ const configuredStepMachineCliPath = resolveFromConfig(serverConfig.stepMachineCliPath);
38
+ const configuredChatHandlerPath = resolveFromConfig(serverConfig.chatHandlerPath);
39
+
40
+ if (!process.env.BOARD_LIVE_CARDS_CLI_JS && configuredCliJs) {
41
+ process.env.BOARD_LIVE_CARDS_CLI_JS = configuredCliJs;
42
+ }
43
+ if (!process.env.DEMO_STEP_MACHINE_CLI_PATH && configuredStepMachineCliPath) {
44
+ process.env.DEMO_STEP_MACHINE_CLI_PATH = configuredStepMachineCliPath;
45
+ }
46
+ if (!process.env.DEMO_CHAT_HANDLER_PATH && configuredChatHandlerPath) {
47
+ process.env.DEMO_CHAT_HANDLER_PATH = configuredChatHandlerPath;
48
+ }
49
+
50
+ const PORT = Number(process.env.DEMO_SERVER_PORT || serverConfig.port || 7799);
17
51
  const CORS_HEADERS = {
18
52
  'Access-Control-Allow-Origin': '*',
19
53
  'Access-Control-Allow-Headers': 'content-type,x-file-name',
@@ -22,7 +56,10 @@ const CORS_HEADERS = {
22
56
 
23
57
  const runtime = createMultiBoardServerRuntime({
24
58
  apiBasePath: '/api/boards',
25
- defaultTaskExecutorPath: process.env.DEMO_TASK_EXECUTOR_PATH || path.join(__dirname, 'demo-task-executor.js'),
59
+ defaultTaskExecutorPath: process.env.DEMO_TASK_EXECUTOR_PATH || configuredTaskExecutorPath || path.join(__dirname, 'demo-task-executor.js'),
60
+ defaultStepMachineCliPath: process.env.DEMO_STEP_MACHINE_CLI_PATH || configuredStepMachineCliPath,
61
+ defaultChatHandlerPath: process.env.DEMO_CHAT_HANDLER_PATH || configuredChatHandlerPath || path.join(__dirname, 'demo-chat-handler.js'),
62
+ boardLiveCardsCliJs: process.env.BOARD_LIVE_CARDS_CLI_JS || configuredCliJs,
26
63
  });
27
64
 
28
65
  const dispatch = createRuntimeRequestDispatcher(runtime);
@@ -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="../../browser/card-compute.js" onerror="this.onerror=null;this.src='https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/card-compute.js';"></script>
10
- <script src="../../browser/live-cards.js" onerror="this.onerror=null;this.src='https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/live-cards.js';"></script>
11
- <script src="../../browser/board-livegraph-runtime.js" onerror="this.onerror=null;this.src='https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/board-livegraph-runtime.js';"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/card-compute.js" onerror="this.onerror=null;this.src='../../browser/card-compute.js';"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/live-cards.js" onerror="this.onerror=null;this.src='../../browser/live-cards.js';"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/board-livegraph-runtime.js" onerror="this.onerror=null;this.src='../../browser/board-livegraph-runtime.js';"></script>
12
12
  <script src="./reusable-runtime-artifacts-adapter.js"></script>
13
13
  </head>
14
14
  <body class="bg-light">
@@ -6,8 +6,8 @@
6
6
  <title>Example Board Demo (Server 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="../../browser/card-compute.js" onerror="this.onerror=null;this.src='https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/card-compute.js';"></script>
10
- <script src="../../browser/live-cards.js" onerror="this.onerror=null;this.src='https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/live-cards.js';"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/card-compute.js" onerror="this.onerror=null;this.src='../../browser/card-compute.js';"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@latest/browser/live-cards.js" onerror="this.onerror=null;this.src='../../browser/live-cards.js';"></script>
11
11
  <script src="./reusable-runtime-artifacts-adapter.js"></script>
12
12
  <script src="./reusable-board-runtime-client.js"></script>
13
13
  </head>
@@ -138,6 +138,12 @@ export function createMultiBoardServerRuntime(options = {}) {
138
138
  const defaultTaskExecutorPath = typeof entry.taskExecutorPath === 'string'
139
139
  ? entry.taskExecutorPath
140
140
  : options.defaultTaskExecutorPath;
141
+ const defaultStepMachineCliPath = typeof entry.stepMachineCliPath === 'string'
142
+ ? entry.stepMachineCliPath
143
+ : options.defaultStepMachineCliPath;
144
+ const defaultChatHandlerPath = typeof entry.chatHandlerPath === 'string'
145
+ ? entry.chatHandlerPath
146
+ : options.defaultChatHandlerPath;
141
147
 
142
148
  const service = createExampleBoardServerRuntime({
143
149
  apiBasePath: `${apiBasePath}/${boardId}`,
@@ -148,6 +154,9 @@ export function createMultiBoardServerRuntime(options = {}) {
148
154
  tmpSurfaceDir: path.join(boardRoot, 'surface'),
149
155
  runtimeOutDir: path.join(boardRoot, 'runtime-out'),
150
156
  defaultTaskExecutorPath,
157
+ defaultStepMachineCliPath,
158
+ defaultChatHandlerPath,
159
+ boardLiveCardsCliJs: options.boardLiveCardsCliJs,
151
160
  });
152
161
 
153
162
  boardServiceCache.set(boardId, service);
@@ -197,6 +206,7 @@ export function createMultiBoardServerRuntime(options = {}) {
197
206
  const label = typeof body.label === 'string' && body.label.trim() ? body.label.trim() : id;
198
207
  const entry = { id, label };
199
208
  if (typeof body.cardsDir === 'string') entry.cardsDir = body.cardsDir;
209
+ if (typeof body.stepMachineCliPath === 'string') entry.stepMachineCliPath = body.stepMachineCliPath;
200
210
  config.boards.push(entry);
201
211
  writeBoardsConfig(config);
202
212
 
@@ -310,6 +320,24 @@ export function createExampleBoardServerRuntime(options = {}) {
310
320
  ? options.defaultTaskExecutorPath
311
321
  : path.resolve(process.cwd(), options.defaultTaskExecutorPath))
312
322
  : null;
323
+ const configuredStepMachineCliPath = typeof options.defaultStepMachineCliPath === 'string'
324
+ && options.defaultStepMachineCliPath.trim()
325
+ ? (path.isAbsolute(options.defaultStepMachineCliPath)
326
+ ? options.defaultStepMachineCliPath
327
+ : path.resolve(process.cwd(), options.defaultStepMachineCliPath))
328
+ : null;
329
+ const configuredBoardLiveCardsCliJs = typeof options.boardLiveCardsCliJs === 'string'
330
+ && options.boardLiveCardsCliJs.trim()
331
+ ? (path.isAbsolute(options.boardLiveCardsCliJs)
332
+ ? options.boardLiveCardsCliJs
333
+ : path.resolve(process.cwd(), options.boardLiveCardsCliJs))
334
+ : null;
335
+ const configuredChatHandlerPath = typeof options.defaultChatHandlerPath === 'string'
336
+ && options.defaultChatHandlerPath.trim()
337
+ ? (path.isAbsolute(options.defaultChatHandlerPath)
338
+ ? options.defaultChatHandlerPath
339
+ : path.resolve(process.cwd(), options.defaultChatHandlerPath))
340
+ : null;
313
341
 
314
342
  const statusSnapshotFile = path.join(runtimeOutDir, 'board-livegraph-status.json');
315
343
  const boardFile = path.join(boardDir, 'board-graph.json');
@@ -318,6 +346,8 @@ export function createExampleBoardServerRuntime(options = {}) {
318
346
  let didDemoSetup = false;
319
347
 
320
348
  function resolveCliJsPath() {
349
+ if (configuredBoardLiveCardsCliJs && fs.existsSync(configuredBoardLiveCardsCliJs)) return configuredBoardLiveCardsCliJs;
350
+
321
351
  const envOverride = process.env.BOARD_LIVE_CARDS_CLI_JS;
322
352
  if (envOverride && fs.existsSync(envOverride)) return envOverride;
323
353
 
@@ -341,6 +371,10 @@ export function createExampleBoardServerRuntime(options = {}) {
341
371
 
342
372
  const cliJs = resolveCliJsPath();
343
373
 
374
+ if (!process.env.DEMO_STEP_MACHINE_CLI_PATH && configuredStepMachineCliPath && fs.existsSync(configuredStepMachineCliPath)) {
375
+ process.env.DEMO_STEP_MACHINE_CLI_PATH = configuredStepMachineCliPath;
376
+ }
377
+
344
378
  function ensureCardStorageDirs(cardId) {
345
379
  const safeCardId = String(cardId || '').replace(/[^a-zA-Z0-9_-]/g, '_') || 'unknown-card';
346
380
  const cardDir = path.join(tmpCardsDir, safeCardId);
@@ -417,7 +451,7 @@ export function createExampleBoardServerRuntime(options = {}) {
417
451
  function ensureBuilt() {
418
452
  if (!cliJs || !fs.existsSync(cliJs)) {
419
453
  throw new Error(
420
- 'Unable to locate board-live-cards CLI. Set BOARD_LIVE_CARDS_CLI_JS or install yaml-flow in this project.'
454
+ 'Unable to locate board-live-cards CLI. Set boardLiveCardsCliJs option, BOARD_LIVE_CARDS_CLI_JS, or install yaml-flow in this project.'
421
455
  );
422
456
  }
423
457
  }
@@ -631,29 +665,51 @@ export function createExampleBoardServerRuntime(options = {}) {
631
665
  return resolved;
632
666
  }
633
667
 
634
- function initBoard(taskExecutorPathParam) {
668
+ function resolveChatHandlerPath(chatHandlerPathParam) {
669
+ const raw = typeof chatHandlerPathParam === 'string' ? chatHandlerPathParam.trim() : '';
670
+ const resolved = raw
671
+ ? (path.isAbsolute(raw) ? raw : path.resolve(__dirname, raw))
672
+ : configuredChatHandlerPath;
673
+ if (!resolved) return null;
674
+ if (!fs.existsSync(resolved)) {
675
+ const err = new Error(`Chat handler script not found: ${resolved}`);
676
+ err.statusCode = 400;
677
+ throw err;
678
+ }
679
+ return resolved;
680
+ }
681
+
682
+ function initBoard(taskExecutorPathParam, chatHandlerPathParam) {
635
683
  fs.mkdirSync(boardDir, { recursive: true });
636
684
 
637
685
  const taskExecutorPath = resolveTaskExecutorPath(taskExecutorPathParam);
686
+ const chatHandlerPath = resolveChatHandlerPath(chatHandlerPathParam);
638
687
  const taskExecutorCmd = `${shellQuote(process.execPath)} ${shellQuote(taskExecutorPath)}`;
688
+ const chatHandlerCmd = chatHandlerPath
689
+ ? `${shellQuote(process.execPath)} ${shellQuote(chatHandlerPath)}`
690
+ : null;
691
+
692
+ const initArgs = ['init', boardDir, '--task-executor', taskExecutorCmd];
693
+ if (chatHandlerCmd) initArgs.push('--chat-handler', chatHandlerCmd);
694
+ initArgs.push('--runtime-out', runtimeOutDir);
639
695
 
640
696
  try {
641
- runCli(['init', boardDir, '--task-executor', taskExecutorCmd, '--runtime-out', runtimeOutDir]);
697
+ runCli(initArgs);
642
698
  } catch (err) {
643
699
  const msg = String((err && err.message) || err);
644
700
  if (!msg.includes('no valid board-graph.json')) throw err;
645
701
 
646
702
  clearDirContents(boardDir);
647
703
  fs.mkdirSync(boardDir, { recursive: true });
648
- runCli(['init', boardDir, '--task-executor', taskExecutorCmd, '--runtime-out', runtimeOutDir]);
704
+ runCli(initArgs);
649
705
  }
650
706
  }
651
707
 
652
- function initBoardAndSetup(taskExecutorPathParam) {
708
+ function initBoardAndSetup(taskExecutorPathParam, chatHandlerPathParam) {
653
709
  ensureDemoSetup();
654
710
 
655
711
  if (!fs.existsSync(boardFile)) {
656
- initBoard(taskExecutorPathParam);
712
+ initBoard(taskExecutorPathParam, chatHandlerPathParam);
657
713
  }
658
714
 
659
715
  const expectedCardsRoot = path.resolve(tmpCardsDir);
@@ -665,7 +721,7 @@ export function createExampleBoardServerRuntime(options = {}) {
665
721
 
666
722
  if (hasStaleMapping) {
667
723
  clearDirContents(boardDir);
668
- initBoard(taskExecutorPathParam);
724
+ initBoard(taskExecutorPathParam, chatHandlerPathParam);
669
725
  }
670
726
  }
671
727
 
@@ -1095,7 +1151,8 @@ export function createExampleBoardServerRuntime(options = {}) {
1095
1151
  try {
1096
1152
  if (method === 'GET' && p === `${apiBasePath}/init-board`) {
1097
1153
  const taskExecutorPathParam = url.searchParams.get('taskExecutorPath') || '';
1098
- initBoardAndSetup(taskExecutorPathParam);
1154
+ const chatHandlerPathParam = url.searchParams.get('chatHandlerPath') || '';
1155
+ initBoardAndSetup(taskExecutorPathParam, chatHandlerPathParam);
1099
1156
  json(res, 200, buildPublishedRuntimePayload());
1100
1157
  return true;
1101
1158
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaml-flow",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Unified workflow engine: step-machine (sequential) + event-graph (stateless DAG) with pluggable storage",
5
5
  "author": "",
6
6
  "license": "MIT",