c64bridge 0.9.0 → 0.9.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/README.md +158 -164
- package/data/vice/vice-binary-monitor-spec.md +21 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/c64Client.js +76 -2
- package/dist/device.js +43 -3
- package/dist/rag/indexer.js +18 -8
- package/dist/sidwaveCompiler.js +1 -1
- package/dist/{assemblyConverter.js → tools/assember.js} +10 -1
- package/dist/{basicConverter.js → tools/basicTokenizer.js} +1 -1
- package/dist/tools/debug.js +158 -5
- package/dist/tools/disassembler.js +478 -0
- package/dist/tools/input.js +338 -0
- package/dist/tools/memory.js +317 -1
- package/dist/tools/programRunners.js +45 -6
- package/dist/tools/registry/batch.js +167 -0
- package/dist/tools/registry/graphics.js +101 -1
- package/dist/tools/registry/index.js +4 -0
- package/dist/tools/registry/input.js +2 -0
- package/dist/tools/registry/memory.js +61 -1
- package/dist/tools/schema.js +4 -5
- package/dist/tools/symbolRegistry.js +49 -0
- package/dist/tools/types.js +19 -4
- package/dist/vice/process.js +43 -2
- package/dist/vice/viceClient.js +5 -1
- package/mcp/schemas/c64_batch.schema.json +53 -0
- package/mcp/schemas/c64_config.schema.json +461 -2
- package/mcp/schemas/c64_debug.schema.json +641 -3
- package/mcp/schemas/c64_disk.schema.json +340 -2
- package/mcp/schemas/c64_drive.schema.json +157 -2
- package/mcp/schemas/c64_extract.schema.json +359 -2
- package/mcp/schemas/c64_graphics.schema.json +415 -3
- package/mcp/schemas/c64_input.schema.json +136 -0
- package/mcp/schemas/c64_memory.schema.json +562 -3
- package/mcp/schemas/c64_printer.schema.json +253 -2
- package/mcp/schemas/c64_program.schema.json +499 -2
- package/mcp/schemas/c64_rag.schema.json +82 -2
- package/mcp/schemas/c64_select_backend.schema.json +35 -2
- package/mcp/schemas/c64_sound.schema.json +793 -2
- package/mcp/schemas/c64_stream.schema.json +73 -2
- package/mcp/schemas/c64_system.schema.json +301 -2
- package/mcp/schemas/c64_vice.schema.json +71 -2
- package/mcp/server.json +1 -1
- package/mcp/tools.json +6718 -1257
- package/mcp.json +1 -1
- package/package.json +1 -1
- package/scripts/run-coverage.mjs +7 -0
- package/scripts/run-tests.ts +2 -0
- package/scripts/update-readme.ts +79 -2
- package/server.json +2 -2
package/dist/vice/process.js
CHANGED
|
@@ -187,8 +187,19 @@ export async function terminateProcess(child, signal = "SIGTERM", timeoutMs = 10
|
|
|
187
187
|
}
|
|
188
188
|
export async function startViceProcess(options) {
|
|
189
189
|
const debugEnabled = process.env.VICE_DEVICE_TEST_DEBUG === "1";
|
|
190
|
-
|
|
191
|
-
const
|
|
190
|
+
// When headless=true, skip Xvfb entirely and rely on VICE's own -headless flag (VICE 3.5+).
|
|
191
|
+
const useHeadless = options.headless === true || process.env.VICE_HEADLESS === "1";
|
|
192
|
+
let useXvfb;
|
|
193
|
+
let display;
|
|
194
|
+
if (useHeadless) {
|
|
195
|
+
useXvfb = false;
|
|
196
|
+
display = "";
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const probe = shouldUseXvfb(options.visible);
|
|
200
|
+
useXvfb = probe.useXvfb;
|
|
201
|
+
display = useXvfb ? resolveXvfbDisplayForLaunch(probe.display) : probe.display;
|
|
202
|
+
}
|
|
192
203
|
const viceEnv = { ...process.env };
|
|
193
204
|
let xvfb = null;
|
|
194
205
|
const xvfbOutput = createOutputTailCapture("xvfb");
|
|
@@ -198,6 +209,7 @@ export async function startViceProcess(options) {
|
|
|
198
209
|
directory: options.directory,
|
|
199
210
|
display,
|
|
200
211
|
extraArgs: options.extraArgs ?? [],
|
|
212
|
+
headless: useHeadless,
|
|
201
213
|
host: options.host,
|
|
202
214
|
port: options.port,
|
|
203
215
|
useXvfb,
|
|
@@ -239,6 +251,7 @@ export async function startViceProcess(options) {
|
|
|
239
251
|
"-binarymonitoraddress", `${options.host}:${options.port}`,
|
|
240
252
|
"-sounddev", "dummy",
|
|
241
253
|
"-config", "/dev/null",
|
|
254
|
+
...(useHeadless ? ["-headless"] : []),
|
|
242
255
|
...(options.directory ? ["-directory", options.directory] : []),
|
|
243
256
|
...(options.extraArgs ?? []),
|
|
244
257
|
];
|
|
@@ -370,15 +383,43 @@ export async function startViceProcess(options) {
|
|
|
370
383
|
});
|
|
371
384
|
return { host: options.host, port: options.port, process: child, stop };
|
|
372
385
|
}
|
|
386
|
+
function isIgnorableSocketDirError(error) {
|
|
387
|
+
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
const code = String(error.code ?? "");
|
|
391
|
+
return code === "EACCES" || code === "EPERM" || code === "EROFS" || code === "EEXIST";
|
|
392
|
+
}
|
|
373
393
|
export function ensureXvfbSocketDir(debugEnabled) {
|
|
374
394
|
const socketDir = "/tmp/.X11-unix";
|
|
375
395
|
try {
|
|
376
396
|
if (!fs.existsSync(socketDir)) {
|
|
377
397
|
fs.mkdirSync(socketDir, { mode: 0o1777 });
|
|
378
398
|
}
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
if (isIgnorableSocketDirError(error)) {
|
|
402
|
+
if (debugEnabled) {
|
|
403
|
+
console.error("[vice-process] unable to create Xvfb socket dir; continuing", error);
|
|
404
|
+
}
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
writeDiagnosticEvent("xvfb_socket_dir_failed", { socketDir, error });
|
|
408
|
+
if (debugEnabled) {
|
|
409
|
+
console.error("[vice-process] failed to prepare Xvfb socket dir", error);
|
|
410
|
+
}
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
379
414
|
fs.chmodSync(socketDir, 0o1777);
|
|
380
415
|
}
|
|
381
416
|
catch (error) {
|
|
417
|
+
if (isIgnorableSocketDirError(error)) {
|
|
418
|
+
if (debugEnabled) {
|
|
419
|
+
console.error("[vice-process] unable to chmod Xvfb socket dir; continuing", error);
|
|
420
|
+
}
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
382
423
|
writeDiagnosticEvent("xvfb_socket_dir_failed", { socketDir, error });
|
|
383
424
|
if (debugEnabled) {
|
|
384
425
|
console.error("[vice-process] failed to prepare Xvfb socket dir", error);
|
package/dist/vice/viceClient.js
CHANGED
|
@@ -9,6 +9,9 @@ export class ViceClient {
|
|
|
9
9
|
this.pending = new Map();
|
|
10
10
|
this.closing = false;
|
|
11
11
|
}
|
|
12
|
+
setUnsolicitedHandler(handler) {
|
|
13
|
+
this.onUnsolicitedHandler = handler;
|
|
14
|
+
}
|
|
12
15
|
async connect(port, host = "127.0.0.1") {
|
|
13
16
|
this.socket = net.connect({ host, port });
|
|
14
17
|
this.closing = false;
|
|
@@ -77,7 +80,8 @@ export class ViceClient {
|
|
|
77
80
|
const err = frame[7];
|
|
78
81
|
const reqId = frame.readUInt32LE(8);
|
|
79
82
|
if (reqId === 0xffffffff) {
|
|
80
|
-
|
|
83
|
+
this.onUnsolicitedHandler?.(responseType, frame);
|
|
84
|
+
continue;
|
|
81
85
|
}
|
|
82
86
|
const pending = this.pending.get(reqId);
|
|
83
87
|
if (!pending) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "object",
|
|
3
|
+
"properties": {
|
|
4
|
+
"commands": {
|
|
5
|
+
"type": "array",
|
|
6
|
+
"description": "Ordered list of commands to execute.",
|
|
7
|
+
"items": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"description": "A single batch command.",
|
|
10
|
+
"properties": {
|
|
11
|
+
"tool": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "MCP tool name (e.g. c64_memory, c64_debug).",
|
|
14
|
+
"minLength": 1
|
|
15
|
+
},
|
|
16
|
+
"args": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"description": "Arguments to pass to the tool (must include 'op' for grouped tools).",
|
|
19
|
+
"properties": {},
|
|
20
|
+
"additionalProperties": true
|
|
21
|
+
},
|
|
22
|
+
"description": {
|
|
23
|
+
"type": [
|
|
24
|
+
"string",
|
|
25
|
+
"null"
|
|
26
|
+
],
|
|
27
|
+
"description": "Optional label for this command in the result.",
|
|
28
|
+
"maxLength": 128
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"required": [
|
|
32
|
+
"tool",
|
|
33
|
+
"args"
|
|
34
|
+
],
|
|
35
|
+
"additionalProperties": false
|
|
36
|
+
},
|
|
37
|
+
"minItems": 1
|
|
38
|
+
},
|
|
39
|
+
"stopOnError": {
|
|
40
|
+
"type": [
|
|
41
|
+
"boolean",
|
|
42
|
+
"null"
|
|
43
|
+
],
|
|
44
|
+
"description": "Halt the batch after the first failure. Default: true.",
|
|
45
|
+
"default": true
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"required": [
|
|
49
|
+
"commands"
|
|
50
|
+
],
|
|
51
|
+
"description": "Execute multiple tool calls in one request.",
|
|
52
|
+
"additionalProperties": false
|
|
53
|
+
}
|
|
@@ -128,6 +128,465 @@
|
|
|
128
128
|
"required": [
|
|
129
129
|
"op"
|
|
130
130
|
],
|
|
131
|
-
"description": "Configuration operations available via the c64_config tool.\n\nOperations:\n- list: List configuration categories reported by the firmware.\n- get: Read a configuration category or specific item.\n- set: Write a configuration value in the selected category.\n- batch_update: Apply multiple configuration updates in a single request.\n- load_flash: Load configuration from flash storage.\n- save_flash: Persist the current configuration to flash storage.\n- reset_defaults: Reset firmware configuration to factory defaults.\n- read_debugreg: Read the Ultimate debug register ($D7FF).\n- write_debugreg: Write a hex value to the Ultimate debug register ($D7FF).\n- info: Retrieve Ultimate hardware information and status.\n- version: Fetch firmware version details.\n- snapshot: Snapshot configuration to disk for later restore or diff.\n- restore: Restore configuration from a snapshot file.\n- diff: Compare the current configuration with a snapshot.\n- shuffle: Discover PRG/CRT files and run each with optional screen capture.",
|
|
132
|
-
"additionalProperties": false
|
|
131
|
+
"description": "Configuration operations available via the c64_config tool.\n\nOperations:\n- list: List configuration categories reported by the firmware. Required inputs: none.\n- get: Read a configuration category or specific item. Required inputs: category. Optional inputs: item.\n- set: Write a configuration value in the selected category. Required inputs: category, item, value.\n- batch_update: Apply multiple configuration updates in a single request. Required inputs: none.\n- load_flash: Load configuration from flash storage. Required inputs: none.\n- save_flash: Persist the current configuration to flash storage. Required inputs: none.\n- reset_defaults: Reset firmware configuration to factory defaults. Required inputs: none.\n- read_debugreg: Read the Ultimate debug register ($D7FF). Required inputs: none.\n- write_debugreg: Write a hex value to the Ultimate debug register ($D7FF). Required inputs: value.\n- info: Retrieve Ultimate hardware information and status. Required inputs: none.\n- version: Fetch firmware version details. Required inputs: none.\n- snapshot: Snapshot configuration to disk for later restore or diff. Required inputs: path.\n- restore: Restore configuration from a snapshot file. Required inputs: path. Optional inputs: applyToFlash.\n- diff: Compare the current configuration with a snapshot. Required inputs: path.\n- shuffle: Discover PRG/CRT files and run each with optional screen capture. Required inputs: none. Optional inputs: root, extensions, durationMs, captureScreen, maxPrograms, outputPath, resetDelayMs.",
|
|
132
|
+
"additionalProperties": false,
|
|
133
|
+
"x-c64bridge-operations": [
|
|
134
|
+
{
|
|
135
|
+
"op": "list",
|
|
136
|
+
"description": "List configuration categories reported by the firmware.",
|
|
137
|
+
"required": [],
|
|
138
|
+
"optional": [],
|
|
139
|
+
"inputSchema": {
|
|
140
|
+
"type": "object",
|
|
141
|
+
"description": "List configuration categories reported by the firmware.",
|
|
142
|
+
"properties": {
|
|
143
|
+
"op": {
|
|
144
|
+
"const": "list"
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"additionalProperties": false,
|
|
148
|
+
"required": [
|
|
149
|
+
"op"
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"op": "get",
|
|
155
|
+
"description": "Read a configuration category or specific item.",
|
|
156
|
+
"required": [
|
|
157
|
+
"category"
|
|
158
|
+
],
|
|
159
|
+
"optional": [
|
|
160
|
+
"item"
|
|
161
|
+
],
|
|
162
|
+
"inputSchema": {
|
|
163
|
+
"type": "object",
|
|
164
|
+
"description": "Read a configuration category or specific item.",
|
|
165
|
+
"properties": {
|
|
166
|
+
"category": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"description": "Configuration category reported by the Ultimate firmware (e.g. 'Audio').",
|
|
169
|
+
"minLength": 1
|
|
170
|
+
},
|
|
171
|
+
"item": {
|
|
172
|
+
"type": [
|
|
173
|
+
"string",
|
|
174
|
+
"null"
|
|
175
|
+
],
|
|
176
|
+
"description": "Specific configuration item inside the selected category (e.g. 'Volume').",
|
|
177
|
+
"minLength": 1
|
|
178
|
+
},
|
|
179
|
+
"op": {
|
|
180
|
+
"const": "get"
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"required": [
|
|
184
|
+
"category",
|
|
185
|
+
"op"
|
|
186
|
+
],
|
|
187
|
+
"additionalProperties": false
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"op": "set",
|
|
192
|
+
"description": "Write a configuration value in the selected category.",
|
|
193
|
+
"required": [
|
|
194
|
+
"category",
|
|
195
|
+
"item",
|
|
196
|
+
"value"
|
|
197
|
+
],
|
|
198
|
+
"optional": [],
|
|
199
|
+
"inputSchema": {
|
|
200
|
+
"type": "object",
|
|
201
|
+
"description": "Write a configuration value in the selected category.",
|
|
202
|
+
"properties": {
|
|
203
|
+
"category": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"description": "Configuration category reported by the Ultimate firmware (e.g. 'Audio').",
|
|
206
|
+
"minLength": 1
|
|
207
|
+
},
|
|
208
|
+
"item": {
|
|
209
|
+
"type": "string",
|
|
210
|
+
"description": "Configuration item name inside the category.",
|
|
211
|
+
"minLength": 1
|
|
212
|
+
},
|
|
213
|
+
"value": {
|
|
214
|
+
"description": "Primitive configuration value (string, number, or boolean).",
|
|
215
|
+
"type": [
|
|
216
|
+
"string",
|
|
217
|
+
"number",
|
|
218
|
+
"boolean"
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
"op": {
|
|
222
|
+
"const": "set"
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
"required": [
|
|
226
|
+
"category",
|
|
227
|
+
"item",
|
|
228
|
+
"value",
|
|
229
|
+
"op"
|
|
230
|
+
],
|
|
231
|
+
"additionalProperties": false
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"op": "batch_update",
|
|
236
|
+
"description": "Apply multiple configuration updates in a single request.",
|
|
237
|
+
"required": [],
|
|
238
|
+
"optional": [],
|
|
239
|
+
"inputSchema": {
|
|
240
|
+
"description": "Apply multiple configuration updates in a single request.",
|
|
241
|
+
"type": "object",
|
|
242
|
+
"additionalProperties": {
|
|
243
|
+
"type": "object",
|
|
244
|
+
"additionalProperties": {
|
|
245
|
+
"type": [
|
|
246
|
+
"string",
|
|
247
|
+
"number",
|
|
248
|
+
"boolean"
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"properties": {
|
|
253
|
+
"op": {
|
|
254
|
+
"const": "batch_update"
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
"required": [
|
|
258
|
+
"op"
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"op": "load_flash",
|
|
264
|
+
"description": "Load configuration from flash storage.",
|
|
265
|
+
"required": [],
|
|
266
|
+
"optional": [],
|
|
267
|
+
"inputSchema": {
|
|
268
|
+
"type": "object",
|
|
269
|
+
"description": "Load configuration from flash storage.",
|
|
270
|
+
"properties": {
|
|
271
|
+
"op": {
|
|
272
|
+
"const": "load_flash"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
"additionalProperties": false,
|
|
276
|
+
"required": [
|
|
277
|
+
"op"
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"op": "save_flash",
|
|
283
|
+
"description": "Persist the current configuration to flash storage.",
|
|
284
|
+
"required": [],
|
|
285
|
+
"optional": [],
|
|
286
|
+
"inputSchema": {
|
|
287
|
+
"type": "object",
|
|
288
|
+
"description": "Persist the current configuration to flash storage.",
|
|
289
|
+
"properties": {
|
|
290
|
+
"op": {
|
|
291
|
+
"const": "save_flash"
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
"additionalProperties": false,
|
|
295
|
+
"required": [
|
|
296
|
+
"op"
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"op": "reset_defaults",
|
|
302
|
+
"description": "Reset firmware configuration to factory defaults.",
|
|
303
|
+
"required": [],
|
|
304
|
+
"optional": [],
|
|
305
|
+
"inputSchema": {
|
|
306
|
+
"type": "object",
|
|
307
|
+
"description": "Reset firmware configuration to factory defaults.",
|
|
308
|
+
"properties": {
|
|
309
|
+
"op": {
|
|
310
|
+
"const": "reset_defaults"
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
"additionalProperties": false,
|
|
314
|
+
"required": [
|
|
315
|
+
"op"
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"op": "read_debugreg",
|
|
321
|
+
"description": "Read the Ultimate debug register ($D7FF).",
|
|
322
|
+
"required": [],
|
|
323
|
+
"optional": [],
|
|
324
|
+
"inputSchema": {
|
|
325
|
+
"type": "object",
|
|
326
|
+
"description": "Read the Ultimate debug register ($D7FF).",
|
|
327
|
+
"properties": {
|
|
328
|
+
"op": {
|
|
329
|
+
"const": "read_debugreg"
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
"additionalProperties": false,
|
|
333
|
+
"required": [
|
|
334
|
+
"op"
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"op": "write_debugreg",
|
|
340
|
+
"description": "Write a hex value to the Ultimate debug register ($D7FF).",
|
|
341
|
+
"required": [
|
|
342
|
+
"value"
|
|
343
|
+
],
|
|
344
|
+
"optional": [],
|
|
345
|
+
"inputSchema": {
|
|
346
|
+
"type": "object",
|
|
347
|
+
"description": "Write a hex value to the Ultimate debug register ($D7FF).",
|
|
348
|
+
"properties": {
|
|
349
|
+
"value": {
|
|
350
|
+
"type": "string",
|
|
351
|
+
"description": "Hex value (00-FF) to write to the debug register.",
|
|
352
|
+
"minLength": 1,
|
|
353
|
+
"maxLength": 2,
|
|
354
|
+
"pattern": "^[0-9A-Fa-f]{1,2}$"
|
|
355
|
+
},
|
|
356
|
+
"op": {
|
|
357
|
+
"const": "write_debugreg"
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
"required": [
|
|
361
|
+
"value",
|
|
362
|
+
"op"
|
|
363
|
+
],
|
|
364
|
+
"additionalProperties": false
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"op": "info",
|
|
369
|
+
"description": "Retrieve Ultimate hardware information and status.",
|
|
370
|
+
"required": [],
|
|
371
|
+
"optional": [],
|
|
372
|
+
"inputSchema": {
|
|
373
|
+
"type": "object",
|
|
374
|
+
"description": "Retrieve Ultimate hardware information and status.",
|
|
375
|
+
"properties": {
|
|
376
|
+
"op": {
|
|
377
|
+
"const": "info"
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
"additionalProperties": false,
|
|
381
|
+
"required": [
|
|
382
|
+
"op"
|
|
383
|
+
]
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"op": "version",
|
|
388
|
+
"description": "Fetch firmware version details.",
|
|
389
|
+
"required": [],
|
|
390
|
+
"optional": [],
|
|
391
|
+
"inputSchema": {
|
|
392
|
+
"type": "object",
|
|
393
|
+
"description": "Fetch firmware version details.",
|
|
394
|
+
"properties": {
|
|
395
|
+
"op": {
|
|
396
|
+
"const": "version"
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
"additionalProperties": false,
|
|
400
|
+
"required": [
|
|
401
|
+
"op"
|
|
402
|
+
]
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"op": "snapshot",
|
|
407
|
+
"description": "Snapshot configuration to disk for later restore or diff.",
|
|
408
|
+
"required": [
|
|
409
|
+
"path"
|
|
410
|
+
],
|
|
411
|
+
"optional": [],
|
|
412
|
+
"inputSchema": {
|
|
413
|
+
"type": "object",
|
|
414
|
+
"description": "Snapshot configuration to disk for later restore or diff.",
|
|
415
|
+
"properties": {
|
|
416
|
+
"path": {
|
|
417
|
+
"type": "string",
|
|
418
|
+
"description": "Absolute or workspace-relative path where the snapshot file will be written.",
|
|
419
|
+
"minLength": 1
|
|
420
|
+
},
|
|
421
|
+
"op": {
|
|
422
|
+
"const": "snapshot"
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
"required": [
|
|
426
|
+
"path",
|
|
427
|
+
"op"
|
|
428
|
+
],
|
|
429
|
+
"additionalProperties": false
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"op": "restore",
|
|
434
|
+
"description": "Restore configuration from a snapshot file.",
|
|
435
|
+
"required": [
|
|
436
|
+
"path"
|
|
437
|
+
],
|
|
438
|
+
"optional": [
|
|
439
|
+
"applyToFlash"
|
|
440
|
+
],
|
|
441
|
+
"inputSchema": {
|
|
442
|
+
"type": "object",
|
|
443
|
+
"description": "Restore configuration from a snapshot file.",
|
|
444
|
+
"properties": {
|
|
445
|
+
"path": {
|
|
446
|
+
"type": "string",
|
|
447
|
+
"description": "Snapshot file to read (must contain categories payload).",
|
|
448
|
+
"minLength": 1
|
|
449
|
+
},
|
|
450
|
+
"applyToFlash": {
|
|
451
|
+
"type": [
|
|
452
|
+
"boolean",
|
|
453
|
+
"null"
|
|
454
|
+
],
|
|
455
|
+
"description": "When true, save the restored configuration to flash immediately.",
|
|
456
|
+
"default": false
|
|
457
|
+
},
|
|
458
|
+
"op": {
|
|
459
|
+
"const": "restore"
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
"required": [
|
|
463
|
+
"path",
|
|
464
|
+
"op"
|
|
465
|
+
],
|
|
466
|
+
"additionalProperties": false
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"op": "diff",
|
|
471
|
+
"description": "Compare the current configuration with a snapshot.",
|
|
472
|
+
"required": [
|
|
473
|
+
"path"
|
|
474
|
+
],
|
|
475
|
+
"optional": [],
|
|
476
|
+
"inputSchema": {
|
|
477
|
+
"type": "object",
|
|
478
|
+
"description": "Compare the current configuration with a snapshot.",
|
|
479
|
+
"properties": {
|
|
480
|
+
"path": {
|
|
481
|
+
"type": "string",
|
|
482
|
+
"description": "Snapshot file to compare with.",
|
|
483
|
+
"minLength": 1
|
|
484
|
+
},
|
|
485
|
+
"op": {
|
|
486
|
+
"const": "diff"
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
"required": [
|
|
490
|
+
"path",
|
|
491
|
+
"op"
|
|
492
|
+
],
|
|
493
|
+
"additionalProperties": false
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"op": "shuffle",
|
|
498
|
+
"description": "Discover PRG/CRT files and run each with optional screen capture.",
|
|
499
|
+
"required": [],
|
|
500
|
+
"optional": [
|
|
501
|
+
"root",
|
|
502
|
+
"extensions",
|
|
503
|
+
"durationMs",
|
|
504
|
+
"captureScreen",
|
|
505
|
+
"maxPrograms",
|
|
506
|
+
"outputPath",
|
|
507
|
+
"resetDelayMs"
|
|
508
|
+
],
|
|
509
|
+
"inputSchema": {
|
|
510
|
+
"type": "object",
|
|
511
|
+
"description": "Discover PRG/CRT files and run each with optional screen capture.",
|
|
512
|
+
"properties": {
|
|
513
|
+
"root": {
|
|
514
|
+
"type": [
|
|
515
|
+
"string",
|
|
516
|
+
"null"
|
|
517
|
+
],
|
|
518
|
+
"description": "Root path to search for programs",
|
|
519
|
+
"minLength": 1,
|
|
520
|
+
"default": "/"
|
|
521
|
+
},
|
|
522
|
+
"extensions": {
|
|
523
|
+
"type": [
|
|
524
|
+
"array",
|
|
525
|
+
"null"
|
|
526
|
+
],
|
|
527
|
+
"items": {
|
|
528
|
+
"type": "string",
|
|
529
|
+
"description": "File extensions to include (without dot)",
|
|
530
|
+
"minLength": 1
|
|
531
|
+
},
|
|
532
|
+
"default": [
|
|
533
|
+
"prg",
|
|
534
|
+
"crt"
|
|
535
|
+
]
|
|
536
|
+
},
|
|
537
|
+
"durationMs": {
|
|
538
|
+
"type": [
|
|
539
|
+
"integer",
|
|
540
|
+
"null"
|
|
541
|
+
],
|
|
542
|
+
"description": "Duration to run each program in milliseconds",
|
|
543
|
+
"minimum": 1,
|
|
544
|
+
"default": 5000
|
|
545
|
+
},
|
|
546
|
+
"captureScreen": {
|
|
547
|
+
"type": [
|
|
548
|
+
"boolean",
|
|
549
|
+
"null"
|
|
550
|
+
],
|
|
551
|
+
"description": "Capture screen after each run",
|
|
552
|
+
"default": true
|
|
553
|
+
},
|
|
554
|
+
"maxPrograms": {
|
|
555
|
+
"type": [
|
|
556
|
+
"integer",
|
|
557
|
+
"null"
|
|
558
|
+
],
|
|
559
|
+
"description": "Maximum number of programs to run",
|
|
560
|
+
"minimum": 1,
|
|
561
|
+
"default": 10
|
|
562
|
+
},
|
|
563
|
+
"outputPath": {
|
|
564
|
+
"type": [
|
|
565
|
+
"string",
|
|
566
|
+
"null"
|
|
567
|
+
],
|
|
568
|
+
"description": "Output directory for run logs and captures",
|
|
569
|
+
"minLength": 1
|
|
570
|
+
},
|
|
571
|
+
"resetDelayMs": {
|
|
572
|
+
"type": [
|
|
573
|
+
"integer",
|
|
574
|
+
"null"
|
|
575
|
+
],
|
|
576
|
+
"description": "Delay after reset operations to allow the platform to settle.",
|
|
577
|
+
"minimum": 0,
|
|
578
|
+
"maximum": 1000,
|
|
579
|
+
"default": 100
|
|
580
|
+
},
|
|
581
|
+
"op": {
|
|
582
|
+
"const": "shuffle"
|
|
583
|
+
}
|
|
584
|
+
},
|
|
585
|
+
"additionalProperties": false,
|
|
586
|
+
"required": [
|
|
587
|
+
"op"
|
|
588
|
+
]
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
]
|
|
133
592
|
}
|