gdharness 1.0.16 → 1.0.17

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.
Files changed (2) hide show
  1. package/build/cli.js +640 -590
  2. package/package.json +1 -1
package/build/cli.js CHANGED
@@ -47,10 +47,233 @@ var __esm = (fn, res, err) => () => {
47
47
  };
48
48
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
49
49
 
50
+ // src/errors.ts
51
+ function errorMessage(error, fallback = "Unknown error") {
52
+ if (error instanceof Error) {
53
+ return error.message || fallback;
54
+ }
55
+ if (typeof error === "string") {
56
+ return error || fallback;
57
+ }
58
+ if (typeof error === "number" || typeof error === "boolean") {
59
+ return String(error);
60
+ }
61
+ return fallback;
62
+ }
63
+ function toError(error) {
64
+ return error instanceof Error ? error : new Error(errorMessage(error), { cause: error });
65
+ }
66
+ var Refusal;
67
+ var init_errors = __esm(() => {
68
+ Refusal = class Refusal extends Error {
69
+ };
70
+ });
71
+
72
+ // src/process-children.ts
73
+ import { execFile, execFileSync, spawnSync } from "node:child_process";
74
+ import { basename } from "node:path";
75
+ import { promisify } from "node:util";
76
+ function startTimesOf(pids) {
77
+ const began = new Map;
78
+ if (pids.length === 0) {
79
+ return began;
80
+ }
81
+ try {
82
+ if (process.platform === "win32") {
83
+ const filter = pids.map((pid) => `ProcessId=${pid}`).join(" OR ");
84
+ const said = execFileSync("powershell", [
85
+ "-NoProfile",
86
+ "-NonInteractive",
87
+ "-Command",
88
+ `Get-CimInstance Win32_Process -Filter "${filter}" | ForEach-Object { "$($_.ProcessId) $(([DateTimeOffset]$_.CreationDate).ToUnixTimeMilliseconds())" }`
89
+ ], { encoding: "utf8", timeout: ASK_TIMEOUT_MS, windowsHide: true });
90
+ for (const line of said.split(`
91
+ `)) {
92
+ const found = /^\s*(\d+)\s+(\d+)\s*$/.exec(line);
93
+ if (found?.[1] !== undefined && found[2] !== undefined) {
94
+ began.set(Number(found[1]), Number(found[2]));
95
+ }
96
+ }
97
+ return began;
98
+ }
99
+ const said = spawnSync("ps", ["-p", pids.join(","), "-o", "pid=,lstart="], {
100
+ encoding: "utf8",
101
+ timeout: ASK_TIMEOUT_MS,
102
+ env: { ...process.env, LC_ALL: "C" }
103
+ }).stdout;
104
+ for (const line of said.split(`
105
+ `)) {
106
+ const found = /^\s*(\d+)\s+(.+)$/.exec(line);
107
+ const at = Date.parse(found?.[2]?.trim() ?? "");
108
+ if (found?.[1] !== undefined && !Number.isNaN(at)) {
109
+ began.set(Number(found[1]), at);
110
+ }
111
+ }
112
+ } catch {}
113
+ return began;
114
+ }
115
+ async function processTree() {
116
+ try {
117
+ if (process.platform === "win32") {
118
+ return parseProcessTable(await askWindows(), true);
119
+ }
120
+ return parseProcessTable(await askPosix());
121
+ } catch {
122
+ return;
123
+ }
124
+ }
125
+ function parseProcessTable(printed, started = false) {
126
+ const tree = new Map;
127
+ for (const line of printed.split(/\r?\n/)) {
128
+ const fields = /^\s*(\d+)\s+(\d+)(?:\s+(.*))?$/.exec(line);
129
+ if (fields === null) {
130
+ continue;
131
+ }
132
+ const pid = Number(fields[1]);
133
+ const parent = Number(fields[2]);
134
+ const rest = (fields[3] ?? "").trim();
135
+ if (pid <= 0) {
136
+ continue;
137
+ }
138
+ if (!started) {
139
+ tree.set(pid, { parent, command: rest });
140
+ continue;
141
+ }
142
+ const timed = /^(\d+)(?:\s+(.*))?$/.exec(rest);
143
+ if (timed === null) {
144
+ continue;
145
+ }
146
+ const began = Number(timed[1]);
147
+ tree.set(pid, { parent, command: (timed[2] ?? "").trim(), ...began > 0 ? { startedAt: began } : {} });
148
+ }
149
+ return tree;
150
+ }
151
+ function linked(tree, child, parent) {
152
+ const from = tree.get(child);
153
+ const to = tree.get(parent);
154
+ if (from === undefined || from.parent !== parent) {
155
+ return false;
156
+ }
157
+ if (from.startedAt === undefined || to?.startedAt === undefined) {
158
+ return true;
159
+ }
160
+ return from.startedAt >= to.startedAt;
161
+ }
162
+ function childrenIn(tree, pid) {
163
+ const children = [];
164
+ for (const child of tree.keys()) {
165
+ if (linked(tree, child, pid)) {
166
+ children.push(child);
167
+ }
168
+ }
169
+ return children;
170
+ }
171
+ function descendantsIn(tree, pid) {
172
+ const found = [];
173
+ const queue = [pid];
174
+ const seen = new Set([pid]);
175
+ while (queue.length > 0) {
176
+ const next = queue.shift();
177
+ if (next === undefined) {
178
+ break;
179
+ }
180
+ for (const child of childrenIn(tree, next)) {
181
+ if (!seen.has(child)) {
182
+ seen.add(child);
183
+ found.push(child);
184
+ queue.push(child);
185
+ }
186
+ }
187
+ }
188
+ return found;
189
+ }
190
+ function ancestorsIn(tree, pid, root) {
191
+ const chain = [];
192
+ const seen = new Set([pid]);
193
+ let child = pid;
194
+ let parent = tree.get(pid)?.parent;
195
+ while (parent !== undefined && !seen.has(parent) && linked(tree, child, parent)) {
196
+ chain.push(parent);
197
+ if (parent === root) {
198
+ break;
199
+ }
200
+ seen.add(parent);
201
+ child = parent;
202
+ parent = tree.get(parent)?.parent;
203
+ }
204
+ return chain;
205
+ }
206
+ function readCommandLine(command) {
207
+ const words = commandWords(command);
208
+ const executable = words[0] === undefined ? "" : basename(words[0].replaceAll("\\", "/"));
209
+ const at = words.indexOf("--path");
210
+ let projectPath = null;
211
+ if (at !== -1 && at + 1 < words.length) {
212
+ const taken = [];
213
+ for (const word of words.slice(at + 1)) {
214
+ if (taken.length > 0 && (word.startsWith("-") || /^[a-z]+:\/\//.test(word))) {
215
+ break;
216
+ }
217
+ taken.push(word);
218
+ }
219
+ projectPath = taken.join(" ");
220
+ }
221
+ return {
222
+ executable,
223
+ projectPath,
224
+ editor: words.some((word) => word === "-e" || word === "--editor")
225
+ };
226
+ }
227
+ function commandWords(command) {
228
+ const words = [];
229
+ let word = "";
230
+ let quoted = false;
231
+ let started = false;
232
+ for (const char of command) {
233
+ if (char === '"') {
234
+ quoted = !quoted;
235
+ started = true;
236
+ } else if (!quoted && /\s/.test(char)) {
237
+ if (started) {
238
+ words.push(word);
239
+ word = "";
240
+ started = false;
241
+ }
242
+ } else {
243
+ word += char;
244
+ started = true;
245
+ }
246
+ }
247
+ if (started) {
248
+ words.push(word);
249
+ }
250
+ return words;
251
+ }
252
+ async function askWindows() {
253
+ const { stdout } = await run("powershell.exe", [
254
+ "-NoProfile",
255
+ "-NonInteractive",
256
+ "-Command",
257
+ `${POWERSHELL_UTF8}Get-CimInstance Win32_Process | ForEach-Object { $began = 0; if ($_.CreationDate) { $began = ([DateTimeOffset]$_.CreationDate).ToUnixTimeMilliseconds() }; "$($_.ProcessId) $($_.ParentProcessId) $began $($_.CommandLine)" }`
258
+ ], { timeout: ASK_TIMEOUT_MS, windowsHide: true, maxBuffer: 16 * 1024 * 1024 });
259
+ return stdout;
260
+ }
261
+ async function askPosix() {
262
+ const { stdout } = await run("ps", ["-e", "-o", "pid=,ppid=,args="], {
263
+ timeout: ASK_TIMEOUT_MS,
264
+ maxBuffer: 16 * 1024 * 1024
265
+ });
266
+ return stdout;
267
+ }
268
+ var run, POWERSHELL_UTF8 = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; ", ASK_TIMEOUT_MS = 15000;
269
+ var init_process_children = __esm(() => {
270
+ run = promisify(execFile);
271
+ });
272
+
50
273
  // src/detection.ts
51
274
  import { existsSync, readdirSync, statSync } from "node:fs";
52
275
  import { homedir } from "node:os";
53
- import { join } from "node:path";
276
+ import { join as join2 } from "node:path";
54
277
  function resolveHomeDirectory() {
55
278
  try {
56
279
  return homedir();
@@ -74,7 +297,7 @@ function scanDirectoryForGodotBinaries(directory, platform) {
74
297
  if (!pattern.test(name)) {
75
298
  continue;
76
299
  }
77
- const fullPath = join(directory, name);
300
+ const fullPath = join2(directory, name);
78
301
  try {
79
302
  const stat = statSync(fullPath);
80
303
  if (stat.isFile()) {
@@ -83,7 +306,7 @@ function scanDirectoryForGodotBinaries(directory, platform) {
83
306
  } catch {}
84
307
  }
85
308
  matches.sort((a, b) => b.mtime - a.mtime);
86
- return matches.map((m) => join(directory, m.name));
309
+ return matches.map((m) => join2(directory, m.name));
87
310
  }
88
311
  function conventionalPaths(platform, home) {
89
312
  const paths = ["godot"];
@@ -133,28 +356,6 @@ function godotCandidates(platform, home) {
133
356
  }
134
357
  var init_detection = () => {};
135
358
 
136
- // src/errors.ts
137
- function errorMessage(error, fallback = "Unknown error") {
138
- if (error instanceof Error) {
139
- return error.message || fallback;
140
- }
141
- if (typeof error === "string") {
142
- return error || fallback;
143
- }
144
- if (typeof error === "number" || typeof error === "boolean") {
145
- return String(error);
146
- }
147
- return fallback;
148
- }
149
- function toError(error) {
150
- return error instanceof Error ? error : new Error(errorMessage(error), { cause: error });
151
- }
152
- var Refusal2;
153
- var init_errors = __esm(() => {
154
- Refusal2 = class Refusal2 extends Error {
155
- };
156
- });
157
-
158
359
  // src/launch.ts
159
360
  function envValue(name, variables = process.env) {
160
361
  const value = variables[name];
@@ -7161,7 +7362,7 @@ var require_public_api = __commonJS(function(exports) {
7161
7362
 
7162
7363
  // src/runner.ts
7163
7364
  import { existsSync as existsSync3 } from "node:fs";
7164
- import { dirname, join as join2 } from "node:path";
7365
+ import { dirname as dirname2, join as join3 } from "node:path";
7165
7366
  import process2 from "node:process";
7166
7367
  function currentRunner() {
7167
7368
  const versions = process2.versions;
@@ -7182,7 +7383,7 @@ function spawnFor(runner, version, execPath = process2.execPath) {
7182
7383
  return { command: alongside(execPath, "npx") ?? "npx", args: ["-y", spec] };
7183
7384
  }
7184
7385
  function alongside(execPath, name) {
7185
- const runner = join2(dirname(execPath), process2.platform === "win32" ? `${name}.cmd` : name);
7386
+ const runner = join3(dirname2(execPath), process2.platform === "win32" ? `${name}.cmd` : name);
7186
7387
  return existsSync3(runner) ? runner : undefined;
7187
7388
  }
7188
7389
  var init_runner = () => {};
@@ -7324,7 +7525,7 @@ var init_game_log = __esm(() => {
7324
7525
  });
7325
7526
 
7326
7527
  // src/scratch.ts
7327
- import { rmSync as rmSync2 } from "node:fs";
7528
+ import { rmSync as rmSync3 } from "node:fs";
7328
7529
  function discardWith(remove, paths) {
7329
7530
  const left = [];
7330
7531
  for (const path of paths) {
@@ -7341,7 +7542,7 @@ function discardWith(remove, paths) {
7341
7542
  }
7342
7543
  function discard(...paths) {
7343
7544
  return discardWith((path) => {
7344
- rmSync2(path, SWEPT);
7545
+ rmSync3(path, SWEPT);
7345
7546
  }, paths);
7346
7547
  }
7347
7548
  var SWEPT;
@@ -7350,9 +7551,9 @@ var init_scratch = __esm(() => {
7350
7551
  });
7351
7552
 
7352
7553
  // src/update-check.ts
7353
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
7554
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
7354
7555
  import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
7355
- import { join as join5 } from "node:path";
7556
+ import { join as join6 } from "node:path";
7356
7557
  function packageUrl(root) {
7357
7558
  return `${root.replace(/\/+$/, "")}/gdharness/latest`;
7358
7559
  }
@@ -7374,20 +7575,20 @@ function cacheDirectory(environment) {
7374
7575
  };
7375
7576
  const home = set("HOME") ?? homedir3();
7376
7577
  if (process.platform === "win32") {
7377
- return join5(set("LOCALAPPDATA") ?? home, "gdharness");
7578
+ return join6(set("LOCALAPPDATA") ?? home, "gdharness");
7378
7579
  }
7379
7580
  if (process.platform === "darwin") {
7380
- return join5(home, "Library", "Caches", "gdharness");
7581
+ return join6(home, "Library", "Caches", "gdharness");
7381
7582
  }
7382
- return join5(set("XDG_CACHE_HOME") ?? join5(home, ".cache"), "gdharness");
7583
+ return join6(set("XDG_CACHE_HOME") ?? join6(home, ".cache"), "gdharness");
7383
7584
  }
7384
7585
  function cacheFile(environment = process.env) {
7385
7586
  try {
7386
7587
  const directory = cacheDirectory(environment);
7387
- mkdirSync2(directory, { recursive: true, mode: 448 });
7388
- return join5(directory, "update-check.json");
7588
+ mkdirSync3(directory, { recursive: true, mode: 448 });
7589
+ return join6(directory, "update-check.json");
7389
7590
  } catch {
7390
- return join5(tmpdir2(), "gdharness-update-check.json");
7591
+ return join6(tmpdir2(), "gdharness-update-check.json");
7391
7592
  }
7392
7593
  }
7393
7594
  function readCache(path) {
@@ -7395,7 +7596,7 @@ function readCache(path) {
7395
7596
  if (!existsSync5(path)) {
7396
7597
  return null;
7397
7598
  }
7398
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
7599
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
7399
7600
  if (typeof parsed !== "object" || parsed === null) {
7400
7601
  return null;
7401
7602
  }
@@ -7412,7 +7613,7 @@ function readCache(path) {
7412
7613
  }
7413
7614
  function writeCache(path, entry) {
7414
7615
  try {
7415
- writeFileSync3(path, JSON.stringify(entry), { encoding: "utf8", mode: 384 });
7616
+ writeFileSync4(path, JSON.stringify(entry), { encoding: "utf8", mode: 384 });
7416
7617
  } catch {}
7417
7618
  }
7418
7619
  function parts(version) {
@@ -7543,7 +7744,7 @@ var init_update_check = __esm(() => {
7543
7744
  });
7544
7745
 
7545
7746
  // src/server-version.ts
7546
- import { readFileSync as readFileSync3 } from "node:fs";
7747
+ import { readFileSync as readFileSync4 } from "node:fs";
7547
7748
  function editorIsStale(addonVersion, serverVersion, addonDigest, shippedDigest) {
7548
7749
  if (addonDigest !== undefined && addonDigest !== "" && shippedDigest !== undefined) {
7549
7750
  return addonDigest !== shippedDigest;
@@ -7579,7 +7780,7 @@ var init_server_version = __esm(() => {
7579
7780
  GODOT_DEBUG_MODE_DEFAULT = process.env["GODOT_DEBUG"] === "true" || DEBUG_MODE;
7580
7781
  SERVER_VERSION = (() => {
7581
7782
  try {
7582
- const pkg = JSON.parse(readFileSync3(new URL("../package.json", import.meta.url), "utf8"));
7783
+ const pkg = JSON.parse(readFileSync4(new URL("../package.json", import.meta.url), "utf8"));
7583
7784
  return typeof pkg.version === "string" ? pkg.version : "0.0.0";
7584
7785
  } catch {
7585
7786
  return "0.0.0";
@@ -7588,23 +7789,23 @@ var init_server_version = __esm(() => {
7588
7789
  });
7589
7790
 
7590
7791
  // src/class-cache.ts
7591
- import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
7592
- import { join as join6 } from "node:path";
7792
+ import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
7793
+ import { join as join7 } from "node:path";
7593
7794
  function declaredClasses(projectPath) {
7594
7795
  const declared = new Map;
7595
7796
  const visit = (directory, prefix) => {
7596
- if (existsSync6(join6(directory, ".gdignore"))) {
7797
+ if (existsSync6(join7(directory, ".gdignore"))) {
7597
7798
  return;
7598
7799
  }
7599
7800
  for (const entry of readdirSync2(directory, { withFileTypes: true })) {
7600
7801
  if (entry.name.startsWith(".")) {
7601
7802
  continue;
7602
7803
  }
7603
- const path = join6(directory, entry.name);
7804
+ const path = join7(directory, entry.name);
7604
7805
  if (entry.isDirectory()) {
7605
7806
  visit(path, `${prefix}${entry.name}/`);
7606
7807
  } else if (entry.isFile() && entry.name.endsWith(".gd")) {
7607
- const found = DECLARATION.exec(readFileSync5(path, "utf8"));
7808
+ const found = DECLARATION.exec(readFileSync6(path, "utf8"));
7608
7809
  if (found?.[1]) {
7609
7810
  declared.set(found[1], `res://${prefix}${entry.name}`);
7610
7811
  }
@@ -7615,12 +7816,12 @@ function declaredClasses(projectPath) {
7615
7816
  return declared;
7616
7817
  }
7617
7818
  function cachedClasses(projectPath) {
7618
- const cache = join6(projectPath, ".godot", "global_script_class_cache.cfg");
7819
+ const cache = join7(projectPath, ".godot", "global_script_class_cache.cfg");
7619
7820
  if (!existsSync6(cache)) {
7620
7821
  return null;
7621
7822
  }
7622
7823
  const listed = new Map;
7623
- const text = readFileSync5(cache, "utf8");
7824
+ const text = readFileSync6(cache, "utf8");
7624
7825
  for (const entry of text.matchAll(/"class":\s*&"([^"]+)"[\s\S]*?"path":\s*"([^"]+)"/g)) {
7625
7826
  listed.set(entry[1] ?? "", entry[2] ?? "");
7626
7827
  }
@@ -7705,7 +7906,7 @@ function uncachedClassNote(types) {
7705
7906
  return `${types.join(", ")} ${one ? "is declared" : "are declared"} in this project and missing from ` + `.godot/global_script_class_cache.cfg, so a game launched now would not resolve ${one ? "it" : "them"} ` + "either. Try editor_rescan first: it asks the editor already running and starts nothing, and it " + "cleared this in 314ms in a second project with a 31-worker fan-out still importing. It is not " + "always enough, because a file another engine has already imported reads as settled and the " + "walk does not look inside it. project_import refresh_classes rewrites the cache from the " + "declarations on disk and does reach that case, at the cost of a short headless engine, which " + "is worth knowing when something else is already running against this project.";
7706
7907
  }
7707
7908
  function cacheWrittenAt(projectPath) {
7708
- const cache = join6(projectPath, ".godot", "global_script_class_cache.cfg");
7909
+ const cache = join7(projectPath, ".godot", "global_script_class_cache.cfg");
7709
7910
  try {
7710
7911
  return statSync2(cache).mtimeMs;
7711
7912
  } catch {
@@ -7719,14 +7920,14 @@ function declaredSince(projectPath, paths, names, since) {
7719
7920
  return false;
7720
7921
  }
7721
7922
  try {
7722
- return statSync2(join6(projectPath, path.slice("res://".length))).mtimeMs > since;
7923
+ return statSync2(join7(projectPath, path.slice("res://".length))).mtimeMs > since;
7723
7924
  } catch {
7724
7925
  return false;
7725
7926
  }
7726
7927
  });
7727
7928
  }
7728
7929
  function cachedAtMissingPaths(cached, projectPath) {
7729
- return [...cached].filter(([, path]) => path.startsWith("res://") && !existsSync6(join6(projectPath, path.slice("res://".length)))).map(([name]) => name).sort();
7930
+ return [...cached].filter(([, path]) => path.startsWith("res://") && !existsSync6(join7(projectPath, path.slice("res://".length)))).map(([name]) => name).sort();
7730
7931
  }
7731
7932
  function staleAgainst(cached, projectPath) {
7732
7933
  return [...declaredClasses(projectPath)].filter(([name, path]) => cached.get(name) !== path).map(([name]) => name);
@@ -7749,11 +7950,11 @@ var init_class_cache = __esm(() => {
7749
7950
  });
7750
7951
 
7751
7952
  // src/headless.ts
7752
- import { execFile as execFile3 } from "node:child_process";
7753
- import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync4 } from "node:fs";
7953
+ import { execFile as execFile4 } from "node:child_process";
7954
+ import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync5 } from "node:fs";
7754
7955
  import { tmpdir as tmpdir3 } from "node:os";
7755
- import { join as join7 } from "node:path";
7756
- import { promisify as promisify3 } from "node:util";
7956
+ import { join as join8 } from "node:path";
7957
+ import { promisify as promisify4 } from "node:util";
7757
7958
  function snakeCased2(params) {
7758
7959
  const result = emptyRecord();
7759
7960
  for (const [key, value] of Object.entries(params)) {
@@ -7792,9 +7993,9 @@ function reason2(stdout, stderr) {
7792
7993
  return stdout.trim().split(/\r?\n/).at(-1) ?? "no output at all";
7793
7994
  }
7794
7995
  async function runImport(godotPath, projectPath) {
7795
- const logDir = mkdtempSync2(join7(tmpdir3(), "gdharness-import-"));
7996
+ const logDir = mkdtempSync2(join8(tmpdir3(), "gdharness-import-"));
7796
7997
  try {
7797
- const { stderr } = await run3(godotPath, ["--headless", "--log-file", join7(logDir, "engine.log"), "--path", projectPath, "--import"], { signal: callSignal() });
7998
+ const { stderr } = await run4(godotPath, ["--headless", "--log-file", join8(logDir, "engine.log"), "--path", projectPath, "--import"], { signal: callSignal() });
7798
7999
  return { ok: true, messages: problems2(stderr) };
7799
8000
  } catch (error) {
7800
8001
  if (error instanceof Error && "stdout" in error && "stderr" in error) {
@@ -7815,13 +8016,13 @@ async function runImport(godotPath, projectPath) {
7815
8016
  }
7816
8017
  }
7817
8018
  async function runOperation2(engine, operation, params, projectPath) {
7818
- const paramsDir = mkdtempSync2(join7(tmpdir3(), "gdharness-params-"));
7819
- const paramsFile = join7(paramsDir, `${operation}.json`);
7820
- writeFileSync4(paramsFile, JSON.stringify(snakeCased2(params)), "utf8");
8019
+ const paramsDir = mkdtempSync2(join8(tmpdir3(), "gdharness-params-"));
8020
+ const paramsFile = join8(paramsDir, `${operation}.json`);
8021
+ writeFileSync5(paramsFile, JSON.stringify(snakeCased2(params)), "utf8");
7821
8022
  const args = [
7822
8023
  "--headless",
7823
8024
  "--log-file",
7824
- join7(paramsDir, "engine.log"),
8025
+ join8(paramsDir, "engine.log"),
7825
8026
  "--path",
7826
8027
  projectPath,
7827
8028
  "--script",
@@ -7833,7 +8034,7 @@ async function runOperation2(engine, operation, params, projectPath) {
7833
8034
  let stdout;
7834
8035
  let stderr;
7835
8036
  try {
7836
- ({ stdout, stderr } = await run3(engine.godotPath, args, { signal: callSignal() }));
8037
+ ({ stdout, stderr } = await run4(engine.godotPath, args, { signal: callSignal() }));
7837
8038
  } catch (error) {
7838
8039
  if (error instanceof Error && "stdout" in error && "stderr" in error) {
7839
8040
  const failed = error;
@@ -7861,12 +8062,12 @@ async function runOperation2(engine, operation, params, projectPath) {
7861
8062
  }
7862
8063
  return { ok: true, payload, messages: problems2(stderr) };
7863
8064
  }
7864
- var run3;
8065
+ var run4;
7865
8066
  var init_headless = __esm(() => {
7866
8067
  init_call_signal();
7867
8068
  init_game_log();
7868
8069
  init_scratch();
7869
- run3 = promisify3(execFile3);
8070
+ run4 = promisify4(execFile4);
7870
8071
  });
7871
8072
 
7872
8073
  // node_modules/zod/v4/core/util.js
@@ -15034,26 +15235,26 @@ var init_paths = __esm(() => {
15034
15235
  });
15035
15236
 
15036
15237
  // src/resources.ts
15037
- import { readFileSync as readFileSync6 } from "node:fs";
15238
+ import { readFileSync as readFileSync7 } from "node:fs";
15038
15239
  import { extname, resolve as resolve2 } from "node:path";
15039
15240
  function ensureProjectPath(getProjectPath) {
15040
15241
  const projectPath = getProjectPath();
15041
15242
  if (!projectPath) {
15042
- throw new Refusal2("Project path is not set. Set a Godot project path first.");
15243
+ throw new Refusal("Project path is not set. Set a Godot project path first.");
15043
15244
  }
15044
15245
  return resolve2(projectPath);
15045
15246
  }
15046
15247
  function uriPathToProjectPath(inputPath) {
15047
15248
  const normalized = inputPath.replace(/\\/g, "/").trim();
15048
15249
  if (normalized.replace(/\//g, "") === "") {
15049
- throw new Refusal2("Resource path is empty.");
15250
+ throw new Refusal("Resource path is empty.");
15050
15251
  }
15051
15252
  return normalized.replace(/^\/+/, "");
15052
15253
  }
15053
15254
  function resolveProjectFile(projectPath, resourcePath) {
15054
15255
  const contained = resolveWithinProject(projectPath, resourcePath);
15055
15256
  if (!contained.ok) {
15056
- throw new Refusal2(contained.reason);
15257
+ throw new Refusal(contained.reason);
15057
15258
  }
15058
15259
  return contained.absolutePath;
15059
15260
  }
@@ -15065,14 +15266,14 @@ function parseGodotUri(uri) {
15065
15266
  try {
15066
15267
  parsed = new URL(uri);
15067
15268
  } catch {
15068
- throw new Refusal2(`Invalid URI: ${uri}`);
15269
+ throw new Refusal(`Invalid URI: ${uri}`);
15069
15270
  }
15070
15271
  if (parsed.protocol !== "godot:") {
15071
- throw new Refusal2(`Unsupported URI scheme: ${parsed.protocol}`);
15272
+ throw new Refusal(`Unsupported URI scheme: ${parsed.protocol}`);
15072
15273
  }
15073
15274
  const host = parsed.hostname;
15074
15275
  if (host !== "scene" && host !== "script" && host !== "resource") {
15075
- throw new Refusal2(`Unsupported Godot resource type: ${host}`);
15276
+ throw new Refusal(`Unsupported Godot resource type: ${host}`);
15076
15277
  }
15077
15278
  const resourcePath = uriPathToProjectPath(decodeURIComponent(parsed.pathname));
15078
15279
  return { kind: host, resourcePath };
@@ -15080,13 +15281,13 @@ function parseGodotUri(uri) {
15080
15281
  function ensureAllowedExtension(kind, filePath) {
15081
15282
  const extension = extname(filePath).toLowerCase();
15082
15283
  if (kind === "scene" && extension !== ".tscn") {
15083
- throw new Refusal2("Scene resources must use .tscn extension.");
15284
+ throw new Refusal("Scene resources must use .tscn extension.");
15084
15285
  }
15085
15286
  if (kind === "script" && extension !== ".gd") {
15086
- throw new Refusal2("Script resources must use .gd extension.");
15287
+ throw new Refusal("Script resources must use .gd extension.");
15087
15288
  }
15088
15289
  if (kind === "resource" && ![".tres", ".tscn", ".gd"].includes(extension)) {
15089
- throw new Refusal2("Resource URIs support only .tres, .tscn, and .gd files.");
15290
+ throw new Refusal("Resource URIs support only .tres, .tscn, and .gd files.");
15090
15291
  }
15091
15292
  }
15092
15293
  function isValueComplete(value) {
@@ -15200,7 +15401,7 @@ function readResourceText(uri, getProjectPath) {
15200
15401
  const parsedUri = parseGodotUri(uri);
15201
15402
  if (parsedUri.kind === "project-info") {
15202
15403
  const projectFilePath = resolveProjectFile(projectPath, "project.godot");
15203
- const rawProject = readFileSync6(projectFilePath, "utf-8");
15404
+ const rawProject = readFileSync7(projectFilePath, "utf-8");
15204
15405
  const parsedProject = parseProjectGodot(rawProject);
15205
15406
  return {
15206
15407
  mimeType: "application/json",
@@ -15209,7 +15410,7 @@ function readResourceText(uri, getProjectPath) {
15209
15410
  }
15210
15411
  const filePath = resolveProjectFile(projectPath, parsedUri.resourcePath);
15211
15412
  ensureAllowedExtension(parsedUri.kind, filePath);
15212
- const text = readFileSync6(filePath, "utf-8");
15413
+ const text = readFileSync7(filePath, "utf-8");
15213
15414
  return {
15214
15415
  mimeType: parsedUri.kind === "script" ? "text/x-gdscript" : "text/plain",
15215
15416
  text
@@ -15238,9 +15439,9 @@ function setupResourceHandlers(mcp, getProjectPath) {
15238
15439
  };
15239
15440
  } catch (error) {
15240
15441
  if (error instanceof Error) {
15241
- throw new Refusal2(`Failed to read resource '${uri}': ${error.message}`, { cause: error });
15442
+ throw new Refusal(`Failed to read resource '${uri}': ${error.message}`, { cause: error });
15242
15443
  }
15243
- throw new Refusal2(`Failed to read resource '${uri}'.`, { cause: error });
15444
+ throw new Refusal(`Failed to read resource '${uri}'.`, { cause: error });
15244
15445
  }
15245
15446
  });
15246
15447
  }
@@ -15341,14 +15542,14 @@ import { createHash as createHash3 } from "node:crypto";
15341
15542
  import {
15342
15543
  cpSync as cpSync2,
15343
15544
  existsSync as existsSync8,
15344
- mkdirSync as mkdirSync4,
15545
+ mkdirSync as mkdirSync5,
15345
15546
  readdirSync as readdirSync4,
15346
- readFileSync as readFileSync8,
15347
- rmSync as rmSync4,
15547
+ readFileSync as readFileSync9,
15548
+ rmSync as rmSync5,
15348
15549
  statSync as statSync4,
15349
- writeFileSync as writeFileSync6
15550
+ writeFileSync as writeFileSync7
15350
15551
  } from "node:fs";
15351
- import { dirname as dirname4, join as join9 } from "node:path";
15552
+ import { dirname as dirname5, join as join10 } from "node:path";
15352
15553
  import { fileURLToPath as fileURLToPath2 } from "node:url";
15353
15554
  function editorAddonDigest2(from = shippedAddonsDirectory2()) {
15354
15555
  const hash = createHash3("sha256");
@@ -15357,21 +15558,21 @@ function editorAddonDigest2(from = shippedAddonsDirectory2()) {
15357
15558
  if (name === VERSION_MARKER2 || name === DIGEST_MARKER2) {
15358
15559
  continue;
15359
15560
  }
15360
- const path = join9(directory, name);
15561
+ const path = join10(directory, name);
15361
15562
  const inside = `${relative}/${name}`;
15362
15563
  if (statSync4(path).isDirectory()) {
15363
15564
  walk(path, inside);
15364
15565
  } else {
15365
15566
  hash.update(`${inside}
15366
15567
  `);
15367
- hash.update(readFileSync8(path));
15568
+ hash.update(readFileSync9(path));
15368
15569
  hash.update(`
15369
15570
  `);
15370
15571
  }
15371
15572
  }
15372
15573
  };
15373
15574
  for (const name of EDITOR_PLUGINS2) {
15374
- walk(join9(from, name), name);
15575
+ walk(join10(from, name), name);
15375
15576
  }
15376
15577
  return hash.digest("hex");
15377
15578
  }
@@ -15386,14 +15587,14 @@ function shippedEditorDigest() {
15386
15587
  return shippedDigest ?? undefined;
15387
15588
  }
15388
15589
  function shippedAddonsDirectory2() {
15389
- return join9(dirname4(fileURLToPath2(import.meta.url)), "godot", "addons");
15590
+ return join10(dirname5(fileURLToPath2(import.meta.url)), "godot", "addons");
15390
15591
  }
15391
15592
  function installedAddonVersion(projectPath) {
15392
- const marker = join9(projectPath, "addons", ADDONS2[0], VERSION_MARKER2);
15593
+ const marker = join10(projectPath, "addons", ADDONS2[0], VERSION_MARKER2);
15393
15594
  if (!existsSync8(marker)) {
15394
15595
  return null;
15395
15596
  }
15396
- const said = readFileSync8(marker, "utf8").trim();
15597
+ const said = readFileSync9(marker, "utf8").trim();
15397
15598
  return said === "" ? null : said;
15398
15599
  }
15399
15600
  var ADDONS2, EDITOR_PLUGINS2, RUNTIME_AUTOLOAD2, SCRIPT_RUNS_SETTING = "gdharness/runtime/serve_script_runs", BIND_ADDRESS_SETTING = "gdharness/runtime/bind_address", PORT_SETTING = "gdharness/runtime/port", VERSION_MARKER2 = ".gdharness-version", DIGEST_MARKER2 = ".gdharness-digest", shippedDigest;
@@ -31375,212 +31576,11 @@ var init_stdio2 = __esm(() => {
31375
31576
  init_stdio();
31376
31577
  });
31377
31578
 
31378
- // src/process-children.ts
31379
- import { execFile as execFile4, execFileSync, spawnSync as spawnSync2 } from "node:child_process";
31380
- import { basename as basename2 } from "node:path";
31381
- import { promisify as promisify4 } from "node:util";
31382
- function startTimesOf(pids) {
31383
- const began = new Map;
31384
- if (pids.length === 0) {
31385
- return began;
31386
- }
31387
- try {
31388
- if (process.platform === "win32") {
31389
- const filter = pids.map((pid) => `ProcessId=${pid}`).join(" OR ");
31390
- const said = execFileSync("powershell", [
31391
- "-NoProfile",
31392
- "-NonInteractive",
31393
- "-Command",
31394
- `Get-CimInstance Win32_Process -Filter "${filter}" | ForEach-Object { "$($_.ProcessId) $(([DateTimeOffset]$_.CreationDate).ToUnixTimeMilliseconds())" }`
31395
- ], { encoding: "utf8", timeout: ASK_TIMEOUT_MS, windowsHide: true });
31396
- for (const line of said.split(`
31397
- `)) {
31398
- const found = /^\s*(\d+)\s+(\d+)\s*$/.exec(line);
31399
- if (found?.[1] !== undefined && found[2] !== undefined) {
31400
- began.set(Number(found[1]), Number(found[2]));
31401
- }
31402
- }
31403
- return began;
31404
- }
31405
- const said = spawnSync2("ps", ["-p", pids.join(","), "-o", "pid=,lstart="], {
31406
- encoding: "utf8",
31407
- timeout: ASK_TIMEOUT_MS,
31408
- env: { ...process.env, LC_ALL: "C" }
31409
- }).stdout;
31410
- for (const line of said.split(`
31411
- `)) {
31412
- const found = /^\s*(\d+)\s+(.+)$/.exec(line);
31413
- const at = Date.parse(found?.[2]?.trim() ?? "");
31414
- if (found?.[1] !== undefined && !Number.isNaN(at)) {
31415
- began.set(Number(found[1]), at);
31416
- }
31417
- }
31418
- } catch {}
31419
- return began;
31420
- }
31421
- async function processTree() {
31422
- try {
31423
- if (process.platform === "win32") {
31424
- return parseProcessTable(await askWindows(), true);
31425
- }
31426
- return parseProcessTable(await askPosix());
31427
- } catch {
31428
- return;
31429
- }
31430
- }
31431
- function parseProcessTable(printed, started = false) {
31432
- const tree = new Map;
31433
- for (const line of printed.split(/\r?\n/)) {
31434
- const fields = /^\s*(\d+)\s+(\d+)(?:\s+(.*))?$/.exec(line);
31435
- if (fields === null) {
31436
- continue;
31437
- }
31438
- const pid = Number(fields[1]);
31439
- const parent = Number(fields[2]);
31440
- const rest = (fields[3] ?? "").trim();
31441
- if (pid <= 0) {
31442
- continue;
31443
- }
31444
- if (!started) {
31445
- tree.set(pid, { parent, command: rest });
31446
- continue;
31447
- }
31448
- const timed = /^(\d+)(?:\s+(.*))?$/.exec(rest);
31449
- if (timed === null) {
31450
- continue;
31451
- }
31452
- const began = Number(timed[1]);
31453
- tree.set(pid, { parent, command: (timed[2] ?? "").trim(), ...began > 0 ? { startedAt: began } : {} });
31454
- }
31455
- return tree;
31456
- }
31457
- function linked(tree, child, parent) {
31458
- const from = tree.get(child);
31459
- const to = tree.get(parent);
31460
- if (from === undefined || from.parent !== parent) {
31461
- return false;
31462
- }
31463
- if (from.startedAt === undefined || to?.startedAt === undefined) {
31464
- return true;
31465
- }
31466
- return from.startedAt >= to.startedAt;
31467
- }
31468
- function childrenIn(tree, pid) {
31469
- const children = [];
31470
- for (const child of tree.keys()) {
31471
- if (linked(tree, child, pid)) {
31472
- children.push(child);
31473
- }
31474
- }
31475
- return children;
31476
- }
31477
- function descendantsIn(tree, pid) {
31478
- const found = [];
31479
- const queue = [pid];
31480
- const seen = new Set([pid]);
31481
- while (queue.length > 0) {
31482
- const next = queue.shift();
31483
- if (next === undefined) {
31484
- break;
31485
- }
31486
- for (const child of childrenIn(tree, next)) {
31487
- if (!seen.has(child)) {
31488
- seen.add(child);
31489
- found.push(child);
31490
- queue.push(child);
31491
- }
31492
- }
31493
- }
31494
- return found;
31495
- }
31496
- function ancestorsIn(tree, pid, root) {
31497
- const chain = [];
31498
- const seen = new Set([pid]);
31499
- let child = pid;
31500
- let parent = tree.get(pid)?.parent;
31501
- while (parent !== undefined && !seen.has(parent) && linked(tree, child, parent)) {
31502
- chain.push(parent);
31503
- if (parent === root) {
31504
- break;
31505
- }
31506
- seen.add(parent);
31507
- child = parent;
31508
- parent = tree.get(parent)?.parent;
31509
- }
31510
- return chain;
31511
- }
31512
- function readCommandLine(command) {
31513
- const words = commandWords(command);
31514
- const executable = words[0] === undefined ? "" : basename2(words[0].replaceAll("\\", "/"));
31515
- const at = words.indexOf("--path");
31516
- let projectPath = null;
31517
- if (at !== -1 && at + 1 < words.length) {
31518
- const taken = [];
31519
- for (const word of words.slice(at + 1)) {
31520
- if (taken.length > 0 && (word.startsWith("-") || /^[a-z]+:\/\//.test(word))) {
31521
- break;
31522
- }
31523
- taken.push(word);
31524
- }
31525
- projectPath = taken.join(" ");
31526
- }
31527
- return {
31528
- executable,
31529
- projectPath,
31530
- editor: words.some((word) => word === "-e" || word === "--editor")
31531
- };
31532
- }
31533
- function commandWords(command) {
31534
- const words = [];
31535
- let word = "";
31536
- let quoted = false;
31537
- let started = false;
31538
- for (const char of command) {
31539
- if (char === '"') {
31540
- quoted = !quoted;
31541
- started = true;
31542
- } else if (!quoted && /\s/.test(char)) {
31543
- if (started) {
31544
- words.push(word);
31545
- word = "";
31546
- started = false;
31547
- }
31548
- } else {
31549
- word += char;
31550
- started = true;
31551
- }
31552
- }
31553
- if (started) {
31554
- words.push(word);
31555
- }
31556
- return words;
31557
- }
31558
- async function askWindows() {
31559
- const { stdout } = await run4("powershell.exe", [
31560
- "-NoProfile",
31561
- "-NonInteractive",
31562
- "-Command",
31563
- `${POWERSHELL_UTF8}Get-CimInstance Win32_Process | ForEach-Object { $began = 0; if ($_.CreationDate) { $began = ([DateTimeOffset]$_.CreationDate).ToUnixTimeMilliseconds() }; "$($_.ProcessId) $($_.ParentProcessId) $began $($_.CommandLine)" }`
31564
- ], { timeout: ASK_TIMEOUT_MS, windowsHide: true, maxBuffer: 16 * 1024 * 1024 });
31565
- return stdout;
31566
- }
31567
- async function askPosix() {
31568
- const { stdout } = await run4("ps", ["-e", "-o", "pid=,ppid=,args="], {
31569
- timeout: ASK_TIMEOUT_MS,
31570
- maxBuffer: 16 * 1024 * 1024
31571
- });
31572
- return stdout;
31573
- }
31574
- var run4, POWERSHELL_UTF8 = "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; ", ASK_TIMEOUT_MS = 15000;
31575
- var init_process_children = __esm(() => {
31576
- run4 = promisify4(execFile4);
31577
- });
31578
-
31579
31579
  // src/runtime-client.ts
31580
- import { existsSync as existsSync10, readdirSync as readdirSync6, readFileSync as readFileSync10, statSync as statSync5, unlinkSync } from "node:fs";
31580
+ import { existsSync as existsSync10, readdirSync as readdirSync6, readFileSync as readFileSync11, statSync as statSync5, unlinkSync } from "node:fs";
31581
31581
  import { createConnection } from "node:net";
31582
31582
  import { tmpdir as tmpdir4 } from "node:os";
31583
- import { dirname as dirname7, join as join12, resolve as resolve3 } from "node:path";
31583
+ import { dirname as dirname8, join as join13, resolve as resolve3 } from "node:path";
31584
31584
  import { setTimeout as delay } from "node:timers/promises";
31585
31585
  function runtimeDirectory(variables = process.env) {
31586
31586
  const explicit = envValue("GDHARNESS_RUNTIME_DIR", variables);
@@ -31588,19 +31588,19 @@ function runtimeDirectory(variables = process.env) {
31588
31588
  return explicit;
31589
31589
  }
31590
31590
  const perUser = envValue("XDG_RUNTIME_DIR", variables);
31591
- return join12(perUser ?? tmpdir4(), "gdharness");
31591
+ return join13(perUser ?? tmpdir4(), "gdharness");
31592
31592
  }
31593
31593
  function runtimeDirectories(variables = process.env) {
31594
31594
  const candidates = [runtimeDirectory(variables)];
31595
31595
  const fallbacks = process.platform === "win32" ? [envValue("SystemRoot", variables) ?? envValue("windir", variables) ?? "C:\\Windows"] : ["/tmp", "/var/tmp"];
31596
31596
  for (const base of fallbacks) {
31597
- candidates.push(join12(base, process.platform === "win32" ? "Temp" : "", "gdharness"));
31597
+ candidates.push(join13(base, process.platform === "win32" ? "Temp" : "", "gdharness"));
31598
31598
  }
31599
31599
  return [...new Set(candidates.map((path) => resolve3(path)))];
31600
31600
  }
31601
31601
  function errorReportOf(pid, directories = runtimeDirectories()) {
31602
31602
  for (const directory of directories) {
31603
- const path = join12(directory, `runtime-${pid}.log`);
31603
+ const path = join13(directory, `runtime-${pid}.log`);
31604
31604
  if (existsSync10(path)) {
31605
31605
  return path;
31606
31606
  }
@@ -31618,7 +31618,7 @@ function processAlive(pid) {
31618
31618
  function parseAnnouncement(file, pid) {
31619
31619
  let fields;
31620
31620
  try {
31621
- fields = asParams(JSON.parse(readFileSync10(file, "utf8")));
31621
+ fields = asParams(JSON.parse(readFileSync11(file, "utf8")));
31622
31622
  } catch {
31623
31623
  return { kind: "rubbish" };
31624
31624
  }
@@ -31670,7 +31670,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
31670
31670
  function wentAway(file, pid) {
31671
31671
  let project = "";
31672
31672
  try {
31673
- const fields = asParams(JSON.parse(readFileSync10(file, "utf8")));
31673
+ const fields = asParams(JSON.parse(readFileSync11(file, "utf8")));
31674
31674
  project = readString(readParams(fields, "project") ?? {}, "path") ?? "";
31675
31675
  } catch {
31676
31676
  return;
@@ -31716,14 +31716,14 @@ function announcedIn(directory) {
31716
31716
  for (const entry of readdirSync6(directory)) {
31717
31717
  const report = ERROR_REPORT_PATTERN.exec(entry);
31718
31718
  if (report) {
31719
- sweepErrorReport(join12(directory, entry), Number.parseInt(report[1] ?? "", 10));
31719
+ sweepErrorReport(join13(directory, entry), Number.parseInt(report[1] ?? "", 10));
31720
31720
  continue;
31721
31721
  }
31722
31722
  const match = ANNOUNCEMENT_PATTERN.exec(entry);
31723
31723
  if (!match) {
31724
31724
  continue;
31725
31725
  }
31726
- const file = join12(directory, entry);
31726
+ const file = join13(directory, entry);
31727
31727
  const pid = Number.parseInt(match[1] ?? "", 10);
31728
31728
  const alive = processAlive(pid);
31729
31729
  entries.push({ file, pid, alive });
@@ -31751,16 +31751,16 @@ function announcedIn(directory) {
31751
31751
  found.push(announced);
31752
31752
  }
31753
31753
  const held = new Set(entries.map((one) => one.file));
31754
- const here = join12(directory, ".");
31754
+ const here = join13(directory, ".");
31755
31755
  for (const file of verdicts.keys()) {
31756
- if (dirname7(file) === here && !held.has(file)) {
31756
+ if (dirname8(file) === here && !held.has(file)) {
31757
31757
  verdicts.delete(file);
31758
31758
  }
31759
31759
  }
31760
31760
  return found;
31761
31761
  }
31762
31762
  async function announcementEnded(pid, directories = runtimeDirectories()) {
31763
- const files = directories.map((directory) => join12(directory, `runtime-${pid}.json`)).filter((file) => existsSync10(file));
31763
+ const files = directories.map((directory) => join13(directory, `runtime-${pid}.json`)).filter((file) => existsSync10(file));
31764
31764
  const first = files[0];
31765
31765
  if (first === undefined) {
31766
31766
  return;
@@ -32009,14 +32009,14 @@ var init_runtime_client = __esm(() => {
32009
32009
  });
32010
32010
 
32011
32011
  // src/boot-note.ts
32012
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "node:fs";
32013
- import { dirname as dirname8, join as join13 } from "node:path";
32012
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
32013
+ import { dirname as dirname9, join as join14 } from "node:path";
32014
32014
  function bootNotePath(projectPath) {
32015
- return join13(projectPath, ".godot", "gdharness-boot.json");
32015
+ return join14(projectPath, ".godot", "gdharness-boot.json");
32016
32016
  }
32017
32017
  function readBootNote(projectPath) {
32018
32018
  try {
32019
- const noted = readNumber(asParams(JSON.parse(readFileSync11(bootNotePath(projectPath), "utf8"))), "announcedAfterMs");
32019
+ const noted = readNumber(asParams(JSON.parse(readFileSync12(bootNotePath(projectPath), "utf8"))), "announcedAfterMs");
32020
32020
  return noted !== undefined && Number.isFinite(noted) && noted > 0 ? noted : null;
32021
32021
  } catch {
32022
32022
  return null;
@@ -32025,8 +32025,8 @@ function readBootNote(projectPath) {
32025
32025
  function writeBootNote(projectPath, announcedAfterMs) {
32026
32026
  try {
32027
32027
  const path = bootNotePath(projectPath);
32028
- mkdirSync6(dirname8(path), { recursive: true });
32029
- writeFileSync8(path, JSON.stringify({ announcedAfterMs: Math.round(announcedAfterMs), at: new Date().toISOString() }, null, 2), "utf8");
32028
+ mkdirSync7(dirname9(path), { recursive: true });
32029
+ writeFileSync9(path, JSON.stringify({ announcedAfterMs: Math.round(announcedAfterMs), at: new Date().toISOString() }, null, 2), "utf8");
32030
32030
  } catch {}
32031
32031
  }
32032
32032
  function halfAsLongAgain(lastBootMs) {
@@ -32044,10 +32044,10 @@ var init_boot_note = __esm(() => {
32044
32044
  });
32045
32045
 
32046
32046
  // src/breakpoint-note.ts
32047
- import { mkdirSync as mkdirSync7, readFileSync as readFileSync12, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "node:fs";
32048
- import { dirname as dirname9, isAbsolute as isAbsolute2, join as join14, relative as relative2 } from "node:path";
32047
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "node:fs";
32048
+ import { dirname as dirname10, isAbsolute as isAbsolute2, join as join15, relative as relative2 } from "node:path";
32049
32049
  function breakpointNotePath(projectPath) {
32050
- return join14(projectPath, ".godot", "gdharness-breakpoints.json");
32050
+ return join15(projectPath, ".godot", "gdharness-breakpoints.json");
32051
32051
  }
32052
32052
  function writeBreakpointNote(projectPath, held) {
32053
32053
  const path = breakpointNotePath(projectPath);
@@ -32055,7 +32055,7 @@ function writeBreakpointNote(projectPath, held) {
32055
32055
  const inside = held.map((one) => ({ scriptPath: realPathOr(one.scriptPath), lines: one.lines })).filter((one) => one.lines.length > 0 && withinProject(root, one.scriptPath));
32056
32056
  try {
32057
32057
  if (inside.length === 0) {
32058
- rmSync6(path, { force: true });
32058
+ rmSync7(path, { force: true });
32059
32059
  return;
32060
32060
  }
32061
32061
  const note = {
@@ -32064,8 +32064,8 @@ function writeBreakpointNote(projectPath, held) {
32064
32064
  lines: [...one.lines]
32065
32065
  }))
32066
32066
  };
32067
- mkdirSync7(dirname9(path), { recursive: true });
32068
- writeFileSync9(path, `${JSON.stringify(note, null, 2)}
32067
+ mkdirSync8(dirname10(path), { recursive: true });
32068
+ writeFileSync10(path, `${JSON.stringify(note, null, 2)}
32069
32069
  `, "utf8");
32070
32070
  } catch (error) {
32071
32071
  console.error(`[SERVER] Could not record the breakpoints at ${path}: ${errorMessage(error)}`);
@@ -32073,7 +32073,7 @@ function writeBreakpointNote(projectPath, held) {
32073
32073
  }
32074
32074
  function readBreakpointNote(projectPath) {
32075
32075
  try {
32076
- const parsed = JSON.parse(readFileSync12(breakpointNotePath(projectPath), "utf8"));
32076
+ const parsed = JSON.parse(readFileSync13(breakpointNotePath(projectPath), "utf8"));
32077
32077
  if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.breakpoints)) {
32078
32078
  return [];
32079
32079
  }
@@ -32088,7 +32088,7 @@ function readBreakpointNote(projectPath) {
32088
32088
  }
32089
32089
  const lines = Array.isArray(listed) ? listed.filter((line) => Number.isInteger(line) && line > 0) : [];
32090
32090
  if (lines.length > 0) {
32091
- held.push({ scriptPath: realPathOr(join14(projectPath, script)), lines });
32091
+ held.push({ scriptPath: realPathOr(join15(projectPath, script)), lines });
32092
32092
  }
32093
32093
  }
32094
32094
  return held;
@@ -32106,14 +32106,14 @@ var init_breakpoint_note = __esm(() => {
32106
32106
  });
32107
32107
 
32108
32108
  // src/bridge-announce.ts
32109
- import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "node:fs";
32110
- import { dirname as dirname10, join as join15 } from "node:path";
32111
- function announcementPath(projectPath) {
32112
- return join15(projectPath, ".godot", "gdharness-bridge.json");
32109
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync14, rmSync as rmSync8, writeFileSync as writeFileSync11 } from "node:fs";
32110
+ import { dirname as dirname11, join as join16 } from "node:path";
32111
+ function announcementPath2(projectPath) {
32112
+ return join16(projectPath, ".godot", "gdharness-bridge.json");
32113
32113
  }
32114
- function readAnnouncement(path) {
32114
+ function readAnnouncement2(path) {
32115
32115
  try {
32116
- const parsed = JSON.parse(readFileSync13(path, "utf8"));
32116
+ const parsed = JSON.parse(readFileSync14(path, "utf8"));
32117
32117
  if (typeof parsed !== "object" || parsed === null) {
32118
32118
  return null;
32119
32119
  }
@@ -32127,12 +32127,12 @@ function readAnnouncement(path) {
32127
32127
  }
32128
32128
  }
32129
32129
  function announcementIsOurs(path) {
32130
- return readAnnouncement(path)?.pid === process.pid;
32130
+ return readAnnouncement2(path)?.pid === process.pid;
32131
32131
  }
32132
32132
  function announceBridge(projectPath, bridge) {
32133
- const path = announcementPath(projectPath);
32133
+ const path = announcementPath2(projectPath);
32134
32134
  try {
32135
- mkdirSync8(dirname10(path), { recursive: true });
32135
+ mkdirSync9(dirname11(path), { recursive: true });
32136
32136
  const announcement = {
32137
32137
  protocol: BRIDGE_ANNOUNCE_PROTOCOL,
32138
32138
  host: bridge.host,
@@ -32141,7 +32141,7 @@ function announceBridge(projectPath, bridge) {
32141
32141
  version: bridge.version,
32142
32142
  startedAt: new Date().toISOString()
32143
32143
  };
32144
- writeFileSync10(path, `${JSON.stringify(announcement, null, 2)}
32144
+ writeFileSync11(path, `${JSON.stringify(announcement, null, 2)}
32145
32145
  `, "utf8");
32146
32146
  return path;
32147
32147
  } catch (error) {
@@ -32154,7 +32154,7 @@ function withdrawBridge(path) {
32154
32154
  return;
32155
32155
  }
32156
32156
  try {
32157
- rmSync7(path, { force: true });
32157
+ rmSync8(path, { force: true });
32158
32158
  } catch (error) {
32159
32159
  console.error(`[SERVER] Could not withdraw the editor bridge announcement: ${errorMessage(error)}`);
32160
32160
  }
@@ -32162,17 +32162,18 @@ function withdrawBridge(path) {
32162
32162
  var BRIDGE_ANNOUNCE_PROTOCOL = 1;
32163
32163
  var init_bridge_announce = __esm(() => {
32164
32164
  init_errors();
32165
+ init_process_children();
32165
32166
  });
32166
32167
 
32167
32168
  // src/class-note.ts
32168
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
32169
- import { dirname as dirname11, join as join16 } from "node:path";
32169
+ import { mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
32170
+ import { dirname as dirname12, join as join17 } from "node:path";
32170
32171
  function classNotePath(projectPath) {
32171
- return join16(projectPath, ".godot", "gdharness-classes.json");
32172
+ return join17(projectPath, ".godot", "gdharness-classes.json");
32172
32173
  }
32173
32174
  function readClassNote(projectPath) {
32174
32175
  try {
32175
- const fields = asParams(JSON.parse(readFileSync14(classNotePath(projectPath), "utf8")));
32176
+ const fields = asParams(JSON.parse(readFileSync15(classNotePath(projectPath), "utf8")));
32176
32177
  const rebuiltWith = readArray(fields, "rebuiltWith");
32177
32178
  if (rebuiltWith === undefined || !rebuiltWith.every((name) => typeof name === "string")) {
32178
32179
  return null;
@@ -32189,24 +32190,24 @@ function readClassNote(projectPath) {
32189
32190
  function writeClassNote(projectPath, note) {
32190
32191
  try {
32191
32192
  const path = classNotePath(projectPath);
32192
- mkdirSync9(dirname11(path), { recursive: true });
32193
- writeFileSync11(path, `${JSON.stringify(note, null, 2)}
32193
+ mkdirSync10(dirname12(path), { recursive: true });
32194
+ writeFileSync12(path, `${JSON.stringify(note, null, 2)}
32194
32195
  `, "utf8");
32195
32196
  } catch {}
32196
32197
  }
32197
32198
  var init_class_note = () => {};
32198
32199
 
32199
32200
  // src/config-pin.ts
32200
- import { existsSync as existsSync11, readFileSync as readFileSync15 } from "node:fs";
32201
- import { join as join17 } from "node:path";
32201
+ import { existsSync as existsSync11, readFileSync as readFileSync16 } from "node:fs";
32202
+ import { join as join18 } from "node:path";
32202
32203
  function versionsNamedInConfig(projectPath) {
32203
- const config = join17(projectPath, ".mcp.json");
32204
+ const config = join18(projectPath, ".mcp.json");
32204
32205
  if (!existsSync11(config)) {
32205
32206
  return [];
32206
32207
  }
32207
32208
  let text;
32208
32209
  try {
32209
- text = readFileSync15(config, "utf8");
32210
+ text = readFileSync16(config, "utf8");
32210
32211
  JSON.parse(text);
32211
32212
  } catch {
32212
32213
  return [];
@@ -32314,7 +32315,7 @@ function portFromEnvOrNull(variable) {
32314
32315
  }
32315
32316
  const parsed = Number.parseInt(raw, 10);
32316
32317
  if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65535 || String(parsed) !== raw) {
32317
- throw new Refusal2(`${variable} is "${raw}", not a port between 1 and 65535.`);
32318
+ throw new Refusal(`${variable} is "${raw}", not a port between 1 and 65535.`);
32318
32319
  }
32319
32320
  return parsed;
32320
32321
  }
@@ -32328,7 +32329,7 @@ async function freePort(preferred, host = "127.0.0.1") {
32328
32329
  }
32329
32330
  const spare = await bindable(0, host);
32330
32331
  if (spare === null) {
32331
- throw new Refusal2(`No port could be bound on ${host}.`);
32332
+ throw new Refusal(`No port could be bound on ${host}.`);
32332
32333
  }
32333
32334
  return spare;
32334
32335
  }
@@ -32478,7 +32479,7 @@ class GodotDAPClient {
32478
32479
  async sendRequest(command, args, timeoutMs = DAP_REQUEST_TIMEOUT_MS) {
32479
32480
  await this.ensureConnected();
32480
32481
  if (!this.socket) {
32481
- throw new Refusal2("DAP socket is not available");
32482
+ throw new Refusal("DAP socket is not available");
32482
32483
  }
32483
32484
  const requestSeq = this.seq++;
32484
32485
  const request = {
@@ -32888,7 +32889,7 @@ async function handleDAPTool(client, toolName, args) {
32888
32889
  }
32889
32890
  case "dap_set_breakpoint": {
32890
32891
  if (typeof safeArgs.scriptPath !== "string" || typeof safeArgs.line !== "number") {
32891
- throw new Refusal2("dap_set_breakpoint requires { scriptPath: string, line: number }");
32892
+ throw new Refusal("dap_set_breakpoint requires { scriptPath: string, line: number }");
32892
32893
  }
32893
32894
  const result = await client.setBreakpoint(safeArgs.scriptPath, safeArgs.line);
32894
32895
  return {
@@ -32897,7 +32898,7 @@ async function handleDAPTool(client, toolName, args) {
32897
32898
  }
32898
32899
  case "dap_remove_breakpoint": {
32899
32900
  if (typeof safeArgs.scriptPath !== "string" || typeof safeArgs.line !== "number") {
32900
- throw new Refusal2("dap_remove_breakpoint requires { scriptPath: string, line: number }");
32901
+ throw new Refusal("dap_remove_breakpoint requires { scriptPath: string, line: number }");
32901
32902
  }
32902
32903
  const result = await client.removeBreakpoint(safeArgs.scriptPath, safeArgs.line);
32903
32904
  return {
@@ -32960,24 +32961,24 @@ var init_dap_client = __esm(() => {
32960
32961
  import {
32961
32962
  closeSync,
32962
32963
  existsSync as existsSync12,
32963
- mkdirSync as mkdirSync10,
32964
+ mkdirSync as mkdirSync11,
32964
32965
  openSync,
32965
- readFileSync as readFileSync16,
32966
+ readFileSync as readFileSync17,
32966
32967
  readSync,
32967
- rmSync as rmSync8,
32968
+ rmSync as rmSync9,
32968
32969
  statSync as statSync6,
32969
- writeFileSync as writeFileSync12
32970
+ writeFileSync as writeFileSync13
32970
32971
  } from "node:fs";
32971
- import { dirname as dirname12, join as join18 } from "node:path";
32972
+ import { dirname as dirname13, join as join19 } from "node:path";
32972
32973
  function editorLogPath(projectPath) {
32973
- return join18(projectPath, ".godot", "gdharness-editor.log");
32974
+ return join19(projectPath, ".godot", "gdharness-editor.log");
32974
32975
  }
32975
32976
  function editorLogNotePath(projectPath) {
32976
- return join18(projectPath, ".godot", "gdharness-editor.json");
32977
+ return join19(projectPath, ".godot", "gdharness-editor.json");
32977
32978
  }
32978
32979
  function readEditorLogNote(projectPath) {
32979
32980
  try {
32980
- const fields = asParams(JSON.parse(readFileSync16(editorLogNotePath(projectPath), "utf8")));
32981
+ const fields = asParams(JSON.parse(readFileSync17(editorLogNotePath(projectPath), "utf8")));
32981
32982
  const pid = readNumber(fields, "pid");
32982
32983
  const startedAt = readString(fields, "startedAt");
32983
32984
  return pid !== undefined && Number.isInteger(pid) && pid > 0 && startedAt !== undefined ? { pid, startedAt } : null;
@@ -32988,16 +32989,16 @@ function readEditorLogNote(projectPath) {
32988
32989
  function clearEditorLog(projectPath) {
32989
32990
  try {
32990
32991
  const path = editorLogPath(projectPath);
32991
- mkdirSync10(dirname12(path), { recursive: true });
32992
- rmSync8(path, { force: true });
32993
- rmSync8(editorLogNotePath(projectPath), { force: true });
32992
+ mkdirSync11(dirname13(path), { recursive: true });
32993
+ rmSync9(path, { force: true });
32994
+ rmSync9(editorLogNotePath(projectPath), { force: true });
32994
32995
  } catch {}
32995
32996
  }
32996
32997
  function writeEditorLogNote(projectPath, pid) {
32997
32998
  try {
32998
32999
  const path = editorLogNotePath(projectPath);
32999
- mkdirSync10(dirname12(path), { recursive: true });
33000
- writeFileSync12(path, JSON.stringify({ pid, startedAt: new Date().toISOString() }, null, 2), "utf8");
33000
+ mkdirSync11(dirname13(path), { recursive: true });
33001
+ writeFileSync13(path, JSON.stringify({ pid, startedAt: new Date().toISOString() }, null, 2), "utf8");
33001
33002
  } catch {}
33002
33003
  }
33003
33004
  function theConsoleWasNotCaptured(why, projectPath) {
@@ -33030,7 +33031,7 @@ function editorConsole(projectPath, editorPid, openedByAServer) {
33030
33031
  function theFirstOf(path) {
33031
33032
  const whole = statSync6(path).size;
33032
33033
  if (whole <= MOST_CONSOLE_BYTES) {
33033
- return { text: readFileSync16(path, "utf8") };
33034
+ return { text: readFileSync17(path, "utf8") };
33034
33035
  }
33035
33036
  const handle = openSync(path, "r");
33036
33037
  try {
@@ -36448,7 +36449,7 @@ var init_godot_bridge = __esm(() => {
36448
36449
  }
36449
36450
  sendMessage(message) {
36450
36451
  if (this.socket?.readyState !== import_websocket.default.OPEN) {
36451
- throw new Refusal2("Godot is not connected");
36452
+ throw new Refusal("Godot is not connected");
36452
36453
  }
36453
36454
  this.socket.send(JSON.stringify(message));
36454
36455
  }
@@ -36998,7 +36999,7 @@ var init_junit = __esm(() => {
36998
36999
  import { realpathSync as realpathSync2 } from "node:fs";
36999
37000
  import { readFile, realpath } from "node:fs/promises";
37000
37001
  import { createConnection as createConnection3 } from "node:net";
37001
- import { dirname as dirname13, resolve as resolve4 } from "node:path";
37002
+ import { dirname as dirname14, resolve as resolve4 } from "node:path";
37002
37003
  import { fileURLToPath as fileURLToPath4, pathToFileURL } from "node:url";
37003
37004
  function diagnosticsKey(uri) {
37004
37005
  let decoded;
@@ -37126,13 +37127,13 @@ class GodotLSPClient {
37126
37127
  if (this.initialized) {
37127
37128
  return;
37128
37129
  }
37129
- const rootPath = this.rootPath ?? dirname13(resolve4(filePath));
37130
+ const rootPath = this.rootPath ?? dirname14(resolve4(filePath));
37130
37131
  await this.initialize(rootPath);
37131
37132
  }
37132
37133
  async sendRequest(method, params) {
37133
37134
  await this.ensureConnected();
37134
37135
  if (!this.socket) {
37135
- throw new Refusal2("Not connected to Godot LSP");
37136
+ throw new Refusal("Not connected to Godot LSP");
37136
37137
  }
37137
37138
  this.requestId += 1;
37138
37139
  const id = this.requestId;
@@ -37171,7 +37172,7 @@ class GodotLSPClient {
37171
37172
  }
37172
37173
  sendNotification(method, params) {
37173
37174
  if (!this.connected || !this.socket) {
37174
- throw new Refusal2("Not connected to Godot LSP");
37175
+ throw new Refusal("Not connected to Godot LSP");
37175
37176
  }
37176
37177
  const payload = {
37177
37178
  jsonrpc: "2.0",
@@ -37453,36 +37454,36 @@ async function resolveLSPPaths(projectPathValue, scriptPathValue) {
37453
37454
  try {
37454
37455
  projectPath = await realpath(requestedProjectPath);
37455
37456
  } catch {
37456
- throw new Refusal2(`Project path does not exist: ${requestedProjectPath}`);
37457
+ throw new Refusal(`Project path does not exist: ${requestedProjectPath}`);
37457
37458
  }
37458
37459
  const contained = resolveWithinProject(projectPath, scriptPathValue);
37459
37460
  if (!contained.ok) {
37460
- throw new Refusal2(contained.reason);
37461
+ throw new Refusal(contained.reason);
37461
37462
  }
37462
37463
  let scriptPath;
37463
37464
  try {
37464
37465
  scriptPath = await realpath(contained.absolutePath);
37465
37466
  } catch {
37466
- throw new Refusal2(`Script file does not exist: ${contained.absolutePath}`);
37467
+ throw new Refusal(`Script file does not exist: ${contained.absolutePath}`);
37467
37468
  }
37468
37469
  if (!isWithinRoot(projectPath, scriptPath)) {
37469
- throw new Refusal2("scriptPath resolves outside the project root boundary.");
37470
+ throw new Refusal("scriptPath resolves outside the project root boundary.");
37470
37471
  }
37471
37472
  return { projectPath, scriptPath };
37472
37473
  }
37473
37474
  async function handleLSPTool(client, toolName, args) {
37474
37475
  try {
37475
37476
  if (!args || typeof args !== "object") {
37476
- throw new Refusal2("Tool arguments must be an object.");
37477
+ throw new Refusal("Tool arguments must be an object.");
37477
37478
  }
37478
37479
  const parsedArgs = args;
37479
37480
  const projectPathValue = parsedArgs["projectPath"];
37480
37481
  const scriptPathValue = parsedArgs["scriptPath"];
37481
37482
  if (typeof projectPathValue !== "string" || projectPathValue.length === 0) {
37482
- throw new Refusal2("Missing required argument: projectPath");
37483
+ throw new Refusal("Missing required argument: projectPath");
37483
37484
  }
37484
37485
  if (typeof scriptPathValue !== "string" || scriptPathValue.length === 0) {
37485
- throw new Refusal2("Missing required argument: scriptPath");
37486
+ throw new Refusal("Missing required argument: scriptPath");
37486
37487
  }
37487
37488
  const { projectPath, scriptPath } = await resolveLSPPaths(projectPathValue, scriptPathValue);
37488
37489
  const content = await readFile(scriptPath, "utf8");
@@ -37496,7 +37497,7 @@ async function handleLSPTool(client, toolName, args) {
37496
37497
  const line = Number(parsedArgs["line"]);
37497
37498
  const character = Number(parsedArgs["character"]);
37498
37499
  if (!Number.isFinite(line) || !Number.isFinite(character)) {
37499
- throw new Refusal2("Arguments line and character must be numbers.");
37500
+ throw new Refusal("Arguments line and character must be numbers.");
37500
37501
  }
37501
37502
  const completions = await client.getCompletions(scriptPath, content, line, character);
37502
37503
  return asToolResponse({ completions });
@@ -37505,7 +37506,7 @@ async function handleLSPTool(client, toolName, args) {
37505
37506
  const line = Number(parsedArgs["line"]);
37506
37507
  const character = Number(parsedArgs["character"]);
37507
37508
  if (!Number.isFinite(line) || !Number.isFinite(character)) {
37508
- throw new Refusal2("Arguments line and character must be numbers.");
37509
+ throw new Refusal("Arguments line and character must be numbers.");
37509
37510
  }
37510
37511
  const hover = await client.getHover(scriptPath, content, line, character);
37511
37512
  return asToolResponse({ hover });
@@ -37571,13 +37572,13 @@ var init_process_time = __esm(() => {
37571
37572
  });
37572
37573
 
37573
37574
  // src/project-scan.ts
37574
- import { existsSync as existsSync14, readdirSync as readdirSync7, readFileSync as readFileSync17 } from "node:fs";
37575
- import { join as join19 } from "node:path";
37575
+ import { existsSync as existsSync14, readdirSync as readdirSync7, readFileSync as readFileSync18 } from "node:fs";
37576
+ import { join as join20 } from "node:path";
37576
37577
  function skipped(name) {
37577
37578
  return name.startsWith(".") || SKIPPED.has(name);
37578
37579
  }
37579
37580
  function steppedOver(directory) {
37580
- return existsSync14(join19(directory, ".gdignore"));
37581
+ return existsSync14(join20(directory, ".gdignore"));
37581
37582
  }
37582
37583
  function projectStructure(projectPath) {
37583
37584
  const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
@@ -37590,7 +37591,7 @@ function projectStructure(projectPath) {
37590
37591
  continue;
37591
37592
  }
37592
37593
  if (entry.isDirectory()) {
37593
- visit(join19(directory, entry.name));
37594
+ visit(join20(directory, entry.name));
37594
37595
  } else if (entry.isFile()) {
37595
37596
  const extension = entry.name.split(".").pop()?.toLowerCase() ?? "";
37596
37597
  if (extension === "tscn") {
@@ -37620,14 +37621,14 @@ function scriptsWithoutUid(projectPath) {
37620
37621
  }
37621
37622
  const spelled = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
37622
37623
  if (entry.isDirectory()) {
37623
- visit(join19(directory, entry.name), spelled);
37624
+ visit(join20(directory, entry.name), spelled);
37624
37625
  continue;
37625
37626
  }
37626
37627
  if (!entry.isFile()) {
37627
37628
  continue;
37628
37629
  }
37629
37630
  const extension = entry.name.split(".").pop()?.toLowerCase() ?? "";
37630
- if (CARRIES_A_UID.has(extension) && !existsSync14(join19(directory, `${entry.name}.uid`))) {
37631
+ if (CARRIES_A_UID.has(extension) && !existsSync14(join20(directory, `${entry.name}.uid`))) {
37631
37632
  found.push(spelled);
37632
37633
  }
37633
37634
  }
@@ -37662,7 +37663,7 @@ function searchProject(projectPath, options) {
37662
37663
  if (skipped(entry.name)) {
37663
37664
  continue;
37664
37665
  }
37665
- const entryPath = join19(directory, entry.name);
37666
+ const entryPath = join20(directory, entry.name);
37666
37667
  if (entry.isDirectory()) {
37667
37668
  visit(entryPath);
37668
37669
  continue;
@@ -37673,7 +37674,7 @@ function searchProject(projectPath, options) {
37673
37674
  }
37674
37675
  result.summary.files_searched += 1;
37675
37676
  const matches = [];
37676
- for (const [index, line] of readFileSync17(entryPath, "utf8").split(`
37677
+ for (const [index, line] of readFileSync18(entryPath, "utf8").split(`
37677
37678
  `).entries()) {
37678
37679
  if (full()) {
37679
37680
  break;
@@ -37702,16 +37703,16 @@ var init_project_scan = __esm(() => {
37702
37703
  });
37703
37704
 
37704
37705
  // src/restart-note.ts
37705
- import { mkdirSync as mkdirSync11, readFileSync as readFileSync18, rmSync as rmSync9, writeFileSync as writeFileSync13 } from "node:fs";
37706
- import { dirname as dirname14, join as join20 } from "node:path";
37706
+ import { mkdirSync as mkdirSync12, readFileSync as readFileSync19, rmSync as rmSync10, writeFileSync as writeFileSync14 } from "node:fs";
37707
+ import { dirname as dirname15, join as join21 } from "node:path";
37707
37708
  function restartNotePath(projectPath) {
37708
- return join20(projectPath, ".godot", "gdharness-restart.json");
37709
+ return join21(projectPath, ".godot", "gdharness-restart.json");
37709
37710
  }
37710
37711
  function noteRestartBegun(note) {
37711
37712
  const path = restartNotePath(note.projectPath);
37712
37713
  try {
37713
- mkdirSync11(dirname14(path), { recursive: true });
37714
- writeFileSync13(path, `${JSON.stringify(note, null, 2)}
37714
+ mkdirSync12(dirname15(path), { recursive: true });
37715
+ writeFileSync14(path, `${JSON.stringify(note, null, 2)}
37715
37716
  `, "utf8");
37716
37717
  } catch (error) {
37717
37718
  console.error(`[SERVER] Could not record the restart at ${path}: ${errorMessage(error)}`);
@@ -37719,7 +37720,7 @@ function noteRestartBegun(note) {
37719
37720
  }
37720
37721
  function restartOwed(projectPath) {
37721
37722
  try {
37722
- const parsed = JSON.parse(readFileSync18(restartNotePath(projectPath), "utf8"));
37723
+ const parsed = JSON.parse(readFileSync19(restartNotePath(projectPath), "utf8"));
37723
37724
  if (typeof parsed !== "object" || parsed === null) {
37724
37725
  return null;
37725
37726
  }
@@ -37734,7 +37735,7 @@ function restartOwed(projectPath) {
37734
37735
  }
37735
37736
  function restartSettled(projectPath) {
37736
37737
  try {
37737
- rmSync9(restartNotePath(projectPath), { force: true });
37738
+ rmSync10(restartNotePath(projectPath), { force: true });
37738
37739
  } catch (error) {
37739
37740
  console.error(`[SERVER] Could not clear the restart note: ${errorMessage(error)}`);
37740
37741
  }
@@ -37745,36 +37746,36 @@ var init_restart_note = __esm(() => {
37745
37746
 
37746
37747
  // src/run-record.ts
37747
37748
  import { execFileSync as execFileSync2 } from "node:child_process";
37748
- import { mkdirSync as mkdirSync12, openSync as openSync2, readdirSync as readdirSync8, readFileSync as readFileSync19, rmSync as rmSync10, statSync as statSync7, writeFileSync as writeFileSync14 } from "node:fs";
37749
- import { basename as basename3, join as join21 } from "node:path";
37749
+ import { mkdirSync as mkdirSync13, openSync as openSync2, readdirSync as readdirSync8, readFileSync as readFileSync20, rmSync as rmSync11, statSync as statSync7, writeFileSync as writeFileSync15 } from "node:fs";
37750
+ import { basename as basename3, join as join22 } from "node:path";
37750
37751
  function runsDirectory() {
37751
- return join21(runtimeDirectory(), "runs");
37752
+ return join22(runtimeDirectory(), "runs");
37752
37753
  }
37753
37754
  function recordPath() {
37754
- return join21(runsDirectory(), "run.json");
37755
+ return join22(runsDirectory(), "run.json");
37755
37756
  }
37756
37757
  function recordPaths() {
37757
- return runtimeDirectories().map((directory) => join21(directory, "runs", "run.json"));
37758
+ return runtimeDirectories().map((directory) => join22(directory, "runs", "run.json"));
37758
37759
  }
37759
37760
  function openTranscript(startedAt) {
37760
- mkdirSync12(runsDirectory(), { recursive: true });
37761
- const path = join21(runsDirectory(), `run-${startedAt}.log`);
37761
+ mkdirSync13(runsDirectory(), { recursive: true });
37762
+ const path = join22(runsDirectory(), `run-${startedAt}.log`);
37762
37763
  return { path, fd: openSync2(path, "a") };
37763
37764
  }
37764
37765
  function writeRunRecord(record) {
37765
- mkdirSync12(runsDirectory(), { recursive: true });
37766
- writeFileSync14(recordPath(), JSON.stringify(record, null, 2), "utf8");
37766
+ mkdirSync13(runsDirectory(), { recursive: true });
37767
+ writeFileSync15(recordPath(), JSON.stringify(record, null, 2), "utf8");
37767
37768
  }
37768
37769
  function editorNotePath() {
37769
- return join21(runsDirectory(), "editor-run.json");
37770
+ return join22(runsDirectory(), "editor-run.json");
37770
37771
  }
37771
37772
  function writeEditorRunNote(note) {
37772
- mkdirSync12(runsDirectory(), { recursive: true });
37773
- writeFileSync14(editorNotePath(), JSON.stringify(note, null, 2), "utf8");
37773
+ mkdirSync13(runsDirectory(), { recursive: true });
37774
+ writeFileSync15(editorNotePath(), JSON.stringify(note, null, 2), "utf8");
37774
37775
  }
37775
37776
  function readEditorRunNote() {
37776
37777
  for (const directory of runtimeDirectories()) {
37777
- const note = editorNoteAt(join21(directory, "runs", "editor-run.json"));
37778
+ const note = editorNoteAt(join22(directory, "runs", "editor-run.json"));
37778
37779
  if (note !== null) {
37779
37780
  return note;
37780
37781
  }
@@ -37784,7 +37785,7 @@ function readEditorRunNote() {
37784
37785
  function editorNoteAt(path) {
37785
37786
  let parsed;
37786
37787
  try {
37787
- parsed = JSON.parse(readFileSync19(path, "utf8"));
37788
+ parsed = JSON.parse(readFileSync20(path, "utf8"));
37788
37789
  } catch {
37789
37790
  return null;
37790
37791
  }
@@ -37807,7 +37808,7 @@ function recordRunEnded(pid, exitCode) {
37807
37808
  return;
37808
37809
  }
37809
37810
  try {
37810
- writeFileSync14(path, JSON.stringify({ ...record, exitCode }, null, 2), "utf8");
37811
+ writeFileSync15(path, JSON.stringify({ ...record, exitCode }, null, 2), "utf8");
37811
37812
  } catch {}
37812
37813
  }
37813
37814
  function readRunRecord() {
@@ -37822,7 +37823,7 @@ function readRunRecord() {
37822
37823
  function recordAt(path) {
37823
37824
  let parsed;
37824
37825
  try {
37825
- parsed = JSON.parse(readFileSync19(path, "utf8"));
37826
+ parsed = JSON.parse(readFileSync20(path, "utf8"));
37826
37827
  } catch {
37827
37828
  return null;
37828
37829
  }
@@ -37867,7 +37868,7 @@ function runningAs(pid) {
37867
37868
  const began = startedAt(pid, null);
37868
37869
  const when = began === null ? {} : { startedAt: began };
37869
37870
  if (process.platform === "linux") {
37870
- const raw = readFileSync19(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ").trim();
37871
+ const raw = readFileSync20(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ").trim();
37871
37872
  return raw === "" ? null : { kind: "commandLine", text: raw, ...when };
37872
37873
  }
37873
37874
  const args = execFileSync2("ps", ["-p", String(pid), "-o", "args="], {
@@ -37994,7 +37995,7 @@ function clearRunRecord(ours = () => true) {
37994
37995
  continue;
37995
37996
  }
37996
37997
  try {
37997
- rmSync10(path);
37998
+ rmSync11(path);
37998
37999
  } catch {}
37999
38000
  }
38000
38001
  }
@@ -38018,12 +38019,12 @@ function sweepTranscripts(keepMs = 24 * 60 * 60 * 1000, now = Date.now()) {
38018
38019
  if (!entry.startsWith("run-") || !entry.endsWith(".log")) {
38019
38020
  continue;
38020
38021
  }
38021
- const path = join21(directory, entry);
38022
+ const path = join22(directory, entry);
38022
38023
  if (path === keep || ageMs(path, now) < keepMs) {
38023
38024
  continue;
38024
38025
  }
38025
38026
  try {
38026
- rmSync10(path);
38027
+ rmSync11(path);
38027
38028
  } catch {}
38028
38029
  }
38029
38030
  }
@@ -38044,17 +38045,17 @@ import {
38044
38045
  copyFileSync,
38045
38046
  existsSync as existsSync15,
38046
38047
  fstatSync,
38047
- mkdirSync as mkdirSync13,
38048
+ mkdirSync as mkdirSync14,
38048
38049
  mkdtempSync as mkdtempSync3,
38049
38050
  openSync as openSync3,
38050
38051
  readdirSync as readdirSync9,
38051
- readFileSync as readFileSync20,
38052
+ readFileSync as readFileSync21,
38052
38053
  readSync as readSync2,
38053
38054
  rmdirSync,
38054
38055
  statSync as statSync8
38055
38056
  } from "node:fs";
38056
38057
  import { tmpdir as tmpdir5 } from "node:os";
38057
- import { basename as basename4, dirname as dirname15, extname as extname2, isAbsolute as isAbsolute3, join as join22, normalize as normalize3, relative as relative3 } from "node:path";
38058
+ import { basename as basename4, dirname as dirname16, extname as extname2, isAbsolute as isAbsolute3, join as join23, normalize as normalize3, relative as relative3 } from "node:path";
38058
38059
  import { setTimeout as delay3 } from "node:timers/promises";
38059
38060
  import { fileURLToPath as fileURLToPath5 } from "node:url";
38060
38061
  import { promisify as promisify7 } from "node:util";
@@ -38068,11 +38069,11 @@ function captureDestinationRefusal(outputPath, projects) {
38068
38069
  if (extname2(outputPath).toLowerCase() !== ".png") {
38069
38070
  return `outputPath ${outputPath} does not end in .png, which is what a capture is.`;
38070
38071
  }
38071
- const directory = realPathOr(dirname15(outputPath));
38072
+ const directory = realPathOr(dirname16(outputPath));
38072
38073
  if (!existsSync15(directory)) {
38073
- return `outputPath's directory ${dirname15(outputPath)} does not exist; a capture creates no directories.`;
38074
+ return `outputPath's directory ${dirname16(outputPath)} does not exist; a capture creates no directories.`;
38074
38075
  }
38075
- const where = join22(directory, basename4(outputPath));
38076
+ const where = join23(directory, basename4(outputPath));
38076
38077
  const inside = projects.find((project) => project !== "" && isWithinRoot(realPathOr(project), where));
38077
38078
  if (inside !== undefined) {
38078
38079
  return `outputPath ${outputPath} is inside the project at ${inside}; a capture is saved outside it, so it never becomes part of the game.`;
@@ -38320,7 +38321,7 @@ function aboveTheRunner(entry) {
38320
38321
  }
38321
38322
  function elsewhereIn(projectPath, asked) {
38322
38323
  const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
38323
- if (wanted === "" || existsSync15(join22(projectPath, wanted))) {
38324
+ if (wanted === "" || existsSync15(join23(projectPath, wanted))) {
38324
38325
  return "";
38325
38326
  }
38326
38327
  const root = (wanted.split("/")[0] ?? "").toLowerCase();
@@ -38334,7 +38335,7 @@ function elsewhereIn(projectPath, asked) {
38334
38335
  return near.length === 0 ? "" : ` The project does have ${there}.`;
38335
38336
  }
38336
38337
  function hasMainScene(projectFile) {
38337
- const scene = parseProjectGodot(readFileSync20(projectFile, "utf8"))["application"]?.["run/main_scene"];
38338
+ const scene = parseProjectGodot(readFileSync21(projectFile, "utf8"))["application"]?.["run/main_scene"];
38338
38339
  return typeof scene === "string" && scene !== "";
38339
38340
  }
38340
38341
  function runtimeAddonAnnouncesEditors(projectPath) {
@@ -38342,13 +38343,13 @@ function runtimeAddonAnnouncesEditors(projectPath) {
38342
38343
  return false;
38343
38344
  }
38344
38345
  try {
38345
- return readFileSync20(join22(projectPath, RUNTIME_AUTOLOAD2.path), "utf8").includes('"editor_pid"');
38346
+ return readFileSync21(join23(projectPath, RUNTIME_AUTOLOAD2.path), "utf8").includes('"editor_pid"');
38346
38347
  } catch {
38347
38348
  return false;
38348
38349
  }
38349
38350
  }
38350
38351
  function editorPlaysHeadless(projectFile) {
38351
- const runArgs = parseProjectGodot(readFileSync20(projectFile, "utf8"))["editor"]?.["run/main_run_args"];
38352
+ const runArgs = parseProjectGodot(readFileSync21(projectFile, "utf8"))["editor"]?.["run/main_run_args"];
38352
38353
  return typeof runArgs === "string" && /(?:^|\s)--headless(?:\s|$)/.test(runArgs);
38353
38354
  }
38354
38355
  function camelCased(params) {
@@ -38367,7 +38368,7 @@ function needsItsOwnProcess(asked) {
38367
38368
  class GodotServer {
38368
38369
  mcp;
38369
38370
  locator = new GodotLocator2;
38370
- operationsScript = join22(__dirname2, "godot", "operations", "godot_operations.gd");
38371
+ operationsScript = join23(__dirname2, "godot", "operations", "godot_operations.gd");
38371
38372
  godotBridge;
38372
38373
  tools = buildToolDefinitions();
38373
38374
  activeProcess = null;
@@ -38511,7 +38512,7 @@ class GodotServer {
38511
38512
  if (this.ownProject === null) {
38512
38513
  return null;
38513
38514
  }
38514
- const announced = readAnnouncement(announcementPath(this.ownProject));
38515
+ const announced = readAnnouncement2(announcementPath2(this.ownProject));
38515
38516
  if (announced === null || announced.pid === process.pid) {
38516
38517
  return null;
38517
38518
  }
@@ -38621,7 +38622,7 @@ class GodotServer {
38621
38622
  try {
38622
38623
  return await this.dispatch(tool, op, args);
38623
38624
  } catch (error) {
38624
- if (error instanceof McpError || error instanceof Refusal2) {
38625
+ if (error instanceof McpError || error instanceof Refusal) {
38625
38626
  throw error;
38626
38627
  }
38627
38628
  const where = op === "" ? tool : `${tool} op=${op}`;
@@ -39032,7 +39033,7 @@ class GodotServer {
39032
39033
  if (path === undefined) {
39033
39034
  return { ok: false, response: this.createErrorResponse("projectPath is required.") };
39034
39035
  }
39035
- const file = join22(path, "project.godot");
39036
+ const file = join23(path, "project.godot");
39036
39037
  if (!existsSync15(file)) {
39037
39038
  return {
39038
39039
  ok: false,
@@ -39301,7 +39302,7 @@ class GodotServer {
39301
39302
  if (!engine.ok) {
39302
39303
  return engine.response;
39303
39304
  }
39304
- const application = parseProjectGodot(readFileSync20(project.value.file, "utf8"))["application"] ?? {};
39305
+ const application = parseProjectGodot(readFileSync21(project.value.file, "utf8"))["application"] ?? {};
39305
39306
  const name = application["config/name"];
39306
39307
  const mainScene = application["run/main_scene"];
39307
39308
  const info = {
@@ -39362,18 +39363,18 @@ class GodotServer {
39362
39363
  if (!engine.ok) {
39363
39364
  return engine.response;
39364
39365
  }
39365
- const folder = dirname15(output.absolutePath);
39366
+ const folder = dirname16(output.absolutePath);
39366
39367
  try {
39367
- mkdirSync13(folder, { recursive: true });
39368
+ mkdirSync14(folder, { recursive: true });
39368
39369
  } catch (error) {
39369
- return this.createErrorResponse(`Cannot create ${dirname15(output.relativePath)} to export into: ${errorMessage(error)}`);
39370
+ return this.createErrorResponse(`Cannot create ${dirname16(output.relativePath)} to export into: ${errorMessage(error)}`);
39370
39371
  }
39371
39372
  const debug = readBoolean(args, "debug") ?? false;
39372
- const exportLogs = mkdtempSync3(join22(tmpdir5(), "gdharness-export-"));
39373
+ const exportLogs = mkdtempSync3(join23(tmpdir5(), "gdharness-export-"));
39373
39374
  const exportArgs = [
39374
39375
  "--headless",
39375
39376
  "--log-file",
39376
- join22(exportLogs, "engine.log"),
39377
+ join23(exportLogs, "engine.log"),
39377
39378
  "--path",
39378
39379
  project.value.path,
39379
39380
  debug ? "--export-debug" : "--export-release",
@@ -39434,7 +39435,7 @@ class GodotServer {
39434
39435
  return contained.response;
39435
39436
  }
39436
39437
  const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
39437
- if (!existsSync15(join22(project.value.path, runner))) {
39438
+ if (!existsSync15(join23(project.value.path, runner))) {
39438
39439
  return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
39439
39440
  "Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
39440
39441
  ]);
@@ -39469,7 +39470,7 @@ class GodotServer {
39469
39470
  ];
39470
39471
  const timeoutMs = readPositiveNumber(args, "timeoutMs") ?? 600000;
39471
39472
  this.logDebug(`Running tests: ${engine.value} ${cmdArgs.join(" ")}`);
39472
- const userData = mkdtempSync3(join22(tmpdir5(), "gdharness-tests-"));
39473
+ const userData = mkdtempSync3(join23(tmpdir5(), "gdharness-tests-"));
39473
39474
  const run = this.spawnGame(engine.value, cmdArgs, userDataIn(userData));
39474
39475
  const hung = await new Promise((resolve) => {
39475
39476
  const timer = setTimeout(() => {
@@ -39485,21 +39486,21 @@ class GodotServer {
39485
39486
  resolve(false);
39486
39487
  });
39487
39488
  });
39488
- const reportsDir = join22(project.value.path, ".godot", ...ours.split("/"));
39489
+ const reportsDir = join23(project.value.path, ".godot", ...ours.split("/"));
39489
39490
  let report = null;
39490
39491
  let reportProblem = null;
39491
39492
  try {
39492
39493
  const written = existsSync15(reportsDir) ? readdirSync9(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
39493
39494
  const newest = written.at(-1);
39494
39495
  if (newest !== undefined) {
39495
- report = parseJUnit(readFileSync20(join22(reportsDir, newest, "results.xml"), "utf8"));
39496
+ report = parseJUnit(readFileSync21(join23(reportsDir, newest, "results.xml"), "utf8"));
39496
39497
  }
39497
39498
  } catch (error) {
39498
39499
  reportProblem = errorMessage(error);
39499
39500
  } finally {
39500
39501
  discard(reportsDir, userData);
39501
39502
  try {
39502
- rmdirSync(dirname15(reportsDir));
39503
+ rmdirSync(dirname16(reportsDir));
39503
39504
  } catch {}
39504
39505
  }
39505
39506
  const engineEntries = run.log.select({ severity: "warning", sinceLastCall: false, limit: 200 }).entries.map(aboveTheRunner);
@@ -39635,7 +39636,7 @@ class GodotServer {
39635
39636
  return null;
39636
39637
  }
39637
39638
  try {
39638
- return readFileSync20(contained.absolutePath, "utf8");
39639
+ return readFileSync21(contained.absolutePath, "utf8");
39639
39640
  } catch {
39640
39641
  return null;
39641
39642
  }
@@ -39689,7 +39690,7 @@ class GodotServer {
39689
39690
  return null;
39690
39691
  }
39691
39692
  try {
39692
- return readFileSync20(contained.absolutePath, "utf8");
39693
+ return readFileSync21(contained.absolutePath, "utf8");
39693
39694
  } catch {
39694
39695
  return null;
39695
39696
  }
@@ -39918,7 +39919,7 @@ class GodotServer {
39918
39919
  return null;
39919
39920
  }
39920
39921
  try {
39921
- return settingKeys(readFileSync20(join22(projectPath, "project.godot"), "utf8"));
39922
+ return settingKeys(readFileSync21(join23(projectPath, "project.godot"), "utf8"));
39922
39923
  } catch {
39923
39924
  return null;
39924
39925
  }
@@ -40169,7 +40170,7 @@ class GodotServer {
40169
40170
  }
40170
40171
  async runtimeUp(projectPath, before, budget, withArgs) {
40171
40172
  const budgetMs = budget.ms;
40172
- if (!existsSync15(join22(projectPath, RUNTIME_AUTOLOAD2.path))) {
40173
+ if (!existsSync15(join23(projectPath, RUNTIME_AUTOLOAD2.path))) {
40173
40174
  return runtimeVerdict(null, { addon: false, budgetMs, heldAt: null, running: false, withArgs });
40174
40175
  }
40175
40176
  let asking = null;
@@ -41352,7 +41353,7 @@ class GodotServer {
41352
41353
  async ownRunOnItsWay(projectPath, budgetMs) {
41353
41354
  const run = this.currentRun();
41354
41355
  const project = projectPath ?? run?.projectPath ?? null;
41355
- if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !existsSync15(join22(project, RUNTIME_AUTOLOAD2.path)) || !await this.runStillGoing(run)) {
41356
+ if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !existsSync15(join23(project, RUNTIME_AUTOLOAD2.path)) || !await this.runStillGoing(run)) {
41356
41357
  return null;
41357
41358
  }
41358
41359
  const already = runtimesAnnounced().running;
@@ -41431,8 +41432,8 @@ class GodotServer {
41431
41432
  return this.createErrorResponse(refusal);
41432
41433
  }
41433
41434
  }
41434
- const screenshotDir = expectsScreenshot ? mkdtempSync3(join22(tmpdir5(), "gdharness-runtime-screenshot-")) : null;
41435
- const screenshotPath = screenshotDir ? join22(screenshotDir, "capture.png") : null;
41435
+ const screenshotDir = expectsScreenshot ? mkdtempSync3(join23(tmpdir5(), "gdharness-runtime-screenshot-")) : null;
41436
+ const screenshotPath = screenshotDir ? join23(screenshotDir, "capture.png") : null;
41436
41437
  try {
41437
41438
  const reply = await runtimeRequest(choice.endpoint, command, screenshotPath ? { ...params, output_path: screenshotPath } : params, timeoutMs);
41438
41439
  if (!reply.ok) {
@@ -41463,7 +41464,7 @@ class GodotServer {
41463
41464
  type: "text",
41464
41465
  text: `Screenshot captured: ${dimensions}${chosenAmongSeveral ? ` from pid ${own}, the game this server holds` : ""}${saveTo === null ? "" : `. Saved to ${saveTo}`}`
41465
41466
  },
41466
- { type: "image", data: readFileSync20(screenshotPath).toString("base64"), mimeType: "image/png" }
41467
+ { type: "image", data: readFileSync21(screenshotPath).toString("base64"), mimeType: "image/png" }
41467
41468
  ]
41468
41469
  };
41469
41470
  } finally {
@@ -41572,7 +41573,7 @@ var init_server3 = __esm(() => {
41572
41573
  init_tool_definitions();
41573
41574
  init_update_check();
41574
41575
  run7 = promisify7(execFile7);
41575
- __dirname2 = dirname15(fileURLToPath5(import.meta.url));
41576
+ __dirname2 = dirname16(fileURLToPath5(import.meta.url));
41576
41577
  CONSOLE_WRAPPER = /_console(\.exe)?$/i;
41577
41578
  LONGEST_BOOT_NOTED_MS = 5 * 60000;
41578
41579
  VALUE_NAMES = {
@@ -41613,20 +41614,61 @@ var init_server3 = __esm(() => {
41613
41614
 
41614
41615
  // src/cli.ts
41615
41616
  import { existsSync as existsSync16 } from "fs";
41616
- import { join as join23, resolve as resolve5 } from "path";
41617
+ import { join as join24, resolve as resolve5 } from "path";
41618
+
41619
+ // src/bridge-announce.ts
41620
+ init_errors();
41621
+ init_process_children();
41622
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
41623
+ import { dirname, join } from "node:path";
41624
+ function announcementPath(projectPath) {
41625
+ return join(projectPath, ".godot", "gdharness-bridge.json");
41626
+ }
41627
+ function readAnnouncement(path) {
41628
+ try {
41629
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
41630
+ if (typeof parsed !== "object" || parsed === null) {
41631
+ return null;
41632
+ }
41633
+ const said = parsed;
41634
+ if (typeof said.port !== "number" || typeof said.pid !== "number") {
41635
+ return null;
41636
+ }
41637
+ return said;
41638
+ } catch {
41639
+ return null;
41640
+ }
41641
+ }
41642
+ function serverBehind(announcement, startedAt) {
41643
+ if (announcement === null || typeof announcement.version !== "string" || startedAt === undefined) {
41644
+ return null;
41645
+ }
41646
+ const announcedAt = Date.parse(announcement.startedAt);
41647
+ if (Number.isNaN(announcedAt) || startedAt > announcedAt + 1000) {
41648
+ return null;
41649
+ }
41650
+ return { version: announcement.version, pid: announcement.pid };
41651
+ }
41652
+ function serverServing(projectPath) {
41653
+ const announcement = readAnnouncement(announcementPath(projectPath));
41654
+ if (announcement === null) {
41655
+ return null;
41656
+ }
41657
+ return serverBehind(announcement, startTimesOf([announcement.pid]).get(announcement.pid));
41658
+ }
41617
41659
 
41618
41660
  // src/errors.ts
41619
- class Refusal extends Error {
41661
+ class Refusal2 extends Error {
41620
41662
  }
41621
41663
 
41622
41664
  // src/godot-path.ts
41623
41665
  init_detection();
41624
41666
  init_errors();
41625
- import { execFile } from "node:child_process";
41667
+ import { execFile as execFile2 } from "node:child_process";
41626
41668
  import { existsSync as existsSync2 } from "node:fs";
41627
41669
  import { normalize } from "node:path";
41628
- import { promisify } from "node:util";
41629
- var run = promisify(execFile);
41670
+ import { promisify as promisify2 } from "node:util";
41671
+ var run2 = promisify2(execFile2);
41630
41672
 
41631
41673
  class GodotLocator {
41632
41674
  answered = new Map;
@@ -41683,7 +41725,7 @@ class GodotLocator {
41683
41725
  reason = "does not exist";
41684
41726
  } else {
41685
41727
  try {
41686
- await run(path, ["--version"]);
41728
+ await run2(path, ["--version"]);
41687
41729
  reason = null;
41688
41730
  } catch (error) {
41689
41731
  reason = `does not answer --version: ${errorMessage(error)}`;
@@ -41695,9 +41737,9 @@ class GodotLocator {
41695
41737
  }
41696
41738
 
41697
41739
  // src/harnesses.ts
41698
- import { existsSync as existsSync4, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
41740
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
41699
41741
  import { homedir as homedir2 } from "node:os";
41700
- import { dirname as dirname2, join as join3 } from "node:path";
41742
+ import { dirname as dirname3, join as join4 } from "node:path";
41701
41743
  import process3 from "node:process";
41702
41744
 
41703
41745
  // node_modules/yaml/dist/index.js
@@ -41870,7 +41912,7 @@ var HARNESSES = [
41870
41912
  shape: "plain",
41871
41913
  home: ".claude",
41872
41914
  marker: ".claude",
41873
- skills: { dir: join3(".claude", "skills"), shared: false }
41915
+ skills: { dir: join4(".claude", "skills"), shared: false }
41874
41916
  },
41875
41917
  {
41876
41918
  id: "copilot-cli",
@@ -41880,7 +41922,7 @@ var HARNESSES = [
41880
41922
  container: "mcpServers",
41881
41923
  shape: "plain",
41882
41924
  home: ".copilot",
41883
- skills: { dir: join3(".github", "skills"), shared: true },
41925
+ skills: { dir: join4(".github", "skills"), shared: true },
41884
41926
  manual: "Trust the folder when Copilot CLI first asks, or it reads no config here."
41885
41927
  },
41886
41928
  {
@@ -41906,22 +41948,22 @@ var HARNESSES = [
41906
41948
  id: "cursor",
41907
41949
  name: "Cursor",
41908
41950
  scope: "project",
41909
- file: join3(".cursor", "mcp.json"),
41951
+ file: join4(".cursor", "mcp.json"),
41910
41952
  container: "mcpServers",
41911
41953
  shape: "plain",
41912
41954
  home: ".cursor",
41913
- skills: { dir: join3(".cursor", "skills"), shared: true },
41955
+ skills: { dir: join4(".cursor", "skills"), shared: true },
41914
41956
  manual: "Cursor asks before each tool call by default, and the server can be toggled off."
41915
41957
  },
41916
41958
  {
41917
41959
  id: "vscode",
41918
41960
  name: "VS Code",
41919
41961
  scope: "project",
41920
- file: join3(".vscode", "mcp.json"),
41962
+ file: join4(".vscode", "mcp.json"),
41921
41963
  container: "servers",
41922
41964
  shape: "typed",
41923
41965
  home: ".vscode",
41924
- skills: { dir: join3(".github", "skills"), shared: true },
41966
+ skills: { dir: join4(".github", "skills"), shared: true },
41925
41967
  manual: "VS Code asks you to trust a server the first time it starts one."
41926
41968
  },
41927
41969
  {
@@ -41931,45 +41973,45 @@ var HARNESSES = [
41931
41973
  file: "opencode.json",
41932
41974
  container: "mcp",
41933
41975
  shape: "opencode",
41934
- home: join3(".config", "opencode"),
41976
+ home: join4(".config", "opencode"),
41935
41977
  marker: ".opencode",
41936
- skills: { dir: join3(".opencode", "skills"), shared: true }
41978
+ skills: { dir: join4(".opencode", "skills"), shared: true }
41937
41979
  },
41938
41980
  {
41939
41981
  id: "junie",
41940
41982
  name: "Junie",
41941
41983
  scope: "project",
41942
- file: join3(".junie", "mcp", "mcp.json"),
41984
+ file: join4(".junie", "mcp", "mcp.json"),
41943
41985
  container: "mcpServers",
41944
41986
  shape: "plain",
41945
41987
  home: ".junie",
41946
- skills: { dir: join3(".junie", "skills"), shared: true }
41988
+ skills: { dir: join4(".junie", "skills"), shared: true }
41947
41989
  },
41948
41990
  {
41949
41991
  id: "kiro",
41950
41992
  name: "Kiro",
41951
41993
  scope: "project",
41952
- file: join3(".kiro", "settings", "mcp.json"),
41994
+ file: join4(".kiro", "settings", "mcp.json"),
41953
41995
  container: "mcpServers",
41954
41996
  shape: "plain",
41955
41997
  home: ".kiro",
41956
- skills: { dir: join3(".kiro", "skills"), shared: false }
41998
+ skills: { dir: join4(".kiro", "skills"), shared: false }
41957
41999
  },
41958
42000
  {
41959
42001
  id: "gemini",
41960
42002
  name: "Gemini CLI",
41961
42003
  scope: "project",
41962
- file: join3(".gemini", "settings.json"),
42004
+ file: join4(".gemini", "settings.json"),
41963
42005
  container: "mcpServers",
41964
42006
  shape: "plain",
41965
42007
  home: ".gemini",
41966
- skills: { dir: join3(".gemini", "skills"), shared: true }
42008
+ skills: { dir: join4(".gemini", "skills"), shared: true }
41967
42009
  },
41968
42010
  {
41969
42011
  id: "roo",
41970
42012
  name: "Roo Code",
41971
42013
  scope: "project",
41972
- file: join3(".roo", "mcp.json"),
42014
+ file: join4(".roo", "mcp.json"),
41973
42015
  container: "mcpServers",
41974
42016
  shape: "plain"
41975
42017
  },
@@ -41977,7 +42019,7 @@ var HARNESSES = [
41977
42019
  id: "kilo",
41978
42020
  name: "Kilo Code",
41979
42021
  scope: "project",
41980
- file: join3(".kilocode", "mcp.json"),
42022
+ file: join4(".kilocode", "mcp.json"),
41981
42023
  container: "mcpServers",
41982
42024
  shape: "plain"
41983
42025
  },
@@ -41985,16 +42027,16 @@ var HARNESSES = [
41985
42027
  id: "amazon-q",
41986
42028
  name: "Amazon Q Developer CLI",
41987
42029
  scope: "project",
41988
- file: join3(".amazonq", "mcp.json"),
42030
+ file: join4(".amazonq", "mcp.json"),
41989
42031
  container: "mcpServers",
41990
42032
  shape: "plain",
41991
- home: join3(".aws", "amazonq")
42033
+ home: join4(".aws", "amazonq")
41992
42034
  },
41993
42035
  {
41994
42036
  id: "zed",
41995
42037
  name: "Zed",
41996
42038
  scope: "project",
41997
- file: join3(".zed", "settings.json"),
42039
+ file: join4(".zed", "settings.json"),
41998
42040
  container: "context_servers",
41999
42041
  shape: "plain"
42000
42042
  },
@@ -42002,16 +42044,16 @@ var HARNESSES = [
42002
42044
  id: "amp",
42003
42045
  name: "Amp",
42004
42046
  scope: "project",
42005
- file: join3(".amp", "settings.json"),
42047
+ file: join4(".amp", "settings.json"),
42006
42048
  container: "amp.mcpServers",
42007
42049
  shape: "plain",
42008
- home: join3(".config", "amp")
42050
+ home: join4(".config", "amp")
42009
42051
  },
42010
42052
  {
42011
42053
  id: "warp",
42012
42054
  name: "Warp",
42013
42055
  scope: "project",
42014
- file: join3(".warp", ".mcp.json"),
42056
+ file: join4(".warp", ".mcp.json"),
42015
42057
  container: "mcpServers",
42016
42058
  shape: "plain",
42017
42059
  home: ".warp",
@@ -42021,7 +42063,7 @@ var HARNESSES = [
42021
42063
  id: "trae",
42022
42064
  name: "Trae",
42023
42065
  scope: "project",
42024
- file: join3(".trae", "mcp.json"),
42066
+ file: join4(".trae", "mcp.json"),
42025
42067
  container: "mcpServers",
42026
42068
  shape: "plain",
42027
42069
  home: ".trae"
@@ -42030,7 +42072,7 @@ var HARNESSES = [
42030
42072
  id: "factory",
42031
42073
  name: "Factory Droid",
42032
42074
  scope: "project",
42033
- file: join3(".factory", "mcp.json"),
42075
+ file: join4(".factory", "mcp.json"),
42034
42076
  container: "mcpServers",
42035
42077
  shape: "typed",
42036
42078
  home: ".factory"
@@ -42039,7 +42081,7 @@ var HARNESSES = [
42039
42081
  id: "tabnine",
42040
42082
  name: "Tabnine",
42041
42083
  scope: "project",
42042
- file: join3(".tabnine", "mcp_servers.json"),
42084
+ file: join4(".tabnine", "mcp_servers.json"),
42043
42085
  container: "mcpServers",
42044
42086
  shape: "plain",
42045
42087
  home: ".tabnine"
@@ -42056,7 +42098,7 @@ var HARNESSES = [
42056
42098
  id: "pi",
42057
42099
  name: "pi",
42058
42100
  scope: "project",
42059
- file: join3(".pi", "mcp.json"),
42101
+ file: join4(".pi", "mcp.json"),
42060
42102
  container: "mcpServers",
42061
42103
  shape: "plain",
42062
42104
  home: ".pi"
@@ -42065,7 +42107,7 @@ var HARNESSES = [
42065
42107
  id: "mistral-vibe",
42066
42108
  name: "Mistral Vibe",
42067
42109
  scope: "project",
42068
- file: join3(".vibe", "config.toml"),
42110
+ file: join4(".vibe", "config.toml"),
42069
42111
  container: "mcp_servers",
42070
42112
  shape: "plain",
42071
42113
  toml: {
@@ -42121,7 +42163,7 @@ var HARNESSES = [
42121
42163
  id: "codex",
42122
42164
  name: "Codex CLI",
42123
42165
  scope: "home",
42124
- file: join3(".codex", "config.toml"),
42166
+ file: join4(".codex", "config.toml"),
42125
42167
  container: "mcp_servers",
42126
42168
  shape: "plain",
42127
42169
  manual: "Codex reads its config at startup, so restart it.",
@@ -42140,20 +42182,20 @@ var HARNESSES = [
42140
42182
  id: "cline",
42141
42183
  name: "Cline",
42142
42184
  scope: "home",
42143
- file: join3(".cline", "data", "settings", "cline_mcp_settings.json"),
42185
+ file: join4(".cline", "data", "settings", "cline_mcp_settings.json"),
42144
42186
  container: "mcpServers",
42145
42187
  shape: "plain",
42146
42188
  marker: ".cline",
42147
- skills: { dir: join3(".cline", "skills"), shared: false }
42189
+ skills: { dir: join4(".cline", "skills"), shared: false }
42148
42190
  },
42149
42191
  {
42150
42192
  id: "goose",
42151
42193
  name: "Goose",
42152
42194
  scope: "home",
42153
42195
  file: {
42154
- win32: { appData: join3("Block", "goose", "config", "config.yaml") },
42155
- darwin: join3(".config", "goose", "config.yaml"),
42156
- linux: join3(".config", "goose", "config.yaml")
42196
+ win32: { appData: join4("Block", "goose", "config", "config.yaml") },
42197
+ darwin: join4(".config", "goose", "config.yaml"),
42198
+ linux: join4(".config", "goose", "config.yaml")
42157
42199
  },
42158
42200
  container: "extensions",
42159
42201
  shape: "plain",
@@ -42174,19 +42216,19 @@ var HARNESSES = [
42174
42216
  id: "windsurf",
42175
42217
  name: "Windsurf",
42176
42218
  scope: "home",
42177
- file: join3(".codeium", "windsurf", "mcp_config.json"),
42219
+ file: join4(".codeium", "windsurf", "mcp_config.json"),
42178
42220
  container: "mcpServers",
42179
42221
  shape: "plain",
42180
- skills: { dir: join3(".windsurf", "skills"), shared: true }
42222
+ skills: { dir: join4(".windsurf", "skills"), shared: true }
42181
42223
  },
42182
42224
  {
42183
42225
  id: "hermes",
42184
42226
  name: "Hermes",
42185
42227
  scope: "home",
42186
- file: join3(".hermes", "config.yaml"),
42228
+ file: join4(".hermes", "config.yaml"),
42187
42229
  container: "mcp_servers",
42188
42230
  shape: "plain",
42189
- skills: { dir: join3(".hermes", "skills"), shared: true },
42231
+ skills: { dir: join4(".hermes", "skills"), shared: true },
42190
42232
  yaml: {
42191
42233
  path: ["mcp_servers", SERVER_KEY],
42192
42234
  entry: (launch) => ({
@@ -42201,7 +42243,7 @@ var HARNESSES = [
42201
42243
  id: "openclaw",
42202
42244
  name: "OpenClaw",
42203
42245
  scope: "home",
42204
- file: join3(".openclaw", "openclaw.json"),
42246
+ file: join4(".openclaw", "openclaw.json"),
42205
42247
  container: "mcpServers",
42206
42248
  shape: "plain"
42207
42249
  },
@@ -42210,9 +42252,9 @@ var HARNESSES = [
42210
42252
  name: "Claude Desktop",
42211
42253
  scope: "home",
42212
42254
  file: {
42213
- win32: { appData: join3("Claude", "claude_desktop_config.json") },
42214
- darwin: join3("Library", "Application Support", "Claude", "claude_desktop_config.json"),
42215
- linux: join3(".config", "Claude", "claude_desktop_config.json")
42255
+ win32: { appData: join4("Claude", "claude_desktop_config.json") },
42256
+ darwin: join4("Library", "Application Support", "Claude", "claude_desktop_config.json"),
42257
+ linux: join4(".config", "Claude", "claude_desktop_config.json")
42216
42258
  },
42217
42259
  container: "mcpServers",
42218
42260
  shape: "plain"
@@ -42221,7 +42263,7 @@ var HARNESSES = [
42221
42263
  id: "zeroclaw",
42222
42264
  name: "ZeroClaw",
42223
42265
  scope: "home",
42224
- file: join3(".zeroclaw", "config.toml"),
42266
+ file: join4(".zeroclaw", "config.toml"),
42225
42267
  container: "mcp.servers",
42226
42268
  shape: "plain",
42227
42269
  toml: {
@@ -42242,7 +42284,7 @@ var HARNESSES = [
42242
42284
  id: "deepcode",
42243
42285
  name: "Deep Code",
42244
42286
  scope: "home",
42245
- file: join3(".deepcode", "settings.json"),
42287
+ file: join4(".deepcode", "settings.json"),
42246
42288
  container: "mcpServers",
42247
42289
  shape: "plain"
42248
42290
  },
@@ -42250,7 +42292,7 @@ var HARNESSES = [
42250
42292
  id: "nanobot",
42251
42293
  name: "nanobot",
42252
42294
  scope: "home",
42253
- file: join3(".nanobot", "config.json"),
42295
+ file: join4(".nanobot", "config.json"),
42254
42296
  container: "mcpServers",
42255
42297
  shape: "plain",
42256
42298
  snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
@@ -42259,17 +42301,17 @@ var HARNESSES = [
42259
42301
  id: "autohand",
42260
42302
  name: "Autohand",
42261
42303
  scope: "home",
42262
- file: join3(".autohand", "config.json"),
42304
+ file: join4(".autohand", "config.json"),
42263
42305
  container: "mcpServers",
42264
42306
  shape: "plain",
42265
42307
  snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
42266
42308
  }
42267
42309
  ];
42268
42310
  function appDataRoot() {
42269
- return process3.env["APPDATA"] ?? join3(homedir2(), "AppData", "Roaming");
42311
+ return process3.env["APPDATA"] ?? join4(homedir2(), "AppData", "Roaming");
42270
42312
  }
42271
42313
  function homePath(path) {
42272
- return typeof path === "string" ? join3(homedir2(), path) : join3(appDataRoot(), path.appData);
42314
+ return typeof path === "string" ? join4(homedir2(), path) : join4(appDataRoot(), path.appData);
42273
42315
  }
42274
42316
  function fileFor(harness, platform = process3.platform) {
42275
42317
  if (typeof harness.file === "string") {
@@ -42280,7 +42322,7 @@ function fileFor(harness, platform = process3.platform) {
42280
42322
  function configPath(harness, projectPath) {
42281
42323
  const file = fileFor(harness);
42282
42324
  if (harness.scope === "project") {
42283
- return join3(projectPath, file);
42325
+ return join4(projectPath, file);
42284
42326
  }
42285
42327
  return homePath(file);
42286
42328
  }
@@ -42339,11 +42381,11 @@ function present(harness, projectPath) {
42339
42381
  return true;
42340
42382
  }
42341
42383
  const root = harness.scope === "project" ? projectPath : homedir2();
42342
- const own = dirname2(path);
42384
+ const own = dirname3(path);
42343
42385
  if (own !== root && existsSync4(own)) {
42344
42386
  return true;
42345
42387
  }
42346
- return harness.marker !== undefined && existsSync4(join3(root, harness.marker));
42388
+ return harness.marker !== undefined && existsSync4(join4(root, harness.marker));
42347
42389
  }
42348
42390
  function candidates(projectPath) {
42349
42391
  const found = [];
@@ -42356,7 +42398,7 @@ function candidates(projectPath) {
42356
42398
  }
42357
42399
  if (present(harness, projectPath)) {
42358
42400
  found.push({ harness, reason: "configured" });
42359
- } else if (harness.home !== undefined && existsSync4(join3(homedir2(), harness.home))) {
42401
+ } else if (harness.home !== undefined && existsSync4(join4(homedir2(), harness.home))) {
42360
42402
  found.push({ harness, reason: "installed" });
42361
42403
  }
42362
42404
  }
@@ -42381,7 +42423,7 @@ function registered(harness, projectPath) {
42381
42423
  if (harness.snippet !== undefined || !existsSync4(path)) {
42382
42424
  return false;
42383
42425
  }
42384
- const text = readFileSync(path, "utf8");
42426
+ const text = readFileSync2(path, "utf8");
42385
42427
  if (harness.toml !== undefined) {
42386
42428
  return text.includes(harness.toml.identity ?? harness.toml.header);
42387
42429
  }
@@ -42411,7 +42453,7 @@ function recordedEnginePath(projectPath) {
42411
42453
  }
42412
42454
  let parsed;
42413
42455
  try {
42414
- parsed = JSON.parse(readFileSync(path, "utf8"));
42456
+ parsed = JSON.parse(readFileSync2(path, "utf8"));
42415
42457
  } catch {
42416
42458
  continue;
42417
42459
  }
@@ -42434,7 +42476,7 @@ function disconnect(harness, projectPath) {
42434
42476
  if (harness.snippet !== undefined) {
42435
42477
  return { harness, path, action: "manual" };
42436
42478
  }
42437
- const text = readFileSync(path, "utf8");
42479
+ const text = readFileSync2(path, "utf8");
42438
42480
  if (harness.toml !== undefined) {
42439
42481
  return taken(harness, path, text, removeToml(text, harness.toml));
42440
42482
  }
@@ -42443,7 +42485,7 @@ function disconnect(harness, projectPath) {
42443
42485
  }
42444
42486
  let existing;
42445
42487
  try {
42446
- existing = JSON.parse(readFileSync(path, "utf8"));
42488
+ existing = JSON.parse(readFileSync2(path, "utf8"));
42447
42489
  } catch {
42448
42490
  return { harness, path, action: "absent" };
42449
42491
  }
@@ -42463,25 +42505,32 @@ function disconnect(harness, projectPath) {
42463
42505
  root[harness.container] = servers;
42464
42506
  }
42465
42507
  if (Object.keys(root).length === 0) {
42466
- rmSync(path, { force: true });
42508
+ rmSync2(path, { force: true });
42467
42509
  return { harness, path, action: "deleted" };
42468
42510
  }
42469
- writeFileSync(path, `${JSON.stringify(root, null, 2)}
42511
+ writeFileSync2(path, `${JSON.stringify(root, null, 2)}
42470
42512
  `, "utf8");
42471
42513
  return { harness, path, action: "removed" };
42472
42514
  }
42473
- function harnessNote(repinned, now) {
42515
+ function harnessNote(repinned, now, running = null) {
42474
42516
  const alsoByHand = repinned.byHand === 0 ? "" : `
42475
42517
  ${repinned.byHand === 1 ? "One harness above was" : `${repinned.byHand} harnesses above were`} handed a command to run instead; run it too.`;
42518
+ const serving = running === null ? ` No gdharness server is announcing itself for this project, so which one your harness
42519
+ ` + ` is running cannot be read from here.
42520
+ ` : ` The server serving this project is gdharness ${running.server.version} (pid ${running.server.pid})${running.isThisVersion ? ", which is already this version." : "."}
42521
+ `;
42522
+ if (running?.isThisVersion === true && repinned.byHand === 0 && (repinned.moved.length > 0 || repinned.written > 0)) {
42523
+ return ` 2. Nothing for the harness: the server serving this project is gdharness ${running.server.version}
42524
+ (pid ${running.server.pid}), which is already this version.`;
42525
+ }
42476
42526
  if (repinned.moved.length > 0) {
42477
- return ` 2. Your harness is still running the server it spawned from ${repinned.moved.join(", ")}.
42478
- ` + ` Its config names ${now} now.
42479
- ` + ` Reconnect the MCP server, or restart the harness.${alsoByHand}`;
42527
+ return ` 2. Your harness config held ${repinned.moved.join(", ")} before this upgrade.
42528
+ ` + ` It names ${now} now.
42529
+ ` + serving + ` Reconnect the MCP server, or restart the harness.${alsoByHand}`;
42480
42530
  }
42481
42531
  if (repinned.written > 0) {
42482
- return ` 2. Your harness config already named this version, but the server it is running is
42483
- ` + ` whichever one it spawned when the session started, which this cannot see from here.
42484
- ` + ` Reconnect the MCP server, or restart the harness.${alsoByHand}`;
42532
+ return ` 2. Your harness config already named this version.
42533
+ ` + serving + ` Reconnect the MCP server, or restart the harness.${alsoByHand}`;
42485
42534
  }
42486
42535
  if (repinned.byHand > 0) {
42487
42536
  return ` 2. None of the harness configs found here can be written for you, so nothing was
@@ -42508,7 +42557,7 @@ function connect(harness, projectPath, launch) {
42508
42557
  if (harness.snippet !== undefined) {
42509
42558
  return { harness, path, action: "snippet", snippet: harness.snippet(launch) };
42510
42559
  }
42511
- const held = existsSync4(path) ? readFileSync(path, "utf8") : "";
42560
+ const held = existsSync4(path) ? readFileSync2(path, "utf8") : "";
42512
42561
  if (harness.toml !== undefined) {
42513
42562
  const already = held.includes(harness.toml.identity ?? harness.toml.header);
42514
42563
  return put(harness, path, writeToml(held, harness.toml, launch), already);
@@ -42522,7 +42571,7 @@ function connect(harness, projectPath, launch) {
42522
42571
  try {
42523
42572
  existing = JSON.parse(held);
42524
42573
  } catch (cause) {
42525
- throw new Refusal2(`${path} is not valid JSON, so gdharness was not added to it.`, { cause });
42574
+ throw new Refusal(`${path} is not valid JSON, so gdharness was not added to it.`, { cause });
42526
42575
  }
42527
42576
  }
42528
42577
  const container = typeof existing === "object" && existing !== null && !Array.isArray(existing) ? existing[harness.container] : undefined;
@@ -42534,8 +42583,8 @@ function connect(harness, projectPath, launch) {
42534
42583
  return was === undefined || was === now ? written : { ...written, wasLaunchedBy: was };
42535
42584
  }
42536
42585
  function put(harness, path, contents, already) {
42537
- mkdirSync(dirname2(path), { recursive: true });
42538
- writeFileSync(path, contents, "utf8");
42586
+ mkdirSync2(dirname3(path), { recursive: true });
42587
+ writeFileSync2(path, contents, "utf8");
42539
42588
  return { harness, path, action: already ? "replaced" : "written" };
42540
42589
  }
42541
42590
  function taken(harness, path, held, stripped) {
@@ -42543,10 +42592,10 @@ function taken(harness, path, held, stripped) {
42543
42592
  return { harness, path, action: "absent" };
42544
42593
  }
42545
42594
  if (stripped.trim() === "" || stripped.trim() === "{}") {
42546
- rmSync(path, { force: true });
42595
+ rmSync2(path, { force: true });
42547
42596
  return { harness, path, action: "deleted" };
42548
42597
  }
42549
- writeFileSync(path, stripped, "utf8");
42598
+ writeFileSync2(path, stripped, "utf8");
42550
42599
  return { harness, path, action: "removed" };
42551
42600
  }
42552
42601
 
@@ -42554,12 +42603,12 @@ function taken(harness, path, held, stripped) {
42554
42603
  init_call_signal();
42555
42604
  init_game_log();
42556
42605
  init_scratch();
42557
- import { execFile as execFile2 } from "node:child_process";
42558
- import { mkdtempSync, writeFileSync as writeFileSync2 } from "node:fs";
42606
+ import { execFile as execFile3 } from "node:child_process";
42607
+ import { mkdtempSync, writeFileSync as writeFileSync3 } from "node:fs";
42559
42608
  import { tmpdir } from "node:os";
42560
- import { join as join4 } from "node:path";
42561
- import { promisify as promisify2 } from "node:util";
42562
- var run2 = promisify2(execFile2);
42609
+ import { join as join5 } from "node:path";
42610
+ import { promisify as promisify3 } from "node:util";
42611
+ var run3 = promisify3(execFile3);
42563
42612
  function snakeCased(params) {
42564
42613
  const result = emptyRecord();
42565
42614
  for (const [key, value] of Object.entries(params)) {
@@ -42598,13 +42647,13 @@ function reason(stdout, stderr) {
42598
42647
  return stdout.trim().split(/\r?\n/).at(-1) ?? "no output at all";
42599
42648
  }
42600
42649
  async function runOperation(engine, operation, params, projectPath) {
42601
- const paramsDir = mkdtempSync(join4(tmpdir(), "gdharness-params-"));
42602
- const paramsFile = join4(paramsDir, `${operation}.json`);
42603
- writeFileSync2(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
42650
+ const paramsDir = mkdtempSync(join5(tmpdir(), "gdharness-params-"));
42651
+ const paramsFile = join5(paramsDir, `${operation}.json`);
42652
+ writeFileSync3(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
42604
42653
  const args = [
42605
42654
  "--headless",
42606
42655
  "--log-file",
42607
- join4(paramsDir, "engine.log"),
42656
+ join5(paramsDir, "engine.log"),
42608
42657
  "--path",
42609
42658
  projectPath,
42610
42659
  "--script",
@@ -42616,7 +42665,7 @@ async function runOperation(engine, operation, params, projectPath) {
42616
42665
  let stdout;
42617
42666
  let stderr;
42618
42667
  try {
42619
- ({ stdout, stderr } = await run2(engine.godotPath, args, { signal: callSignal() }));
42668
+ ({ stdout, stderr } = await run3(engine.godotPath, args, { signal: callSignal() }));
42620
42669
  } catch (error) {
42621
42670
  if (error instanceof Error && "stdout" in error && "stderr" in error) {
42622
42671
  const failed = error;
@@ -42774,12 +42823,12 @@ class Ask {
42774
42823
 
42775
42824
  // src/server-version.ts
42776
42825
  init_update_check();
42777
- import { readFileSync as readFileSync4 } from "node:fs";
42826
+ import { readFileSync as readFileSync5 } from "node:fs";
42778
42827
  var DEBUG_MODE2 = process.env["DEBUG"] === "true";
42779
42828
  var GODOT_DEBUG_MODE_DEFAULT2 = process.env["GODOT_DEBUG"] === "true" || DEBUG_MODE2;
42780
42829
  var SERVER_VERSION2 = (() => {
42781
42830
  try {
42782
- const pkg = JSON.parse(readFileSync4(new URL("../package.json", import.meta.url), "utf8"));
42831
+ const pkg = JSON.parse(readFileSync5(new URL("../package.json", import.meta.url), "utf8"));
42783
42832
  return typeof pkg.version === "string" ? pkg.version : "0.0.0";
42784
42833
  } catch {
42785
42834
  return "0.0.0";
@@ -42791,19 +42840,19 @@ init_class_cache();
42791
42840
  init_headless();
42792
42841
  init_resources();
42793
42842
  init_server_version();
42794
- import { spawnSync } from "node:child_process";
42843
+ import { spawnSync as spawnSync2 } from "node:child_process";
42795
42844
  import { createHash as createHash2 } from "node:crypto";
42796
42845
  import {
42797
42846
  cpSync,
42798
42847
  existsSync as existsSync7,
42799
- mkdirSync as mkdirSync3,
42848
+ mkdirSync as mkdirSync4,
42800
42849
  readdirSync as readdirSync3,
42801
- readFileSync as readFileSync7,
42802
- rmSync as rmSync3,
42850
+ readFileSync as readFileSync8,
42851
+ rmSync as rmSync4,
42803
42852
  statSync as statSync3,
42804
- writeFileSync as writeFileSync5
42853
+ writeFileSync as writeFileSync6
42805
42854
  } from "node:fs";
42806
- import { dirname as dirname3, join as join8 } from "node:path";
42855
+ import { dirname as dirname4, join as join9 } from "node:path";
42807
42856
  import { fileURLToPath } from "node:url";
42808
42857
  var ADDONS = ["gdharness_editor", "gdharness_runtime", "auto_reload"];
42809
42858
  var EDITOR_PLUGINS = ["gdharness_editor", "auto_reload"];
@@ -42820,64 +42869,64 @@ function editorAddonDigest(from = shippedAddonsDirectory()) {
42820
42869
  if (name === VERSION_MARKER || name === DIGEST_MARKER) {
42821
42870
  continue;
42822
42871
  }
42823
- const path = join8(directory, name);
42872
+ const path = join9(directory, name);
42824
42873
  const inside = `${relative}/${name}`;
42825
42874
  if (statSync3(path).isDirectory()) {
42826
42875
  walk(path, inside);
42827
42876
  } else {
42828
42877
  hash.update(`${inside}
42829
42878
  `);
42830
- hash.update(readFileSync7(path));
42879
+ hash.update(readFileSync8(path));
42831
42880
  hash.update(`
42832
42881
  `);
42833
42882
  }
42834
42883
  }
42835
42884
  };
42836
42885
  for (const name of EDITOR_PLUGINS) {
42837
- walk(join8(from, name), name);
42886
+ walk(join9(from, name), name);
42838
42887
  }
42839
42888
  return hash.digest("hex");
42840
42889
  }
42841
42890
  function installedEditorDigest(projectPath) {
42842
- const marker = join8(projectPath, "addons", ADDONS[0], DIGEST_MARKER);
42891
+ const marker = join9(projectPath, "addons", ADDONS[0], DIGEST_MARKER);
42843
42892
  if (!existsSync7(marker)) {
42844
42893
  return null;
42845
42894
  }
42846
- const said = readFileSync7(marker, "utf8").trim();
42895
+ const said = readFileSync8(marker, "utf8").trim();
42847
42896
  return said === "" ? null : said;
42848
42897
  }
42849
42898
  function shippedAddonsDirectory() {
42850
- return join8(dirname3(fileURLToPath(import.meta.url)), "godot", "addons");
42899
+ return join9(dirname4(fileURLToPath(import.meta.url)), "godot", "addons");
42851
42900
  }
42852
42901
  function shippedOperationsScript() {
42853
- return join8(dirname3(fileURLToPath(import.meta.url)), "godot", "operations", "godot_operations.gd");
42902
+ return join9(dirname4(fileURLToPath(import.meta.url)), "godot", "operations", "godot_operations.gd");
42854
42903
  }
42855
42904
  function installAddons(projectPath, from = shippedAddonsDirectory()) {
42856
42905
  const installed = [];
42857
42906
  for (const name of ADDONS) {
42858
- const source = join8(from, name);
42859
- if (!existsSync7(join8(source, name === "gdharness_runtime" ? "runtime_autoload.gd" : "plugin.cfg"))) {
42907
+ const source = join9(from, name);
42908
+ if (!existsSync7(join9(source, name === "gdharness_runtime" ? "runtime_autoload.gd" : "plugin.cfg"))) {
42860
42909
  throw new Error(`The package holds no ${name} addon at ${source}.`);
42861
42910
  }
42862
- const target = join8(projectPath, "addons", name);
42911
+ const target = join9(projectPath, "addons", name);
42863
42912
  const replaced = existsSync7(target);
42864
- rmSync3(target, { recursive: true, force: true });
42865
- mkdirSync3(dirname3(target), { recursive: true });
42913
+ rmSync4(target, { recursive: true, force: true });
42914
+ mkdirSync4(dirname4(target), { recursive: true });
42866
42915
  cpSync(source, target, { recursive: true });
42867
- writeFileSync5(join8(target, VERSION_MARKER), `${SERVER_VERSION}
42916
+ writeFileSync6(join9(target, VERSION_MARKER), `${SERVER_VERSION}
42868
42917
  `);
42869
42918
  installed.push({ name, path: target, replaced });
42870
42919
  }
42871
- writeFileSync5(join8(projectPath, "addons", ADDONS[0], DIGEST_MARKER), `${editorAddonDigest(from)}
42920
+ writeFileSync6(join9(projectPath, "addons", ADDONS[0], DIGEST_MARKER), `${editorAddonDigest(from)}
42872
42921
  `);
42873
42922
  return installed;
42874
42923
  }
42875
42924
  function removeAddons(projectPath) {
42876
42925
  const removed = [];
42877
42926
  for (const name of ADDONS) {
42878
- const target = join8(projectPath, "addons", name);
42927
+ const target = join9(projectPath, "addons", name);
42879
42928
  if (existsSync7(target)) {
42880
- rmSync3(target, { recursive: true, force: true });
42929
+ rmSync4(target, { recursive: true, force: true });
42881
42930
  removed.push(target);
42882
42931
  }
42883
42932
  }
@@ -42911,7 +42960,7 @@ function loaderAmong(projectPath, named) {
42911
42960
  }
42912
42961
  let source = null;
42913
42962
  try {
42914
- source = readFileSync7(join8(projectPath, path), "utf8");
42963
+ source = readFileSync8(join9(projectPath, path), "utf8");
42915
42964
  } catch {}
42916
42965
  if (source?.includes(RUNTIME_AUTOLOAD.path)) {
42917
42966
  return { name: entry, path, exists: true };
@@ -42934,7 +42983,7 @@ function trackedByGit(projectPath, wanted) {
42934
42983
  if (wanted.length === 0) {
42935
42984
  return new Set;
42936
42985
  }
42937
- const asked = spawnSync("git", ["ls-files", "-z", "--", ...wanted], {
42986
+ const asked = spawnSync2("git", ["ls-files", "-z", "--", ...wanted], {
42938
42987
  cwd: projectPath,
42939
42988
  encoding: "utf8"
42940
42989
  });
@@ -42953,10 +43002,10 @@ function enabledPlugins(settings) {
42953
43002
  function inspectProject(projectPath) {
42954
43003
  const problems = [];
42955
43004
  const addons = ADDONS.map((name) => {
42956
- const directory = join8(projectPath, "addons", name);
42957
- const marker = join8(directory, VERSION_MARKER);
43005
+ const directory = join9(projectPath, "addons", name);
43006
+ const marker = join9(directory, VERSION_MARKER);
42958
43007
  const installed = existsSync7(directory);
42959
- const version = existsSync7(marker) ? readFileSync7(marker, "utf8").trim() : null;
43008
+ const version = existsSync7(marker) ? readFileSync8(marker, "utf8").trim() : null;
42960
43009
  const current = version === SERVER_VERSION;
42961
43010
  if (!installed) {
42962
43011
  problems.push(`addons/${name} is not installed; run gdharness setup`);
@@ -42965,7 +43014,7 @@ function inspectProject(projectPath) {
42965
43014
  }
42966
43015
  return { name, installed, version, current };
42967
43016
  });
42968
- const settings = parseProjectGodot(readFileSync7(join8(projectPath, "project.godot"), "utf8"));
43017
+ const settings = parseProjectGodot(readFileSync8(join9(projectPath, "project.godot"), "utf8"));
42969
43018
  const pluginsEnabled = enabledPlugins(settings);
42970
43019
  for (const name of EDITOR_PLUGINS) {
42971
43020
  if (!pluginsEnabled.includes(name)) {
@@ -42981,7 +43030,7 @@ function inspectProject(projectPath) {
42981
43030
  const tracked = trackedByGit(projectPath, [...named.values()]);
42982
43031
  const addonMissing = (path) => addons.some((addon) => !addon.installed && path.startsWith(`addons/${addon.name}/`));
42983
43032
  for (const [name, path] of named) {
42984
- if (!existsSync7(join8(projectPath, path))) {
43033
+ if (!existsSync7(join9(projectPath, path))) {
42985
43034
  if (!addonMissing(path)) {
42986
43035
  problems.push(`the ${name} autoload names res://${path}, which is not in this project, so it boots with a missing script; restore that file, or point the autoload at one that is here`);
42987
43036
  }
@@ -43014,8 +43063,8 @@ function inspectProject(projectPath) {
43014
43063
  // src/skill.ts
43015
43064
  init_setup();
43016
43065
  init_tool_definitions();
43017
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, readdirSync as readdirSync5, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
43018
- import { basename, dirname as dirname5, join as join10 } from "node:path";
43066
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync5, rmSync as rmSync6, writeFileSync as writeFileSync8 } from "node:fs";
43067
+ import { basename as basename2, dirname as dirname6, join as join11 } from "node:path";
43019
43068
 
43020
43069
  // src/tool-reference.ts
43021
43070
  init_headless_operations();
@@ -43111,7 +43160,7 @@ function renderToolsMarkdown() {
43111
43160
 
43112
43161
  // src/skill.ts
43113
43162
  var SKILL_NAME = "gdharness";
43114
- var SHARED_SKILLS = join10(".agents", "skills");
43163
+ var SHARED_SKILLS = join11(".agents", "skills");
43115
43164
  function skillMarkdown(version) {
43116
43165
  return `---
43117
43166
  name: ${SKILL_NAME}
@@ -43284,27 +43333,27 @@ whatever the engine said on stderr comes back under \`engine_messages\`.
43284
43333
  function skillFiles(version) {
43285
43334
  return new Map([
43286
43335
  ["SKILL.md", skillMarkdown(version)],
43287
- [join10("references", "tools.md"), renderToolsMarkdown()]
43336
+ [join11("references", "tools.md"), renderToolsMarkdown()]
43288
43337
  ]);
43289
43338
  }
43290
43339
  function skillDirectories(harnesses, projectPath, exists) {
43291
- const directories = [join10(projectPath, SHARED_SKILLS, SKILL_NAME)];
43340
+ const directories = [join11(projectPath, SHARED_SKILLS, SKILL_NAME)];
43292
43341
  for (const harness of harnesses) {
43293
43342
  if (harness.skills === undefined) {
43294
43343
  continue;
43295
43344
  }
43296
- const own = join10(projectPath, harness.skills.dir);
43297
- if ((!harness.skills.shared || exists(own)) && !directories.includes(join10(own, SKILL_NAME))) {
43298
- directories.push(join10(own, SKILL_NAME));
43345
+ const own = join11(projectPath, harness.skills.dir);
43346
+ if ((!harness.skills.shared || exists(own)) && !directories.includes(join11(own, SKILL_NAME))) {
43347
+ directories.push(join11(own, SKILL_NAME));
43299
43348
  }
43300
43349
  }
43301
43350
  return directories;
43302
43351
  }
43303
43352
  function everySkillDirectory(projectPath, harnesses) {
43304
- const directories = new Set([join10(projectPath, SHARED_SKILLS, SKILL_NAME)]);
43353
+ const directories = new Set([join11(projectPath, SHARED_SKILLS, SKILL_NAME)]);
43305
43354
  for (const harness of harnesses) {
43306
43355
  if (harness.skills !== undefined) {
43307
- directories.add(join10(projectPath, harness.skills.dir, SKILL_NAME));
43356
+ directories.add(join11(projectPath, harness.skills.dir, SKILL_NAME));
43308
43357
  }
43309
43358
  }
43310
43359
  return [...directories];
@@ -43313,51 +43362,51 @@ function removeSkill(directories, projectPath) {
43313
43362
  const removed = [];
43314
43363
  for (const directory of directories) {
43315
43364
  if (existsSync9(directory)) {
43316
- rmSync5(directory, { recursive: true, force: true });
43317
- pruneEmpty(dirname5(directory), projectPath);
43365
+ rmSync6(directory, { recursive: true, force: true });
43366
+ pruneEmpty(dirname6(directory), projectPath);
43318
43367
  removed.push(directory);
43319
43368
  }
43320
43369
  }
43321
43370
  return removed;
43322
43371
  }
43323
43372
  function pruneEmpty(directory, projectPath) {
43324
- const shared = join10(projectPath, ".agents");
43373
+ const shared = join11(projectPath, ".agents");
43325
43374
  let path = directory;
43326
- while (path !== projectPath && (basename(path) === "skills" || path === shared)) {
43375
+ while (path !== projectPath && (basename2(path) === "skills" || path === shared)) {
43327
43376
  if (readdirSync5(path).length > 0) {
43328
43377
  return;
43329
43378
  }
43330
- rmSync5(path, { recursive: true, force: true });
43331
- path = dirname5(path);
43379
+ rmSync6(path, { recursive: true, force: true });
43380
+ path = dirname6(path);
43332
43381
  }
43333
43382
  }
43334
43383
  function writeSkill(directories, version) {
43335
43384
  const files = skillFiles(version);
43336
43385
  return directories.map((directory) => {
43337
43386
  const replaced = existsSync9(directory);
43338
- rmSync5(directory, { recursive: true, force: true });
43387
+ rmSync6(directory, { recursive: true, force: true });
43339
43388
  for (const [name, contents] of files) {
43340
- const path = join10(directory, name);
43341
- mkdirSync5(dirname5(path), { recursive: true });
43342
- writeFileSync7(path, contents, "utf8");
43389
+ const path = join11(directory, name);
43390
+ mkdirSync6(dirname6(path), { recursive: true });
43391
+ writeFileSync8(path, contents, "utf8");
43343
43392
  }
43344
43393
  return { path: directory, replaced };
43345
43394
  });
43346
43395
  }
43347
43396
 
43348
43397
  // src/version.ts
43349
- import { readFileSync as readFileSync9 } from "node:fs";
43350
- import { dirname as dirname6, join as join11 } from "node:path";
43398
+ import { readFileSync as readFileSync10 } from "node:fs";
43399
+ import { dirname as dirname7, join as join12 } from "node:path";
43351
43400
  import { fileURLToPath as fileURLToPath3 } from "node:url";
43352
43401
  function getLocalVersion() {
43353
- const currentDirectory = dirname6(fileURLToPath3(import.meta.url));
43402
+ const currentDirectory = dirname7(fileURLToPath3(import.meta.url));
43354
43403
  const packageCandidates = [
43355
- join11(currentDirectory, "..", "package.json"),
43356
- join11(currentDirectory, "..", "..", "package.json")
43404
+ join12(currentDirectory, "..", "package.json"),
43405
+ join12(currentDirectory, "..", "..", "package.json")
43357
43406
  ];
43358
43407
  for (const packagePath of packageCandidates) {
43359
43408
  try {
43360
- const value = JSON.parse(readFileSync9(packagePath, "utf-8"));
43409
+ const value = JSON.parse(readFileSync10(packagePath, "utf-8"));
43361
43410
  if (typeof value === "object" && value !== null && "name" in value && value.name === "gdharness" && "version" in value && typeof value.version === "string") {
43362
43411
  return value.version;
43363
43412
  }
@@ -43370,12 +43419,12 @@ function getLocalVersion() {
43370
43419
  var args = process.argv.slice(2);
43371
43420
  var command = args[0];
43372
43421
 
43373
- class UsageError extends Refusal {
43422
+ class UsageError extends Refusal2 {
43374
43423
  }
43375
43424
  function projectArgument(at) {
43376
43425
  const named = args.slice(at).find((value) => !value.startsWith("--"));
43377
43426
  const projectPath = resolve5(named ?? ".");
43378
- if (!existsSync16(join23(projectPath, "project.godot"))) {
43427
+ if (!existsSync16(join24(projectPath, "project.godot"))) {
43379
43428
  throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
43380
43429
  }
43381
43430
  return projectPath;
@@ -43394,7 +43443,7 @@ async function engine(projectPath) {
43394
43443
  }
43395
43444
  function said2(outcome, what) {
43396
43445
  if (!outcome.ok) {
43397
- throw new Refusal(`${what}: ${outcome.message}`);
43446
+ throw new Refusal2(`${what}: ${outcome.message}`);
43398
43447
  }
43399
43448
  for (const entry of outcome.messages) {
43400
43449
  console.error(` engine ${entry.severity}: ${entry.text}`);
@@ -43414,7 +43463,7 @@ async function registerRuntime(godot, projectPath) {
43414
43463
  return;
43415
43464
  }
43416
43465
  console.log(`${RUNTIME_AUTOLOAD.name} autoload left at ${named}, which this project registers itself`);
43417
- if (!existsSync16(join23(projectPath, (named ?? "").replace(/^res:\/\//, "")))) {
43466
+ if (!existsSync16(join24(projectPath, (named ?? "").replace(/^res:\/\//, "")))) {
43418
43467
  console.log(` that file is not in this project, so it boots with a missing script: restore it, or point the entry at res://${RUNTIME_AUTOLOAD.path}`);
43419
43468
  }
43420
43469
  }
@@ -43649,7 +43698,8 @@ On ${version}. What is left for you:`);
43649
43698
  ` + ` so it gives an open editor nothing to restart for. editor_status says addonIsStale
43650
43699
  ` + " if the editor is older than that." : ` 1. The open editor is still running the addons it loaded at startup. Restart it with the
43651
43700
  ` + " editor_launch restart tool, which closes and reopens the window.");
43652
- console.log(harnessNote({ moved, written, byHand }, [launch.command, ...launch.args].join(" ")));
43701
+ const serving = serverServing(projectPath);
43702
+ console.log(harnessNote({ moved, written, byHand }, [launch.command, ...launch.args].join(" "), serving === null ? null : { server: serving, isThisVersion: serving.version === version }));
43653
43703
  }
43654
43704
  function doctorReport(projectPath) {
43655
43705
  const report = inspectProject(projectPath);
@@ -43809,7 +43859,7 @@ async function main() {
43809
43859
  }
43810
43860
  }
43811
43861
  await main().catch((error) => {
43812
- if (error instanceof Refusal) {
43862
+ if (error instanceof Refusal2) {
43813
43863
  console.error("gdharness:", error.message);
43814
43864
  process.exit(error instanceof UsageError ? 2 : 1);
43815
43865
  }