gdharness 0.12.10 → 0.12.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 +47 -23
- package/build/index.js +30 -16
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -7583,6 +7583,8 @@ async function runOperation2(engine, operation, params, projectPath) {
|
|
|
7583
7583
|
writeFileSync4(paramsFile, JSON.stringify(snakeCased2(params)), "utf8");
|
|
7584
7584
|
const args = [
|
|
7585
7585
|
"--headless",
|
|
7586
|
+
"--log-file",
|
|
7587
|
+
join7(paramsDir, "engine.log"),
|
|
7586
7588
|
"--path",
|
|
7587
7589
|
projectPath,
|
|
7588
7590
|
"--script",
|
|
@@ -15324,7 +15326,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
15324
15326
|
},
|
|
15325
15327
|
{
|
|
15326
15328
|
name: "project_search",
|
|
15327
|
-
description: "Searches text or a regular expression across project files and returns file paths with line numbers.",
|
|
15329
|
+
description: "Searches text or a regular expression across project files and returns file paths with line numbers. What the engine steps over is not searched: directories spelled with a dot, node_modules, and any directory holding a .gdignore. A vendored engine or an export directory is therefore absent from the results rather than matching the code you are looking for in a copy nobody runs.",
|
|
15328
15330
|
parameters: {
|
|
15329
15331
|
projectPath: PROJECT_PATH,
|
|
15330
15332
|
query: { type: "string", description: "The text or pattern to find." },
|
|
@@ -35786,13 +35788,22 @@ var init_lsp_client = __esm(() => {
|
|
|
35786
35788
|
});
|
|
35787
35789
|
|
|
35788
35790
|
// src/project-scan.ts
|
|
35789
|
-
import { readdirSync as readdirSync4, readFileSync as readFileSync10 } from "node:fs";
|
|
35791
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync10 } from "node:fs";
|
|
35790
35792
|
import { join as join12 } from "node:path";
|
|
35793
|
+
function skipped(name) {
|
|
35794
|
+
return name.startsWith(".") || SKIPPED.has(name);
|
|
35795
|
+
}
|
|
35796
|
+
function steppedOver(directory) {
|
|
35797
|
+
return existsSync10(join12(directory, ".gdignore"));
|
|
35798
|
+
}
|
|
35791
35799
|
function projectStructure(projectPath) {
|
|
35792
35800
|
const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
|
|
35793
35801
|
const visit = (directory) => {
|
|
35802
|
+
if (steppedOver(directory)) {
|
|
35803
|
+
return;
|
|
35804
|
+
}
|
|
35794
35805
|
for (const entry of readdirSync4(directory, { withFileTypes: true })) {
|
|
35795
|
-
if (entry.name
|
|
35806
|
+
if (skipped(entry.name)) {
|
|
35796
35807
|
continue;
|
|
35797
35808
|
}
|
|
35798
35809
|
if (entry.isDirectory()) {
|
|
@@ -35831,11 +35842,14 @@ function searchProject(projectPath, options) {
|
|
|
35831
35842
|
return false;
|
|
35832
35843
|
};
|
|
35833
35844
|
const visit = (directory) => {
|
|
35845
|
+
if (steppedOver(directory)) {
|
|
35846
|
+
return;
|
|
35847
|
+
}
|
|
35834
35848
|
for (const entry of readdirSync4(directory, { withFileTypes: true })) {
|
|
35835
35849
|
if (full()) {
|
|
35836
35850
|
return;
|
|
35837
35851
|
}
|
|
35838
|
-
if (
|
|
35852
|
+
if (skipped(entry.name)) {
|
|
35839
35853
|
continue;
|
|
35840
35854
|
}
|
|
35841
35855
|
const entryPath = join12(directory, entry.name);
|
|
@@ -35872,12 +35886,12 @@ function searchProject(projectPath, options) {
|
|
|
35872
35886
|
}
|
|
35873
35887
|
var SKIPPED, ASSET_EXTENSIONS;
|
|
35874
35888
|
var init_project_scan = __esm(() => {
|
|
35875
|
-
SKIPPED = new Set(["
|
|
35889
|
+
SKIPPED = new Set(["node_modules"]);
|
|
35876
35890
|
ASSET_EXTENSIONS = new Set(["png", "jpg", "jpeg", "webp", "svg", "ttf", "otf", "wav", "mp3", "ogg"]);
|
|
35877
35891
|
});
|
|
35878
35892
|
|
|
35879
35893
|
// src/runtime-client.ts
|
|
35880
|
-
import { existsSync as
|
|
35894
|
+
import { existsSync as existsSync11, readdirSync as readdirSync5, readFileSync as readFileSync11, unlinkSync } from "node:fs";
|
|
35881
35895
|
import { createConnection as createConnection3 } from "node:net";
|
|
35882
35896
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
35883
35897
|
import { join as join13, resolve as resolve4 } from "node:path";
|
|
@@ -35948,7 +35962,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
|
|
|
35948
35962
|
return runtimesAnnounced(directories).running;
|
|
35949
35963
|
}
|
|
35950
35964
|
function announcedIn(directory) {
|
|
35951
|
-
if (!
|
|
35965
|
+
if (!existsSync11(directory)) {
|
|
35952
35966
|
return [];
|
|
35953
35967
|
}
|
|
35954
35968
|
const found = [];
|
|
@@ -36285,11 +36299,11 @@ var init_run_record = __esm(() => {
|
|
|
36285
36299
|
});
|
|
36286
36300
|
|
|
36287
36301
|
// src/setup.ts
|
|
36288
|
-
import { cpSync as cpSync2, existsSync as
|
|
36302
|
+
import { cpSync as cpSync2, existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync13, rmSync as rmSync8, writeFileSync as writeFileSync9 } from "node:fs";
|
|
36289
36303
|
import { dirname as dirname8, join as join15 } from "node:path";
|
|
36290
36304
|
function installedAddonVersion(projectPath) {
|
|
36291
36305
|
const marker = join15(projectPath, "addons", ADDONS2[0], VERSION_MARKER2);
|
|
36292
|
-
if (!
|
|
36306
|
+
if (!existsSync12(marker)) {
|
|
36293
36307
|
return null;
|
|
36294
36308
|
}
|
|
36295
36309
|
const said = readFileSync13(marker, "utf8").trim();
|
|
@@ -36312,7 +36326,7 @@ var init_setup = __esm(() => {
|
|
|
36312
36326
|
import { execFile as execFile5, spawn } from "node:child_process";
|
|
36313
36327
|
import {
|
|
36314
36328
|
closeSync,
|
|
36315
|
-
existsSync as
|
|
36329
|
+
existsSync as existsSync13,
|
|
36316
36330
|
fstatSync,
|
|
36317
36331
|
mkdirSync as mkdirSync8,
|
|
36318
36332
|
mkdtempSync as mkdtempSync3,
|
|
@@ -36460,7 +36474,7 @@ function aboveTheRunner(entry) {
|
|
|
36460
36474
|
}
|
|
36461
36475
|
function elsewhereIn(projectPath, asked) {
|
|
36462
36476
|
const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
|
|
36463
|
-
if (wanted === "" ||
|
|
36477
|
+
if (wanted === "" || existsSync13(join16(projectPath, wanted))) {
|
|
36464
36478
|
return "";
|
|
36465
36479
|
}
|
|
36466
36480
|
const root = (wanted.split("/")[0] ?? "").toLowerCase();
|
|
@@ -37077,7 +37091,7 @@ class GodotServer {
|
|
|
37077
37091
|
return { ok: false, response: this.createErrorResponse("projectPath is required.") };
|
|
37078
37092
|
}
|
|
37079
37093
|
const file = join16(path, "project.godot");
|
|
37080
|
-
if (!
|
|
37094
|
+
if (!existsSync13(file)) {
|
|
37081
37095
|
return {
|
|
37082
37096
|
ok: false,
|
|
37083
37097
|
response: this.createErrorResponse(`Not a Godot project: ${path}`, [
|
|
@@ -37341,7 +37355,7 @@ class GodotServer {
|
|
|
37341
37355
|
log.finish();
|
|
37342
37356
|
const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
|
|
37343
37357
|
const verdict = {
|
|
37344
|
-
exported: exitCode === 0 && log.count("error") === 0 &&
|
|
37358
|
+
exported: exitCode === 0 && log.count("error") === 0 && existsSync13(output.absolutePath),
|
|
37345
37359
|
preset,
|
|
37346
37360
|
outputPath: output.relativePath,
|
|
37347
37361
|
debug,
|
|
@@ -37371,7 +37385,7 @@ class GodotServer {
|
|
|
37371
37385
|
return contained.response;
|
|
37372
37386
|
}
|
|
37373
37387
|
const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
|
|
37374
|
-
if (!
|
|
37388
|
+
if (!existsSync13(join16(project.value.path, runner))) {
|
|
37375
37389
|
return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
|
|
37376
37390
|
"Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
|
|
37377
37391
|
]);
|
|
@@ -37425,7 +37439,7 @@ class GodotServer {
|
|
|
37425
37439
|
let report = null;
|
|
37426
37440
|
let reportProblem = null;
|
|
37427
37441
|
try {
|
|
37428
|
-
const written =
|
|
37442
|
+
const written = existsSync13(reportsDir) ? readdirSync7(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
|
|
37429
37443
|
const newest = written.at(-1);
|
|
37430
37444
|
if (newest !== undefined) {
|
|
37431
37445
|
report = parseJUnit(readFileSync14(join16(reportsDir, newest, "results.xml"), "utf8"));
|
|
@@ -37845,7 +37859,7 @@ class GodotServer {
|
|
|
37845
37859
|
return runIsUp(run, editorSays);
|
|
37846
37860
|
}
|
|
37847
37861
|
async runtimeUp(projectPath, before, budgetMs) {
|
|
37848
|
-
if (!
|
|
37862
|
+
if (!existsSync13(join16(projectPath, RUNTIME_AUTOLOAD2.path))) {
|
|
37849
37863
|
return runtimeVerdict(null, { addon: false, budgetMs, heldAt: null, running: false });
|
|
37850
37864
|
}
|
|
37851
37865
|
const endpoint = await announcedSince(projectPath, before, {
|
|
@@ -38475,7 +38489,7 @@ var init_server3 = __esm(() => {
|
|
|
38475
38489
|
});
|
|
38476
38490
|
|
|
38477
38491
|
// src/cli.ts
|
|
38478
|
-
import { existsSync as
|
|
38492
|
+
import { existsSync as existsSync14 } from "fs";
|
|
38479
38493
|
import { join as join17, resolve as resolve5 } from "path";
|
|
38480
38494
|
|
|
38481
38495
|
// src/errors.ts
|
|
@@ -39407,6 +39421,8 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
39407
39421
|
writeFileSync2(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
|
|
39408
39422
|
const args = [
|
|
39409
39423
|
"--headless",
|
|
39424
|
+
"--log-file",
|
|
39425
|
+
join4(paramsDir, "engine.log"),
|
|
39410
39426
|
"--path",
|
|
39411
39427
|
projectPath,
|
|
39412
39428
|
"--script",
|
|
@@ -39887,9 +39903,17 @@ breakpoint on the line you want instead.
|
|
|
39887
39903
|
\`scene_signal\` and \`resource_edit\` change it through the editor, so the files keep their
|
|
39888
39904
|
formatting. \`script_diagnostics\` and \`script_info\` come from the editor's own language server.
|
|
39889
39905
|
|
|
39890
|
-
\`project_info\`, \`project_dependencies\`, \`
|
|
39906
|
+
\`project_info\`, \`project_dependencies\`, \`project_settings\`, \`project_import\`,
|
|
39907
|
+
\`project_export\`, \`project_test\`, \`script_edit\`, \`script_info structure\` and
|
|
39891
39908
|
\`editor_classes\` need nothing open: they run a short headless engine and are gone before the
|
|
39892
|
-
answer is printed.
|
|
39909
|
+
answer is printed. \`project_settings get\` is on that list too, reading as it does like a look at
|
|
39910
|
+
a config file: it starts an engine so that a setting nobody wrote down still answers with the
|
|
39911
|
+
default the engine registers for it.
|
|
39912
|
+
|
|
39913
|
+
Editing a file while a game is running does not change the running game. \`auto_reload\` is an
|
|
39914
|
+
editor plugin and reloads into the editor's own process; the game is a separate process holding
|
|
39915
|
+
its own copy. So a long run is not a reason to stop editing, and the new code arrives on the next
|
|
39916
|
+
\`editor_run start\`.
|
|
39893
39917
|
|
|
39894
39918
|
A wall of "Could not find type" on the project's own classes means the editor is not holding
|
|
39895
39919
|
them. \`editor_rescan\` asks it to scan and names any class it still cannot resolve under
|
|
@@ -40018,7 +40042,7 @@ class UsageError extends Refusal {
|
|
|
40018
40042
|
function projectArgument(at) {
|
|
40019
40043
|
const named = args.slice(at).find((value) => !value.startsWith("--"));
|
|
40020
40044
|
const projectPath = resolve5(named ?? ".");
|
|
40021
|
-
if (!
|
|
40045
|
+
if (!existsSync14(join17(projectPath, "project.godot"))) {
|
|
40022
40046
|
throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
|
|
40023
40047
|
}
|
|
40024
40048
|
return projectPath;
|
|
@@ -40052,7 +40076,7 @@ async function registerRuntime(godot, projectPath) {
|
|
|
40052
40076
|
return;
|
|
40053
40077
|
}
|
|
40054
40078
|
console.log(`${RUNTIME_AUTOLOAD.name} autoload left at ${named}, which this project registers itself`);
|
|
40055
|
-
if (!
|
|
40079
|
+
if (!existsSync14(join17(projectPath, (named ?? "").replace(/^res:\/\//, "")))) {
|
|
40056
40080
|
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}`);
|
|
40057
40081
|
}
|
|
40058
40082
|
}
|
|
@@ -40184,7 +40208,7 @@ async function setup() {
|
|
|
40184
40208
|
console.log("no harness configured; name one yourself, and gdharness harnesses lists them all");
|
|
40185
40209
|
}
|
|
40186
40210
|
if (!args.includes("--no-skill")) {
|
|
40187
|
-
const directories = skillDirectories(chosen.harnesses, projectPath,
|
|
40211
|
+
const directories = skillDirectories(chosen.harnesses, projectPath, existsSync14);
|
|
40188
40212
|
for (const written of writeSkill(directories, getLocalVersion())) {
|
|
40189
40213
|
console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
|
|
40190
40214
|
}
|
|
@@ -40273,7 +40297,7 @@ async function upgrade() {
|
|
|
40273
40297
|
if (already.length === 0) {
|
|
40274
40298
|
console.log("no harness config names gdharness, so none was re-pinned");
|
|
40275
40299
|
}
|
|
40276
|
-
for (const written of writeSkill(skillDirectories(already, projectPath,
|
|
40300
|
+
for (const written of writeSkill(skillDirectories(already, projectPath, existsSync14), version)) {
|
|
40277
40301
|
console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
|
|
40278
40302
|
}
|
|
40279
40303
|
console.log(`
|
package/build/index.js
CHANGED
|
@@ -10134,7 +10134,7 @@ function defectReport(where, error, godotVersion) {
|
|
|
10134
10134
|
import { execFile as execFile3, spawn } from "node:child_process";
|
|
10135
10135
|
import {
|
|
10136
10136
|
closeSync,
|
|
10137
|
-
existsSync as
|
|
10137
|
+
existsSync as existsSync8,
|
|
10138
10138
|
fstatSync,
|
|
10139
10139
|
mkdirSync as mkdirSync5,
|
|
10140
10140
|
mkdtempSync as mkdtempSync2,
|
|
@@ -26299,6 +26299,8 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
26299
26299
|
writeFileSync3(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
|
|
26300
26300
|
const args = [
|
|
26301
26301
|
"--headless",
|
|
26302
|
+
"--log-file",
|
|
26303
|
+
join5(paramsDir, "engine.log"),
|
|
26302
26304
|
"--path",
|
|
26303
26305
|
projectPath,
|
|
26304
26306
|
"--script",
|
|
@@ -27196,15 +27198,24 @@ async function handleLSPTool(client, toolName, args) {
|
|
|
27196
27198
|
}
|
|
27197
27199
|
|
|
27198
27200
|
// src/project-scan.ts
|
|
27199
|
-
import { readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
|
|
27201
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
|
|
27200
27202
|
import { join as join6 } from "node:path";
|
|
27201
|
-
var SKIPPED = new Set(["
|
|
27203
|
+
var SKIPPED = new Set(["node_modules"]);
|
|
27204
|
+
function skipped(name) {
|
|
27205
|
+
return name.startsWith(".") || SKIPPED.has(name);
|
|
27206
|
+
}
|
|
27207
|
+
function steppedOver(directory) {
|
|
27208
|
+
return existsSync5(join6(directory, ".gdignore"));
|
|
27209
|
+
}
|
|
27202
27210
|
var ASSET_EXTENSIONS = new Set(["png", "jpg", "jpeg", "webp", "svg", "ttf", "otf", "wav", "mp3", "ogg"]);
|
|
27203
27211
|
function projectStructure(projectPath) {
|
|
27204
27212
|
const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
|
|
27205
27213
|
const visit = (directory) => {
|
|
27214
|
+
if (steppedOver(directory)) {
|
|
27215
|
+
return;
|
|
27216
|
+
}
|
|
27206
27217
|
for (const entry of readdirSync3(directory, { withFileTypes: true })) {
|
|
27207
|
-
if (entry.name
|
|
27218
|
+
if (skipped(entry.name)) {
|
|
27208
27219
|
continue;
|
|
27209
27220
|
}
|
|
27210
27221
|
if (entry.isDirectory()) {
|
|
@@ -27243,11 +27254,14 @@ function searchProject(projectPath, options) {
|
|
|
27243
27254
|
return false;
|
|
27244
27255
|
};
|
|
27245
27256
|
const visit = (directory) => {
|
|
27257
|
+
if (steppedOver(directory)) {
|
|
27258
|
+
return;
|
|
27259
|
+
}
|
|
27246
27260
|
for (const entry of readdirSync3(directory, { withFileTypes: true })) {
|
|
27247
27261
|
if (full()) {
|
|
27248
27262
|
return;
|
|
27249
27263
|
}
|
|
27250
|
-
if (
|
|
27264
|
+
if (skipped(entry.name)) {
|
|
27251
27265
|
continue;
|
|
27252
27266
|
}
|
|
27253
27267
|
const entryPath = join6(directory, entry.name);
|
|
@@ -27506,7 +27520,7 @@ import { mkdirSync as mkdirSync3, openSync, readdirSync as readdirSync5, readFil
|
|
|
27506
27520
|
import { basename, join as join8 } from "node:path";
|
|
27507
27521
|
|
|
27508
27522
|
// src/runtime-client.ts
|
|
27509
|
-
import { existsSync as
|
|
27523
|
+
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync7, unlinkSync } from "node:fs";
|
|
27510
27524
|
import { createConnection as createConnection3 } from "node:net";
|
|
27511
27525
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
27512
27526
|
import { join as join7, resolve as resolve4 } from "node:path";
|
|
@@ -27632,7 +27646,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
|
|
|
27632
27646
|
return runtimesAnnounced(directories).running;
|
|
27633
27647
|
}
|
|
27634
27648
|
function announcedIn(directory) {
|
|
27635
|
-
if (!
|
|
27649
|
+
if (!existsSync6(directory)) {
|
|
27636
27650
|
return [];
|
|
27637
27651
|
}
|
|
27638
27652
|
const found = [];
|
|
@@ -27962,7 +27976,7 @@ function sweepTranscripts(keepMs = 24 * 60 * 60 * 1000, now = Date.now()) {
|
|
|
27962
27976
|
}
|
|
27963
27977
|
|
|
27964
27978
|
// src/setup.ts
|
|
27965
|
-
import { cpSync, existsSync as
|
|
27979
|
+
import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync9, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
27966
27980
|
import { dirname as dirname3, join as join9 } from "node:path";
|
|
27967
27981
|
var ADDONS = ["gdharness_editor", "gdharness_runtime", "auto_reload"];
|
|
27968
27982
|
var RUNTIME_AUTOLOAD = {
|
|
@@ -27972,7 +27986,7 @@ var RUNTIME_AUTOLOAD = {
|
|
|
27972
27986
|
var VERSION_MARKER = ".gdharness-version";
|
|
27973
27987
|
function installedAddonVersion(projectPath) {
|
|
27974
27988
|
const marker = join9(projectPath, "addons", ADDONS[0], VERSION_MARKER);
|
|
27975
|
-
if (!
|
|
27989
|
+
if (!existsSync7(marker)) {
|
|
27976
27990
|
return null;
|
|
27977
27991
|
}
|
|
27978
27992
|
const said = readFileSync9(marker, "utf8").trim();
|
|
@@ -28199,7 +28213,7 @@ var TOOL_SPECS = [
|
|
|
28199
28213
|
},
|
|
28200
28214
|
{
|
|
28201
28215
|
name: "project_search",
|
|
28202
|
-
description: "Searches text or a regular expression across project files and returns file paths with line numbers.",
|
|
28216
|
+
description: "Searches text or a regular expression across project files and returns file paths with line numbers. What the engine steps over is not searched: directories spelled with a dot, node_modules, and any directory holding a .gdignore. A vendored engine or an export directory is therefore absent from the results rather than matching the code you are looking for in a copy nobody runs.",
|
|
28203
28217
|
parameters: {
|
|
28204
28218
|
projectPath: PROJECT_PATH,
|
|
28205
28219
|
query: { type: "string", description: "The text or pattern to find." },
|
|
@@ -29242,7 +29256,7 @@ function aboveTheRunner(entry) {
|
|
|
29242
29256
|
}
|
|
29243
29257
|
function elsewhereIn(projectPath, asked) {
|
|
29244
29258
|
const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
|
|
29245
|
-
if (wanted === "" ||
|
|
29259
|
+
if (wanted === "" || existsSync8(join10(projectPath, wanted))) {
|
|
29246
29260
|
return "";
|
|
29247
29261
|
}
|
|
29248
29262
|
const root = (wanted.split("/")[0] ?? "").toLowerCase();
|
|
@@ -29859,7 +29873,7 @@ class GodotServer {
|
|
|
29859
29873
|
return { ok: false, response: this.createErrorResponse("projectPath is required.") };
|
|
29860
29874
|
}
|
|
29861
29875
|
const file = join10(path, "project.godot");
|
|
29862
|
-
if (!
|
|
29876
|
+
if (!existsSync8(file)) {
|
|
29863
29877
|
return {
|
|
29864
29878
|
ok: false,
|
|
29865
29879
|
response: this.createErrorResponse(`Not a Godot project: ${path}`, [
|
|
@@ -30123,7 +30137,7 @@ class GodotServer {
|
|
|
30123
30137
|
log.finish();
|
|
30124
30138
|
const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
|
|
30125
30139
|
const verdict = {
|
|
30126
|
-
exported: exitCode === 0 && log.count("error") === 0 &&
|
|
30140
|
+
exported: exitCode === 0 && log.count("error") === 0 && existsSync8(output.absolutePath),
|
|
30127
30141
|
preset,
|
|
30128
30142
|
outputPath: output.relativePath,
|
|
30129
30143
|
debug,
|
|
@@ -30153,7 +30167,7 @@ class GodotServer {
|
|
|
30153
30167
|
return contained.response;
|
|
30154
30168
|
}
|
|
30155
30169
|
const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
|
|
30156
|
-
if (!
|
|
30170
|
+
if (!existsSync8(join10(project.value.path, runner))) {
|
|
30157
30171
|
return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
|
|
30158
30172
|
"Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
|
|
30159
30173
|
]);
|
|
@@ -30207,7 +30221,7 @@ class GodotServer {
|
|
|
30207
30221
|
let report = null;
|
|
30208
30222
|
let reportProblem = null;
|
|
30209
30223
|
try {
|
|
30210
|
-
const written =
|
|
30224
|
+
const written = existsSync8(reportsDir) ? readdirSync6(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
|
|
30211
30225
|
const newest = written.at(-1);
|
|
30212
30226
|
if (newest !== undefined) {
|
|
30213
30227
|
report = parseJUnit(readFileSync10(join10(reportsDir, newest, "results.xml"), "utf8"));
|
|
@@ -30627,7 +30641,7 @@ class GodotServer {
|
|
|
30627
30641
|
return runIsUp(run, editorSays);
|
|
30628
30642
|
}
|
|
30629
30643
|
async runtimeUp(projectPath, before, budgetMs) {
|
|
30630
|
-
if (!
|
|
30644
|
+
if (!existsSync8(join10(projectPath, RUNTIME_AUTOLOAD.path))) {
|
|
30631
30645
|
return runtimeVerdict(null, { addon: false, budgetMs, heldAt: null, running: false });
|
|
30632
30646
|
}
|
|
30633
30647
|
const endpoint = await announcedSince(projectPath, before, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.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",
|