c64bridge 0.9.1 → 0.9.2
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 +34 -2
- package/data/assembly/assembly-spec.md +1 -1
- package/data/context/bootstrap.md +3 -3
- package/data/context/fast-paths.md +3 -1
- package/data/graphics/petscii-style-guide.md +1 -1
- package/data/graphics/sprite-charset-best-practices.md +14 -13
- package/data/sound/sid-file-structure.md +5 -5
- package/data/sound/sid-programming-best-practices.md +5 -5
- package/data/vice/vice-binary-monitor-spec.md +5 -6
- package/dist/.tsbuildinfo +1 -1
- package/dist/c64Client.js +33 -8
- package/dist/sidwaveCompiler.js +1 -1
- package/dist/tools/input.js +5 -7
- package/dist/tools/memory.js +11 -2
- package/dist/tools/programRunners.js +3 -3
- package/dist/tools/responses.js +14 -1
- package/dist/tools/{assember.js → translation/assembler.js} +56 -162
- package/dist/tools/{basicTokenizer.js → translation/basicTokenizer.js} +1 -1
- package/dist/tools/translation/disassembler.js +150 -0
- package/dist/tools/translation/opcodeInventory.js +126 -0
- package/doc/reviews/audit.md +143 -0
- package/mcp/schemas/c64_input.schema.json +231 -113
- package/mcp/server.json +1 -1
- package/mcp/tools.json +234 -115
- package/mcp.json +1 -1
- package/package.json +2 -2
- package/scripts/c64-cli.mjs +2 -2
- package/scripts/run-coverage.mjs +54 -3
- package/scripts/run-tests.mjs +1 -0
- package/scripts/run-tests.ts +1 -0
- package/server.json +2 -2
- package/dist/tools/disassembler.js +0 -478
- /package/dist/tools/{symbolRegistry.js → translation/symbolRegistry.js} +0 -0
package/mcp/tools.json
CHANGED
|
@@ -8125,147 +8125,266 @@
|
|
|
8125
8125
|
"description": "Keyboard buffer injection (cross-platform) and joystick simulation (VICE only).",
|
|
8126
8126
|
"inputSchema": {
|
|
8127
8127
|
"type": "object",
|
|
8128
|
-
"
|
|
8129
|
-
|
|
8128
|
+
"properties": {
|
|
8129
|
+
"op": {
|
|
8130
|
+
"type": "string",
|
|
8131
|
+
"enum": [
|
|
8132
|
+
"write_text",
|
|
8133
|
+
"key",
|
|
8134
|
+
"joystick"
|
|
8135
|
+
],
|
|
8136
|
+
"description": "Selects the operation."
|
|
8137
|
+
},
|
|
8138
|
+
"text": {
|
|
8139
|
+
"type": "string",
|
|
8140
|
+
"description": "Text to type. Use {RETURN}, {CLR}, {F1}…{F8}, {UP/DOWN/LEFT/RIGHT}, colour names, etc.",
|
|
8141
|
+
"minLength": 1,
|
|
8142
|
+
"maxLength": 512
|
|
8143
|
+
},
|
|
8144
|
+
"delayMs": {
|
|
8145
|
+
"type": [
|
|
8146
|
+
"integer",
|
|
8147
|
+
"null"
|
|
8148
|
+
],
|
|
8149
|
+
"description": "Delay in ms after sending (default 0).",
|
|
8150
|
+
"minimum": 0,
|
|
8151
|
+
"maximum": 10000,
|
|
8152
|
+
"default": 0
|
|
8153
|
+
},
|
|
8154
|
+
"key": {
|
|
8155
|
+
"type": "string",
|
|
8156
|
+
"description": "Key to press: a printable character, or a PETSCII token name (RETURN, F1…F8, UP, etc.).",
|
|
8157
|
+
"minLength": 1,
|
|
8158
|
+
"maxLength": 32
|
|
8159
|
+
},
|
|
8160
|
+
"durationMs": {
|
|
8161
|
+
"type": [
|
|
8162
|
+
"integer",
|
|
8163
|
+
"null"
|
|
8164
|
+
],
|
|
8165
|
+
"description": "Delay in ms after each queued key press before the next press (default 0 = no delay).",
|
|
8166
|
+
"minimum": 0,
|
|
8167
|
+
"maximum": 5000,
|
|
8168
|
+
"default": 0
|
|
8169
|
+
},
|
|
8170
|
+
"count": {
|
|
8171
|
+
"type": [
|
|
8172
|
+
"integer",
|
|
8173
|
+
"null"
|
|
8174
|
+
],
|
|
8175
|
+
"description": "Number of times to press the key (default 1).",
|
|
8176
|
+
"minimum": 1,
|
|
8177
|
+
"maximum": 100,
|
|
8178
|
+
"default": 1
|
|
8179
|
+
},
|
|
8180
|
+
"port": {
|
|
8181
|
+
"type": "integer",
|
|
8182
|
+
"description": "Joystick port (1 = $DC01, 2 = $DC00).",
|
|
8183
|
+
"minimum": 1,
|
|
8184
|
+
"maximum": 2
|
|
8185
|
+
},
|
|
8186
|
+
"controls": {
|
|
8187
|
+
"type": "array",
|
|
8188
|
+
"description": "List of controls to activate simultaneously.",
|
|
8189
|
+
"items": {
|
|
8190
|
+
"type": "string",
|
|
8191
|
+
"description": "Control to activate.",
|
|
8192
|
+
"enum": [
|
|
8193
|
+
"up",
|
|
8194
|
+
"down",
|
|
8195
|
+
"left",
|
|
8196
|
+
"right",
|
|
8197
|
+
"fire"
|
|
8198
|
+
]
|
|
8199
|
+
},
|
|
8200
|
+
"minItems": 0
|
|
8201
|
+
},
|
|
8202
|
+
"action": {
|
|
8203
|
+
"type": "string",
|
|
8204
|
+
"description": "press = hold until a release call; release = restore all bits; tap = press then release after durationMs.",
|
|
8205
|
+
"enum": [
|
|
8206
|
+
"press",
|
|
8207
|
+
"release",
|
|
8208
|
+
"tap"
|
|
8209
|
+
]
|
|
8210
|
+
}
|
|
8211
|
+
},
|
|
8212
|
+
"required": [
|
|
8213
|
+
"op"
|
|
8214
|
+
],
|
|
8215
|
+
"description": "Input operations: write_text, key, joystick.\n\nOperations:\n- write_text: Send a text string to the keyboard buffer, with PETSCII token expansion. Required inputs: text. Optional inputs: delayMs.\n- key: Tap a single key or hold it for a duration. Required inputs: key. Optional inputs: durationMs, count.\n- joystick: Simulate joystick input by writing directly to CIA1 Port A/B registers. Required inputs: port, controls, action. Optional inputs: durationMs.",
|
|
8216
|
+
"additionalProperties": false,
|
|
8217
|
+
"x-c64bridge-operations": [
|
|
8130
8218
|
{
|
|
8131
|
-
"
|
|
8219
|
+
"op": "write_text",
|
|
8132
8220
|
"description": "Send a text string to the keyboard buffer, with PETSCII token expansion.",
|
|
8133
|
-
"properties": {
|
|
8134
|
-
"op": {
|
|
8135
|
-
"const": "write_text"
|
|
8136
|
-
},
|
|
8137
|
-
"text": {
|
|
8138
|
-
"type": "string",
|
|
8139
|
-
"description": "Text to type. Use {RETURN}, {CLR}, {F1}…{F8}, {UP/DOWN/LEFT/RIGHT}, colour names, etc.",
|
|
8140
|
-
"minLength": 1,
|
|
8141
|
-
"maxLength": 512
|
|
8142
|
-
},
|
|
8143
|
-
"delayMs": {
|
|
8144
|
-
"type": [
|
|
8145
|
-
"integer",
|
|
8146
|
-
"null"
|
|
8147
|
-
],
|
|
8148
|
-
"description": "Delay in ms after sending (default 0).",
|
|
8149
|
-
"minimum": 0,
|
|
8150
|
-
"maximum": 10000,
|
|
8151
|
-
"default": 0
|
|
8152
|
-
}
|
|
8153
|
-
},
|
|
8154
8221
|
"required": [
|
|
8155
|
-
"op",
|
|
8156
8222
|
"text"
|
|
8157
8223
|
],
|
|
8158
|
-
"
|
|
8224
|
+
"optional": [
|
|
8225
|
+
"delayMs"
|
|
8226
|
+
],
|
|
8227
|
+
"inputSchema": {
|
|
8228
|
+
"type": "object",
|
|
8229
|
+
"description": "Send a text string to the keyboard buffer, with PETSCII token expansion.",
|
|
8230
|
+
"properties": {
|
|
8231
|
+
"op": {
|
|
8232
|
+
"const": "write_text"
|
|
8233
|
+
},
|
|
8234
|
+
"text": {
|
|
8235
|
+
"type": "string",
|
|
8236
|
+
"description": "Text to type. Use {RETURN}, {CLR}, {F1}…{F8}, {UP/DOWN/LEFT/RIGHT}, colour names, etc.",
|
|
8237
|
+
"minLength": 1,
|
|
8238
|
+
"maxLength": 512
|
|
8239
|
+
},
|
|
8240
|
+
"delayMs": {
|
|
8241
|
+
"type": [
|
|
8242
|
+
"integer",
|
|
8243
|
+
"null"
|
|
8244
|
+
],
|
|
8245
|
+
"description": "Delay in ms after sending (default 0).",
|
|
8246
|
+
"minimum": 0,
|
|
8247
|
+
"maximum": 10000,
|
|
8248
|
+
"default": 0
|
|
8249
|
+
}
|
|
8250
|
+
},
|
|
8251
|
+
"required": [
|
|
8252
|
+
"op",
|
|
8253
|
+
"text"
|
|
8254
|
+
],
|
|
8255
|
+
"additionalProperties": false
|
|
8256
|
+
}
|
|
8159
8257
|
},
|
|
8160
8258
|
{
|
|
8161
|
-
"
|
|
8259
|
+
"op": "key",
|
|
8162
8260
|
"description": "Tap a single key or hold it for a duration.",
|
|
8163
|
-
"properties": {
|
|
8164
|
-
"op": {
|
|
8165
|
-
"const": "key"
|
|
8166
|
-
},
|
|
8167
|
-
"key": {
|
|
8168
|
-
"type": "string",
|
|
8169
|
-
"description": "Key to press: a printable character, or a PETSCII token name (RETURN, F1…F8, UP, etc.).",
|
|
8170
|
-
"minLength": 1,
|
|
8171
|
-
"maxLength": 32
|
|
8172
|
-
},
|
|
8173
|
-
"durationMs": {
|
|
8174
|
-
"type": [
|
|
8175
|
-
"integer",
|
|
8176
|
-
"null"
|
|
8177
|
-
],
|
|
8178
|
-
"description": "Delay in ms after each queued key press before the next press (default 0 = no delay).",
|
|
8179
|
-
"minimum": 0,
|
|
8180
|
-
"maximum": 5000,
|
|
8181
|
-
"default": 0
|
|
8182
|
-
},
|
|
8183
|
-
"count": {
|
|
8184
|
-
"type": [
|
|
8185
|
-
"integer",
|
|
8186
|
-
"null"
|
|
8187
|
-
],
|
|
8188
|
-
"description": "Number of times to press the key (default 1).",
|
|
8189
|
-
"minimum": 1,
|
|
8190
|
-
"maximum": 100,
|
|
8191
|
-
"default": 1
|
|
8192
|
-
}
|
|
8193
|
-
},
|
|
8194
8261
|
"required": [
|
|
8195
|
-
"op",
|
|
8196
8262
|
"key"
|
|
8197
8263
|
],
|
|
8198
|
-
"
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
"
|
|
8203
|
-
|
|
8204
|
-
"
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
"
|
|
8210
|
-
"minimum": 1,
|
|
8211
|
-
"maximum": 2
|
|
8212
|
-
},
|
|
8213
|
-
"controls": {
|
|
8214
|
-
"type": "array",
|
|
8215
|
-
"description": "List of controls to activate simultaneously.",
|
|
8216
|
-
"items": {
|
|
8264
|
+
"optional": [
|
|
8265
|
+
"durationMs",
|
|
8266
|
+
"count"
|
|
8267
|
+
],
|
|
8268
|
+
"inputSchema": {
|
|
8269
|
+
"type": "object",
|
|
8270
|
+
"description": "Tap a single key or hold it for a duration.",
|
|
8271
|
+
"properties": {
|
|
8272
|
+
"op": {
|
|
8273
|
+
"const": "key"
|
|
8274
|
+
},
|
|
8275
|
+
"key": {
|
|
8217
8276
|
"type": "string",
|
|
8218
|
-
"description": "
|
|
8219
|
-
"
|
|
8220
|
-
|
|
8221
|
-
"down",
|
|
8222
|
-
"left",
|
|
8223
|
-
"right",
|
|
8224
|
-
"fire"
|
|
8225
|
-
]
|
|
8277
|
+
"description": "Key to press: a printable character, or a PETSCII token name (RETURN, F1…F8, UP, etc.).",
|
|
8278
|
+
"minLength": 1,
|
|
8279
|
+
"maxLength": 32
|
|
8226
8280
|
},
|
|
8227
|
-
"
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
"
|
|
8234
|
-
"
|
|
8235
|
-
"
|
|
8236
|
-
|
|
8281
|
+
"durationMs": {
|
|
8282
|
+
"type": [
|
|
8283
|
+
"integer",
|
|
8284
|
+
"null"
|
|
8285
|
+
],
|
|
8286
|
+
"description": "Delay in ms after each queued key press before the next press (default 0 = no delay).",
|
|
8287
|
+
"minimum": 0,
|
|
8288
|
+
"maximum": 5000,
|
|
8289
|
+
"default": 0
|
|
8290
|
+
},
|
|
8291
|
+
"count": {
|
|
8292
|
+
"type": [
|
|
8293
|
+
"integer",
|
|
8294
|
+
"null"
|
|
8295
|
+
],
|
|
8296
|
+
"description": "Number of times to press the key (default 1).",
|
|
8297
|
+
"minimum": 1,
|
|
8298
|
+
"maximum": 100,
|
|
8299
|
+
"default": 1
|
|
8300
|
+
}
|
|
8237
8301
|
},
|
|
8238
|
-
"
|
|
8239
|
-
"
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
},
|
|
8302
|
+
"required": [
|
|
8303
|
+
"op",
|
|
8304
|
+
"key"
|
|
8305
|
+
],
|
|
8306
|
+
"additionalProperties": false
|
|
8307
|
+
}
|
|
8308
|
+
},
|
|
8309
|
+
{
|
|
8310
|
+
"op": "joystick",
|
|
8311
|
+
"description": "Simulate joystick input by writing directly to CIA1 Port A/B registers.",
|
|
8249
8312
|
"required": [
|
|
8250
|
-
"op",
|
|
8251
8313
|
"port",
|
|
8252
8314
|
"controls",
|
|
8253
8315
|
"action"
|
|
8254
8316
|
],
|
|
8255
|
-
"
|
|
8317
|
+
"optional": [
|
|
8318
|
+
"durationMs"
|
|
8319
|
+
],
|
|
8320
|
+
"inputSchema": {
|
|
8321
|
+
"type": "object",
|
|
8322
|
+
"description": "Simulate joystick input by writing directly to CIA1 Port A/B registers.",
|
|
8323
|
+
"properties": {
|
|
8324
|
+
"op": {
|
|
8325
|
+
"const": "joystick"
|
|
8326
|
+
},
|
|
8327
|
+
"port": {
|
|
8328
|
+
"type": "integer",
|
|
8329
|
+
"description": "Joystick port (1 = $DC01, 2 = $DC00).",
|
|
8330
|
+
"minimum": 1,
|
|
8331
|
+
"maximum": 2
|
|
8332
|
+
},
|
|
8333
|
+
"controls": {
|
|
8334
|
+
"type": "array",
|
|
8335
|
+
"description": "List of controls to activate simultaneously.",
|
|
8336
|
+
"items": {
|
|
8337
|
+
"type": "string",
|
|
8338
|
+
"description": "Control to activate.",
|
|
8339
|
+
"enum": [
|
|
8340
|
+
"up",
|
|
8341
|
+
"down",
|
|
8342
|
+
"left",
|
|
8343
|
+
"right",
|
|
8344
|
+
"fire"
|
|
8345
|
+
]
|
|
8346
|
+
},
|
|
8347
|
+
"minItems": 0
|
|
8348
|
+
},
|
|
8349
|
+
"action": {
|
|
8350
|
+
"type": "string",
|
|
8351
|
+
"description": "press = hold until a release call; release = restore all bits; tap = press then release after durationMs.",
|
|
8352
|
+
"enum": [
|
|
8353
|
+
"press",
|
|
8354
|
+
"release",
|
|
8355
|
+
"tap"
|
|
8356
|
+
]
|
|
8357
|
+
},
|
|
8358
|
+
"durationMs": {
|
|
8359
|
+
"type": [
|
|
8360
|
+
"integer",
|
|
8361
|
+
"null"
|
|
8362
|
+
],
|
|
8363
|
+
"description": "Duration to hold for tap action in ms (default 80).",
|
|
8364
|
+
"minimum": 10,
|
|
8365
|
+
"maximum": 5000,
|
|
8366
|
+
"default": 80
|
|
8367
|
+
}
|
|
8368
|
+
},
|
|
8369
|
+
"required": [
|
|
8370
|
+
"op",
|
|
8371
|
+
"port",
|
|
8372
|
+
"controls",
|
|
8373
|
+
"action"
|
|
8374
|
+
],
|
|
8375
|
+
"additionalProperties": false
|
|
8376
|
+
}
|
|
8256
8377
|
}
|
|
8257
|
-
]
|
|
8258
|
-
"discriminator": {
|
|
8259
|
-
"propertyName": "op"
|
|
8260
|
-
}
|
|
8378
|
+
]
|
|
8261
8379
|
},
|
|
8262
8380
|
"_meta": {
|
|
8263
8381
|
"domain": "input",
|
|
8264
8382
|
"summary": "Types text, taps keys, and simulates joystick movements.",
|
|
8265
8383
|
"lifecycle": "request-response",
|
|
8266
8384
|
"resources": [
|
|
8267
|
-
"c64://
|
|
8268
|
-
"c64://
|
|
8385
|
+
"c64://guide/bootstrap",
|
|
8386
|
+
"c64://memory/map",
|
|
8387
|
+
"c64://io/cia/spec"
|
|
8269
8388
|
],
|
|
8270
8389
|
"prompts": [],
|
|
8271
8390
|
"examples": [
|
package/mcp.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c64bridge",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"mcpName": "io.github.chrisgleissner/c64bridge",
|
|
5
5
|
"description": "C64 Bridge MCP server for Commodore 64 Ultimate hardware and VICE emulator control",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"mcp": "node scripts/invoke-bun.mjs src/mcp-server.ts",
|
|
19
19
|
"mcp:node": "node dist/mcp-server.js",
|
|
20
20
|
"mcp:build": "npm run build && node dist/mcp-server.js",
|
|
21
|
-
"build": "node scripts/prebuild.mjs && tsc -p tsconfig.json && node scripts/postbuild.mjs && node scripts/invoke-bun.mjs scripts/update-readme.ts && node scripts/invoke-bun.mjs scripts/generate-mcp-interface.ts",
|
|
21
|
+
"build": "VICE_VISIBLE=false node scripts/prebuild.mjs && VICE_VISIBLE=false tsc -p tsconfig.json && VICE_VISIBLE=false node scripts/postbuild.mjs && VICE_VISIBLE=false node scripts/invoke-bun.mjs scripts/update-readme.ts && VICE_VISIBLE=false node scripts/invoke-bun.mjs scripts/generate-mcp-interface.ts",
|
|
22
22
|
"lint": "npm run check",
|
|
23
23
|
"test": "node scripts/invoke-bun.mjs scripts/run-tests.ts",
|
|
24
24
|
"test:node": "node scripts/run-tests.mjs",
|
package/scripts/c64-cli.mjs
CHANGED
|
@@ -18,7 +18,7 @@ async function loadCoreModules() {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
if (typeof globalThis.Bun !== "undefined") {
|
|
21
|
-
({ basicToPrg } = await import("../src/
|
|
21
|
+
({ basicToPrg } = await import("../src/tools/translation/basicTokenizer.ts"));
|
|
22
22
|
({ loadConfig } = await import("../src/config.ts"));
|
|
23
23
|
({ C64Client } = await import("../src/c64Client.ts"));
|
|
24
24
|
return;
|
|
@@ -26,7 +26,7 @@ async function loadCoreModules() {
|
|
|
26
26
|
|
|
27
27
|
const distPath = resolve(projectRoot, "dist");
|
|
28
28
|
try {
|
|
29
|
-
({ basicToPrg } = await import(pathToFileURL(resolve(distPath, "
|
|
29
|
+
({ basicToPrg } = await import(pathToFileURL(resolve(distPath, "tools/translation/basicTokenizer.js")).href));
|
|
30
30
|
({ loadConfig } = await import(pathToFileURL(resolve(distPath, "config.js")).href));
|
|
31
31
|
({ C64Client } = await import(pathToFileURL(resolve(distPath, "c64Client.js")).href));
|
|
32
32
|
} catch (error) {
|
package/scripts/run-coverage.mjs
CHANGED
|
@@ -162,7 +162,8 @@ async function listRepoTestFiles(root) {
|
|
|
162
162
|
return files;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
function runCoverageLeg(leg, legDir, label, files) {
|
|
165
|
+
async function runCoverageLeg(leg, legDir, label, files) {
|
|
166
|
+
const knownTempFiles = new Set(await listCoverageTempFiles(coverageDir));
|
|
166
167
|
return new Promise((resolve, reject) => {
|
|
167
168
|
const outputPath = path.join(legDir, `${label}.lcov.info`);
|
|
168
169
|
const args = [runner, "scripts/run-tests.ts", "--coverage", ...leg.args, ...files];
|
|
@@ -178,7 +179,7 @@ function runCoverageLeg(leg, legDir, label, files) {
|
|
|
178
179
|
return;
|
|
179
180
|
}
|
|
180
181
|
try {
|
|
181
|
-
await
|
|
182
|
+
await copyCoverageOutput(coverageDir, outputPath, knownTempFiles);
|
|
182
183
|
resolve(outputPath);
|
|
183
184
|
} catch (error) {
|
|
184
185
|
reject(error);
|
|
@@ -187,6 +188,56 @@ function runCoverageLeg(leg, legDir, label, files) {
|
|
|
187
188
|
});
|
|
188
189
|
}
|
|
189
190
|
|
|
191
|
+
export async function copyCoverageOutput(sourceDir, outputPath, knownTempFiles = new Set()) {
|
|
192
|
+
const stablePath = path.join(sourceDir, "lcov.info");
|
|
193
|
+
try {
|
|
194
|
+
await fs.copyFile(stablePath, outputPath);
|
|
195
|
+
return outputPath;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
if (!isNodeErrorCode(error, "ENOENT")) {
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const tempFiles = await listCoverageTempFiles(sourceDir);
|
|
203
|
+
const newTempFiles = tempFiles.filter((filePath) => !knownTempFiles.has(filePath));
|
|
204
|
+
if (newTempFiles.length === 0) {
|
|
205
|
+
throw new Error(`Coverage run completed but no LCOV report was produced in ${sourceDir}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const newest = await newestFile(newTempFiles);
|
|
209
|
+
await fs.copyFile(newest, outputPath);
|
|
210
|
+
return outputPath;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function listCoverageTempFiles(dir) {
|
|
214
|
+
let entries;
|
|
215
|
+
try {
|
|
216
|
+
entries = await fs.readdir(dir);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
if (isNodeErrorCode(error, "ENOENT")) {
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
return entries
|
|
224
|
+
.filter((entry) => /^\.lcov\.info\.[^.]+\.tmp$/.test(entry))
|
|
225
|
+
.map((entry) => path.join(dir, entry));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async function newestFile(filePaths) {
|
|
229
|
+
const stats = await Promise.all(filePaths.map(async (filePath) => ({
|
|
230
|
+
filePath,
|
|
231
|
+
mtimeMs: (await fs.stat(filePath)).mtimeMs,
|
|
232
|
+
})));
|
|
233
|
+
stats.sort((a, b) => b.mtimeMs - a.mtimeMs || a.filePath.localeCompare(b.filePath));
|
|
234
|
+
return stats[0].filePath;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function isNodeErrorCode(error, code) {
|
|
238
|
+
return Boolean(error && typeof error === "object" && error.code === code);
|
|
239
|
+
}
|
|
240
|
+
|
|
190
241
|
async function readReport(filePath) {
|
|
191
242
|
const text = await fs.readFile(filePath, "utf8");
|
|
192
243
|
return parseReport(text);
|
|
@@ -313,4 +364,4 @@ function globToRegExp(glob) {
|
|
|
313
364
|
}
|
|
314
365
|
regex += "$";
|
|
315
366
|
return new RegExp(regex);
|
|
316
|
-
}
|
|
367
|
+
}
|
package/scripts/run-tests.mjs
CHANGED
package/scripts/run-tests.ts
CHANGED
|
@@ -142,6 +142,7 @@ export function buildMatrixEnv(
|
|
|
142
142
|
const env: Record<string, string> = { ...envSource } as Record<string, string>;
|
|
143
143
|
env.C64_MODE = platform;
|
|
144
144
|
env.C64_TEST_TARGET = target === "device" ? "real" : "mock";
|
|
145
|
+
env.VICE_VISIBLE = "false";
|
|
145
146
|
|
|
146
147
|
if (platform === "vice") {
|
|
147
148
|
const useViceMock = target !== "device";
|
package/server.json
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
10
|
"websiteUrl": "https://github.com/chrisgleissner/c64bridge",
|
|
11
|
-
"version": "0.9.
|
|
11
|
+
"version": "0.9.2",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "c64bridge",
|
|
16
|
-
"version": "0.9.
|
|
16
|
+
"version": "0.9.2",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
},
|