@henols/c64-re-tools 1.0.0 → 2.0.0-rc.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/LICENSE +21 -0
- package/README.md +190 -37
- package/distribution/package.ts +36 -0
- package/distribution/plugin.ts +120 -0
- package/package.json +34 -40
- package/skills/c64-assembler/SKILL.md +73 -0
- package/skills/c64-assembler/scripts/assemble.ts +103 -0
- package/skills/c64-basic/SKILL.md +67 -0
- package/skills/c64-basic/scripts/basic.ts +46 -0
- package/skills/c64-disk/SKILL.md +79 -0
- package/skills/c64-disk/scripts/disk.ts +65 -0
- package/skills/c64-emulator/SKILL.md +124 -0
- package/skills/c64-knowledge/SKILL.md +102 -0
- package/skills/c64-knowledge/scripts/knowledge.ts +257 -0
- package/skills/c64-memory-map/SKILL.md +76 -0
- package/skills/c64-memory-map/scripts/memmap.ts +81 -0
- package/skills/c64-memory-map/scripts/platform.ts +424 -0
- package/skills/c64-provenance/SKILL.md +76 -0
- package/skills/c64-provenance/scripts/compare.ts +92 -0
- package/skills/c64-provenance/scripts/provenance.ts +83 -0
- package/skills/c64-reverse-engineering/SKILL.md +90 -0
- package/skills/c64-static-analysis/SKILL.md +96 -0
- package/skills/c64-static-analysis/scripts/analyze.ts +175 -0
- package/skills/c64-static-analysis/scripts/findings.ts +73 -0
- package/skills/c64-testing/SKILL.md +79 -0
- package/skills/c64-testing/references/scenario-format.md +76 -0
- package/skills/c64-testing/scripts/checklist.ts +51 -0
- package/skills/c64-testing/scripts/scenario.ts +473 -0
- package/skills/c64-testing/scripts/test.ts +55 -0
- package/skills/c64-unpacker/SKILL.md +82 -0
- package/skills/c64-unpacker/scripts/evidence.ts +135 -0
- package/skills/c64-unpacker/scripts/unpack.ts +216 -0
- package/src/c64.ts +281 -0
- package/src/cli/ap-sdk.ts +44 -0
- package/src/cli/cleanup.ts +194 -0
- package/src/cli/main.ts +122 -0
- package/src/cli/status.ts +34 -0
- package/src/host/main.ts +121 -0
- package/src/host/server.ts +409 -0
- package/src/host/tools/c1541.ts +255 -0
- package/src/host/tools/index.ts +31 -0
- package/src/host/tools/petcat.ts +70 -0
- package/src/host/tools/status.ts +30 -0
- package/src/host/tools/version.ts +41 -0
- package/src/host/vice/adapter.ts +761 -0
- package/src/host/vice/binary-monitor.ts +389 -0
- package/src/host/vice/chips.ts +108 -0
- package/src/host/vice/connect.ts +34 -0
- package/src/host/vice/process.ts +402 -0
- package/src/host/vice/screen.ts +183 -0
- package/src/host/vice/session.ts +1316 -0
- package/src/host/vice/text-monitor.ts +223 -0
- package/src/host-client/connect.ts +241 -0
- package/src/host-client/tools.ts +89 -0
- package/src/host-client/transfer.ts +100 -0
- package/src/host-client/vice-session.ts +254 -0
- package/src/knowledge/database.ts +132 -0
- package/src/knowledge/history.ts +128 -0
- package/src/knowledge/import.ts +344 -0
- package/src/knowledge/read.ts +191 -0
- package/src/knowledge/schema.ts +140 -0
- package/src/knowledge/write.ts +348 -0
- package/src/mcp/main.ts +109 -0
- package/src/mcp/server.ts +307 -0
- package/src/mcp/tools/debug.ts +237 -0
- package/src/mcp/tools/execution.ts +116 -0
- package/src/mcp/tools/input.ts +69 -0
- package/src/mcp/tools/machine.ts +97 -0
- package/src/mcp/tools/media.ts +106 -0
- package/src/mcp/tools/memory.ts +203 -0
- package/src/mcp/tools/video.ts +260 -0
- package/src/native/acme.ts +116 -0
- package/src/native/discover.ts +141 -0
- package/src/native/dxa.ts +166 -0
- package/src/native/ghidra/analyze.ts +86 -0
- package/src/native/ghidra/index.ts +157 -0
- package/src/native/ghidra/language/c64rt_6510.cspec +34 -0
- package/src/native/ghidra/language/c64rt_6510.ldefs +15 -0
- package/src/native/ghidra/language/c64rt_6510.pspec +15 -0
- package/src/native/ghidra/language/c64rt_6510.slaspec +596 -0
- package/src/native/ghidra/scripts/C64Export.java +242 -0
- package/src/native/ghidra/scripts/C64Prepare.java +60 -0
- package/src/native/local.ts +34 -0
- package/src/native/processes.ts +350 -0
- package/src/native/run.ts +172 -0
- package/src/native/staging.ts +83 -0
- package/src/native/status.ts +101 -0
- package/src/native/types.ts +228 -0
- package/src/native/watchdog.ts +78 -0
- package/src/project.ts +39 -0
- package/src/protocol/framing.ts +132 -0
- package/src/protocol/messages.ts +252 -0
- package/src/protocol/tools.ts +247 -0
- package/src/protocol/vice.ts +1235 -0
- package/src/script.ts +59 -0
- package/src/time.ts +15 -0
- package/src/trace.ts +162 -0
- package/THIRD-PARTY-NOTICES.md +0 -26
- package/bin/cli.mjs +0 -283
- package/skills/acme-build/SKILL.md +0 -260
- package/skills/acme-build/scripts/acme.mjs +0 -341
- package/skills/acme-build/template.a +0 -53
- package/skills/c64-disk-access/SKILL.md +0 -159
- package/skills/c64-disk-access/scripts/c1541.mjs +0 -569
- package/skills/c64-memory-mapping/SKILL.md +0 -631
- package/skills/c64-memory-mapping/memmap.json +0 -8800
- package/skills/c64-memory-mapping/scripts/driver.mjs +0 -553
- package/skills/c64-petcat/SKILL.md +0 -87
- package/skills/c64-petcat/scripts/petcat.mjs +0 -221
- package/skills/c64-program-recon/SKILL.md +0 -706
- package/skills/c64-program-recon/references/control-flow.md +0 -180
- package/skills/c64-program-recon/references/graphics.md +0 -79
- package/skills/c64-program-recon/references/observation-hazards.md +0 -143
- package/skills/c64-program-recon/references/reconstruction.md +0 -133
- package/skills/c64-program-recon/references/sound-and-input.md +0 -74
- package/skills/c64-program-recon/references/tool-selection.md +0 -78
- package/skills/c64-program-recon/scripts/derive.mjs +0 -364
- package/skills/c64-program-recon/scripts/packer-finding.mjs +0 -709
- package/skills/c64-program-recon/templates/memory-map.template.md +0 -101
- package/skills/c64-provenance-diff/SKILL.md +0 -292
- package/skills/c64-provenance-diff/scripts/diff-images.mjs +0 -984
- package/skills/c64-provenance-diff/scripts/recovery-schema.mjs +0 -395
- package/skills/c64-ram-capture/RELEASES.json.example +0 -17
- package/skills/c64-ram-capture/SKILL.md +0 -474
- package/skills/c64-ram-capture/scripts/compare-cross-binary.mjs +0 -525
- package/skills/c64-ram-capture/scripts/compare.mjs +0 -258
- package/skills/c64-ram-capture/scripts/derive-transients.mjs +0 -575
- package/skills/c64-ram-capture/scripts/dump-artifacts.mjs +0 -317
- package/skills/c64-ram-capture/scripts/mcp-module.mjs +0 -174
- package/skills/c64-ram-capture/scripts/project-paths.mjs +0 -81
- package/skills/c64-ram-capture/scripts/releases.mjs +0 -109
- package/skills/c64-ram-capture/scripts/vsf-slice.mjs +0 -147
- package/skills/c64-ram-capture/scripts/watch-loads.mjs +0 -581
- package/skills/c64-ram-capture/templates/capture-record.template.md +0 -99
- package/skills/c64-ram-capture/transients/README.md +0 -137
- package/skills/routine-queue-walker/SKILL.md +0 -394
- package/skills/routine-queue-walker/scripts/completeness-report.mjs +0 -465
- package/skills/vice-wedge-triage/SKILL.md +0 -269
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Compare 65536-byte C64 RAM captures and classify every difference.
|
|
3
|
-
//
|
|
4
|
-
// Pure logic. This module reads files the agent already captured and does
|
|
5
|
-
// arithmetic over them. It contacts nothing: the mcp__plugin_c64-re-tools_vice__* tools are the
|
|
6
|
-
// only route to the emulator (.claude/CLAUDE.md § Emulator Access), and
|
|
7
|
-
// nothing here opens a connection, reads broker state, or shells out.
|
|
8
|
-
//
|
|
9
|
-
// The classification rules are the ones c64-ram-capture/SKILL.md states, and
|
|
10
|
-
// they live here so they are applied identically every time instead of being
|
|
11
|
-
// re-derived by hand per session:
|
|
12
|
-
//
|
|
13
|
-
// volatile $0000-$0001, $0100-$01FF, $0200-$03FF, $D000-$DFFF -- counted,
|
|
14
|
-
// reported, excluded from the verdict
|
|
15
|
-
// drift exactly one bit differs -- listed as a candidate, does not fail
|
|
16
|
-
// divergence two or more bits differ -- listed, and fails the comparison
|
|
17
|
-
//
|
|
18
|
-
// $D000-$DFFF is this module's one departure from what SKILL.md said when it was
|
|
19
|
-
// written: that range is I/O, not RAM, so it can never be stable. See the VOLATILE
|
|
20
|
-
// table below for the evidence (observed 2026-08-04).
|
|
21
|
-
|
|
22
|
-
import { readFileSync } from "node:fs";
|
|
23
|
-
import { createHash } from "node:crypto";
|
|
24
|
-
import { basename } from "node:path";
|
|
25
|
-
|
|
26
|
-
const IMAGE_BYTES = 65536;
|
|
27
|
-
|
|
28
|
-
// Volatile spans, inclusive. A difference inside these is expected on any two
|
|
29
|
-
// captures of the same checkpoint and never fails a comparison.
|
|
30
|
-
const VOLATILE = [
|
|
31
|
-
[0x0000, 0x0001], // CPU port
|
|
32
|
-
[0x0100, 0x01ff], // stack page
|
|
33
|
-
[0x0200, 0x03ff], // KERNAL work area / BASIC input buffer
|
|
34
|
-
// $D000-$DFFF is I/O, not RAM: the VIC's registers repeat every $40 across
|
|
35
|
-
// $D000-$D3FF and the SID's across $D400-$D7FF, so reading this range samples
|
|
36
|
-
// live hardware and two captures can never agree here. Added 2026-08-04 after
|
|
37
|
-
// every divergence across all six committed gameentry pairings landed either
|
|
38
|
-
// here ($D344, $D625, $D628) or in RAM under KERNAL ROM -- see
|
|
39
|
-
// Observed 2026-08-04. Confidence HIGH: structural.
|
|
40
|
-
[0xd000, 0xdfff],
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
// Deliberately NOT volatile: $E000-$FFFF (RAM under KERNAL ROM when HIRAM=0).
|
|
44
|
-
// $FAD8 and $FC51 do differ across captures, but only 2 addresses out of 8192 --
|
|
45
|
-
// far too few for power-on garbage, and unexplained. Blanket-excluding 8 KB on
|
|
46
|
-
// two data points would hide real divergence, so these still fail and the
|
|
47
|
-
// capture record carries the explanation. Confidence MEDIUM, see the same entry.
|
|
48
|
-
|
|
49
|
-
const isVolatile = (a) => VOLATILE.some(([lo, hi]) => a >= lo && a <= hi);
|
|
50
|
-
|
|
51
|
-
const hex4 = (n) => "$" + n.toString(16).toUpperCase().padStart(4, "0");
|
|
52
|
-
const hex2 = (n) => "$" + n.toString(16).toUpperCase().padStart(2, "0");
|
|
53
|
-
const bin8 = (n) => "%" + n.toString(2).padStart(8, "0");
|
|
54
|
-
|
|
55
|
-
const popcount = (n) => {
|
|
56
|
-
let c = 0;
|
|
57
|
-
while (n) {
|
|
58
|
-
n &= n - 1;
|
|
59
|
-
c++;
|
|
60
|
-
}
|
|
61
|
-
return c;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
function loadImage(path) {
|
|
65
|
-
const buf = readFileSync(path);
|
|
66
|
-
if (buf.length !== IMAGE_BYTES) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`${path}: ${buf.length} bytes, expected ${IMAGE_BYTES} — not a full 64K image`,
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
return buf;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const sha256 = (buf) => createHash("sha256").update(buf).digest("hex");
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Classify every differing address between two images.
|
|
78
|
-
* Returns { volatile[], drift[], divergence[], pass } — the three lists
|
|
79
|
-
* SKILL.md requires, plus the verdict.
|
|
80
|
-
*/
|
|
81
|
-
function compare(a, b) {
|
|
82
|
-
const volatile_ = [];
|
|
83
|
-
const drift = [];
|
|
84
|
-
const divergence = [];
|
|
85
|
-
|
|
86
|
-
for (let addr = 0; addr < IMAGE_BYTES; addr++) {
|
|
87
|
-
const x = a[addr];
|
|
88
|
-
const y = b[addr];
|
|
89
|
-
if (x === y) continue;
|
|
90
|
-
|
|
91
|
-
const bits = popcount(x ^ y);
|
|
92
|
-
const rec = { addr, a: x, b: y, bits };
|
|
93
|
-
|
|
94
|
-
// Volatile wins over bit-count: an address in a volatile span is excluded
|
|
95
|
-
// from the verdict regardless of how many bits moved.
|
|
96
|
-
if (isVolatile(addr)) volatile_.push(rec);
|
|
97
|
-
else if (bits === 1) drift.push(rec);
|
|
98
|
-
else divergence.push(rec);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return { volatile: volatile_, drift, divergence, pass: divergence.length === 0 };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const fmtRow = (r) =>
|
|
105
|
-
` ${hex4(r.addr)} ${hex2(r.a)} ${bin8(r.a)} -> ${hex2(r.b)} ${bin8(r.b)} ${r.bits} bit${r.bits === 1 ? "" : "s"}`;
|
|
106
|
-
|
|
107
|
-
function printList(title, rows, limit) {
|
|
108
|
-
console.log(`\n${title}: ${rows.length}`);
|
|
109
|
-
if (!rows.length) return;
|
|
110
|
-
// --limit 0 means unlimited, matching the usage text. Anything else caps.
|
|
111
|
-
const shown = limit ? rows.slice(0, limit) : rows;
|
|
112
|
-
for (const r of shown) console.log(fmtRow(r));
|
|
113
|
-
if (shown.length < rows.length) {
|
|
114
|
-
console.log(` … ${rows.length - shown.length} more (--limit 0 for all)`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function cmdCompare(argv) {
|
|
119
|
-
const limit = limitFrom(argv);
|
|
120
|
-
const paths = argv.filter((s) => !s.startsWith("--") && !/^\d+$/.test(s));
|
|
121
|
-
if (paths.length !== 2) throw new Error("compare needs exactly two image paths");
|
|
122
|
-
|
|
123
|
-
const [pa, pb] = paths;
|
|
124
|
-
const a = loadImage(pa);
|
|
125
|
-
const b = loadImage(pb);
|
|
126
|
-
|
|
127
|
-
const ha = sha256(a);
|
|
128
|
-
const hb = sha256(b);
|
|
129
|
-
|
|
130
|
-
console.log(`A ${basename(pa)} sha256 ${ha}`);
|
|
131
|
-
console.log(`B ${basename(pb)} sha256 ${hb}`);
|
|
132
|
-
|
|
133
|
-
if (ha === hb) {
|
|
134
|
-
console.log("\nIDENTICAL — the two images are byte-for-byte equal.");
|
|
135
|
-
console.log("\nVERDICT: PASS");
|
|
136
|
-
return 0;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const r = compare(a, b);
|
|
140
|
-
|
|
141
|
-
printList("volatile (excluded from the verdict)", r.volatile, limit);
|
|
142
|
-
printList("drift — exactly one bit, reported as candidates", r.drift, limit);
|
|
143
|
-
printList("DIVERGENCE — two or more bits, fails the comparison", r.divergence, limit);
|
|
144
|
-
|
|
145
|
-
const total = r.volatile.length + r.drift.length + r.divergence.length;
|
|
146
|
-
console.log(`\ntotal differing addresses: ${total} of ${IMAGE_BYTES}`);
|
|
147
|
-
console.log(`\nVERDICT: ${r.pass ? "PASS" : "FAIL"}`);
|
|
148
|
-
if (r.pass && r.drift.length) {
|
|
149
|
-
console.log("Drift candidates present — pass, but record them with the capture.");
|
|
150
|
-
}
|
|
151
|
-
return r.pass ? 0 : 1;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Drift floor across N captures of the same checkpoint: every address that
|
|
156
|
-
* differed in ANY pairing. Reported as a floor, never as a complete set —
|
|
157
|
-
* more captures can only widen it.
|
|
158
|
-
*/
|
|
159
|
-
function cmdFloor(argv) {
|
|
160
|
-
const limit = limitFrom(argv);
|
|
161
|
-
const paths = argv.filter((s) => !s.startsWith("--") && !/^\d+$/.test(s));
|
|
162
|
-
if (paths.length < 2) throw new Error("floor needs at least two image paths");
|
|
163
|
-
|
|
164
|
-
const imgs = paths.map((p) => ({ path: p, buf: loadImage(p) }));
|
|
165
|
-
for (const i of imgs) console.log(`${basename(i.path)} sha256 ${sha256(i.buf)}`);
|
|
166
|
-
|
|
167
|
-
const floor = new Map(); // addr -> Set of distinct values seen
|
|
168
|
-
let worstPair = null;
|
|
169
|
-
|
|
170
|
-
for (let i = 0; i < imgs.length; i++) {
|
|
171
|
-
for (let j = i + 1; j < imgs.length; j++) {
|
|
172
|
-
const r = compare(imgs[i].buf, imgs[j].buf);
|
|
173
|
-
for (const rec of [...r.volatile, ...r.drift, ...r.divergence]) {
|
|
174
|
-
if (!floor.has(rec.addr)) floor.set(rec.addr, new Set());
|
|
175
|
-
floor.get(rec.addr).add(rec.a);
|
|
176
|
-
floor.get(rec.addr).add(rec.b);
|
|
177
|
-
}
|
|
178
|
-
const label = `${basename(imgs[i].path)} vs ${basename(imgs[j].path)}`;
|
|
179
|
-
console.log(
|
|
180
|
-
`\n${label}: ${r.volatile.length} volatile, ${r.drift.length} drift, ${r.divergence.length} divergence -> ${r.pass ? "PASS" : "FAIL"}`,
|
|
181
|
-
);
|
|
182
|
-
if (!r.pass && (!worstPair || r.divergence.length > worstPair.n)) {
|
|
183
|
-
worstPair = { label, n: r.divergence.length };
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const addrs = [...floor.keys()].sort((x, y) => x - y);
|
|
189
|
-
const vol = addrs.filter(isVolatile).length;
|
|
190
|
-
|
|
191
|
-
console.log(`\nDRIFT FLOOR: ${addrs.length} addresses (${vol} inside volatile spans)`);
|
|
192
|
-
const shown = limit === 0 ? addrs : addrs.slice(0, limit || 40);
|
|
193
|
-
for (const a of shown) {
|
|
194
|
-
const vals = [...floor.get(a)].sort((p, q) => p - q).map(hex2).join(" / ");
|
|
195
|
-
console.log(` ${hex4(a)}${isVolatile(a) ? " [volatile]" : " "} ${vals}`);
|
|
196
|
-
}
|
|
197
|
-
if (shown.length < addrs.length) {
|
|
198
|
-
console.log(` … ${addrs.length - shown.length} more (--limit 0 for all)`);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
console.log(
|
|
202
|
-
"\nThis is a FLOOR, not a complete set — more captures of the same checkpoint can only widen it.",
|
|
203
|
-
);
|
|
204
|
-
if (worstPair) {
|
|
205
|
-
const n = worstPair.n;
|
|
206
|
-
console.log(`Worst pairing: ${worstPair.label} (${n} divergence${n === 1 ? "" : "s"}).`);
|
|
207
|
-
}
|
|
208
|
-
return 0;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** SHA-256 and size of each image, for recording alongside a capture. */
|
|
212
|
-
function cmdDigest(argv) {
|
|
213
|
-
const paths = argv.filter((s) => !s.startsWith("--"));
|
|
214
|
-
if (!paths.length) throw new Error("digest needs at least one image path");
|
|
215
|
-
for (const p of paths) {
|
|
216
|
-
const buf = readFileSync(p);
|
|
217
|
-
const ok = buf.length === IMAGE_BYTES;
|
|
218
|
-
console.log(
|
|
219
|
-
`${sha256(buf)} ${buf.length} bytes${ok ? "" : " *** NOT 65536 — not a full image ***"} ${basename(p)}`,
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
return 0;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function limitFrom(argv) {
|
|
226
|
-
const i = argv.indexOf("--limit");
|
|
227
|
-
if (i < 0) return undefined;
|
|
228
|
-
const n = Number(argv[i + 1]);
|
|
229
|
-
if (!Number.isInteger(n) || n < 0) throw new Error("--limit needs a non-negative integer");
|
|
230
|
-
return n;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const commands = { compare: cmdCompare, floor: cmdFloor, digest: cmdDigest };
|
|
234
|
-
|
|
235
|
-
const [cmd, ...rest] = process.argv.slice(2);
|
|
236
|
-
if (!cmd || !commands[cmd]) {
|
|
237
|
-
console.error(`usage: node compare.mjs <command>
|
|
238
|
-
|
|
239
|
-
compare <a.bin> <b.bin> [--limit N] classify every difference, print a verdict
|
|
240
|
-
floor <a.bin> <b.bin> [...] [--limit N] drift floor across N captures of one checkpoint
|
|
241
|
-
digest <image.bin>... sha256 + size, for the capture record
|
|
242
|
-
|
|
243
|
-
Volatile (counted, excluded from the verdict): $0000-$0001, $0100-$01FF, $0200-$03FF, $D000-$DFFF.
|
|
244
|
-
$D000-$DFFF is I/O, not RAM — reading it samples live hardware, so it can never be stable.
|
|
245
|
-
One differing bit is drift and passes; two or more is divergence and fails.
|
|
246
|
-
--limit 0 prints every row. Exit status is 1 on a FAIL verdict.
|
|
247
|
-
|
|
248
|
-
Images come from the capture procedure in this skill's SKILL.md, via mcp__plugin_c64-re-tools_vice__*.
|
|
249
|
-
This script contacts nothing.`);
|
|
250
|
-
process.exit(cmd ? 1 : 0);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
try {
|
|
254
|
-
process.exit(commands[cmd](rest));
|
|
255
|
-
} catch (e) {
|
|
256
|
-
console.error(`error: ${e.message}`);
|
|
257
|
-
process.exit(1);
|
|
258
|
-
}
|