c64bridge 1.0.6 → 1.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/.github/skills/assembly-program/SKILL.md +37 -0
- package/.github/skills/basic-program/SKILL.md +40 -0
- package/.github/skills/cross-platform-demo/SKILL.md +32 -0
- package/.github/skills/drive-manager/SKILL.md +33 -0
- package/.github/skills/graphics-demo/SKILL.md +30 -0
- package/.github/skills/hello-world/SKILL.md +36 -0
- package/.github/skills/memory-debug/SKILL.md +32 -0
- package/.github/skills/pr-converge/SKILL.md +33 -0
- package/.github/skills/printer-job/SKILL.md +30 -0
- package/.github/skills/sid-music/SKILL.md +35 -0
- package/.github/skills/software-launch/SKILL.md +31 -0
- package/.github/skills/stream-control/SKILL.md +29 -0
- package/.github/skills/system-control/SKILL.md +32 -0
- package/AGENTS.md +28 -7
- package/README.md +70 -15
- package/data/assembly/assembly-spec.md +2 -0
- package/dist/c64Client.js +238 -60
- package/dist/chargen.js +0 -4
- package/dist/config.js +53 -28
- package/dist/device.js +92 -37
- package/dist/diagnostics.js +66 -5
- package/dist/hostPaths.js +128 -0
- package/dist/logger.js +3 -2
- package/dist/loggingHttpClient.js +71 -2
- package/dist/mcp-server.js +416 -291
- package/dist/numericArg.js +55 -0
- package/dist/petscii.js +13 -6
- package/dist/platform.js +12 -3
- package/dist/prompts/registry.js +6 -1
- package/dist/redact.js +166 -0
- package/dist/tools/access.js +66 -0
- package/dist/tools/debug.js +6 -0
- package/dist/tools/developer.js +77 -36
- package/dist/tools/errors.js +54 -3
- package/dist/tools/input.js +25 -8
- package/dist/tools/machineControl.js +113 -21
- package/dist/tools/memory.js +135 -30
- package/dist/tools/meta/artifacts.js +5 -5
- package/dist/tools/meta/background.js +216 -54
- package/dist/tools/meta/compilation.js +6 -5
- package/dist/tools/meta/config.js +20 -10
- package/dist/tools/meta/configInventory.js +25 -2
- package/dist/tools/meta/diagnostics.js +2 -1
- package/dist/tools/meta/filesystem.js +16 -14
- package/dist/tools/meta/graphics.js +48 -20
- package/dist/tools/meta/memory.js +45 -19
- package/dist/tools/meta/program.js +10 -7
- package/dist/tools/meta/screen.js +116 -25
- package/dist/tools/pauseGuard.js +23 -0
- package/dist/tools/pollValidator.js +53 -8
- package/dist/tools/programRunners.js +62 -18
- package/dist/tools/registry/batch.js +17 -11
- package/dist/tools/registry/config.js +9 -2
- package/dist/tools/registry/disk.js +12 -2
- package/dist/tools/registry/drive.js +3 -0
- package/dist/tools/registry/extract.js +3 -0
- package/dist/tools/registry/graphics.js +59 -6
- package/dist/tools/registry/index.js +17 -1
- package/dist/tools/registry/memory.js +11 -1
- package/dist/tools/registry/platform.js +4 -1
- package/dist/tools/registry/printer.js +2 -1
- package/dist/tools/registry/program.js +5 -1
- package/dist/tools/registry/rag.js +1 -0
- package/dist/tools/registry/sound.js +12 -1
- package/dist/tools/registry/stream.js +2 -1
- package/dist/tools/registry/system.js +8 -1
- package/dist/tools/schema.js +7 -7
- package/dist/tools/streaming.js +34 -4
- package/dist/tools/translation/assembler.js +247 -24
- package/dist/tools/translation/basicDetokenizer.js +80 -0
- package/dist/tools/translation/basicTokenizer.js +8 -3
- package/dist/tools/translation/disassembler.js +14 -0
- package/dist/tools/types.js +258 -7
- package/dist/tools/vice.js +5 -16
- package/dist/vicBitmap.js +1 -1
- package/dist/vice/mockServer.js +3 -0
- package/dist/vice/process.js +19 -0
- package/dist/vice/resourcePolicy.js +36 -0
- package/dist/vice/viceClient.js +22 -5
- package/doc/vice/support-matrix.md +17 -11
- package/mcp/schemas/c64_batch.schema.json +2 -1
- package/mcp/schemas/c64_config.schema.json +33 -466
- package/mcp/schemas/c64_debug.schema.json +3 -602
- package/mcp/schemas/c64_disk.schema.json +17 -344
- package/mcp/schemas/c64_drive.schema.json +2 -157
- package/mcp/schemas/c64_extract.schema.json +10 -364
- package/mcp/schemas/c64_graphics.schema.json +19 -426
- package/mcp/schemas/c64_input.schema.json +5 -318
- package/mcp/schemas/c64_memory.schema.json +23 -491
- package/mcp/schemas/c64_printer.schema.json +3 -258
- package/mcp/schemas/c64_program.schema.json +16 -491
- package/mcp/schemas/c64_rag.schema.json +1 -81
- package/mcp/schemas/c64_select_backend.schema.json +2 -36
- package/mcp/schemas/c64_sound.schema.json +20 -822
- package/mcp/schemas/c64_stream.schema.json +4 -75
- package/mcp/schemas/c64_system.schema.json +28 -348
- package/mcp/schemas/c64_vice.schema.json +2 -71
- package/mcp/server.json +1 -1
- package/mcp/tools.json +1990 -6900
- package/mcp.json +21 -1
- package/package.json +19 -8
- package/scripts/mockC64Server.mjs +44 -0
- package/scripts/run-coverage.mjs +27 -1
- package/scripts/smoke-run.sh +3 -2
- package/scripts/start.mjs +23 -1
- package/server.json +53 -3
- package/dist/.tsbuildinfo +0 -1
- package/doc/agent-state-spec.md +0 -243
- package/doc/plans/bun/baseline-metrics.md +0 -16
- package/doc/plans/bun/migration-checklist.md +0 -55
- package/doc/plans/bun/migration.md +0 -83
- package/doc/plans/improve-knowledge/notes.md +0 -43
- package/doc/plans/improve-knowledge/plan.md +0 -121
- package/doc/plans/improve-knowledge/rollout.md +0 -110
- package/doc/plans/meta-tools/README.md +0 -110
- package/doc/plans/meta-tools/analysis.md +0 -272
- package/doc/plans/meta-tools/catalog.md +0 -435
- package/doc/plans/meta-tools/notes.md +0 -192
- package/doc/plans/meta-tools/rollout.md +0 -368
- package/doc/plans/prompts/README.md +0 -96
- package/doc/plans/prompts/user-prompt-ideas.md +0 -147
- package/doc/plans/tool-consolidation/notes.md +0 -28
- package/doc/plans/tool-consolidation/plan.md +0 -169
- package/doc/plans/tool-consolidation/rollout.md +0 -104
- package/doc/plans/vice-backend-switch/plan.md +0 -486
- package/doc/plans/vice-backend-switch-2/plan.md +0 -48
- package/doc/plans/vice-support/notes.md +0 -63
- package/doc/plans/vice-support/plan.md +0 -88
- package/doc/plans/vice-support/rollout.md +0 -99
- package/doc/reviews/audit.md +0 -143
- package/doc/reviews/hardening/01-fable/prompt-handover.md +0 -125
- package/doc/reviews/hardening/01-fable/prompt.md +0 -98
- package/doc/reviews/hardening/01-fable/review-prompt.md +0 -468
- package/doc/reviews/hardening/01-fable/review.md +0 -1234
- package/doc/reviews/vice-support-review.md +0 -185
- package/scripts/compare-rest/rest-compare-2025-11-01T00-25-21-830Z.json +0 -2513
package/dist/logger.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
|
+
import { redactText, redactValue } from "./redact.js";
|
|
2
3
|
const LEVEL_ORDER = {
|
|
3
4
|
debug: 0,
|
|
4
5
|
info: 1,
|
|
@@ -24,9 +25,9 @@ function createPrefixedLogger(prefix) {
|
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
26
27
|
const consoleMethod = selectConsole(level);
|
|
27
|
-
const label = `[${prefix}] ${message}`;
|
|
28
|
+
const label = `[${prefix}] ${redactText(message)}`;
|
|
28
29
|
if (details && Object.keys(details).length > 0) {
|
|
29
|
-
consoleMethod(label, details);
|
|
30
|
+
consoleMethod(label, redactValue(details));
|
|
30
31
|
}
|
|
31
32
|
else {
|
|
32
33
|
consoleMethod(label);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HttpClient } from "../generated/c64/index.js";
|
|
2
|
+
import { registerSecret, scrubRequestError } from "./redact.js";
|
|
2
3
|
import { formatErrorMessage, formatPayloadForDebug, loggerFor, payloadByteLength } from "./logger.js";
|
|
3
4
|
/** Headers are useful in diagnostics, but credentials must never leave the
|
|
4
5
|
* transport layer. Axios normalises some keys and preserves others, so do a
|
|
@@ -12,8 +13,55 @@ function redactHeaders(headers) {
|
|
|
12
13
|
sensitive.test(key) ? "***" : value,
|
|
13
14
|
]));
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
+
/**
|
|
17
|
+
* First-in first-out gate that lets one operation run at a time. The Ultimate
|
|
18
|
+
* firmware serves REST requests on a single thread, so every request to one
|
|
19
|
+
* device goes through one queue. A failed operation releases the gate like a
|
|
20
|
+
* successful one, so the queue cannot deadlock.
|
|
21
|
+
*/
|
|
22
|
+
export class RequestQueue {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.tail = Promise.resolve();
|
|
25
|
+
}
|
|
26
|
+
/** The shared queue for one device base URL, so every client of that device (backends, fallback clients) waits in the same line. */
|
|
27
|
+
static forDevice(baseUrl) {
|
|
28
|
+
const key = baseUrl.replace(/\/+$/, "").toLowerCase();
|
|
29
|
+
let queue = RequestQueue.byDevice.get(key);
|
|
30
|
+
if (!queue) {
|
|
31
|
+
queue = new RequestQueue();
|
|
32
|
+
RequestQueue.byDevice.set(key, queue);
|
|
33
|
+
}
|
|
34
|
+
return queue;
|
|
35
|
+
}
|
|
36
|
+
/** Resolves when all earlier holders have released; call the returned function exactly once. */
|
|
37
|
+
async acquire() {
|
|
38
|
+
let release;
|
|
39
|
+
const held = new Promise((resolve) => { release = resolve; });
|
|
40
|
+
const previous = this.tail;
|
|
41
|
+
this.tail = previous.then(() => held);
|
|
42
|
+
await previous;
|
|
43
|
+
let released = false;
|
|
44
|
+
return () => {
|
|
45
|
+
if (!released) {
|
|
46
|
+
released = true;
|
|
47
|
+
release();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
async run(operation) {
|
|
52
|
+
const release = await this.acquire();
|
|
53
|
+
try {
|
|
54
|
+
return await operation();
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
release();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
RequestQueue.byDevice = new Map();
|
|
62
|
+
export function createLoggingHttpClient(config, logger = loggerFor("c64u"), queue) {
|
|
16
63
|
const http = new HttpClient(config);
|
|
64
|
+
registerSecret(readPasswordHeader(config?.headers));
|
|
17
65
|
http.instance.interceptors.request.use((request) => {
|
|
18
66
|
const method = (request.method ?? "get").toUpperCase();
|
|
19
67
|
const path = resolvePath(request);
|
|
@@ -28,15 +76,36 @@ export function createLoggingHttpClient(config, logger = loggerFor("c64u")) {
|
|
|
28
76
|
request.__c64Meta = meta;
|
|
29
77
|
return request;
|
|
30
78
|
});
|
|
79
|
+
if (queue) {
|
|
80
|
+
// The generated client sends every request through `instance.request`, so
|
|
81
|
+
// the gate is taken around that call. Interceptors, request transforms and
|
|
82
|
+
// the adapter all run inside it: the start time is recorded after the wait,
|
|
83
|
+
// the request timeout (started by the adapter) does not include the wait,
|
|
84
|
+
// and the gate is released however the request settles, including a
|
|
85
|
+
// failure before the adapter is called (for example a body that cannot be
|
|
86
|
+
// serialised).
|
|
87
|
+
const instance = http.instance;
|
|
88
|
+
const sendRequest = instance.request.bind(instance);
|
|
89
|
+
instance.request = ((requestConfig) => queue.run(() => sendRequest(requestConfig)));
|
|
90
|
+
}
|
|
31
91
|
http.instance.interceptors.response.use((response) => {
|
|
32
92
|
handleResponse(response, logger);
|
|
33
93
|
return response;
|
|
34
94
|
}, (error) => {
|
|
35
95
|
handleError(error, logger);
|
|
36
|
-
return Promise.reject(error);
|
|
96
|
+
return Promise.reject(scrubRequestError(error));
|
|
37
97
|
});
|
|
38
98
|
return http;
|
|
39
99
|
}
|
|
100
|
+
function readPasswordHeader(headers) {
|
|
101
|
+
if (!headers || typeof headers !== "object")
|
|
102
|
+
return undefined;
|
|
103
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
104
|
+
if (/^x-password$/i.test(key) && typeof value === "string")
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
40
109
|
function handleResponse(response, logger) {
|
|
41
110
|
const meta = extractMeta(response.config);
|
|
42
111
|
const latency = meta ? Date.now() - meta.startedAt : 0;
|