gdharness 0.13.10 → 0.13.12
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 +64 -34
- package/build/index.js +45 -19
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -7281,6 +7281,32 @@ var init_game_log = __esm(() => {
|
|
|
7281
7281
|
STREAMS = ["stdout", "stderr", "transcript"];
|
|
7282
7282
|
});
|
|
7283
7283
|
|
|
7284
|
+
// src/scratch.ts
|
|
7285
|
+
import { rmSync as rmSync2 } from "node:fs";
|
|
7286
|
+
function discardWith(remove, paths) {
|
|
7287
|
+
const left = [];
|
|
7288
|
+
for (const path of paths) {
|
|
7289
|
+
if (!path) {
|
|
7290
|
+
continue;
|
|
7291
|
+
}
|
|
7292
|
+
try {
|
|
7293
|
+
remove(path);
|
|
7294
|
+
} catch (error) {
|
|
7295
|
+
left.push({ path, reason: error instanceof Error ? error.message : String(error) });
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
return left;
|
|
7299
|
+
}
|
|
7300
|
+
function discard(...paths) {
|
|
7301
|
+
return discardWith((path) => {
|
|
7302
|
+
rmSync2(path, SWEPT);
|
|
7303
|
+
}, paths);
|
|
7304
|
+
}
|
|
7305
|
+
var SWEPT;
|
|
7306
|
+
var init_scratch = __esm(() => {
|
|
7307
|
+
SWEPT = { recursive: true, force: true, maxRetries: 20, retryDelay: 250 };
|
|
7308
|
+
});
|
|
7309
|
+
|
|
7284
7310
|
// src/update-check.ts
|
|
7285
7311
|
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
7286
7312
|
import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
|
|
@@ -7554,7 +7580,7 @@ var init_class_cache = () => {};
|
|
|
7554
7580
|
|
|
7555
7581
|
// src/headless.ts
|
|
7556
7582
|
import { execFile as execFile3 } from "node:child_process";
|
|
7557
|
-
import { mkdtempSync as mkdtempSync2,
|
|
7583
|
+
import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
7558
7584
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
7559
7585
|
import { join as join7 } from "node:path";
|
|
7560
7586
|
import { promisify as promisify3 } from "node:util";
|
|
@@ -7630,7 +7656,7 @@ async function runOperation2(engine, operation, params, projectPath) {
|
|
|
7630
7656
|
messages: []
|
|
7631
7657
|
};
|
|
7632
7658
|
} finally {
|
|
7633
|
-
|
|
7659
|
+
discard(paramsDir);
|
|
7634
7660
|
}
|
|
7635
7661
|
const payload = lastJsonObject2(stdout);
|
|
7636
7662
|
if (payload === null) {
|
|
@@ -7645,6 +7671,7 @@ async function runOperation2(engine, operation, params, projectPath) {
|
|
|
7645
7671
|
var run3;
|
|
7646
7672
|
var init_headless = __esm(() => {
|
|
7647
7673
|
init_game_log();
|
|
7674
|
+
init_scratch();
|
|
7648
7675
|
run3 = promisify3(execFile3);
|
|
7649
7676
|
});
|
|
7650
7677
|
|
|
@@ -14897,10 +14924,10 @@ function isValueComplete(value) {
|
|
|
14897
14924
|
return depth <= 0 && !inString;
|
|
14898
14925
|
}
|
|
14899
14926
|
function settingKeys(content) {
|
|
14900
|
-
const named = new
|
|
14927
|
+
const named = new Map;
|
|
14901
14928
|
for (const [section, entries] of Object.entries(parseProjectGodot(content))) {
|
|
14902
|
-
for (const key of Object.
|
|
14903
|
-
named.
|
|
14929
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
14930
|
+
named.set(`${section}/${key}`, value);
|
|
14904
14931
|
}
|
|
14905
14932
|
}
|
|
14906
14933
|
return named;
|
|
@@ -15787,7 +15814,10 @@ var init_tool_definitions = __esm(() => {
|
|
|
15787
15814
|
summary: "run the project until it quits or is stopped",
|
|
15788
15815
|
requires: ["projectPath"]
|
|
15789
15816
|
},
|
|
15790
|
-
stop: {
|
|
15817
|
+
stop: {
|
|
15818
|
+
summary: "end the run and answer with what it printed last, naming the process ended under endedPid: a game that started processes of its own keeps them",
|
|
15819
|
+
requires: []
|
|
15820
|
+
},
|
|
15791
15821
|
check: {
|
|
15792
15822
|
summary: "boot headless, quit after a few frames, and report the verdict",
|
|
15793
15823
|
requires: ["projectPath"]
|
|
@@ -30943,7 +30973,7 @@ var init_stdio2 = __esm(() => {
|
|
|
30943
30973
|
});
|
|
30944
30974
|
|
|
30945
30975
|
// src/bridge-announce.ts
|
|
30946
|
-
import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, rmSync as
|
|
30976
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
30947
30977
|
import { dirname as dirname6, join as join11 } from "node:path";
|
|
30948
30978
|
function announcementPath(projectPath) {
|
|
30949
30979
|
return join11(projectPath, ".godot", "gdharness-bridge.json");
|
|
@@ -30991,7 +31021,7 @@ function withdrawBridge(path) {
|
|
|
30991
31021
|
return;
|
|
30992
31022
|
}
|
|
30993
31023
|
try {
|
|
30994
|
-
|
|
31024
|
+
rmSync5(path, { force: true });
|
|
30995
31025
|
} catch (error) {
|
|
30996
31026
|
console.error(`[SERVER] Could not withdraw the editor bridge announcement: ${errorMessage(error)}`);
|
|
30997
31027
|
}
|
|
@@ -36327,7 +36357,7 @@ var init_runtime_client = __esm(() => {
|
|
|
36327
36357
|
|
|
36328
36358
|
// src/run-record.ts
|
|
36329
36359
|
import { execFileSync } from "node:child_process";
|
|
36330
|
-
import { mkdirSync as mkdirSync6, openSync, readdirSync as readdirSync6, readFileSync as readFileSync13, rmSync as
|
|
36360
|
+
import { mkdirSync as mkdirSync6, openSync, readdirSync as readdirSync6, readFileSync as readFileSync13, rmSync as rmSync6, statSync as statSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
36331
36361
|
import { basename as basename2, join as join15 } from "node:path";
|
|
36332
36362
|
function runsDirectory() {
|
|
36333
36363
|
return join15(runtimeDirectory(), "runs");
|
|
@@ -36537,7 +36567,7 @@ function clearRunRecord(ours = () => true) {
|
|
|
36537
36567
|
continue;
|
|
36538
36568
|
}
|
|
36539
36569
|
try {
|
|
36540
|
-
|
|
36570
|
+
rmSync6(path);
|
|
36541
36571
|
} catch {}
|
|
36542
36572
|
}
|
|
36543
36573
|
}
|
|
@@ -36566,7 +36596,7 @@ function sweepTranscripts(keepMs = 24 * 60 * 60 * 1000, now = Date.now()) {
|
|
|
36566
36596
|
continue;
|
|
36567
36597
|
}
|
|
36568
36598
|
try {
|
|
36569
|
-
|
|
36599
|
+
rmSync6(path);
|
|
36570
36600
|
} catch {}
|
|
36571
36601
|
}
|
|
36572
36602
|
}
|
|
@@ -36575,7 +36605,7 @@ var init_run_record = __esm(() => {
|
|
|
36575
36605
|
});
|
|
36576
36606
|
|
|
36577
36607
|
// src/setup.ts
|
|
36578
|
-
import { cpSync as cpSync2, existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync14, rmSync as
|
|
36608
|
+
import { cpSync as cpSync2, existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync14, rmSync as rmSync7, writeFileSync as writeFileSync9 } from "node:fs";
|
|
36579
36609
|
import { dirname as dirname8, join as join16 } from "node:path";
|
|
36580
36610
|
function installedAddonVersion(projectPath) {
|
|
36581
36611
|
const marker = join16(projectPath, "addons", ADDONS2[0], VERSION_MARKER2);
|
|
@@ -36611,8 +36641,7 @@ import {
|
|
|
36611
36641
|
openSync as openSync2,
|
|
36612
36642
|
readdirSync as readdirSync7,
|
|
36613
36643
|
readFileSync as readFileSync15,
|
|
36614
|
-
readSync
|
|
36615
|
-
rmSync as rmSync9
|
|
36644
|
+
readSync
|
|
36616
36645
|
} from "node:fs";
|
|
36617
36646
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
36618
36647
|
import { basename as basename3, dirname as dirname9, join as join17, normalize as normalize3 } from "node:path";
|
|
@@ -37689,7 +37718,7 @@ class GodotServer {
|
|
|
37689
37718
|
log.append("stderr", failed.stderr);
|
|
37690
37719
|
exitCode = typeof failed.code === "number" ? failed.code : -1;
|
|
37691
37720
|
} finally {
|
|
37692
|
-
|
|
37721
|
+
discard(exportLogs);
|
|
37693
37722
|
}
|
|
37694
37723
|
log.finish();
|
|
37695
37724
|
const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
|
|
@@ -37787,8 +37816,7 @@ class GodotServer {
|
|
|
37787
37816
|
} catch (error) {
|
|
37788
37817
|
reportProblem = errorMessage(error);
|
|
37789
37818
|
} finally {
|
|
37790
|
-
|
|
37791
|
-
rmSync9(userData, { recursive: true, force: true });
|
|
37819
|
+
discard(reportsDir, userData);
|
|
37792
37820
|
}
|
|
37793
37821
|
const engineEntries = run.log.select({ severity: "warning", sinceLastCall: false, limit: 200 }).entries.map(aboveTheRunner);
|
|
37794
37822
|
const verdicts = {
|
|
@@ -38030,12 +38058,12 @@ class GodotServer {
|
|
|
38030
38058
|
}
|
|
38031
38059
|
settingKeysOf(projectPath) {
|
|
38032
38060
|
if (projectPath === undefined) {
|
|
38033
|
-
return new
|
|
38061
|
+
return new Map;
|
|
38034
38062
|
}
|
|
38035
38063
|
try {
|
|
38036
38064
|
return settingKeys(readFileSync15(join17(projectPath, "project.godot"), "utf8"));
|
|
38037
38065
|
} catch {
|
|
38038
|
-
return new
|
|
38066
|
+
return new Map;
|
|
38039
38067
|
}
|
|
38040
38068
|
}
|
|
38041
38069
|
async handleRestartEditor() {
|
|
@@ -38067,7 +38095,7 @@ class GodotServer {
|
|
|
38067
38095
|
}
|
|
38068
38096
|
const now = this.godotBridge.getStatus();
|
|
38069
38097
|
const after = this.settingKeysOf(before.projectPath);
|
|
38070
|
-
const dropped = [...settingsBefore].filter((key) => !after.has(key));
|
|
38098
|
+
const dropped = [...settingsBefore].filter(([key]) => !after.has(key));
|
|
38071
38099
|
return this.jsonTextResponse({
|
|
38072
38100
|
restarted: true,
|
|
38073
38101
|
editorPid: now.editorPid,
|
|
@@ -38075,8 +38103,8 @@ class GodotServer {
|
|
|
38075
38103
|
serverVersion: SERVER_VERSION,
|
|
38076
38104
|
addonIsStale: now.addonVersion !== SERVER_VERSION,
|
|
38077
38105
|
staleNote: addonMismatch(now.addonVersion, SERVER_VERSION),
|
|
38078
|
-
settingsDropped: dropped.length > 0 ? dropped : undefined,
|
|
38079
|
-
settingsNote: dropped.length > 0 ?
|
|
38106
|
+
settingsDropped: dropped.length > 0 ? dropped.map(([setting, was]) => ({ setting, was })) : undefined,
|
|
38107
|
+
settingsNote: dropped.length > 0 ? `The editor saved project.godot on its way out and these keys are no longer in it, with the value each one held. Godot writes only what differs from its own defaults, so a key named deliberately at its default value is redundant to the editor and is dropped on save; it will be dropped again on the next restart. If any of them were pinned on purpose, to keep "set to this on purpose" and "not set" apart, project_settings set puts one back: ${dropped.map(([setting, was]) => `setting "${setting}" value ${JSON.stringify(was)}`).join(", ")}. Nothing else will say they have gone until something depends on one.` : undefined,
|
|
38080
38108
|
tookMs: Date.now() - began
|
|
38081
38109
|
});
|
|
38082
38110
|
}
|
|
@@ -38701,11 +38729,13 @@ class GodotServer {
|
|
|
38701
38729
|
return this.jsonTextResponse({
|
|
38702
38730
|
stopped: true,
|
|
38703
38731
|
through: stopped.throughEditor ? "editor" : "gdharness",
|
|
38732
|
+
endedPid: stopped.pid,
|
|
38704
38733
|
exitedBeforeStop: stopped.exitCode !== null,
|
|
38705
38734
|
exitCode: stopped.exitCode,
|
|
38706
38735
|
errors: stopped.log.count("error"),
|
|
38707
38736
|
warnings: stopped.log.count("warning"),
|
|
38708
38737
|
clean: stopped.log.count("error") === 0,
|
|
38738
|
+
note: stopped.throughEditor ? "The editor was asked to stop the scene it is playing. Anything that game started for itself, with OS.create_process or otherwise, is not the editor's to stop and is still running." : "The process named under endedPid was ended. Anything that game started for itself, with OS.create_process or otherwise, is a separate process and is still running.",
|
|
38709
38739
|
entries: forAnswer(stopped.log.select({ severity: "warning", sinceLastCall: false, limit: 200 }).entries)
|
|
38710
38740
|
});
|
|
38711
38741
|
}
|
|
@@ -38865,9 +38895,7 @@ class GodotServer {
|
|
|
38865
38895
|
]
|
|
38866
38896
|
};
|
|
38867
38897
|
} finally {
|
|
38868
|
-
|
|
38869
|
-
rmSync9(screenshotDir, { recursive: true, force: true });
|
|
38870
|
-
}
|
|
38898
|
+
discard(screenshotDir);
|
|
38871
38899
|
}
|
|
38872
38900
|
}
|
|
38873
38901
|
async handleFindRuntimeNodes(args) {
|
|
@@ -38954,6 +38982,7 @@ var init_server3 = __esm(() => {
|
|
|
38954
38982
|
init_resources();
|
|
38955
38983
|
init_run_record();
|
|
38956
38984
|
init_runtime_client();
|
|
38985
|
+
init_scratch();
|
|
38957
38986
|
init_server_version();
|
|
38958
38987
|
init_setup();
|
|
38959
38988
|
init_tool_definitions();
|
|
@@ -39906,8 +39935,9 @@ function taken(harness, path, held, stripped) {
|
|
|
39906
39935
|
|
|
39907
39936
|
// src/headless.ts
|
|
39908
39937
|
init_game_log();
|
|
39938
|
+
init_scratch();
|
|
39909
39939
|
import { execFile as execFile2 } from "node:child_process";
|
|
39910
|
-
import { mkdtempSync,
|
|
39940
|
+
import { mkdtempSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
39911
39941
|
import { tmpdir } from "node:os";
|
|
39912
39942
|
import { join as join4 } from "node:path";
|
|
39913
39943
|
import { promisify as promisify2 } from "node:util";
|
|
@@ -39984,7 +40014,7 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
39984
40014
|
messages: []
|
|
39985
40015
|
};
|
|
39986
40016
|
} finally {
|
|
39987
|
-
|
|
40017
|
+
discard(paramsDir);
|
|
39988
40018
|
}
|
|
39989
40019
|
const payload = lastJsonObject(stdout);
|
|
39990
40020
|
if (payload === null) {
|
|
@@ -40133,7 +40163,7 @@ init_headless();
|
|
|
40133
40163
|
init_resources();
|
|
40134
40164
|
init_server_version();
|
|
40135
40165
|
import { spawnSync } from "node:child_process";
|
|
40136
|
-
import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync7, rmSync as
|
|
40166
|
+
import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
40137
40167
|
import { dirname as dirname3, join as join8 } from "node:path";
|
|
40138
40168
|
import { fileURLToPath } from "node:url";
|
|
40139
40169
|
var ADDONS = ["gdharness_editor", "gdharness_runtime", "auto_reload"];
|
|
@@ -40158,7 +40188,7 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
|
|
|
40158
40188
|
}
|
|
40159
40189
|
const target = join8(projectPath, "addons", name);
|
|
40160
40190
|
const replaced = existsSync7(target);
|
|
40161
|
-
|
|
40191
|
+
rmSync3(target, { recursive: true, force: true });
|
|
40162
40192
|
mkdirSync3(dirname3(target), { recursive: true });
|
|
40163
40193
|
cpSync(source, target, { recursive: true });
|
|
40164
40194
|
writeFileSync5(join8(target, VERSION_MARKER), `${SERVER_VERSION}
|
|
@@ -40172,7 +40202,7 @@ function removeAddons(projectPath) {
|
|
|
40172
40202
|
for (const name of ADDONS) {
|
|
40173
40203
|
const target = join8(projectPath, "addons", name);
|
|
40174
40204
|
if (existsSync7(target)) {
|
|
40175
|
-
|
|
40205
|
+
rmSync3(target, { recursive: true, force: true });
|
|
40176
40206
|
removed.push(target);
|
|
40177
40207
|
}
|
|
40178
40208
|
}
|
|
@@ -40301,7 +40331,7 @@ function inspectProject(projectPath) {
|
|
|
40301
40331
|
|
|
40302
40332
|
// src/skill.ts
|
|
40303
40333
|
init_tool_definitions();
|
|
40304
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync as
|
|
40334
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
40305
40335
|
import { basename, dirname as dirname4, join as join9 } from "node:path";
|
|
40306
40336
|
|
|
40307
40337
|
// src/tool-reference.ts
|
|
@@ -40546,7 +40576,7 @@ function removeSkill(directories, projectPath) {
|
|
|
40546
40576
|
const removed = [];
|
|
40547
40577
|
for (const directory of directories) {
|
|
40548
40578
|
if (existsSync8(directory)) {
|
|
40549
|
-
|
|
40579
|
+
rmSync4(directory, { recursive: true, force: true });
|
|
40550
40580
|
pruneEmpty(dirname4(directory), projectPath);
|
|
40551
40581
|
removed.push(directory);
|
|
40552
40582
|
}
|
|
@@ -40560,7 +40590,7 @@ function pruneEmpty(directory, projectPath) {
|
|
|
40560
40590
|
if (readdirSync3(path).length > 0) {
|
|
40561
40591
|
return;
|
|
40562
40592
|
}
|
|
40563
|
-
|
|
40593
|
+
rmSync4(path, { recursive: true, force: true });
|
|
40564
40594
|
path = dirname4(path);
|
|
40565
40595
|
}
|
|
40566
40596
|
}
|
|
@@ -40568,7 +40598,7 @@ function writeSkill(directories, version) {
|
|
|
40568
40598
|
const files = skillFiles(version);
|
|
40569
40599
|
return directories.map((directory) => {
|
|
40570
40600
|
const replaced = existsSync8(directory);
|
|
40571
|
-
|
|
40601
|
+
rmSync4(directory, { recursive: true, force: true });
|
|
40572
40602
|
for (const [name, contents] of files) {
|
|
40573
40603
|
const path = join9(directory, name);
|
|
40574
40604
|
mkdirSync4(dirname4(path), { recursive: true });
|
package/build/index.js
CHANGED
|
@@ -10151,8 +10151,7 @@ import {
|
|
|
10151
10151
|
openSync as openSync2,
|
|
10152
10152
|
readdirSync as readdirSync6,
|
|
10153
10153
|
readFileSync as readFileSync11,
|
|
10154
|
-
readSync
|
|
10155
|
-
rmSync as rmSync5
|
|
10154
|
+
readSync
|
|
10156
10155
|
} from "node:fs";
|
|
10157
10156
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
10158
10157
|
import { basename as basename2, dirname as dirname4, join as join11, normalize as normalize2 } from "node:path";
|
|
@@ -26324,10 +26323,35 @@ class GodotLocator {
|
|
|
26324
26323
|
|
|
26325
26324
|
// src/headless.ts
|
|
26326
26325
|
import { execFile as execFile2 } from "node:child_process";
|
|
26327
|
-
import { mkdtempSync,
|
|
26326
|
+
import { mkdtempSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
26328
26327
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
26329
26328
|
import { join as join6 } from "node:path";
|
|
26330
26329
|
import { promisify as promisify2 } from "node:util";
|
|
26330
|
+
|
|
26331
|
+
// src/scratch.ts
|
|
26332
|
+
import { rmSync as rmSync2 } from "node:fs";
|
|
26333
|
+
var SWEPT = { recursive: true, force: true, maxRetries: 20, retryDelay: 250 };
|
|
26334
|
+
function discardWith(remove, paths) {
|
|
26335
|
+
const left = [];
|
|
26336
|
+
for (const path of paths) {
|
|
26337
|
+
if (!path) {
|
|
26338
|
+
continue;
|
|
26339
|
+
}
|
|
26340
|
+
try {
|
|
26341
|
+
remove(path);
|
|
26342
|
+
} catch (error) {
|
|
26343
|
+
left.push({ path, reason: error instanceof Error ? error.message : String(error) });
|
|
26344
|
+
}
|
|
26345
|
+
}
|
|
26346
|
+
return left;
|
|
26347
|
+
}
|
|
26348
|
+
function discard(...paths) {
|
|
26349
|
+
return discardWith((path) => {
|
|
26350
|
+
rmSync2(path, SWEPT);
|
|
26351
|
+
}, paths);
|
|
26352
|
+
}
|
|
26353
|
+
|
|
26354
|
+
// src/headless.ts
|
|
26331
26355
|
var run2 = promisify2(execFile2);
|
|
26332
26356
|
function snakeCased(params) {
|
|
26333
26357
|
const result = emptyRecord();
|
|
@@ -26401,7 +26425,7 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
26401
26425
|
messages: []
|
|
26402
26426
|
};
|
|
26403
26427
|
} finally {
|
|
26404
|
-
|
|
26428
|
+
discard(paramsDir);
|
|
26405
26429
|
}
|
|
26406
26430
|
const payload = lastJsonObject(stdout);
|
|
26407
26431
|
if (payload === null) {
|
|
@@ -27558,10 +27582,10 @@ function isValueComplete(value) {
|
|
|
27558
27582
|
return depth <= 0 && !inString;
|
|
27559
27583
|
}
|
|
27560
27584
|
function settingKeys(content) {
|
|
27561
|
-
const named = new
|
|
27585
|
+
const named = new Map;
|
|
27562
27586
|
for (const [section, entries] of Object.entries(parseProjectGodot(content))) {
|
|
27563
|
-
for (const key of Object.
|
|
27564
|
-
named.
|
|
27587
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
27588
|
+
named.set(`${section}/${key}`, value);
|
|
27565
27589
|
}
|
|
27566
27590
|
}
|
|
27567
27591
|
return named;
|
|
@@ -28877,7 +28901,10 @@ var TOOL_SPECS = [
|
|
|
28877
28901
|
summary: "run the project until it quits or is stopped",
|
|
28878
28902
|
requires: ["projectPath"]
|
|
28879
28903
|
},
|
|
28880
|
-
stop: {
|
|
28904
|
+
stop: {
|
|
28905
|
+
summary: "end the run and answer with what it printed last, naming the process ended under endedPid: a game that started processes of its own keeps them",
|
|
28906
|
+
requires: []
|
|
28907
|
+
},
|
|
28881
28908
|
check: {
|
|
28882
28909
|
summary: "boot headless, quit after a few frames, and report the verdict",
|
|
28883
28910
|
requires: ["projectPath"]
|
|
@@ -30443,7 +30470,7 @@ class GodotServer {
|
|
|
30443
30470
|
log.append("stderr", failed.stderr);
|
|
30444
30471
|
exitCode = typeof failed.code === "number" ? failed.code : -1;
|
|
30445
30472
|
} finally {
|
|
30446
|
-
|
|
30473
|
+
discard(exportLogs);
|
|
30447
30474
|
}
|
|
30448
30475
|
log.finish();
|
|
30449
30476
|
const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
|
|
@@ -30541,8 +30568,7 @@ class GodotServer {
|
|
|
30541
30568
|
} catch (error) {
|
|
30542
30569
|
reportProblem = errorMessage(error);
|
|
30543
30570
|
} finally {
|
|
30544
|
-
|
|
30545
|
-
rmSync5(userData, { recursive: true, force: true });
|
|
30571
|
+
discard(reportsDir, userData);
|
|
30546
30572
|
}
|
|
30547
30573
|
const engineEntries = run.log.select({ severity: "warning", sinceLastCall: false, limit: 200 }).entries.map(aboveTheRunner);
|
|
30548
30574
|
const verdicts = {
|
|
@@ -30784,12 +30810,12 @@ class GodotServer {
|
|
|
30784
30810
|
}
|
|
30785
30811
|
settingKeysOf(projectPath) {
|
|
30786
30812
|
if (projectPath === undefined) {
|
|
30787
|
-
return new
|
|
30813
|
+
return new Map;
|
|
30788
30814
|
}
|
|
30789
30815
|
try {
|
|
30790
30816
|
return settingKeys(readFileSync11(join11(projectPath, "project.godot"), "utf8"));
|
|
30791
30817
|
} catch {
|
|
30792
|
-
return new
|
|
30818
|
+
return new Map;
|
|
30793
30819
|
}
|
|
30794
30820
|
}
|
|
30795
30821
|
async handleRestartEditor() {
|
|
@@ -30821,7 +30847,7 @@ class GodotServer {
|
|
|
30821
30847
|
}
|
|
30822
30848
|
const now = this.godotBridge.getStatus();
|
|
30823
30849
|
const after = this.settingKeysOf(before.projectPath);
|
|
30824
|
-
const dropped = [...settingsBefore].filter((key) => !after.has(key));
|
|
30850
|
+
const dropped = [...settingsBefore].filter(([key]) => !after.has(key));
|
|
30825
30851
|
return this.jsonTextResponse({
|
|
30826
30852
|
restarted: true,
|
|
30827
30853
|
editorPid: now.editorPid,
|
|
@@ -30829,8 +30855,8 @@ class GodotServer {
|
|
|
30829
30855
|
serverVersion: SERVER_VERSION,
|
|
30830
30856
|
addonIsStale: now.addonVersion !== SERVER_VERSION,
|
|
30831
30857
|
staleNote: addonMismatch(now.addonVersion, SERVER_VERSION),
|
|
30832
|
-
settingsDropped: dropped.length > 0 ? dropped : undefined,
|
|
30833
|
-
settingsNote: dropped.length > 0 ?
|
|
30858
|
+
settingsDropped: dropped.length > 0 ? dropped.map(([setting, was]) => ({ setting, was })) : undefined,
|
|
30859
|
+
settingsNote: dropped.length > 0 ? `The editor saved project.godot on its way out and these keys are no longer in it, with the value each one held. Godot writes only what differs from its own defaults, so a key named deliberately at its default value is redundant to the editor and is dropped on save; it will be dropped again on the next restart. If any of them were pinned on purpose, to keep "set to this on purpose" and "not set" apart, project_settings set puts one back: ${dropped.map(([setting, was]) => `setting "${setting}" value ${JSON.stringify(was)}`).join(", ")}. Nothing else will say they have gone until something depends on one.` : undefined,
|
|
30834
30860
|
tookMs: Date.now() - began
|
|
30835
30861
|
});
|
|
30836
30862
|
}
|
|
@@ -31455,11 +31481,13 @@ class GodotServer {
|
|
|
31455
31481
|
return this.jsonTextResponse({
|
|
31456
31482
|
stopped: true,
|
|
31457
31483
|
through: stopped.throughEditor ? "editor" : "gdharness",
|
|
31484
|
+
endedPid: stopped.pid,
|
|
31458
31485
|
exitedBeforeStop: stopped.exitCode !== null,
|
|
31459
31486
|
exitCode: stopped.exitCode,
|
|
31460
31487
|
errors: stopped.log.count("error"),
|
|
31461
31488
|
warnings: stopped.log.count("warning"),
|
|
31462
31489
|
clean: stopped.log.count("error") === 0,
|
|
31490
|
+
note: stopped.throughEditor ? "The editor was asked to stop the scene it is playing. Anything that game started for itself, with OS.create_process or otherwise, is not the editor's to stop and is still running." : "The process named under endedPid was ended. Anything that game started for itself, with OS.create_process or otherwise, is a separate process and is still running.",
|
|
31463
31491
|
entries: forAnswer(stopped.log.select({ severity: "warning", sinceLastCall: false, limit: 200 }).entries)
|
|
31464
31492
|
});
|
|
31465
31493
|
}
|
|
@@ -31619,9 +31647,7 @@ class GodotServer {
|
|
|
31619
31647
|
]
|
|
31620
31648
|
};
|
|
31621
31649
|
} finally {
|
|
31622
|
-
|
|
31623
|
-
rmSync5(screenshotDir, { recursive: true, force: true });
|
|
31624
|
-
}
|
|
31650
|
+
discard(screenshotDir);
|
|
31625
31651
|
}
|
|
31626
31652
|
}
|
|
31627
31653
|
async handleFindRuntimeNodes(args) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.12",
|
|
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",
|