gdharness 1.1.13 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cli.js +742 -361
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +19 -1
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +8 -51
- package/build/godot/addons/gdharness_runtime/runtime_says.gd +97 -0
- package/build/godot/addons/gdharness_runtime/runtime_says.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +54 -12
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +4 -4
- package/build/index.js +623 -245
- package/build/keeper.js +111 -10
- package/package.json +1 -1
package/build/keeper.js
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// src/keeper.ts
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
-
import { closeSync, existsSync
|
|
6
|
-
import {
|
|
7
|
-
import { join as join3 } from "node:path";
|
|
5
|
+
import { closeSync, existsSync as existsSync2, openSync as openSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
6
|
+
import { join as join4 } from "node:path";
|
|
8
7
|
import { setTimeout as delay } from "node:timers/promises";
|
|
9
8
|
|
|
10
9
|
// src/desktop.ts
|
|
@@ -242,6 +241,7 @@ function readLaunched(printed) {
|
|
|
242
241
|
}
|
|
243
242
|
|
|
244
243
|
// src/run-record.ts
|
|
244
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
245
245
|
import { createHash as createHash2 } from "node:crypto";
|
|
246
246
|
import {
|
|
247
247
|
mkdirSync,
|
|
@@ -254,10 +254,33 @@ import {
|
|
|
254
254
|
writeFileSync
|
|
255
255
|
} from "node:fs";
|
|
256
256
|
import { basename, dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
|
|
257
|
+
import { promisify as promisify2 } from "node:util";
|
|
257
258
|
|
|
258
259
|
// src/process-children.ts
|
|
259
|
-
import { execFile
|
|
260
|
+
import { execFile } from "node:child_process";
|
|
260
261
|
import { promisify } from "node:util";
|
|
262
|
+
|
|
263
|
+
// src/windows-ask.ts
|
|
264
|
+
var SCRIPT = [
|
|
265
|
+
"[Console]::OutputEncoding = [Text.Encoding]::UTF8",
|
|
266
|
+
"$in = [Console]::In",
|
|
267
|
+
"while ($null -ne ($line = $in.ReadLine())) {",
|
|
268
|
+
' $parts = $line.Split(" ", 2)',
|
|
269
|
+
" try {",
|
|
270
|
+
" $asked = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($parts[1]))",
|
|
271
|
+
" $said = (& ([ScriptBlock]::Create($asked)) | Out-String -Width 1000000)",
|
|
272
|
+
' $tag = "OK"',
|
|
273
|
+
" } catch {",
|
|
274
|
+
" $said = $_.Exception.Message",
|
|
275
|
+
' $tag = "ERR"',
|
|
276
|
+
" }",
|
|
277
|
+
' [Console]::Out.Write($parts[0] + " " + $tag + " " + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($said)) + "`n")',
|
|
278
|
+
" [Console]::Out.Flush()",
|
|
279
|
+
"}"
|
|
280
|
+
].join(`
|
|
281
|
+
`);
|
|
282
|
+
|
|
283
|
+
// src/process-children.ts
|
|
261
284
|
var run = promisify(execFile);
|
|
262
285
|
|
|
263
286
|
// src/runtime-client.ts
|
|
@@ -285,6 +308,7 @@ var LATE_ANSWER_MS = 30 * 60000;
|
|
|
285
308
|
var lateAnswers = new Map;
|
|
286
309
|
|
|
287
310
|
// src/run-record.ts
|
|
311
|
+
var execFileAsync = promisify2(execFile2);
|
|
288
312
|
function runsDirectory() {
|
|
289
313
|
return join2(runtimeDirectory(), "runs");
|
|
290
314
|
}
|
|
@@ -361,6 +385,83 @@ function recordAt(path) {
|
|
|
361
385
|
};
|
|
362
386
|
}
|
|
363
387
|
|
|
388
|
+
// src/scratch.ts
|
|
389
|
+
import { existsSync, mkdtempSync, readdirSync as readdirSync2, rmSync as rmSync2 } from "node:fs";
|
|
390
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
391
|
+
import { join as join3 } from "node:path";
|
|
392
|
+
import process2 from "node:process";
|
|
393
|
+
var SWEPT = { recursive: true, force: true };
|
|
394
|
+
var AGAIN_AFTER_MS = [250, 500, 1000, 2000, 4000, 8000, 16000];
|
|
395
|
+
var waiting = new Set;
|
|
396
|
+
var atExit = new Set;
|
|
397
|
+
function scratchDirectory(kind) {
|
|
398
|
+
return mkdtempSync(join3(tmpdir2(), `gdharness-${kind}-${process2.pid}-`));
|
|
399
|
+
}
|
|
400
|
+
function discardWith(remove, paths) {
|
|
401
|
+
const left = [];
|
|
402
|
+
for (const path of paths) {
|
|
403
|
+
if (!path) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
try {
|
|
407
|
+
remove(path);
|
|
408
|
+
} catch (error) {
|
|
409
|
+
left.push({ path, reason: error instanceof Error ? error.message : String(error) });
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return left;
|
|
413
|
+
}
|
|
414
|
+
function discard(...paths) {
|
|
415
|
+
const left = discardWith(remove, paths);
|
|
416
|
+
for (const { path } of left) {
|
|
417
|
+
tryAgain(path, 0);
|
|
418
|
+
}
|
|
419
|
+
return left;
|
|
420
|
+
}
|
|
421
|
+
function remove(path) {
|
|
422
|
+
rmSync2(path, SWEPT);
|
|
423
|
+
}
|
|
424
|
+
function tryAgain(path, attempt) {
|
|
425
|
+
if (attempt === 0) {
|
|
426
|
+
if (waiting.has(path)) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
waiting.add(path);
|
|
430
|
+
atExit.delete(path);
|
|
431
|
+
lastTryOnExit();
|
|
432
|
+
}
|
|
433
|
+
const after = AGAIN_AFTER_MS[attempt];
|
|
434
|
+
if (after === undefined || !existsSync(path)) {
|
|
435
|
+
waiting.delete(path);
|
|
436
|
+
if (after === undefined) {
|
|
437
|
+
atExit.add(path);
|
|
438
|
+
}
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
setTimeout(() => {
|
|
442
|
+
try {
|
|
443
|
+
remove(path);
|
|
444
|
+
waiting.delete(path);
|
|
445
|
+
} catch {
|
|
446
|
+
tryAgain(path, attempt + 1);
|
|
447
|
+
}
|
|
448
|
+
}, after).unref();
|
|
449
|
+
}
|
|
450
|
+
var lastTryWatched = false;
|
|
451
|
+
function lastTryOnExit() {
|
|
452
|
+
if (lastTryWatched) {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
lastTryWatched = true;
|
|
456
|
+
process2.once("exit", () => {
|
|
457
|
+
for (const path of [...waiting, ...atExit]) {
|
|
458
|
+
try {
|
|
459
|
+
remove(path);
|
|
460
|
+
} catch {}
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
|
|
364
465
|
// src/keeper.ts
|
|
365
466
|
async function startDirectly(spec, output, hidden, detached = true, errors = output) {
|
|
366
467
|
return await new Promise((resolve) => {
|
|
@@ -379,9 +480,9 @@ async function startDirectly(spec, output, hidden, detached = true, errors = out
|
|
|
379
480
|
});
|
|
380
481
|
}
|
|
381
482
|
async function startThroughHelper(spec, output) {
|
|
382
|
-
const scratch =
|
|
383
|
-
const pidFile =
|
|
384
|
-
const errorFile =
|
|
483
|
+
const scratch = scratchDirectory("desktop");
|
|
484
|
+
const pidFile = join4(scratch, "pid");
|
|
485
|
+
const errorFile = join4(scratch, "error");
|
|
385
486
|
const where = spec.desktop === undefined ? "without activation" : `on the ${spec.desktop} desktop`;
|
|
386
487
|
try {
|
|
387
488
|
const wrapper = throughHelper(spec, spec.command, spec.args, pidFile, errorFile);
|
|
@@ -394,12 +495,12 @@ async function startThroughHelper(spec, output) {
|
|
|
394
495
|
exited.now = true;
|
|
395
496
|
});
|
|
396
497
|
for (let waited = 0;waited < DESKTOP_START_MS; waited += 50) {
|
|
397
|
-
const pid =
|
|
498
|
+
const pid = existsSync2(pidFile) ? Number(readFileSync2(pidFile, "utf8").trim()) : Number.NaN;
|
|
398
499
|
if (Number.isInteger(pid) && pid > 0) {
|
|
399
500
|
return { child: started.child, pid };
|
|
400
501
|
}
|
|
401
502
|
if (exited.now) {
|
|
402
|
-
const why =
|
|
503
|
+
const why = existsSync2(errorFile) ? readFileSync2(errorFile, "utf8").trim() : "it exited saying nothing";
|
|
403
504
|
return { error: `it could not be started ${where}: ${why}` };
|
|
404
505
|
}
|
|
405
506
|
await delay(50);
|
|
@@ -407,7 +508,7 @@ async function startThroughHelper(spec, output) {
|
|
|
407
508
|
started.child.kill();
|
|
408
509
|
return { error: `it was not started ${where} within ${DESKTOP_START_MS} ms` };
|
|
409
510
|
} finally {
|
|
410
|
-
|
|
511
|
+
discard(scratch);
|
|
411
512
|
}
|
|
412
513
|
}
|
|
413
514
|
var DESKTOP_START_MS = 60000;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
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",
|