c64-debug-mcp 1.0.13 → 1.0.14
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/dist/http.cjs +90 -6
- package/dist/http.js +90 -6
- package/dist/stdio.cjs +90 -6
- package/dist/stdio.js +90 -6
- package/package.json +1 -1
package/dist/http.cjs
CHANGED
|
@@ -66,7 +66,7 @@ var stopReasonSchema = import_zod.z.enum([
|
|
|
66
66
|
]);
|
|
67
67
|
var sessionHealthSchema = import_zod.z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
68
68
|
var breakpointKindSchema = import_zod.z.enum(["exec", "read", "write", "read_write"]);
|
|
69
|
-
var resetModeSchema = import_zod.z.enum(["soft", "hard"]);
|
|
69
|
+
var resetModeSchema = import_zod.z.enum(["soft", "hard", "nuclear"]);
|
|
70
70
|
var inputActionSchema = import_zod.z.enum(["press", "release", "tap"]);
|
|
71
71
|
var joystickControlSchema = import_zod.z.enum(["up", "down", "left", "right", "fire"]);
|
|
72
72
|
var joystickPortSchema = import_zod.z.union([import_zod.z.literal(1), import_zod.z.literal(2)]);
|
|
@@ -1728,7 +1728,17 @@ var ViceSession = class {
|
|
|
1728
1728
|
}
|
|
1729
1729
|
this.#syncMonitorRuntimeState();
|
|
1730
1730
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1731
|
-
void this.#scheduleRecovery()
|
|
1731
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1732
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1733
|
+
});
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1736
|
+
this.#client.on("transport-error", (error) => {
|
|
1737
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1738
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1739
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1740
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1741
|
+
});
|
|
1732
1742
|
}
|
|
1733
1743
|
});
|
|
1734
1744
|
this.#client.on("event", (event) => {
|
|
@@ -2069,6 +2079,10 @@ var ViceSession = class {
|
|
|
2069
2079
|
async resetMachine(mode) {
|
|
2070
2080
|
return this.#withExecutionLock(async () => {
|
|
2071
2081
|
await this.#ensureReady();
|
|
2082
|
+
this.#clearHeldInputState();
|
|
2083
|
+
if (mode === "nuclear") {
|
|
2084
|
+
return await this.#performNuclearReset();
|
|
2085
|
+
}
|
|
2072
2086
|
const wasPaused = this.#explicitPauseActive;
|
|
2073
2087
|
this.#lastExecutionIntent = "reset";
|
|
2074
2088
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2088,6 +2102,67 @@ var ViceSession = class {
|
|
|
2088
2102
|
};
|
|
2089
2103
|
});
|
|
2090
2104
|
}
|
|
2105
|
+
async #performNuclearReset() {
|
|
2106
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2107
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2108
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2109
|
+
await this.#scheduleRecovery();
|
|
2110
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2111
|
+
this.#explicitPauseActive = wasPaused;
|
|
2112
|
+
if (wasPaused) {
|
|
2113
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2114
|
+
await this.pauseExecution();
|
|
2115
|
+
}
|
|
2116
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2117
|
+
const debugState = await this.#readDebugState();
|
|
2118
|
+
return {
|
|
2119
|
+
executionState: debugState.executionState,
|
|
2120
|
+
lastStopReason: debugState.lastStopReason,
|
|
2121
|
+
programCounter: debugState.programCounter,
|
|
2122
|
+
registers: debugState.registers,
|
|
2123
|
+
warnings: []
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
async #captureBreakpointState() {
|
|
2127
|
+
try {
|
|
2128
|
+
const result = await this.listBreakpoints(true);
|
|
2129
|
+
return result.breakpoints.map((bp) => ({
|
|
2130
|
+
kind: bp.kind,
|
|
2131
|
+
start: bp.start,
|
|
2132
|
+
end: bp.end,
|
|
2133
|
+
enabled: bp.enabled,
|
|
2134
|
+
temporary: bp.temporary,
|
|
2135
|
+
hasCondition: bp.hasCondition,
|
|
2136
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2137
|
+
}));
|
|
2138
|
+
} catch (error) {
|
|
2139
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2140
|
+
return [];
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2144
|
+
if (savedBreakpoints.length === 0) {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2148
|
+
for (const bp of savedBreakpoints) {
|
|
2149
|
+
try {
|
|
2150
|
+
await this.breakpointSet({
|
|
2151
|
+
kind: bp.kind,
|
|
2152
|
+
address: bp.start,
|
|
2153
|
+
length: bp.end - bp.start + 1,
|
|
2154
|
+
enabled: bp.enabled,
|
|
2155
|
+
temporary: bp.temporary,
|
|
2156
|
+
label: bp.label ?? void 0
|
|
2157
|
+
});
|
|
2158
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2159
|
+
} catch (error) {
|
|
2160
|
+
this.#writeProcessLogLine(
|
|
2161
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2091
2166
|
async listBreakpoints(includeDisabled = true) {
|
|
2092
2167
|
await this.#ensureReady();
|
|
2093
2168
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2802,7 +2877,9 @@ var ViceSession = class {
|
|
|
2802
2877
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2803
2878
|
];
|
|
2804
2879
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2805
|
-
void this.#scheduleRecovery()
|
|
2880
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2881
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2882
|
+
});
|
|
2806
2883
|
}
|
|
2807
2884
|
});
|
|
2808
2885
|
child.once("error", (error) => {
|
|
@@ -2815,12 +2892,16 @@ var ViceSession = class {
|
|
|
2815
2892
|
this.#transportState = "faulted";
|
|
2816
2893
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2817
2894
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2818
|
-
void this.#scheduleRecovery()
|
|
2895
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2896
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2897
|
+
});
|
|
2819
2898
|
}
|
|
2820
2899
|
});
|
|
2821
2900
|
}
|
|
2822
2901
|
#attachProcessLogging(child, binary, args) {
|
|
2823
2902
|
const logStream = (0, import_node_fs.createWriteStream)(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2903
|
+
logStream.on("error", () => {
|
|
2904
|
+
});
|
|
2824
2905
|
this.#processLogStream = logStream;
|
|
2825
2906
|
this.#stdoutMirrorBuffer = "";
|
|
2826
2907
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2854,7 +2935,10 @@ var ViceSession = class {
|
|
|
2854
2935
|
logStream.write(`
|
|
2855
2936
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2856
2937
|
`);
|
|
2857
|
-
logStream.end()
|
|
2938
|
+
logStream.end(() => {
|
|
2939
|
+
});
|
|
2940
|
+
logStream.on("error", () => {
|
|
2941
|
+
});
|
|
2858
2942
|
this.#processLogStream = null;
|
|
2859
2943
|
}
|
|
2860
2944
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3697,7 +3781,7 @@ var executeTool = createViceTool({
|
|
|
3697
3781
|
inputSchema: import_zod4.z.object({
|
|
3698
3782
|
action: import_zod4.z.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3699
3783
|
count: import_zod4.z.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3700
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3784
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3701
3785
|
waitUntilRunningStable: import_zod4.z.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3702
3786
|
}),
|
|
3703
3787
|
dataSchema: debugStateSchema.extend({
|
package/dist/http.js
CHANGED
|
@@ -43,7 +43,7 @@ var stopReasonSchema = z.enum([
|
|
|
43
43
|
]);
|
|
44
44
|
var sessionHealthSchema = z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
45
45
|
var breakpointKindSchema = z.enum(["exec", "read", "write", "read_write"]);
|
|
46
|
-
var resetModeSchema = z.enum(["soft", "hard"]);
|
|
46
|
+
var resetModeSchema = z.enum(["soft", "hard", "nuclear"]);
|
|
47
47
|
var inputActionSchema = z.enum(["press", "release", "tap"]);
|
|
48
48
|
var joystickControlSchema = z.enum(["up", "down", "left", "right", "fire"]);
|
|
49
49
|
var joystickPortSchema = z.union([z.literal(1), z.literal(2)]);
|
|
@@ -1705,7 +1705,17 @@ var ViceSession = class {
|
|
|
1705
1705
|
}
|
|
1706
1706
|
this.#syncMonitorRuntimeState();
|
|
1707
1707
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1708
|
-
void this.#scheduleRecovery()
|
|
1708
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1709
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
});
|
|
1713
|
+
this.#client.on("transport-error", (error) => {
|
|
1714
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1715
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1716
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1717
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1718
|
+
});
|
|
1709
1719
|
}
|
|
1710
1720
|
});
|
|
1711
1721
|
this.#client.on("event", (event) => {
|
|
@@ -2046,6 +2056,10 @@ var ViceSession = class {
|
|
|
2046
2056
|
async resetMachine(mode) {
|
|
2047
2057
|
return this.#withExecutionLock(async () => {
|
|
2048
2058
|
await this.#ensureReady();
|
|
2059
|
+
this.#clearHeldInputState();
|
|
2060
|
+
if (mode === "nuclear") {
|
|
2061
|
+
return await this.#performNuclearReset();
|
|
2062
|
+
}
|
|
2049
2063
|
const wasPaused = this.#explicitPauseActive;
|
|
2050
2064
|
this.#lastExecutionIntent = "reset";
|
|
2051
2065
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2065,6 +2079,67 @@ var ViceSession = class {
|
|
|
2065
2079
|
};
|
|
2066
2080
|
});
|
|
2067
2081
|
}
|
|
2082
|
+
async #performNuclearReset() {
|
|
2083
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2084
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2085
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2086
|
+
await this.#scheduleRecovery();
|
|
2087
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2088
|
+
this.#explicitPauseActive = wasPaused;
|
|
2089
|
+
if (wasPaused) {
|
|
2090
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2091
|
+
await this.pauseExecution();
|
|
2092
|
+
}
|
|
2093
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2094
|
+
const debugState = await this.#readDebugState();
|
|
2095
|
+
return {
|
|
2096
|
+
executionState: debugState.executionState,
|
|
2097
|
+
lastStopReason: debugState.lastStopReason,
|
|
2098
|
+
programCounter: debugState.programCounter,
|
|
2099
|
+
registers: debugState.registers,
|
|
2100
|
+
warnings: []
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
async #captureBreakpointState() {
|
|
2104
|
+
try {
|
|
2105
|
+
const result = await this.listBreakpoints(true);
|
|
2106
|
+
return result.breakpoints.map((bp) => ({
|
|
2107
|
+
kind: bp.kind,
|
|
2108
|
+
start: bp.start,
|
|
2109
|
+
end: bp.end,
|
|
2110
|
+
enabled: bp.enabled,
|
|
2111
|
+
temporary: bp.temporary,
|
|
2112
|
+
hasCondition: bp.hasCondition,
|
|
2113
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2114
|
+
}));
|
|
2115
|
+
} catch (error) {
|
|
2116
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2117
|
+
return [];
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2121
|
+
if (savedBreakpoints.length === 0) {
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2125
|
+
for (const bp of savedBreakpoints) {
|
|
2126
|
+
try {
|
|
2127
|
+
await this.breakpointSet({
|
|
2128
|
+
kind: bp.kind,
|
|
2129
|
+
address: bp.start,
|
|
2130
|
+
length: bp.end - bp.start + 1,
|
|
2131
|
+
enabled: bp.enabled,
|
|
2132
|
+
temporary: bp.temporary,
|
|
2133
|
+
label: bp.label ?? void 0
|
|
2134
|
+
});
|
|
2135
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2136
|
+
} catch (error) {
|
|
2137
|
+
this.#writeProcessLogLine(
|
|
2138
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2139
|
+
);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2068
2143
|
async listBreakpoints(includeDisabled = true) {
|
|
2069
2144
|
await this.#ensureReady();
|
|
2070
2145
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2779,7 +2854,9 @@ var ViceSession = class {
|
|
|
2779
2854
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2780
2855
|
];
|
|
2781
2856
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2782
|
-
void this.#scheduleRecovery()
|
|
2857
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2858
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2859
|
+
});
|
|
2783
2860
|
}
|
|
2784
2861
|
});
|
|
2785
2862
|
child.once("error", (error) => {
|
|
@@ -2792,12 +2869,16 @@ var ViceSession = class {
|
|
|
2792
2869
|
this.#transportState = "faulted";
|
|
2793
2870
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2794
2871
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2795
|
-
void this.#scheduleRecovery()
|
|
2872
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2873
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2874
|
+
});
|
|
2796
2875
|
}
|
|
2797
2876
|
});
|
|
2798
2877
|
}
|
|
2799
2878
|
#attachProcessLogging(child, binary, args) {
|
|
2800
2879
|
const logStream = createWriteStream(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2880
|
+
logStream.on("error", () => {
|
|
2881
|
+
});
|
|
2801
2882
|
this.#processLogStream = logStream;
|
|
2802
2883
|
this.#stdoutMirrorBuffer = "";
|
|
2803
2884
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2831,7 +2912,10 @@ var ViceSession = class {
|
|
|
2831
2912
|
logStream.write(`
|
|
2832
2913
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2833
2914
|
`);
|
|
2834
|
-
logStream.end()
|
|
2915
|
+
logStream.end(() => {
|
|
2916
|
+
});
|
|
2917
|
+
logStream.on("error", () => {
|
|
2918
|
+
});
|
|
2835
2919
|
this.#processLogStream = null;
|
|
2836
2920
|
}
|
|
2837
2921
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3674,7 +3758,7 @@ var executeTool = createViceTool({
|
|
|
3674
3758
|
inputSchema: z3.object({
|
|
3675
3759
|
action: z3.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3676
3760
|
count: z3.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3677
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3761
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3678
3762
|
waitUntilRunningStable: z3.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3679
3763
|
}),
|
|
3680
3764
|
dataSchema: debugStateSchema.extend({
|
package/dist/stdio.cjs
CHANGED
|
@@ -63,7 +63,7 @@ var stopReasonSchema = import_zod.z.enum([
|
|
|
63
63
|
]);
|
|
64
64
|
var sessionHealthSchema = import_zod.z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
65
65
|
var breakpointKindSchema = import_zod.z.enum(["exec", "read", "write", "read_write"]);
|
|
66
|
-
var resetModeSchema = import_zod.z.enum(["soft", "hard"]);
|
|
66
|
+
var resetModeSchema = import_zod.z.enum(["soft", "hard", "nuclear"]);
|
|
67
67
|
var inputActionSchema = import_zod.z.enum(["press", "release", "tap"]);
|
|
68
68
|
var joystickControlSchema = import_zod.z.enum(["up", "down", "left", "right", "fire"]);
|
|
69
69
|
var joystickPortSchema = import_zod.z.union([import_zod.z.literal(1), import_zod.z.literal(2)]);
|
|
@@ -1725,7 +1725,17 @@ var ViceSession = class {
|
|
|
1725
1725
|
}
|
|
1726
1726
|
this.#syncMonitorRuntimeState();
|
|
1727
1727
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1728
|
-
void this.#scheduleRecovery()
|
|
1728
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1729
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
});
|
|
1733
|
+
this.#client.on("transport-error", (error) => {
|
|
1734
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1735
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1736
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1737
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1738
|
+
});
|
|
1729
1739
|
}
|
|
1730
1740
|
});
|
|
1731
1741
|
this.#client.on("event", (event) => {
|
|
@@ -2066,6 +2076,10 @@ var ViceSession = class {
|
|
|
2066
2076
|
async resetMachine(mode) {
|
|
2067
2077
|
return this.#withExecutionLock(async () => {
|
|
2068
2078
|
await this.#ensureReady();
|
|
2079
|
+
this.#clearHeldInputState();
|
|
2080
|
+
if (mode === "nuclear") {
|
|
2081
|
+
return await this.#performNuclearReset();
|
|
2082
|
+
}
|
|
2069
2083
|
const wasPaused = this.#explicitPauseActive;
|
|
2070
2084
|
this.#lastExecutionIntent = "reset";
|
|
2071
2085
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2085,6 +2099,67 @@ var ViceSession = class {
|
|
|
2085
2099
|
};
|
|
2086
2100
|
});
|
|
2087
2101
|
}
|
|
2102
|
+
async #performNuclearReset() {
|
|
2103
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2104
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2105
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2106
|
+
await this.#scheduleRecovery();
|
|
2107
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2108
|
+
this.#explicitPauseActive = wasPaused;
|
|
2109
|
+
if (wasPaused) {
|
|
2110
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2111
|
+
await this.pauseExecution();
|
|
2112
|
+
}
|
|
2113
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2114
|
+
const debugState = await this.#readDebugState();
|
|
2115
|
+
return {
|
|
2116
|
+
executionState: debugState.executionState,
|
|
2117
|
+
lastStopReason: debugState.lastStopReason,
|
|
2118
|
+
programCounter: debugState.programCounter,
|
|
2119
|
+
registers: debugState.registers,
|
|
2120
|
+
warnings: []
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
async #captureBreakpointState() {
|
|
2124
|
+
try {
|
|
2125
|
+
const result = await this.listBreakpoints(true);
|
|
2126
|
+
return result.breakpoints.map((bp) => ({
|
|
2127
|
+
kind: bp.kind,
|
|
2128
|
+
start: bp.start,
|
|
2129
|
+
end: bp.end,
|
|
2130
|
+
enabled: bp.enabled,
|
|
2131
|
+
temporary: bp.temporary,
|
|
2132
|
+
hasCondition: bp.hasCondition,
|
|
2133
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2134
|
+
}));
|
|
2135
|
+
} catch (error) {
|
|
2136
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2137
|
+
return [];
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2141
|
+
if (savedBreakpoints.length === 0) {
|
|
2142
|
+
return;
|
|
2143
|
+
}
|
|
2144
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2145
|
+
for (const bp of savedBreakpoints) {
|
|
2146
|
+
try {
|
|
2147
|
+
await this.breakpointSet({
|
|
2148
|
+
kind: bp.kind,
|
|
2149
|
+
address: bp.start,
|
|
2150
|
+
length: bp.end - bp.start + 1,
|
|
2151
|
+
enabled: bp.enabled,
|
|
2152
|
+
temporary: bp.temporary,
|
|
2153
|
+
label: bp.label ?? void 0
|
|
2154
|
+
});
|
|
2155
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2156
|
+
} catch (error) {
|
|
2157
|
+
this.#writeProcessLogLine(
|
|
2158
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2088
2163
|
async listBreakpoints(includeDisabled = true) {
|
|
2089
2164
|
await this.#ensureReady();
|
|
2090
2165
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2799,7 +2874,9 @@ var ViceSession = class {
|
|
|
2799
2874
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2800
2875
|
];
|
|
2801
2876
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2802
|
-
void this.#scheduleRecovery()
|
|
2877
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2878
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2879
|
+
});
|
|
2803
2880
|
}
|
|
2804
2881
|
});
|
|
2805
2882
|
child.once("error", (error) => {
|
|
@@ -2812,12 +2889,16 @@ var ViceSession = class {
|
|
|
2812
2889
|
this.#transportState = "faulted";
|
|
2813
2890
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2814
2891
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2815
|
-
void this.#scheduleRecovery()
|
|
2892
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2893
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2894
|
+
});
|
|
2816
2895
|
}
|
|
2817
2896
|
});
|
|
2818
2897
|
}
|
|
2819
2898
|
#attachProcessLogging(child, binary, args) {
|
|
2820
2899
|
const logStream = (0, import_node_fs.createWriteStream)(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2900
|
+
logStream.on("error", () => {
|
|
2901
|
+
});
|
|
2821
2902
|
this.#processLogStream = logStream;
|
|
2822
2903
|
this.#stdoutMirrorBuffer = "";
|
|
2823
2904
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2851,7 +2932,10 @@ var ViceSession = class {
|
|
|
2851
2932
|
logStream.write(`
|
|
2852
2933
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2853
2934
|
`);
|
|
2854
|
-
logStream.end()
|
|
2935
|
+
logStream.end(() => {
|
|
2936
|
+
});
|
|
2937
|
+
logStream.on("error", () => {
|
|
2938
|
+
});
|
|
2855
2939
|
this.#processLogStream = null;
|
|
2856
2940
|
}
|
|
2857
2941
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3694,7 +3778,7 @@ var executeTool = createViceTool({
|
|
|
3694
3778
|
inputSchema: import_zod4.z.object({
|
|
3695
3779
|
action: import_zod4.z.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3696
3780
|
count: import_zod4.z.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3697
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3781
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3698
3782
|
waitUntilRunningStable: import_zod4.z.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3699
3783
|
}),
|
|
3700
3784
|
dataSchema: debugStateSchema.extend({
|
package/dist/stdio.js
CHANGED
|
@@ -40,7 +40,7 @@ var stopReasonSchema = z.enum([
|
|
|
40
40
|
]);
|
|
41
41
|
var sessionHealthSchema = z.enum(["not_configured", "starting", "ready", "recovering", "stopped", "error"]);
|
|
42
42
|
var breakpointKindSchema = z.enum(["exec", "read", "write", "read_write"]);
|
|
43
|
-
var resetModeSchema = z.enum(["soft", "hard"]);
|
|
43
|
+
var resetModeSchema = z.enum(["soft", "hard", "nuclear"]);
|
|
44
44
|
var inputActionSchema = z.enum(["press", "release", "tap"]);
|
|
45
45
|
var joystickControlSchema = z.enum(["up", "down", "left", "right", "fire"]);
|
|
46
46
|
var joystickPortSchema = z.union([z.literal(1), z.literal(2)]);
|
|
@@ -1702,7 +1702,17 @@ var ViceSession = class {
|
|
|
1702
1702
|
}
|
|
1703
1703
|
this.#syncMonitorRuntimeState();
|
|
1704
1704
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1705
|
-
void this.#scheduleRecovery()
|
|
1705
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
1706
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
this.#client.on("transport-error", (error) => {
|
|
1711
|
+
this.#writeProcessLogLine(`[monitor-error] transport error: ${error.message}`);
|
|
1712
|
+
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
1713
|
+
void this.#scheduleRecovery().catch((recoveryError) => {
|
|
1714
|
+
this.#writeProcessLogLine(`[recovery-error] ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1715
|
+
});
|
|
1706
1716
|
}
|
|
1707
1717
|
});
|
|
1708
1718
|
this.#client.on("event", (event) => {
|
|
@@ -2043,6 +2053,10 @@ var ViceSession = class {
|
|
|
2043
2053
|
async resetMachine(mode) {
|
|
2044
2054
|
return this.#withExecutionLock(async () => {
|
|
2045
2055
|
await this.#ensureReady();
|
|
2056
|
+
this.#clearHeldInputState();
|
|
2057
|
+
if (mode === "nuclear") {
|
|
2058
|
+
return await this.#performNuclearReset();
|
|
2059
|
+
}
|
|
2046
2060
|
const wasPaused = this.#explicitPauseActive;
|
|
2047
2061
|
this.#lastExecutionIntent = "reset";
|
|
2048
2062
|
this.#writeProcessLogLine(`[tx] execute reset mode=${mode}`);
|
|
@@ -2062,6 +2076,67 @@ var ViceSession = class {
|
|
|
2062
2076
|
};
|
|
2063
2077
|
});
|
|
2064
2078
|
}
|
|
2079
|
+
async #performNuclearReset() {
|
|
2080
|
+
const savedBreakpoints = await this.#captureBreakpointState();
|
|
2081
|
+
const wasPaused = this.#explicitPauseActive;
|
|
2082
|
+
this.#writeProcessLogLine("[nuclear-reset] initiating full VICE process restart");
|
|
2083
|
+
await this.#scheduleRecovery();
|
|
2084
|
+
await this.#restoreBreakpointState(savedBreakpoints);
|
|
2085
|
+
this.#explicitPauseActive = wasPaused;
|
|
2086
|
+
if (wasPaused) {
|
|
2087
|
+
this.#writeProcessLogLine("[nuclear-reset] restoring paused state");
|
|
2088
|
+
await this.pauseExecution();
|
|
2089
|
+
}
|
|
2090
|
+
this.#writeProcessLogLine("[nuclear-reset] completed successfully");
|
|
2091
|
+
const debugState = await this.#readDebugState();
|
|
2092
|
+
return {
|
|
2093
|
+
executionState: debugState.executionState,
|
|
2094
|
+
lastStopReason: debugState.lastStopReason,
|
|
2095
|
+
programCounter: debugState.programCounter,
|
|
2096
|
+
registers: debugState.registers,
|
|
2097
|
+
warnings: []
|
|
2098
|
+
};
|
|
2099
|
+
}
|
|
2100
|
+
async #captureBreakpointState() {
|
|
2101
|
+
try {
|
|
2102
|
+
const result = await this.listBreakpoints(true);
|
|
2103
|
+
return result.breakpoints.map((bp) => ({
|
|
2104
|
+
kind: bp.kind,
|
|
2105
|
+
start: bp.start,
|
|
2106
|
+
end: bp.end,
|
|
2107
|
+
enabled: bp.enabled,
|
|
2108
|
+
temporary: bp.temporary,
|
|
2109
|
+
hasCondition: bp.hasCondition,
|
|
2110
|
+
label: this.#breakpointLabels.get(bp.id) ?? null
|
|
2111
|
+
}));
|
|
2112
|
+
} catch (error) {
|
|
2113
|
+
this.#writeProcessLogLine(`[nuclear-reset] failed to capture breakpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
2114
|
+
return [];
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
async #restoreBreakpointState(savedBreakpoints) {
|
|
2118
|
+
if (savedBreakpoints.length === 0) {
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
this.#writeProcessLogLine(`[nuclear-reset] restoring ${savedBreakpoints.length} breakpoints`);
|
|
2122
|
+
for (const bp of savedBreakpoints) {
|
|
2123
|
+
try {
|
|
2124
|
+
await this.breakpointSet({
|
|
2125
|
+
kind: bp.kind,
|
|
2126
|
+
address: bp.start,
|
|
2127
|
+
length: bp.end - bp.start + 1,
|
|
2128
|
+
enabled: bp.enabled,
|
|
2129
|
+
temporary: bp.temporary,
|
|
2130
|
+
label: bp.label ?? void 0
|
|
2131
|
+
});
|
|
2132
|
+
this.#writeProcessLogLine(`[nuclear-reset] restored breakpoint at $${bp.start.toString(16).toUpperCase()}`);
|
|
2133
|
+
} catch (error) {
|
|
2134
|
+
this.#writeProcessLogLine(
|
|
2135
|
+
`[nuclear-reset] failed to restore breakpoint at $${bp.start.toString(16).toUpperCase()}: ${error instanceof Error ? error.message : String(error)}`
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2065
2140
|
async listBreakpoints(includeDisabled = true) {
|
|
2066
2141
|
await this.#ensureReady();
|
|
2067
2142
|
this.#writeProcessLogLine(`[tx] breakpoint_list includeDisabled=${includeDisabled}`);
|
|
@@ -2776,7 +2851,9 @@ var ViceSession = class {
|
|
|
2776
2851
|
makeWarning(`C64 emulator process exited (${code ?? "null"} / ${signal ?? "null"})`, "process_exit")
|
|
2777
2852
|
];
|
|
2778
2853
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2779
|
-
void this.#scheduleRecovery()
|
|
2854
|
+
void this.#scheduleRecovery().catch((error) => {
|
|
2855
|
+
this.#writeProcessLogLine(`[recovery-error] ${error instanceof Error ? error.message : String(error)}`);
|
|
2856
|
+
});
|
|
2780
2857
|
}
|
|
2781
2858
|
});
|
|
2782
2859
|
child.once("error", (error) => {
|
|
@@ -2789,12 +2866,16 @@ var ViceSession = class {
|
|
|
2789
2866
|
this.#transportState = "faulted";
|
|
2790
2867
|
this.#warnings = [...this.#warnings.filter((warning) => warning.code !== "process_error"), makeWarning(error.message, "process_error")];
|
|
2791
2868
|
if (!this.#suppressRecovery && !this.#shuttingDown && this.#config) {
|
|
2792
|
-
void this.#scheduleRecovery()
|
|
2869
|
+
void this.#scheduleRecovery().catch((error2) => {
|
|
2870
|
+
this.#writeProcessLogLine(`[recovery-error] ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
2871
|
+
});
|
|
2793
2872
|
}
|
|
2794
2873
|
});
|
|
2795
2874
|
}
|
|
2796
2875
|
#attachProcessLogging(child, binary, args) {
|
|
2797
2876
|
const logStream = createWriteStream(VICE_PROCESS_LOG_PATH, { flags: "a" });
|
|
2877
|
+
logStream.on("error", () => {
|
|
2878
|
+
});
|
|
2798
2879
|
this.#processLogStream = logStream;
|
|
2799
2880
|
this.#stdoutMirrorBuffer = "";
|
|
2800
2881
|
this.#stderrMirrorBuffer = "";
|
|
@@ -2828,7 +2909,10 @@ var ViceSession = class {
|
|
|
2828
2909
|
logStream.write(`
|
|
2829
2910
|
=== Emulator stream closed ${nowIso()} (${reason}) ===
|
|
2830
2911
|
`);
|
|
2831
|
-
logStream.end()
|
|
2912
|
+
logStream.end(() => {
|
|
2913
|
+
});
|
|
2914
|
+
logStream.on("error", () => {
|
|
2915
|
+
});
|
|
2832
2916
|
this.#processLogStream = null;
|
|
2833
2917
|
}
|
|
2834
2918
|
#mirrorViceOutputChunk(stream, chunk) {
|
|
@@ -3671,7 +3755,7 @@ var executeTool = createViceTool({
|
|
|
3671
3755
|
inputSchema: z3.object({
|
|
3672
3756
|
action: z3.enum(["pause", "resume", "step", "step_over", "step_out", "reset"]),
|
|
3673
3757
|
count: z3.number().int().positive().default(1).describe("Instruction count for step and step_over actions"),
|
|
3674
|
-
resetMode: resetModeSchema.default("soft").describe("Reset mode
|
|
3758
|
+
resetMode: resetModeSchema.default("soft").describe("Reset mode: soft (CPU reset), hard (full machine reset), or nuclear (complete VICE restart)"),
|
|
3675
3759
|
waitUntilRunningStable: z3.boolean().default(false).describe("When action is resume, wait until running becomes stable before returning")
|
|
3676
3760
|
}),
|
|
3677
3761
|
dataSchema: debugStateSchema.extend({
|