gdharness 1.2.30 → 1.2.32

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 (37) hide show
  1. package/build/cli.js +7197 -6159
  2. package/build/godot/addons/gdharness_editor/bridge_client.gd +14 -0
  3. package/build/godot/addons/gdharness_editor/file_reads.gd +237 -0
  4. package/build/godot/addons/gdharness_editor/file_reads.gd.uid +1 -0
  5. package/build/godot/addons/gdharness_editor/plugin.gd +27 -0
  6. package/build/godot/addons/gdharness_editor/property_values.gd +80 -54
  7. package/build/godot/addons/gdharness_editor/scene_file.gd +38 -1
  8. package/build/godot/addons/gdharness_editor/serialisation.gd +46 -0
  9. package/build/godot/addons/gdharness_editor/tool_executor.gd +1 -0
  10. package/build/godot/addons/gdharness_editor/tools/class_tools.gd +22 -0
  11. package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +64 -1
  12. package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +82 -44
  13. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +178 -0
  14. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd.uid +1 -0
  15. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +73 -124
  16. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +39 -0
  17. package/build/godot/addons/gdharness_runtime/runtime_hover.gd +285 -0
  18. package/build/godot/addons/gdharness_runtime/runtime_hover.gd.uid +1 -0
  19. package/build/godot/addons/gdharness_runtime/runtime_input.gd +151 -106
  20. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +112 -0
  21. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd.uid +1 -0
  22. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +5 -4
  23. package/build/godot/addons/gdharness_runtime/runtime_values.gd +1 -47
  24. package/build/godot/addons/gdharness_runtime/serialisation.gd +46 -0
  25. package/build/godot/operations/audio_buses.gd +14 -1
  26. package/build/godot/operations/class_cache.gd +146 -35
  27. package/build/godot/operations/classdb_queries.gd +19 -12
  28. package/build/godot/operations/file_reads.gd +237 -0
  29. package/build/godot/operations/gdscript_authoring.gd +136 -19
  30. package/build/godot/operations/godot_operations.gd +24 -0
  31. package/build/godot/operations/project_config.gd +16 -6
  32. package/build/godot/operations/property_values.gd +767 -0
  33. package/build/godot/operations/rename_checks.gd +5 -2
  34. package/build/godot/operations/serialisation.gd +46 -0
  35. package/build/index.js +4896 -3872
  36. package/build/keeper.js +184 -71
  37. package/package.json +1 -1
package/build/keeper.js CHANGED
@@ -1,14 +1,57 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/keeper.ts
4
- import { closeSync, existsSync as existsSync2, mkdtempSync as mkdtempSync3, openSync as openSync2, readFileSync as readFileSync2, rmSync as rmSync5, writeFileSync as writeFileSync3 } from "node:fs";
5
- import { tmpdir as tmpdir4 } from "node:os";
6
- import { join as join5 } from "node:path";
7
- import { setTimeout as delay } from "node:timers/promises";
4
+ import { closeSync as closeSync2, existsSync as existsSync3, mkdtempSync as mkdtempSync4, openSync as openSync3, readFileSync as readFileSync3, rmSync as rmSync6, writeFileSync as writeFileSync3 } from "node:fs";
5
+ import { tmpdir as tmpdir5 } from "node:os";
6
+ import { join as join6 } from "node:path";
7
+ import { setTimeout as delay2 } from "node:timers/promises";
8
8
 
9
9
  // src/desktop.ts
10
10
  import { createHash } from "node:crypto";
