yaml-flow 8.4.23 → 8.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/browser/asset-integrity.json +3 -3
  2. package/cli/browser-api/board-live-cards-browser-adapter.d.ts +1 -1
  3. package/cli/browser-api/board-live-cards-browser-adapter.js +1 -1
  4. package/cli/bundled/board-live-cards-cli.mjs +14 -14
  5. package/cli/bundled/chat-store-cli.mjs +6 -6
  6. package/cli/{types-juH2nFpz.d.ts → types-D2s3VzyY.d.ts} +3 -2
  7. package/examples/board/demo-shell-with-server.html +2 -2
  8. package/examples/board/doc.html +2 -2
  9. package/examples/board/server/board-server.js +8 -0
  10. package/examples/board/server/chat-flow/copilot-chat/assistant.js +4 -2
  11. package/examples/board/server/chat-flow/flow-steps.json +70 -10
  12. package/examples/board/test/server-http-mcp-test.js +791 -0
  13. package/examples/board/test/server-http-test.js +32 -15
  14. package/examples/board-local/demo-shell-localstorage.html +3 -3
  15. package/lib/artifacts-store-public.d.cts +1 -1
  16. package/lib/artifacts-store-public.d.ts +1 -1
  17. package/lib/board-live-cards-mcp.cjs +2 -0
  18. package/lib/board-live-cards-mcp.d.cts +259 -0
  19. package/lib/board-live-cards-mcp.d.ts +259 -0
  20. package/lib/board-live-cards-mcp.js +2 -0
  21. package/lib/board-live-cards-node.cjs +14 -14
  22. package/lib/board-live-cards-node.d.cts +8 -6
  23. package/lib/board-live-cards-node.d.ts +8 -6
  24. package/lib/board-live-cards-node.js +14 -14
  25. package/lib/{board-live-cards-public-B4RcYPC_.d.cts → board-live-cards-public-CvkDfZQ7.d.cts} +1 -1
  26. package/lib/{board-live-cards-public-ydXuA4zh.d.ts → board-live-cards-public-DdVhH4M-.d.ts} +1 -1
  27. package/lib/board-live-cards-public.cjs +1 -1
  28. package/lib/board-live-cards-public.d.cts +1 -1
  29. package/lib/board-live-cards-public.d.ts +1 -1
  30. package/lib/board-live-cards-public.js +1 -1
  31. package/lib/board-live-cards-server-runtime.cjs +5 -4
  32. package/lib/board-live-cards-server-runtime.d.cts +3 -3
  33. package/lib/board-live-cards-server-runtime.d.ts +3 -3
  34. package/lib/board-live-cards-server-runtime.js +5 -4
  35. package/lib/card-store-public.d.cts +1 -1
  36. package/lib/card-store-public.d.ts +1 -1
  37. package/lib/{chat-storage-lib-B1wU27y3.d.cts → chat-storage-lib-0imhRX3l.d.cts} +2 -1
  38. package/lib/{chat-storage-lib-DsF4kPon.d.ts → chat-storage-lib-CJn7a6OH.d.ts} +2 -1
  39. package/lib/chat-store-public.cjs +1 -1
  40. package/lib/chat-store-public.d.cts +2 -2
  41. package/lib/chat-store-public.d.ts +2 -2
  42. package/lib/chat-store-public.js +1 -1
  43. package/lib/server-runtime/index.cjs +5 -4
  44. package/lib/server-runtime/index.d.cts +4 -4
  45. package/lib/server-runtime/index.d.ts +4 -4
  46. package/lib/server-runtime/index.js +5 -4
  47. package/lib/{types-D501gMQt.d.cts → types-NM_d_1oZ.d.cts} +5 -2
  48. package/lib/{types-1L1D33mr.d.ts → types-QNI__eAf.d.ts} +5 -2
  49. package/package.json +10 -2
  50. package/browser/board-livecards-localstorage.js +0 -10
@@ -318,6 +318,7 @@ interface ChatRecord {
318
318
  role: string;
319
319
  text: string;
320
320
  files: unknown[];
321
+ turn: string;
321
322
  updated_at: string;
322
323
  }
