@vscxml/mcp 0.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.
- package/README.md +252 -0
- package/dist/bin/scxml-mcp.d.ts +2 -0
- package/dist/bin/scxml-mcp.js +51 -0
- package/dist/bin/scxml-mcp.js.map +1 -0
- package/dist/bridges/editor-bridge.d.ts +135 -0
- package/dist/bridges/editor-bridge.js +285 -0
- package/dist/bridges/editor-bridge.js.map +1 -0
- package/dist/bridges/generator-bridge.d.ts +72 -0
- package/dist/bridges/generator-bridge.js +190 -0
- package/dist/bridges/generator-bridge.js.map +1 -0
- package/dist/bridges/simulator-bridge.d.ts +89 -0
- package/dist/bridges/simulator-bridge.js +451 -0
- package/dist/bridges/simulator-bridge.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/process-manager.d.ts +42 -0
- package/dist/process-manager.js +211 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +721 -0
- package/dist/server.js.map +1 -0
- package/dist/trace-buffer.d.ts +22 -0
- package/dist/trace-buffer.js +36 -0
- package/dist/trace-buffer.js.map +1 -0
- package/dist/types.d.ts +143 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
- package/server.json +78 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket bridge to the VSCXML-Editor API.
|
|
4
|
+
* The editor's Electron main process runs a lightweight WS server on port 48623
|
|
5
|
+
* that relays commands to/from the React renderer via IPC.
|
|
6
|
+
*/
|
|
7
|
+
export class EditorBridge {
|
|
8
|
+
ws = null;
|
|
9
|
+
url;
|
|
10
|
+
connected = false;
|
|
11
|
+
requestId = 0;
|
|
12
|
+
pendingRequests = new Map();
|
|
13
|
+
// Broadcast event buffers (selection/document changes from editor)
|
|
14
|
+
lastSelection = null;
|
|
15
|
+
lastDocumentChange = null;
|
|
16
|
+
constructor(url) {
|
|
17
|
+
this.url = url || `ws://localhost:${48623}`;
|
|
18
|
+
}
|
|
19
|
+
setUrl(url) {
|
|
20
|
+
this.url = url;
|
|
21
|
+
}
|
|
22
|
+
isConnected() {
|
|
23
|
+
return this.connected;
|
|
24
|
+
}
|
|
25
|
+
/** Connect to the editor WebSocket API */
|
|
26
|
+
async connect() {
|
|
27
|
+
if (this.connected)
|
|
28
|
+
return;
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
try {
|
|
31
|
+
this.ws = new WebSocket(this.url);
|
|
32
|
+
const timeout = setTimeout(() => {
|
|
33
|
+
reject(new Error(`Connection timeout to editor at ${this.url}`));
|
|
34
|
+
this.ws?.close();
|
|
35
|
+
}, 3000);
|
|
36
|
+
this.ws.on('open', () => {
|
|
37
|
+
clearTimeout(timeout);
|
|
38
|
+
this.connected = true;
|
|
39
|
+
resolve();
|
|
40
|
+
});
|
|
41
|
+
this.ws.on('message', (data) => {
|
|
42
|
+
this.handleMessage(data.toString());
|
|
43
|
+
});
|
|
44
|
+
this.ws.on('close', () => {
|
|
45
|
+
this.connected = false;
|
|
46
|
+
this.ws = null;
|
|
47
|
+
for (const [, req] of this.pendingRequests) {
|
|
48
|
+
clearTimeout(req.timer);
|
|
49
|
+
req.reject(new Error('Connection closed'));
|
|
50
|
+
}
|
|
51
|
+
this.pendingRequests.clear();
|
|
52
|
+
});
|
|
53
|
+
this.ws.on('error', (err) => {
|
|
54
|
+
clearTimeout(timeout);
|
|
55
|
+
if (!this.connected) {
|
|
56
|
+
reject(err);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
reject(err);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/** Disconnect */
|
|
66
|
+
disconnect() {
|
|
67
|
+
if (this.ws) {
|
|
68
|
+
this.ws.close();
|
|
69
|
+
this.ws = null;
|
|
70
|
+
}
|
|
71
|
+
this.connected = false;
|
|
72
|
+
}
|
|
73
|
+
/** Check if editor is reachable */
|
|
74
|
+
async isAvailable() {
|
|
75
|
+
if (this.connected)
|
|
76
|
+
return true;
|
|
77
|
+
try {
|
|
78
|
+
await this.connect();
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Push SCXML content to the editor */
|
|
86
|
+
async pushScxml(scxml) {
|
|
87
|
+
const resp = await this.sendRequest('push_scxml', { scxml });
|
|
88
|
+
return { success: resp.type !== 'error' };
|
|
89
|
+
}
|
|
90
|
+
/** Get current SCXML from the editor */
|
|
91
|
+
async getScxml() {
|
|
92
|
+
const resp = await this.sendRequest('get_scxml');
|
|
93
|
+
return {
|
|
94
|
+
scxml: resp.scxml || '',
|
|
95
|
+
modified: resp.modified || false,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** Show a toast notification in the editor */
|
|
99
|
+
async showNotification(message, severity = 'info', duration = 5000) {
|
|
100
|
+
await this.sendRequest('notify', { message, severity, duration });
|
|
101
|
+
}
|
|
102
|
+
/** Highlight specific states in the editor */
|
|
103
|
+
async highlight(states, options) {
|
|
104
|
+
await this.sendRequest('highlight', {
|
|
105
|
+
states,
|
|
106
|
+
color: options?.color,
|
|
107
|
+
duration: options?.duration,
|
|
108
|
+
clear: options?.clear,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/** Add a note to the editor canvas */
|
|
112
|
+
async addNote(content, options) {
|
|
113
|
+
const resp = await this.sendRequest('add_note', {
|
|
114
|
+
content,
|
|
115
|
+
attachedTo: options?.attachedTo,
|
|
116
|
+
color: options?.color,
|
|
117
|
+
visibleWhen: options?.visibleWhen,
|
|
118
|
+
});
|
|
119
|
+
return { noteId: resp.noteId || '' };
|
|
120
|
+
}
|
|
121
|
+
/** Remove notes from the editor */
|
|
122
|
+
async removeNotes(noteIds) {
|
|
123
|
+
await this.sendRequest('remove_notes', { noteIds });
|
|
124
|
+
}
|
|
125
|
+
/** Navigate the editor canvas */
|
|
126
|
+
async navigate(options) {
|
|
127
|
+
await this.sendRequest('navigate', options);
|
|
128
|
+
}
|
|
129
|
+
/** Save content to a file path */
|
|
130
|
+
async saveFile(filePath, content) {
|
|
131
|
+
const resp = await this.sendRequest('save_file', { filePath, content });
|
|
132
|
+
return { success: resp.type !== 'error', filePath: resp.filePath || filePath };
|
|
133
|
+
}
|
|
134
|
+
/** Load a file from disk into the editor */
|
|
135
|
+
async loadFile(filePath) {
|
|
136
|
+
const resp = await this.sendRequest('load_file', { filePath });
|
|
137
|
+
return {
|
|
138
|
+
content: resp.content || '',
|
|
139
|
+
filePath: resp.filePath || filePath,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/** Get the current file path from the editor */
|
|
143
|
+
async getFilePath() {
|
|
144
|
+
const resp = await this.sendRequest('get_file_path');
|
|
145
|
+
return { filePath: resp.filePath || null };
|
|
146
|
+
}
|
|
147
|
+
/** Capture a screenshot of the editor window */
|
|
148
|
+
async screenshot() {
|
|
149
|
+
const resp = await this.sendRequest('screenshot', {}, 10000);
|
|
150
|
+
return {
|
|
151
|
+
data: resp.data || '',
|
|
152
|
+
format: resp.format || 'png',
|
|
153
|
+
width: resp.width || 0,
|
|
154
|
+
height: resp.height || 0,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/** Connect the editor's simulator panel to the simulator backend */
|
|
158
|
+
async connectSimulator(port) {
|
|
159
|
+
const resp = await this.sendRequest('connect_simulator', { port: port || 48621 });
|
|
160
|
+
return { success: resp.type !== 'error' };
|
|
161
|
+
}
|
|
162
|
+
/** Get the current selection in the editor */
|
|
163
|
+
async getSelection() {
|
|
164
|
+
const resp = await this.sendRequest('get_selection');
|
|
165
|
+
return {
|
|
166
|
+
highlightedStates: resp.highlightedStates || [],
|
|
167
|
+
cursorPosition: resp.cursorPosition,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/** Get the editor viewport state */
|
|
171
|
+
async getViewport() {
|
|
172
|
+
const resp = await this.sendRequest('get_viewport');
|
|
173
|
+
return {
|
|
174
|
+
transform: resp.transform || { x: 0, y: 0, scale: 1 },
|
|
175
|
+
viewportWidth: resp.viewportWidth || 0,
|
|
176
|
+
viewportHeight: resp.viewportHeight || 0,
|
|
177
|
+
visibleArea: resp.visibleArea || { left: 0, top: 0, right: 0, bottom: 0 },
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** Export the full diagram as SVG text */
|
|
181
|
+
async exportSvg() {
|
|
182
|
+
const resp = await this.sendRequest('export_svg', {}, 15000);
|
|
183
|
+
return { svg: resp.svg || '' };
|
|
184
|
+
}
|
|
185
|
+
/** Export the full diagram as PNG (base64) */
|
|
186
|
+
async exportPng() {
|
|
187
|
+
const resp = await this.sendRequest('export_png', {}, 15000);
|
|
188
|
+
return {
|
|
189
|
+
data: resp.data || '',
|
|
190
|
+
width: resp.width || 0,
|
|
191
|
+
height: resp.height || 0,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/** Export interactive Player HTML */
|
|
195
|
+
async exportPlayerHtml(options) {
|
|
196
|
+
const resp = await this.sendRequest('export_player_html', {
|
|
197
|
+
exportMode: options?.exportMode,
|
|
198
|
+
selectedTraceIds: options?.selectedTraceIds,
|
|
199
|
+
}, 30000);
|
|
200
|
+
return { html: resp.html || '' };
|
|
201
|
+
}
|
|
202
|
+
/** Get editor status */
|
|
203
|
+
async getStatus() {
|
|
204
|
+
if (!this.connected) {
|
|
205
|
+
return { connected: false, hasDocument: false, documentName: null };
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
const resp = await this.sendRequest('status');
|
|
209
|
+
return {
|
|
210
|
+
connected: true,
|
|
211
|
+
hasDocument: resp.hasDocument || false,
|
|
212
|
+
documentName: resp.documentName || null,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return { connected: false, hasDocument: false, documentName: null };
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
handleMessage(data) {
|
|
220
|
+
let msg;
|
|
221
|
+
try {
|
|
222
|
+
msg = JSON.parse(data);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Process request-response matches
|
|
228
|
+
const requestId = msg.requestId;
|
|
229
|
+
if (requestId && this.pendingRequests.has(requestId)) {
|
|
230
|
+
const pending = this.pendingRequests.get(requestId);
|
|
231
|
+
this.pendingRequests.delete(requestId);
|
|
232
|
+
clearTimeout(pending.timer);
|
|
233
|
+
if (msg.type === 'error') {
|
|
234
|
+
pending.reject(new Error(msg.message || 'Editor error'));
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
pending.resolve(msg);
|
|
238
|
+
}
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
// Buffer broadcast events (no requestId — editor push notifications)
|
|
242
|
+
const type = msg.type;
|
|
243
|
+
switch (type) {
|
|
244
|
+
case 'selection_changed':
|
|
245
|
+
this.lastSelection = {
|
|
246
|
+
selectedStates: msg.selectedStates || [],
|
|
247
|
+
selectedTransitions: msg.selectedTransitions || [],
|
|
248
|
+
timestamp: msg.timestamp || Date.now(),
|
|
249
|
+
};
|
|
250
|
+
break;
|
|
251
|
+
case 'document_changed':
|
|
252
|
+
this.lastDocumentChange = {
|
|
253
|
+
stateCount: msg.stateCount || 0,
|
|
254
|
+
transitionCount: msg.transitionCount || 0,
|
|
255
|
+
timestamp: msg.timestamp || Date.now(),
|
|
256
|
+
};
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/** Get the latest buffered selection event */
|
|
261
|
+
getLastSelection() {
|
|
262
|
+
return this.lastSelection;
|
|
263
|
+
}
|
|
264
|
+
/** Get the latest buffered document change event */
|
|
265
|
+
getLastDocumentChange() {
|
|
266
|
+
return this.lastDocumentChange;
|
|
267
|
+
}
|
|
268
|
+
sendRequest(action, params = {}, timeoutMs = 5000) {
|
|
269
|
+
return new Promise((resolve, reject) => {
|
|
270
|
+
if (!this.ws || !this.connected) {
|
|
271
|
+
reject(new Error('Not connected to editor'));
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const reqId = `req_${++this.requestId}`;
|
|
275
|
+
const message = JSON.stringify({ action, requestId: reqId, ...params });
|
|
276
|
+
const timer = setTimeout(() => {
|
|
277
|
+
this.pendingRequests.delete(reqId);
|
|
278
|
+
reject(new Error(`Editor request '${action}' timed out`));
|
|
279
|
+
}, timeoutMs);
|
|
280
|
+
this.pendingRequests.set(reqId, { resolve, reject, timer });
|
|
281
|
+
this.ws.send(message);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=editor-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-bridge.js","sourceRoot":"","sources":["../../src/bridges/editor-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { ValidationResult, InspectResult, GenerateResult, GenerateOptions, TargetInfo } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* HTTP bridge to the VSCXML-Generator-CLI REST API.
|
|
4
|
+
* Communicates with the generator server for validation, inspection,
|
|
5
|
+
* and code generation.
|
|
6
|
+
*/
|
|
7
|
+
export declare class GeneratorBridge {
|
|
8
|
+
private baseUrl;
|
|
9
|
+
constructor(baseUrl?: string);
|
|
10
|
+
/** Update the base URL (e.g., after auto-discovery) */
|
|
11
|
+
setBaseUrl(url: string): void;
|
|
12
|
+
/** Check if the generator server is reachable */
|
|
13
|
+
isAvailable(): Promise<boolean>;
|
|
14
|
+
/** GET /api/health */
|
|
15
|
+
health(): Promise<{
|
|
16
|
+
status: string;
|
|
17
|
+
version: string;
|
|
18
|
+
}>;
|
|
19
|
+
/** POST /api/validate */
|
|
20
|
+
validate(scxml: string): Promise<ValidationResult>;
|
|
21
|
+
/** POST /api/inspect */
|
|
22
|
+
inspect(scxml: string): Promise<InspectResult>;
|
|
23
|
+
/** POST /api/generate - returns generated files as text (extracts from ZIP) */
|
|
24
|
+
generate(scxml: string, target: string, options?: GenerateOptions): Promise<GenerateResult>;
|
|
25
|
+
/** POST /api/create - build SCXML from structured spec */
|
|
26
|
+
create(spec: {
|
|
27
|
+
name?: string;
|
|
28
|
+
datamodel?: string;
|
|
29
|
+
binding?: string;
|
|
30
|
+
states?: Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
type?: string;
|
|
33
|
+
parent?: string | null;
|
|
34
|
+
initial?: string | null;
|
|
35
|
+
onEntry?: string | null;
|
|
36
|
+
onExit?: string | null;
|
|
37
|
+
data?: Array<{
|
|
38
|
+
id: string;
|
|
39
|
+
expr?: string;
|
|
40
|
+
type?: string;
|
|
41
|
+
}>;
|
|
42
|
+
}>;
|
|
43
|
+
transitions?: Array<{
|
|
44
|
+
source: string;
|
|
45
|
+
target?: string | null;
|
|
46
|
+
event?: string | null;
|
|
47
|
+
cond?: string | null;
|
|
48
|
+
type?: string | null;
|
|
49
|
+
actions?: string | null;
|
|
50
|
+
}>;
|
|
51
|
+
data?: Array<{
|
|
52
|
+
id: string;
|
|
53
|
+
expr?: string;
|
|
54
|
+
type?: string;
|
|
55
|
+
}>;
|
|
56
|
+
}): Promise<{
|
|
57
|
+
scxml: string;
|
|
58
|
+
}>;
|
|
59
|
+
/** Generate a full project (codeOnly=false) and return files */
|
|
60
|
+
generateProject(scxml: string, target: string, options?: GenerateOptions): Promise<GenerateResult>;
|
|
61
|
+
/** GET /api/targets */
|
|
62
|
+
listTargets(): Promise<TargetInfo[]>;
|
|
63
|
+
/** GET /api/schema/{target} */
|
|
64
|
+
getTargetSchema(target: string): Promise<Record<string, unknown>>;
|
|
65
|
+
private fetch;
|
|
66
|
+
/**
|
|
67
|
+
* Extract files from a ZIP buffer.
|
|
68
|
+
* Reads the central directory (handles data descriptors where local header
|
|
69
|
+
* has 0-size fields). Uses Node zlib for deflate decompression.
|
|
70
|
+
*/
|
|
71
|
+
private extractZip;
|
|
72
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { inflateRawSync } from 'zlib';
|
|
2
|
+
/**
|
|
3
|
+
* HTTP bridge to the VSCXML-Generator-CLI REST API.
|
|
4
|
+
* Communicates with the generator server for validation, inspection,
|
|
5
|
+
* and code generation.
|
|
6
|
+
*/
|
|
7
|
+
export class GeneratorBridge {
|
|
8
|
+
baseUrl;
|
|
9
|
+
constructor(baseUrl) {
|
|
10
|
+
this.baseUrl = baseUrl || `http://localhost:${48620}`;
|
|
11
|
+
}
|
|
12
|
+
/** Update the base URL (e.g., after auto-discovery) */
|
|
13
|
+
setBaseUrl(url) {
|
|
14
|
+
this.baseUrl = url;
|
|
15
|
+
}
|
|
16
|
+
/** Check if the generator server is reachable */
|
|
17
|
+
async isAvailable() {
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch(`${this.baseUrl}/api/health`, {
|
|
20
|
+
signal: AbortSignal.timeout(3000),
|
|
21
|
+
});
|
|
22
|
+
return res.ok;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** GET /api/health */
|
|
29
|
+
async health() {
|
|
30
|
+
const res = await this.fetch('/api/health');
|
|
31
|
+
return res.json();
|
|
32
|
+
}
|
|
33
|
+
/** POST /api/validate */
|
|
34
|
+
async validate(scxml) {
|
|
35
|
+
const res = await this.fetch('/api/validate', {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'Content-Type': 'application/json' },
|
|
38
|
+
body: JSON.stringify({ scxml }),
|
|
39
|
+
});
|
|
40
|
+
return res.json();
|
|
41
|
+
}
|
|
42
|
+
/** POST /api/inspect */
|
|
43
|
+
async inspect(scxml) {
|
|
44
|
+
const res = await this.fetch('/api/inspect', {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { 'Content-Type': 'application/json' },
|
|
47
|
+
body: JSON.stringify({ scxml }),
|
|
48
|
+
});
|
|
49
|
+
return res.json();
|
|
50
|
+
}
|
|
51
|
+
/** POST /api/generate - returns generated files as text (extracts from ZIP) */
|
|
52
|
+
async generate(scxml, target, options) {
|
|
53
|
+
const config = { scxml, target };
|
|
54
|
+
if (options) {
|
|
55
|
+
config.options = options;
|
|
56
|
+
}
|
|
57
|
+
const res = await this.fetch('/api/generate', {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: { 'Content-Type': 'application/json' },
|
|
60
|
+
body: JSON.stringify(config),
|
|
61
|
+
});
|
|
62
|
+
// Response is a ZIP file — extract file contents
|
|
63
|
+
const zipBuffer = await res.arrayBuffer();
|
|
64
|
+
const files = await this.extractZip(new Uint8Array(zipBuffer));
|
|
65
|
+
return { files, target, config };
|
|
66
|
+
}
|
|
67
|
+
/** POST /api/create - build SCXML from structured spec */
|
|
68
|
+
async create(spec) {
|
|
69
|
+
const res = await this.fetch('/api/create', {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: { 'Content-Type': 'application/json' },
|
|
72
|
+
body: JSON.stringify(spec),
|
|
73
|
+
});
|
|
74
|
+
return res.json();
|
|
75
|
+
}
|
|
76
|
+
/** Generate a full project (codeOnly=false) and return files */
|
|
77
|
+
async generateProject(scxml, target, options) {
|
|
78
|
+
return this.generate(scxml, target, { ...options, codeOnly: false });
|
|
79
|
+
}
|
|
80
|
+
/** GET /api/targets */
|
|
81
|
+
async listTargets() {
|
|
82
|
+
const res = await this.fetch('/api/targets');
|
|
83
|
+
const data = await res.json();
|
|
84
|
+
return data.targets;
|
|
85
|
+
}
|
|
86
|
+
/** GET /api/schema/{target} */
|
|
87
|
+
async getTargetSchema(target) {
|
|
88
|
+
const res = await this.fetch(`/api/schema/${encodeURIComponent(target)}`);
|
|
89
|
+
return res.json();
|
|
90
|
+
}
|
|
91
|
+
async fetch(path, init) {
|
|
92
|
+
const url = `${this.baseUrl}${path}`;
|
|
93
|
+
const res = await fetch(url, {
|
|
94
|
+
...init,
|
|
95
|
+
signal: init?.signal || AbortSignal.timeout(30000),
|
|
96
|
+
});
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
let errorMsg;
|
|
99
|
+
try {
|
|
100
|
+
const errorJson = await res.json();
|
|
101
|
+
errorMsg = errorJson.error || res.statusText;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
errorMsg = res.statusText;
|
|
105
|
+
}
|
|
106
|
+
throw new Error(`Generator API error (${res.status}): ${errorMsg}`);
|
|
107
|
+
}
|
|
108
|
+
return res;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Extract files from a ZIP buffer.
|
|
112
|
+
* Reads the central directory (handles data descriptors where local header
|
|
113
|
+
* has 0-size fields). Uses Node zlib for deflate decompression.
|
|
114
|
+
*/
|
|
115
|
+
async extractZip(data) {
|
|
116
|
+
const files = [];
|
|
117
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
118
|
+
// Find End of Central Directory record (scan backwards)
|
|
119
|
+
let eocdOffset = -1;
|
|
120
|
+
for (let i = data.length - 22; i >= 0; i--) {
|
|
121
|
+
if (view.getUint32(i, true) === 0x06054b50) {
|
|
122
|
+
eocdOffset = i;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (eocdOffset === -1)
|
|
127
|
+
return files;
|
|
128
|
+
const cdOffset = view.getUint32(eocdOffset + 16, true);
|
|
129
|
+
const cdEntries = view.getUint16(eocdOffset + 10, true);
|
|
130
|
+
// Walk central directory entries
|
|
131
|
+
let cdPos = cdOffset;
|
|
132
|
+
for (let i = 0; i < cdEntries; i++) {
|
|
133
|
+
if (view.getUint32(cdPos, true) !== 0x02014b50)
|
|
134
|
+
break;
|
|
135
|
+
const compression = view.getUint16(cdPos + 10, true);
|
|
136
|
+
const compSize = view.getUint32(cdPos + 20, true);
|
|
137
|
+
const uncompSize = view.getUint32(cdPos + 24, true);
|
|
138
|
+
const nameLen = view.getUint16(cdPos + 28, true);
|
|
139
|
+
const extraLen = view.getUint16(cdPos + 30, true);
|
|
140
|
+
const commentLen = view.getUint16(cdPos + 32, true);
|
|
141
|
+
const localHeaderOffset = view.getUint32(cdPos + 42, true);
|
|
142
|
+
const fileName = new TextDecoder().decode(data.slice(cdPos + 46, cdPos + 46 + nameLen));
|
|
143
|
+
// Find data start in local header
|
|
144
|
+
const localNameLen = view.getUint16(localHeaderOffset + 26, true);
|
|
145
|
+
const localExtraLen = view.getUint16(localHeaderOffset + 28, true);
|
|
146
|
+
const dataStart = localHeaderOffset + 30 + localNameLen + localExtraLen;
|
|
147
|
+
if (uncompSize > 0 && !fileName.endsWith('/')) {
|
|
148
|
+
let content = null;
|
|
149
|
+
if (compression === 0) {
|
|
150
|
+
content = new TextDecoder().decode(data.slice(dataStart, dataStart + uncompSize));
|
|
151
|
+
}
|
|
152
|
+
else if (compression === 8) {
|
|
153
|
+
try {
|
|
154
|
+
const compressed = data.slice(dataStart, dataStart + compSize);
|
|
155
|
+
const decompressed = inflateRawSync(Buffer.from(compressed));
|
|
156
|
+
content = new TextDecoder().decode(decompressed);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// Skip entries that fail to decompress
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (content !== null) {
|
|
163
|
+
const ext = fileName.split('.').pop() || '';
|
|
164
|
+
files.push({ path: fileName, content, language: extToLanguage(ext) });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
cdPos += 46 + nameLen + extraLen + commentLen;
|
|
168
|
+
}
|
|
169
|
+
return files;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function extToLanguage(ext) {
|
|
173
|
+
const map = {
|
|
174
|
+
java: 'java',
|
|
175
|
+
js: 'javascript',
|
|
176
|
+
mjs: 'javascript',
|
|
177
|
+
cs: 'csharp',
|
|
178
|
+
c: 'c',
|
|
179
|
+
h: 'c',
|
|
180
|
+
py: 'python',
|
|
181
|
+
go: 'go',
|
|
182
|
+
st: 'structured-text',
|
|
183
|
+
json: 'json',
|
|
184
|
+
xml: 'xml',
|
|
185
|
+
gradle: 'groovy',
|
|
186
|
+
kts: 'kotlin',
|
|
187
|
+
};
|
|
188
|
+
return map[ext] || ext;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=generator-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator-bridge.js","sourceRoot":"","sources":["../../src/bridges/generator-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { TraceEntry, TraceInfo, TracePlaybackStatus, SimulationState } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket bridge to the VSCXML-Simulator.
|
|
4
|
+
* Uses response-type matching (the server does not echo commandId).
|
|
5
|
+
* Buffers broadcast events (state_update, transition_fired, etc.) into a trace.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SimulatorBridge {
|
|
8
|
+
private ws;
|
|
9
|
+
private url;
|
|
10
|
+
private pendingResolve;
|
|
11
|
+
private traceBuffer;
|
|
12
|
+
private sessionId;
|
|
13
|
+
private connected;
|
|
14
|
+
private reconnectTimer;
|
|
15
|
+
private activeStates;
|
|
16
|
+
private variables;
|
|
17
|
+
private enabledEvents;
|
|
18
|
+
private finished;
|
|
19
|
+
private mode;
|
|
20
|
+
constructor(url?: string);
|
|
21
|
+
setUrl(url: string): void;
|
|
22
|
+
isConnected(): boolean;
|
|
23
|
+
getSessionId(): string | null;
|
|
24
|
+
/** Connect to the simulator WebSocket */
|
|
25
|
+
connect(): Promise<void>;
|
|
26
|
+
disconnect(): void;
|
|
27
|
+
isAvailable(): Promise<boolean>;
|
|
28
|
+
/** Load SCXML and return session info */
|
|
29
|
+
loadScxml(scxml: string): Promise<SimulationState>;
|
|
30
|
+
/** Start the state machine */
|
|
31
|
+
start(): Promise<SimulationState>;
|
|
32
|
+
/** Send an event and return trace + state */
|
|
33
|
+
sendEvent(eventName: string, eventData?: unknown): Promise<{
|
|
34
|
+
trace: TraceEntry[];
|
|
35
|
+
state: SimulationState;
|
|
36
|
+
}>;
|
|
37
|
+
/** Get current state without sending an event */
|
|
38
|
+
getState(): Promise<SimulationState & {
|
|
39
|
+
history: TraceEntry[];
|
|
40
|
+
}>;
|
|
41
|
+
/** Reset the simulation */
|
|
42
|
+
reset(): Promise<SimulationState>;
|
|
43
|
+
/** Get current SCXML content */
|
|
44
|
+
getScxml(): Promise<string>;
|
|
45
|
+
/** List embedded traces in the current SCXML document */
|
|
46
|
+
listTraces(): Promise<TraceInfo[]>;
|
|
47
|
+
/** Save/embed a trace into the SCXML document */
|
|
48
|
+
saveTrace(name: string, options?: {
|
|
49
|
+
description?: string;
|
|
50
|
+
content?: string;
|
|
51
|
+
}): Promise<{
|
|
52
|
+
entryCount: number;
|
|
53
|
+
scxml: string;
|
|
54
|
+
}>;
|
|
55
|
+
/** Delete an embedded trace by name */
|
|
56
|
+
deleteTrace(name: string): Promise<{
|
|
57
|
+
scxml: string;
|
|
58
|
+
}>;
|
|
59
|
+
/** Load an embedded trace by name (returns parsed entries) */
|
|
60
|
+
loadTrace(name: string): Promise<{
|
|
61
|
+
entries: Record<string, unknown>[];
|
|
62
|
+
entryCount: number;
|
|
63
|
+
description?: string;
|
|
64
|
+
}>;
|
|
65
|
+
/** Start playing an embedded trace by name */
|
|
66
|
+
playTrace(name: string, speed?: number): Promise<{
|
|
67
|
+
entryCount: number;
|
|
68
|
+
}>;
|
|
69
|
+
/** Step forward/backward in trace playback */
|
|
70
|
+
stepTrace(delta: number): Promise<{
|
|
71
|
+
index: number;
|
|
72
|
+
total: number;
|
|
73
|
+
entry?: Record<string, unknown>;
|
|
74
|
+
}>;
|
|
75
|
+
/** Pause trace playback */
|
|
76
|
+
pauseTrace(): Promise<{
|
|
77
|
+
index: number;
|
|
78
|
+
total: number;
|
|
79
|
+
}>;
|
|
80
|
+
/** Get trace playback status */
|
|
81
|
+
getTraceStatus(): Promise<TracePlaybackStatus>;
|
|
82
|
+
/** Set a variable value during simulation */
|
|
83
|
+
setVariable(name: string, value: unknown): Promise<void>;
|
|
84
|
+
private getCurrentState;
|
|
85
|
+
private drainTrace;
|
|
86
|
+
private waitForSettle;
|
|
87
|
+
private handleMessage;
|
|
88
|
+
private sendCommand;
|
|
89
|
+
}
|