11
- import { writeFileSync } from "node:fs";
11
+ import {
12
+ closeSync,
13
+ existsSync,
14
+ mkdtempSync,
15
+ openSync,
16
+ readFileSync,
17
+ rmSync,
18
+ statSync,
19
+ writeFileSync,
20
+ writeSync
21
+ } from "node:fs";
22
+ import { tmpdir } from "node:os";
23
+ import { join } from "node:path";
24
+ import { setTimeout as delay } from "node:timers/promises";
25
+
26
+ // src/alive.ts
27
+ import process2 from "node:process";
28
+ function alive(pid) {
29
+ if (pid === undefined || pid === null) {
30
+ return false;
31
+ }
32
+ try {
33
+ process2.kill(pid, 0);
34
+ return true;
35
+ } catch (error) {
36
+ return error.code === "EPERM";
37
+ }
38
+ }
39
+
40
+ // src/spawn.ts
41
+ import {
42
+ execFile,
43
+ execFileSync,
44
+ spawn,
45
+ spawnSync
46
+ } from "node:child_process";
47
+ function spawnHidden(command, args, options = {}) {
48
+ return spawn(command, [...args], { ...options, windowsHide: true });
49
+ }
50
+ function spawnShown(command, args, options = {}) {
51
+ return spawn(command, [...args], { ...options, windowsHide: false });
52
+ }
53
+
54
+ // src/desktop.ts
12
55
  var DESKTOP_VARIABLE = "GDHARNESS_DESKTOP";
13
56
  var SOURCE = `using System;
14
57
  using System.ComponentModel;
@@ -161,6 +204,95 @@ public static class GdharnessDesktop {
161
204
  }
162
205
  }
163
206
  `;