323
324
  interface ChatConfig {
@@ -330,7 +331,7 @@ interface ChatReadAfterResult {
330
331
  }
331
332
  interface ChatStorage {
332
333
  /** Append a message; returns the new entry id (usable as a cursor). */
333
- append(cardId: string, role: string, text: string, files?: unknown[]): string;
334
+ append(cardId: string, role: string, text: string, files?: unknown[], turn?: string): string;
334
335
  /** Read all messages in insertion order. */
335
336
  readAll(cardId: string): ChatRecord[];
336
337
  /**
@@ -389,4 +390,4 @@ interface DescribeEnvelope {
389
390
  supports?: string[];
390
391
  }
391
392
 
392
- export { type BoardPlatformAdapter as B, type ChatStorage as C, type DescribeEnvelope as D, type InvocationAdapter as I, type NotificationTransport as N, type CommandInput as a, type CommandResult as b, type BoardNonCorePlatformAdapter as c, type BoardLiveCardsNonCorePublic as d, type BoardLiveCardsPublic as e, type ChatConfig as f, type ChatRecord as g, createBoardLiveCardsNonCorePublic as h, createBoardLiveCardsPublic as i, createChatStorage as j, createInMemoryChatStorage as k };
393
+ export { type BoardPlatformAdapter as B, type ChatStorage as C, type DescribeEnvelope as D, type InvocationAdapter as I, type NotificationTransport as N, type CommandInput as a, type CommandResult as b, type ChatRecord as c, type ChatReadAfterResult as d, type ChatConfig as e, type BoardNonCorePlatformAdapter as f, type BoardLiveCardsNonCorePublic as g, type BoardLiveCardsPublic as h, createBoardLiveCardsNonCorePublic as i, createBoardLiveCardsPublic as j, createChatStorage as k, createInMemoryChatStorage as l };
@@ -19,8 +19,8 @@
19
19
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
20
20
  <script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
21
21
  <script src="https://cdn.jsdelivr.net/npm/leader-line/leader-line.min.js"></script>
22
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.4.23/browser/live-cards.js"></script>
23
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.4.23/browser/board-livecards-client.js"></script>
22
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.5.0/browser/live-cards.js"></script>
23
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.5.0/browser/board-livecards-client.js"></script>
24
24
  </head>
25
25
  <body class="bg-light">
26
26
  <div class="container-fluid py-3">
@@ -37,8 +37,8 @@
37
37
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
38
38
  <script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
39
39
  <script src="https://cdn.jsdelivr.net/npm/leader-line/leader-line.min.js"></script>
40
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.4.23/browser/live-cards.js"></script>
41
- <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.4.23/browser/board-livecards-client.js"></script>
40
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.5.0/browser/live-cards.js"></script>
41
+ <script src="https://cdn.jsdelivr.net/npm/yaml-flow@8.5.0/browser/board-livecards-client.js"></script>
42
42
  </head>
43
43
  <body class="bg-light">
44
44
  <div class="container-fluid py-3">
@@ -16,6 +16,7 @@ import {
16
16
  import {
17
17
  buildLocalBaseSpec,
18
18
  createFsBoardPlatformAdapter,
19
+ createFsBoardNonCorePlatformAdapter,
19
20
  createFsBoardChatStorage,
20
21
  createNodeSpawnInvocationAdapter,
21
22
  createArtifactsStore,
@@ -301,10 +302,13 @@ function buildBoardContextConfig(label, boardDir, taskExecPath, chatHandlerFlow,
301
302
  const notifyChannel = `yaml-flow-server-${label}-${boardId}-${process.pid}`;
302
303
  const baseRef = parseRef(serializeRef({ kind: 'fs-path', value: boardDir }));
303
304
  const boardAdapter = createFsBoardPlatformAdapter(baseRef, { notifyChannel });
305
+ const nonCoreAdapter = createFsBoardNonCorePlatformAdapter(baseRef, { notifyChannel });
304
306
  boardAdapter.requestProcessAccumulated = () => {};
307
+ nonCoreAdapter.requestProcessAccumulated = () => {};
305
308
 
306
309
  const artifactsRef = parseRef(serializeRef({ kind: 'fs-path', value: runtimeCardsDir }));
307
310
  const artifactsAdapter = createFsBoardPlatformAdapter(artifactsRef, { suppressSpawn: true });
311
+ const artifactsStoreRef = serializeRef({ kind: 'fs-path', value: runtimeCardsDir });
308
312
  const cardStoreRef = serializeRef({ kind: 'fs-path', value: runtimeCardStoreDir });
309
313
  const scratchStoreRef = serializeRef({ kind: 'fs-path', value: scratchDir });
310
314
  const archiveStoreRef = serializeRef({ kind: 'fs-path', value: archiveDir });
@@ -312,10 +316,12 @@ function buildBoardContextConfig(label, boardDir, taskExecPath, chatHandlerFlow,
312
316
  return {
313
317
  label,
314
318
  boardAdapter,
319
+ nonCoreAdapter,
315
320
  artifactsAdapter,
316
321
  baseRef,
317
322
  cardStoreRef,
318
323
  outputsStoreRef: serializeRef({ kind: 'fs-path', value: runtimeOutDir }),
324
+ artifactsStoreRef,
319
325
  scratchStoreRef,
320
326
  archiveStoreRef,
321
327
  notifyRef: { kind: 'named-pipe', value: namedPipePath(notifyChannel) },
@@ -422,6 +428,7 @@ const runtime = createMultiBoardServerRuntime({
422
428
  });
423
429
  const baseExecutionExtra = {
424
430
  boardSetupRoot: boardRoot,
431
+ boardBaseRef: serializeRef({ kind: 'fs-path', value: boardDir }),
425
432
  boardRuntimeDir: 'runtime',
426
433
  runtimeStatusDir: 'runtime-out',
427
434
  cardsDir: 'cards',
@@ -452,6 +459,7 @@ const runtime = createMultiBoardServerRuntime({
452
459
  serverUrl: `http://127.0.0.1:${PORT}`,
453
460
  executionExtra: {
454
461
  boardSetupRoot: boardRoot,
462
+ boardBaseRef: serializeRef({ kind: 'fs-path', value: boardDir }),
455
463
  boardRuntimeDir: 'runtime',
456
464
  runtimeStatusDir: 'runtime-out',
457
465
  cardsDir: 'cards',
@@ -30,6 +30,7 @@ const {
30
30
  cardsDir = '',
31
31
  chatMessages: rawChatMessages = [],
32
32
  userText = 'what is two plus two?',
33
+ turnId = '',
33
34
  chatCopilotTimeoutMs: rawChatCopilotTimeoutMs = 300000,
34
35
  } = extra;
35
36
 
@@ -39,7 +40,7 @@ const chatCopilotTimeoutMs = Number.isFinite(Number(rawChatCopilotTimeoutMs)) &&
39
40
  : 300000;
40
41
 
41
42
 
42
- function buildPrompt(cId, historyDump, currentUserText) {
43
+ function buildPrompt(cId, historyDump, currentUserText, currentTurnId) {
43
44
  const cardSetupDirRel = path.join(cardsDir, cId).replace(/\\/g, '/');
44
45
  const runtimeDirRel = boardRuntimeDir;
45
46
  const statusDirRel = runtimeStatusDir;
@@ -53,6 +54,7 @@ function buildPrompt(cId, historyDump, currentUserText) {
53
54
  'The user sees the data available in cards which is rendered, and the status from ' + statusDirRel + '.',
54
55
  'Everything else is internal detail not to be exposed to the user.',
55
56
  'The conversation history is provided below exactly as received from the runtime API as a string dump.',
57
+ ...(currentTurnId ? ['The current conversation turn id is: ' + currentTurnId] : []),
56
58
  'The current user query is: ' + currentUserText,
57
59
  'Return only the assistant response text for the user.',
58
60
  'Do not write files, and do not include any internal notes, logs, or orchestration details in the response.',
@@ -98,7 +100,7 @@ function runCopilot(prompt, workingDir) {
98
100
 
99
101
  const historyDump = JSON.stringify(chatMessages, null, 2);
100
102
  const workingDir = boardSetupRoot;
101
- const prompt = buildPrompt(cardId, historyDump, userText.trim());
103
+ const prompt = buildPrompt(cardId, historyDump, userText.trim(), String(turnId || '').trim());
102
104
 
103
105
  try {
104
106
  const replyText = runCopilot(prompt, workingDir).trim();
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "open_turn": {
40
40
  "description": "Resolve the current user turn from flow-provided chat messages and parse any chat envelope options",
41
- "produces_data": ["boardId", "cardId", "boardSetupRoot", "boardRuntimeDir", "runtimeStatusDir", "cardsDir", "projectRoot", "chatFlowRoot", "chatMessages", "userText", "lastChatEntryId", "probe", "chatHandlerMode", "chatCopilotTimeoutMs"],
41
+ "produces_data": ["boardId", "cardId", "boardSetupRoot", "boardBaseRef", "boardRuntimeDir", "runtimeStatusDir", "cardsDir", "projectRoot", "chatFlowRoot", "chatMessages", "userText", "lastChatEntryId", "turnId", "probe", "chatHandlerMode", "chatCopilotTimeoutMs", "probeAttachmentFileIdx"],
42
42
  "input_validations": [
43
43
  "$type(cardId) = \"string\" and $length(cardId) > 0",
44
44
  "$type(chatMessages) = \"array\"",
@@ -51,6 +51,7 @@
51
51
  "data.boardId = $type(expects_data.boardId) = \"string\" ? expects_data.boardId : \"\"",
52
52
  "data.cardId = $type(expects_data.cardId) = \"string\" ? expects_data.cardId : \"\"",
53
53
  "data.boardSetupRoot = $type(expects_data.boardSetupRoot) = \"string\" ? expects_data.boardSetupRoot : \"\"",
54
+ "data.boardBaseRef = $type(expects_data.boardBaseRef) = \"string\" ? expects_data.boardBaseRef : \"\"",
54
55
  "data.boardRuntimeDir = ($type(expects_data.boardRuntimeDir) = \"string\" and $length(expects_data.boardRuntimeDir) > 0) ? expects_data.boardRuntimeDir : \"runtime\"",
55
56
  "data.runtimeStatusDir = ($type(expects_data.runtimeStatusDir) = \"string\" and $length(expects_data.runtimeStatusDir) > 0) ? expects_data.runtimeStatusDir : \"runtime-out\"",
56
57
  "data.cardsDir = ($type(expects_data.cardsDir) = \"string\" and $length(expects_data.cardsDir) > 0) ? expects_data.cardsDir : \"cards\"",
@@ -58,7 +59,10 @@
58
59
  "data.chatFlowRoot = $type(expects_data.chatFlowRoot) = \"string\" ? expects_data.chatFlowRoot : \"\"",
59
60
  "data.chatMessages = expects_data.chatMessages",
60
61
  "data.lastChatEntryId = expects_data.lastChatEntryId",
61
- "data._rawMessageText = $trim($string($filter(expects_data.chatMessages, function($message) { $message.id = expects_data.lastChatEntryId and $message.role = \"user\" })[0].text))",
62
+ "data._currentUserMessage = $filter(expects_data.chatMessages, function($message) { $message.id = expects_data.lastChatEntryId and $message.role = \"user\" })[0]",
63
+ "data.turnId = ($type(expects_data.turnId) = \"string\") ? expects_data.turnId : (($type(data._currentUserMessage.turn) = \"string\") ? data._currentUserMessage.turn : \"\")",
64
+ "data._rawMessageText = $trim($string(data._currentUserMessage.text))",
65
+ "data.probeAttachmentFileIdx = ($type(data._currentUserMessage.files) = \"array\" and $count(data._currentUserMessage.files) > 0) ? 0 : null",
62
66
  "data._marker = \"__probe__echo__probe__\"",
63
67
  "data._markerLen = $length(data._marker)",
64
68
  "data._isEchoProbe = $length(data._rawMessageText) >= (data._markerLen * 2) and $substring(data._rawMessageText, 0, data._markerLen) = data._marker and $substring(data._rawMessageText, $length(data._rawMessageText) - data._markerLen) = data._marker",
@@ -91,7 +95,25 @@
91
95
  },
92
96
  "transitions": {
93
97
  "copilot": "copilot_assistant",
94
- "probe": "probe_assistant",
98
+ "probe": "select_probe_reply_source",
99
+ "failure": "cleanup_failure",
100
+ "error": "cleanup_failure"
101
+ }
102
+ },
103
+ "select_probe_reply_source": {
104
+ "description": "Use attached file content for probe replies when the current user message carries a file",
105
+ "expects_data": ["probeAttachmentFileIdx"],
106
+ "produces_data": ["probeReplySource"],
107
+ "handler": {
108
+ "type": "compute-jsonata",
109
+ "expr": [
110
+ "data.probeReplySource = $type(expects_data.probeAttachmentFileIdx) = \"number\" ? \"attachment\" : \"echo\"",
111
+ "result = data.probeReplySource"
112
+ ]
113
+ },
114
+ "transitions": {
115
+ "attachment": "probe_attachment_reply",
116
+ "echo": "probe_assistant",
95
117
  "failure": "cleanup_failure",
96
118
  "error": "cleanup_failure"
97
119
  }
@@ -108,7 +130,7 @@
108
130
  "meta": "chat-handler",
109
131
  "argsMassaging": {
110
132
  "cmdTemplate": ["'--stdin'"],
111
- "stdinTemplate": "{ 'storeRef': $fsPathRef(boardSetupRoot & '/' & boardRuntimeDir), 'cardId': cardId, 'commands': [{ 'command': 'append', 'role': 'system', 'text': 'in-progress', 'files': [] }] }"
133
+ "stdinTemplate": "{ 'storeRef': $fsPathRef(boardSetupRoot & '/' & boardRuntimeDir), 'cardId': cardId, 'commands': [{ 'command': 'append', 'role': 'system', 'text': 'in-progress', 'files': [], 'turn': turnId }] }"
112
134
  }
113
135
  },
114
136
  "transitions": {
@@ -117,9 +139,47 @@
117
139
  "error": "cleanup_failure"
118
140
  }
119
141
  },
142
+ "probe_attachment_reply": {
143
+ "description": "Read the current probe attachment via board-live-cards-cli and use its content as the assistant reply",
144
+ "expects_data": ["boardBaseRef", "cardId", "probeAttachmentFileIdx"],
145
+ "produces_data": ["replyText"],
146
+ "input_validations": [
147
+ "$type(boardBaseRef) = \"string\" and $length(boardBaseRef) > 0",
148
+ "$type(cardId) = \"string\" and $length(cardId) > 0",
149
+ "$type(probeAttachmentFileIdx) = \"number\" and probeAttachmentFileIdx >= 0"
150
+ ],
151
+ "handler": {
152
+ "type": "ref",
153
+ "howToRun": "local-node",
154
+ "whatToRun": {
155
+ "kind": "yaml-flow-cli",
156
+ "value": "board-live-cards-cli.js"
157
+ },
158
+ "meta": "chat-handler",
159
+ "argsMassaging": {
160
+ "cmdTemplate": [
161
+ "'get-attachment-content'",
162
+ "'--base-ref'",
163
+ "boardBaseRef",
164
+ "'--card-id'",
165
+ "cardId",
166
+ "'--file-idx'",
167
+ "$string(probeAttachmentFileIdx)"
168
+ ]
169
+ },
170
+ "outputTransforms": {
171
+ "dataTemplate": "{ 'replyText': $string(output.data.stdout) }"
172
+ }
173
+ },
174
+ "transitions": {
175
+ "success": "probe_in_progress",
176
+ "failure": "cleanup_failure",
177
+ "error": "cleanup_failure"
178
+ }
179
+ },
120
180
  "copilot_assistant": {
121
181
  "description": "Run the Copilot-backed assistant logic to generate the reply from the resolved chat history",
122
- "expects_data": ["userText", "chatMessages", "boardId", "cardId", "boardSetupRoot", "boardRuntimeDir", "runtimeStatusDir", "cardsDir", "projectRoot", "chatFlowRoot", "chatCopilotTimeoutMs"],
182
+ "expects_data": ["userText", "chatMessages", "boardId", "cardId", "boardSetupRoot", "boardRuntimeDir", "runtimeStatusDir", "cardsDir", "projectRoot", "chatFlowRoot", "chatCopilotTimeoutMs", "turnId"],
123
183
  "produces_data": ["replyText"],
124
184
  "input_validations": [
125
185
  "$type(userText) = \"string\"",
@@ -134,7 +194,7 @@
134
194
  },
135
195
  "argsMassaging": {
136
196
  "cmdTemplate": ["chatFlowRoot & '/copilot-chat/assistant.js'"],
137
- "stdinTemplate": "{ 'cardId': cardId, 'boardSetupRoot': boardSetupRoot, 'boardRuntimeDir': boardRuntimeDir, 'runtimeStatusDir': runtimeStatusDir, 'cardsDir': cardsDir, 'chatMessages': chatMessages, 'userText': userText, 'chatCopilotTimeoutMs': chatCopilotTimeoutMs }"
197
+ "stdinTemplate": "{ 'cardId': cardId, 'boardSetupRoot': boardSetupRoot, 'boardRuntimeDir': boardRuntimeDir, 'runtimeStatusDir': runtimeStatusDir, 'cardsDir': cardsDir, 'chatMessages': chatMessages, 'userText': userText, 'chatCopilotTimeoutMs': chatCopilotTimeoutMs, 'turnId': turnId }"
138
198
  },
139
199
  "meta": "chat-handler"
140
200
  },
@@ -166,7 +226,7 @@
166
226
  },
167
227
  "write_reply": {
168
228
  "description": "Append the assistant reply and clear processing via one chat-store-cli command envelope",
169
- "expects_data": ["boardSetupRoot", "boardRuntimeDir", "cardId", "replyText"],
229
+ "expects_data": ["boardSetupRoot", "boardRuntimeDir", "cardId", "replyText", "turnId"],
170
230
  "produces_data": ["replyId"],
171
231
  "input_validations": [
172
232
  "$type(boardSetupRoot) = \"string\" and $length(boardSetupRoot) > 0",
@@ -183,7 +243,7 @@
183
243
  "meta": "chat-handler",
184
244
  "argsMassaging": {
185
245
  "cmdTemplate": ["'--stdin'"],
186
- "stdinTemplate": "{ 'storeRef': $fsPathRef(boardSetupRoot & '/' & boardRuntimeDir), 'cardId': cardId, 'commands': [{ 'command': 'append', 'role': 'assistant', 'text': replyText, 'files': [] }, { 'command': 'set-processing', 'active': false }] }"
246
+ "stdinTemplate": "{ 'storeRef': $fsPathRef(boardSetupRoot & '/' & boardRuntimeDir), 'cardId': cardId, 'commands': [{ 'command': 'append', 'role': 'assistant', 'text': replyText, 'files': [], 'turn': turnId }, { 'command': 'set-processing', 'active': false }] }"
187
247
  },
188
248
  "outputTransforms": {
189
249
  "dataTemplate": "{ 'replyId': output.data.results[0].data.id }"
@@ -197,7 +257,7 @@
197
257
  },
198
258
  "cleanup_failure": {
199
259
  "description": "Write a failure system message and clear processing via one chat-store-cli command envelope",
200
- "expects_data": ["boardSetupRoot", "boardRuntimeDir", "cardId"],
260
+ "expects_data": ["boardSetupRoot", "boardRuntimeDir", "cardId", "turnId"],
201
261
  "input_validations": [
202
262
  "$type(boardSetupRoot) = \"string\" and $length(boardSetupRoot) > 0",
203
263
  "$type(cardId) = \"string\" and $length(cardId) > 0"
@@ -212,7 +272,7 @@
212
272
  "meta": "chat-handler",
213
273
  "argsMassaging": {
214
274
  "cmdTemplate": ["'--stdin'"],
215
- "stdinTemplate": "{ 'storeRef': $fsPathRef(boardSetupRoot & '/' & boardRuntimeDir), 'cardId': cardId, 'commands': [{ 'command': 'append', 'role': 'system', 'text': 'AI response failed - the assistant could not generate a reply. Check server configuration and logs.', 'files': [] }, { 'command': 'set-processing', 'active': false }] }"
275
+ "stdinTemplate": "{ 'storeRef': $fsPathRef(boardSetupRoot & '/' & boardRuntimeDir), 'cardId': cardId, 'commands': [{ 'command': 'append', 'role': 'system', 'text': 'AI response failed - the assistant could not generate a reply. Check server configuration and logs.', 'files': [], 'turn': turnId }, { 'command': 'set-processing', 'active': false }] }"
216
276
  }
217
277
  },
218
278
  "transitions": {