yaml-flow 8.7.1 → 8.8.5

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 (195) hide show
  1. package/browser/adapters/firebase-storage.js +2 -2
  2. package/browser/adapters/firestore-storage.js +2 -2
  3. package/browser/adapters/localstorage-storage.js +3 -3
  4. package/browser/asset-integrity.json +9 -13
  5. package/browser/live-cards.js +6 -6
  6. package/browser/server-runtime-controlface.js +5 -5
  7. package/examples/ARCHITECTURE.md +0 -27
  8. package/examples/board/server/board-server.js +150 -100
  9. package/examples/board/server/board-worker/source_def_flows.json +0 -8
  10. package/examples/board/server/board-worker/task-executor.js +1 -3
  11. package/examples/board/server/chat-flow/flow-steps.json +5 -5
  12. package/examples/board/test/server-http-test.js +726 -87
  13. package/examples/board-firestore/server/worker.js +8 -0
  14. package/examples/portfolio-tracker/portfolio-tracker.js +11 -1
  15. package/examples/portfolio-tracker/test/portfolio-t4.js +12 -2
  16. package/lib/{artifacts-store-lib-D9nMkVcE.d.cts → artifacts-store-lib-C6qBpMfU.d.cts} +1 -1
  17. package/lib/{artifacts-store-lib-DSSMqVL2.d.ts → artifacts-store-lib-D4qf7Q-7.d.ts} +1 -1
  18. package/lib/artifacts-store-public.d.cts +3 -3
  19. package/lib/artifacts-store-public.d.ts +3 -3
  20. package/lib/board-live-cards-mcp.cjs +1 -1
  21. package/lib/board-live-cards-mcp.d.cts +6 -7
  22. package/lib/board-live-cards-mcp.d.ts +6 -7
  23. package/lib/board-live-cards-mcp.js +1 -1
  24. package/lib/board-live-cards-node.cjs +8 -8
  25. package/lib/board-live-cards-node.d.cts +70 -15
  26. package/lib/board-live-cards-node.d.ts +70 -15
  27. package/lib/board-live-cards-node.js +8 -8
  28. package/lib/{board-live-cards-public-LlVUQPL2.d.cts → board-live-cards-public-BT5HrgqZ.d.cts} +82 -59
  29. package/lib/{board-live-cards-public-JNRKfBZy.d.ts → board-live-cards-public-DSRamFm8.d.ts} +82 -59
  30. package/lib/{board-live-cards-public-async-Di9QB141.d.cts → board-live-cards-public-async-CYjr4mgX.d.cts} +18 -8
  31. package/lib/{board-live-cards-public-async-fwd1QI82.d.ts → board-live-cards-public-async-DlyC3PgC.d.ts} +18 -8
  32. package/lib/board-live-cards-public.cjs +1 -1
  33. package/lib/board-live-cards-public.d.cts +2 -2
  34. package/lib/board-live-cards-public.d.ts +2 -2
  35. package/lib/board-live-cards-public.js +1 -1
  36. package/lib/board-live-cards-server-runtime.cjs +1 -1
  37. package/lib/board-live-cards-server-runtime.d.cts +6 -8
  38. package/lib/board-live-cards-server-runtime.d.ts +6 -8
  39. package/lib/board-live-cards-server-runtime.js +1 -1
  40. package/lib/board-livegraph-runtime/index.cjs +1 -1
  41. package/lib/board-livegraph-runtime/index.d.cts +1 -0
  42. package/lib/board-livegraph-runtime/index.d.ts +1 -0
  43. package/lib/board-livegraph-runtime/index.js +1 -1
  44. package/lib/{board-platform-adapter-async-BfHmHdx2.d.cts → board-platform-adapter-async-BZIftm36.d.cts} +18 -14
  45. package/lib/{board-platform-adapter-async-DYahVzIK.d.ts → board-platform-adapter-async-JP9V-U5E.d.ts} +18 -14
  46. package/lib/board-worker-adapter.cjs +1 -24
  47. package/lib/board-worker-adapter.d.cts +68 -3
  48. package/lib/board-worker-adapter.d.ts +68 -3
  49. package/lib/board-worker-adapter.js +1 -24
  50. package/lib/card-store-public.d.cts +2 -2
  51. package/lib/card-store-public.d.ts +2 -2
  52. package/lib/chat-store-public.cjs +1 -1
  53. package/lib/chat-store-public.d.cts +20 -20
  54. package/lib/chat-store-public.d.ts +20 -20
  55. package/lib/chat-store-public.js +1 -1
  56. package/lib/chunk-35N7ONTH.js +2 -0
  57. package/lib/chunk-36QUKFL7.cjs +3 -0
  58. package/lib/chunk-37HDEW26.cjs +2 -0
  59. package/lib/{chunk-PMUSJQSR.cjs → chunk-3CZCGNY4.cjs} +2 -2
  60. package/lib/{chunk-BQS3EIEK.js → chunk-44L64VQ2.js} +3 -3
  61. package/lib/{chunk-YGKDQLYP.js → chunk-4HIEOBJC.js} +2 -2
  62. package/lib/chunk-6OPXQPSC.js +2 -0
  63. package/lib/chunk-7BTZCOT5.js +2 -0
  64. package/lib/{chunk-U2N6MCD5.cjs → chunk-7JVHYHT2.cjs} +2 -2
  65. package/lib/chunk-7QQFDYBM.js +3 -0
  66. package/lib/chunk-7QZ267XP.cjs +2 -0
  67. package/lib/chunk-ABAVFLDP.js +7 -0
  68. package/lib/{chunk-XQRNDX4Q.js → chunk-ANKA7HEJ.js} +2 -2
  69. package/lib/{chunk-KAWQPLIE.cjs → chunk-BQUQTOPB.cjs} +2 -2
  70. package/lib/chunk-ETW3BXHD.cjs +2 -0
  71. package/lib/{chunk-SGV7PU4H.js → chunk-FOFGEABN.js} +2 -2
  72. package/lib/chunk-GPCMBPLK.cjs +2 -0
  73. package/lib/chunk-H22NK6KH.cjs +7 -0
  74. package/lib/chunk-H4TYOSMD.cjs +45 -0
  75. package/lib/chunk-HFW7E2Z7.cjs +4 -0
  76. package/lib/chunk-J4MHQ7JF.js +45 -0
  77. package/lib/chunk-MCPADH33.cjs +2 -0
  78. package/lib/chunk-NBJTYAYN.cjs +2 -0
  79. package/lib/chunk-NNSBBO5R.js +2 -0
  80. package/lib/chunk-NU5NO5NM.js +2 -0
  81. package/lib/chunk-O5UYCGIN.js +2 -0
  82. package/lib/chunk-O6II7S4M.js +3 -0
  83. package/lib/chunk-PN5D32NP.cjs +3 -0
  84. package/lib/chunk-Q3OTUDIE.js +2 -0
  85. package/lib/chunk-R44X3RQB.cjs +2 -0
  86. package/lib/chunk-RKKSVOP2.js +2 -0
  87. package/lib/chunk-UB54HZA4.cjs +2 -0
  88. package/lib/{chunk-CIAJNUR4.js → chunk-VGDLSS2H.js} +2 -2
  89. package/lib/{chunk-SFVO2LB2.cjs → chunk-VQCIOKJV.cjs} +3 -3
  90. package/lib/chunk-VS3BXEYK.js +4 -0
  91. package/lib/{chunk-S6DRP2HX.cjs → chunk-XQAHHUZO.cjs} +2 -2
  92. package/lib/chunk-Y4WK7HE4.js +2 -0
  93. package/lib/chunk-ZENTBLLA.cjs +3 -0
  94. package/lib/chunk-ZK3E7L4Y.cjs +2 -0
  95. package/lib/chunk-ZWVT24YW.js +3 -0
  96. package/lib/cloud-storage.cjs +1 -1
  97. package/lib/cloud-storage.d.cts +6 -6
  98. package/lib/cloud-storage.d.ts +6 -6
  99. package/lib/cloud-storage.js +1 -1
  100. package/lib/execution-refs.cjs +1 -1
  101. package/lib/execution-refs.js +1 -1
  102. package/lib/firebase-storage/index.cjs +2 -2
  103. package/lib/firebase-storage/index.d.cts +2 -2
  104. package/lib/firebase-storage/index.d.ts +2 -2
  105. package/lib/firebase-storage/index.js +2 -2
  106. package/lib/firestore-storage/index.cjs +2 -2
  107. package/lib/firestore-storage/index.d.cts +12 -21
  108. package/lib/firestore-storage/index.d.ts +12 -21
  109. package/lib/firestore-storage/index.js +2 -2
  110. package/lib/index.cjs +2 -2
  111. package/lib/index.d.cts +1 -1
  112. package/lib/index.d.ts +1 -1
  113. package/lib/index.js +1 -1
  114. package/lib/localstorage-storage/index.cjs +1 -1
  115. package/lib/localstorage-storage/index.d.cts +10 -6
  116. package/lib/localstorage-storage/index.d.ts +10 -6
  117. package/lib/localstorage-storage/index.js +1 -1
  118. package/lib/{mcp-tool-registries-W3TRj6O5.d.cts → mcp-tool-registries-CRtea2x4.d.cts} +3 -0
  119. package/lib/{mcp-tool-registries-BBObLYga.d.ts → mcp-tool-registries-D3rWSppt.d.ts} +3 -0
  120. package/lib/server-jobs-queue-runner/index.cjs +1 -1
  121. package/lib/server-jobs-queue-runner/index.d.cts +12 -9
  122. package/lib/server-jobs-queue-runner/index.d.ts +12 -9
  123. package/lib/server-jobs-queue-runner/index.js +1 -1
  124. package/lib/server-runtime/index.cjs +1 -1
  125. package/lib/server-runtime/index.d.cts +7 -9
  126. package/lib/server-runtime/index.d.ts +7 -9
  127. package/lib/server-runtime/index.js +1 -1
  128. package/lib/server-runtime-agentface/index.d.cts +7 -9
  129. package/lib/server-runtime-agentface/index.d.ts +7 -9
  130. package/lib/server-runtime-controlface/index.cjs +1 -1
  131. package/lib/server-runtime-controlface/index.d.cts +8 -9
  132. package/lib/server-runtime-controlface/index.d.ts +8 -9
  133. package/lib/server-runtime-controlface/index.js +1 -1
  134. package/lib/server-runtime-core/index.cjs +1 -1
  135. package/lib/server-runtime-core/index.d.cts +59 -21
  136. package/lib/server-runtime-core/index.d.ts +59 -21
  137. package/lib/server-runtime-core/index.js +1 -1
  138. package/lib/server-runtime-watchers/index.cjs +1 -1
  139. package/lib/server-runtime-watchers/index.d.cts +9 -65
  140. package/lib/server-runtime-watchers/index.d.ts +9 -65
  141. package/lib/server-runtime-watchers/index.js +1 -1
  142. package/lib/server-runtime-webhooks/index.d.cts +7 -9
  143. package/lib/server-runtime-webhooks/index.d.ts +7 -9
  144. package/lib/sse-hub-BDjWI7JR.d.cts +63 -0
  145. package/lib/sse-hub-DM8bw-dO.d.ts +63 -0
  146. package/lib/step-machine-public/index.cjs +1 -1
  147. package/lib/step-machine-public/index.d.cts +1 -1
  148. package/lib/step-machine-public/index.d.ts +1 -1
  149. package/lib/step-machine-public/index.js +1 -1
  150. package/lib/{storage-async-interface-BRR4eBjx.d.cts → storage-async-interface-CG0bMqvE.d.ts} +20 -1
  151. package/lib/{storage-async-interface-DhlOVPSp.d.ts → storage-async-interface-CyO-zwVQ.d.cts} +20 -1
  152. package/lib/{storage-interface-BFiD3kyB.d.ts → storage-interface-D-iEiTJA.d.cts} +45 -1
  153. package/lib/{storage-interface-BFiD3kyB.d.cts → storage-interface-D-iEiTJA.d.ts} +45 -1
  154. package/lib/stores/index.d.cts +1 -1
  155. package/lib/stores/index.d.ts +1 -1
  156. package/lib/stores/kv.d.cts +1 -1
  157. package/lib/stores/kv.d.ts +1 -1
  158. package/lib/{types-SO5OZm4s.d.ts → types-BsfXZyI3.d.ts} +64 -29
  159. package/lib/{types-Ba8H5_Wo.d.cts → types-CPnYv7RC.d.cts} +64 -29
  160. package/package.json +4 -5
  161. package/browser/board-livecards-client.js +0 -2
  162. package/examples/board/demo-shell-with-server.html +0 -272
  163. package/examples/board/doc.html +0 -465
  164. package/examples/board/server-config.json +0 -24
  165. package/examples/board/test/sse-worker.js +0 -49
  166. package/lib/chat-storage-lib-B9Q34Dyv.d.cts +0 -54
  167. package/lib/chat-storage-lib-DB9iSai2.d.ts +0 -54
  168. package/lib/chunk-5XHOHTLZ.cjs +0 -2
  169. package/lib/chunk-6APH25VI.js +0 -2
  170. package/lib/chunk-76C7N4YT.js +0 -3
  171. package/lib/chunk-76ON3V7R.js +0 -2
  172. package/lib/chunk-7ICPAABP.cjs +0 -7
  173. package/lib/chunk-ASR44K7H.cjs +0 -3
  174. package/lib/chunk-CPAXTVBQ.cjs +0 -2
  175. package/lib/chunk-EGRHWZRV.js +0 -2
  176. package/lib/chunk-EZENHAVZ.cjs +0 -2
  177. package/lib/chunk-GL2OHR2E.cjs +0 -2
  178. package/lib/chunk-GYQXDNNI.cjs +0 -2
  179. package/lib/chunk-HEEDJEKM.js +0 -2
  180. package/lib/chunk-IPLSRN6P.cjs +0 -4
  181. package/lib/chunk-J6EGN6S4.cjs +0 -3
  182. package/lib/chunk-JH37NJGP.js +0 -3
  183. package/lib/chunk-JJL5VOQZ.cjs +0 -3
  184. package/lib/chunk-NJJ7WEDT.cjs +0 -2
  185. package/lib/chunk-NKIQRCOM.cjs +0 -2
  186. package/lib/chunk-PBCDDO4V.cjs +0 -2
  187. package/lib/chunk-PBOQ4HYB.cjs +0 -2
  188. package/lib/chunk-PRKRXAVN.js +0 -3
  189. package/lib/chunk-QJVR3FWQ.js +0 -2
  190. package/lib/chunk-S44QZUDX.js +0 -2
  191. package/lib/chunk-TSN3RTXT.js +0 -4
  192. package/lib/chunk-VXJHBWK3.js +0 -2
  193. package/lib/chunk-WHDEBJLT.js +0 -7
  194. package/lib/chunk-YGALANRO.js +0 -2
  195. package/lib/chunk-ZCNN6XPV.js +0 -2
