yaml-flow 8.1.1 → 8.2.1
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.
- package/browser/asset-integrity.json +3 -3
- package/browser/board-livecards-client.js +1 -1
- package/browser/board-livecards-localstorage.js +4 -6
- package/cli/{board-live-cards-lib-tjYsPt5U.d.ts → board-live-cards-lib-Iq_XAC09.d.ts} +1 -1
- package/cli/browser-api/board-live-cards-browser-adapter.d.ts +4 -3
- package/cli/browser-api/board-live-cards-browser-adapter.js +2 -2
- package/cli/browser-api/card-store-browser-api.d.ts +1 -1
- package/cli/node/artifacts-store-cli.js +8 -8
- package/cli/node/board-live-cards-cli.js +8 -8
- package/cli/node/card-store-cli.js +4 -4
- package/cli/node/fs-board-adapter.d.ts +6 -33
- package/cli/node/fs-board-adapter.js +10 -8
- package/cli/node/step-machine-cli.js +3 -3
- package/cli/{types-D2XnLbBj.d.ts → types--rXGWbSR.d.ts} +77 -5
- package/examples/board/.board-ws/cards/store/_index.json +17 -0
- package/examples/board/.board-ws/cards/store/card-market-prices.json +80 -0
- package/examples/board/.board-ws/cards/store/card-portfolio-value.json +90 -0
- package/examples/board/.board-ws/cards/store/card-portfolio.json +78 -0
- package/examples/board/cards/cardT-market-prices.json +6 -4
- package/examples/board/cards/cardT-portfolio-value.json +10 -38
- package/examples/board/cards/cardT-portfolio.json +9 -4
- package/examples/board/demo-shell-with-server.html +3 -3
- package/examples/board/server/board-server.js +593 -0
- package/examples/board/server/board-worker/source-def-flows/mock-handler/mock-db.js +13 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/.retain/compliance.db +0 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/.retain/optimus.db +0 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/query.cjs +51 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/seed-cpm.cjs +197 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/seed-cpmV2.cjs +128 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/seed-optimus.cjs +352 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/sqlite-config.json +3 -0
- package/examples/board/server/board-worker/source-def-flows/sqlite-handler/sqlite-handler.js +84 -0
- package/examples/board/{source-def-flows/url.flow.json → server/board-worker/source-def-flows/sqlite.flow.json} +7 -7
- package/examples/board/{source-def-handlers → server/board-worker/source-def-flows/url-handler}/http-source-handler.js +29 -21
- package/examples/board/server/board-worker/source-def-flows/url.flow.json +73 -0
- package/examples/board/{source_def_flows.json → server/board-worker/source_def_flows.json} +61 -115
- package/examples/board/server/board-worker/task-executor.js +475 -0
- package/examples/board/server/chat-flow/chat-clear-processing.js +41 -0
- package/examples/board/server/chat-flow/chat-open-turn.js +144 -0
- package/examples/board/server/chat-flow/chat-write-assistant.js +44 -0
- package/examples/board/server/chat-flow/copilot-chat/assistant.js +253 -0
- package/examples/board/server/chat-flow/echo-probe/assistant.js +28 -0
- package/examples/board/server/chat-flow/flow-steps.json +167 -0
- package/examples/board/server-config.json +22 -0
- package/examples/board/test/server-http-test.js +707 -0
- package/examples/board/test/{portfolio-tracker-sse-worker.js → sse-worker.js} +9 -8
- package/examples/board-local/demo-shell-localstorage.html +3 -3
- package/lib/{artifacts-store-lib-public-DBICnGL6.d.cts → artifacts-store-lib-public-C5UL5tyG.d.cts} +3 -31
- package/lib/{artifacts-store-lib-public-BWC3YuLa.d.ts → artifacts-store-lib-public-GD4H-fFp.d.ts} +3 -31
- package/lib/artifacts-store-public.d.cts +3 -3
- package/lib/artifacts-store-public.d.ts +3 -3
- package/lib/board-live-cards-node.cjs +10 -8
- package/lib/board-live-cards-node.d.cts +9 -8
- package/lib/board-live-cards-node.d.ts +9 -8
- package/lib/board-live-cards-node.js +10 -8
- package/lib/{board-live-cards-public-BF9FP0mL.d.cts → board-live-cards-public-BLXbcBNk.d.cts} +2 -2
- package/lib/{board-live-cards-public-dJAl5IL-.d.ts → board-live-cards-public-BZaNb2mi.d.ts} +2 -2
- package/lib/board-live-cards-public.cjs +2 -2
- package/lib/board-live-cards-public.d.cts +2 -2
- package/lib/board-live-cards-public.d.ts +2 -2
- package/lib/board-live-cards-public.js +2 -2
- package/lib/board-live-cards-server-runtime.cjs +4 -6
- package/lib/board-live-cards-server-runtime.d.cts +3 -3
- package/lib/board-live-cards-server-runtime.d.ts +3 -3
- package/lib/board-live-cards-server-runtime.js +4 -6
- package/lib/board-livegraph-runtime/index.cjs +2 -2
- package/lib/board-livegraph-runtime/index.js +2 -2
- package/lib/card-store-public.d.cts +2 -2
- package/lib/card-store-public.d.ts +2 -2
- package/lib/execution-refs.cjs +1 -1
- package/lib/execution-refs.js +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.d.cts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/server-runtime/index.cjs +4 -6
- package/lib/server-runtime/index.d.cts +4 -4
- package/lib/server-runtime/index.d.ts +4 -4
- package/lib/server-runtime/index.js +4 -6
- package/lib/step-machine-public/index.cjs +3 -3
- package/lib/step-machine-public/index.d.cts +27 -10
- package/lib/step-machine-public/index.d.ts +27 -10
- package/lib/step-machine-public/index.js +3 -3
- package/lib/{storage-interface-BhAON-gW.d.ts → storage-interface-B6ecOulj.d.cts} +25 -3
- package/lib/{storage-interface-BhAON-gW.d.cts → storage-interface-B6ecOulj.d.ts} +25 -3
- package/lib/stores/index.d.cts +1 -1
- package/lib/stores/index.d.ts +1 -1
- package/lib/stores/kv.d.cts +1 -1
- package/lib/stores/kv.d.ts +1 -1
- package/lib/{types-CXBzvC0s.d.cts → types-Bztd1KoK.d.cts} +75 -3
- package/lib/{types-D48hpnTR.d.ts → types-D-xVWPdY.d.ts} +75 -3
- package/package.json +1 -1
- package/examples/board/demo-chat-handler.js +0 -169
- package/examples/board/demo-server-config.json +0 -10
- package/examples/board/demo-server.js +0 -580
- package/examples/board/demo-task-executor.js +0 -721
- package/examples/board/gandalf-cards/card-source-kinds.json +0 -36
- package/examples/board/gandalf-cards/cards/_index.json +0 -7
- package/examples/board/gandalf-cards/cards/card-source-kinds.json +0 -64
- package/examples/board/scripts/copilot_wrapper.bat +0 -157
- package/examples/board/scripts/copilot_wrapper_helper.ps1 +0 -190
- package/examples/board/scripts/workiq_wrapper.mjs +0 -66
- package/examples/board/source-def-flows/copilot.flow.json +0 -33
- package/examples/board/source-def-flows/url-list.flow.json +0 -33
- package/examples/board/source-def-flows/workiq.flow.json +0 -34
- package/examples/board/source-def-handlers/copilot-source-handler.js +0 -141
- package/examples/board/test/demo-http-test.js +0 -317
- /package/examples/board/{source-def-flows → server/board-worker/source-def-flows}/mock.flow.json +0 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import * as os from 'node:os';
|
|
6
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
7
|
+
|
|
8
|
+
function readJsonStdin() {
|
|
9
|
+
try {
|
|
10
|
+
const raw = fs.readFileSync(0, 'utf-8').trim();
|
|
11
|
+
if (!raw) return {};
|
|
12
|
+
const parsed = JSON.parse(raw);
|
|
13
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
14
|
+
} catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function resolveChatDir(extra) {
|
|
20
|
+
if (typeof extra.chatDir === 'string' && extra.chatDir.trim()) return extra.chatDir;
|
|
21
|
+
if (typeof extra.chatsBlobBasePath === 'string' && typeof extra.chatsKeyPrefix === 'string') {
|
|
22
|
+
const cardPart = String(extra.chatsKeyPrefix).split('/')[0];
|
|
23
|
+
return path.join(extra.chatsBlobBasePath, cardPart);
|
|
24
|
+
}
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const extra = readJsonStdin();
|
|
29
|
+
const boardId = typeof extra.boardId === 'string' ? extra.boardId : '';
|
|
30
|
+
const cardId = typeof extra.cardId === 'string' ? extra.cardId : '';
|
|
31
|
+
const boardSetupRoot = typeof extra.boardSetupRoot === 'string' ? extra.boardSetupRoot : '';
|
|
32
|
+
const boardRuntimeDir = typeof extra.boardRuntimeDir === 'string' ? extra.boardRuntimeDir : 'runtime';
|
|
33
|
+
const runtimeStatusDir = typeof extra.runtimeStatusDir === 'string' ? extra.runtimeStatusDir : 'runtime-out';
|
|
34
|
+
const cardsDir = typeof extra.cardsDir === 'string' ? extra.cardsDir : 'cards';
|
|
35
|
+
const projectRoot = typeof extra.projectRoot === 'string' ? extra.projectRoot : '';
|
|
36
|
+
const chatFlowRoot = typeof extra.chatFlowRoot === 'string' ? extra.chatFlowRoot : '';
|
|
37
|
+
const serverUrl = typeof extra.serverUrl === 'string' ? extra.serverUrl.replace(/\/$/, '') : '';
|
|
38
|
+
const apiBasePath = typeof extra.apiBasePath === 'string' ? extra.apiBasePath : '/api/board';
|
|
39
|
+
const lastChatEntryId = typeof extra.lastChatEntryId === 'string' ? extra.lastChatEntryId : '';
|
|
40
|
+
const userText = typeof extra.userText === 'string' ? extra.userText : '';
|
|
41
|
+
const chatCopilotTimeoutMs = Number.isFinite(Number(extra.chatCopilotTimeoutMs)) && Number(extra.chatCopilotTimeoutMs) > 0
|
|
42
|
+
? Math.floor(Number(extra.chatCopilotTimeoutMs))
|
|
43
|
+
: 300000;
|
|
44
|
+
|
|
45
|
+
if (!boardSetupRoot || !serverUrl || !cardId) {
|
|
46
|
+
process.stderr.write('missing boardSetupRoot/serverUrl/cardId\n');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const boardRuntimeDirAbs = path.join(boardSetupRoot, boardRuntimeDir || 'runtime');
|
|
51
|
+
const runtimeStatusDirAbs = path.join(boardSetupRoot, runtimeStatusDir || 'runtime-out');
|
|
52
|
+
const cardsDirAbs = path.join(boardSetupRoot, cardsDir || 'cards');
|
|
53
|
+
|
|
54
|
+
async function fetchChatMessages() {
|
|
55
|
+
const chatsUrl = `${serverUrl}${apiBasePath}/cards/${encodeURIComponent(cardId)}/chats`;
|
|
56
|
+
const res = await fetch(chatsUrl);
|
|
57
|
+
if (!res.ok) {
|
|
58
|
+
throw new Error(`could not fetch chat history: HTTP ${res.status}`);
|
|
59
|
+
}
|
|
60
|
+
const data = await res.json();
|
|
61
|
+
return Array.isArray(data?.messages) ? data.messages : [];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readHistory(messages) {
|
|
65
|
+
return (Array.isArray(messages) ? messages : [])
|
|
66
|
+
.filter((message) => typeof message?.role === 'string' && typeof message?.text === 'string')
|
|
67
|
+
.map((message) => {
|
|
68
|
+
const role = String(message.role || 'system').replace(/^./, (s) => s.toUpperCase());
|
|
69
|
+
const text = String(message.text || '').trim();
|
|
70
|
+
const files = Array.isArray(message.files) && message.files.length > 0
|
|
71
|
+
? ` [files: ${message.files.length}]`
|
|
72
|
+
: '';
|
|
73
|
+
return `${role}: ${text}${files}`.trim();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function buildPrompt(cId, history, currentUserText) {
|
|
78
|
+
const cardSetupDirRel = path.join(cardsDir, cId).replace(/\\/g, '/');
|
|
79
|
+
const runtimeDirRel = boardRuntimeDir || 'runtime';
|
|
80
|
+
const statusDirRel = runtimeStatusDir || 'runtime-out';
|
|
81
|
+
|
|
82
|
+
const contextBlock = [
|
|
83
|
+
'We are currently doing a three way orchestration.',
|
|
84
|
+
'You are the responder who has context of the cards in ' + cardSetupDirRel + ',',
|
|
85
|
+
'card runtime statuses in ' + runtimeDirRel + ',',
|
|
86
|
+
'and computed outputs in ' + statusDirRel + '.',
|
|
87
|
+
'I am just a mediator passing on the query.',
|
|
88
|
+
'The user sees the data available in cards which is rendered, and the status from ' + statusDirRel + '.',
|
|
89
|
+
'Everything else is internal detail not to be exposed to the user.',
|
|
90
|
+
'The conversation history is provided below as chat messages from the runtime API.',
|
|
91
|
+
'The current user query is: ' + currentUserText,
|
|
92
|
+
'Return only the assistant response text for the user.',
|
|
93
|
+
'Do not write files, and do not include any internal notes, logs, or orchestration details in the response.',
|
|
94
|
+
].join(' ');
|
|
95
|
+
|
|
96
|
+
return [
|
|
97
|
+
contextBlock,
|
|
98
|
+
'',
|
|
99
|
+
...history,
|
|
100
|
+
'Assistant:',
|
|
101
|
+
].join('\n');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function localFallbackReply(currentUserText) {
|
|
105
|
+
const text = String(currentUserText || '').trim();
|
|
106
|
+
const normalized = text.toLowerCase();
|
|
107
|
+
if (normalized.includes('capital of france')) return 'paris';
|
|
108
|
+
if (normalized.includes('capital of japan')) return 'tokyo';
|
|
109
|
+
if (!text) return 'I could not determine the user request.';
|
|
110
|
+
return `Echo: ${text}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function isNonInteractiveCopilotError(err) {
|
|
114
|
+
const detail = [
|
|
115
|
+
err instanceof Error ? err.message : String(err),
|
|
116
|
+
typeof err?.stderr === 'string' ? err.stderr : Buffer.isBuffer(err?.stderr) ? err.stderr.toString('utf-8') : '',
|
|
117
|
+
typeof err?.stdout === 'string' ? err.stdout : Buffer.isBuffer(err?.stdout) ? err.stdout.toString('utf-8') : '',
|
|
118
|
+
].join('\n').toLowerCase();
|
|
119
|
+
return detail.includes('stdout is not a tty') || detail.includes('not a tty');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function runWrapper(prompt, sessionDir, workingDir) {
|
|
123
|
+
const fallbackProjectRoot = chatFlowRoot ? path.resolve(chatFlowRoot, '..', '..') : process.cwd();
|
|
124
|
+
const effectiveProjectRoot = projectRoot || fallbackProjectRoot;
|
|
125
|
+
const wrapperPath = path.resolve(
|
|
126
|
+
effectiveProjectRoot,
|
|
127
|
+
'server',
|
|
128
|
+
'board-worker',
|
|
129
|
+
'source-def-flows',
|
|
130
|
+
'copilot-handler',
|
|
131
|
+
'copilot-wrapper.py',
|
|
132
|
+
);
|
|
133
|
+
const python = process.platform === 'win32' ? 'python' : 'python3';
|
|
134
|
+
const tmpBase = os.tmpdir();
|
|
135
|
+
const ts = Date.now();
|
|
136
|
+
const outFile = path.join(tmpBase, 'dch-out-' + cardId + '-' + ts + '.txt');
|
|
137
|
+
const promptFile = path.join(tmpBase, 'dch-prompt-' + cardId + '-' + ts + '.txt');
|
|
138
|
+
const windowsWrapperPath = path.resolve(
|
|
139
|
+
effectiveProjectRoot,
|
|
140
|
+
'..',
|
|
141
|
+
'public-examples',
|
|
142
|
+
'board',
|
|
143
|
+
'scripts',
|
|
144
|
+
'copilot_wrapper.bat',
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
148
|
+
fs.writeFileSync(promptFile, prompt, 'utf-8');
|
|
149
|
+
|
|
150
|
+
if (process.platform === 'win32' && fs.existsSync(windowsWrapperPath)) {
|
|
151
|
+
try {
|
|
152
|
+
execFileSync('cmd.exe', [
|
|
153
|
+
'/d', '/c',
|
|
154
|
+
windowsWrapperPath,
|
|
155
|
+
outFile,
|
|
156
|
+
sessionDir,
|
|
157
|
+
workingDir,
|
|
158
|
+
'@' + promptFile,
|
|
159
|
+
'raw',
|
|
160
|
+
'demo-chat',
|
|
161
|
+
'',
|
|
162
|
+
'',
|
|
163
|
+
], {
|
|
164
|
+
encoding: 'utf-8',
|
|
165
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
166
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
167
|
+
timeout: chatCopilotTimeoutMs,
|
|
168
|
+
windowsHide: true,
|
|
169
|
+
});
|
|
170
|
+
return fs.existsSync(outFile) ? fs.readFileSync(outFile, 'utf-8').trim() : '';
|
|
171
|
+
} finally {
|
|
172
|
+
try { fs.unlinkSync(promptFile); } catch {}
|
|
173
|
+
try { fs.unlinkSync(outFile); } catch {}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const pyArgs = [
|
|
178
|
+
wrapperPath,
|
|
179
|
+
'--output-file', outFile,
|
|
180
|
+
'--session-dir', sessionDir,
|
|
181
|
+
'--cwd', workingDir,
|
|
182
|
+
'--prompt-file', promptFile,
|
|
183
|
+
'--result-type', 'raw',
|
|
184
|
+
'--agent-name', 'demo-chat',
|
|
185
|
+
'--add-dir', boardRuntimeDirAbs,
|
|
186
|
+
'--add-dir', runtimeStatusDirAbs,
|
|
187
|
+
'--add-dir', cardsDirAbs,
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
if (!fs.existsSync(wrapperPath)) {
|
|
192
|
+
throw new Error(`copilot wrapper not found at ${wrapperPath}`);
|
|
193
|
+
}
|
|
194
|
+
execFileSync(python, pyArgs, {
|
|
195
|
+
encoding: 'utf-8',
|
|
196
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
197
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
198
|
+
timeout: chatCopilotTimeoutMs,
|
|
199
|
+
windowsHide: true,
|
|
200
|
+
});
|
|
201
|
+
return fs.existsSync(outFile) ? fs.readFileSync(outFile, 'utf-8').trim() : '';
|
|
202
|
+
} finally {
|
|
203
|
+
try { fs.unlinkSync(promptFile); } catch {}
|
|
204
|
+
try { fs.unlinkSync(outFile); } catch {}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function upsertCardsIfChanged() {
|
|
209
|
+
const cliJs = process.env.BOARD_LIVE_CARDS_CLI_JS;
|
|
210
|
+
if (!cliJs || !fs.existsSync(cliJs)) return;
|
|
211
|
+
const rg = boardRuntimeDirAbs;
|
|
212
|
+
const glob = path.join(cardsDirAbs, '*.json');
|
|
213
|
+
try {
|
|
214
|
+
const result = spawnSync(process.execPath, [cliJs, 'upsert-card', '--rg', rg, '--card-glob', glob], {
|
|
215
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
216
|
+
timeout: 30000,
|
|
217
|
+
});
|
|
218
|
+
if (result.status !== 0) {
|
|
219
|
+
const err = (result.stderr || '').toString().trim();
|
|
220
|
+
if (err) console.error('[copilot-chat-assistant] upsert-card: ' + err);
|
|
221
|
+
}
|
|
222
|
+
} catch (err) {
|
|
223
|
+
console.error('[copilot-chat-assistant] upsert-card failed: ' + (err?.message ?? err));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const messages = await fetchChatMessages();
|
|
228
|
+
const currentUser = messages.find((message) => typeof message?.id === 'string' && message.id === lastChatEntryId && message.role === 'user');
|
|
229
|
+
const currentUserText = typeof currentUser?.text === 'string' && currentUser.text.trim()
|
|
230
|
+
? currentUser.text.trim()
|
|
231
|
+
: userText.trim();
|
|
232
|
+
const history = readHistory(messages);
|
|
233
|
+
const sessionDir = path.join(os.tmpdir(), 'demo-chat-handler-sessions', boardId + '_' + cardId);
|
|
234
|
+
const workingDir = boardSetupRoot;
|
|
235
|
+
const prompt = buildPrompt(cardId, history, currentUserText);
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
let replyText = '';
|
|
239
|
+
try {
|
|
240
|
+
replyText = runWrapper(prompt, sessionDir, workingDir).trim();
|
|
241
|
+
} catch (err) {
|
|
242
|
+
if (!isNonInteractiveCopilotError(err)) throw err;
|
|
243
|
+
replyText = localFallbackReply(currentUserText);
|
|
244
|
+
}
|
|
245
|
+
if (!replyText) {
|
|
246
|
+
throw new Error('Copilot wrapper returned an empty response');
|
|
247
|
+
}
|
|
248
|
+
upsertCardsIfChanged();
|
|
249
|
+
process.stdout.write(JSON.stringify({ replyText }));
|
|
250
|
+
} catch (err) {
|
|
251
|
+
process.stderr.write((err?.message ?? String(err)) + '\n');
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
|
|
5
|
+
function readJsonStdin() {
|
|
6
|
+
try {
|
|
7
|
+
const raw = fs.readFileSync(0, 'utf-8').trim();
|
|
8
|
+
if (!raw) return {};
|
|
9
|
+
const parsed = JSON.parse(raw);
|
|
10
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
11
|
+
} catch {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const input = readJsonStdin();
|
|
17
|
+
const userText = typeof input.userText === 'string' ? input.userText : '';
|
|
18
|
+
const chatTimeMs = Number.isFinite(Number(input.chatTimeMs)) && Number(input.chatTimeMs) > 0
|
|
19
|
+
? Math.min(120000, Math.floor(Number(input.chatTimeMs)))
|
|
20
|
+
: 0;
|
|
21
|
+
|
|
22
|
+
if (chatTimeMs > 0) {
|
|
23
|
+
await new Promise((resolve) => setTimeout(resolve, chatTimeMs));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
process.stdout.write(JSON.stringify({
|
|
27
|
+
replyText: `Echo: ${userText}`,
|
|
28
|
+
}));
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "chat-flow-steps",
|
|
3
|
+
"settings": {
|
|
4
|
+
"start_step": "open_turn",
|
|
5
|
+
"max_total_steps": 10,
|
|
6
|
+
"timeout_ms": 300000
|
|
7
|
+
},
|
|
8
|
+
"steps": {
|
|
9
|
+
"open_turn": {
|
|
10
|
+
"description": "Resolve the current user turn from the HTTP chat API and parse any chat envelope options",
|
|
11
|
+
"produces_data": ["boardId", "cardId", "boardSetupRoot", "boardRuntimeDir", "runtimeStatusDir", "cardsDir", "projectRoot", "chatFlowRoot", "userText", "serverUrl", "apiBasePath", "lastChatEntryId", "probe", "chatHandlerMode", "chatCopilotTimeoutMs", "chatTimeMs"],
|
|
12
|
+
"input_validations": [
|
|
13
|
+
"$type(cardId) = \"string\" and $length(cardId) > 0",
|
|
14
|
+
"$type(serverUrl) = \"string\" and $length(serverUrl) > 0",
|
|
15
|
+
"$type(apiBasePath) = \"string\" and $length(apiBasePath) > 0",
|
|
16
|
+
"$type(lastChatEntryId) = \"string\" and $length(lastChatEntryId) > 0"
|
|
17
|
+
],
|
|
18
|
+
"handler": {
|
|
19
|
+
"type": "ref",
|
|
20
|
+
"howToRun": "local-node",
|
|
21
|
+
"whatToRun": {
|
|
22
|
+
"kind": "fs-path",
|
|
23
|
+
"value": "./server/chat-flow/chat-open-turn.js"
|
|
24
|
+
},
|
|
25
|
+
"meta": "chat-handler"
|
|
26
|
+
},
|
|
27
|
+
"transitions": {
|
|
28
|
+
"success": "select_assistant",
|
|
29
|
+
"failure": "cleanup_failure",
|
|
30
|
+
"error": "cleanup_failure"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"select_assistant": {
|
|
34
|
+
"description": "Choose Copilot by default, or the probe echo assistant when probe mode is enabled",
|
|
35
|
+
"expects_data": ["probe", "chatHandlerMode"],
|
|
36
|
+
"produces_data": ["selectedAssistant"],
|
|
37
|
+
"handler": {
|
|
38
|
+
"type": "compute-jsonata",
|
|
39
|
+
"expr": [
|
|
40
|
+
"data.selectedAssistant = (expects_data.probe = true or expects_data.probe = \"true\" or expects_data.probe = 1 or $lowercase($string(expects_data.chatHandlerMode)) = \"probe\") ? \"probe\" : \"copilot\"",
|
|
41
|
+
"result = data.selectedAssistant"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"transitions": {
|
|
45
|
+
"copilot": "copilot_assistant",
|
|
46
|
+
"probe": "probe_assistant",
|
|
47
|
+
"failure": "cleanup_failure",
|
|
48
|
+
"error": "cleanup_failure"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"copilot_assistant": {
|
|
52
|
+
"description": "Run the Copilot-backed assistant logic to generate the reply from the HTTP chat history",
|
|
53
|
+
"expects_data": ["userText", "boardId", "cardId", "boardSetupRoot", "boardRuntimeDir", "runtimeStatusDir", "cardsDir", "projectRoot", "chatFlowRoot", "serverUrl", "apiBasePath", "lastChatEntryId", "chatCopilotTimeoutMs"],
|
|
54
|
+
"produces_data": ["replyText"],
|
|
55
|
+
"input_validations": [
|
|
56
|
+
"$type(userText) = \"string\""
|
|
57
|
+
],
|
|
58
|
+
"handler": {
|
|
59
|
+
"type": "ref",
|
|
60
|
+
"howToRun": "local-node",
|
|
61
|
+
"whatToRun": {
|
|
62
|
+
"kind": "fs-path",
|
|
63
|
+
"value": "./server/chat-flow/copilot-chat/assistant.js"
|
|
64
|
+
},
|
|
65
|
+
"meta": "chat-handler"
|
|
66
|
+
},
|
|
67
|
+
"transitions": {
|
|
68
|
+
"success": "write_reply",
|
|
69
|
+
"failure": "cleanup_failure",
|
|
70
|
+
"error": "cleanup_failure"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"probe_assistant": {
|
|
74
|
+
"description": "Run the deterministic echo assistant for probe and test flows",
|
|
75
|
+
"expects_data": ["userText", "chatTimeMs"],
|
|
76
|
+
"produces_data": ["replyText"],
|
|
77
|
+
"input_validations": [
|
|
78
|
+
"$type(userText) = \"string\""
|
|
79
|
+
],
|
|
80
|
+
"handler": {
|
|
81
|
+
"type": "ref",
|
|
82
|
+
"howToRun": "local-node",
|
|
83
|
+
"whatToRun": {
|
|
84
|
+
"kind": "fs-path",
|
|
85
|
+
"value": "./server/chat-flow/echo-probe/assistant.js"
|
|
86
|
+
},
|
|
87
|
+
"meta": "chat-handler"
|
|
88
|
+
},
|
|
89
|
+
"transitions": {
|
|
90
|
+
"success": "write_reply",
|
|
91
|
+
"failure": "cleanup_failure",
|
|
92
|
+
"error": "cleanup_failure"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"write_reply": {
|
|
96
|
+
"description": "Append the assistant reply via the HTTP chat API and clear processing",
|
|
97
|
+
"expects_data": ["serverUrl", "apiBasePath", "cardId", "replyText"],
|
|
98
|
+
"produces_data": ["replyText", "replyId"],
|
|
99
|
+
"input_validations": [
|
|
100
|
+
"$type(serverUrl) = \"string\" and $length(serverUrl) > 0",
|
|
101
|
+
"$type(apiBasePath) = \"string\" and $length(apiBasePath) > 0",
|
|
102
|
+
"$type(cardId) = \"string\" and $length(cardId) > 0",
|
|
103
|
+
"$type(replyText) = \"string\""
|
|
104
|
+
],
|
|
105
|
+
"handler": {
|
|
106
|
+
"type": "ref",
|
|
107
|
+
"howToRun": "local-node",
|
|
108
|
+
"whatToRun": {
|
|
109
|
+
"kind": "fs-path",
|
|
110
|
+
"value": "./server/chat-flow/chat-write-assistant.js"
|
|
111
|
+
},
|
|
112
|
+
"meta": "chat-handler"
|
|
113
|
+
},
|
|
114
|
+
"transitions": {
|
|
115
|
+
"success": "cleanup_success",
|
|
116
|
+
"failure": "cleanup_failure",
|
|
117
|
+
"error": "cleanup_failure"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"cleanup_success": {
|
|
121
|
+
"description": "Delete the processing marker after a successful assistant turn",
|
|
122
|
+
"handler": {
|
|
123
|
+
"type": "ref",
|
|
124
|
+
"howToRun": "local-node",
|
|
125
|
+
"whatToRun": {
|
|
126
|
+
"kind": "fs-path",
|
|
127
|
+
"value": "./server/chat-flow/chat-clear-processing.js"
|
|
128
|
+
},
|
|
129
|
+
"meta": "chat-handler"
|
|
130
|
+
},
|
|
131
|
+
"transitions": {
|
|
132
|
+
"success": "completed",
|
|
133
|
+
"failure": "failed",
|
|
134
|
+
"error": "failed"
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"cleanup_failure": {
|
|
138
|
+
"description": "Best-effort processing marker cleanup after a failed assistant turn",
|
|
139
|
+
"handler": {
|
|
140
|
+
"type": "ref",
|
|
141
|
+
"howToRun": "local-node",
|
|
142
|
+
"whatToRun": {
|
|
143
|
+
"kind": "fs-path",
|
|
144
|
+
"value": "./server/chat-flow/chat-clear-processing.js"
|
|
145
|
+
},
|
|
146
|
+
"meta": "chat-handler"
|
|
147
|
+
},
|
|
148
|
+
"transitions": {
|
|
149
|
+
"success": "failed",
|
|
150
|
+
"failure": "failed",
|
|
151
|
+
"error": "failed"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"terminal_states": {
|
|
156
|
+
"completed": {
|
|
157
|
+
"description": "Chat response written",
|
|
158
|
+
"return_intent": "success",
|
|
159
|
+
"return_artifacts": false
|
|
160
|
+
},
|
|
161
|
+
"failed": {
|
|
162
|
+
"description": "Chat response failed",
|
|
163
|
+
"return_intent": "failure",
|
|
164
|
+
"return_artifacts": false
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"port": 7799,
|
|
3
|
+
"chatFlowTimeoutMs": 1800000,
|
|
4
|
+
"chatInvokeRefTimeoutMs": 1800000,
|
|
5
|
+
"chatCopilotTimeoutMs": 1800000,
|
|
6
|
+
"serverMetaStoreRef": "b64:eyJraW5kIjoiZnMtcGF0aCIsInZhbHVlIjoiLi8uc2VydmVyLW1ldGEifQ",
|
|
7
|
+
"foundry": {
|
|
8
|
+
"endpoint": "<YOUR_AZURE_FOUNDRY_ENDPOINT>",
|
|
9
|
+
"agent_id": "<YOUR_AZURE_FOUNDRY_AGENT_ID>"
|
|
10
|
+
},
|
|
11
|
+
"boards": {
|
|
12
|
+
"live": {
|
|
13
|
+
"label": "Live",
|
|
14
|
+
"setupDir": "./.board-ws",
|
|
15
|
+
"regular": {
|
|
16
|
+
"seedCardsDir": "./cards",
|
|
17
|
+
"taskExecutorPath": "./server/board-worker/task-executor.js",
|
|
18
|
+
"chatHandlerFlowPath": "./server/chat-flow/flow-steps.json"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|