207
+ var DIGEST = createHash("sha256").update(SOURCE).digest("hex").slice(0, 16);
208
+ var HELPER_COMPILE_MS = 180000;
209
+ function helperAssembly(directory = tmpdir()) {
210
+ return join(directory, `gdharness-desktop-${DIGEST}.dll`);
211
+ }
212
+ async function ensureHelperCompiled(directory = tmpdir(), budgetMs = HELPER_COMPILE_MS, wait = true) {
213
+ const assembly = helperAssembly(directory);
214
+ const lock = `${assembly}.compiling`;
215
+ const until = Date.now() + budgetMs;
216
+ while (Date.now() < until) {
217
+ if (existsSync(assembly)) {
218
+ return null;
219
+ }
220
+ let mine = false;
221
+ try {
222
+ const held = openSync(lock, "wx");
223
+ writeSync(held, String(process.pid));
224
+ closeSync(held);
225
+ mine = true;
226
+ } catch {}
227
+ if (mine) {
228
+ try {
229
+ return await compileHelper(directory, assembly, until - Date.now());
230
+ } finally {
231
+ rmSync(lock, { force: true });
232
+ }
233
+ }
234
+ try {
235
+ const holder = Number(readFileSync(lock, "utf8").trim());
236
+ const old = Date.now() - statSync(lock).mtimeMs > budgetMs;
237
+ if (old || Number.isInteger(holder) && holder > 0 && !alive(holder)) {
238
+ rmSync(lock, { force: true });
239
+ continue;
240
+ }
241
+ } catch {}
242
+ if (!wait) {
243
+ return null;
244
+ }
245
+ await delay(200);
246
+ }
247
+ return `the desktop helper was not compiled within ${String(budgetMs)} ms`;
248
+ }
249
+ async function compileHelper(directory, assembly, budgetMs) {
250
+ const scratch = mkdtempSync(join(directory, "gdharness-desktop-source-"));
251
+ const source = join(scratch, "helper.cs");
252
+ writeFileSync(source, SOURCE, "utf8");
253
+ const literal = (path) => `'${path.replaceAll("'", "''")}'`;
254
+ const script = [
255
+ "$ErrorActionPreference = 'Stop'",
256
+ "try {",
257
+ ` $partial = ${literal(assembly)} + '.' + $PID`,
258
+ ` Add-Type -TypeDefinition ([IO.File]::ReadAllText(${literal(source)}, [Text.Encoding]::UTF8)) -OutputAssembly $partial`,
259
+ ` Move-Item -LiteralPath $partial -Destination ${literal(assembly)}`,
260
+ "} catch {",
261
+ " [Console]::Error.WriteLine($_.Exception.Message)",
262
+ " exit 1",
263
+ "}"
264
+ ].join(`
265
+ `);
266
+ try {
267
+ return await new Promise((resolve) => {
268
+ const compiler = spawnHidden("powershell.exe", [
269
+ "-NoProfile",
270
+ "-NonInteractive",
271
+ "-ExecutionPolicy",
272
+ "Bypass",
273
+ "-EncodedCommand",
274
+ Buffer.from(script, "utf16le").toString("base64")
275
+ ], { stdio: ["ignore", "ignore", "pipe"] });
276
+ let complained = "";
277
+ compiler.stderr.on("data", (chunk) => {
278
+ complained += chunk.toString();
279
+ });
280
+ const timer = setTimeout(() => {
281
+ compiler.kill();
282
+ }, budgetMs);
283
+ compiler.once("error", (error) => {
284
+ clearTimeout(timer);
285
+ resolve(`Windows PowerShell did not start: ${error.message}`);
286
+ });
287
+ compiler.once("close", (code) => {
288
+ clearTimeout(timer);
289
+ resolve(existsSync(assembly) ? null : `Windows PowerShell could not compile it${code === null ? " in time" : ""}: ${complained.trim() || `exit code ${String(code)}`}`);
290
+ });
291
+ });
292
+ } finally {
293
+ rmSync(scratch, { recursive: true, force: true });
294
+ }
295
+ }
164
296
  function quoted(argument) {
165
297
  if (argument !== "" && !/[\s"]/.test(argument)) {
166
298
  return argument;
@@ -180,7 +312,7 @@ function quoted(argument) {
180
312
  function windowsCommandLine(command, args) {
181
313
  return [command, ...args].map(quoted).join(" ");
182
314
  }
183
- function throughHelper(how, command, args, files) {
315
+ function throughHelper(how, command, args, files, assembly = helperAssembly()) {
184
316
  const spec = {
185
317
  desktop: how.desktop ?? "",
186
318
  noActivate: how.noActivate === true,
@@ -188,8 +320,7 @@ function throughHelper(how, command, args, files) {
188
320
  pidFile: files.pid,
189
321
  stopFile: files.stop,
190
322
  directory: how.directory,
191
- source: SOURCE,
192
- digest: createHash("sha256").update(SOURCE).digest("hex").slice(0, 16)
323
+ assembly
193
324
  };
194
325
  writeFileSync(files.spec, JSON.stringify(spec), "utf8");
195
326
  const literal = (path) => `'${path.replaceAll("'", "''")}'`;
@@ -197,13 +328,7 @@ function throughHelper(how, command, args, files) {
197
328
  "$ErrorActionPreference = 'Stop'",
198
329
  "try {",
199
330
  ` $spec = [IO.File]::ReadAllText(${literal(files.spec)}, [Text.Encoding]::UTF8) | ConvertFrom-Json`,
200
- " $assembly = Join-Path ([IO.Path]::GetTempPath()) ('gdharness-desktop-' + $spec.digest + '.dll')",
201
- " if (-not (Test-Path -LiteralPath $assembly)) {",
202
- ' $partial = "$assembly.$PID"',
203
- " Add-Type -TypeDefinition $spec.source -OutputAssembly $partial",
204
- " try { Move-Item -LiteralPath $partial -Destination $assembly } catch { Remove-Item -LiteralPath $partial -ErrorAction SilentlyContinue }",
205
- " }",
206
- " Add-Type -LiteralPath $assembly",
331
+ " Add-Type -LiteralPath $spec.assembly",
207
332
  " $code = [GdharnessDesktop]::Run($spec.desktop, $spec.commandLine, $spec.pidFile, [bool]$spec.noActivate, $spec.stopFile, $spec.directory)",
208
333
  "} catch {",
209
334
  ` [IO.File]::WriteAllText(${literal(files.error)}, $_.Exception.Message)`,
@@ -1003,11 +1128,11 @@ class GameDebugger {
1003
1128
 
1004
1129
  // src/keeper-channel.ts
1005
1130
  import { randomUUID } from "node:crypto";
1006
- import { mkdtempSync, rmSync } from "node:fs";
1131
+ import { mkdtempSync as mkdtempSync2, rmSync as rmSync2 } from "node:fs";
1007
1132
  import { connect, createServer as createServer2 } from "node:net";
1008
- import { tmpdir } from "node:os";
1009
- import { join } from "node:path";
1010
- import process2 from "node:process";
1133
+ import { tmpdir as tmpdir2 } from "node:os";
1134
+ import { join as join2 } from "node:path";
1135
+ import process3 from "node:process";
1011
1136
  var DEBUG_PREFIX = "debug ";
1012
1137
  function endedOrWhyNot(end) {
1013
1138
  try {
@@ -1034,8 +1159,8 @@ function errorText(error) {
1034
1159
  async function listenForTheServer(end, debug) {
1035
1160
  let directory = null;
1036
1161
  try {
1037
- directory = process2.platform === "win32" ? null : mkdtempSync(join(tmpdir(), "gdharness-keeper-"));
1038
- const address = directory === null ? `\\\\.\\pipe\\gdharness-keeper-${randomUUID()}` : join(directory, "keeper.sock");
1162
+ directory = process3.platform === "win32" ? null : mkdtempSync2(join2(tmpdir2(), "gdharness-keeper-"));
1163
+ const address = directory === null ? `\\\\.\\pipe\\gdharness-keeper-${randomUUID()}` : join2(directory, "keeper.sock");
1039
1164
  const server = createServer2((socket) => {
1040
1165
  socket.setEncoding("utf8");
1041
1166
  socket.on("error", () => {});
@@ -1071,13 +1196,13 @@ async function listenForTheServer(end, debug) {
1071
1196
  close: () => {
1072
1197
  server.close();
1073
1198
  if (made !== null) {
1074
- rmSync(made, { recursive: true, force: true });
1199
+ rmSync2(made, { recursive: true, force: true });
1075
1200
  }
1076
1201
  }
1077
1202
  };
1078
1203
  } catch {
1079
1204
  if (directory !== null) {
1080
- rmSync(directory, { recursive: true, force: true });
1205
+ rmSync2(directory, { recursive: true, force: true });
1081
1206
  }
1082
1207
  return null;
1083
1208
  }
@@ -1094,22 +1219,6 @@ function listening(server, address) {
1094
1219
 
1095
1220
  // src/outside.ts
1096
1221
  import { fileURLToPath } from "node:url";
1097
-
1098
- // src/spawn.ts
1099
- import {
1100
- execFile,
1101
- execFileSync,
1102
- spawn,
1103
- spawnSync
1104
- } from "node:child_process";
1105
- function spawnHidden(command, args, options = {}) {
1106
- return spawn(command, [...args], { ...options, windowsHide: true });
1107
- }
1108
- function spawnShown(command, args, options = {}) {
1109
- return spawn(command, [...args], { ...options, windowsHide: false });
1110
- }
1111
-
1112
- // src/outside.ts
1113
1222
  function withChanges(base, changes) {
1114
1223
  const env = { ...base };
1115
1224
  for (const [name, value] of Object.entries(changes)) {
@@ -1144,8 +1253,8 @@ function readLaunched(printed) {
1144
1253
 
1145
1254
  // src/run-record.ts
1146
1255
  import { createHash as createHash2 } from "node:crypto";
1147
- import { mkdirSync, openSync, readdirSync, readFileSync, realpathSync, rmSync as rmSync3, statSync } from "node:fs";
1148
- import { basename, dirname as dirname2, join as join3, resolve as resolve2 } from "node:path";
1256
+ import { mkdirSync, openSync as openSync2, readdirSync, readFileSync as readFileSync2, realpathSync, rmSync as rmSync4, statSync as statSync2 } from "node:fs";
1257
+ import { basename, dirname as dirname2, join as join4, resolve as resolve2 } from "node:path";
1149
1258
 
1150
1259
  // src/windows-ask.ts
1151
1260
  var SCRIPT = [
@@ -1168,8 +1277,8 @@ var SCRIPT = [
1168
1277
  `);
1169
1278
 
1170
1279
  // src/runtime-client.ts
1171
- import { tmpdir as tmpdir2 } from "node:os";
1172
- import { dirname, join as join2, resolve } from "node:path";
1280
+ import { tmpdir as tmpdir3 } from "node:os";
1281
+ import { dirname, join as join3, resolve } from "node:path";
1173
1282
 
1174
1283
  // src/launch.ts
1175
1284
  function envValue(name, variables = process.env) {
@@ -1214,7 +1323,7 @@ function runtimeDirectory(variables = process.env) {
1214
1323
  return explicit;
1215
1324
  }
1216
1325
  const perUser = envValue("XDG_RUNTIME_DIR", variables);
1217
- return join2(perUser ?? tmpdir2(), "gdharness");
1326
+ return join3(perUser ?? tmpdir3(), "gdharness");
1218
1327
  }
1219
1328
  var ERROR_REPORT_KEEP_MS = 60 * 60 * 1000;
1220
1329
  var verdicts = new Map;
@@ -1222,7 +1331,7 @@ var LATE_ANSWER_MS = 30 * 60000;
1222
1331
  var lateAnswers = new Map;
1223
1332
 
1224
1333
  // src/whole-file.ts
1225
- import { renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
1334
+ import { renameSync, rmSync as rmSync3, writeFileSync as writeFileSync2 } from "node:fs";
1226
1335
  var HELD_FILE_MS = 1000;
1227
1336
  var HELD_FILE_RETRY_MS = 10;
1228
1337
  var HELD_BY_A_READER = new Set(["EPERM", "EACCES", "EBUSY"]);
@@ -1242,7 +1351,7 @@ function writeWhole(path, text) {
1242
1351
  const code = error.code ?? "";
1243
1352
  if (!HELD_BY_A_READER.has(code) || Date.now() >= until) {
1244
1353
  try {
1245
- rmSync2(partial, { force: true });
1354
+ rmSync3(partial, { force: true });
1246
1355
  } catch {}
1247
1356
  return false;
1248
1357
  }
@@ -1253,14 +1362,14 @@ function writeWhole(path, text) {
1253
1362
 
1254
1363
  // src/run-record.ts
1255
1364
  function runsDirectory() {
1256
- return join3(runtimeDirectory(), "runs");
1365
+ return join4(runtimeDirectory(), "runs");
1257
1366
  }
1258
1367
  function realAsFarAsItExists(path) {
1259
1368
  const missing = [];
1260
1369
  let at = path;
1261
1370
  for (;; ) {
1262
1371
  try {
1263
- return join3(realpathSync.native(at), ...missing);
1372
+ return join4(realpathSync.native(at), ...missing);
1264
1373
  } catch {
1265
1374
  const parent = dirname2(at);
1266
1375
  if (parent === at) {
@@ -1277,7 +1386,7 @@ function projectKey(projectPath) {
1277
1386
  return createHash2("sha256").update(folded.replaceAll("\\", "/")).digest("hex").slice(0, 16);
1278
1387
  }
1279
1388
  function runRecordPath(projectPath, directory = runtimeDirectory()) {
1280
- return join3(directory, "runs", `note-${projectKey(projectPath)}.json`);
1389
+ return join4(directory, "runs", `note-${projectKey(projectPath)}.json`);
1281
1390
  }
1282
1391
  function writeRunRecord(record) {
1283
1392
  mkdirSync(runsDirectory(), { recursive: true });
@@ -1303,7 +1412,7 @@ function recordRunEnded(projectPath, pid, ending) {
1303
1412
  function recordAt(path) {
1304
1413
  let parsed;
1305
1414
  try {
1306
- parsed = JSON.parse(readFileSync(path, "utf8"));
1415
+ parsed = JSON.parse(readFileSync2(path, "utf8"));
1307
1416
  } catch {
1308
1417
  return null;
1309
1418
  }
@@ -1336,16 +1445,16 @@ function recordAt(path) {
1336
1445
  }
1337
1446
 
1338
1447
  // src/scratch.ts
1339
- import { existsSync, mkdtempSync as mkdtempSync2, readdirSync as readdirSync2, rmSync as rmSync4 } from "node:fs";
1340
- import { tmpdir as tmpdir3 } from "node:os";
1341
- import { join as join4 } from "node:path";
1342
- import process3 from "node:process";
1448
+ import { existsSync as existsSync2, mkdtempSync as mkdtempSync3, readdirSync as readdirSync2, rmSync as rmSync5 } from "node:fs";
1449
+ import { tmpdir as tmpdir4 } from "node:os";
1450
+ import { join as join5 } from "node:path";
1451
+ import process4 from "node:process";
1343
1452
  var SWEPT = { recursive: true, force: true };
1344
1453
  var AGAIN_AFTER_MS = [250, 500, 1000, 2000, 4000, 8000, 16000];
1345
1454
  var waiting = new Set;
1346
1455
  var atExit = new Set;
1347
1456
  function scratchDirectory(kind) {
1348
- return mkdtempSync2(join4(tmpdir3(), `gdharness-${kind}-${process3.pid}-`));
1457
+ return mkdtempSync3(join5(tmpdir4(), `gdharness-${kind}-${process4.pid}-`));
1349
1458
  }
1350
1459
  function discardWith(remove, paths) {
1351
1460
  const left = [];
@@ -1369,7 +1478,7 @@ function discard(...paths) {
1369
1478
  return left;
1370
1479
  }
1371
1480
  function remove(path) {
1372
- rmSync4(path, SWEPT);
1481
+ rmSync5(path, SWEPT);
1373
1482
  }
1374
1483
  function tryAgain(path, attempt) {
1375
1484
  if (attempt === 0) {
@@ -1381,7 +1490,7 @@ function tryAgain(path, attempt) {
1381
1490
  lastTryOnExit();
1382
1491
  }
1383
1492
  const after = AGAIN_AFTER_MS[attempt];
1384
- if (after === undefined || !existsSync(path)) {
1493
+ if (after === undefined || !existsSync2(path)) {
1385
1494
  waiting.delete(path);
1386
1495
  if (after === undefined) {
1387
1496
  atExit.add(path);
@@ -1403,7 +1512,7 @@ function lastTryOnExit() {
1403
1512
  return;
1404
1513
  }
1405
1514
  lastTryWatched = true;
1406
- process3.once("exit", () => {
1515
+ process4.once("exit", () => {
1407
1516
  for (const path of [...waiting, ...atExit]) {
1408
1517
  try {
1409
1518
  remove(path);
@@ -1805,18 +1914,22 @@ async function startDirectly(spec, output, hidden, detached = true, errors = out
1805
1914
  }
1806
1915
  async function startThroughHelper(spec, output, stopFile) {
1807
1916
  const scratch = scratchDirectory("desktop");
1808
- const pidFile = join5(scratch, "pid");
1809
- const errorFile = join5(scratch, "error");
1917
+ const pidFile = join6(scratch, "pid");
1918
+ const errorFile = join6(scratch, "error");
1810
1919
  const where = spec.desktop === undefined ? "without activation" : `on the ${spec.desktop} desktop`;
1811
1920
  try {
1921
+ const compiled = await ensureHelperCompiled();
1922
+ if (compiled !== null) {
1923
+ return { error: `it could not be started ${where}: ${compiled}` };
1924
+ }
1812
1925
  const wrapper = throughHelper({ ...spec, directory: process.cwd() }, spec.command, spec.args, {
1813
- spec: join5(scratch, "spec.json"),
1926
+ spec: join6(scratch, "spec.json"),
1814
1927
  pid: pidFile,
1815
1928
  error: errorFile,
1816
1929
  stop: stopFile
1817
1930
  });
1818
1931
  const envChanges = spec.desktop === undefined ? spec.envChanges : { ...spec.envChanges, [DESKTOP_VARIABLE]: spec.desktop };
1819
- const started = await startDirectly({ ...spec, command: wrapper.command, args: wrapper.args, envChanges }, output, true, false, "ignore", tmpdir4());
1932
+ const started = await startDirectly({ ...spec, command: wrapper.command, args: wrapper.args, envChanges }, output, true, false, "ignore", tmpdir5());
1820
1933
  if ("error" in started) {
1821
1934
  return started;
1822
1935
  }
@@ -1825,15 +1938,15 @@ async function startThroughHelper(spec, output, stopFile) {
1825
1938
  exited.now = true;
1826
1939
  });
1827
1940
  for (let waited = 0;waited < DESKTOP_START_MS; waited += 50) {
1828
- const pid = existsSync2(pidFile) ? Number(readFileSync2(pidFile, "utf8").trim()) : Number.NaN;
1941
+ const pid = existsSync3(pidFile) ? Number(readFileSync3(pidFile, "utf8").trim()) : Number.NaN;
1829
1942
  if (Number.isInteger(pid) && pid > 0) {
1830
1943
  return { child: started.child, pid };
1831
1944
  }
1832
1945
  if (exited.now) {
1833
- const why = existsSync2(errorFile) ? readFileSync2(errorFile, "utf8").trim() : "it exited saying nothing";
1946
+ const why = existsSync3(errorFile) ? readFileSync3(errorFile, "utf8").trim() : "it exited saying nothing";
1834
1947
  return { error: `it could not be started ${where}: ${why}` };
1835
1948
  }
1836
- await delay(50);
1949
+ await delay2(50);
1837
1950
  }
1838
1951
  started.child.kill();
1839
1952
  return { error: `it was not started ${where} within ${DESKTOP_START_MS} ms` };
@@ -1854,7 +1967,7 @@ function profiledBy(path, projectPath) {
1854
1967
  };
1855
1968
  let projectGodot = null;
1856
1969
  try {
1857
- projectGodot = readFileSync2(join5(projectPath, "project.godot"), "utf8");
1970
+ projectGodot = readFileSync3(join6(projectPath, "project.godot"), "utf8");
1858
1971
  } catch {}
1859
1972
  const observer = new ProfileObserver((totals) => {
1860
1973
  const first = latest === null;
@@ -1956,15 +2069,15 @@ async function keep() {
1956
2069
  const profiled = run?.profile === undefined ? null : profiledBy(run.profile, run.projectPath);
1957
2070
  const debuggerPeer = run === undefined || run.debugged === false ? null : await GameDebugger.open(run.breakpoints ?? [], profiled === null ? [] : [profiled.observer]);
1958
2071
  const toStart = debuggerPeer === null ? spec : { ...spec, args: withEngineArguments(spec.args, debuggerPeer.engineArguments) };
1959
- const transcript = run === undefined ? "ignore" : openSync2(run.transcript, "a");
1960
- const own = run !== undefined && throughTheHelper(spec) ? mkdtempSync3(join5(tmpdir4(), "gdharness-stop-")) : null;
1961
- const stopFile = own === null ? "" : join5(own, "stop");
2072
+ const transcript = run === undefined ? "ignore" : openSync3(run.transcript, "a");
2073
+ const own = run !== undefined && throughTheHelper(spec) ? mkdtempSync4(join6(tmpdir5(), "gdharness-stop-")) : null;
2074
+ const stopFile = own === null ? "" : join6(own, "stop");
1962
2075
  let started;
1963
2076
  try {
1964
2077
  started = await startDetached(toStart, transcript, run === undefined, stopFile);
1965
2078
  } finally {
1966
2079
  if (transcript !== "ignore") {
1967
- closeSync(transcript);
2080
+ closeSync2(transcript);
1968
2081
  }
1969
2082
  }
1970
2083
  if ("error" in started) {
@@ -1998,7 +2111,7 @@ async function keep() {
1998
2111
  debuggerPeer?.close();
1999
2112
  listening?.close();
2000
2113
  if (own !== null) {
2001
- rmSync5(own, { recursive: true, force: true });
2114
+ rmSync6(own, { recursive: true, force: true });
2002
2115
  }
2003
2116
  process.exit(0);
2004
2117
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "1.2.30",
3
+ "version": "1.2.32",
4
4
  "mcpName": "io.github.Aureliolo/gdharness",
5
5
  "description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
6
6
  "type": "module",