@@ -82,32 +82,6 @@ No public API — just sets `window.jsonataSync` for other bundles to pick up.
82
82
 
83
83
  ---
84
84
 
85
- ### board-livecards-client.js → `window.BoardLiveCardsClient`
86
-
87
- **Client for a yaml-flow HTTP/SSE server.** Two modes in one bundle:
88
-
89
- 1. **SSE/HTTP mode** — connects to a `board-live-cards-server-runtime` host:
90
- ```html
91
- <script src="board-livecards-client.js"></script>
92
- <script>
93
- const client = BoardLiveCardsClient.createBoardRuntimeClient({
94
- fetchServer,
95
- boardPaths: BoardLiveCardsClient.defaultBoardPaths('my-board'),
96
- getServerOrigin,
97
- });
98
- await client.bootstrapBoard({ boardId: 'my-board', rootElement: el });
99
- </script>
100
- ```
101
-
102
- 2. **Custom transport mode** — use the platform-free state layer with Firebase,
103
- WebSocket, or any other transport. Import `buildBoardState`, `applyNotification`,
104
- `selectAllLiveCardModels` and drive them yourself.
105
-
106
- Key exports: `createBoardRuntimeClient`, `defaultBoardPaths`, `singleBoardPaths`,
107
- `buildBoardState`, `applyNotification`, `selectLiveCardModel`, `selectAllLiveCardModels`
108
-
109
- ---
110
-
111
85
  ### live-cards.js → `window.LiveCard`
