gdharness 1.2.27 → 1.2.28
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
CHANGED
|
@@ -8198,24 +8198,106 @@ var init_engine_run = __esm(() => {
|
|
|
8198
8198
|
init_game_log();
|
|
8199
8199
|
});
|
|
8200
8200
|
|
|
8201
|
+
// src/library-copies.ts
|
|
8202
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync3, renameSync, unlinkSync } from "node:fs";
|
|
8203
|
+
import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute2, join as join5 } from "node:path";
|
|
8204
|
+
function freeLibraryCopies(projectPath, platform = process.platform) {
|
|
8205
|
+
const setAside = [];
|
|
8206
|
+
const swept = [];
|
|
8207
|
+
if (platform !== "win32") {
|
|
8208
|
+
return { setAside, swept };
|
|
8209
|
+
}
|
|
8210
|
+
for (const library of windowsLibraries(projectPath)) {
|
|
8211
|
+
const folder = dirname4(library);
|
|
8212
|
+
const copy = `~${basename3(library)}`;
|
|
8213
|
+
if (existsSync5(join5(folder, copy))) {
|
|
8214
|
+
const aside = join5(folder, `${copy}.aside-${process.pid}-${Date.now()}`);
|
|
8215
|
+
try {
|
|
8216
|
+
renameSync(join5(folder, copy), aside);
|
|
8217
|
+
setAside.push(aside);
|
|
8218
|
+
} catch {}
|
|
8219
|
+
}
|
|
8220
|
+
let names;
|
|
8221
|
+
try {
|
|
8222
|
+
names = readdirSync3(folder);
|
|
8223
|
+
} catch {
|
|
8224
|
+
continue;
|
|
8225
|
+
}
|
|
8226
|
+
for (const name of names) {
|
|
8227
|
+
if (name.length > copy.length && name.toLowerCase().startsWith(copy.toLowerCase())) {
|
|
8228
|
+
try {
|
|
8229
|
+
unlinkSync(join5(folder, name));
|
|
8230
|
+
swept.push(join5(folder, name));
|
|
8231
|
+
} catch {}
|
|
8232
|
+
}
|
|
8233
|
+
}
|
|
8234
|
+
}
|
|
8235
|
+
return { setAside, swept };
|
|
8236
|
+
}
|
|
8237
|
+
function windowsLibraries(projectPath) {
|
|
8238
|
+
const listed = readOrNull(join5(projectPath, ".godot", "extension_list.cfg"));
|
|
8239
|
+
if (listed === null) {
|
|
8240
|
+
return [];
|
|
8241
|
+
}
|
|
8242
|
+
const libraries = new Set;
|
|
8243
|
+
for (const line of listed.split(/\r?\n/)) {
|
|
8244
|
+
const manifest = resolveResource(projectPath, projectPath, line.trim());
|
|
8245
|
+
const text = manifest === null ? null : readOrNull(manifest);
|
|
8246
|
+
if (manifest === null || text === null) {
|
|
8247
|
+
continue;
|
|
8248
|
+
}
|
|
8249
|
+
let inLibraries = false;
|
|
8250
|
+
for (const row of text.split(/\r?\n/)) {
|
|
8251
|
+
const section = /^\s*\[([^\]]+)\]/.exec(row)?.[1];
|
|
8252
|
+
if (section !== undefined) {
|
|
8253
|
+
inLibraries = section.trim() === "libraries";
|
|
8254
|
+
continue;
|
|
8255
|
+
}
|
|
8256
|
+
const named = inLibraries ? /^\s*windows[\w.]*\s*=\s*"([^"]+)"/.exec(row)?.[1] : undefined;
|
|
8257
|
+
const library = named === undefined ? null : resolveResource(projectPath, dirname4(manifest), named);
|
|
8258
|
+
if (library !== null) {
|
|
8259
|
+
libraries.add(library);
|
|
8260
|
+
}
|
|
8261
|
+
}
|
|
8262
|
+
}
|
|
8263
|
+
return [...libraries];
|
|
8264
|
+
}
|
|
8265
|
+
function resolveResource(projectPath, relativeTo, path) {
|
|
8266
|
+
if (path === "") {
|
|
8267
|
+
return null;
|
|
8268
|
+
}
|
|
8269
|
+
if (path.startsWith("res://")) {
|
|
8270
|
+
return join5(projectPath, path.slice("res://".length));
|
|
8271
|
+
}
|
|
8272
|
+
return isAbsolute2(path) ? path : join5(relativeTo, path);
|
|
8273
|
+
}
|
|
8274
|
+
function readOrNull(path) {
|
|
8275
|
+
try {
|
|
8276
|
+
return readFileSync3(path, "utf8");
|
|
8277
|
+
} catch {
|
|
8278
|
+
return null;
|
|
8279
|
+
}
|
|
8280
|
+
}
|
|
8281
|
+
var init_library_copies = () => {};
|
|
8282
|
+
|
|
8201
8283
|
// src/reimport.ts
|
|
8202
8284
|
import { createHash } from "node:crypto";
|
|
8203
|
-
import { existsSync as
|
|
8204
|
-
import { basename as
|
|
8285
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, rmSync as rmSync3, statSync as statSync3, utimesSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
8286
|
+
import { basename as basename4, join as join6 } from "node:path";
|
|
8205
8287
|
function forceNextImport(projectPath, resourcePath) {
|
|
8206
8288
|
const relative = resourcePath.replace(/^res:\/\//, "");
|
|
8207
|
-
const sidecar =
|
|
8208
|
-
if (!
|
|
8289
|
+
const sidecar = join6(projectPath, `${relative}.import`);
|
|
8290
|
+
if (!existsSync6(sidecar)) {
|
|
8209
8291
|
return;
|
|
8210
8292
|
}
|
|
8211
8293
|
const { atime, mtimeMs } = statSync3(sidecar);
|
|
8212
|
-
writeFileSync3(sidecar,
|
|
8294
|
+
writeFileSync3(sidecar, readFileSync4(sidecar, "utf8").replace(/^valid=false\r?\n/m, ""));
|
|
8213
8295
|
utimesSync(sidecar, atime, new Date(mtimeMs + 2000));
|
|
8214
8296
|
rmSync3(importRecord(projectPath, resourcePath), { force: true });
|
|
8215
8297
|
}
|
|
8216
8298
|
function importRecord(projectPath, resourcePath) {
|
|
8217
8299
|
const digest = createHash("md5").update(resourcePath).digest("hex");
|
|
8218
|
-
return
|
|
8300
|
+
return join6(projectPath, ".godot", "imported", `${basename4(resourcePath)}-${digest}.md5`);
|
|
8219
8301
|
}
|
|
8220
8302
|
var init_reimport = () => {};
|
|
8221
8303
|
|
|
@@ -8235,17 +8317,17 @@ function alive(pid) {
|
|
|
8235
8317
|
var init_alive = () => {};
|
|
8236
8318
|
|
|
8237
8319
|
// src/scratch.ts
|
|
8238
|
-
import { existsSync as
|
|
8320
|
+
import { existsSync as existsSync7, mkdtempSync, readdirSync as readdirSync4, rmSync as rmSync4 } from "node:fs";
|
|
8239
8321
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
8240
|
-
import { join as
|
|
8322
|
+
import { join as join7 } from "node:path";
|
|
8241
8323
|
import process6 from "node:process";
|
|
8242
8324
|
function scratchDirectory(kind) {
|
|
8243
|
-
return mkdtempSync(
|
|
8325
|
+
return mkdtempSync(join7(tmpdir2(), `gdharness-${kind}-${process6.pid}-`));
|
|
8244
8326
|
}
|
|
8245
8327
|
function sweepAbandonedScratch(directory = tmpdir2()) {
|
|
8246
8328
|
let entries;
|
|
8247
8329
|
try {
|
|
8248
|
-
entries =
|
|
8330
|
+
entries = readdirSync4(directory);
|
|
8249
8331
|
} catch {
|
|
8250
8332
|
return;
|
|
8251
8333
|
}
|
|
@@ -8256,7 +8338,7 @@ function sweepAbandonedScratch(directory = tmpdir2()) {
|
|
|
8256
8338
|
continue;
|
|
8257
8339
|
}
|
|
8258
8340
|
try {
|
|
8259
|
-
remove(
|
|
8341
|
+
remove(join7(directory, entry));
|
|
8260
8342
|
} catch {}
|
|
8261
8343
|
}
|
|
8262
8344
|
}
|
|
@@ -8294,7 +8376,7 @@ function tryAgain(path, attempt) {
|
|
|
8294
8376
|
lastTryOnExit();
|
|
8295
8377
|
}
|
|
8296
8378
|
const after = AGAIN_AFTER_MS[attempt];
|
|
8297
|
-
if (after === undefined || !
|
|
8379
|
+
if (after === undefined || !existsSync7(path)) {
|
|
8298
8380
|
waiting.delete(path);
|
|
8299
8381
|
if (after === undefined) {
|
|
8300
8382
|
atExit.add(path);
|
|
@@ -8341,8 +8423,8 @@ var init_scratch = __esm(() => {
|
|
|
8341
8423
|
});
|
|
8342
8424
|
|
|
8343
8425
|
// src/headless.ts
|
|
8344
|
-
import { existsSync as
|
|
8345
|
-
import { dirname as
|
|
8426
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5, realpathSync as realpathSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
8427
|
+
import { dirname as dirname5, join as join8 } from "node:path";
|
|
8346
8428
|
function snakeCased(params) {
|
|
8347
8429
|
const result = emptyRecord();
|
|
8348
8430
|
for (const [key, value] of Object.entries(params)) {
|
|
@@ -8397,7 +8479,7 @@ function refusalsIn(log) {
|
|
|
8397
8479
|
}
|
|
8398
8480
|
function scriptFault(problems, script) {
|
|
8399
8481
|
const spelled = (path) => `(${path.replaceAll("\\", "/").toLowerCase()}/`;
|
|
8400
|
-
const directories = [...new Set([spelled(
|
|
8482
|
+
const directories = [...new Set([spelled(dirname5(script)), spelled(resolvedOr(dirname5(script)))])];
|
|
8401
8483
|
return problems.find((entry) => {
|
|
8402
8484
|
const at = entry.detail.find((line) => line.startsWith("at: "))?.replaceAll("\\", "/").toLowerCase();
|
|
8403
8485
|
return entry.severity === "error" && at !== undefined && directories.some((directory) => at.includes(directory));
|
|
@@ -8422,7 +8504,7 @@ function librariesNotCopied(messages) {
|
|
|
8422
8504
|
}
|
|
8423
8505
|
function extensionRetryNote(libraries, stillNotLoaded = []) {
|
|
8424
8506
|
const second = stillNotLoaded.length === 0 ? "so the import was run again and loaded the extension, and the messages are from that second run." : `so the import was run again, and it still could not load ${stillNotLoaded.join(" and ")}: this answer is from an import without ${stillNotLoaded.length === 1 ? "it" : "them"}, and its messages say what the engine hit.`;
|
|
8425
|
-
return `The first import could not load ${libraries.join(" and ")}: on Windows an engine running as the editor ` + "loads a GDExtension from a ~ copy beside the library, and the editor open on this project holds its own " + "copy there, so the first engine started beside it cannot make one. That failed attempt moves the " + `editor's copy aside, ${second} The editor's copy is left beside the library as a ~RF….TMP file, which ` + "
|
|
8507
|
+
return `The first import could not load ${libraries.join(" and ")}: on Windows an engine running as the editor ` + "loads a GDExtension from a ~ copy beside the library, and the editor open on this project holds its own " + "copy there, so the first engine started beside it cannot make one. That failed attempt moves the " + `editor's copy aside, ${second} The editor's copy is left beside the library as a ~RF….TMP file, which ` + "the next import, export or editor this server starts on the project deletes once the editor has exited.";
|
|
8426
8508
|
}
|
|
8427
8509
|
async function runImport(godotPath, projectPath, options = {}) {
|
|
8428
8510
|
const once = options.once ?? importOnce;
|
|
@@ -8430,6 +8512,7 @@ async function runImport(godotPath, projectPath, options = {}) {
|
|
|
8430
8512
|
for (const target of options.forcing ?? []) {
|
|
8431
8513
|
forceNextImport(projectPath, target);
|
|
8432
8514
|
}
|
|
8515
|
+
freeLibraryCopies(projectPath);
|
|
8433
8516
|
return once(godotPath, projectPath);
|
|
8434
8517
|
};
|
|
8435
8518
|
const first = await pass();
|
|
@@ -8453,7 +8536,7 @@ async function importOnce(godotPath, projectPath) {
|
|
|
8453
8536
|
ran = await runEngine(godotPath, [
|
|
8454
8537
|
"--headless",
|
|
8455
8538
|
"--log-file",
|
|
8456
|
-
|
|
8539
|
+
join8(logDir, "engine.log"),
|
|
8457
8540
|
"--path",
|
|
8458
8541
|
projectPath,
|
|
8459
8542
|
"--import"
|
|
@@ -8473,13 +8556,13 @@ async function importOnce(godotPath, projectPath) {
|
|
|
8473
8556
|
}
|
|
8474
8557
|
async function runOperation(engine, operation, params, projectPath) {
|
|
8475
8558
|
const paramsDir = scratchDirectory("params");
|
|
8476
|
-
const paramsFile =
|
|
8477
|
-
const answerFile =
|
|
8559
|
+
const paramsFile = join8(paramsDir, `${operation}.json`);
|
|
8560
|
+
const answerFile = join8(paramsDir, "answer.json");
|
|
8478
8561
|
writeFileSync4(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
|
|
8479
8562
|
const args = [
|
|
8480
8563
|
"--headless",
|
|
8481
8564
|
"--log-file",
|
|
8482
|
-
|
|
8565
|
+
join8(paramsDir, "engine.log"),
|
|
8483
8566
|
"--path",
|
|
8484
8567
|
projectPath,
|
|
8485
8568
|
"--script",
|
|
@@ -8549,10 +8632,10 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
8549
8632
|
};
|
|
8550
8633
|
}
|
|
8551
8634
|
function answerIn(file) {
|
|
8552
|
-
if (!
|
|
8635
|
+
if (!existsSync8(file)) {
|
|
8553
8636
|
return { kind: "none" };
|
|
8554
8637
|
}
|
|
8555
|
-
const text =
|
|
8638
|
+
const text = readFileSync5(file, "utf8");
|
|
8556
8639
|
try {
|
|
8557
8640
|
const parsed = JSON.parse(text);
|
|
8558
8641
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? { kind: "answer", payload: parsed } : { kind: "unreadable", why: `it is JSON but not an object: ${text.slice(0, 200)}` };
|
|
@@ -8566,14 +8649,15 @@ function answerIn(file) {
|
|
|
8566
8649
|
var AFTER_ANSWER_NOTE = "Printed after this operation had written its answer, while the engine ran the project's autoloads and shut down: Godot starts a project's autoloads in every script run and cannot be told not to. An error raised in a project script here is that autoload's own, and none of these changes the answer.", OWN_ERROR = "[ERROR] ", ANSWERED = "[gdharness] answered", MESSAGES_KEPT = 200, ERRORS_NAMED = 3;
|
|
8567
8650
|
var init_headless = __esm(() => {
|
|
8568
8651
|
init_engine_run();
|
|
8652
|
+
init_library_copies();
|
|
8569
8653
|
init_reimport();
|
|
8570
8654
|
init_scratch();
|
|
8571
8655
|
});
|
|
8572
8656
|
|
|
8573
8657
|
// src/update-check.ts
|
|
8574
|
-
import { existsSync as
|
|
8658
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
8575
8659
|
import { homedir as homedir3, tmpdir as tmpdir3 } from "node:os";
|
|
8576
|
-
import { join as
|
|
8660
|
+
import { join as join9 } from "node:path";
|
|
8577
8661
|
function packageUrl(root) {
|
|
8578
8662
|
return `${root.replace(/\/+$/, "")}/gdharness/latest`;
|
|
8579
8663
|
}
|
|
@@ -8595,28 +8679,28 @@ function cacheDirectory(environment) {
|
|
|
8595
8679
|
};
|
|
8596
8680
|
const home = set("HOME") ?? homedir3();
|
|
8597
8681
|
if (process.platform === "win32") {
|
|
8598
|
-
return
|
|
8682
|
+
return join9(set("LOCALAPPDATA") ?? home, "gdharness");
|
|
8599
8683
|
}
|
|
8600
8684
|
if (process.platform === "darwin") {
|
|
8601
|
-
return
|
|
8685
|
+
return join9(home, "Library", "Caches", "gdharness");
|
|
8602
8686
|
}
|
|
8603
|
-
return
|
|
8687
|
+
return join9(set("XDG_CACHE_HOME") ?? join9(home, ".cache"), "gdharness");
|
|
8604
8688
|
}
|
|
8605
8689
|
function cacheFile(environment = process.env) {
|
|
8606
8690
|
try {
|
|
8607
8691
|
const directory = cacheDirectory(environment);
|
|
8608
8692
|
mkdirSync3(directory, { recursive: true, mode: 448 });
|
|
8609
|
-
return
|
|
8693
|
+
return join9(directory, "update-check.json");
|
|
8610
8694
|
} catch {
|
|
8611
|
-
return
|
|
8695
|
+
return join9(tmpdir3(), "gdharness-update-check.json");
|
|
8612
8696
|
}
|
|
8613
8697
|
}
|
|
8614
8698
|
function readCache(path) {
|
|
8615
8699
|
try {
|
|
8616
|
-
if (!
|
|
8700
|
+
if (!existsSync9(path)) {
|
|
8617
8701
|
return null;
|
|
8618
8702
|
}
|
|
8619
|
-
const parsed = JSON.parse(
|
|
8703
|
+
const parsed = JSON.parse(readFileSync6(path, "utf8"));
|
|
8620
8704
|
if (typeof parsed !== "object" || parsed === null) {
|
|
8621
8705
|
return null;
|
|
8622
8706
|
}
|
|
@@ -8764,7 +8848,7 @@ var init_update_check = __esm(() => {
|
|
|
8764
8848
|
});
|
|
8765
8849
|
|
|
8766
8850
|
// src/server-version.ts
|
|
8767
|
-
import { readFileSync as
|
|
8851
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
8768
8852
|
function editorIsStale(addonVersion, serverVersion, addonDigest, shippedDigest) {
|
|
8769
8853
|
if (addonDigest !== undefined && addonDigest !== "" && shippedDigest !== undefined) {
|
|
8770
8854
|
return addonDigest !== shippedDigest;
|
|
@@ -8835,7 +8919,7 @@ var init_server_version = __esm(() => {
|
|
|
8835
8919
|
GODOT_DEBUG_MODE_DEFAULT = process.env["GODOT_DEBUG"] === "true" || DEBUG_MODE;
|
|
8836
8920
|
SERVER_VERSION = (() => {
|
|
8837
8921
|
try {
|
|
8838
|
-
const pkg = JSON.parse(
|
|
8922
|
+
const pkg = JSON.parse(readFileSync7(new URL("../package.json", import.meta.url), "utf8"));
|
|
8839
8923
|
return typeof pkg.version === "string" ? pkg.version : "0.0.0";
|
|
8840
8924
|
} catch {
|
|
8841
8925
|
return "0.0.0";
|
|
@@ -9620,8 +9704,8 @@ var init_gdscript_source = __esm(() => {
|
|
|
9620
9704
|
});
|
|
9621
9705
|
|
|
9622
9706
|
// src/class-cache.ts
|
|
9623
|
-
import { existsSync as
|
|
9624
|
-
import { join as
|
|
9707
|
+
import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
|
|
9708
|
+
import { join as join10, posix } from "node:path";
|
|
9625
9709
|
function isToolScript(source) {
|
|
9626
9710
|
return TOOL.test(codeOf(source));
|
|
9627
9711
|
}
|
|
@@ -9637,18 +9721,18 @@ function declaredClasses(projectPath) {
|
|
|
9637
9721
|
}
|
|
9638
9722
|
function eachScript(projectPath, each) {
|
|
9639
9723
|
const visit = (directory, prefix) => {
|
|
9640
|
-
if (
|
|
9724
|
+
if (existsSync10(join10(directory, ".gdignore"))) {
|
|
9641
9725
|
return;
|
|
9642
9726
|
}
|
|
9643
|
-
for (const entry of
|
|
9727
|
+
for (const entry of readdirSync5(directory, { withFileTypes: true })) {
|
|
9644
9728
|
if (entry.name.startsWith(".")) {
|
|
9645
9729
|
continue;
|
|
9646
9730
|
}
|
|
9647
|
-
const path =
|
|
9731
|
+
const path = join10(directory, entry.name);
|
|
9648
9732
|
if (entry.isDirectory()) {
|
|
9649
9733
|
visit(path, `${prefix}${entry.name}/`);
|
|
9650
9734
|
} else if (entry.isFile() && entry.name.endsWith(".gd")) {
|
|
9651
|
-
each(`res://${prefix}${entry.name}`,
|
|
9735
|
+
each(`res://${prefix}${entry.name}`, readFileSync8(path, "utf8"));
|
|
9652
9736
|
}
|
|
9653
9737
|
}
|
|
9654
9738
|
};
|
|
@@ -9670,12 +9754,12 @@ function scriptsNaming(projectPath, classes) {
|
|
|
9670
9754
|
return naming.sort((a, b) => a.script.localeCompare(b.script));
|
|
9671
9755
|
}
|
|
9672
9756
|
function cachedClasses(projectPath) {
|
|
9673
|
-
const cache =
|
|
9674
|
-
if (!
|
|
9757
|
+
const cache = join10(projectPath, ".godot", "global_script_class_cache.cfg");
|
|
9758
|
+
if (!existsSync10(cache)) {
|
|
9675
9759
|
return null;
|
|
9676
9760
|
}
|
|
9677
9761
|
const listed = new Map;
|
|
9678
|
-
const text =
|
|
9762
|
+
const text = readFileSync8(cache, "utf8");
|
|
9679
9763
|
for (const entry of text.matchAll(/"class":\s*&"([^"]+)"[\s\S]*?"path":\s*"([^"]+)"/g)) {
|
|
9680
9764
|
listed.set(entry[1] ?? "", entry[2] ?? "");
|
|
9681
9765
|
}
|
|
@@ -9941,7 +10025,7 @@ function uncachedClassNote(types) {
|
|
|
9941
10025
|
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.";
|
|
9942
10026
|
}
|
|
9943
10027
|
function cacheWrittenAt(projectPath) {
|
|
9944
|
-
const cache =
|
|
10028
|
+
const cache = join10(projectPath, ".godot", "global_script_class_cache.cfg");
|
|
9945
10029
|
try {
|
|
9946
10030
|
return statSync4(cache).mtimeMs;
|
|
9947
10031
|
} catch {
|
|
@@ -9955,14 +10039,14 @@ function declaredSince(projectPath, paths, names, since) {
|
|
|
9955
10039
|
return false;
|
|
9956
10040
|
}
|
|
9957
10041
|
try {
|
|
9958
|
-
return statSync4(
|
|
10042
|
+
return statSync4(join10(projectPath, path.slice("res://".length))).mtimeMs > since;
|
|
9959
10043
|
} catch {
|
|
9960
10044
|
return false;
|
|
9961
10045
|
}
|
|
9962
10046
|
});
|
|
9963
10047
|
}
|
|
9964
10048
|
function cachedAtMissingPaths(cached, projectPath) {
|
|
9965
|
-
return [...cached].filter(([, path]) => path.startsWith("res://") && !
|
|
10049
|
+
return [...cached].filter(([, path]) => path.startsWith("res://") && !existsSync10(join10(projectPath, path.slice("res://".length)))).map(([name]) => name).sort();
|
|
9966
10050
|
}
|
|
9967
10051
|
function staleAgainst(cached, projectPath) {
|
|
9968
10052
|
return [...declaredClasses(projectPath)].filter(([name, path]) => cached.get(name) !== path).map(([name]) => name);
|
|
@@ -9987,8 +10071,8 @@ var init_class_cache = __esm(() => {
|
|
|
9987
10071
|
});
|
|
9988
10072
|
|
|
9989
10073
|
// src/project-scan.ts
|
|
9990
|
-
import { existsSync as
|
|
9991
|
-
import { extname, join as
|
|
10074
|
+
import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync9 } from "node:fs";
|
|
10075
|
+
import { extname, join as join11 } from "node:path";
|
|
9992
10076
|
function skipped(name) {
|
|
9993
10077
|
return name.startsWith(".") || SKIPPED.has(name);
|
|
9994
10078
|
}
|
|
@@ -9996,10 +10080,10 @@ function steppedOver(directory) {
|
|
|
9996
10080
|
return gdignored(directory) || installedByUs(directory);
|
|
9997
10081
|
}
|
|
9998
10082
|
function gdignored(directory) {
|
|
9999
|
-
return
|
|
10083
|
+
return existsSync11(join11(directory, ".gdignore"));
|
|
10000
10084
|
}
|
|
10001
10085
|
function installedByUs(directory) {
|
|
10002
|
-
return
|
|
10086
|
+
return existsSync11(join11(directory, VERSION_MARKER));
|
|
10003
10087
|
}
|
|
10004
10088
|
function projectStructure(projectPath) {
|
|
10005
10089
|
const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
|
|
@@ -10007,12 +10091,12 @@ function projectStructure(projectPath) {
|
|
|
10007
10091
|
if (steppedOver(directory)) {
|
|
10008
10092
|
return;
|
|
10009
10093
|
}
|
|
10010
|
-
for (const entry of
|
|
10094
|
+
for (const entry of readdirSync6(directory, { withFileTypes: true })) {
|
|
10011
10095
|
if (skipped(entry.name)) {
|
|
10012
10096
|
continue;
|
|
10013
10097
|
}
|
|
10014
10098
|
if (entry.isDirectory()) {
|
|
10015
|
-
visit(
|
|
10099
|
+
visit(join11(directory, entry.name));
|
|
10016
10100
|
} else if (entry.isFile()) {
|
|
10017
10101
|
const extension = entry.name.split(".").pop()?.toLowerCase() ?? "";
|
|
10018
10102
|
if (SCENE_EXTENSIONS.has(extension)) {
|
|
@@ -10036,13 +10120,13 @@ function projectFiles(projectPath, extensions) {
|
|
|
10036
10120
|
if (steppedOver(directory)) {
|
|
10037
10121
|
return;
|
|
10038
10122
|
}
|
|
10039
|
-
for (const entry of
|
|
10123
|
+
for (const entry of readdirSync6(directory, { withFileTypes: true })) {
|
|
10040
10124
|
if (skipped(entry.name)) {
|
|
10041
10125
|
continue;
|
|
10042
10126
|
}
|
|
10043
10127
|
const spelled = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
|
|
10044
10128
|
if (entry.isDirectory()) {
|
|
10045
|
-
visit(
|
|
10129
|
+
visit(join11(directory, entry.name), spelled);
|
|
10046
10130
|
} else if (entry.isFile() && extensions.includes(extname(entry.name).toLowerCase())) {
|
|
10047
10131
|
found.push(spelled);
|
|
10048
10132
|
}
|
|
@@ -10057,20 +10141,20 @@ function scriptsWithoutUid(projectPath) {
|
|
|
10057
10141
|
if (steppedOver(directory)) {
|
|
10058
10142
|
return;
|
|
10059
10143
|
}
|
|
10060
|
-
for (const entry of
|
|
10144
|
+
for (const entry of readdirSync6(directory, { withFileTypes: true })) {
|
|
10061
10145
|
if (skipped(entry.name)) {
|
|
10062
10146
|
continue;
|
|
10063
10147
|
}
|
|
10064
10148
|
const spelled = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
|
|
10065
10149
|
if (entry.isDirectory()) {
|
|
10066
|
-
visit(
|
|
10150
|
+
visit(join11(directory, entry.name), spelled);
|
|
10067
10151
|
continue;
|
|
10068
10152
|
}
|
|
10069
10153
|
if (!entry.isFile()) {
|
|
10070
10154
|
continue;
|
|
10071
10155
|
}
|
|
10072
10156
|
const extension = entry.name.split(".").pop()?.toLowerCase() ?? "";
|
|
10073
|
-
if (CARRIES_A_UID.has(extension) && !
|
|
10157
|
+
if (CARRIES_A_UID.has(extension) && !existsSync11(join11(directory, `${entry.name}.uid`))) {
|
|
10074
10158
|
found.push(spelled);
|
|
10075
10159
|
}
|
|
10076
10160
|
}
|
|
@@ -10087,11 +10171,11 @@ function projectTexts(projectPath) {
|
|
|
10087
10171
|
if (steppedOver(directory)) {
|
|
10088
10172
|
return;
|
|
10089
10173
|
}
|
|
10090
|
-
for (const entry of
|
|
10174
|
+
for (const entry of readdirSync6(directory, { withFileTypes: true })) {
|
|
10091
10175
|
if (skipped(entry.name)) {
|
|
10092
10176
|
continue;
|
|
10093
10177
|
}
|
|
10094
|
-
const absolute =
|
|
10178
|
+
const absolute = join11(directory, entry.name);
|
|
10095
10179
|
const spelled = `${prefix}${entry.name}`;
|
|
10096
10180
|
if (entry.isDirectory()) {
|
|
10097
10181
|
visit(absolute, `${spelled}/`);
|
|
@@ -10101,7 +10185,7 @@ function projectTexts(projectPath) {
|
|
|
10101
10185
|
if (!entry.isFile() || BINARY_EXTENSIONS.has(extension)) {
|
|
10102
10186
|
continue;
|
|
10103
10187
|
}
|
|
10104
|
-
const bytes =
|
|
10188
|
+
const bytes = readFileSync9(absolute);
|
|
10105
10189
|
if (!isBinary(bytes)) {
|
|
10106
10190
|
found.push({ path: `res://${spelled}`, absolute, text: bytes.toString("utf8") });
|
|
10107
10191
|
}
|
|
@@ -10117,11 +10201,11 @@ function ignoredTexts(projectPath) {
|
|
|
10117
10201
|
return;
|
|
10118
10202
|
}
|
|
10119
10203
|
const under = ignored || gdignored(directory);
|
|
10120
|
-
for (const entry of
|
|
10204
|
+
for (const entry of readdirSync6(directory, { withFileTypes: true })) {
|
|
10121
10205
|
if (skipped(entry.name)) {
|
|
10122
10206
|
continue;
|
|
10123
10207
|
}
|
|
10124
|
-
const absolute =
|
|
10208
|
+
const absolute = join11(directory, entry.name);
|
|
10125
10209
|
const spelled = `${prefix}${entry.name}`;
|
|
10126
10210
|
if (entry.isDirectory()) {
|
|
10127
10211
|
visit(absolute, `${spelled}/`, under);
|
|
@@ -10131,7 +10215,7 @@ function ignoredTexts(projectPath) {
|
|
|
10131
10215
|
if (!under || !entry.isFile() || BINARY_EXTENSIONS.has(extension) || entry.name === ".gdignore") {
|
|
10132
10216
|
continue;
|
|
10133
10217
|
}
|
|
10134
|
-
const bytes =
|
|
10218
|
+
const bytes = readFileSync9(absolute);
|
|
10135
10219
|
if (!isBinary(bytes)) {
|
|
10136
10220
|
found.push({ path: `res://${spelled}`, absolute, text: bytes.toString("utf8") });
|
|
10137
10221
|
}
|
|
@@ -10154,14 +10238,14 @@ function searchProject(projectPath, options) {
|
|
|
10154
10238
|
if (steppedOver(directory)) {
|
|
10155
10239
|
return;
|
|
10156
10240
|
}
|
|
10157
|
-
for (const entry of
|
|
10241
|
+
for (const entry of readdirSync6(directory, { withFileTypes: true })) {
|
|
10158
10242
|
if (full()) {
|
|
10159
10243
|
return;
|
|
10160
10244
|
}
|
|
10161
10245
|
if (skipped(entry.name)) {
|
|
10162
10246
|
continue;
|
|
10163
10247
|
}
|
|
10164
|
-
const entryPath =
|
|
10248
|
+
const entryPath = join11(directory, entry.name);
|
|
10165
10249
|
if (entry.isDirectory()) {
|
|
10166
10250
|
visit(entryPath);
|
|
10167
10251
|
continue;
|
|
@@ -10170,7 +10254,7 @@ function searchProject(projectPath, options) {
|
|
|
10170
10254
|
if (!entry.isFile() || extensions !== null && !extensions.has(extension)) {
|
|
10171
10255
|
continue;
|
|
10172
10256
|
}
|
|
10173
|
-
const bytes =
|
|
10257
|
+
const bytes = readFileSync9(entryPath);
|
|
10174
10258
|
if (extensions === null && isBinary(bytes)) {
|
|
10175
10259
|
continue;
|
|
10176
10260
|
}
|
|
@@ -10257,7 +10341,7 @@ var init_answer_json = __esm(() => {
|
|
|
10257
10341
|
});
|
|
10258
10342
|
|
|
10259
10343
|
// src/resources.ts
|
|
10260
|
-
import { readFileSync as
|
|
10344
|
+
import { readFileSync as readFileSync10, realpathSync as realpathSync3 } from "node:fs";
|
|
10261
10345
|
import { extname as extname2, resolve as resolve3 } from "node:path";
|
|
10262
10346
|
function ensureProjectPath(getProjectPath) {
|
|
10263
10347
|
const projectPath = getProjectPath();
|
|
@@ -10453,7 +10537,7 @@ function readResourceText(uri, getProjectPath) {
|
|
|
10453
10537
|
const parsedUri = parseGodotUri(uri);
|
|
10454
10538
|
if (parsedUri.kind === "project-info") {
|
|
10455
10539
|
const projectFilePath = resolveProjectFile(projectPath, "project.godot");
|
|
10456
|
-
const rawProject =
|
|
10540
|
+
const rawProject = readFileSync10(projectFilePath, "utf-8");
|
|
10457
10541
|
const parsedProject = parseProjectGodot(rawProject);
|
|
10458
10542
|
return {
|
|
10459
10543
|
mimeType: "application/json",
|
|
@@ -10462,7 +10546,7 @@ function readResourceText(uri, getProjectPath) {
|
|
|
10462
10546
|
}
|
|
10463
10547
|
const filePath = resolveProjectFile(projectPath, parsedUri.resourcePath);
|
|
10464
10548
|
ensureAllowedExtension(parsedUri.kind, filePath);
|
|
10465
|
-
const text =
|
|
10549
|
+
const text = readFileSync10(filePath, "utf-8");
|
|
10466
10550
|
return {
|
|
10467
10551
|
mimeType: parsedUri.kind === "script" ? "text/x-gdscript" : "text/plain",
|
|
10468
10552
|
text
|
|
@@ -10607,16 +10691,16 @@ import { spawnSync } from "node:child_process";
|
|
|
10607
10691
|
import { createHash as createHash3 } from "node:crypto";
|
|
10608
10692
|
import {
|
|
10609
10693
|
cpSync,
|
|
10610
|
-
existsSync as
|
|
10694
|
+
existsSync as existsSync12,
|
|
10611
10695
|
mkdirSync as mkdirSync4,
|
|
10612
|
-
readdirSync as
|
|
10613
|
-
readFileSync as
|
|
10696
|
+
readdirSync as readdirSync7,
|
|
10697
|
+
readFileSync as readFileSync11,
|
|
10614
10698
|
rmdirSync,
|
|
10615
10699
|
rmSync as rmSync5,
|
|
10616
10700
|
statSync as statSync5,
|
|
10617
10701
|
writeFileSync as writeFileSync6
|
|
10618
10702
|
} from "node:fs";
|
|
10619
|
-
import { dirname as
|
|
10703
|
+
import { dirname as dirname6, join as join12 } from "node:path";
|
|
10620
10704
|
import { fileURLToPath } from "node:url";
|
|
10621
10705
|
function editorAddonDigest(from = shippedAddonsDirectory()) {
|
|
10622
10706
|
return addonsDigest(EDITOR_PLUGINS, from);
|
|
@@ -10627,25 +10711,25 @@ function runtimeAddonDigest(from = shippedAddonsDirectory()) {
|
|
|
10627
10711
|
function addonsDigest(names, from) {
|
|
10628
10712
|
const hash = createHash3("sha256");
|
|
10629
10713
|
const walk = (directory, relative) => {
|
|
10630
|
-
for (const name of
|
|
10714
|
+
for (const name of readdirSync7(directory).sort()) {
|
|
10631
10715
|
if (name === VERSION_MARKER || name === DIGEST_MARKER) {
|
|
10632
10716
|
continue;
|
|
10633
10717
|
}
|
|
10634
|
-
const path =
|
|
10718
|
+
const path = join12(directory, name);
|
|
10635
10719
|
const inside = `${relative}/${name}`;
|
|
10636
10720
|
if (statSync5(path).isDirectory()) {
|
|
10637
10721
|
walk(path, inside);
|
|
10638
10722
|
} else {
|
|
10639
10723
|
hash.update(`${inside}
|
|
10640
10724
|
`);
|
|
10641
|
-
hash.update(
|
|
10725
|
+
hash.update(readFileSync11(path));
|
|
10642
10726
|
hash.update(`
|
|
10643
10727
|
`);
|
|
10644
10728
|
}
|
|
10645
10729
|
}
|
|
10646
10730
|
};
|
|
10647
10731
|
for (const name of names) {
|
|
10648
|
-
walk(
|
|
10732
|
+
walk(join12(from, name), name);
|
|
10649
10733
|
}
|
|
10650
10734
|
return hash.digest("hex");
|
|
10651
10735
|
}
|
|
@@ -10676,60 +10760,60 @@ function installedRuntimeDigest(projectPath) {
|
|
|
10676
10760
|
return digestMarker(projectPath, RUNTIME_ADDON);
|
|
10677
10761
|
}
|
|
10678
10762
|
function digestMarker(projectPath, addon) {
|
|
10679
|
-
const marker =
|
|
10680
|
-
if (!
|
|
10763
|
+
const marker = join12(projectPath, "addons", addon, DIGEST_MARKER);
|
|
10764
|
+
if (!existsSync12(marker)) {
|
|
10681
10765
|
return null;
|
|
10682
10766
|
}
|
|
10683
|
-
const said =
|
|
10767
|
+
const said = readFileSync11(marker, "utf8").trim();
|
|
10684
10768
|
return said === "" ? null : said;
|
|
10685
10769
|
}
|
|
10686
10770
|
function shippedAddonsDirectory() {
|
|
10687
|
-
return
|
|
10771
|
+
return join12(dirname6(fileURLToPath(import.meta.url)), "godot", "addons");
|
|
10688
10772
|
}
|
|
10689
10773
|
function shippedOperationsScript() {
|
|
10690
|
-
return
|
|
10774
|
+
return join12(dirname6(fileURLToPath(import.meta.url)), "godot", "operations", "godot_operations.gd");
|
|
10691
10775
|
}
|
|
10692
10776
|
function installAddons(projectPath, from = shippedAddonsDirectory()) {
|
|
10693
10777
|
const installed = [];
|
|
10694
10778
|
for (const name of ADDONS) {
|
|
10695
|
-
const source =
|
|
10696
|
-
if (!
|
|
10779
|
+
const source = join12(from, name);
|
|
10780
|
+
if (!existsSync12(join12(source, name === RUNTIME_ADDON ? "runtime_autoload.gd" : "plugin.cfg"))) {
|
|
10697
10781
|
throw new Error(`The package holds no ${name} addon at ${source}.`);
|
|
10698
10782
|
}
|
|
10699
|
-
const target =
|
|
10700
|
-
const replaced =
|
|
10783
|
+
const target = join12(projectPath, "addons", name);
|
|
10784
|
+
const replaced = existsSync12(target);
|
|
10701
10785
|
rmSync5(target, { recursive: true, force: true });
|
|
10702
|
-
mkdirSync4(
|
|
10786
|
+
mkdirSync4(dirname6(target), { recursive: true });
|
|
10703
10787
|
cpSync(source, target, { recursive: true });
|
|
10704
|
-
writeFileSync6(
|
|
10788
|
+
writeFileSync6(join12(target, VERSION_MARKER), `${SERVER_VERSION}
|
|
10705
10789
|
`);
|
|
10706
10790
|
installed.push({ name, path: target, replaced });
|
|
10707
10791
|
}
|
|
10708
|
-
writeFileSync6(
|
|
10792
|
+
writeFileSync6(join12(projectPath, "addons", ADDONS[0], DIGEST_MARKER), `${editorAddonDigest(from)}
|
|
10709
10793
|
`);
|
|
10710
|
-
writeFileSync6(
|
|
10794
|
+
writeFileSync6(join12(projectPath, "addons", RUNTIME_ADDON, DIGEST_MARKER), `${runtimeAddonDigest(from)}
|
|
10711
10795
|
`);
|
|
10712
10796
|
return installed;
|
|
10713
10797
|
}
|
|
10714
10798
|
function installedAddonVersion(projectPath) {
|
|
10715
|
-
const marker =
|
|
10716
|
-
if (!
|
|
10799
|
+
const marker = join12(projectPath, "addons", ADDONS[0], VERSION_MARKER);
|
|
10800
|
+
if (!existsSync12(marker)) {
|
|
10717
10801
|
return null;
|
|
10718
10802
|
}
|
|
10719
|
-
const said =
|
|
10803
|
+
const said = readFileSync11(marker, "utf8").trim();
|
|
10720
10804
|
return said === "" ? null : said;
|
|
10721
10805
|
}
|
|
10722
10806
|
function removeAddons(projectPath) {
|
|
10723
10807
|
const removed = [];
|
|
10724
10808
|
for (const name of ADDONS) {
|
|
10725
|
-
const target =
|
|
10726
|
-
if (
|
|
10809
|
+
const target = join12(projectPath, "addons", name);
|
|
10810
|
+
if (existsSync12(target)) {
|
|
10727
10811
|
rmSync5(target, { recursive: true, force: true });
|
|
10728
10812
|
removed.push(target);
|
|
10729
10813
|
}
|
|
10730
10814
|
}
|
|
10731
|
-
const addons =
|
|
10732
|
-
if (removed.length > 0 &&
|
|
10815
|
+
const addons = join12(projectPath, "addons");
|
|
10816
|
+
if (removed.length > 0 && existsSync12(addons) && readdirSync7(addons).length === 0) {
|
|
10733
10817
|
rmdirSync(addons);
|
|
10734
10818
|
removed.push(addons);
|
|
10735
10819
|
}
|
|
@@ -10763,7 +10847,7 @@ function loaderAmong(projectPath, named) {
|
|
|
10763
10847
|
}
|
|
10764
10848
|
let source = null;
|
|
10765
10849
|
try {
|
|
10766
|
-
source =
|
|
10850
|
+
source = readFileSync11(join12(projectPath, path), "utf8");
|
|
10767
10851
|
} catch {}
|
|
10768
10852
|
if (source?.includes(RUNTIME_AUTOLOAD.path)) {
|
|
10769
10853
|
return { name: entry, path, exists: true };
|
|
@@ -10805,10 +10889,10 @@ function enabledPlugins(settings) {
|
|
|
10805
10889
|
function inspectProject(projectPath) {
|
|
10806
10890
|
const problems = [];
|
|
10807
10891
|
const addons = ADDONS.map((name) => {
|
|
10808
|
-
const directory =
|
|
10809
|
-
const marker =
|
|
10810
|
-
const installed =
|
|
10811
|
-
const version =
|
|
10892
|
+
const directory = join12(projectPath, "addons", name);
|
|
10893
|
+
const marker = join12(directory, VERSION_MARKER);
|
|
10894
|
+
const installed = existsSync12(directory);
|
|
10895
|
+
const version = existsSync12(marker) ? readFileSync11(marker, "utf8").trim() : null;
|
|
10812
10896
|
const current = version === SERVER_VERSION;
|
|
10813
10897
|
if (!installed) {
|
|
10814
10898
|
problems.push(`addons/${name} is not installed; run gdharness setup`);
|
|
@@ -10817,7 +10901,7 @@ function inspectProject(projectPath) {
|
|
|
10817
10901
|
}
|
|
10818
10902
|
return { name, installed, version, current };
|
|
10819
10903
|
});
|
|
10820
|
-
const settings = parseProjectGodot(
|
|
10904
|
+
const settings = parseProjectGodot(readFileSync11(join12(projectPath, "project.godot"), "utf8"));
|
|
10821
10905
|
const pluginsEnabled = enabledPlugins(settings);
|
|
10822
10906
|
for (const name of EDITOR_PLUGINS) {
|
|
10823
10907
|
if (!pluginsEnabled.includes(name)) {
|
|
@@ -10833,7 +10917,7 @@ function inspectProject(projectPath) {
|
|
|
10833
10917
|
const tracked = trackedByGit(projectPath, [...named.values()]);
|
|
10834
10918
|
const addonMissing = (path) => addons.some((addon) => !addon.installed && path.startsWith(`addons/${addon.name}/`));
|
|
10835
10919
|
for (const [name, path] of named) {
|
|
10836
|
-
if (!
|
|
10920
|
+
if (!existsSync12(join12(projectPath, path))) {
|
|
10837
10921
|
if (!addonMissing(path)) {
|
|
10838
10922
|
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`);
|
|
10839
10923
|
}
|
|
@@ -12241,12 +12325,12 @@ var init_tool_definitions = __esm(() => {
|
|
|
12241
12325
|
},
|
|
12242
12326
|
metrics: {
|
|
12243
12327
|
effect: "read",
|
|
12244
|
-
summary: "frame time, memory, draw calls and the rest. frame_time is the mean wall time of a frame over the last frames_timed frames (up to 120, timed by the game itself, physics and the wait for the display included), frame_time_max the slowest of them, both in seconds and null before a frame has passed; vsync says whether a frame waits for the display, and max_fps is the game's frame-rate cap, 0 for none. fps, process_time_max and physics_time are the engine's monitors, which it sets once a second: the frames counted in the last second, and the slowest process and physics step in it, so they trail a change by up to a second and the last two are a worst case rather than the frame. The memory, object and render counts are read as asked. memory_static is what the engine allocated on the CPU side, in bytes; render_video_mem_used, render_texture_mem_used and render_buffer_mem_used are what the renderer has on the GPU, in bytes, which memory_static does not count",
|
|
12328
|
+
summary: "frame time, memory, draw calls and the rest. frame_time is the mean wall time of a frame over the last frames_timed frames (up to 120, timed by the game itself, physics and the wait for the display included), frame_time_max the slowest of them, both in seconds and null before a frame has passed; vsync says whether a frame waits for the display, and max_fps is the game's frame-rate cap, 0 for none. physics_steps_per_second is the physics steps taken a second over those frames, fewer than physics_ticks_per_second when a frame needs more than max_physics_steps_per_frame or the editor's Game view slows it. fps, process_time_max and physics_time are the engine's monitors, which it sets once a second: the frames counted in the last second, and the slowest process and physics step in it, so they trail a change by up to a second and the last two are a worst case rather than the frame. The memory, object and render counts are read as asked. memory_static is what the engine allocated on the CPU side, in bytes; render_video_mem_used, render_texture_mem_used and render_buffer_mem_used are what the renderer has on the GPU, in bytes, which memory_static does not count",
|
|
12245
12329
|
requires: []
|
|
12246
12330
|
},
|
|
12247
12331
|
accessibility: {
|
|
12248
12332
|
effect: "read",
|
|
12249
|
-
summary:
|
|
12333
|
+
summary: "what the game tells a screen reader, read through UI Automation as a Windows screen reader reads it, under windows: one tree per window, each element with its role (text for static text, button, check_box, group for a control holding others), name, value, description, placeholder, bounds in the window's pixels, the actions a reader is offered (click, focus, toggle, set_value, select, expand_collapse, scroll_into_view), and focused on the one with the focus. node is the path of the node that made the element; an element a node made as a part of itself has part_of instead, and part: announcement marks the text a window speaks announcements through. An empty name is read as nothing: static text takes it from accessibility_update_set_value, and _note counts the text elements on screen with none. tooltip is the node's tooltip_text, which a Windows reader is not told. With no control focused, the engine reports the first node under the root, GdharnessRuntime, as focused. Needs a windowed run on Windows started with engineArgs [\"--accessibility\", \"always\"] or accessibility_support at Always Active, since the engine builds the tree only when asked; reading takes a second or two",
|
|
12250
12334
|
requires: []
|
|
12251
12335
|
}
|
|
12252
12336
|
},
|
|
@@ -34422,10 +34506,10 @@ var init_stdio = __esm(() => {
|
|
|
34422
34506
|
});
|
|
34423
34507
|
|
|
34424
34508
|
// src/runtime-client.ts
|
|
34425
|
-
import { existsSync as
|
|
34509
|
+
import { existsSync as existsSync14, readdirSync as readdirSync9, readFileSync as readFileSync13, statSync as statSync6, unlinkSync as unlinkSync2 } from "node:fs";
|
|
34426
34510
|
import { createConnection } from "node:net";
|
|
34427
34511
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
34428
|
-
import { dirname as
|
|
34512
|
+
import { dirname as dirname9, join as join15, resolve as resolve4 } from "node:path";
|
|
34429
34513
|
import { setTimeout as delay } from "node:timers/promises";
|
|
34430
34514
|
function runtimeDirectory(variables = process.env) {
|
|
34431
34515
|
const explicit = envValue("GDHARNESS_RUNTIME_DIR", variables);
|
|
@@ -34433,20 +34517,20 @@ function runtimeDirectory(variables = process.env) {
|
|
|
34433
34517
|
return explicit;
|
|
34434
34518
|
}
|
|
34435
34519
|
const perUser = envValue("XDG_RUNTIME_DIR", variables);
|
|
34436
|
-
return
|
|
34520
|
+
return join15(perUser ?? tmpdir4(), "gdharness");
|
|
34437
34521
|
}
|
|
34438
34522
|
function runtimeDirectories(variables = process.env) {
|
|
34439
34523
|
const candidates = [runtimeDirectory(variables)];
|
|
34440
34524
|
const fallbacks = process.platform === "win32" ? [envValue("SystemRoot", variables) ?? envValue("windir", variables) ?? "C:\\Windows"] : ["/tmp", "/var/tmp"];
|
|
34441
34525
|
for (const base of fallbacks) {
|
|
34442
|
-
candidates.push(
|
|
34526
|
+
candidates.push(join15(base, process.platform === "win32" ? "Temp" : "", "gdharness"));
|
|
34443
34527
|
}
|
|
34444
34528
|
return [...new Set(candidates.map((path) => resolve4(path)))];
|
|
34445
34529
|
}
|
|
34446
34530
|
function errorReportOf(pid, directories = runtimeDirectories()) {
|
|
34447
34531
|
for (const directory of directories) {
|
|
34448
|
-
const path =
|
|
34449
|
-
if (
|
|
34532
|
+
const path = join15(directory, `runtime-${pid}.log`);
|
|
34533
|
+
if (existsSync14(path)) {
|
|
34450
34534
|
return path;
|
|
34451
34535
|
}
|
|
34452
34536
|
}
|
|
@@ -34477,7 +34561,7 @@ function reportAlreadyInTranscript(transcript, report) {
|
|
|
34477
34561
|
function parseAnnouncement(file, pid) {
|
|
34478
34562
|
let fields;
|
|
34479
34563
|
try {
|
|
34480
|
-
fields = asParams(JSON.parse(
|
|
34564
|
+
fields = asParams(JSON.parse(readFileSync13(file, "utf8")));
|
|
34481
34565
|
} catch {
|
|
34482
34566
|
return { kind: "rubbish" };
|
|
34483
34567
|
}
|
|
@@ -34543,7 +34627,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
|
|
|
34543
34627
|
function wentAway(file, pid) {
|
|
34544
34628
|
let project = "";
|
|
34545
34629
|
try {
|
|
34546
|
-
const fields = asParams(JSON.parse(
|
|
34630
|
+
const fields = asParams(JSON.parse(readFileSync13(file, "utf8")));
|
|
34547
34631
|
project = readString(readParams(fields, "project") ?? {}, "path") ?? "";
|
|
34548
34632
|
} catch {
|
|
34549
34633
|
return;
|
|
@@ -34586,23 +34670,23 @@ function strangersAmong(candidates, now, startTimes = startTimesOf) {
|
|
|
34586
34670
|
}).map((one) => one.file));
|
|
34587
34671
|
}
|
|
34588
34672
|
function announcedIn(directory) {
|
|
34589
|
-
if (!
|
|
34673
|
+
if (!existsSync14(directory)) {
|
|
34590
34674
|
return [];
|
|
34591
34675
|
}
|
|
34592
34676
|
const found = [];
|
|
34593
34677
|
const candidates = [];
|
|
34594
34678
|
const entries = [];
|
|
34595
|
-
for (const entry of
|
|
34679
|
+
for (const entry of readdirSync9(directory)) {
|
|
34596
34680
|
const report = ERROR_REPORT_PATTERN.exec(entry);
|
|
34597
34681
|
if (report) {
|
|
34598
|
-
sweepErrorReport(
|
|
34682
|
+
sweepErrorReport(join15(directory, entry), Number.parseInt(report[1] ?? "", 10));
|
|
34599
34683
|
continue;
|
|
34600
34684
|
}
|
|
34601
34685
|
const match = ANNOUNCEMENT_PATTERN.exec(entry);
|
|
34602
34686
|
if (!match) {
|
|
34603
34687
|
continue;
|
|
34604
34688
|
}
|
|
34605
|
-
const file =
|
|
34689
|
+
const file = join15(directory, entry);
|
|
34606
34690
|
const pid = Number.parseInt(match[1] ?? "", 10);
|
|
34607
34691
|
const running = alive(pid);
|
|
34608
34692
|
entries.push({ file, pid, running });
|
|
@@ -34622,7 +34706,7 @@ function announcedIn(directory) {
|
|
|
34622
34706
|
}
|
|
34623
34707
|
wentAway(file, pid);
|
|
34624
34708
|
try {
|
|
34625
|
-
|
|
34709
|
+
unlinkSync2(file);
|
|
34626
34710
|
} catch {}
|
|
34627
34711
|
verdicts.delete(file);
|
|
34628
34712
|
continue;
|
|
@@ -34630,16 +34714,16 @@ function announcedIn(directory) {
|
|
|
34630
34714
|
found.push(announced);
|
|
34631
34715
|
}
|
|
34632
34716
|
const held = new Set(entries.map((one) => one.file));
|
|
34633
|
-
const here =
|
|
34717
|
+
const here = join15(directory, ".");
|
|
34634
34718
|
for (const file of verdicts.keys()) {
|
|
34635
|
-
if (
|
|
34719
|
+
if (dirname9(file) === here && !held.has(file)) {
|
|
34636
34720
|
verdicts.delete(file);
|
|
34637
34721
|
}
|
|
34638
34722
|
}
|
|
34639
34723
|
return found;
|
|
34640
34724
|
}
|
|
34641
34725
|
async function announcementEnded(pid, directories = runtimeDirectories()) {
|
|
34642
|
-
const files = directories.map((directory) =>
|
|
34726
|
+
const files = directories.map((directory) => join15(directory, `runtime-${pid}.json`)).filter((file) => existsSync14(file));
|
|
34643
34727
|
const first = files[0];
|
|
34644
34728
|
if (first === undefined) {
|
|
34645
34729
|
return;
|
|
@@ -34655,7 +34739,7 @@ async function announcementEnded(pid, directories = runtimeDirectories()) {
|
|
|
34655
34739
|
wentAway(first, pid);
|
|
34656
34740
|
for (const file of files) {
|
|
34657
34741
|
try {
|
|
34658
|
-
|
|
34742
|
+
unlinkSync2(file);
|
|
34659
34743
|
} catch {}
|
|
34660
34744
|
verdicts.delete(file);
|
|
34661
34745
|
}
|
|
@@ -34666,7 +34750,7 @@ function sweepErrorReport(path, pid, now = Date.now()) {
|
|
|
34666
34750
|
}
|
|
34667
34751
|
try {
|
|
34668
34752
|
if (now - statSync6(path).mtimeMs >= ERROR_REPORT_KEEP_MS) {
|
|
34669
|
-
|
|
34753
|
+
unlinkSync2(path);
|
|
34670
34754
|
}
|
|
34671
34755
|
} catch {}
|
|
34672
34756
|
}
|
|
@@ -34940,14 +35024,14 @@ var init_runtime_client = __esm(() => {
|
|
|
34940
35024
|
});
|
|
34941
35025
|
|
|
34942
35026
|
// src/boot-note.ts
|
|
34943
|
-
import { mkdirSync as mkdirSync6, readFileSync as
|
|
34944
|
-
import { dirname as
|
|
35027
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "node:fs";
|
|
35028
|
+
import { dirname as dirname10, join as join16 } from "node:path";
|
|
34945
35029
|
function bootNotePath(projectPath) {
|
|
34946
|
-
return
|
|
35030
|
+
return join16(projectPath, ".godot", "gdharness-boot.json");
|
|
34947
35031
|
}
|
|
34948
35032
|
function readScenes(projectPath) {
|
|
34949
35033
|
try {
|
|
34950
|
-
return asParams(asParams(JSON.parse(
|
|
35034
|
+
return asParams(asParams(JSON.parse(readFileSync14(bootNotePath(projectPath), "utf8")))["scenes"]);
|
|
34951
35035
|
} catch {
|
|
34952
35036
|
return {};
|
|
34953
35037
|
}
|
|
@@ -34963,7 +35047,7 @@ function readBootNote(projectPath, scene) {
|
|
|
34963
35047
|
function writeBootNote(projectPath, scene, announcedAfterMs) {
|
|
34964
35048
|
try {
|
|
34965
35049
|
const path = bootNotePath(projectPath);
|
|
34966
|
-
mkdirSync6(
|
|
35050
|
+
mkdirSync6(dirname10(path), { recursive: true });
|
|
34967
35051
|
const scenes = {
|
|
34968
35052
|
...readScenes(projectPath),
|
|
34969
35053
|
[scene]: {
|
|
@@ -34989,10 +35073,10 @@ var init_boot_note = __esm(() => {
|
|
|
34989
35073
|
});
|
|
34990
35074
|
|
|
34991
35075
|
// src/breakpoint-note.ts
|
|
34992
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
34993
|
-
import { dirname as
|
|
35076
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync15, rmSync as rmSync7, writeFileSync as writeFileSync9 } from "node:fs";
|
|
35077
|
+
import { dirname as dirname11, isAbsolute as isAbsolute3, join as join17, relative as relative3 } from "node:path";
|
|
34994
35078
|
function breakpointNotePath(projectPath) {
|
|
34995
|
-
return
|
|
35079
|
+
return join17(projectPath, ".godot", "gdharness-breakpoints.json");
|
|
34996
35080
|
}
|
|
34997
35081
|
function writeBreakpointNote(projectPath, held) {
|
|
34998
35082
|
const path = breakpointNotePath(projectPath);
|
|
@@ -35009,7 +35093,7 @@ function writeBreakpointNote(projectPath, held) {
|
|
|
35009
35093
|
lines: [...one.lines]
|
|
35010
35094
|
}))
|
|
35011
35095
|
};
|
|
35012
|
-
mkdirSync7(
|
|
35096
|
+
mkdirSync7(dirname11(path), { recursive: true });
|
|
35013
35097
|
writeFileSync9(path, `${JSON.stringify(note, null, 2)}
|
|
35014
35098
|
`, "utf8");
|
|
35015
35099
|
} catch (error) {
|
|
@@ -35018,7 +35102,7 @@ function writeBreakpointNote(projectPath, held) {
|
|
|
35018
35102
|
}
|
|
35019
35103
|
function readBreakpointNote(projectPath) {
|
|
35020
35104
|
try {
|
|
35021
|
-
const parsed = JSON.parse(
|
|
35105
|
+
const parsed = JSON.parse(readFileSync15(breakpointNotePath(projectPath), "utf8"));
|
|
35022
35106
|
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.breakpoints)) {
|
|
35023
35107
|
return [];
|
|
35024
35108
|
}
|
|
@@ -35028,12 +35112,12 @@ function readBreakpointNote(projectPath) {
|
|
|
35028
35112
|
continue;
|
|
35029
35113
|
}
|
|
35030
35114
|
const { script, lines: listed } = entry;
|
|
35031
|
-
if (typeof script !== "string" ||
|
|
35115
|
+
if (typeof script !== "string" || isAbsolute3(script) || script.split("/").includes("..")) {
|
|
35032
35116
|
continue;
|
|
35033
35117
|
}
|
|
35034
35118
|
const lines = Array.isArray(listed) ? listed.filter((line) => Number.isInteger(line) && line > 0) : [];
|
|
35035
35119
|
if (lines.length > 0) {
|
|
35036
|
-
held.push({ scriptPath: realPathOr(
|
|
35120
|
+
held.push({ scriptPath: realPathOr(join17(projectPath, script)), lines });
|
|
35037
35121
|
}
|
|
35038
35122
|
}
|
|
35039
35123
|
return held;
|
|
@@ -35043,7 +35127,7 @@ function readBreakpointNote(projectPath) {
|
|
|
35043
35127
|
}
|
|
35044
35128
|
function withinProject(projectPath, scriptPath) {
|
|
35045
35129
|
const rel = relative3(projectPath, scriptPath);
|
|
35046
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
35130
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute3(rel);
|
|
35047
35131
|
}
|
|
35048
35132
|
var init_breakpoint_note = __esm(() => {
|
|
35049
35133
|
init_errors();
|
|
@@ -35051,14 +35135,14 @@ var init_breakpoint_note = __esm(() => {
|
|
|
35051
35135
|
});
|
|
35052
35136
|
|
|
35053
35137
|
// src/class-note.ts
|
|
35054
|
-
import { mkdirSync as mkdirSync8, readFileSync as
|
|
35055
|
-
import { dirname as
|
|
35138
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync16, writeFileSync as writeFileSync10 } from "node:fs";
|
|
35139
|
+
import { dirname as dirname12, join as join18 } from "node:path";
|
|
35056
35140
|
function classNotePath(projectPath) {
|
|
35057
|
-
return
|
|
35141
|
+
return join18(projectPath, ".godot", "gdharness-classes.json");
|
|
35058
35142
|
}
|
|
35059
35143
|
function readClassNote(projectPath) {
|
|
35060
35144
|
try {
|
|
35061
|
-
const fields = asParams(JSON.parse(
|
|
35145
|
+
const fields = asParams(JSON.parse(readFileSync16(classNotePath(projectPath), "utf8")));
|
|
35062
35146
|
const rebuiltWith = readArray(fields, "rebuiltWith");
|
|
35063
35147
|
if (rebuiltWith === undefined || !rebuiltWith.every((name) => typeof name === "string")) {
|
|
35064
35148
|
return null;
|
|
@@ -35075,7 +35159,7 @@ function readClassNote(projectPath) {
|
|
|
35075
35159
|
function writeClassNote(projectPath, note) {
|
|
35076
35160
|
try {
|
|
35077
35161
|
const path = classNotePath(projectPath);
|
|
35078
|
-
mkdirSync8(
|
|
35162
|
+
mkdirSync8(dirname12(path), { recursive: true });
|
|
35079
35163
|
writeFileSync10(path, `${JSON.stringify(note, null, 2)}
|
|
35080
35164
|
`, "utf8");
|
|
35081
35165
|
} catch {}
|
|
@@ -35083,16 +35167,16 @@ function writeClassNote(projectPath, note) {
|
|
|
35083
35167
|
var init_class_note = () => {};
|
|
35084
35168
|
|
|
35085
35169
|
// src/config-pin.ts
|
|
35086
|
-
import { existsSync as
|
|
35087
|
-
import { join as
|
|
35170
|
+
import { existsSync as existsSync15, readFileSync as readFileSync17 } from "node:fs";
|
|
35171
|
+
import { join as join19 } from "node:path";
|
|
35088
35172
|
function versionsNamedInConfig(projectPath) {
|
|
35089
|
-
const config =
|
|
35090
|
-
if (!
|
|
35173
|
+
const config = join19(projectPath, ".mcp.json");
|
|
35174
|
+
if (!existsSync15(config)) {
|
|
35091
35175
|
return [];
|
|
35092
35176
|
}
|
|
35093
35177
|
let text;
|
|
35094
35178
|
try {
|
|
35095
|
-
text =
|
|
35179
|
+
text = readFileSync17(config, "utf8");
|
|
35096
35180
|
JSON.parse(text);
|
|
35097
35181
|
} catch {
|
|
35098
35182
|
return [];
|
|
@@ -35113,26 +35197,26 @@ var init_config_pin = __esm(() => {
|
|
|
35113
35197
|
});
|
|
35114
35198
|
|
|
35115
35199
|
// src/cut-test-run.ts
|
|
35116
|
-
import { existsSync as
|
|
35117
|
-
import { dirname as
|
|
35200
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync18, rmSync as rmSync8, writeFileSync as writeFileSync11 } from "node:fs";
|
|
35201
|
+
import { dirname as dirname13, join as join20 } from "node:path";
|
|
35118
35202
|
function keptAt(projectPath) {
|
|
35119
|
-
return
|
|
35203
|
+
return join20(projectPath, ".godot", "gdharness-reports", "cut-run.json");
|
|
35120
35204
|
}
|
|
35121
35205
|
function keepCutTestRun(projectPath, run) {
|
|
35122
35206
|
const path = keptAt(projectPath);
|
|
35123
35207
|
try {
|
|
35124
|
-
mkdirSync9(
|
|
35208
|
+
mkdirSync9(dirname13(path), { recursive: true });
|
|
35125
35209
|
writeFileSync11(path, `${JSON.stringify(run, null, 2)}
|
|
35126
35210
|
`, "utf8");
|
|
35127
35211
|
} catch {}
|
|
35128
35212
|
}
|
|
35129
35213
|
function takeCutTestRun(projectPath) {
|
|
35130
35214
|
const path = keptAt(projectPath);
|
|
35131
|
-
if (!
|
|
35215
|
+
if (!existsSync16(path)) {
|
|
35132
35216
|
return null;
|
|
35133
35217
|
}
|
|
35134
35218
|
try {
|
|
35135
|
-
const run = JSON.parse(
|
|
35219
|
+
const run = JSON.parse(readFileSync18(path, "utf8"));
|
|
35136
35220
|
rmSync8(path, { force: true });
|
|
35137
35221
|
return typeof run.cutAt === "string" && Array.isArray(run.paths) && run.paths.every((path) => typeof path === "string") ? run : null;
|
|
35138
35222
|
} catch {
|
|
@@ -35948,25 +36032,25 @@ var init_desktop = () => {};
|
|
|
35948
36032
|
// src/editor-log.ts
|
|
35949
36033
|
import {
|
|
35950
36034
|
closeSync,
|
|
35951
|
-
existsSync as
|
|
36035
|
+
existsSync as existsSync17,
|
|
35952
36036
|
mkdirSync as mkdirSync10,
|
|
35953
36037
|
openSync,
|
|
35954
|
-
readFileSync as
|
|
36038
|
+
readFileSync as readFileSync19,
|
|
35955
36039
|
readSync,
|
|
35956
36040
|
rmSync as rmSync9,
|
|
35957
36041
|
statSync as statSync7,
|
|
35958
36042
|
writeFileSync as writeFileSync12
|
|
35959
36043
|
} from "node:fs";
|
|
35960
|
-
import { dirname as
|
|
36044
|
+
import { dirname as dirname14, join as join21 } from "node:path";
|
|
35961
36045
|
function editorLogPath(projectPath) {
|
|
35962
|
-
return
|
|
36046
|
+
return join21(projectPath, ".godot", "gdharness-editor.log");
|
|
35963
36047
|
}
|
|
35964
36048
|
function editorLogNotePath(projectPath) {
|
|
35965
|
-
return
|
|
36049
|
+
return join21(projectPath, ".godot", "gdharness-editor.json");
|
|
35966
36050
|
}
|
|
35967
36051
|
function readEditorLogNote(projectPath) {
|
|
35968
36052
|
try {
|
|
35969
|
-
const fields = asParams(JSON.parse(
|
|
36053
|
+
const fields = asParams(JSON.parse(readFileSync19(editorLogNotePath(projectPath), "utf8")));
|
|
35970
36054
|
const pid = readNumber(fields, "pid");
|
|
35971
36055
|
const startedAt = readString(fields, "startedAt");
|
|
35972
36056
|
return pid !== undefined && Number.isInteger(pid) && pid > 0 && startedAt !== undefined ? { pid, startedAt } : null;
|
|
@@ -35977,7 +36061,7 @@ function readEditorLogNote(projectPath) {
|
|
|
35977
36061
|
function clearEditorLog(projectPath) {
|
|
35978
36062
|
try {
|
|
35979
36063
|
const path = editorLogPath(projectPath);
|
|
35980
|
-
mkdirSync10(
|
|
36064
|
+
mkdirSync10(dirname14(path), { recursive: true });
|
|
35981
36065
|
rmSync9(path, { force: true });
|
|
35982
36066
|
rmSync9(editorLogNotePath(projectPath), { force: true });
|
|
35983
36067
|
} catch {}
|
|
@@ -35985,7 +36069,7 @@ function clearEditorLog(projectPath) {
|
|
|
35985
36069
|
function writeEditorLogNote(projectPath, pid) {
|
|
35986
36070
|
try {
|
|
35987
36071
|
const path = editorLogNotePath(projectPath);
|
|
35988
|
-
mkdirSync10(
|
|
36072
|
+
mkdirSync10(dirname14(path), { recursive: true });
|
|
35989
36073
|
writeFileSync12(path, JSON.stringify({ pid, startedAt: new Date().toISOString() }, null, 2), "utf8");
|
|
35990
36074
|
} catch {}
|
|
35991
36075
|
}
|
|
@@ -36007,7 +36091,7 @@ function editorConsole(projectPath, editorPid, openedByAServer) {
|
|
|
36007
36091
|
return { kind: "older server", notedPid: noted?.pid ?? null };
|
|
36008
36092
|
}
|
|
36009
36093
|
const path = editorLogPath(projectPath);
|
|
36010
|
-
if (!
|
|
36094
|
+
if (!existsSync17(path)) {
|
|
36011
36095
|
return { kind: "not written" };
|
|
36012
36096
|
}
|
|
36013
36097
|
const log = new GameLog;
|
|
@@ -36065,7 +36149,7 @@ function foldProgress(text) {
|
|
|
36065
36149
|
function theFirstOf(path) {
|
|
36066
36150
|
const whole = statSync7(path).size;
|
|
36067
36151
|
if (whole <= MOST_CONSOLE_BYTES) {
|
|
36068
|
-
return { text:
|
|
36152
|
+
return { text: readFileSync19(path, "utf8") };
|
|
36069
36153
|
}
|
|
36070
36154
|
const handle = openSync(path, "r");
|
|
36071
36155
|
try {
|
|
@@ -40273,19 +40357,19 @@ var DEBUG_PREFIX = "debug ";
|
|
|
40273
40357
|
var init_keeper_channel = () => {};
|
|
40274
40358
|
|
|
40275
40359
|
// src/lifecycle-log.ts
|
|
40276
|
-
import { appendFileSync, mkdirSync as mkdirSync11, renameSync, statSync as statSync8 } from "node:fs";
|
|
40277
|
-
import { dirname as
|
|
40360
|
+
import { appendFileSync, mkdirSync as mkdirSync11, renameSync as renameSync2, statSync as statSync8 } from "node:fs";
|
|
40361
|
+
import { dirname as dirname15, join as join22 } from "node:path";
|
|
40278
40362
|
import process10 from "node:process";
|
|
40279
40363
|
function lifecycleLogPath() {
|
|
40280
|
-
return
|
|
40364
|
+
return join22(runtimeDirectory(), "servers.log");
|
|
40281
40365
|
}
|
|
40282
40366
|
function writeLifecycle(event, fields = {}) {
|
|
40283
40367
|
const path = lifecycleLogPath();
|
|
40284
40368
|
try {
|
|
40285
|
-
mkdirSync11(
|
|
40369
|
+
mkdirSync11(dirname15(path), { recursive: true });
|
|
40286
40370
|
if ((statSync8(path, { throwIfNoEntry: false })?.size ?? 0) > LIFECYCLE_LOG_LIMIT) {
|
|
40287
40371
|
try {
|
|
40288
|
-
|
|
40372
|
+
renameSync2(path, `${path}.1`);
|
|
40289
40373
|
} catch {}
|
|
40290
40374
|
}
|
|
40291
40375
|
const line = {
|
|
@@ -40320,10 +40404,10 @@ var init_lifecycle_log = __esm(() => {
|
|
|
40320
40404
|
});
|
|
40321
40405
|
|
|
40322
40406
|
// src/lsp_client.ts
|
|
40323
|
-
import { existsSync as
|
|
40407
|
+
import { existsSync as existsSync18, realpathSync as realpathSync4 } from "node:fs";
|
|
40324
40408
|
import { readFile, realpath } from "node:fs/promises";
|
|
40325
40409
|
import { createConnection as createConnection3 } from "node:net";
|
|
40326
|
-
import { dirname as
|
|
40410
|
+
import { dirname as dirname16, join as join23, resolve as resolve5 } from "node:path";
|
|
40327
40411
|
import { setTimeout as delay3 } from "node:timers/promises";
|
|
40328
40412
|
import { fileURLToPath as fileURLToPath3, pathToFileURL } from "node:url";
|
|
40329
40413
|
function initializeTimeoutMs() {
|
|
@@ -40485,7 +40569,7 @@ class GodotLSPClient {
|
|
|
40485
40569
|
if (this.initialized) {
|
|
40486
40570
|
return;
|
|
40487
40571
|
}
|
|
40488
|
-
const rootPath = this.rootPath ??
|
|
40572
|
+
const rootPath = this.rootPath ?? dirname16(resolve5(filePath));
|
|
40489
40573
|
await this.initialize(rootPath);
|
|
40490
40574
|
}
|
|
40491
40575
|
async sendRequest(method, params, timeoutMs = this.timeouts.requestMs) {
|
|
@@ -40986,7 +41070,7 @@ async function resolveLSPPaths(projectPathValue, scriptPathValue) {
|
|
|
40986
41070
|
} catch {
|
|
40987
41071
|
throw new ArgumentRefusal(`Project path does not exist: ${requestedProjectPath}`);
|
|
40988
41072
|
}
|
|
40989
|
-
if (!
|
|
41073
|
+
if (!existsSync18(join23(projectPath, "project.godot"))) {
|
|
40990
41074
|
throw new ArgumentRefusal(`Not a Godot project: ${projectPath}. Point projectPath at the directory holding project.godot.`);
|
|
40991
41075
|
}
|
|
40992
41076
|
const contained = resolveWithinProject(projectPath, scriptPathValue);
|
|
@@ -41426,8 +41510,8 @@ var init_prompts = __esm(() => {
|
|
|
41426
41510
|
});
|
|
41427
41511
|
|
|
41428
41512
|
// src/rename.ts
|
|
41429
|
-
import { existsSync as
|
|
41430
|
-
import { dirname as
|
|
41513
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync12, readFileSync as readFileSync20, renameSync as renameSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync13 } from "node:fs";
|
|
41514
|
+
import { dirname as dirname17, posix as posix2 } from "node:path";
|
|
41431
41515
|
|
|
41432
41516
|
class Script {
|
|
41433
41517
|
path;
|
|
@@ -42128,26 +42212,26 @@ function rewritesOf(plan, texts, move) {
|
|
|
42128
42212
|
}
|
|
42129
42213
|
function applyRewrites(rewrites) {
|
|
42130
42214
|
for (const rewrite of rewrites) {
|
|
42131
|
-
const now =
|
|
42215
|
+
const now = readFileSync20(rewrite.absolute, "utf8");
|
|
42132
42216
|
if (now !== rewrite.before) {
|
|
42133
42217
|
throw new Error(`${rewrite.path} changed on disk while the rename was being worked out; nothing was written`);
|
|
42134
42218
|
}
|
|
42135
|
-
if (rewrite.writeTo !== rewrite.absolute &&
|
|
42219
|
+
if (rewrite.writeTo !== rewrite.absolute && existsSync19(rewrite.writeTo)) {
|
|
42136
42220
|
throw new Error(`${rewrite.writeTo} already exists; nothing was written`);
|
|
42137
42221
|
}
|
|
42138
42222
|
}
|
|
42139
42223
|
const done = [];
|
|
42140
42224
|
try {
|
|
42141
42225
|
for (const rewrite of rewrites) {
|
|
42142
|
-
mkdirSync12(
|
|
42226
|
+
mkdirSync12(dirname17(rewrite.writeTo), { recursive: true });
|
|
42143
42227
|
const staging = `${rewrite.writeTo}.gdharness-rename`;
|
|
42144
42228
|
writeFileSync13(staging, rewrite.after, "utf8");
|
|
42145
|
-
|
|
42229
|
+
renameSync3(staging, rewrite.writeTo);
|
|
42146
42230
|
let movedUid = false;
|
|
42147
42231
|
if (rewrite.writeTo !== rewrite.absolute) {
|
|
42148
|
-
|
|
42149
|
-
if (
|
|
42150
|
-
|
|
42232
|
+
unlinkSync3(rewrite.absolute);
|
|
42233
|
+
if (existsSync19(`${rewrite.absolute}.uid`)) {
|
|
42234
|
+
renameSync3(`${rewrite.absolute}.uid`, `${rewrite.writeTo}.uid`);
|
|
42151
42235
|
movedUid = true;
|
|
42152
42236
|
}
|
|
42153
42237
|
}
|
|
@@ -42158,9 +42242,9 @@ function applyRewrites(rewrites) {
|
|
|
42158
42242
|
try {
|
|
42159
42243
|
writeFileSync13(rewrite.absolute, rewrite.before, "utf8");
|
|
42160
42244
|
if (rewrite.writeTo !== rewrite.absolute) {
|
|
42161
|
-
|
|
42245
|
+
unlinkSync3(rewrite.writeTo);
|
|
42162
42246
|
if (movedUid) {
|
|
42163
|
-
|
|
42247
|
+
renameSync3(`${rewrite.writeTo}.uid`, `${rewrite.absolute}.uid`);
|
|
42164
42248
|
}
|
|
42165
42249
|
}
|
|
42166
42250
|
} catch {}
|
|
@@ -42192,8 +42276,8 @@ var init_rename = __esm(() => {
|
|
|
42192
42276
|
});
|
|
42193
42277
|
|
|
42194
42278
|
// src/rename-symbol.ts
|
|
42195
|
-
import { existsSync as
|
|
42196
|
-
import { basename as
|
|
42279
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync13, readdirSync as readdirSync10, realpathSync as realpathSync5, rmSync as rmSync10, writeFileSync as writeFileSync14 } from "node:fs";
|
|
42280
|
+
import { basename as basename6, dirname as dirname18, join as join24, relative as relative4, resolve as resolve6 } from "node:path";
|
|
42197
42281
|
function resourcePathOf(projectPath, absolute) {
|
|
42198
42282
|
const inside = relative4(onDiskSpelling(projectPath), onDiskSpelling(absolute));
|
|
42199
42283
|
if (inside === "" || inside.startsWith("..") || /^[A-Za-z]:/.test(inside)) {
|
|
@@ -42206,13 +42290,13 @@ function onDiskSpelling(path) {
|
|
|
42206
42290
|
let at = resolve6(path);
|
|
42207
42291
|
for (;; ) {
|
|
42208
42292
|
try {
|
|
42209
|
-
return
|
|
42293
|
+
return join24(realpathSync5.native(at), ...missing.reverse());
|
|
42210
42294
|
} catch {
|
|
42211
|
-
const parent =
|
|
42295
|
+
const parent = dirname18(at);
|
|
42212
42296
|
if (parent === at) {
|
|
42213
42297
|
return resolve6(path);
|
|
42214
42298
|
}
|
|
42215
|
-
missing.push(
|
|
42299
|
+
missing.push(basename6(at));
|
|
42216
42300
|
at = parent;
|
|
42217
42301
|
}
|
|
42218
42302
|
}
|
|
@@ -42259,7 +42343,7 @@ async function renameSymbol(request, services) {
|
|
|
42259
42343
|
reason: `newScriptPath must be a .gd path inside the project, and ${request.newScriptPath} is not.`
|
|
42260
42344
|
};
|
|
42261
42345
|
}
|
|
42262
|
-
if (
|
|
42346
|
+
if (existsSync20(request.newScriptPath)) {
|
|
42263
42347
|
return { ok: false, reason: `${moveTo} already exists, so the script cannot be moved there.` };
|
|
42264
42348
|
}
|
|
42265
42349
|
}
|
|
@@ -42435,7 +42519,7 @@ async function renameSymbol(request, services) {
|
|
|
42435
42519
|
scripts,
|
|
42436
42520
|
from: declaringPath,
|
|
42437
42521
|
to: moveTo,
|
|
42438
|
-
exists: (path) =>
|
|
42522
|
+
exists: (path) => existsSync20(`${projectPath}/${path.slice("res://".length)}`)
|
|
42439
42523
|
}, plan);
|
|
42440
42524
|
}
|
|
42441
42525
|
plan = mentionIgnored(plan, ignoredTexts(projectPath), symbol, moveTo === null ? null : declaringPath);
|
|
@@ -42634,15 +42718,15 @@ ${mention.kind}`;
|
|
|
42634
42718
|
};
|
|
42635
42719
|
}
|
|
42636
42720
|
function writeLeftAloneDetail(projectPath, symbol, detail) {
|
|
42637
|
-
const directory =
|
|
42721
|
+
const directory = join24(projectPath, ".godot", "gdharness-renames");
|
|
42638
42722
|
mkdirSync13(directory, { recursive: true });
|
|
42639
42723
|
detailWrites += 1;
|
|
42640
|
-
const path =
|
|
42724
|
+
const path = join24(directory, `${String(Date.now())}-${String(detailWrites).padStart(6, "0")}-${String(process.pid)}-${symbol}.json`);
|
|
42641
42725
|
writeFileSync14(path, `${JSON.stringify(detail, null, 2)}
|
|
42642
42726
|
`, "utf8");
|
|
42643
|
-
const kept =
|
|
42727
|
+
const kept = readdirSync10(directory).filter((name) => name.endsWith(".json")).sort().reverse();
|
|
42644
42728
|
for (const old of kept.slice(10)) {
|
|
42645
|
-
rmSync10(
|
|
42729
|
+
rmSync10(join24(directory, old), { force: true });
|
|
42646
42730
|
}
|
|
42647
42731
|
return path;
|
|
42648
42732
|
}
|
|
@@ -42682,15 +42766,15 @@ var init_rename_symbol = __esm(() => {
|
|
|
42682
42766
|
});
|
|
42683
42767
|
|
|
42684
42768
|
// src/restart-note.ts
|
|
42685
|
-
import { mkdirSync as mkdirSync14, readFileSync as
|
|
42686
|
-
import { dirname as
|
|
42769
|
+
import { mkdirSync as mkdirSync14, readFileSync as readFileSync21, rmSync as rmSync11, writeFileSync as writeFileSync15 } from "node:fs";
|
|
42770
|
+
import { dirname as dirname19, join as join25 } from "node:path";
|
|
42687
42771
|
function restartNotePath(projectPath) {
|
|
42688
|
-
return
|
|
42772
|
+
return join25(projectPath, ".godot", "gdharness-restart.json");
|
|
42689
42773
|
}
|
|
42690
42774
|
function noteRestartBegun(note) {
|
|
42691
42775
|
const path = restartNotePath(note.projectPath);
|
|
42692
42776
|
try {
|
|
42693
|
-
mkdirSync14(
|
|
42777
|
+
mkdirSync14(dirname19(path), { recursive: true });
|
|
42694
42778
|
writeFileSync15(path, `${JSON.stringify(note, null, 2)}
|
|
42695
42779
|
`, "utf8");
|
|
42696
42780
|
} catch (error) {
|
|
@@ -42699,7 +42783,7 @@ function noteRestartBegun(note) {
|
|
|
42699
42783
|
}
|
|
42700
42784
|
function restartOwed(projectPath) {
|
|
42701
42785
|
try {
|
|
42702
|
-
const parsed = JSON.parse(
|
|
42786
|
+
const parsed = JSON.parse(readFileSync21(restartNotePath(projectPath), "utf8"));
|
|
42703
42787
|
if (typeof parsed !== "object" || parsed === null) {
|
|
42704
42788
|
return null;
|
|
42705
42789
|
}
|
|
@@ -42724,7 +42808,7 @@ var init_restart_note = __esm(() => {
|
|
|
42724
42808
|
});
|
|
42725
42809
|
|
|
42726
42810
|
// src/whole-file.ts
|
|
42727
|
-
import { renameSync as
|
|
42811
|
+
import { renameSync as renameSync4, rmSync as rmSync12, writeFileSync as writeFileSync16 } from "node:fs";
|
|
42728
42812
|
function writeWhole(path, text) {
|
|
42729
42813
|
const partial = `${path}.${process.pid}.partial`;
|
|
42730
42814
|
try {
|
|
@@ -42735,7 +42819,7 @@ function writeWhole(path, text) {
|
|
|
42735
42819
|
const until = Date.now() + HELD_FILE_MS;
|
|
42736
42820
|
for (;; ) {
|
|
42737
42821
|
try {
|
|
42738
|
-
|
|
42822
|
+
renameSync4(partial, path);
|
|
42739
42823
|
return true;
|
|
42740
42824
|
} catch (error) {
|
|
42741
42825
|
const code = error.code ?? "";
|
|
@@ -42757,24 +42841,24 @@ var init_whole_file = __esm(() => {
|
|
|
42757
42841
|
// src/run-record.ts
|
|
42758
42842
|
import { execFile as execFile4 } from "node:child_process";
|
|
42759
42843
|
import { createHash as createHash4 } from "node:crypto";
|
|
42760
|
-
import { mkdirSync as mkdirSync15, openSync as openSync2, readdirSync as
|
|
42761
|
-
import { basename as
|
|
42844
|
+
import { mkdirSync as mkdirSync15, openSync as openSync2, readdirSync as readdirSync11, readFileSync as readFileSync22, realpathSync as realpathSync6, rmSync as rmSync13, statSync as statSync9 } from "node:fs";
|
|
42845
|
+
import { basename as basename7, dirname as dirname20, join as join26, resolve as resolve7 } from "node:path";
|
|
42762
42846
|
import { promisify as promisify4 } from "node:util";
|
|
42763
42847
|
function runsDirectory() {
|
|
42764
|
-
return
|
|
42848
|
+
return join26(runtimeDirectory(), "runs");
|
|
42765
42849
|
}
|
|
42766
42850
|
function realAsFarAsItExists(path) {
|
|
42767
42851
|
const missing = [];
|
|
42768
42852
|
let at = path;
|
|
42769
42853
|
for (;; ) {
|
|
42770
42854
|
try {
|
|
42771
|
-
return
|
|
42855
|
+
return join26(realpathSync6.native(at), ...missing);
|
|
42772
42856
|
} catch {
|
|
42773
|
-
const parent =
|
|
42857
|
+
const parent = dirname20(at);
|
|
42774
42858
|
if (parent === at) {
|
|
42775
42859
|
return path;
|
|
42776
42860
|
}
|
|
42777
|
-
missing.unshift(
|
|
42861
|
+
missing.unshift(basename7(at));
|
|
42778
42862
|
at = parent;
|
|
42779
42863
|
}
|
|
42780
42864
|
}
|
|
@@ -42785,10 +42869,10 @@ function projectKey(projectPath) {
|
|
|
42785
42869
|
return createHash4("sha256").update(folded.replaceAll("\\", "/")).digest("hex").slice(0, 16);
|
|
42786
42870
|
}
|
|
42787
42871
|
function runRecordPath(projectPath, directory = runtimeDirectory()) {
|
|
42788
|
-
return
|
|
42872
|
+
return join26(directory, "runs", `note-${projectKey(projectPath)}.json`);
|
|
42789
42873
|
}
|
|
42790
42874
|
function latestRunPath(servedBy, directory = runtimeDirectory()) {
|
|
42791
|
-
return
|
|
42875
|
+
return join26(directory, "runs", `latest-${projectKey(servedBy)}.json`);
|
|
42792
42876
|
}
|
|
42793
42877
|
function writeLatestRun(servedBy, latest) {
|
|
42794
42878
|
try {
|
|
@@ -42798,7 +42882,7 @@ function writeLatestRun(servedBy, latest) {
|
|
|
42798
42882
|
}
|
|
42799
42883
|
function readLatestRun(servedBy, directory = runtimeDirectory()) {
|
|
42800
42884
|
try {
|
|
42801
|
-
const fields = JSON.parse(
|
|
42885
|
+
const fields = JSON.parse(readFileSync22(latestRunPath(servedBy, directory), "utf8"));
|
|
42802
42886
|
if (typeof fields !== "object" || fields === null) {
|
|
42803
42887
|
return null;
|
|
42804
42888
|
}
|
|
@@ -42813,17 +42897,17 @@ function readLatestRun(servedBy, directory = runtimeDirectory()) {
|
|
|
42813
42897
|
}
|
|
42814
42898
|
function openTranscript(startedAt) {
|
|
42815
42899
|
mkdirSync15(runsDirectory(), { recursive: true });
|
|
42816
|
-
const path =
|
|
42900
|
+
const path = join26(runsDirectory(), `run-${startedAt}.log`);
|
|
42817
42901
|
return { path, fd: openSync2(path, "a") };
|
|
42818
42902
|
}
|
|
42819
42903
|
function profilePath(startedAt) {
|
|
42820
|
-
return
|
|
42904
|
+
return join26(runsDirectory(), `run-${startedAt}.profile.json`);
|
|
42821
42905
|
}
|
|
42822
42906
|
function noteIsAbout(note, playing) {
|
|
42823
42907
|
return note.play !== undefined && playing !== null && note.play.play === playing.play && note.play.editorPid === playing.editorPid;
|
|
42824
42908
|
}
|
|
42825
42909
|
function editorNotePath(projectPath, directory = runtimeDirectory()) {
|
|
42826
|
-
return
|
|
42910
|
+
return join26(directory, "runs", `editor-${projectKey(projectPath)}.json`);
|
|
42827
42911
|
}
|
|
42828
42912
|
function writeEditorRunNote(note) {
|
|
42829
42913
|
mkdirSync15(runsDirectory(), { recursive: true });
|
|
@@ -42834,7 +42918,7 @@ function writeEditorRunNote(note) {
|
|
|
42834
42918
|
}
|
|
42835
42919
|
function readEditorRunNote(projectPath) {
|
|
42836
42920
|
for (const directory of runtimeDirectories()) {
|
|
42837
|
-
const note = editorNoteAt(editorNotePath(projectPath, directory)) ?? editorNoteAt(
|
|
42921
|
+
const note = editorNoteAt(editorNotePath(projectPath, directory)) ?? editorNoteAt(join26(directory, "runs", "editor-run.json"));
|
|
42838
42922
|
if (note !== null && isSameDirectory(note.projectPath, projectPath)) {
|
|
42839
42923
|
return note;
|
|
42840
42924
|
}
|
|
@@ -42844,7 +42928,7 @@ function readEditorRunNote(projectPath) {
|
|
|
42844
42928
|
function editorNoteAt(path) {
|
|
42845
42929
|
let parsed;
|
|
42846
42930
|
try {
|
|
42847
|
-
parsed = JSON.parse(
|
|
42931
|
+
parsed = JSON.parse(readFileSync22(path, "utf8"));
|
|
42848
42932
|
} catch {
|
|
42849
42933
|
return null;
|
|
42850
42934
|
}
|
|
@@ -42868,7 +42952,7 @@ function readRunRecord(projectPath) {
|
|
|
42868
42952
|
if (own !== null) {
|
|
42869
42953
|
return own;
|
|
42870
42954
|
}
|
|
42871
|
-
const shared = recordAt(
|
|
42955
|
+
const shared = recordAt(join26(directory, "runs", SHARED_NOTE));
|
|
42872
42956
|
if (shared !== null && shared.projectPath !== "" && isSameDirectory(shared.projectPath, projectPath)) {
|
|
42873
42957
|
return shared;
|
|
42874
42958
|
}
|
|
@@ -42880,13 +42964,13 @@ function everyRunRecord() {
|
|
|
42880
42964
|
for (const directory of runtimeDirectories()) {
|
|
42881
42965
|
let entries;
|
|
42882
42966
|
try {
|
|
42883
|
-
entries =
|
|
42967
|
+
entries = readdirSync11(join26(directory, "runs"));
|
|
42884
42968
|
} catch {
|
|
42885
42969
|
continue;
|
|
42886
42970
|
}
|
|
42887
42971
|
for (const entry of entries) {
|
|
42888
42972
|
if (entry === SHARED_NOTE || entry.startsWith("note-") && entry.endsWith(".json")) {
|
|
42889
|
-
const record = recordAt(
|
|
42973
|
+
const record = recordAt(join26(directory, "runs", entry));
|
|
42890
42974
|
if (record !== null) {
|
|
42891
42975
|
found.push(record);
|
|
42892
42976
|
}
|
|
@@ -42898,7 +42982,7 @@ function everyRunRecord() {
|
|
|
42898
42982
|
function recordAt(path) {
|
|
42899
42983
|
let parsed;
|
|
42900
42984
|
try {
|
|
42901
|
-
parsed = JSON.parse(
|
|
42985
|
+
parsed = JSON.parse(readFileSync22(path, "utf8"));
|
|
42902
42986
|
} catch {
|
|
42903
42987
|
return null;
|
|
42904
42988
|
}
|
|
@@ -42951,7 +43035,7 @@ async function runningAs(pid) {
|
|
|
42951
43035
|
const began = await startedAt(pid, null);
|
|
42952
43036
|
const when = began === null ? {} : { startedAt: began };
|
|
42953
43037
|
if (process.platform === "linux") {
|
|
42954
|
-
const raw =
|
|
43038
|
+
const raw = readFileSync22(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ").trim();
|
|
42955
43039
|
return raw === "" ? null : { kind: "commandLine", text: raw, ...when };
|
|
42956
43040
|
}
|
|
42957
43041
|
const args = (await execFileAsync("ps", ["-p", String(pid), "-o", "args="], { encoding: "utf8", timeout: 15000 })).stdout.trim();
|
|
@@ -43057,7 +43141,7 @@ function whyNotTheRun(record, running, needed) {
|
|
|
43057
43141
|
if (after > SAME_RUN_WINDOW_MS) {
|
|
43058
43142
|
return `that process started ${Math.round(after / 1000)} seconds after the run had`;
|
|
43059
43143
|
}
|
|
43060
|
-
const engine = record.command === undefined ? null :
|
|
43144
|
+
const engine = record.command === undefined ? null : basename7(record.command);
|
|
43061
43145
|
const said = process.platform === "win32" ? running.text.toLowerCase() : running.text;
|
|
43062
43146
|
const wanted = engine === null || process.platform !== "win32" ? engine : engine.toLowerCase();
|
|
43063
43147
|
if (wanted !== null && !said.includes(wanted)) {
|
|
@@ -43096,7 +43180,7 @@ function judgeAnnouncedGame(running, projectPath, announcedAt) {
|
|
|
43096
43180
|
}
|
|
43097
43181
|
function clearRunRecord(projectPath) {
|
|
43098
43182
|
for (const directory of runtimeDirectories()) {
|
|
43099
|
-
const shared =
|
|
43183
|
+
const shared = join26(directory, "runs", SHARED_NOTE);
|
|
43100
43184
|
const sharedRecord = recordAt(shared);
|
|
43101
43185
|
const ours = sharedRecord !== null && sharedRecord.projectPath !== "" && isSameDirectory(sharedRecord.projectPath, projectPath);
|
|
43102
43186
|
for (const path of [runRecordPath(projectPath, directory), ...ours ? [shared] : []]) {
|
|
@@ -43121,7 +43205,7 @@ function sweepTranscripts(keepMs = 24 * 60 * 60 * 1000, now = Date.now()) {
|
|
|
43121
43205
|
]));
|
|
43122
43206
|
let entries;
|
|
43123
43207
|
try {
|
|
43124
|
-
entries =
|
|
43208
|
+
entries = readdirSync11(directory);
|
|
43125
43209
|
} catch {
|
|
43126
43210
|
return;
|
|
43127
43211
|
}
|
|
@@ -43130,7 +43214,7 @@ function sweepTranscripts(keepMs = 24 * 60 * 60 * 1000, now = Date.now()) {
|
|
|
43130
43214
|
if (!transcript && !entry.endsWith(".partial")) {
|
|
43131
43215
|
continue;
|
|
43132
43216
|
}
|
|
43133
|
-
const path =
|
|
43217
|
+
const path = join26(directory, entry);
|
|
43134
43218
|
if (kept.has(path) || ageMs(path, now) < keepMs) {
|
|
43135
43219
|
continue;
|
|
43136
43220
|
}
|
|
@@ -43151,7 +43235,7 @@ var init_run_record = __esm(() => {
|
|
|
43151
43235
|
});
|
|
43152
43236
|
|
|
43153
43237
|
// src/script-origins.ts
|
|
43154
|
-
import { join as
|
|
43238
|
+
import { join as join27 } from "node:path";
|
|
43155
43239
|
function unresolvedClassIn(message) {
|
|
43156
43240
|
return UNRESOLVED.exec(message)?.[1] ?? null;
|
|
43157
43241
|
}
|
|
@@ -43204,7 +43288,7 @@ function checkWithEngine(godotPath, projectPath) {
|
|
|
43204
43288
|
const ran = await runEngine(godotPath, [
|
|
43205
43289
|
"--headless",
|
|
43206
43290
|
"--log-file",
|
|
43207
|
-
|
|
43291
|
+
join27(logDir, "engine.log"),
|
|
43208
43292
|
"--path",
|
|
43209
43293
|
projectPath,
|
|
43210
43294
|
"--check-only",
|
|
@@ -43249,10 +43333,10 @@ var init_script_origins = __esm(() => {
|
|
|
43249
43333
|
});
|
|
43250
43334
|
|
|
43251
43335
|
// src/script-profile.ts
|
|
43252
|
-
import { readFileSync as
|
|
43336
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
43253
43337
|
function readProfileFile(path) {
|
|
43254
43338
|
try {
|
|
43255
|
-
const parsed = JSON.parse(
|
|
43339
|
+
const parsed = JSON.parse(readFileSync23(path, "utf8"));
|
|
43256
43340
|
return typeof parsed === "object" && typeof parsed.connected === "boolean" ? parsed : null;
|
|
43257
43341
|
} catch {
|
|
43258
43342
|
return null;
|
|
@@ -43430,17 +43514,17 @@ import {
|
|
|
43430
43514
|
closeSync as closeSync2,
|
|
43431
43515
|
constants,
|
|
43432
43516
|
copyFileSync,
|
|
43433
|
-
existsSync as
|
|
43517
|
+
existsSync as existsSync21,
|
|
43434
43518
|
fstatSync,
|
|
43435
43519
|
mkdirSync as mkdirSync16,
|
|
43436
43520
|
openSync as openSync3,
|
|
43437
|
-
readdirSync as
|
|
43438
|
-
readFileSync as
|
|
43521
|
+
readdirSync as readdirSync12,
|
|
43522
|
+
readFileSync as readFileSync24,
|
|
43439
43523
|
readSync as readSync2,
|
|
43440
43524
|
rmdirSync as rmdirSync2,
|
|
43441
43525
|
statSync as statSync10
|
|
43442
43526
|
} from "node:fs";
|
|
43443
|
-
import { basename as
|
|
43527
|
+
import { basename as basename8, dirname as dirname21, extname as extname3, isAbsolute as isAbsolute4, join as join28, normalize as normalize2, relative as relative5 } from "node:path";
|
|
43444
43528
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
43445
43529
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
43446
43530
|
import { promisify as promisify5 } from "node:util";
|
|
@@ -43471,22 +43555,22 @@ function writtenFileRefusal(path, rule) {
|
|
|
43471
43555
|
if (/^(res|user):\/\//.test(path)) {
|
|
43472
43556
|
return `${named} ${path} is a Godot path; ${what} is saved outside the project, at an absolute path on this machine.`;
|
|
43473
43557
|
}
|
|
43474
|
-
if (!
|
|
43558
|
+
if (!isAbsolute4(path)) {
|
|
43475
43559
|
return `${named} ${path} is not absolute; name the whole path, so where it is written does not depend on this server's directory.`;
|
|
43476
43560
|
}
|
|
43477
43561
|
if (!rule.extensions.includes(extname3(path).toLowerCase())) {
|
|
43478
43562
|
return `${named} ${path} does not end in ${rule.extensions.join(" or ")}, which is what ${what} is.`;
|
|
43479
43563
|
}
|
|
43480
|
-
const directory = realPathOr(
|
|
43481
|
-
if (!
|
|
43482
|
-
return `${named}'s directory ${
|
|
43564
|
+
const directory = realPathOr(dirname21(path));
|
|
43565
|
+
if (!existsSync21(directory)) {
|
|
43566
|
+
return `${named}'s directory ${dirname21(path)} does not exist; ${what} creates no directories.`;
|
|
43483
43567
|
}
|
|
43484
|
-
const where =
|
|
43568
|
+
const where = join28(directory, basename8(path));
|
|
43485
43569
|
const inside = rule.projects.find((project) => project !== "" && isWithinRoot(realPathOr(project), where));
|
|
43486
43570
|
if (inside !== undefined) {
|
|
43487
43571
|
return `${named} ${path} is inside the project at ${inside}; ${what} is saved outside it, so it never becomes part of the game.`;
|
|
43488
43572
|
}
|
|
43489
|
-
const taken = rule.writes(where).find((file) =>
|
|
43573
|
+
const taken = rule.writes(where).find((file) => existsSync21(file));
|
|
43490
43574
|
if (taken !== undefined) {
|
|
43491
43575
|
return taken === where ? `${named} ${path} already exists; ${what} is not written over a file. Name a new one.` : `${named} ${path} would write ${taken}, which already exists; ${what} is not written over a file. Name a new one.`;
|
|
43492
43576
|
}
|
|
@@ -43982,6 +44066,7 @@ function notRunNote(notRun, failFast) {
|
|
|
43982
44066
|
function exportAnswer(ending, asked, before, after) {
|
|
43983
44067
|
const { log } = ending;
|
|
43984
44068
|
const written = after !== null && after !== before;
|
|
44069
|
+
const notCopied = librariesNotCopied(log.all);
|
|
43985
44070
|
const verdict = {
|
|
43986
44071
|
exported: ending.exitCode === 0 && ending.failure === null && log.count("error") === 0 && written,
|
|
43987
44072
|
...asked,
|
|
@@ -43990,6 +44075,10 @@ function exportAnswer(ending, asked, before, after) {
|
|
|
43990
44075
|
failure: ending.failure ?? undefined,
|
|
43991
44076
|
errors: log.count("error"),
|
|
43992
44077
|
warnings: log.count("warning"),
|
|
44078
|
+
...notCopied.length === 0 ? {} : {
|
|
44079
|
+
librariesNotLoaded: notCopied,
|
|
44080
|
+
extensionNote: `The export could not load ${notCopied.join(" and ")}: on Windows an engine running as the editor, which an export is, loads a GDExtension from a ~ copy beside the library, and another engine on this project held that copy: it could not be moved aside before the export, or another engine made a new one in between. Export again once that engine has loaded or exited.`
|
|
44081
|
+
},
|
|
43993
44082
|
...foldedEntriesAnswer(log)
|
|
43994
44083
|
};
|
|
43995
44084
|
if (verdict.exported) {
|
|
@@ -44027,7 +44116,7 @@ function engineFlagsNote(args) {
|
|
|
44027
44116
|
return `${named} ${among.length === 1 ? "is a flag" : "are flags"} the engine reads, and args goes to the game after --, where the engine does not read ${among.length === 1 ? "it" : "them"}. engineArgs hands the engine its own flags; ${among.length === 1 ? "leave it" : "leave them"} in args only for a game that reads ${among.length === 1 ? "that flag" : "those flags"} itself.`;
|
|
44028
44117
|
}
|
|
44029
44118
|
function editorAddonMissing(projectPath) {
|
|
44030
|
-
if (!
|
|
44119
|
+
if (!existsSync21(join28(projectPath, "project.godot"))) {
|
|
44031
44120
|
return null;
|
|
44032
44121
|
}
|
|
44033
44122
|
const report = inspectProject(projectPath);
|
|
@@ -44263,7 +44352,7 @@ function profileFrameFunctions(projectPath) {
|
|
|
44263
44352
|
let projectGodot = null;
|
|
44264
44353
|
if (projectPath !== null) {
|
|
44265
44354
|
try {
|
|
44266
|
-
projectGodot =
|
|
44355
|
+
projectGodot = readFileSync24(join28(projectPath, "project.godot"), "utf8");
|
|
44267
44356
|
} catch {}
|
|
44268
44357
|
}
|
|
44269
44358
|
return frameFunctionsFor(queuedMessagesOf(projectGodot));
|
|
@@ -44287,7 +44376,7 @@ function projectSourceOf(projectPath) {
|
|
|
44287
44376
|
let source = null;
|
|
44288
44377
|
if (inside.ok) {
|
|
44289
44378
|
try {
|
|
44290
|
-
source =
|
|
44379
|
+
source = readFileSync24(inside.absolutePath, "utf8");
|
|
44291
44380
|
} catch {}
|
|
44292
44381
|
}
|
|
44293
44382
|
read.set(script, source);
|
|
@@ -44437,7 +44526,7 @@ function foldedEntriesAnswer(log, floor = "warning") {
|
|
|
44437
44526
|
}
|
|
44438
44527
|
function gdUnitFailsOnScriptErrors(projectPath) {
|
|
44439
44528
|
try {
|
|
44440
|
-
return settingKeys(
|
|
44529
|
+
return settingKeys(readFileSync24(join28(projectPath, "project.godot"), "utf8")).get("gdunit4/report/godot/script_error") !== false;
|
|
44441
44530
|
} catch {
|
|
44442
44531
|
return true;
|
|
44443
44532
|
}
|
|
@@ -44452,13 +44541,13 @@ function uncaughtNote(uncaught) {
|
|
|
44452
44541
|
}
|
|
44453
44542
|
function elsewhereIn(projectPath, asked) {
|
|
44454
44543
|
const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
|
|
44455
|
-
if (wanted === "" ||
|
|
44544
|
+
if (wanted === "" || existsSync21(join28(projectPath, wanted))) {
|
|
44456
44545
|
return "";
|
|
44457
44546
|
}
|
|
44458
44547
|
const root = (wanted.split("/")[0] ?? "").toLowerCase();
|
|
44459
44548
|
let near = [];
|
|
44460
44549
|
try {
|
|
44461
|
-
near =
|
|
44550
|
+
near = readdirSync12(projectPath, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.toLowerCase() !== root).map((entry) => entry.name).filter((name) => name.toLowerCase().startsWith("test") || root.startsWith(name.toLowerCase()));
|
|
44462
44551
|
} catch {
|
|
44463
44552
|
return "";
|
|
44464
44553
|
}
|
|
@@ -44548,17 +44637,17 @@ function isDirectory(path) {
|
|
|
44548
44637
|
}
|
|
44549
44638
|
}
|
|
44550
44639
|
function scriptsUnder(directory, prefix) {
|
|
44551
|
-
if (
|
|
44640
|
+
if (existsSync21(join28(directory, ".gdignore"))) {
|
|
44552
44641
|
return [];
|
|
44553
44642
|
}
|
|
44554
44643
|
const found = [];
|
|
44555
|
-
for (const entry of
|
|
44644
|
+
for (const entry of readdirSync12(directory, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : 1)) {
|
|
44556
44645
|
if (entry.name.startsWith(".")) {
|
|
44557
44646
|
continue;
|
|
44558
44647
|
}
|
|
44559
44648
|
const path = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
|
|
44560
44649
|
if (entry.isDirectory()) {
|
|
44561
|
-
found.push(...scriptsUnder(
|
|
44650
|
+
found.push(...scriptsUnder(join28(directory, entry.name), path));
|
|
44562
44651
|
} else if (entry.isFile() && entry.name.endsWith(".gd")) {
|
|
44563
44652
|
found.push(path);
|
|
44564
44653
|
}
|
|
@@ -44566,7 +44655,7 @@ function scriptsUnder(directory, prefix) {
|
|
|
44566
44655
|
return found;
|
|
44567
44656
|
}
|
|
44568
44657
|
function hasMainScene(projectFile) {
|
|
44569
|
-
const scene = parseProjectGodot(
|
|
44658
|
+
const scene = parseProjectGodot(readFileSync24(projectFile, "utf8"))["application"]?.["run/main_scene"];
|
|
44570
44659
|
return typeof scene === "string" && scene !== "";
|
|
44571
44660
|
}
|
|
44572
44661
|
function runtimeAddonAnnouncesEditors(projectPath) {
|
|
@@ -44574,13 +44663,13 @@ function runtimeAddonAnnouncesEditors(projectPath) {
|
|
|
44574
44663
|
return false;
|
|
44575
44664
|
}
|
|
44576
44665
|
try {
|
|
44577
|
-
return
|
|
44666
|
+
return readFileSync24(join28(projectPath, RUNTIME_AUTOLOAD.path), "utf8").includes('"editor_pid"');
|
|
44578
44667
|
} catch {
|
|
44579
44668
|
return false;
|
|
44580
44669
|
}
|
|
44581
44670
|
}
|
|
44582
44671
|
function editorPlaysHeadless(projectFile) {
|
|
44583
|
-
const runArgs = parseProjectGodot(
|
|
44672
|
+
const runArgs = parseProjectGodot(readFileSync24(projectFile, "utf8"))["editor"]?.["run/main_run_args"];
|
|
44584
44673
|
return typeof runArgs === "string" && /(?:^|\s)--headless(?:\s|$)/.test(runArgs);
|
|
44585
44674
|
}
|
|
44586
44675
|
function camelCased(params) {
|
|
@@ -44599,7 +44688,7 @@ function needsItsOwnProcess(asked) {
|
|
|
44599
44688
|
class GodotServer {
|
|
44600
44689
|
stdio = null;
|
|
44601
44690
|
locator = new GodotLocator;
|
|
44602
|
-
operationsScript =
|
|
44691
|
+
operationsScript = join28(__dirname2, "godot", "operations", "godot_operations.gd");
|
|
44603
44692
|
godotBridge;
|
|
44604
44693
|
tools = buildToolDefinitions();
|
|
44605
44694
|
activeProcess = null;
|
|
@@ -44624,6 +44713,7 @@ class GodotServer {
|
|
|
44624
44713
|
launchedDropped = null;
|
|
44625
44714
|
closedHere = null;
|
|
44626
44715
|
inFlight = new Map;
|
|
44716
|
+
callsOnGames = new Set;
|
|
44627
44717
|
callsTaken = 0;
|
|
44628
44718
|
clientNoted = null;
|
|
44629
44719
|
parentCommand = null;
|
|
@@ -44855,14 +44945,14 @@ class GodotServer {
|
|
|
44855
44945
|
}
|
|
44856
44946
|
noteTheStart() {
|
|
44857
44947
|
const cwd = process.cwd();
|
|
44858
|
-
const mcpJson =
|
|
44948
|
+
const mcpJson = join28(cwd, ".mcp.json");
|
|
44859
44949
|
const announced = this.ownProject === null ? null : readAnnouncement(announcementPath(this.ownProject));
|
|
44860
44950
|
const predecessor = announced !== null && announced.pid !== process.pid && alive(announced.pid) ? announced.pid : null;
|
|
44861
44951
|
writeLifecycle("started", {
|
|
44862
44952
|
argv: process.argv.slice(1),
|
|
44863
44953
|
cwd,
|
|
44864
44954
|
project: this.ownProject,
|
|
44865
|
-
mcpJson:
|
|
44955
|
+
mcpJson: existsSync21(mcpJson) ? mcpJson : null
|
|
44866
44956
|
});
|
|
44867
44957
|
if (predecessor !== null) {
|
|
44868
44958
|
writeLifecycle("replaced", { project: this.ownProject, predecessor });
|
|
@@ -45003,7 +45093,7 @@ class GodotServer {
|
|
|
45003
45093
|
return checked.response;
|
|
45004
45094
|
}
|
|
45005
45095
|
const named = args["projectPath"];
|
|
45006
|
-
if (typeof named === "string" &&
|
|
45096
|
+
if (typeof named === "string" && existsSync21(join28(named, "project.godot"))) {
|
|
45007
45097
|
this.lastProjectPath = named;
|
|
45008
45098
|
}
|
|
45009
45099
|
this.updates.refresh();
|
|
@@ -45561,8 +45651,8 @@ class GodotServer {
|
|
|
45561
45651
|
if (path === undefined) {
|
|
45562
45652
|
return { ok: false, response: this.createErrorResponse("projectPath is required.") };
|
|
45563
45653
|
}
|
|
45564
|
-
const file =
|
|
45565
|
-
if (!
|
|
45654
|
+
const file = join28(path, "project.godot");
|
|
45655
|
+
if (!existsSync21(file)) {
|
|
45566
45656
|
return {
|
|
45567
45657
|
ok: false,
|
|
45568
45658
|
response: this.createErrorResponse(`Not a Godot project: ${path}`, [
|
|
@@ -45608,7 +45698,7 @@ class GodotServer {
|
|
|
45608
45698
|
}
|
|
45609
45699
|
runEnvironment(args) {
|
|
45610
45700
|
const savesIn = readNonEmptyString(args, "savesIn");
|
|
45611
|
-
if (savesIn !== undefined && !
|
|
45701
|
+
if (savesIn !== undefined && !isAbsolute4(savesIn)) {
|
|
45612
45702
|
return {
|
|
45613
45703
|
ok: false,
|
|
45614
45704
|
response: this.createErrorResponse(`savesIn must be an absolute path, not "${savesIn}".`, [
|
|
@@ -46192,11 +46282,11 @@ class GodotServer {
|
|
|
46192
46282
|
if (!engine.ok) {
|
|
46193
46283
|
return engine.response;
|
|
46194
46284
|
}
|
|
46195
|
-
const application = parseProjectGodot(
|
|
46285
|
+
const application = parseProjectGodot(readFileSync24(project.value.file, "utf8"))["application"] ?? {};
|
|
46196
46286
|
const name = application["config/name"];
|
|
46197
46287
|
const mainScene = application["run/main_scene"];
|
|
46198
46288
|
const info = {
|
|
46199
|
-
name: typeof name === "string" && name !== "" ? name :
|
|
46289
|
+
name: typeof name === "string" && name !== "" ? name : basename8(project.value.path),
|
|
46200
46290
|
path: project.value.path,
|
|
46201
46291
|
mainScene: typeof mainScene === "string" && mainScene !== "" ? mainScene : null,
|
|
46202
46292
|
godotVersion: await this.godotVersion(engine.value),
|
|
@@ -46248,18 +46338,18 @@ class GodotServer {
|
|
|
46248
46338
|
if (!engine.ok) {
|
|
46249
46339
|
return engine.response;
|
|
46250
46340
|
}
|
|
46251
|
-
const folder =
|
|
46341
|
+
const folder = dirname21(output.absolutePath);
|
|
46252
46342
|
try {
|
|
46253
46343
|
mkdirSync16(folder, { recursive: true });
|
|
46254
46344
|
} catch (error) {
|
|
46255
|
-
return this.createErrorResponse(`Cannot create ${
|
|
46345
|
+
return this.createErrorResponse(`Cannot create ${dirname21(output.relativePath)} to export into: ${errorMessage(error)}`);
|
|
46256
46346
|
}
|
|
46257
46347
|
const debug = readBoolean(args, "debug") ?? false;
|
|
46258
46348
|
const exportLogs = scratchDirectory("export");
|
|
46259
46349
|
const exportArgs = [
|
|
46260
46350
|
"--headless",
|
|
46261
46351
|
"--log-file",
|
|
46262
|
-
|
|
46352
|
+
join28(exportLogs, "engine.log"),
|
|
46263
46353
|
"--path",
|
|
46264
46354
|
project.value.path,
|
|
46265
46355
|
debug ? "--export-debug" : "--export-release",
|
|
@@ -46267,8 +46357,12 @@ class GodotServer {
|
|
|
46267
46357
|
output.absolutePath
|
|
46268
46358
|
];
|
|
46269
46359
|
this.logDebug(`Exporting: ${engine.value} ${exportArgs.join(" ")}`);
|
|
46270
|
-
const writtenAt = () =>
|
|
46360
|
+
const writtenAt = () => existsSync21(output.absolutePath) ? statSync10(output.absolutePath).mtimeMs : null;
|
|
46271
46361
|
const before = writtenAt();
|
|
46362
|
+
const freed = freeLibraryCopies(project.value.path);
|
|
46363
|
+
if (freed.setAside.length > 0 || freed.swept.length > 0) {
|
|
46364
|
+
this.logDebug(`Before the export: set aside ${freed.setAside.join(", ")}; swept ${freed.swept.join(", ")}`);
|
|
46365
|
+
}
|
|
46272
46366
|
let ending;
|
|
46273
46367
|
try {
|
|
46274
46368
|
ending = await runEngine(engine.value, exportArgs, { timeout: { ms: 300000, said: "five minutes" } });
|
|
@@ -46331,10 +46425,10 @@ class GodotServer {
|
|
|
46331
46425
|
if (movie !== null) {
|
|
46332
46426
|
return this.createErrorResponse(movie);
|
|
46333
46427
|
}
|
|
46334
|
-
const missing = paths.value.filter((path) => !
|
|
46428
|
+
const missing = paths.value.filter((path) => !existsSync21(join28(project.value.path, path.slice("res://".length))));
|
|
46335
46429
|
const asked = paths.value.filter((path) => !missing.includes(path));
|
|
46336
46430
|
const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
|
|
46337
|
-
const noRunner = !
|
|
46431
|
+
const noRunner = !existsSync21(join28(project.value.path, runner));
|
|
46338
46432
|
if (asked.length === 0) {
|
|
46339
46433
|
const verdict = `nothing at ${missing.join(" and ")}`;
|
|
46340
46434
|
const andNoRunner = noRunner ? `, and gdUnit4 is not installed in this project: no ${runner}` : "";
|
|
@@ -46425,21 +46519,21 @@ class GodotServer {
|
|
|
46425
46519
|
await untilGone([run.process.pid]);
|
|
46426
46520
|
}
|
|
46427
46521
|
await run.settled;
|
|
46428
|
-
const reportsDir =
|
|
46522
|
+
const reportsDir = join28(project.value.path, ".godot", ...ours.split("/"));
|
|
46429
46523
|
let report = null;
|
|
46430
46524
|
let reportProblem = null;
|
|
46431
46525
|
try {
|
|
46432
|
-
const written =
|
|
46526
|
+
const written = existsSync21(reportsDir) ? readdirSync12(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
|
|
46433
46527
|
const newest = written.at(-1);
|
|
46434
46528
|
if (newest !== undefined) {
|
|
46435
|
-
report = parseJUnit(
|
|
46529
|
+
report = parseJUnit(readFileSync24(join28(reportsDir, newest, "results.xml"), "utf8"));
|
|
46436
46530
|
}
|
|
46437
46531
|
} catch (error) {
|
|
46438
46532
|
reportProblem = errorMessage(error);
|
|
46439
46533
|
} finally {
|
|
46440
46534
|
discard(reportsDir, userData);
|
|
46441
46535
|
try {
|
|
46442
|
-
rmdirSync2(
|
|
46536
|
+
rmdirSync2(dirname21(reportsDir));
|
|
46443
46537
|
} catch {}
|
|
46444
46538
|
}
|
|
46445
46539
|
const engineEntries = foldedRepeats(run.log.select({
|
|
@@ -46699,11 +46793,11 @@ class GodotServer {
|
|
|
46699
46793
|
const cached = cachedClasses(projectPath);
|
|
46700
46794
|
const sourceOf = (resourcePath) => {
|
|
46701
46795
|
const contained = resolveWithinProject(projectPath, resourcePath);
|
|
46702
|
-
if (!contained.ok || !
|
|
46796
|
+
if (!contained.ok || !existsSync21(contained.absolutePath)) {
|
|
46703
46797
|
return null;
|
|
46704
46798
|
}
|
|
46705
46799
|
try {
|
|
46706
|
-
return
|
|
46800
|
+
return readFileSync24(contained.absolutePath, "utf8");
|
|
46707
46801
|
} catch {
|
|
46708
46802
|
return null;
|
|
46709
46803
|
}
|
|
@@ -46768,11 +46862,11 @@ class GodotServer {
|
|
|
46768
46862
|
}
|
|
46769
46863
|
sourceOfClass(projectPath, resourcePath) {
|
|
46770
46864
|
const contained = resolveWithinProject(projectPath, resourcePath);
|
|
46771
|
-
if (!contained.ok || !
|
|
46865
|
+
if (!contained.ok || !existsSync21(contained.absolutePath)) {
|
|
46772
46866
|
return null;
|
|
46773
46867
|
}
|
|
46774
46868
|
try {
|
|
46775
|
-
return
|
|
46869
|
+
return readFileSync24(contained.absolutePath, "utf8");
|
|
46776
46870
|
} catch {
|
|
46777
46871
|
return null;
|
|
46778
46872
|
}
|
|
@@ -46920,7 +47014,7 @@ class GodotServer {
|
|
|
46920
47014
|
...Array.isArray(stack) ? {
|
|
46921
47015
|
stack: stack.map((frame) => ({
|
|
46922
47016
|
...frame,
|
|
46923
|
-
...projectPath !== "" && typeof frame["script"] === "string" && frame["script"].startsWith("res://") ? { path:
|
|
47017
|
+
...projectPath !== "" && typeof frame["script"] === "string" && frame["script"].startsWith("res://") ? { path: join28(projectPath, frame["script"].slice("res://".length)) } : {}
|
|
46924
47018
|
}))
|
|
46925
47019
|
} : {}
|
|
46926
47020
|
});
|
|
@@ -47190,7 +47284,7 @@ class GodotServer {
|
|
|
47190
47284
|
return null;
|
|
47191
47285
|
}
|
|
47192
47286
|
try {
|
|
47193
|
-
return settingKeys(
|
|
47287
|
+
return settingKeys(readFileSync24(join28(projectPath, "project.godot"), "utf8"));
|
|
47194
47288
|
} catch {
|
|
47195
47289
|
return null;
|
|
47196
47290
|
}
|
|
@@ -47455,6 +47549,7 @@ class GodotServer {
|
|
|
47455
47549
|
}
|
|
47456
47550
|
async openAnEditor(engine, projectPath, ports, hidden) {
|
|
47457
47551
|
clearEditorLog(projectPath);
|
|
47552
|
+
freeLibraryCopies(projectPath);
|
|
47458
47553
|
const launched = await launchOutsideTheTree({
|
|
47459
47554
|
command: engine,
|
|
47460
47555
|
args: editorArguments(projectPath, ports, editorLogPath(projectPath), hidden),
|
|
@@ -47613,7 +47708,7 @@ class GodotServer {
|
|
|
47613
47708
|
}
|
|
47614
47709
|
async runtimeUp(projectPath, before, budget, withArgs) {
|
|
47615
47710
|
const budgetMs = budget.ms;
|
|
47616
|
-
if (!
|
|
47711
|
+
if (!existsSync21(join28(projectPath, RUNTIME_AUTOLOAD.path))) {
|
|
47617
47712
|
return runtimeVerdict(null, {
|
|
47618
47713
|
addon: false,
|
|
47619
47714
|
budgetMs,
|
|
@@ -47892,7 +47987,7 @@ class GodotServer {
|
|
|
47892
47987
|
return 0;
|
|
47893
47988
|
}
|
|
47894
47989
|
try {
|
|
47895
|
-
return reportAlreadyInTranscript(
|
|
47990
|
+
return reportAlreadyInTranscript(readFileSync24(game.transcript), readFileSync24(report));
|
|
47896
47991
|
} catch (error) {
|
|
47897
47992
|
this.logDebug(`Could not compare a picked-up run's report with its transcript: ${errorMessage(error)}`);
|
|
47898
47993
|
return 0;
|
|
@@ -48572,7 +48667,7 @@ class GodotServer {
|
|
|
48572
48667
|
}
|
|
48573
48668
|
const going = await this.runStillGoing(run);
|
|
48574
48669
|
const projectPath = run.projectPath;
|
|
48575
|
-
const projectGone = projectPath !== null && !
|
|
48670
|
+
const projectGone = projectPath !== null && !existsSync21(join28(projectPath, "project.godot"));
|
|
48576
48671
|
if (projectGone && callersName !== undefined) {
|
|
48577
48672
|
return this.createErrorResponse(`callersOf reads the project's scripts, and the run's project at ${projectPath} has no project.godot any more.`, ["editor_run profile without callersOf answers with the profile itself"]);
|
|
48578
48673
|
}
|
|
@@ -48860,7 +48955,7 @@ class GodotServer {
|
|
|
48860
48955
|
notes.push(endedWithoutACode({
|
|
48861
48956
|
throughEditor: run.throughEditor,
|
|
48862
48957
|
announced: announced !== undefined || run.announcedPid !== undefined,
|
|
48863
|
-
couldAnnounce: run.projectPath !== null &&
|
|
48958
|
+
couldAnnounce: run.projectPath !== null && existsSync21(join28(run.projectPath, RUNTIME_AUTOLOAD.path)),
|
|
48864
48959
|
endedHere: typeof run.endedHere === "string",
|
|
48865
48960
|
pickedUp: run.pickedUp === true
|
|
48866
48961
|
}));
|
|
@@ -49425,7 +49520,7 @@ class GodotServer {
|
|
|
49425
49520
|
if (!scriptPath.ok) {
|
|
49426
49521
|
return this.createErrorResponse(scriptPath.reason);
|
|
49427
49522
|
}
|
|
49428
|
-
if (!
|
|
49523
|
+
if (!existsSync21(scriptPath.absolutePath)) {
|
|
49429
49524
|
return this.createErrorResponse(`Script file does not exist: ${scriptPath.absolutePath}`);
|
|
49430
49525
|
}
|
|
49431
49526
|
const asked = readNonEmptyString(args, "newScriptPath");
|
|
@@ -49753,7 +49848,7 @@ class GodotServer {
|
|
|
49753
49848
|
async ownRunOnItsWay(projectPath, budgetMs) {
|
|
49754
49849
|
const run = await this.currentRun();
|
|
49755
49850
|
const project = projectPath ?? run?.projectPath ?? null;
|
|
49756
|
-
if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !
|
|
49851
|
+
if (run === null || project === null || run.announcedPid !== undefined || run.projectPath !== null && !isSameDirectory(run.projectPath, project) || !existsSync21(join28(project, RUNTIME_AUTOLOAD.path)) || !await this.runStillGoing(run)) {
|
|
49757
49852
|
return null;
|
|
49758
49853
|
}
|
|
49759
49854
|
const already = runtimesAnnounced().running;
|
|
@@ -49838,12 +49933,25 @@ class GodotServer {
|
|
|
49838
49933
|
}
|
|
49839
49934
|
}
|
|
49840
49935
|
const screenshotDir = expectsScreenshot ? scratchDirectory("runtime-screenshot") : null;
|
|
49841
|
-
const screenshotPath = screenshotDir ?
|
|
49936
|
+
const screenshotPath = screenshotDir ? join28(screenshotDir, "capture.png") : null;
|
|
49842
49937
|
const staleNote = this.runtimeStaleNote(choice.endpoint);
|
|
49843
49938
|
const stale = staleNote === undefined ? {} : { addonIsStale: true, staleNote };
|
|
49844
49939
|
const refused = (message) => this.createErrorResponse(staleNote === undefined ? message : `${message}
|
|
49845
49940
|
|
|
49846
49941
|
${staleNote}`);
|
|
49942
|
+
const onGame = {
|
|
49943
|
+
pid: choice.endpoint.pid,
|
|
49944
|
+
what: `${asked.tool} ${asked.op}`,
|
|
49945
|
+
alongside: new Set
|
|
49946
|
+
};
|
|
49947
|
+
for (const other of this.callsOnGames) {
|
|
49948
|
+
if (other.pid === onGame.pid) {
|
|
49949
|
+
other.alongside.add(onGame.what);
|
|
49950
|
+
onGame.alongside.add(other.what);
|
|
49951
|
+
}
|
|
49952
|
+
}
|
|
49953
|
+
this.callsOnGames.add(onGame);
|
|
49954
|
+
const alongside = () => onGame.alongside.size === 0 ? {} : { ranAlongside: [...onGame.alongside], alongsideNote: ALONGSIDE_NOTE };
|
|
49847
49955
|
try {
|
|
49848
49956
|
const reply = await runtimeRequest(choice.endpoint, command, screenshotPath ? { ...params, output_path: screenshotPath } : params, timeoutMs, !expectsScreenshot);
|
|
49849
49957
|
if (!reply.ok && reply.requestId !== undefined) {
|
|
@@ -49854,7 +49962,8 @@ ${staleNote}`);
|
|
|
49854
49962
|
waitedMs: timeoutMs,
|
|
49855
49963
|
note: `${reply.message} ${longerWaitNote(asked.tool, asked.op, timeoutMs)}`,
|
|
49856
49964
|
...answeredBy,
|
|
49857
|
-
...stale
|
|
49965
|
+
...stale,
|
|
49966
|
+
...alongside()
|
|
49858
49967
|
});
|
|
49859
49968
|
}
|
|
49860
49969
|
if (!reply.ok) {
|
|
@@ -49862,7 +49971,7 @@ ${staleNote}`);
|
|
|
49862
49971
|
}
|
|
49863
49972
|
const { id: _id, ...payload } = reply.payload;
|
|
49864
49973
|
if (!expectsScreenshot) {
|
|
49865
|
-
return this.jsonTextResponse({ ...payload, ...answeredBy, ...stale });
|
|
49974
|
+
return this.jsonTextResponse({ ...payload, ...answeredBy, ...stale, ...alongside() });
|
|
49866
49975
|
}
|
|
49867
49976
|
const returnedPath = readString(payload, "path");
|
|
49868
49977
|
if (readString(payload, "type") !== "screenshot_file" || !returnedPath || !screenshotPath) {
|
|
@@ -49879,18 +49988,22 @@ ${staleNote}`);
|
|
|
49879
49988
|
return this.createErrorResponse(`The capture was taken and could not be saved at ${saveTo}: ${errorMessage(error)}`);
|
|
49880
49989
|
}
|
|
49881
49990
|
}
|
|
49991
|
+
const ranWith = [...onGame.alongside];
|
|
49882
49992
|
return {
|
|
49883
49993
|
content: [
|
|
49884
49994
|
{
|
|
49885
49995
|
type: "text",
|
|
49886
|
-
text: `Screenshot captured: ${dimensions}${chosenAmongSeveral ? ` from pid ${own}, the game this server holds` : ""}${captureDetail(payload)}${saveTo === null ? "" : `. Saved to ${saveTo}`}${
|
|
49996
|
+
text: `Screenshot captured: ${dimensions}${chosenAmongSeveral ? ` from pid ${own}, the game this server holds` : ""}${captureDetail(payload)}${saveTo === null ? "" : `. Saved to ${saveTo}`}${ranWith.length === 0 ? "" : `
|
|
49997
|
+
|
|
49998
|
+
Ran alongside ${ranWith.join(", ")}. ${ALONGSIDE_NOTE}`}${staleNote === undefined ? "" : `
|
|
49887
49999
|
|
|
49888
50000
|
${staleNote}`}`
|
|
49889
50001
|
},
|
|
49890
|
-
{ type: "image", data:
|
|
50002
|
+
{ type: "image", data: readFileSync24(screenshotPath).toString("base64"), mimeType: "image/png" }
|
|
49891
50003
|
]
|
|
49892
50004
|
};
|
|
49893
50005
|
} finally {
|
|
50006
|
+
this.callsOnGames.delete(onGame);
|
|
49894
50007
|
discard(screenshotDir);
|
|
49895
50008
|
}
|
|
49896
50009
|
}
|
|
@@ -49989,7 +50102,7 @@ async function runGodotServer() {
|
|
|
49989
50102
|
const server = new GodotServer;
|
|
49990
50103
|
await server.run();
|
|
49991
50104
|
}
|
|
49992
|
-
var UPDATE_NOTICE_EVERY = 500, FEEDBACK_NOTICE_EVERY = 250, run4, __dirname2, PARENT_ASKED_AFTER_MS = 5000, EDITOR_SERVERS_START_MS = 20000, HOLD_PING_MS = 2000, SLOWEST_FRAME_RATE = 20, OWN_DEBUGGER = " Its debugger is the keeper holding it rather than the editor, so the debug_* tools answer for it all the same: breakpoints stop it, and debug_control pause breaks into it wherever it is, which the editor offers no way to do.", PLAY_STARTS_WITHIN_MS = 30000, KEEPER_ANSWER_MS = 15000, KEEPER_DEBUG_MS, EXIT_REPORTED_WITHIN_MS = 2000, CONSOLE_WRAPPER, LONGEST_BOOT_NOTED_MS, PROFILE_SEND_MS = 5000, MOST_GROUPS = 20, RUNTIME_LISTENING_LINE = "[gdharness] runtime listening on ", VALUE_NAMES, BRIDGE_RETRY_MS = 2000, SUCCESSOR_CHECK_MS = 1e4, CONSOLE_WATCH_MS = 250, BOUNDARY_WAIT_MS = 2000, HANDOVER_MS, HANDOVER_POLL_MS = 250, CACHE_WRITE_MS = 2000, STREAMS_GRACE_MS = 2000, PLAYING_STATUS_MS = 1000, SCAN_START_MS = 2000, SCAN_SETTLED_MS = 500, REIMPORT_TIMEOUT_MS = 300000, EDITOR_FREE_INSTEAD, OPS_ELSEWHERE, AUDIO_BUS_OPS, STALLED_AFTER_MS = 30000, TEST_HEARTBEAT_MS = 20000, DEPENDED_FAILED = "Failed to compile depended scripts", WAIT_FOR_RUN_MS = 600000, RUN_POLL_MS = 250, PATH_SOLUTIONS, PROJECT_FILE_ARGUMENTS, DEBUG_STATE_CALLS, PROJECT_INFO_SECTIONS2, RUNNER_DIRECTORY = "addons/gdUnit4/", PROFILE_FUNCTIONS = 30, PROFILER_ON_MS = 3000, PROPERTY_PLACES = "It is a property, so each place says whether it writes it (access write), which runs its set block, or reads it (access read), which runs its get block: withinCalls on a read says nothing of the set block, nor on a write of the get block unless the write is a compound one such as +=. Inside the property's own blocks its name is the value stored, which the engine reads and writes without running them, so those lines are not listed.", CALLERS_FOUND_BY_NAME = "Found by name in the project's scripts, since the engine's profiler counts calls and time per function and records nothing about who made them: a method of the same name on another class is listed too, unless one class was asked about and it is called through another class by name or through a variable declared as one. Each place carries the profile's numbers for the function it is written in.", MOST_ENGINE_ENTRIES = 200, ERROR_ASSERT = "GdUnitGodotErrorAssertImpl.gd", EXTERNAL_MEMBER = 'Could not resolve external class member "', STATIC_LIST_HINT;
|
|
50105
|
+
var UPDATE_NOTICE_EVERY = 500, FEEDBACK_NOTICE_EVERY = 250, run4, __dirname2, PARENT_ASKED_AFTER_MS = 5000, EDITOR_SERVERS_START_MS = 20000, HOLD_PING_MS = 2000, SLOWEST_FRAME_RATE = 20, ALONGSIDE_NOTE = "Another call on this game was running while this one was: calls sent together run together and are answered as each finishes, so this answer is not from after the other. Send a call meant to come after another once that one has answered.", OWN_DEBUGGER = " Its debugger is the keeper holding it rather than the editor, so the debug_* tools answer for it all the same: breakpoints stop it, and debug_control pause breaks into it wherever it is, which the editor offers no way to do.", PLAY_STARTS_WITHIN_MS = 30000, KEEPER_ANSWER_MS = 15000, KEEPER_DEBUG_MS, EXIT_REPORTED_WITHIN_MS = 2000, CONSOLE_WRAPPER, LONGEST_BOOT_NOTED_MS, PROFILE_SEND_MS = 5000, MOST_GROUPS = 20, RUNTIME_LISTENING_LINE = "[gdharness] runtime listening on ", VALUE_NAMES, BRIDGE_RETRY_MS = 2000, SUCCESSOR_CHECK_MS = 1e4, CONSOLE_WATCH_MS = 250, BOUNDARY_WAIT_MS = 2000, HANDOVER_MS, HANDOVER_POLL_MS = 250, CACHE_WRITE_MS = 2000, STREAMS_GRACE_MS = 2000, PLAYING_STATUS_MS = 1000, SCAN_START_MS = 2000, SCAN_SETTLED_MS = 500, REIMPORT_TIMEOUT_MS = 300000, EDITOR_FREE_INSTEAD, OPS_ELSEWHERE, AUDIO_BUS_OPS, STALLED_AFTER_MS = 30000, TEST_HEARTBEAT_MS = 20000, DEPENDED_FAILED = "Failed to compile depended scripts", WAIT_FOR_RUN_MS = 600000, RUN_POLL_MS = 250, PATH_SOLUTIONS, PROJECT_FILE_ARGUMENTS, DEBUG_STATE_CALLS, PROJECT_INFO_SECTIONS2, RUNNER_DIRECTORY = "addons/gdUnit4/", PROFILE_FUNCTIONS = 30, PROFILER_ON_MS = 3000, PROPERTY_PLACES = "It is a property, so each place says whether it writes it (access write), which runs its set block, or reads it (access read), which runs its get block: withinCalls on a read says nothing of the set block, nor on a write of the get block unless the write is a compound one such as +=. Inside the property's own blocks its name is the value stored, which the engine reads and writes without running them, so those lines are not listed.", CALLERS_FOUND_BY_NAME = "Found by name in the project's scripts, since the engine's profiler counts calls and time per function and records nothing about who made them: a method of the same name on another class is listed too, unless one class was asked about and it is called through another class by name or through a variable declared as one. Each place carries the profile's numbers for the function it is written in.", MOST_ENGINE_ENTRIES = 200, ERROR_ASSERT = "GdUnitGodotErrorAssertImpl.gd", EXTERNAL_MEMBER = 'Could not resolve external class member "', STATIC_LIST_HINT;
|
|
49993
50106
|
var init_server = __esm(() => {
|
|
49994
50107
|
init_dist();
|
|
49995
50108
|
init_stdio();
|
|
@@ -50019,6 +50132,7 @@ var init_server = __esm(() => {
|
|
|
50019
50132
|
init_junit();
|
|
50020
50133
|
init_keeper_channel();
|
|
50021
50134
|
init_launch();
|
|
50135
|
+
init_library_copies();
|
|
50022
50136
|
init_lifecycle_log();
|
|
50023
50137
|
init_lsp_client();
|
|
50024
50138
|
init_outside();
|
|
@@ -50045,7 +50159,7 @@ var init_server = __esm(() => {
|
|
|
50045
50159
|
init_tool_reference();
|
|
50046
50160
|
init_update_check();
|
|
50047
50161
|
run4 = promisify5(execFile5);
|
|
50048
|
-
__dirname2 =
|
|
50162
|
+
__dirname2 = dirname21(fileURLToPath5(import.meta.url));
|
|
50049
50163
|
KEEPER_DEBUG_MS = PAUSE_MS + STEP_MS + 2 * READ_MS;
|
|
50050
50164
|
CONSOLE_WRAPPER = /_console(\.exe)?$/i;
|
|
50051
50165
|
LONGEST_BOOT_NOTED_MS = 5 * 60000;
|
|
@@ -50104,8 +50218,8 @@ var init_server = __esm(() => {
|
|
|
50104
50218
|
init_bridge_announce();
|
|
50105
50219
|
init_errors();
|
|
50106
50220
|
init_godot_path();
|
|
50107
|
-
import { existsSync as
|
|
50108
|
-
import { join as
|
|
50221
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
50222
|
+
import { join as join29, resolve as resolve8 } from "node:path";
|
|
50109
50223
|
|
|
50110
50224
|
// src/harnesses.ts
|
|
50111
50225
|
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
@@ -51070,10 +51184,10 @@ init_setup();
|
|
|
51070
51184
|
init_setup();
|
|
51071
51185
|
init_tool_definitions();
|
|
51072
51186
|
init_tool_reference();
|
|
51073
|
-
import { existsSync as
|
|
51074
|
-
import { basename as
|
|
51187
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync5, readdirSync as readdirSync8, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
51188
|
+
import { basename as basename5, dirname as dirname7, join as join13 } from "node:path";
|
|
51075
51189
|
var SKILL_NAME = "gdharness";
|
|
51076
|
-
var SHARED_SKILLS =
|
|
51190
|
+
var SHARED_SKILLS = join13(".agents", "skills");
|
|
51077
51191
|
function skillMarkdown(version) {
|
|
51078
51192
|
return `---
|
|
51079
51193
|
name: ${SKILL_NAME}
|
|
@@ -51279,27 +51393,27 @@ comes back separately, under \`engine_messages_after_answer\`: none of it change
|
|
|
51279
51393
|
function skillFiles(version) {
|
|
51280
51394
|
return new Map([
|
|
51281
51395
|
["SKILL.md", skillMarkdown(version)],
|
|
51282
|
-
[
|
|
51396
|
+
[join13("references", "tools.md"), renderToolsMarkdown()]
|
|
51283
51397
|
]);
|
|
51284
51398
|
}
|
|
51285
51399
|
function skillDirectories(harnesses, projectPath, exists) {
|
|
51286
|
-
const directories = [
|
|
51400
|
+
const directories = [join13(projectPath, SHARED_SKILLS, SKILL_NAME)];
|
|
51287
51401
|
for (const harness of harnesses) {
|
|
51288
51402
|
if (harness.skills === undefined) {
|
|
51289
51403
|
continue;
|
|
51290
51404
|
}
|
|
51291
|
-
const own =
|
|
51292
|
-
if ((!harness.skills.shared || exists(own)) && !directories.includes(
|
|
51293
|
-
directories.push(
|
|
51405
|
+
const own = join13(projectPath, harness.skills.dir);
|
|
51406
|
+
if ((!harness.skills.shared || exists(own)) && !directories.includes(join13(own, SKILL_NAME))) {
|
|
51407
|
+
directories.push(join13(own, SKILL_NAME));
|
|
51294
51408
|
}
|
|
51295
51409
|
}
|
|
51296
51410
|
return directories;
|
|
51297
51411
|
}
|
|
51298
51412
|
function everySkillDirectory(projectPath, harnesses) {
|
|
51299
|
-
const directories = new Set([
|
|
51413
|
+
const directories = new Set([join13(projectPath, SHARED_SKILLS, SKILL_NAME)]);
|
|
51300
51414
|
for (const harness of harnesses) {
|
|
51301
51415
|
if (harness.skills !== undefined) {
|
|
51302
|
-
directories.add(
|
|
51416
|
+
directories.add(join13(projectPath, harness.skills.dir, SKILL_NAME));
|
|
51303
51417
|
}
|
|
51304
51418
|
}
|
|
51305
51419
|
return [...directories];
|
|
@@ -51307,33 +51421,33 @@ function everySkillDirectory(projectPath, harnesses) {
|
|
|
51307
51421
|
function removeSkill(directories, projectPath) {
|
|
51308
51422
|
const removed = [];
|
|
51309
51423
|
for (const directory of directories) {
|
|
51310
|
-
if (
|
|
51424
|
+
if (existsSync13(directory)) {
|
|
51311
51425
|
rmSync6(directory, { recursive: true, force: true });
|
|
51312
|
-
pruneEmpty(
|
|
51426
|
+
pruneEmpty(dirname7(directory), projectPath);
|
|
51313
51427
|
removed.push(directory);
|
|
51314
51428
|
}
|
|
51315
51429
|
}
|
|
51316
51430
|
return removed;
|
|
51317
51431
|
}
|
|
51318
51432
|
function pruneEmpty(directory, projectPath) {
|
|
51319
|
-
const shared =
|
|
51433
|
+
const shared = join13(projectPath, ".agents");
|
|
51320
51434
|
let path = directory;
|
|
51321
|
-
while (path !== projectPath && (
|
|
51322
|
-
if (
|
|
51435
|
+
while (path !== projectPath && (basename5(path) === "skills" || path === shared)) {
|
|
51436
|
+
if (readdirSync8(path).length > 0) {
|
|
51323
51437
|
return;
|
|
51324
51438
|
}
|
|
51325
51439
|
rmSync6(path, { recursive: true, force: true });
|
|
51326
|
-
path =
|
|
51440
|
+
path = dirname7(path);
|
|
51327
51441
|
}
|
|
51328
51442
|
}
|
|
51329
51443
|
function writeSkill(directories, version) {
|
|
51330
51444
|
const files = skillFiles(version);
|
|
51331
51445
|
return directories.map((directory) => {
|
|
51332
|
-
const replaced =
|
|
51446
|
+
const replaced = existsSync13(directory);
|
|
51333
51447
|
rmSync6(directory, { recursive: true, force: true });
|
|
51334
51448
|
for (const [name, contents] of files) {
|
|
51335
|
-
const path =
|
|
51336
|
-
mkdirSync5(
|
|
51449
|
+
const path = join13(directory, name);
|
|
51450
|
+
mkdirSync5(dirname7(path), { recursive: true });
|
|
51337
51451
|
writeFileSync7(path, contents, "utf8");
|
|
51338
51452
|
}
|
|
51339
51453
|
return { path: directory, replaced };
|
|
@@ -51341,18 +51455,18 @@ function writeSkill(directories, version) {
|
|
|
51341
51455
|
}
|
|
51342
51456
|
|
|
51343
51457
|
// src/version.ts
|
|
51344
|
-
import { readFileSync as
|
|
51345
|
-
import { dirname as
|
|
51458
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
51459
|
+
import { dirname as dirname8, join as join14 } from "node:path";
|
|
51346
51460
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
51347
51461
|
function getLocalVersion() {
|
|
51348
|
-
const currentDirectory =
|
|
51462
|
+
const currentDirectory = dirname8(fileURLToPath2(import.meta.url));
|
|
51349
51463
|
const packageCandidates = [
|
|
51350
|
-
|
|
51351
|
-
|
|
51464
|
+
join14(currentDirectory, "..", "package.json"),
|
|
51465
|
+
join14(currentDirectory, "..", "..", "package.json")
|
|
51352
51466
|
];
|
|
51353
51467
|
for (const packagePath of packageCandidates) {
|
|
51354
51468
|
try {
|
|
51355
|
-
const value = JSON.parse(
|
|
51469
|
+
const value = JSON.parse(readFileSync12(packagePath, "utf-8"));
|
|
51356
51470
|
if (typeof value === "object" && value !== null && "name" in value && value.name === "gdharness" && "version" in value && typeof value.version === "string") {
|
|
51357
51471
|
return value.version;
|
|
51358
51472
|
}
|
|
@@ -51370,7 +51484,7 @@ class UsageError extends Refusal {
|
|
|
51370
51484
|
function projectArgument(at) {
|
|
51371
51485
|
const named = args.slice(at).find((value) => !value.startsWith("--"));
|
|
51372
51486
|
const projectPath = resolve8(named ?? ".");
|
|
51373
|
-
if (!
|
|
51487
|
+
if (!existsSync22(join29(projectPath, "project.godot"))) {
|
|
51374
51488
|
throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
|
|
51375
51489
|
}
|
|
51376
51490
|
return projectPath;
|
|
@@ -51415,7 +51529,7 @@ async function registerRuntime(godot, projectPath) {
|
|
|
51415
51529
|
return;
|
|
51416
51530
|
}
|
|
51417
51531
|
console.log(`${RUNTIME_AUTOLOAD.name} autoload left at ${named}, which this project registers itself`);
|
|
51418
|
-
if (!
|
|
51532
|
+
if (!existsSync22(join29(projectPath, (named ?? "").replace(/^res:\/\//, "")))) {
|
|
51419
51533
|
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}`);
|
|
51420
51534
|
}
|
|
51421
51535
|
}
|
|
@@ -51547,7 +51661,7 @@ async function setup() {
|
|
|
51547
51661
|
console.log("no harness configured; name one yourself, and gdharness harnesses lists them all");
|
|
51548
51662
|
}
|
|
51549
51663
|
if (!args.includes("--no-skill")) {
|
|
51550
|
-
const directories = skillDirectories(chosen.harnesses, projectPath,
|
|
51664
|
+
const directories = skillDirectories(chosen.harnesses, projectPath, existsSync22);
|
|
51551
51665
|
for (const written of writeSkill(directories, getLocalVersion())) {
|
|
51552
51666
|
console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
|
|
51553
51667
|
}
|
|
@@ -51661,7 +51775,7 @@ async function upgrade() {
|
|
|
51661
51775
|
moved.push(took.from);
|
|
51662
51776
|
}
|
|
51663
51777
|
}
|
|
51664
|
-
for (const written of writeSkill(skillDirectories(already, projectPath,
|
|
51778
|
+
for (const written of writeSkill(skillDirectories(already, projectPath, existsSync22), version)) {
|
|
51665
51779
|
console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
|
|
51666
51780
|
}
|
|
51667
51781
|
console.log(`
|