c64bridge 0.8.0 → 0.9.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/.github/prompts/steer.prompt.md +55 -0
- package/AGENTS.md +9 -7
- package/README.md +139 -95
- package/data/embeddings_asm.json +1 -1
- package/data/embeddings_basic.json +1 -1
- package/data/embeddings_hardware.json +1 -1
- package/data/embeddings_mixed.json +1 -1
- package/data/embeddings_other.json +1 -1
- package/data/graphics/petscii-style-guide.md +4 -4
- package/data/graphics/sprite-charset-best-practices.md +9 -9
- package/data/vice/vice-binary-monitor-spec.md +921 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/device.js +86 -10
- package/dist/mcp-server.js +1 -1
- package/dist/prompts/registry.js +27 -25
- package/dist/rag/knowledgeIndex.js +112 -79
- package/dist/rag/resourceUris.js +93 -0
- package/dist/tools/audio.js +11 -11
- package/dist/tools/debug.js +1 -1
- package/dist/tools/developer.js +13 -13
- package/dist/tools/graphics.js +10 -10
- package/dist/tools/machineControl.js +5 -5
- package/dist/tools/memory.js +19 -11
- package/dist/tools/meta/index.js +1 -1
- package/dist/tools/printer.js +11 -12
- package/dist/tools/programRunners.js +16 -16
- package/dist/tools/rag.js +9 -9
- package/dist/tools/registry/config.js +1 -1
- package/dist/tools/registry/disk.js +1 -1
- package/dist/tools/registry/drive.js +1 -1
- package/dist/tools/registry/extract.js +1 -1
- package/dist/tools/registry/graphics.js +1 -1
- package/dist/tools/registry/memory.js +1 -1
- package/dist/tools/registry/platform.js +1 -1
- package/dist/tools/registry/printer.js +1 -1
- package/dist/tools/registry/program.js +1 -1
- package/dist/tools/registry/rag.js +1 -1
- package/dist/tools/registry/sound.js +1 -1
- package/dist/tools/registry/stream.js +1 -1
- package/dist/tools/registry/system.js +1 -1
- package/dist/tools/storage.js +15 -15
- package/dist/tools/streaming.js +3 -3
- package/dist/tools/types.js +41 -4
- package/dist/tools/vice.js +2 -5
- package/dist/vice/process.js +79 -2
- package/dist/vice/readiness.js +35 -0
- package/dist/vice/smokeOptions.js +44 -0
- package/dist/viceRunner.js +2 -0
- package/doc/developer.md +10 -2
- package/doc/plans/prompts/README.md +7 -7
- package/mcp/prompts.json +42 -59
- package/mcp/protocol-examples.json +2 -2
- package/mcp/resources.json +179 -166
- package/mcp/schemas/c64_config.schema.json +109 -326
- package/mcp/schemas/c64_debug.schema.json +158 -337
- package/mcp/schemas/c64_disk.schema.json +180 -262
- package/mcp/schemas/c64_drive.schema.json +31 -111
- package/mcp/schemas/c64_extract.schema.json +193 -291
- package/mcp/schemas/c64_graphics.schema.json +208 -308
- package/mcp/schemas/c64_memory.schema.json +94 -144
- package/mcp/schemas/c64_printer.schema.json +151 -205
- package/mcp/schemas/c64_program.schema.json +229 -367
- package/mcp/schemas/c64_rag.schema.json +25 -59
- package/mcp/schemas/c64_select_backend.schema.json +19 -26
- package/mcp/schemas/c64_sound.schema.json +346 -622
- package/mcp/schemas/c64_stream.schema.json +25 -54
- package/mcp/schemas/c64_system.schema.json +79 -212
- package/mcp/schemas/c64_vice.schema.json +24 -55
- package/mcp/server.json +1 -1
- package/mcp/tools.json +1935 -3443
- package/mcp.json +10 -9
- package/package.json +20 -15
- package/scripts/fetch-external-sources.mjs +1 -2
- package/scripts/prepare-release.mjs +59 -2
- package/scripts/run-coverage.mjs +26 -1
- package/scripts/run-tests.mjs +2 -2
- package/scripts/run-tests.ts +273 -52
- package/scripts/update-readme.ts +54 -2
- package/server.json +94 -0
package/mcp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c64bridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Stdio-based Model Context Protocol (MCP) server that bridges Commodore 64 Ultimate hardware with AI agents.",
|
|
5
5
|
"entry": "dist/index.js",
|
|
6
6
|
"type": "stdio",
|
|
@@ -9,11 +9,14 @@
|
|
|
9
9
|
"mcp-server",
|
|
10
10
|
"model context protocol",
|
|
11
11
|
"openai",
|
|
12
|
-
"
|
|
13
|
-
"commodore64",
|
|
14
|
-
"commodore 64",
|
|
12
|
+
"commodore",
|
|
15
13
|
"c64",
|
|
16
14
|
"c64u",
|
|
15
|
+
"commodore64",
|
|
16
|
+
"commodore 64",
|
|
17
|
+
"commodore 64 ultimate",
|
|
18
|
+
"ultimate64",
|
|
19
|
+
"ultimate 64",
|
|
17
20
|
"sid",
|
|
18
21
|
"basic",
|
|
19
22
|
"assembly",
|
|
@@ -22,9 +25,7 @@
|
|
|
22
25
|
"retrogaming",
|
|
23
26
|
"vintage computing",
|
|
24
27
|
"hardware integration",
|
|
25
|
-
"c64 development"
|
|
26
|
-
"commodore 64 ultimate",
|
|
27
|
-
"ultimate 64"
|
|
28
|
+
"c64 development"
|
|
28
29
|
],
|
|
29
30
|
"env": {
|
|
30
31
|
"LOG_LEVEL": {
|
|
@@ -112,11 +113,11 @@
|
|
|
112
113
|
"default": "120000000"
|
|
113
114
|
},
|
|
114
115
|
"VICE_BINARY": {
|
|
115
|
-
"description": "VICE binary to launch for managed emulator sessions and audio capture",
|
|
116
|
+
"description": "VICE binary to launch for managed emulator sessions and audio capture; automatic search is used only when this override is missing or invalid",
|
|
116
117
|
"default": "x64sc"
|
|
117
118
|
},
|
|
118
119
|
"VICE_DIRECTORY": {
|
|
119
|
-
"description": "Override the VICE resource directory used for ROM and UI asset discovery",
|
|
120
|
+
"description": "Override the VICE resource directory used for ROM and UI asset discovery; automatic search is used only when this override is missing or invalid",
|
|
120
121
|
"default": "auto-detect"
|
|
121
122
|
},
|
|
122
123
|
"VICE_HOST": {
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c64bridge",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"mcpName": "io.github.chrisgleissner/c64bridge",
|
|
5
|
+
"description": "C64 Bridge MCP server for Commodore 64 Ultimate hardware and VICE emulator control",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "dist/index.js",
|
|
7
8
|
"packageManager": "bun@1.3.1",
|
|
@@ -21,9 +22,11 @@
|
|
|
21
22
|
"lint": "npm run check",
|
|
22
23
|
"test": "node scripts/invoke-bun.mjs scripts/run-tests.ts",
|
|
23
24
|
"test:node": "node scripts/run-tests.mjs",
|
|
25
|
+
"test:vice:mock": "npm run test -- --platform=vice --target=mock",
|
|
26
|
+
"test:vice:device": "FORCE_XVFB=1 VICE_VISIBLE=false VICE_WARP=true npm run test -- --platform=vice --target=device",
|
|
24
27
|
"coverage": "node scripts/run-coverage.mjs",
|
|
25
28
|
"coverage:single": "node scripts/invoke-bun.mjs scripts/run-tests.ts --coverage",
|
|
26
|
-
"test:matrix": "npm run test -- --platform=c64u --target=mock && npm run test
|
|
29
|
+
"test:matrix": "npm run test -- --platform=c64u --target=mock && npm run test:vice:mock && npm run test:vice:device",
|
|
27
30
|
"mcp:generate": "node scripts/invoke-bun.mjs scripts/generate-mcp-interface.ts",
|
|
28
31
|
"check:package": "node scripts/check-package.mjs",
|
|
29
32
|
"check:run-local": "bash scripts/run-mcp-check.sh local 5",
|
|
@@ -39,7 +42,8 @@
|
|
|
39
42
|
"changelog:generate": "node scripts/generate-changelog.mjs",
|
|
40
43
|
"release:prepare": "node scripts/prepare-release.mjs",
|
|
41
44
|
"compare:rest": "node scripts/compare-rest-apis.mjs",
|
|
42
|
-
"vice:smoke": "node scripts/invoke-bun.mjs test/vice/viceSmokeTest.ts"
|
|
45
|
+
"vice:smoke": "node scripts/invoke-bun.mjs test/vice/viceSmokeTest.ts",
|
|
46
|
+
"vice:smoke:visible": "node scripts/invoke-bun.mjs test/vice/viceSmokeTest.ts --visible-demo"
|
|
43
47
|
},
|
|
44
48
|
"keywords": [
|
|
45
49
|
"mcp",
|
|
@@ -58,27 +62,28 @@
|
|
|
58
62
|
"node": ">=24"
|
|
59
63
|
},
|
|
60
64
|
"dependencies": {
|
|
61
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
62
|
-
"axios": "^1.
|
|
65
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
66
|
+
"axios": "^1.16.0",
|
|
63
67
|
"date-fns": "^4.1.0",
|
|
64
|
-
"fastify": "^5.
|
|
65
|
-
"jimp": "^1.6.
|
|
66
|
-
"meyda": "^5.6.
|
|
67
|
-
"octokit": "^5.0.
|
|
68
|
-
"pitchfinder": "^2.
|
|
68
|
+
"fastify": "^5.8.5",
|
|
69
|
+
"jimp": "^1.6.1",
|
|
70
|
+
"meyda": "^5.6.3",
|
|
71
|
+
"octokit": "^5.0.5",
|
|
72
|
+
"pitchfinder": "^2.3.4",
|
|
69
73
|
"reflect-metadata": "^0.2.2",
|
|
70
|
-
"yaml": "^2.
|
|
74
|
+
"yaml": "^2.8.4"
|
|
71
75
|
},
|
|
72
76
|
"optionalDependencies": {
|
|
73
77
|
"naudiodon": "^2.3.6"
|
|
74
78
|
},
|
|
75
79
|
"devDependencies": {
|
|
76
|
-
"@types/node": "^
|
|
77
|
-
"
|
|
78
|
-
"typescript": "^
|
|
80
|
+
"@types/node": "^25.6.0",
|
|
81
|
+
"tsx": "^4.21.0",
|
|
82
|
+
"typescript": "^6.0.3"
|
|
79
83
|
},
|
|
80
84
|
"files": [
|
|
81
85
|
"mcp.json",
|
|
86
|
+
"server.json",
|
|
82
87
|
"AGENTS.md",
|
|
83
88
|
"LICENSE",
|
|
84
89
|
"README.md",
|
|
@@ -7,8 +7,7 @@ import { register } from 'node:module';
|
|
|
7
7
|
async function main() {
|
|
8
8
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
9
|
const projectRoot = path.resolve(__dirname, '..');
|
|
10
|
-
|
|
11
|
-
register(tsNodeLoader, pathToFileURL(projectRoot));
|
|
10
|
+
register("tsx/esm", pathToFileURL(projectRoot));
|
|
12
11
|
const { fetchFromCsv } = await import('../src/rag/externalFetcher.ts');
|
|
13
12
|
// Resolve sources.csv from env, dist/rag, or src/rag (in that order)
|
|
14
13
|
let csvPath = process.env.RAG_SOURCES_CSV;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { access, readFile, writeFile } from 'node:fs/promises';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
|
|
@@ -16,6 +16,27 @@ const updateJsonFile = async (relativePath, updater) => {
|
|
|
16
16
|
await writeFile(filePath, JSON.stringify(updated, null, 2) + '\n');
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
const fileExists = async (relativePath) => {
|
|
20
|
+
try {
|
|
21
|
+
await access(path.resolve(relativePath));
|
|
22
|
+
return true;
|
|
23
|
+
} catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const getRepositoryMetadata = (repository) => {
|
|
29
|
+
const url = typeof repository === 'string' ? repository : repository?.url;
|
|
30
|
+
if (!url) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
url,
|
|
36
|
+
source: url.includes('github.com') ? 'github' : undefined,
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
19
40
|
const normaliseVersion = (value) => value.replace(/^v/, '');
|
|
20
41
|
|
|
21
42
|
const isExactVersion = (value) => /^v?\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(value);
|
|
@@ -72,6 +93,42 @@ await updateJsonFile('mcp.json', async (data) => ({
|
|
|
72
93
|
version: newVersion,
|
|
73
94
|
}));
|
|
74
95
|
|
|
96
|
+
if (await fileExists('server.json')) {
|
|
97
|
+
await updateJsonFile('server.json', async (data) => {
|
|
98
|
+
const packages = Array.isArray(data.packages) ? [...data.packages] : [];
|
|
99
|
+
const primaryPackage = packages[0] ?? {
|
|
100
|
+
registryType: 'npm',
|
|
101
|
+
transport: {
|
|
102
|
+
type: 'stdio',
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
packages[0] = {
|
|
107
|
+
...primaryPackage,
|
|
108
|
+
identifier: pkg.name,
|
|
109
|
+
version: newVersion,
|
|
110
|
+
transport: primaryPackage.transport ?? {
|
|
111
|
+
type: 'stdio',
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const repository = getRepositoryMetadata(pkg.repository);
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
...data,
|
|
119
|
+
name: pkg.mcpName ?? data.name,
|
|
120
|
+
version: newVersion,
|
|
121
|
+
repository: repository
|
|
122
|
+
? {
|
|
123
|
+
...(data.repository ?? {}),
|
|
124
|
+
...repository,
|
|
125
|
+
}
|
|
126
|
+
: data.repository,
|
|
127
|
+
packages,
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
75
132
|
// Manifest generation removed (runtime discovery via MCP stdio)
|
|
76
133
|
|
|
77
134
|
// Update CHANGELOG.md from commits since last tag using Conventional Commits subjects.
|
|
@@ -88,4 +145,4 @@ if (skippedVersionBump && hasExistingChangelogEntry) {
|
|
|
88
145
|
}
|
|
89
146
|
|
|
90
147
|
console.log(`Release metadata updated to ${newVersion}.`);
|
|
91
|
-
console.log('Next steps: commit the changes,
|
|
148
|
+
console.log('Next steps: commit and push the changes, then create the release tag from GitHub once main is ready.');
|
package/scripts/run-coverage.mjs
CHANGED
|
@@ -13,6 +13,22 @@ const runner = path.join(repoRoot, "scripts", "invoke-bun.mjs");
|
|
|
13
13
|
const configPath = path.join(repoRoot, ".c8rc.json");
|
|
14
14
|
const testRoot = path.join(repoRoot, "test");
|
|
15
15
|
const DEFAULT_COVERAGE_SHARD_SIZE = 12;
|
|
16
|
+
const DEFAULT_VICE_MOCK_TEST_FILES = [
|
|
17
|
+
"test/device.test.mjs",
|
|
18
|
+
"test/viceIntegration.test.mjs",
|
|
19
|
+
"test/viceModule.test.mjs",
|
|
20
|
+
"test/groupedToolsShims.test.mjs",
|
|
21
|
+
"test/toolsTypes.test.mjs",
|
|
22
|
+
"test/platformRegistry.test.mjs",
|
|
23
|
+
"test/meta/program.test.mjs",
|
|
24
|
+
"test/mcpServerIntegration.test.mjs",
|
|
25
|
+
"test/c64Client.test.mjs",
|
|
26
|
+
"test/vice/viceSmokeTest.ts",
|
|
27
|
+
];
|
|
28
|
+
const DEFAULT_VICE_DEVICE_TEST_FILES = [
|
|
29
|
+
"test/device.test.mjs",
|
|
30
|
+
"test/vice/viceSmokeTest.ts",
|
|
31
|
+
];
|
|
16
32
|
|
|
17
33
|
const legs = [
|
|
18
34
|
{ name: "c64u-mock", args: ["--platform=c64u", "--target=mock"] },
|
|
@@ -50,11 +66,20 @@ export async function main() {
|
|
|
50
66
|
const allTestFiles = await listRepoTestFiles(testRoot);
|
|
51
67
|
const isolatedTestSet = new Set(isolatedTests);
|
|
52
68
|
const defaultTestFiles = allTestFiles.filter((f) => !isolatedTestSet.has(f));
|
|
53
|
-
const coverageBatches = buildCoverageBatches(defaultTestFiles, [...supplementalTests, ...isolatedTests], process.env);
|
|
54
69
|
for (const leg of legs) {
|
|
55
70
|
const legDir = path.join(coverageDir, "matrix", leg.name);
|
|
56
71
|
await fs.mkdir(legDir, { recursive: true });
|
|
57
72
|
|
|
73
|
+
const legDefaultFiles = leg.name === "vice-mock"
|
|
74
|
+
? DEFAULT_VICE_MOCK_TEST_FILES
|
|
75
|
+
: leg.name === "vice-device"
|
|
76
|
+
? DEFAULT_VICE_DEVICE_TEST_FILES
|
|
77
|
+
: defaultTestFiles;
|
|
78
|
+
const legSupplementalTests = leg.name.startsWith("vice")
|
|
79
|
+
? []
|
|
80
|
+
: [...supplementalTests, ...isolatedTests];
|
|
81
|
+
const coverageBatches = buildCoverageBatches(legDefaultFiles, legSupplementalTests, process.env);
|
|
82
|
+
|
|
58
83
|
const reports = [];
|
|
59
84
|
for (const batch of coverageBatches) {
|
|
60
85
|
reports.push(await runCoverageLeg(leg, legDir, batch.label, batch.files));
|
package/scripts/run-tests.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
export const DEFAULT_TARGET = "mock";
|
|
9
9
|
|
|
10
10
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
-
const
|
|
11
|
+
const tsLoader = "tsx/esm";
|
|
12
12
|
const { nodeArgs, target, explicitBaseUrl } = buildNodeTestArgs(process.argv.slice(2));
|
|
13
13
|
const defaultEmbeddingsDir = path.join(repoRoot, "artifacts", "test-embeddings");
|
|
14
14
|
if (!fs.existsSync(defaultEmbeddingsDir)) {
|
|
@@ -180,7 +180,7 @@ function isMainModule(moduleUrl) {
|
|
|
180
180
|
|
|
181
181
|
export function buildNodeTestArgs(args, root = repoRoot) {
|
|
182
182
|
const defaultTestFiles = listRepoTestFiles(path.join(root, "test"), root);
|
|
183
|
-
const nodeArgs = ["--import",
|
|
183
|
+
const nodeArgs = ["--import", tsLoader, "--test"];
|
|
184
184
|
let target = DEFAULT_TARGET;
|
|
185
185
|
let explicitBaseUrl = null;
|
|
186
186
|
let hasExplicitTestFiles = false;
|