112
86
 
113
87
  **UI rendering engine** — turns board state (card models) into interactive HTML.
@@ -156,6 +130,5 @@ charts fall back to tables and markdown renders as escaped plain text.
156
130
  <script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
157
131
 
158
132
  <!-- 2. yaml-flow bundles -->
159
- <script src="board-livecards-client.js"></script>
160
133
  <script src="live-cards.js"></script>
161
134
  ```
@@ -26,6 +26,7 @@ import {
26
26
  createFsBoardNonCorePlatformAdapter,
27
27
  createInProcessBoardCallbackTransport,
28
28
  createFsBoardChatStorage,
29
+ createInMemoryChatStorage,
29
30
  createNodeSpawnInvocationAdapter,
30
31
  createArtifactsStore,
31
32
  evaluateArgsMassaging,
@@ -34,9 +35,12 @@ import {
34
35
  registerInProcessExecutionHandler,
35
36
  startQueueLaneRunners,
36
37
  serializeRef,
37
- serializeExecutionRef,
38
38
  } from 'yaml-flow/board-live-cards-node';
39
- import { registerInProcessBoardWorkerCallback } from 'yaml-flow/board-worker-adapter';
39
+ import {
40
+ createImmediateBoardWorkerHook,
41
+ registerInProcessBoardWorkerCallback,
42
+ registerInProcessBoardWorkerInvoke,
43
+ } from 'yaml-flow/board-worker-adapter';
40
44
  import {
41
45
  createStepMachineChatFlowRunner,
42
46
  } from 'yaml-flow/step-machine-public';
@@ -106,32 +110,6 @@ function applyFlowTimeout(flow, timeoutMs) {
106
110
  };
107
111
  }
108
112
 
109
- function buildChatHandlerFlowFromScript(scriptPath, timeoutMs = null) {
110
- if (!scriptPath) return null;
111
- const resolved = path.isAbsolute(scriptPath) ? scriptPath : path.resolve(BOARD_ROOT, scriptPath);
112
- const resolvedTimeoutMs = normalizeTimeoutMs(timeoutMs, 300000);
113
- return {
114
- id: 'demo-chat-script-handler',
115
- settings: { start_step: 'respond', max_total_steps: 5, timeout_ms: resolvedTimeoutMs },
116
- steps: {
117
- respond: {
118
- description: 'Run the demo board chat responder from a script path',
119
- handler: {
120
- type: 'ref',
121
- howToRun: 'local-node',
122
- whatToRun: { kind: 'fs-path', value: resolved },
123
- meta: 'chat-handler',
124
- },
125
- transitions: { success: 'completed', failure: 'failed' },
126
- },
127
- },
128
- terminal_states: {
129
- completed: { description: 'Chat response completed', return_intent: 'success', return_artifacts: false },
130
- failed: { description: 'Chat response failed', return_intent: 'failure', return_artifacts: false },
131
- },
132
- };
133
- }
134
-
135
113
  function resolveKindRefFromConfig(configValue) {
136
114
  if (typeof configValue !== 'string' || !configValue.trim()) return null;
137
115
  const trimmed = configValue.trim();
@@ -174,20 +152,18 @@ const configuredRuntimeMode = normalizeRuntimeMode(
174
152
  );
175
153
 
176
154
  // Resolve top-level config defaults (used as fallbacks for per-board config)
177
- const configuredTaskExecutorPath = resolveFromConfig(serverConfig.taskExecutorPath);
178
- const configuredChatHandlerPath = resolveFromConfig(serverConfig.chatHandlerPath);
179
- const configuredFlowFromPath = loadJsonFromConfig(serverConfig.chatHandlerFlowPath);
155
+ const configuredTaskExecutorPath = resolveFromConfig(serverConfig.taskExecutorPath)
156
+ || path.join(SERVER_DIR, 'board-worker', 'task-executor.js');
157
+ const configuredChatHandlerPath = resolveFromConfig(serverConfig.chatHandlerPath)
158
+ || path.join(SERVER_DIR, 'chat-flow', 'copilot-chat', 'assistant.js');
159
+ const configuredFlowFromPath = loadJsonFromConfig(serverConfig.chatHandlerFlowPath)
160
+ || loadJsonFromConfig(path.join('server', 'chat-flow', 'flow-steps.json'));
180
161
  const configuredChatHandlerFlow = applyFlowTimeout(
181
- configuredFlowFromPath || buildChatHandlerFlowFromScript(configuredChatHandlerPath, configuredChatFlowTimeoutMs),
162
+ configuredFlowFromPath,
182
163
  configuredChatFlowTimeoutMs,
183
164
  );
184
165
  const configuredInferenceAdapterPath = resolveFromConfig(serverConfig.inferenceAdapterPath);
185
- const configuredStepMachineCliPath = resolveFromConfig(serverConfig.stepMachineCliPath);
186
166
  const configuredServerMetaStoreRef = resolveKindRefFromConfig(serverConfig.serverMetaStoreRef);
187
-
188
- if (!process.env.DEMO_STEP_MACHINE_CLI_PATH && configuredStepMachineCliPath) {
189
- process.env.DEMO_STEP_MACHINE_CLI_PATH = configuredStepMachineCliPath;
190
- }
191
167
  if (!process.env.DEMO_CHAT_HANDLER_PATH && configuredChatHandlerPath) {
192
168
  process.env.DEMO_CHAT_HANDLER_PATH = configuredChatHandlerPath;
193
169
  }
@@ -262,24 +238,6 @@ function makeExecutionRef(scriptPath, extra) {
262
238
  };
263
239
  }
264
240
 
265
- function makeLocalTaskExecutorRef(scriptPath, extra) {
266
- if (!scriptPath) return undefined;
267
- const resolved = path.isAbsolute(scriptPath) ? scriptPath : path.resolve(process.cwd(), scriptPath);
268
- return {
269
- meta: 'task-executor',
270
- howToRun: 'local-node',
271
- whatToRun: serializeRef({ kind: 'fs-path', value: resolved }),
272
- ...(extra !== undefined ? { extra } : {}),
273
- };
274
- }
275
-
276
- function isHostedTaskExecutorRef(ref) {
277
- return ref?.howToRun === 'queue-storage'
278
- || ref?.howToRun === 'in-process-loop'
279
- || ref?.howToRun === 'http:post'
280
- || ref?.howToRun === 'http:get';
281
- }
282
-
283
241
  function makeHostedBoardWorkerRef(boardId, taskExecPath, transport, executionExtra) {
284
242
  if (!taskExecPath) return undefined;
285
243
  if (transport === 'in-process-loop') {
@@ -311,6 +269,21 @@ function makeHostedBoardWorkerRef(boardId, taskExecPath, transport, executionExt
311
269
  throw new Error(`Unsupported board-worker transport for demo host: ${transport}`);
312
270
  }
313
271
 
272
+ function isHostedTaskExecutorRef(ref) {
273
+ return ref?.howToRun === 'queue-storage'
274
+ || ref?.howToRun === 'in-process-loop'
275
+ || ref?.howToRun === 'http:post'
276
+ || ref?.howToRun === 'http:get';
277
+ }
278
+
279
+ function normalizeImmediateExecutorResult(result) {
280
+ if (typeof result === 'string') return result;
281
+ if (result && typeof result === 'object' && !Array.isArray(result) && typeof result.stdout === 'string') {
282
+ return String(result.stdout);
283
+ }
284
+ return JSON.stringify(result ?? {});
285
+ }
286
+
314
287
  function makeBoardWorkerCallbackTransport(serverUrl, boardApiBasePath, transport, boardId) {
315
288
  if (transport === 'in-process-loop' || transport === 'queue' || transport === 'http') {
316
289
  return createInProcessBoardCallbackTransport(`board:${boardId}:board-worker-callback`);
@@ -504,6 +477,24 @@ class MemoryAsyncBlobStorage {
504
477
  this.byteValues.delete(key);
505
478
  }
506
479
 
480
+ async renameKey(from, to) {
481
+ if (this.byteValues.has(from)) {
482
+ this.byteValues.set(to, this.byteValues.get(from));
483
+ this.byteValues.delete(from);
484
+ this.textValues.delete(to);
485
+ this.textValues.delete(from);
486
+ return true;
487
+ }
488
+ if (this.textValues.has(from)) {
489
+ this.textValues.set(to, this.textValues.get(from));
490
+ this.textValues.delete(from);
491
+ this.byteValues.delete(to);
492
+ this.byteValues.delete(from);
493
+ return true;
494
+ }
495
+ return false;
496
+ }
497
+
507
498
  async exists(key) {
508
499
  return this.textValues.has(key) || this.byteValues.has(key);
509
500
  }
@@ -735,6 +726,10 @@ function getCloudBoardBundle(boardId, notifyChannel, boardDir = null) {
735
726
  const kvNamespaces = new Map();
736
727
  const kvRefs = new Map();
737
728
  const blobNamespaces = new Map();
729
+ const blobRefs = new Map();
730
+ const chatRefs = new Map();
731
+ const queueRefs = new Map();
732
+ const journalRefs = new Map();
738
733
  const blobKindToNamespace = new Map([
739
734
  ['cloud-blob-key', ''],
740
735
  ['cloud-source-key', 'sources'],
@@ -772,11 +767,51 @@ function getCloudBoardBundle(boardId, notifyChannel, boardDir = null) {
772
767
  }
773
768
  return blobNamespaces.get(key);
774
769
  };
770
+ const getBlobRef = (ref) => {
771
+ const key = String(ref || '');
772
+ if (!blobRefs.has(key)) {
773
+ let kind = 'cloud-blob-key';
774
+ try {
775
+ kind = parseRef(key).kind;
776
+ } catch {
777
+ if (key.endsWith(':sources')) kind = 'cloud-source-key';
778
+ else if (key.endsWith(':archive')) kind = 'cloud-archive-key';
779
+ else if (key.endsWith(':scratch')) kind = 'cloud-scratch-key';
780
+ }
781
+ const keyRefFactory = kind === 'cloud-source-key' && stagedSourcesDir
782
+ ? (blobKey) => ({ kind: 'fs-path', value: path.join(stagedSourcesDir, ...String(blobKey).split('/')) })
783
+ : null;
784
+ blobRefs.set(key, new MemoryAsyncBlobStorage(kind, keyRefFactory));
785
+ }
786
+ return blobRefs.get(key);
787
+ };
788
+ const getChatRef = (ref) => {
789
+ const key = String(ref || '');
790
+ if (!chatRefs.has(key)) chatRefs.set(key, createInMemoryChatStorage());
791
+ return chatRefs.get(key);
792
+ };
793
+ const getQueueRef = (ref, lane) => {
794
+ const key = `${String(ref || '')}::${String(lane || '')}`;
795
+ if (!queueRefs.has(key)) {
796
+ if (lane === 'task-executor') queueRefs.set(key, boardWorkerQueueStorage);
797
+ else if (lane === 'chat-agent') queueRefs.set(key, chatAgentQueueStorage);
798
+ else if (lane === 'process-accumulated') queueRefs.set(key, processAccumulatedQueueStorage);
799
+ else queueRefs.set(key, new MemoryAsyncQueueStorage());
800
+ }
801
+ return queueRefs.get(key);
802
+ };
803
+ const getJournalRef = (ref) => {
804
+ const key = String(ref || '');
805
+ if (!journalRefs.has(key)) journalRefs.set(key, archiveFactory.stream(`board-journal-${stableHash(key)}`));
806
+ return journalRefs.get(key);
807
+ };
808
+ const queueStoreRef = serializeRef({ kind: 'cloud-queue-ref', value: `${boardId}:runtime` });
775
809
 
776
810
  const bundle = {
777
811
  getKvNamespace,
778
812
  getKvRef,
779
813
  getBlobNamespace,
814
+ getChatRef,
780
815
  adapter: null,
781
816
  notifyChannel,
782
817
  };
@@ -786,14 +821,16 @@ function getCloudBoardBundle(boardId, notifyChannel, boardDir = null) {
786
821
  kvStorage: (namespace) => getKvNamespace(namespace),
787
822
  kvStorageForRef: (ref) => getKvRef(ref),
788
823
  blobStorage: (namespace) => getBlobNamespace(namespace),
824
+ blobStorageForRef: (ref) => getBlobRef(ref),
825
+ chatStorageForRef: (ref) => getChatRef(ref),
826
+ queueStorageForRef: (ref, lane) => getQueueRef(ref, lane),
789
827
  scratchStorage: () => scratchStore,
790
828
  scratchStorageForRef: () => scratchStore,
791
829
  archiveFactory: () => archiveFactory,
792
830
  archiveFactoryForRef: () => archiveFactory,
793
831
  journalStorage: () => journalStorage,
794
- queueStorage: boardWorkerQueueStorage,
795
- chatAgentQueueStorage,
796
- processAccumulatedQueueStorage,
832
+ journalStorageForRef: (ref) => getJournalRef(ref),
833
+ queueStoreRef,
797
834
  lock: createImmediateAsyncLock(),
798
835
  callbackTransport: undefined,
799
836
  resolveBlob: async (ref) => {
@@ -851,8 +888,10 @@ function buildBoardContextConfig(label, boardDir, taskExecPath, chatHandlerFlow,
851
888
  const runtimeCardStoreDir = path.join(runtimeCardsDir, 'store');
852
889
  fs.mkdirSync(runtimeCardStoreDir, { recursive: true });
853
890
  const runtimeOutDir = path.join(path.dirname(boardDir), 'runtime-out');
891
+ const fetchedSourcesDir = path.join(path.dirname(boardDir), 'sources');
854
892
  const scratchDir = path.join(runtimeOutDir, '.tmp');
855
893
  const archiveDir = path.join(runtimeOutDir, 'archive');
894
+ fs.mkdirSync(fetchedSourcesDir, { recursive: true });
856
895
  fs.mkdirSync(scratchDir, { recursive: true });
857
896
  fs.mkdirSync(archiveDir, { recursive: true });
858
897
 
@@ -866,6 +905,7 @@ function buildBoardContextConfig(label, boardDir, taskExecPath, chatHandlerFlow,
866
905
  if (runtimeMode === 'cloud') {
867
906
  const cloudBundle = getCloudBoardBundle(boardId, notifyChannel, boardDir);
868
907
  cloudBundle.adapter.callbackTransport = callbackTransport;
908
+ const boardRuntimeStoreRef = serializeRef({ kind: 'cloud-kv-ref', value: `${boardId}:runtime-board` });
869
909
  const cloudNonCoreAdapter = createFsBoardNonCorePlatformAdapter(
870
910
  parseRef(serializeRef({ kind: 'fs-path', value: boardDir })),
871
911
  {
@@ -873,35 +913,46 @@ function buildBoardContextConfig(label, boardDir, taskExecPath, chatHandlerFlow,
873
913
  ...(callbackTransport ? { callbackTransport } : {}),
874
914
  },
875
915
  );
916
+ const cloudKvStorageForRef = cloudNonCoreAdapter.kvStorageForRef.bind(cloudNonCoreAdapter);
917
+ cloudNonCoreAdapter.kvStorageForRef = (ref) => {
918
+ try {
919
+ if (parseRef(ref).kind === 'cloud-kv-ref') return cloudBundle.getKvRef(ref);
920
+ } catch {}
921
+ return cloudKvStorageForRef(ref);
922
+ };
876
923
  const cloudHostedTaskExecutorRef = makeHostedBoardWorkerRef(boardId, taskExecPath, boardWorkerTransport, executionExtra);
877
- const cloudLocalSyncTaskExecutorRef = makeLocalTaskExecutorRef(taskExecPath, executionExtra);
878
- if (cloudLocalSyncTaskExecutorRef) {
924
+ const hostedBoardWorkerDispatch = createHostedBoardWorkerDispatcher(boardId, taskExecPath);
925
+ if (hostedBoardWorkerDispatch) {
926
+ const immediateTaskExecutor = createImmediateBoardWorkerHook(hostedBoardWorkerDispatch, executionExtra);
879
927
  const invokeExecutor = cloudNonCoreAdapter.invokeExecutor.bind(cloudNonCoreAdapter);
880
- cloudNonCoreAdapter.invokeExecutor = (ref, subcommand, execOpts) => {
881
- const syncRef = isHostedTaskExecutorRef(ref) ? cloudLocalSyncTaskExecutorRef : ref;
882
- return invokeExecutor(syncRef, subcommand, execOpts);
928
+ cloudNonCoreAdapter.invokeExecutor = async (ref, subcommand, execOpts) => {
929
+ if (isHostedTaskExecutorRef(ref)) {
930
+ const result = await immediateTaskExecutor({
931
+ subcommand,
932
+ ...(execOpts?.input !== undefined ? { input: execOpts.input } : {}),
933
+ ...(execOpts?.timeout !== undefined ? { timeoutMs: execOpts.timeout } : {}),
934
+ ...(ref?.extra ? { extra: ref.extra } : {}),
935
+ });
936
+ return normalizeImmediateExecutorResult(result);
937
+ }
938
+ return invokeExecutor(ref, subcommand, execOpts);
883
939
  };
884
940
  }
885
941
  cloudNonCoreAdapter.requestProcessAccumulated = () => {};
886
- try {
887
- const seedTeRef = cloudLocalSyncTaskExecutorRef ?? cloudHostedTaskExecutorRef;
888
- if (seedTeRef) {
889
- cloudNonCoreAdapter.kvStorage('config').write('task-executor', serializeExecutionRef(seedTeRef));
890
- }
891
- } catch (e) {
892
- logger.warn(`[cloud:${boardId}] failed to seed non-core task-executor config: ${e?.message || e}`);
893
- }
894
942
  return {
895
943
  label,
896
944
  boardAdapter: cloudBundle.adapter,
897
945
  nonCoreAdapter: cloudNonCoreAdapter,
898
- artifactsAdapter: cloudBundle.adapter,
899
946
  baseRef: { kind: 'cloud-board', value: `board:${boardId}` },
900
- cardStoreRef: `cloud:${boardId}:cards`,
901
- outputsStoreRef: `cloud:${boardId}:runtime-out`,
902
- artifactsStoreRef: `cloud:${boardId}:artifacts`,
903
- scratchStoreRef: `cloud:${boardId}:scratch`,
904
- archiveStoreRef: `cloud:${boardId}:archive`,
947
+ boardRuntimeStoreRef,
948
+ cardStoreRef: serializeRef({ kind: 'cloud-kv-ref', value: `${boardId}:cards` }),
949
+ outputsStoreRef: serializeRef({ kind: 'cloud-blob-key', value: `${boardId}:runtime-out` }),
950
+ queueStoreRef: serializeRef({ kind: 'cloud-queue-ref', value: `${boardId}:runtime` }),
951
+ fetchedSourcesStoreRef: serializeRef({ kind: 'cloud-source-key', value: `${boardId}:sources` }),
952
+ chatStoreRef: serializeRef({ kind: 'cloud-chat-ref', value: `${boardId}:chat` }),
953
+ artifactsStoreRef: serializeRef({ kind: 'cloud-blob-key', value: `${boardId}:artifacts` }),
954
+ scratchStoreRef: serializeRef({ kind: 'cloud-scratch-key', value: `${boardId}:scratch` }),
955
+ archiveStoreRef: serializeRef({ kind: 'cloud-archive-key', value: `${boardId}:archive` }),
905
956
  notifyRef: { kind: 'in-memory-notify', value: notifyChannel },
906
957
  taskExecutorRef: cloudHostedTaskExecutorRef,
907
958
  chatHandlerFlow,
@@ -910,40 +961,38 @@ function buildBoardContextConfig(label, boardDir, taskExecPath, chatHandlerFlow,
910
961
  }
911
962
 
912
963
  const baseRef = parseRef(serializeRef({ kind: 'fs-path', value: boardDir }));
964
+ const artifactsStoreRef = serializeRef({ kind: 'fs-path', value: runtimeCardsDir });
965
+ const cardStoreRef = serializeRef({ kind: 'fs-path', value: runtimeCardStoreDir });
966
+ const fetchedSourcesStoreRef = serializeRef({ kind: 'fs-path', value: fetchedSourcesDir });
967
+ const boardRuntimeStoreRef = serializeRef({ kind: 'fs-path', value: path.join(runtimeOutDir, '.board-runtime') });
968
+ const queueStoreRef = serializeRef({ kind: 'fs-path', value: path.join(runtimeOutDir, '.runtime') });
969
+ const scratchStoreRef = serializeRef({ kind: 'fs-path', value: scratchDir });
970
+ const archiveStoreRef = serializeRef({ kind: 'fs-path', value: archiveDir });
971
+ const chatStoreRef = serializeRef({ kind: 'fs-path', value: boardDir });
913
972
  const boardAdapter = createFsBoardPlatformAdapter(baseRef, {
914
973
  notifyChannel,
974
+ boardRuntimeStoreRef,
975
+ queueStoreRef,
915
976
  ...(callbackTransport ? { callbackTransport } : {}),
916
977
  });
917
978
  const nonCoreAdapter = createFsBoardNonCorePlatformAdapter(baseRef, {
918
979
  notifyChannel,
919
980
  ...(callbackTransport ? { callbackTransport } : {}),
920
981
  });
921
- const localSyncTaskExecutorRef = makeLocalTaskExecutorRef(taskExecPath, executionExtra);
922
- if (localSyncTaskExecutorRef) {
923
- const invokeExecutor = nonCoreAdapter.invokeExecutor.bind(nonCoreAdapter);
924
- nonCoreAdapter.invokeExecutor = (ref, subcommand, execOpts) => {
925
- const syncRef = isHostedTaskExecutorRef(ref) ? localSyncTaskExecutorRef : ref;
926
- return invokeExecutor(syncRef, subcommand, execOpts);
927
- };
928
- }
929
982
  boardAdapter.requestProcessAccumulated = () => {};
930
983
  nonCoreAdapter.requestProcessAccumulated = () => {};
931
984
 
932
- const artifactsRef = parseRef(serializeRef({ kind: 'fs-path', value: runtimeCardsDir }));
933
- const artifactsAdapter = createFsBoardPlatformAdapter(artifactsRef, { suppressSpawn: true });
934
- const artifactsStoreRef = serializeRef({ kind: 'fs-path', value: runtimeCardsDir });
935
- const cardStoreRef = serializeRef({ kind: 'fs-path', value: runtimeCardStoreDir });
936
- const scratchStoreRef = serializeRef({ kind: 'fs-path', value: scratchDir });
937
- const archiveStoreRef = serializeRef({ kind: 'fs-path', value: archiveDir });
938
-
939
985
  return {
940
986
  label,
941
987
  boardAdapter,
942
988
  nonCoreAdapter,
943
- artifactsAdapter,
944
989
  baseRef,
990
+ boardRuntimeStoreRef,
945
991
  cardStoreRef,
946
992
  outputsStoreRef: serializeRef({ kind: 'fs-path', value: runtimeOutDir }),
993
+ queueStoreRef,
994
+ fetchedSourcesStoreRef,
995
+ chatStoreRef,
947
996
  artifactsStoreRef,
948
997
  scratchStoreRef,
949
998
  archiveStoreRef,
@@ -1018,12 +1067,10 @@ const runtime = createMultiBoardServerRuntime({
1018
1067
  const chatHandlerFlow = applyFlowTimeout(
1019
1068
  loadJsonFromConfig(regular.chatHandlerFlowPath)
1020
1069
  || entry?.chatHandlerFlow
1021
- || buildChatHandlerFlowFromScript(chatHandlerPath, boardFlowTimeoutMs)
1022
1070
  || configuredChatHandlerFlow,
1023
1071
  boardFlowTimeoutMs,
1024
1072
  );
1025
1073
  const infAdapterPath = resolveFromConfig(regular.inferenceAdapterPath) || (entry?.inferenceAdapterPath || configuredInferenceAdapterPath);
1026
- const stepMachinePath = resolveFromConfig(regular.stepMachineCliPath || cfg?.stepMachineCliPath) || (entry?.stepMachineCliPath || configuredStepMachineCliPath);
1027
1074
  const runtimeMode = normalizeRuntimeMode(regular.mode || entry?.mode || cfg?.mode || configuredRuntimeMode);
1028
1075
  const boardWorkerTransport = normalizeHostedBoardWorkerTransport(
1029
1076
  runtimeMode,
@@ -1066,7 +1113,6 @@ const runtime = createMultiBoardServerRuntime({
1066
1113
  serverUrl: `http://127.0.0.1:${PORT}`,
