c64bridge 0.8.1 → 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/.github/prompts/steer.prompt.md +55 -0
- package/AGENTS.md +9 -7
- package/README.md +192 -154
- 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 +938 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/c64Client.js +76 -2
- package/dist/device.js +129 -13
- package/dist/mcp-server.js +1 -1
- package/dist/prompts/registry.js +27 -25
- package/dist/rag/indexer.js +18 -8
- package/dist/rag/knowledgeIndex.js +112 -79
- package/dist/rag/resourceUris.js +93 -0
- package/dist/sidwaveCompiler.js +1 -1
- package/dist/{assemblyConverter.js → tools/assember.js} +10 -1
- package/dist/tools/audio.js +11 -11
- package/dist/{basicConverter.js → tools/basicTokenizer.js} +1 -1
- package/dist/tools/debug.js +159 -6
- package/dist/tools/developer.js +13 -13
- package/dist/tools/disassembler.js +478 -0
- package/dist/tools/graphics.js +10 -10
- package/dist/tools/input.js +338 -0
- package/dist/tools/machineControl.js +5 -5
- package/dist/tools/memory.js +336 -12
- package/dist/tools/meta/index.js +1 -1
- package/dist/tools/printer.js +11 -12
- package/dist/tools/programRunners.js +61 -22
- package/dist/tools/rag.js +9 -9
- package/dist/tools/registry/batch.js +167 -0
- 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 +102 -2
- package/dist/tools/registry/index.js +4 -0
- package/dist/tools/registry/input.js +2 -0
- package/dist/tools/registry/memory.js +62 -2
- 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/schema.js +4 -5
- package/dist/tools/storage.js +15 -15
- package/dist/tools/streaming.js +3 -3
- package/dist/tools/symbolRegistry.js +49 -0
- package/dist/tools/types.js +56 -4
- package/dist/tools/vice.js +2 -5
- package/dist/vice/process.js +120 -2
- package/dist/vice/readiness.js +35 -0
- package/dist/vice/smokeOptions.js +44 -0
- package/dist/vice/viceClient.js +5 -1
- package/dist/viceRunner.js +2 -0
- 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_batch.schema.json +53 -0
- package/mcp/schemas/c64_config.schema.json +525 -283
- package/mcp/schemas/c64_debug.schema.json +763 -304
- package/mcp/schemas/c64_disk.schema.json +499 -243
- package/mcp/schemas/c64_drive.schema.json +165 -90
- package/mcp/schemas/c64_extract.schema.json +533 -274
- package/mcp/schemas/c64_graphics.schema.json +607 -295
- package/mcp/schemas/c64_input.schema.json +136 -0
- package/mcp/schemas/c64_memory.schema.json +637 -128
- package/mcp/schemas/c64_printer.schema.json +393 -196
- package/mcp/schemas/c64_program.schema.json +699 -340
- package/mcp/schemas/c64_rag.schema.json +100 -54
- package/mcp/schemas/c64_select_backend.schema.json +49 -23
- package/mcp/schemas/c64_sound.schema.json +1092 -577
- package/mcp/schemas/c64_stream.schema.json +89 -47
- package/mcp/schemas/c64_system.schema.json +351 -185
- package/mcp/schemas/c64_vice.schema.json +85 -47
- package/mcp/server.json +1 -1
- package/mcp/tools.json +7299 -3346
- package/mcp.json +3 -3
- package/package.json +17 -14
- package/scripts/fetch-external-sources.mjs +1 -2
- package/scripts/run-coverage.mjs +33 -1
- package/scripts/run-tests.mjs +2 -2
- package/scripts/run-tests.ts +275 -52
- package/scripts/update-readme.ts +132 -3
- package/server.json +2 -2
package/scripts/update-readme.ts
CHANGED
|
@@ -142,6 +142,8 @@ type GroupedOperation = {
|
|
|
142
142
|
readonly op: string;
|
|
143
143
|
readonly description: string;
|
|
144
144
|
readonly required: readonly string[];
|
|
145
|
+
readonly optional: readonly string[];
|
|
146
|
+
readonly properties: Readonly<Record<string, JsonSchema | undefined>>;
|
|
145
147
|
readonly notes: readonly string[];
|
|
146
148
|
};
|
|
147
149
|
|
|
@@ -165,20 +167,91 @@ function toTableValue(values: readonly string[]): string {
|
|
|
165
167
|
return values.join(", ");
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
function formatInputName(name: string, schema?: JsonSchema): string {
|
|
171
|
+
const defaultSuffix = schema && Object.prototype.hasOwnProperty.call(schema, "default")
|
|
172
|
+
? `=${JSON.stringify(schema.default)}`
|
|
173
|
+
: "";
|
|
174
|
+
return `\`${name}${defaultSuffix}\``;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function formatInputs(names: readonly string[], properties: Readonly<Record<string, JsonSchema | undefined>>): string {
|
|
178
|
+
return toTableValue(names.map((name) => formatInputName(name, properties[name])));
|
|
179
|
+
}
|
|
180
|
+
|
|
168
181
|
function collectGroupedOperations(schema?: JsonSchema): readonly GroupedOperation[] {
|
|
169
182
|
if (!schema || !isObject(schema)) {
|
|
170
183
|
return [];
|
|
171
184
|
}
|
|
172
185
|
|
|
186
|
+
const metadataOperations = collectFromOperationMetadata(schema);
|
|
187
|
+
if (metadataOperations.length > 0) {
|
|
188
|
+
return metadataOperations;
|
|
189
|
+
}
|
|
190
|
+
|
|
173
191
|
const discriminator = (schema as JsonSchema & { discriminator?: { propertyName?: string } }).discriminator;
|
|
174
192
|
const variants = (schema as JsonSchema & { oneOf?: readonly JsonSchema[] }).oneOf;
|
|
175
193
|
|
|
176
|
-
if (
|
|
194
|
+
if (discriminator && discriminator.propertyName === "op" && Array.isArray(variants)) {
|
|
195
|
+
return collectFromVariantList(variants);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return collectFromFlattenedSchema(schema);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function collectFromOperationMetadata(schema: JsonSchema): readonly GroupedOperation[] {
|
|
202
|
+
const metadata = (schema as JsonSchema & {
|
|
203
|
+
readonly "x-c64bridge-operations"?: readonly unknown[];
|
|
204
|
+
})["x-c64bridge-operations"];
|
|
205
|
+
|
|
206
|
+
if (!Array.isArray(metadata)) {
|
|
177
207
|
return [];
|
|
178
208
|
}
|
|
179
209
|
|
|
180
210
|
const operations: GroupedOperation[] = [];
|
|
181
211
|
|
|
212
|
+
for (const entry of metadata) {
|
|
213
|
+
if (!isObject(entry)) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const opName = getString(entry.op);
|
|
218
|
+
if (!opName) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const inputSchema = isObject(entry.inputSchema) ? (entry.inputSchema as JsonSchema) : undefined;
|
|
223
|
+
const properties = (inputSchema?.properties ?? {}) as Record<string, JsonSchema | undefined>;
|
|
224
|
+
const requiredProps = Array.isArray(entry.required)
|
|
225
|
+
? entry.required.filter((name): name is string => typeof name === "string" && name !== "op")
|
|
226
|
+
: [];
|
|
227
|
+
const optionalProps = Array.isArray(entry.optional)
|
|
228
|
+
? entry.optional.filter((name): name is string => typeof name === "string" && name !== "op")
|
|
229
|
+
: Object.keys(properties).filter((name) => name !== "op" && !requiredProps.includes(name));
|
|
230
|
+
|
|
231
|
+
const notes: string[] = [];
|
|
232
|
+
const hasVerificationProperty = Object.keys(properties).some((name) =>
|
|
233
|
+
name.toLowerCase().startsWith("verify"),
|
|
234
|
+
);
|
|
235
|
+
if (hasVerificationProperty) {
|
|
236
|
+
notes.push("supports verify");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
operations.push({
|
|
240
|
+
op: opName,
|
|
241
|
+
description: getString(entry.description, `Operation ${opName}`),
|
|
242
|
+
required: requiredProps,
|
|
243
|
+
optional: optionalProps,
|
|
244
|
+
properties,
|
|
245
|
+
notes,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return operations;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function collectFromVariantList(variants: readonly JsonSchema[]): readonly GroupedOperation[] {
|
|
253
|
+
const operations: GroupedOperation[] = [];
|
|
254
|
+
|
|
182
255
|
for (const variant of variants) {
|
|
183
256
|
if (!variant || !isObject(variant)) {
|
|
184
257
|
continue;
|
|
@@ -220,6 +293,8 @@ function collectGroupedOperations(schema?: JsonSchema): readonly GroupedOperatio
|
|
|
220
293
|
op: opName,
|
|
221
294
|
description,
|
|
222
295
|
required: requiredProps,
|
|
296
|
+
optional: Object.keys(properties).filter((name) => name !== "op" && !requiredProps.includes(name)),
|
|
297
|
+
properties,
|
|
223
298
|
notes,
|
|
224
299
|
});
|
|
225
300
|
}
|
|
@@ -227,6 +302,56 @@ function collectGroupedOperations(schema?: JsonSchema): readonly GroupedOperatio
|
|
|
227
302
|
return operations;
|
|
228
303
|
}
|
|
229
304
|
|
|
305
|
+
function collectFromFlattenedSchema(schema: JsonSchema): readonly GroupedOperation[] {
|
|
306
|
+
const properties = (schema.properties ?? {}) as Record<string, JsonSchema | undefined>;
|
|
307
|
+
const opSchema = properties.op;
|
|
308
|
+
if (!opSchema || !isObject(opSchema)) {
|
|
309
|
+
return [];
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const enumValues = (opSchema as JsonSchema).enum;
|
|
313
|
+
if (!Array.isArray(enumValues) || enumValues.length === 0) {
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const opNames = enumValues.filter((value): value is string => typeof value === "string" && value.length > 0);
|
|
318
|
+
if (opNames.length === 0) {
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const descriptionMap = parseOperationDescriptions(getString(schema.description));
|
|
323
|
+
const hasVerificationProperty = Object.keys(properties).some((name) =>
|
|
324
|
+
name !== "op" && name.toLowerCase().startsWith("verify"),
|
|
325
|
+
);
|
|
326
|
+
const notes = hasVerificationProperty ? ["supports verify"] : [];
|
|
327
|
+
|
|
328
|
+
return opNames.map((opName) => ({
|
|
329
|
+
op: opName,
|
|
330
|
+
description: descriptionMap.get(opName) ?? `Operation ${opName}`,
|
|
331
|
+
required: [] as readonly string[],
|
|
332
|
+
optional: Object.keys(properties).filter((name) => name !== "op"),
|
|
333
|
+
properties,
|
|
334
|
+
notes,
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function parseOperationDescriptions(description: string): Map<string, string> {
|
|
339
|
+
const result = new Map<string, string>();
|
|
340
|
+
if (!description) {
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const lines = description.split(/\r?\n/);
|
|
345
|
+
for (const line of lines) {
|
|
346
|
+
const match = line.match(/^\s*-\s+([A-Za-z0-9_]+):\s*(.+)$/);
|
|
347
|
+
if (match) {
|
|
348
|
+
result.set(match[1], match[2].trim());
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
|
|
230
355
|
export function renderToolsSection(modules: readonly ToolModuleDescriptor[] = describeToolModules()): string[] {
|
|
231
356
|
const lines: string[] = ["### Tools", ""];
|
|
232
357
|
const groupedTools: GroupedToolInfo[] = [];
|
|
@@ -250,6 +375,9 @@ export function renderToolsSection(modules: readonly ToolModuleDescriptor[] = de
|
|
|
250
375
|
if (operations.length === 0) {
|
|
251
376
|
lines.push("_No operations defined._");
|
|
252
377
|
} else {
|
|
378
|
+
if (!lines.includes("_Address range convention: `address` + `length` means start address plus byte count; `startAddress` + `endAddress` means inclusive bounds._")) {
|
|
379
|
+
lines.splice(2, 0, "_Address range convention: `address` + `length` means start address plus byte count; `startAddress` + `endAddress` means inclusive bounds._", "");
|
|
380
|
+
}
|
|
253
381
|
const toolPlatforms: readonly string[] = tool.metadata.platforms ?? ["c64u"];
|
|
254
382
|
const opPlatformOverrides: Record<string, readonly string[]> = tool.metadata.operationPlatforms ?? {};
|
|
255
383
|
const operationRows = operations
|
|
@@ -260,14 +388,15 @@ export function renderToolsSection(modules: readonly ToolModuleDescriptor[] = de
|
|
|
260
388
|
return [
|
|
261
389
|
`\`${operation.op}\``,
|
|
262
390
|
escapeCell(operation.description),
|
|
263
|
-
escapeCell(
|
|
391
|
+
escapeCell(formatInputs(operation.required, operation.properties)),
|
|
392
|
+
escapeCell(formatInputs(operation.optional, operation.properties)),
|
|
264
393
|
operation.notes.length ? escapeCell(operation.notes.join(", ")) : "—",
|
|
265
394
|
effectivePlatforms.includes("c64u") ? "✅" : "",
|
|
266
395
|
effectivePlatforms.includes("vice") ? "✅" : "",
|
|
267
396
|
];
|
|
268
397
|
});
|
|
269
398
|
|
|
270
|
-
lines.push(renderTable(["Operation", "Description", "Required Inputs", "Notes", "C64U", "VICE"], operationRows));
|
|
399
|
+
lines.push(renderTable(["Operation", "Description", "Required Inputs", "Optional Inputs", "Notes", "C64U", "VICE"], operationRows));
|
|
271
400
|
}
|
|
272
401
|
|
|
273
402
|
lines.push("");
|
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.
|
|
11
|
+
"version": "0.9.1",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "c64bridge",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.9.1",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
},
|