1067
1114
  taskExecutorTransport: boardWorkerTransport,
1068
1115
  chatCopilotTimeoutMs,
1069
- ...(stepMachinePath ? { stepMachineCliPath: stepMachinePath } : {}),
1070
1116
  };
1071
1117
 
1072
1118
  const baseCfg = buildBoardContextConfig('base', boardDir, taskExecPath, chatHandlerFlow, infAdapterPath, boardId, baseExecutionExtra, runtimeMode);
@@ -1083,13 +1129,14 @@ const runtime = createMultiBoardServerRuntime({
1083
1129
  }
1084
1130
  }
1085
1131
 
1086
- const chatStorage = createFsBoardChatStorage(boardDir);
1132
+ const chatStorage = runtimeMode === 'cloud'
1133
+ ? getCloudBoardBundle(boardId, baseCfg.notifyRef.value, boardDir).getChatRef(baseCfg.chatStoreRef)
1134
+ : createFsBoardChatStorage(boardDir);
1087
1135
  hostedBoardChatStorages.set(boardId, chatStorage);
1088
1136
 
1089
1137
  const singleBoardRuntime = createSingleBoardServerRuntime({
1090
1138
  apiBasePath: `${apiBasePath}/${boardId}`,
1091
1139
  boardId,
1092
- chatStorage,
1093
1140
  boards,
1094
1141
  invocationAdapter,
1095
1142
  chatFlowRunner: flowRunner,
@@ -1105,7 +1152,6 @@ const runtime = createMultiBoardServerRuntime({
1105
1152
  projectRoot: BOARD_ROOT,
1106
1153
  chatFlowRoot,
1107
1154
  chatCopilotTimeoutMs,
1108
- ...(stepMachinePath ? { stepMachineCliPath: stepMachinePath } : {}),
1109
1155
  },
1110
1156
  });
1111
1157
 
@@ -1125,6 +1171,9 @@ const runtime = createMultiBoardServerRuntime({
1125
1171
  });
1126
1172
  return { result: 'success', data: { dispatched: true } };
1127
1173
  });
1174
+ registerInProcessBoardWorkerInvoke(`board:${boardId}:board-worker`, async (request) => {
1175
+ return await hostedBoardWorkerDispatch(request);
1176
+ });
1128
1177
  }
1129
1178
  if ((boardWorkerTransport === 'in-process-loop' || boardWorkerTransport === 'queue' || boardWorkerTransport === 'http') && hostedBoardWorkerDispatch) {
1130
1179
  registerInProcessBoardWorkerCallback(`board:${boardId}:board-worker-callback`, (payload) => {
@@ -1136,6 +1185,7 @@ const runtime = createMultiBoardServerRuntime({
1136
1185
  }
1137
1186
  const stopQueueRunner = startQueueLaneRunners(createHostedBoardQueueLaneRegistry({
1138
1187
  boardId,
1188
+ queueStoreRef: baseCfg.queueStoreRef,
1139
1189
  runtime: singleBoardRuntime,
1140
1190
  boardAdapter: baseCfg.boardAdapter,
1141
1191
  logger,
@@ -1293,7 +1343,7 @@ server.listen(PORT, '127.0.0.1', () => {
1293
1343
  console.log('[board-server] endpoints:');
1294
1344
  console.log(` GET ${apiBasePath} <- list boards`);
1295
1345
  console.log(` POST ${apiBasePath} {id, label?} <- register board`);
1296
- console.log(` GET ${apiBasePath}/:boardId/init-board`);
1346
+ console.log(` GET ${apiBasePath}/:boardId/sse?one-shot`);
1297
1347
  console.log(` GET ${apiBasePath}/:boardId/sse`);
1298
1348
  console.log(` GET ${apiBasePath}/:boardId/board-status`);
1299
1349
  console.log(` GET ${apiBasePath}/:boardId/cards/:id`);
@@ -36,14 +36,6 @@
36
36
  "serverUrl": {
37
37
  "type": "string",
38
38
  "description": "Base URL of the hosting server (e.g. http://127.0.0.1:7799). Used by source kinds that call server-side endpoints."
39
- },
40
- "boardLiveCardsCliJs": {
41
- "type": "string",
42
- "description": "Absolute path to board-live-cards-cli.js when injected by the runtime; for authored ExecutionRefs that target the packaged CLI, prefer kind 'yaml-flow-cli' with value 'board-live-cards-cli.js'."
43
- },
44
- "stepMachineCliPath": {
45
- "type": "string",
46
- "description": "Absolute path to step-machine-cli.js when injected by the runtime; for authored ExecutionRefs that target the packaged CLI, prefer kind 'yaml-flow-cli' with value 'step-machine-cli.js'."
47
39
  }
48
40
  }
49
41
  },
@@ -38,9 +38,7 @@
38
38
  * "boardRuntimeDir": "<relative>",
39
39
  * "runtimeStatusDir": "<relative>",
40
40
  * "cardsDir": "<relative>",
41
- * "serverUrl": "<base url>",
42
- * "boardLiveCardsCliJs": "<abs path>",
43
- * "stepMachineCliPath": "<abs path>"
41
+ * "serverUrl": "<base url>"
44
42
  * }
45
43
  *
46
44
  * Source kinds are resolved from source_def_flows.json in resolveOrder.
@@ -72,11 +72,10 @@
72
72
  "data._legacyEnvelope = data._hasLegacyEnvelope ? $eval(data._rawMessageText) : null",
73
73
  "data._legacyPrompt = ($type(data._legacyEnvelope.prompt) = \"string\" and $length($trim(data._legacyEnvelope.prompt)) > 0) ? data._legacyEnvelope.prompt : (($type(data._legacyEnvelope.text) = \"string\" and $length($trim(data._legacyEnvelope.text)) > 0) ? data._legacyEnvelope.text : (($type(data._legacyEnvelope.userText) = \"string\" and $length($trim(data._legacyEnvelope.userText)) > 0) ? data._legacyEnvelope.userText : (($type(data._legacyEnvelope.query) = \"string\" and $length($trim(data._legacyEnvelope.query)) > 0) ? data._legacyEnvelope.query : null)))",
74
74
  "data.userText = data._isEchoProbe ? $trim($substring(data._rawMessageText, data._markerLen, $length(data._rawMessageText) - (data._markerLen * 2))) : (($type(data._legacyPrompt) = \"string\" and $length($trim(data._legacyPrompt)) > 0) ? $trim(data._legacyPrompt) : data._rawMessageText)",
75
- "data._attachMarker = \"[attach]\"",
76
- "data.probeGenerateAttachment = $lowercase($substring(data.userText, 0, $length(data._attachMarker))) = data._attachMarker",
77
- "data.userText = data.probeGenerateAttachment ? $trim($substring(data.userText, $length(data._attachMarker))) : data.userText",
75
+ "data._probeMode = $type(expects_data.probe) = \"string\" ? $lowercase($trim(expects_data.probe)) : \"\"",
76
+ "data.probeGenerateAttachment = data._probeMode = \"echoattach\"",
78
77
  "data.replyFiles = []",
79
- "data.probe = data._isEchoProbe ? true : (data._legacyEnvelope.probe = true or data._legacyEnvelope.probe = 1 or ($type(data._legacyEnvelope.probe) = \"string\" and $count($filter([\"1\", \"true\", \"yes\", \"on\"], function($value) { $value = $lowercase($trim(data._legacyEnvelope.probe)) })) > 0))",
78
+ "data.probe = (data._isEchoProbe or $length(data._probeMode) > 0) ? true : (data._legacyEnvelope.probe = true or data._legacyEnvelope.probe = 1 or ($type(data._legacyEnvelope.probe) = \"string\" and $count($filter([\"1\", \"true\", \"yes\", \"on\"], function($value) { $value = $lowercase($trim(data._legacyEnvelope.probe)) })) > 0))",
80
79
  "data.chatHandlerMode = data._isEchoProbe ? \"echo-probe\" : (($type(data._legacyEnvelope.chatHandlerMode) = \"string\" and $length($trim(data._legacyEnvelope.chatHandlerMode)) > 0) ? $lowercase($trim(data._legacyEnvelope.chatHandlerMode)) : (data.probe ? \"probe\" : \"copilot\"))",
81
80
  "data.chatCopilotTimeoutMs = ($parsePositiveInt := function($value) { ($type($value) = \"number\" and $value > 0) ? $floor($value) : (($type($value) = \"string\" and $count($match($trim($value), /^[0-9]+$/)) > 0 and $number($trim($value)) > 0) ? $floor($number($trim($value))) : null) }; $legacyTimeout := $parsePositiveInt(data._legacyEnvelope.chatTimeoutMs); $legacyCopilotTimeout := $parsePositiveInt(data._legacyEnvelope.chatCopilotTimeoutMs); $fallbackTimeout := $parsePositiveInt(expects_data.chatCopilotTimeoutMs); $legacyTimeout ? $legacyTimeout : ($legacyCopilotTimeout ? $legacyCopilotTimeout : ($fallbackTimeout ? $fallbackTimeout : 300000)))",
82
81
  "result = \"success\""
@@ -95,7 +94,8 @@
95
94
  "handler": {
96
95
  "type": "compute-jsonata",
97
96
  "expr": [
98
- "data.selectedAssistant = (expects_data.probe = true or expects_data.probe = \"true\" or expects_data.probe = 1 or $lowercase($string(expects_data.chatHandlerMode)) = \"probe\" or $lowercase($string(expects_data.chatHandlerMode)) = \"echo-probe\") ? \"probe\" : \"copilot\"",
97
+ "data._probeMode = $type(expects_data.probe) = \"string\" ? $lowercase($trim(expects_data.probe)) : \"\"",
98
+ "data.selectedAssistant = (expects_data.probe = true or expects_data.probe = \"true\" or expects_data.probe = 1 or $length(data._probeMode) > 0 or $lowercase($string(expects_data.chatHandlerMode)) = \"probe\" or $lowercase($string(expects_data.chatHandlerMode)) = \"echo-probe\") ? \"probe\" : \"copilot\"",
99
99
  "result = data.selectedAssistant"
100
100
  ]
101
101
  },