gdharness 0.5.2 → 0.5.4
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 +228 -193
- package/build/index.js +53 -34
- package/package.json +1 -1
package/build/cli.js
CHANGED
|
@@ -7139,14 +7139,32 @@ var init_errors = __esm(() => {
|
|
|
7139
7139
|
});
|
|
7140
7140
|
|
|
7141
7141
|
// src/runner.ts
|
|
7142
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
7143
|
+
import { dirname, join as join2 } from "node:path";
|
|
7144
|
+
import process2 from "node:process";
|
|
7142
7145
|
function currentRunner() {
|
|
7143
|
-
const versions =
|
|
7146
|
+
const versions = process2.versions;
|
|
7144
7147
|
return versions["bun"] === undefined ? "npx" : "bunx";
|
|
7145
7148
|
}
|
|
7146
7149
|
function runLine(runner, version, rest = "") {
|
|
7147
7150
|
const flag = runner === "npx" ? "-y " : "";
|
|
7148
7151
|
return `${runner} ${flag}gdharness@${version}${rest === "" ? "" : ` ${rest}`}`;
|
|
7149
7152
|
}
|
|
7153
|
+
function spawnFor(runner, version, execPath = process2.execPath) {
|
|
7154
|
+
const spec = `gdharness@${version}`;
|
|
7155
|
+
if (runner !== currentRunner()) {
|
|
7156
|
+
return { command: runner, args: runner === "npx" ? ["-y", spec] : [spec] };
|
|
7157
|
+
}
|
|
7158
|
+
if (runner === "bunx") {
|
|
7159
|
+
return { command: execPath, args: ["x", spec] };
|
|
7160
|
+
}
|
|
7161
|
+
return { command: alongside(execPath, "npx") ?? "npx", args: ["-y", spec] };
|
|
7162
|
+
}
|
|
7163
|
+
function alongside(execPath, name) {
|
|
7164
|
+
const runner = join2(dirname(execPath), process2.platform === "win32" ? `${name}.cmd` : name);
|
|
7165
|
+
return existsSync3(runner) ? runner : undefined;
|
|
7166
|
+
}
|
|
7167
|
+
var init_runner = () => {};
|
|
7150
7168
|
|
|
7151
7169
|
// src/dictionary.ts
|
|
7152
7170
|
function emptyRecord() {
|
|
@@ -7242,9 +7260,9 @@ var init_game_log = __esm(() => {
|
|
|
7242
7260
|
});
|
|
7243
7261
|
|
|
7244
7262
|
// src/update-check.ts
|
|
7245
|
-
import { existsSync as
|
|
7263
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
7246
7264
|
import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
|
|
7247
|
-
import { join as
|
|
7265
|
+
import { join as join5 } from "node:path";
|
|
7248
7266
|
function cacheDirectory(environment) {
|
|
7249
7267
|
const set = (name) => {
|
|
7250
7268
|
const value = environment[name];
|
|
@@ -7252,25 +7270,25 @@ function cacheDirectory(environment) {
|
|
|
7252
7270
|
};
|
|
7253
7271
|
const home = set("HOME") ?? homedir3();
|
|
7254
7272
|
if (process.platform === "win32") {
|
|
7255
|
-
return
|
|
7273
|
+
return join5(set("LOCALAPPDATA") ?? home, "gdharness");
|
|
7256
7274
|
}
|
|
7257
7275
|
if (process.platform === "darwin") {
|
|
7258
|
-
return
|
|
7276
|
+
return join5(home, "Library", "Caches", "gdharness");
|
|
7259
7277
|
}
|
|
7260
|
-
return
|
|
7278
|
+
return join5(set("XDG_CACHE_HOME") ?? join5(home, ".cache"), "gdharness");
|
|
7261
7279
|
}
|
|
7262
7280
|
function cacheFile(environment = process.env) {
|
|
7263
7281
|
try {
|
|
7264
7282
|
const directory = cacheDirectory(environment);
|
|
7265
7283
|
mkdirSync2(directory, { recursive: true, mode: 448 });
|
|
7266
|
-
return
|
|
7284
|
+
return join5(directory, "update-check.json");
|
|
7267
7285
|
} catch {
|
|
7268
|
-
return
|
|
7286
|
+
return join5(tmpdir2(), "gdharness-update-check.json");
|
|
7269
7287
|
}
|
|
7270
7288
|
}
|
|
7271
7289
|
function readCache(path) {
|
|
7272
7290
|
try {
|
|
7273
|
-
if (!
|
|
7291
|
+
if (!existsSync5(path)) {
|
|
7274
7292
|
return null;
|
|
7275
7293
|
}
|
|
7276
7294
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
@@ -7403,6 +7421,7 @@ class UpdateCheck {
|
|
|
7403
7421
|
}
|
|
7404
7422
|
var REGISTRY = "https://registry.npmjs.org/gdharness/latest", RELEASES = "https://github.com/Aureliolo/gdharness/releases/tag", CACHE_MS, REQUEST_TIMEOUT_MS = 1e4, MAX_BODY_BYTES, FIRST_RETRY_MS = 30000, MAX_RETRY_MS, VERSION;
|
|
7405
7423
|
var init_update_check = __esm(() => {
|
|
7424
|
+
init_runner();
|
|
7406
7425
|
CACHE_MS = 4 * 60 * 60 * 1000;
|
|
7407
7426
|
MAX_BODY_BYTES = 1 << 20;
|
|
7408
7427
|
MAX_RETRY_MS = 60 * 60 * 1000;
|
|
@@ -7439,8 +7458,8 @@ var init_server_version = __esm(() => {
|
|
|
7439
7458
|
});
|
|
7440
7459
|
|
|
7441
7460
|
// src/class-cache.ts
|
|
7442
|
-
import { existsSync as
|
|
7443
|
-
import { join as
|
|
7461
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync5 } from "node:fs";
|
|
7462
|
+
import { join as join6 } from "node:path";
|
|
7444
7463
|
function declaredClasses(projectPath) {
|
|
7445
7464
|
const declared = new Map;
|
|
7446
7465
|
const visit = (directory, prefix) => {
|
|
@@ -7448,7 +7467,7 @@ function declaredClasses(projectPath) {
|
|
|
7448
7467
|
if (entry.name.startsWith(".")) {
|
|
7449
7468
|
continue;
|
|
7450
7469
|
}
|
|
7451
|
-
const path =
|
|
7470
|
+
const path = join6(directory, entry.name);
|
|
7452
7471
|
if (entry.isDirectory()) {
|
|
7453
7472
|
visit(path, `${prefix}${entry.name}/`);
|
|
7454
7473
|
} else if (entry.isFile() && entry.name.endsWith(".gd")) {
|
|
@@ -7463,8 +7482,8 @@ function declaredClasses(projectPath) {
|
|
|
7463
7482
|
return declared;
|
|
7464
7483
|
}
|
|
7465
7484
|
function cachedClasses(projectPath) {
|
|
7466
|
-
const cache =
|
|
7467
|
-
if (!
|
|
7485
|
+
const cache = join6(projectPath, ".godot", "global_script_class_cache.cfg");
|
|
7486
|
+
if (!existsSync6(cache)) {
|
|
7468
7487
|
return null;
|
|
7469
7488
|
}
|
|
7470
7489
|
const listed = new Map;
|
|
@@ -7487,7 +7506,7 @@ var init_class_cache = () => {};
|
|
|
7487
7506
|
import { execFile as execFile3 } from "node:child_process";
|
|
7488
7507
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
7489
7508
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
7490
|
-
import { join as
|
|
7509
|
+
import { join as join7 } from "node:path";
|
|
7491
7510
|
import { promisify as promisify3 } from "node:util";
|
|
7492
7511
|
function snakeCased2(params) {
|
|
7493
7512
|
const result = emptyRecord();
|
|
@@ -7527,8 +7546,8 @@ function reason2(stdout, stderr) {
|
|
|
7527
7546
|
return stdout.trim().split(/\r?\n/).at(-1) ?? "no output at all";
|
|
7528
7547
|
}
|
|
7529
7548
|
async function runOperation2(engine, operation, params, projectPath) {
|
|
7530
|
-
const paramsDir = mkdtempSync2(
|
|
7531
|
-
const paramsFile =
|
|
7549
|
+
const paramsDir = mkdtempSync2(join7(tmpdir3(), "gdharness-params-"));
|
|
7550
|
+
const paramsFile = join7(paramsDir, `${operation}.json`);
|
|
7532
7551
|
writeFileSync4(paramsFile, JSON.stringify(snakeCased2(params)), "utf8");
|
|
7533
7552
|
const args = [
|
|
7534
7553
|
"--headless",
|
|
@@ -30552,10 +30571,10 @@ var init_stdio = __esm(() => {
|
|
|
30552
30571
|
});
|
|
30553
30572
|
|
|
30554
30573
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
30555
|
-
import
|
|
30574
|
+
import process6 from "node:process";
|
|
30556
30575
|
|
|
30557
30576
|
class StdioServerTransport {
|
|
30558
|
-
constructor(_stdin =
|
|
30577
|
+
constructor(_stdin = process6.stdin, _stdout = process6.stdout, options) {
|
|
30559
30578
|
this._stdin = _stdin;
|
|
30560
30579
|
this._stdout = _stdout;
|
|
30561
30580
|
this._started = false;
|
|
@@ -34491,7 +34510,7 @@ var init_godot_bridge = __esm(() => {
|
|
|
34491
34510
|
|
|
34492
34511
|
// src/godot-path.ts
|
|
34493
34512
|
import { execFile as execFile4 } from "node:child_process";
|
|
34494
|
-
import { existsSync as
|
|
34513
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
34495
34514
|
import { normalize as normalize2 } from "node:path";
|
|
34496
34515
|
import { promisify as promisify4 } from "node:util";
|
|
34497
34516
|
var run4, GodotLocator2;
|
|
@@ -34533,7 +34552,7 @@ var init_godot_path = __esm(() => {
|
|
|
34533
34552
|
return known;
|
|
34534
34553
|
}
|
|
34535
34554
|
let ok = false;
|
|
34536
|
-
if (path === "godot" ||
|
|
34555
|
+
if (path === "godot" || existsSync9(path)) {
|
|
34537
34556
|
try {
|
|
34538
34557
|
await run4(path, ["--version"]);
|
|
34539
34558
|
ok = true;
|
|
@@ -34549,7 +34568,7 @@ var init_godot_path = __esm(() => {
|
|
|
34549
34568
|
|
|
34550
34569
|
// src/issues.ts
|
|
34551
34570
|
import { createHash as createHash2 } from "node:crypto";
|
|
34552
|
-
import
|
|
34571
|
+
import process7 from "node:process";
|
|
34553
34572
|
function feedbackNotice() {
|
|
34554
34573
|
return JSON.stringify({
|
|
34555
34574
|
gdharness_feedback: {
|
|
@@ -34559,9 +34578,9 @@ function feedbackNotice() {
|
|
|
34559
34578
|
}, null, 2);
|
|
34560
34579
|
}
|
|
34561
34580
|
function runtime2() {
|
|
34562
|
-
const versions =
|
|
34581
|
+
const versions = process7.versions;
|
|
34563
34582
|
const bun = versions["bun"];
|
|
34564
|
-
return bun === undefined ? `node ${
|
|
34583
|
+
return bun === undefined ? `node ${process7.versions.node}` : `bun ${bun}`;
|
|
34565
34584
|
}
|
|
34566
34585
|
function defectSignature2(where, message) {
|
|
34567
34586
|
const normalised = `${where}
|
|
@@ -34573,7 +34592,7 @@ function facts2(where, message, godotVersion) {
|
|
|
34573
34592
|
["Where", where],
|
|
34574
34593
|
["Error", message],
|
|
34575
34594
|
["Version", `gdharness ${SERVER_VERSION}`],
|
|
34576
|
-
["Runtime", `${runtime2()}, ${
|
|
34595
|
+
["Runtime", `${runtime2()}, ${process7.platform} ${process7.arch}`],
|
|
34577
34596
|
["Godot", godotVersion ?? "not known at the point this failed"],
|
|
34578
34597
|
["Signature", defectSignature2(where, message)]
|
|
34579
34598
|
];
|
|
@@ -34583,7 +34602,7 @@ function filledTemplate2(where, message, godotVersion) {
|
|
|
34583
34602
|
`**gdharness version**: ${SERVER_VERSION}`,
|
|
34584
34603
|
`**Godot version**: ${godotVersion ?? ""}`,
|
|
34585
34604
|
`**Bun version**: ${runtime2()}`,
|
|
34586
|
-
`**OS**: ${
|
|
34605
|
+
`**OS**: ${process7.platform} ${process7.arch}`,
|
|
34587
34606
|
"**MCP client**:",
|
|
34588
34607
|
"",
|
|
34589
34608
|
"## What you did",
|
|
@@ -34836,7 +34855,7 @@ var init_junit = __esm(() => {
|
|
|
34836
34855
|
import { realpathSync } from "node:fs";
|
|
34837
34856
|
import { readFile, realpath } from "node:fs/promises";
|
|
34838
34857
|
import { createConnection as createConnection2 } from "node:net";
|
|
34839
|
-
import { dirname as
|
|
34858
|
+
import { dirname as dirname6, resolve as resolve3 } from "node:path";
|
|
34840
34859
|
import { fileURLToPath as fileURLToPath3, pathToFileURL } from "node:url";
|
|
34841
34860
|
function diagnosticsKey(uri) {
|
|
34842
34861
|
let decoded;
|
|
@@ -34962,7 +34981,7 @@ class GodotLSPClient {
|
|
|
34962
34981
|
if (this.initialized) {
|
|
34963
34982
|
return;
|
|
34964
34983
|
}
|
|
34965
|
-
const rootPath = this.rootPath ??
|
|
34984
|
+
const rootPath = this.rootPath ?? dirname6(resolve3(filePath));
|
|
34966
34985
|
await this.initialize(rootPath);
|
|
34967
34986
|
}
|
|
34968
34987
|
async sendRequest(method, params) {
|
|
@@ -35337,7 +35356,7 @@ var init_lsp_client = __esm(() => {
|
|
|
35337
35356
|
|
|
35338
35357
|
// src/project-scan.ts
|
|
35339
35358
|
import { readdirSync as readdirSync4, readFileSync as readFileSync9 } from "node:fs";
|
|
35340
|
-
import { join as
|
|
35359
|
+
import { join as join11 } from "node:path";
|
|
35341
35360
|
function projectStructure(projectPath) {
|
|
35342
35361
|
const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
|
|
35343
35362
|
const visit = (directory) => {
|
|
@@ -35346,7 +35365,7 @@ function projectStructure(projectPath) {
|
|
|
35346
35365
|
continue;
|
|
35347
35366
|
}
|
|
35348
35367
|
if (entry.isDirectory()) {
|
|
35349
|
-
visit(
|
|
35368
|
+
visit(join11(directory, entry.name));
|
|
35350
35369
|
} else if (entry.isFile()) {
|
|
35351
35370
|
const extension = entry.name.split(".").pop()?.toLowerCase() ?? "";
|
|
35352
35371
|
if (extension === "tscn") {
|
|
@@ -35388,7 +35407,7 @@ function searchProject(projectPath, options) {
|
|
|
35388
35407
|
if (SKIPPED.has(entry.name)) {
|
|
35389
35408
|
continue;
|
|
35390
35409
|
}
|
|
35391
|
-
const entryPath =
|
|
35410
|
+
const entryPath = join11(directory, entry.name);
|
|
35392
35411
|
if (entry.isDirectory()) {
|
|
35393
35412
|
visit(entryPath);
|
|
35394
35413
|
continue;
|
|
@@ -35427,23 +35446,23 @@ var init_project_scan = __esm(() => {
|
|
|
35427
35446
|
});
|
|
35428
35447
|
|
|
35429
35448
|
// src/runtime-client.ts
|
|
35430
|
-
import { existsSync as
|
|
35449
|
+
import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync10, unlinkSync } from "node:fs";
|
|
35431
35450
|
import { createConnection as createConnection3 } from "node:net";
|
|
35432
35451
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
35433
|
-
import { join as
|
|
35452
|
+
import { join as join12, resolve as resolve4 } from "node:path";
|
|
35434
35453
|
function runtimeDirectory(variables = process.env) {
|
|
35435
35454
|
const explicit = envValue("GDHARNESS_RUNTIME_DIR", variables);
|
|
35436
35455
|
if (explicit) {
|
|
35437
35456
|
return explicit;
|
|
35438
35457
|
}
|
|
35439
35458
|
const perUser = envValue("XDG_RUNTIME_DIR", variables);
|
|
35440
|
-
return
|
|
35459
|
+
return join12(perUser ?? tmpdir4(), "gdharness");
|
|
35441
35460
|
}
|
|
35442
35461
|
function runtimeDirectories(variables = process.env) {
|
|
35443
35462
|
const candidates = [runtimeDirectory(variables)];
|
|
35444
35463
|
const fallbacks = process.platform === "win32" ? [envValue("SystemRoot", variables) ?? envValue("windir", variables) ?? "C:\\Windows"] : ["/tmp", "/var/tmp"];
|
|
35445
35464
|
for (const base of fallbacks) {
|
|
35446
|
-
candidates.push(
|
|
35465
|
+
candidates.push(join12(base, process.platform === "win32" ? "Temp" : "", "gdharness"));
|
|
35447
35466
|
}
|
|
35448
35467
|
return [...new Set(candidates.map((path) => resolve4(path)))];
|
|
35449
35468
|
}
|
|
@@ -35460,35 +35479,44 @@ function parseAnnouncement(file, pid) {
|
|
|
35460
35479
|
try {
|
|
35461
35480
|
fields = asParams(JSON.parse(readFileSync10(file, "utf8")));
|
|
35462
35481
|
} catch {
|
|
35463
|
-
return
|
|
35482
|
+
return { kind: "rubbish" };
|
|
35464
35483
|
}
|
|
35465
35484
|
const project = readParams(fields, "project");
|
|
35466
35485
|
const port = readNumber(fields, "port");
|
|
35467
35486
|
const address = readString(fields, "address");
|
|
35468
|
-
|
|
35469
|
-
|
|
35487
|
+
const protocol = readNumber(fields, "protocol");
|
|
35488
|
+
if (readNumber(fields, "pid") !== pid || port === undefined || !Number.isInteger(port) || port < 1 || port > 65535 || address === undefined || project === undefined) {
|
|
35489
|
+
return { kind: "rubbish" };
|
|
35470
35490
|
}
|
|
35471
|
-
|
|
35472
|
-
|
|
35473
|
-
|
|
35474
|
-
address,
|
|
35475
|
-
project: { name: readString(project, "name") ?? "", path: readString(project, "path") ?? "" },
|
|
35476
|
-
file
|
|
35491
|
+
const named = {
|
|
35492
|
+
name: readString(project, "name") ?? "",
|
|
35493
|
+
path: readString(project, "path") ?? ""
|
|
35477
35494
|
};
|
|
35495
|
+
if (protocol !== RUNTIME_PROTOCOL) {
|
|
35496
|
+
return { kind: "unspoken", unspoken: { pid, protocol: protocol ?? 0, project: named } };
|
|
35497
|
+
}
|
|
35498
|
+
return { kind: "runtime", endpoint: { pid, port, address, project: named, file } };
|
|
35478
35499
|
}
|
|
35479
|
-
function
|
|
35480
|
-
const
|
|
35500
|
+
function runtimesAnnounced(directories = runtimeDirectories()) {
|
|
35501
|
+
const running = new Map;
|
|
35502
|
+
const unspoken = new Map;
|
|
35481
35503
|
for (const directory of directories) {
|
|
35482
|
-
for (const
|
|
35483
|
-
if (
|
|
35484
|
-
|
|
35504
|
+
for (const found of announcedIn(directory)) {
|
|
35505
|
+
if (found.kind === "runtime" && !running.has(found.endpoint.pid)) {
|
|
35506
|
+
running.set(found.endpoint.pid, found.endpoint);
|
|
35507
|
+
} else if (found.kind === "unspoken" && !unspoken.has(found.unspoken.pid)) {
|
|
35508
|
+
unspoken.set(found.unspoken.pid, found.unspoken);
|
|
35485
35509
|
}
|
|
35486
35510
|
}
|
|
35487
35511
|
}
|
|
35488
|
-
|
|
35512
|
+
const newest = (a, b) => b.pid - a.pid;
|
|
35513
|
+
return { running: [...running.values()].sort(newest), unspoken: [...unspoken.values()].sort(newest) };
|
|
35514
|
+
}
|
|
35515
|
+
function discoverRuntimes(directories = runtimeDirectories()) {
|
|
35516
|
+
return runtimesAnnounced(directories).running;
|
|
35489
35517
|
}
|
|
35490
35518
|
function announcedIn(directory) {
|
|
35491
|
-
if (!
|
|
35519
|
+
if (!existsSync10(directory)) {
|
|
35492
35520
|
return [];
|
|
35493
35521
|
}
|
|
35494
35522
|
const found = [];
|
|
@@ -35497,24 +35525,32 @@ function announcedIn(directory) {
|
|
|
35497
35525
|
if (!match) {
|
|
35498
35526
|
continue;
|
|
35499
35527
|
}
|
|
35500
|
-
const file =
|
|
35528
|
+
const file = join12(directory, entry);
|
|
35501
35529
|
const pid = Number.parseInt(match[1] ?? "", 10);
|
|
35502
|
-
const
|
|
35503
|
-
if (
|
|
35504
|
-
found.push(endpoint);
|
|
35505
|
-
} else {
|
|
35530
|
+
const announced = processAlive(pid) ? parseAnnouncement(file, pid) : { kind: "rubbish" };
|
|
35531
|
+
if (announced.kind === "rubbish") {
|
|
35506
35532
|
try {
|
|
35507
35533
|
unlinkSync(file);
|
|
35508
35534
|
} catch {}
|
|
35535
|
+
continue;
|
|
35509
35536
|
}
|
|
35537
|
+
found.push(announced);
|
|
35510
35538
|
}
|
|
35511
35539
|
return found;
|
|
35512
35540
|
}
|
|
35513
35541
|
function describe2(endpoint) {
|
|
35514
35542
|
return `pid ${endpoint.pid} on ${endpoint.address}:${endpoint.port} (${endpoint.project.name || "unnamed"} at ${endpoint.project.path})`;
|
|
35515
35543
|
}
|
|
35516
|
-
function
|
|
35544
|
+
function tooNew(unspoken) {
|
|
35545
|
+
const named = unspoken.map((game) => `pid ${game.pid} speaks ${game.protocol} (${game.project.name || "unnamed"} at ${game.project.path})`).join("; ");
|
|
35546
|
+
const half = unspoken.some((game) => game.protocol > RUNTIME_PROTOCOL) ? "this server is the older half: reconnect it so it spawns the installed version" : "the addon is the older half: reinstall it and restart the game";
|
|
35547
|
+
return `A game is running, in a protocol this server does not speak ${named}. This server speaks ${RUNTIME_PROTOCOL}, so ${half}.`;
|
|
35548
|
+
}
|
|
35549
|
+
function chooseRuntime(endpoints, projectPath, unspoken = []) {
|
|
35517
35550
|
if (endpoints.length === 0) {
|
|
35551
|
+
if (unspoken.length > 0) {
|
|
35552
|
+
return { problem: tooNew(unspoken) };
|
|
35553
|
+
}
|
|
35518
35554
|
return {
|
|
35519
35555
|
problem: "No game with the runtime addon is running. Start one with editor_run, or play the project from the editor with the addon enabled."
|
|
35520
35556
|
};
|
|
@@ -35635,9 +35671,9 @@ var init_runtime_client = __esm(() => {
|
|
|
35635
35671
|
|
|
35636
35672
|
// src/server.ts
|
|
35637
35673
|
import { execFile as execFile5, spawn } from "node:child_process";
|
|
35638
|
-
import { existsSync as
|
|
35674
|
+
import { existsSync as existsSync11, mkdtempSync as mkdtempSync3, readdirSync as readdirSync6, readFileSync as readFileSync11, realpathSync as realpathSync2, rmSync as rmSync6 } from "node:fs";
|
|
35639
35675
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
35640
|
-
import { basename as basename2, dirname as
|
|
35676
|
+
import { basename as basename2, dirname as dirname7, join as join13, normalize as normalize3 } from "node:path";
|
|
35641
35677
|
import { setTimeout as delay2 } from "node:timers/promises";
|
|
35642
35678
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
35643
35679
|
import { promisify as promisify5 } from "node:util";
|
|
@@ -35683,7 +35719,7 @@ function camelCased(params) {
|
|
|
35683
35719
|
class GodotServer {
|
|
35684
35720
|
mcp;
|
|
35685
35721
|
locator = new GodotLocator2;
|
|
35686
|
-
operationsScript =
|
|
35722
|
+
operationsScript = join13(__dirname2, "godot", "operations", "godot_operations.gd");
|
|
35687
35723
|
godotBridge;
|
|
35688
35724
|
tools = buildToolDefinitions();
|
|
35689
35725
|
activeProcess = null;
|
|
@@ -36137,8 +36173,8 @@ class GodotServer {
|
|
|
36137
36173
|
if (path === undefined) {
|
|
36138
36174
|
return { ok: false, response: this.createErrorResponse("projectPath is required.") };
|
|
36139
36175
|
}
|
|
36140
|
-
const file =
|
|
36141
|
-
if (!
|
|
36176
|
+
const file = join13(path, "project.godot");
|
|
36177
|
+
if (!existsSync11(file)) {
|
|
36142
36178
|
return {
|
|
36143
36179
|
ok: false,
|
|
36144
36180
|
response: this.createErrorResponse(`Not a Godot project: ${path}`, [
|
|
@@ -36372,7 +36408,7 @@ class GodotServer {
|
|
|
36372
36408
|
log.finish();
|
|
36373
36409
|
const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
|
|
36374
36410
|
const verdict = {
|
|
36375
|
-
exported: exitCode === 0 && log.count("error") === 0 &&
|
|
36411
|
+
exported: exitCode === 0 && log.count("error") === 0 && existsSync11(output.absolutePath),
|
|
36376
36412
|
preset,
|
|
36377
36413
|
outputPath: output.relativePath,
|
|
36378
36414
|
debug,
|
|
@@ -36402,7 +36438,7 @@ class GodotServer {
|
|
|
36402
36438
|
return contained.response;
|
|
36403
36439
|
}
|
|
36404
36440
|
const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
|
|
36405
|
-
if (!
|
|
36441
|
+
if (!existsSync11(join13(project.value.path, runner))) {
|
|
36406
36442
|
return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
|
|
36407
36443
|
"Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
|
|
36408
36444
|
]);
|
|
@@ -36435,7 +36471,7 @@ class GodotServer {
|
|
|
36435
36471
|
];
|
|
36436
36472
|
const timeoutMs = readPositiveNumber(args, "timeoutMs") ?? 600000;
|
|
36437
36473
|
this.logDebug(`Running tests: ${engine.value} ${cmdArgs.join(" ")}`);
|
|
36438
|
-
const userData = mkdtempSync3(
|
|
36474
|
+
const userData = mkdtempSync3(join13(tmpdir5(), "gdharness-tests-"));
|
|
36439
36475
|
const run = this.spawnGame(engine.value, cmdArgs, userDataIn(userData));
|
|
36440
36476
|
const hung = await new Promise((resolve) => {
|
|
36441
36477
|
const timer = setTimeout(() => {
|
|
@@ -36451,14 +36487,14 @@ class GodotServer {
|
|
|
36451
36487
|
resolve(false);
|
|
36452
36488
|
});
|
|
36453
36489
|
});
|
|
36454
|
-
const reportsDir =
|
|
36490
|
+
const reportsDir = join13(project.value.path, ".godot", "gdharness-reports");
|
|
36455
36491
|
let report = null;
|
|
36456
36492
|
let reportProblem = null;
|
|
36457
36493
|
try {
|
|
36458
|
-
const written =
|
|
36494
|
+
const written = existsSync11(reportsDir) ? readdirSync6(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
|
|
36459
36495
|
const newest = written.at(-1);
|
|
36460
36496
|
if (newest !== undefined) {
|
|
36461
|
-
report = parseJUnit(readFileSync11(
|
|
36497
|
+
report = parseJUnit(readFileSync11(join13(reportsDir, newest, "results.xml"), "utf8"));
|
|
36462
36498
|
}
|
|
36463
36499
|
} catch (error) {
|
|
36464
36500
|
reportProblem = errorMessage(error);
|
|
@@ -36965,13 +37001,14 @@ class GodotServer {
|
|
|
36965
37001
|
}
|
|
36966
37002
|
async handleRuntimeCommand(command, args, timeoutMs = this.runtimeTimeoutMs()) {
|
|
36967
37003
|
const { op: _op, projectPath, ...params } = asParams(args);
|
|
36968
|
-
const
|
|
37004
|
+
const announced = runtimesAnnounced();
|
|
37005
|
+
const choice = chooseRuntime(announced.running, typeof projectPath === "string" ? projectPath : undefined, announced.unspoken);
|
|
36969
37006
|
if ("problem" in choice) {
|
|
36970
37007
|
return this.createErrorResponse(choice.problem);
|
|
36971
37008
|
}
|
|
36972
37009
|
const expectsScreenshot = command === "capture_screenshot" || command === "capture_viewport";
|
|
36973
|
-
const screenshotDir = expectsScreenshot ? mkdtempSync3(
|
|
36974
|
-
const screenshotPath = screenshotDir ?
|
|
37010
|
+
const screenshotDir = expectsScreenshot ? mkdtempSync3(join13(tmpdir5(), "gdharness-runtime-screenshot-")) : null;
|
|
37011
|
+
const screenshotPath = screenshotDir ? join13(screenshotDir, "capture.png") : null;
|
|
36975
37012
|
try {
|
|
36976
37013
|
const reply = await runtimeRequest(choice.endpoint, command, screenshotPath ? { ...params, output_path: screenshotPath } : params, timeoutMs);
|
|
36977
37014
|
if (!reply.ok) {
|
|
@@ -37077,7 +37114,7 @@ var init_server3 = __esm(() => {
|
|
|
37077
37114
|
init_tool_definitions();
|
|
37078
37115
|
init_update_check();
|
|
37079
37116
|
run5 = promisify5(execFile5);
|
|
37080
|
-
__dirname2 =
|
|
37117
|
+
__dirname2 = dirname7(fileURLToPath4(import.meta.url));
|
|
37081
37118
|
PATH_SOLUTIONS = [
|
|
37082
37119
|
'Give the path relative to the project, such as "scenes/main.tscn" or "res://scenes/main.tscn"',
|
|
37083
37120
|
"Point projectPath at the project the file belongs to"
|
|
@@ -37134,8 +37171,8 @@ var init_server3 = __esm(() => {
|
|
|
37134
37171
|
});
|
|
37135
37172
|
|
|
37136
37173
|
// src/cli.ts
|
|
37137
|
-
import { existsSync as
|
|
37138
|
-
import { join as
|
|
37174
|
+
import { existsSync as existsSync12 } from "fs";
|
|
37175
|
+
import { join as join14, resolve as resolve5 } from "path";
|
|
37139
37176
|
|
|
37140
37177
|
// src/errors.ts
|
|
37141
37178
|
class Refusal extends Error {
|
|
@@ -37198,10 +37235,10 @@ class GodotLocator {
|
|
|
37198
37235
|
}
|
|
37199
37236
|
|
|
37200
37237
|
// src/harnesses.ts
|
|
37201
|
-
import { existsSync as
|
|
37238
|
+
import { existsSync as existsSync4, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
37202
37239
|
import { homedir as homedir2 } from "node:os";
|
|
37203
|
-
import { dirname, join as
|
|
37204
|
-
import
|
|
37240
|
+
import { dirname as dirname2, join as join3 } from "node:path";
|
|
37241
|
+
import process3 from "node:process";
|
|
37205
37242
|
|
|
37206
37243
|
// node_modules/yaml/dist/index.js
|
|
37207
37244
|
var composer = require_composer();
|
|
@@ -37343,13 +37380,11 @@ function isEmptyCollection(node) {
|
|
|
37343
37380
|
|
|
37344
37381
|
// src/harnesses.ts
|
|
37345
37382
|
init_errors();
|
|
37383
|
+
init_runner();
|
|
37346
37384
|
var SERVER_KEY = "gdharness";
|
|
37347
37385
|
function launchFor(version, godotPath, runner = currentRunner()) {
|
|
37348
|
-
|
|
37349
|
-
|
|
37350
|
-
args: runner === "npx" ? ["-y", `gdharness@${version}`] : [`gdharness@${version}`],
|
|
37351
|
-
env: { GODOT_PATH: godotPath }
|
|
37352
|
-
};
|
|
37386
|
+
const spawn = spawnFor(runner, version);
|
|
37387
|
+
return { command: spawn.command, args: spawn.args, env: { GODOT_PATH: godotPath } };
|
|
37353
37388
|
}
|
|
37354
37389
|
function tomlArray(values) {
|
|
37355
37390
|
return `[${values.map((value) => `"${value}"`).join(", ")}]`;
|
|
@@ -37371,7 +37406,7 @@ var HARNESSES = [
|
|
|
37371
37406
|
shape: "plain",
|
|
37372
37407
|
home: ".claude",
|
|
37373
37408
|
marker: ".claude",
|
|
37374
|
-
skills: { dir:
|
|
37409
|
+
skills: { dir: join3(".claude", "skills"), shared: false }
|
|
37375
37410
|
},
|
|
37376
37411
|
{
|
|
37377
37412
|
id: "copilot-cli",
|
|
@@ -37381,7 +37416,7 @@ var HARNESSES = [
|
|
|
37381
37416
|
container: "mcpServers",
|
|
37382
37417
|
shape: "plain",
|
|
37383
37418
|
home: ".copilot",
|
|
37384
|
-
skills: { dir:
|
|
37419
|
+
skills: { dir: join3(".github", "skills"), shared: true },
|
|
37385
37420
|
manual: "Trust the folder when Copilot CLI first asks, or it reads no config here."
|
|
37386
37421
|
},
|
|
37387
37422
|
{
|
|
@@ -37407,22 +37442,22 @@ var HARNESSES = [
|
|
|
37407
37442
|
id: "cursor",
|
|
37408
37443
|
name: "Cursor",
|
|
37409
37444
|
scope: "project",
|
|
37410
|
-
file:
|
|
37445
|
+
file: join3(".cursor", "mcp.json"),
|
|
37411
37446
|
container: "mcpServers",
|
|
37412
37447
|
shape: "plain",
|
|
37413
37448
|
home: ".cursor",
|
|
37414
|
-
skills: { dir:
|
|
37449
|
+
skills: { dir: join3(".cursor", "skills"), shared: true },
|
|
37415
37450
|
manual: "Cursor asks before each tool call by default, and the server can be toggled off."
|
|
37416
37451
|
},
|
|
37417
37452
|
{
|
|
37418
37453
|
id: "vscode",
|
|
37419
37454
|
name: "VS Code",
|
|
37420
37455
|
scope: "project",
|
|
37421
|
-
file:
|
|
37456
|
+
file: join3(".vscode", "mcp.json"),
|
|
37422
37457
|
container: "servers",
|
|
37423
37458
|
shape: "typed",
|
|
37424
37459
|
home: ".vscode",
|
|
37425
|
-
skills: { dir:
|
|
37460
|
+
skills: { dir: join3(".github", "skills"), shared: true },
|
|
37426
37461
|
manual: "VS Code asks you to trust a server the first time it starts one."
|
|
37427
37462
|
},
|
|
37428
37463
|
{
|
|
@@ -37432,45 +37467,45 @@ var HARNESSES = [
|
|
|
37432
37467
|
file: "opencode.json",
|
|
37433
37468
|
container: "mcp",
|
|
37434
37469
|
shape: "opencode",
|
|
37435
|
-
home:
|
|
37470
|
+
home: join3(".config", "opencode"),
|
|
37436
37471
|
marker: ".opencode",
|
|
37437
|
-
skills: { dir:
|
|
37472
|
+
skills: { dir: join3(".opencode", "skills"), shared: true }
|
|
37438
37473
|
},
|
|
37439
37474
|
{
|
|
37440
37475
|
id: "junie",
|
|
37441
37476
|
name: "Junie",
|
|
37442
37477
|
scope: "project",
|
|
37443
|
-
file:
|
|
37478
|
+
file: join3(".junie", "mcp", "mcp.json"),
|
|
37444
37479
|
container: "mcpServers",
|
|
37445
37480
|
shape: "plain",
|
|
37446
37481
|
home: ".junie",
|
|
37447
|
-
skills: { dir:
|
|
37482
|
+
skills: { dir: join3(".junie", "skills"), shared: true }
|
|
37448
37483
|
},
|
|
37449
37484
|
{
|
|
37450
37485
|
id: "kiro",
|
|
37451
37486
|
name: "Kiro",
|
|
37452
37487
|
scope: "project",
|
|
37453
|
-
file:
|
|
37488
|
+
file: join3(".kiro", "settings", "mcp.json"),
|
|
37454
37489
|
container: "mcpServers",
|
|
37455
37490
|
shape: "plain",
|
|
37456
37491
|
home: ".kiro",
|
|
37457
|
-
skills: { dir:
|
|
37492
|
+
skills: { dir: join3(".kiro", "skills"), shared: false }
|
|
37458
37493
|
},
|
|
37459
37494
|
{
|
|
37460
37495
|
id: "gemini",
|
|
37461
37496
|
name: "Gemini CLI",
|
|
37462
37497
|
scope: "project",
|
|
37463
|
-
file:
|
|
37498
|
+
file: join3(".gemini", "settings.json"),
|
|
37464
37499
|
container: "mcpServers",
|
|
37465
37500
|
shape: "plain",
|
|
37466
37501
|
home: ".gemini",
|
|
37467
|
-
skills: { dir:
|
|
37502
|
+
skills: { dir: join3(".gemini", "skills"), shared: true }
|
|
37468
37503
|
},
|
|
37469
37504
|
{
|
|
37470
37505
|
id: "roo",
|
|
37471
37506
|
name: "Roo Code",
|
|
37472
37507
|
scope: "project",
|
|
37473
|
-
file:
|
|
37508
|
+
file: join3(".roo", "mcp.json"),
|
|
37474
37509
|
container: "mcpServers",
|
|
37475
37510
|
shape: "plain"
|
|
37476
37511
|
},
|
|
@@ -37478,7 +37513,7 @@ var HARNESSES = [
|
|
|
37478
37513
|
id: "kilo",
|
|
37479
37514
|
name: "Kilo Code",
|
|
37480
37515
|
scope: "project",
|
|
37481
|
-
file:
|
|
37516
|
+
file: join3(".kilocode", "mcp.json"),
|
|
37482
37517
|
container: "mcpServers",
|
|
37483
37518
|
shape: "plain"
|
|
37484
37519
|
},
|
|
@@ -37486,16 +37521,16 @@ var HARNESSES = [
|
|
|
37486
37521
|
id: "amazon-q",
|
|
37487
37522
|
name: "Amazon Q Developer CLI",
|
|
37488
37523
|
scope: "project",
|
|
37489
|
-
file:
|
|
37524
|
+
file: join3(".amazonq", "mcp.json"),
|
|
37490
37525
|
container: "mcpServers",
|
|
37491
37526
|
shape: "plain",
|
|
37492
|
-
home:
|
|
37527
|
+
home: join3(".aws", "amazonq")
|
|
37493
37528
|
},
|
|
37494
37529
|
{
|
|
37495
37530
|
id: "zed",
|
|
37496
37531
|
name: "Zed",
|
|
37497
37532
|
scope: "project",
|
|
37498
|
-
file:
|
|
37533
|
+
file: join3(".zed", "settings.json"),
|
|
37499
37534
|
container: "context_servers",
|
|
37500
37535
|
shape: "plain"
|
|
37501
37536
|
},
|
|
@@ -37503,16 +37538,16 @@ var HARNESSES = [
|
|
|
37503
37538
|
id: "amp",
|
|
37504
37539
|
name: "Amp",
|
|
37505
37540
|
scope: "project",
|
|
37506
|
-
file:
|
|
37541
|
+
file: join3(".amp", "settings.json"),
|
|
37507
37542
|
container: "amp.mcpServers",
|
|
37508
37543
|
shape: "plain",
|
|
37509
|
-
home:
|
|
37544
|
+
home: join3(".config", "amp")
|
|
37510
37545
|
},
|
|
37511
37546
|
{
|
|
37512
37547
|
id: "warp",
|
|
37513
37548
|
name: "Warp",
|
|
37514
37549
|
scope: "project",
|
|
37515
|
-
file:
|
|
37550
|
+
file: join3(".warp", ".mcp.json"),
|
|
37516
37551
|
container: "mcpServers",
|
|
37517
37552
|
shape: "plain",
|
|
37518
37553
|
home: ".warp",
|
|
@@ -37522,7 +37557,7 @@ var HARNESSES = [
|
|
|
37522
37557
|
id: "trae",
|
|
37523
37558
|
name: "Trae",
|
|
37524
37559
|
scope: "project",
|
|
37525
|
-
file:
|
|
37560
|
+
file: join3(".trae", "mcp.json"),
|
|
37526
37561
|
container: "mcpServers",
|
|
37527
37562
|
shape: "plain",
|
|
37528
37563
|
home: ".trae"
|
|
@@ -37531,7 +37566,7 @@ var HARNESSES = [
|
|
|
37531
37566
|
id: "factory",
|
|
37532
37567
|
name: "Factory Droid",
|
|
37533
37568
|
scope: "project",
|
|
37534
|
-
file:
|
|
37569
|
+
file: join3(".factory", "mcp.json"),
|
|
37535
37570
|
container: "mcpServers",
|
|
37536
37571
|
shape: "typed",
|
|
37537
37572
|
home: ".factory"
|
|
@@ -37540,7 +37575,7 @@ var HARNESSES = [
|
|
|
37540
37575
|
id: "tabnine",
|
|
37541
37576
|
name: "Tabnine",
|
|
37542
37577
|
scope: "project",
|
|
37543
|
-
file:
|
|
37578
|
+
file: join3(".tabnine", "mcp_servers.json"),
|
|
37544
37579
|
container: "mcpServers",
|
|
37545
37580
|
shape: "plain",
|
|
37546
37581
|
home: ".tabnine"
|
|
@@ -37557,7 +37592,7 @@ var HARNESSES = [
|
|
|
37557
37592
|
id: "pi",
|
|
37558
37593
|
name: "pi",
|
|
37559
37594
|
scope: "project",
|
|
37560
|
-
file:
|
|
37595
|
+
file: join3(".pi", "mcp.json"),
|
|
37561
37596
|
container: "mcpServers",
|
|
37562
37597
|
shape: "plain",
|
|
37563
37598
|
home: ".pi"
|
|
@@ -37566,7 +37601,7 @@ var HARNESSES = [
|
|
|
37566
37601
|
id: "mistral-vibe",
|
|
37567
37602
|
name: "Mistral Vibe",
|
|
37568
37603
|
scope: "project",
|
|
37569
|
-
file:
|
|
37604
|
+
file: join3(".vibe", "config.toml"),
|
|
37570
37605
|
container: "mcp_servers",
|
|
37571
37606
|
shape: "plain",
|
|
37572
37607
|
toml: {
|
|
@@ -37622,7 +37657,7 @@ var HARNESSES = [
|
|
|
37622
37657
|
id: "codex",
|
|
37623
37658
|
name: "Codex CLI",
|
|
37624
37659
|
scope: "home",
|
|
37625
|
-
file:
|
|
37660
|
+
file: join3(".codex", "config.toml"),
|
|
37626
37661
|
container: "mcp_servers",
|
|
37627
37662
|
shape: "plain",
|
|
37628
37663
|
manual: "Codex reads its config at startup, so restart it.",
|
|
@@ -37641,20 +37676,20 @@ var HARNESSES = [
|
|
|
37641
37676
|
id: "cline",
|
|
37642
37677
|
name: "Cline",
|
|
37643
37678
|
scope: "home",
|
|
37644
|
-
file:
|
|
37679
|
+
file: join3(".cline", "data", "settings", "cline_mcp_settings.json"),
|
|
37645
37680
|
container: "mcpServers",
|
|
37646
37681
|
shape: "plain",
|
|
37647
37682
|
marker: ".cline",
|
|
37648
|
-
skills: { dir:
|
|
37683
|
+
skills: { dir: join3(".cline", "skills"), shared: false }
|
|
37649
37684
|
},
|
|
37650
37685
|
{
|
|
37651
37686
|
id: "goose",
|
|
37652
37687
|
name: "Goose",
|
|
37653
37688
|
scope: "home",
|
|
37654
37689
|
file: {
|
|
37655
|
-
win32: { appData:
|
|
37656
|
-
darwin:
|
|
37657
|
-
linux:
|
|
37690
|
+
win32: { appData: join3("Block", "goose", "config", "config.yaml") },
|
|
37691
|
+
darwin: join3(".config", "goose", "config.yaml"),
|
|
37692
|
+
linux: join3(".config", "goose", "config.yaml")
|
|
37658
37693
|
},
|
|
37659
37694
|
container: "extensions",
|
|
37660
37695
|
shape: "plain",
|
|
@@ -37675,19 +37710,19 @@ var HARNESSES = [
|
|
|
37675
37710
|
id: "windsurf",
|
|
37676
37711
|
name: "Windsurf",
|
|
37677
37712
|
scope: "home",
|
|
37678
|
-
file:
|
|
37713
|
+
file: join3(".codeium", "windsurf", "mcp_config.json"),
|
|
37679
37714
|
container: "mcpServers",
|
|
37680
37715
|
shape: "plain",
|
|
37681
|
-
skills: { dir:
|
|
37716
|
+
skills: { dir: join3(".windsurf", "skills"), shared: true }
|
|
37682
37717
|
},
|
|
37683
37718
|
{
|
|
37684
37719
|
id: "hermes",
|
|
37685
37720
|
name: "Hermes",
|
|
37686
37721
|
scope: "home",
|
|
37687
|
-
file:
|
|
37722
|
+
file: join3(".hermes", "config.yaml"),
|
|
37688
37723
|
container: "mcp_servers",
|
|
37689
37724
|
shape: "plain",
|
|
37690
|
-
skills: { dir:
|
|
37725
|
+
skills: { dir: join3(".hermes", "skills"), shared: true },
|
|
37691
37726
|
yaml: {
|
|
37692
37727
|
path: ["mcp_servers", SERVER_KEY],
|
|
37693
37728
|
entry: (launch) => ({
|
|
@@ -37702,7 +37737,7 @@ var HARNESSES = [
|
|
|
37702
37737
|
id: "openclaw",
|
|
37703
37738
|
name: "OpenClaw",
|
|
37704
37739
|
scope: "home",
|
|
37705
|
-
file:
|
|
37740
|
+
file: join3(".openclaw", "openclaw.json"),
|
|
37706
37741
|
container: "mcpServers",
|
|
37707
37742
|
shape: "plain"
|
|
37708
37743
|
},
|
|
@@ -37711,9 +37746,9 @@ var HARNESSES = [
|
|
|
37711
37746
|
name: "Claude Desktop",
|
|
37712
37747
|
scope: "home",
|
|
37713
37748
|
file: {
|
|
37714
|
-
win32: { appData:
|
|
37715
|
-
darwin:
|
|
37716
|
-
linux:
|
|
37749
|
+
win32: { appData: join3("Claude", "claude_desktop_config.json") },
|
|
37750
|
+
darwin: join3("Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
|
37751
|
+
linux: join3(".config", "Claude", "claude_desktop_config.json")
|
|
37717
37752
|
},
|
|
37718
37753
|
container: "mcpServers",
|
|
37719
37754
|
shape: "plain"
|
|
@@ -37722,7 +37757,7 @@ var HARNESSES = [
|
|
|
37722
37757
|
id: "zeroclaw",
|
|
37723
37758
|
name: "ZeroClaw",
|
|
37724
37759
|
scope: "home",
|
|
37725
|
-
file:
|
|
37760
|
+
file: join3(".zeroclaw", "config.toml"),
|
|
37726
37761
|
container: "mcp.servers",
|
|
37727
37762
|
shape: "plain",
|
|
37728
37763
|
toml: {
|
|
@@ -37743,7 +37778,7 @@ var HARNESSES = [
|
|
|
37743
37778
|
id: "deepcode",
|
|
37744
37779
|
name: "Deep Code",
|
|
37745
37780
|
scope: "home",
|
|
37746
|
-
file:
|
|
37781
|
+
file: join3(".deepcode", "settings.json"),
|
|
37747
37782
|
container: "mcpServers",
|
|
37748
37783
|
shape: "plain"
|
|
37749
37784
|
},
|
|
@@ -37751,7 +37786,7 @@ var HARNESSES = [
|
|
|
37751
37786
|
id: "nanobot",
|
|
37752
37787
|
name: "nanobot",
|
|
37753
37788
|
scope: "home",
|
|
37754
|
-
file:
|
|
37789
|
+
file: join3(".nanobot", "config.json"),
|
|
37755
37790
|
container: "mcpServers",
|
|
37756
37791
|
shape: "plain",
|
|
37757
37792
|
snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
|
|
@@ -37760,19 +37795,19 @@ var HARNESSES = [
|
|
|
37760
37795
|
id: "autohand",
|
|
37761
37796
|
name: "Autohand",
|
|
37762
37797
|
scope: "home",
|
|
37763
|
-
file:
|
|
37798
|
+
file: join3(".autohand", "config.json"),
|
|
37764
37799
|
container: "mcpServers",
|
|
37765
37800
|
shape: "plain",
|
|
37766
37801
|
snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
|
|
37767
37802
|
}
|
|
37768
37803
|
];
|
|
37769
37804
|
function appDataRoot() {
|
|
37770
|
-
return
|
|
37805
|
+
return process3.env["APPDATA"] ?? join3(homedir2(), "AppData", "Roaming");
|
|
37771
37806
|
}
|
|
37772
37807
|
function homePath(path) {
|
|
37773
|
-
return typeof path === "string" ?
|
|
37808
|
+
return typeof path === "string" ? join3(homedir2(), path) : join3(appDataRoot(), path.appData);
|
|
37774
37809
|
}
|
|
37775
|
-
function fileFor(harness, platform =
|
|
37810
|
+
function fileFor(harness, platform = process3.platform) {
|
|
37776
37811
|
if (typeof harness.file === "string") {
|
|
37777
37812
|
return harness.file;
|
|
37778
37813
|
}
|
|
@@ -37781,11 +37816,11 @@ function fileFor(harness, platform = process2.platform) {
|
|
|
37781
37816
|
function configPath(harness, projectPath) {
|
|
37782
37817
|
const file = fileFor(harness);
|
|
37783
37818
|
if (harness.scope === "project") {
|
|
37784
|
-
return
|
|
37819
|
+
return join3(projectPath, file);
|
|
37785
37820
|
}
|
|
37786
37821
|
return homePath(file);
|
|
37787
37822
|
}
|
|
37788
|
-
function displayPath(harness, platform =
|
|
37823
|
+
function displayPath(harness, platform = process3.platform) {
|
|
37789
37824
|
const file = fileFor(harness, platform);
|
|
37790
37825
|
if (typeof file !== "string") {
|
|
37791
37826
|
return `%APPDATA%/${file.appData.replaceAll("\\", "/")}`;
|
|
@@ -37821,15 +37856,15 @@ function harnessById(id) {
|
|
|
37821
37856
|
}
|
|
37822
37857
|
function present(harness, projectPath) {
|
|
37823
37858
|
const path = configPath(harness, projectPath);
|
|
37824
|
-
if (
|
|
37859
|
+
if (existsSync4(path)) {
|
|
37825
37860
|
return true;
|
|
37826
37861
|
}
|
|
37827
37862
|
const root = harness.scope === "project" ? projectPath : homedir2();
|
|
37828
|
-
const own =
|
|
37829
|
-
if (own !== root &&
|
|
37863
|
+
const own = dirname2(path);
|
|
37864
|
+
if (own !== root && existsSync4(own)) {
|
|
37830
37865
|
return true;
|
|
37831
37866
|
}
|
|
37832
|
-
return harness.marker !== undefined &&
|
|
37867
|
+
return harness.marker !== undefined && existsSync4(join3(root, harness.marker));
|
|
37833
37868
|
}
|
|
37834
37869
|
function candidates(projectPath) {
|
|
37835
37870
|
const found = [];
|
|
@@ -37842,7 +37877,7 @@ function candidates(projectPath) {
|
|
|
37842
37877
|
}
|
|
37843
37878
|
if (present(harness, projectPath)) {
|
|
37844
37879
|
found.push({ harness, reason: "configured" });
|
|
37845
|
-
} else if (harness.home !== undefined &&
|
|
37880
|
+
} else if (harness.home !== undefined && existsSync4(join3(homedir2(), harness.home))) {
|
|
37846
37881
|
found.push({ harness, reason: "installed" });
|
|
37847
37882
|
}
|
|
37848
37883
|
}
|
|
@@ -37864,7 +37899,7 @@ function groupByFile(harnesses, projectPath) {
|
|
|
37864
37899
|
}
|
|
37865
37900
|
function registered(harness, projectPath) {
|
|
37866
37901
|
const path = configPath(harness, projectPath);
|
|
37867
|
-
if (harness.snippet !== undefined || !
|
|
37902
|
+
if (harness.snippet !== undefined || !existsSync4(path)) {
|
|
37868
37903
|
return false;
|
|
37869
37904
|
}
|
|
37870
37905
|
const text = readFileSync(path, "utf8");
|
|
@@ -37888,7 +37923,7 @@ function registered(harness, projectPath) {
|
|
|
37888
37923
|
}
|
|
37889
37924
|
function disconnect(harness, projectPath) {
|
|
37890
37925
|
const path = configPath(harness, projectPath);
|
|
37891
|
-
if (!
|
|
37926
|
+
if (!existsSync4(path)) {
|
|
37892
37927
|
return { harness, path, action: "absent" };
|
|
37893
37928
|
}
|
|
37894
37929
|
if (harness.snippet !== undefined) {
|
|
@@ -37935,7 +37970,7 @@ function connect(harness, projectPath, launch) {
|
|
|
37935
37970
|
if (harness.snippet !== undefined) {
|
|
37936
37971
|
return { harness, path, action: "snippet", snippet: harness.snippet(launch) };
|
|
37937
37972
|
}
|
|
37938
|
-
const held =
|
|
37973
|
+
const held = existsSync4(path) ? readFileSync(path, "utf8") : "";
|
|
37939
37974
|
if (harness.toml !== undefined) {
|
|
37940
37975
|
const already = held.includes(harness.toml.identity ?? harness.toml.header);
|
|
37941
37976
|
return put(harness, path, writeToml(held, harness.toml, launch), already);
|
|
@@ -37958,7 +37993,7 @@ function connect(harness, projectPath, launch) {
|
|
|
37958
37993
|
`, already);
|
|
37959
37994
|
}
|
|
37960
37995
|
function put(harness, path, contents, already) {
|
|
37961
|
-
mkdirSync(
|
|
37996
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
37962
37997
|
writeFileSync(path, contents, "utf8");
|
|
37963
37998
|
return { harness, path, action: already ? "replaced" : "written" };
|
|
37964
37999
|
}
|
|
@@ -37979,7 +38014,7 @@ init_game_log();
|
|
|
37979
38014
|
import { execFile as execFile2 } from "node:child_process";
|
|
37980
38015
|
import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
37981
38016
|
import { tmpdir } from "node:os";
|
|
37982
|
-
import { join as
|
|
38017
|
+
import { join as join4 } from "node:path";
|
|
37983
38018
|
import { promisify as promisify2 } from "node:util";
|
|
37984
38019
|
var run2 = promisify2(execFile2);
|
|
37985
38020
|
function snakeCased(params) {
|
|
@@ -38020,8 +38055,8 @@ function reason(stdout, stderr) {
|
|
|
38020
38055
|
return stdout.trim().split(/\r?\n/).at(-1) ?? "no output at all";
|
|
38021
38056
|
}
|
|
38022
38057
|
async function runOperation(engine, operation, params, projectPath) {
|
|
38023
|
-
const paramsDir = mkdtempSync(
|
|
38024
|
-
const paramsFile =
|
|
38058
|
+
const paramsDir = mkdtempSync(join4(tmpdir(), "gdharness-params-"));
|
|
38059
|
+
const paramsFile = join4(paramsDir, `${operation}.json`);
|
|
38025
38060
|
writeFileSync2(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
|
|
38026
38061
|
const args = [
|
|
38027
38062
|
"--headless",
|
|
@@ -38069,13 +38104,13 @@ async function runOperation(engine, operation, params, projectPath) {
|
|
|
38069
38104
|
init_errors();
|
|
38070
38105
|
init_server_version();
|
|
38071
38106
|
import { createHash } from "node:crypto";
|
|
38072
|
-
import
|
|
38107
|
+
import process4 from "node:process";
|
|
38073
38108
|
var NEW_ISSUE = "https://github.com/Aureliolo/gdharness/issues/new";
|
|
38074
38109
|
var ENHANCEMENT_URL = `${NEW_ISSUE}?template=feature_request.md`;
|
|
38075
38110
|
function runtime() {
|
|
38076
|
-
const versions =
|
|
38111
|
+
const versions = process4.versions;
|
|
38077
38112
|
const bun = versions["bun"];
|
|
38078
|
-
return bun === undefined ? `node ${
|
|
38113
|
+
return bun === undefined ? `node ${process4.versions.node}` : `bun ${bun}`;
|
|
38079
38114
|
}
|
|
38080
38115
|
function defectSignature(where, message) {
|
|
38081
38116
|
const normalised = `${where}
|
|
@@ -38087,7 +38122,7 @@ function facts(where, message, godotVersion) {
|
|
|
38087
38122
|
["Where", where],
|
|
38088
38123
|
["Error", message],
|
|
38089
38124
|
["Version", `gdharness ${SERVER_VERSION}`],
|
|
38090
|
-
["Runtime", `${runtime()}, ${
|
|
38125
|
+
["Runtime", `${runtime()}, ${process4.platform} ${process4.arch}`],
|
|
38091
38126
|
["Godot", godotVersion ?? "not known at the point this failed"],
|
|
38092
38127
|
["Signature", defectSignature(where, message)]
|
|
38093
38128
|
];
|
|
@@ -38097,7 +38132,7 @@ function filledTemplate(where, message, godotVersion) {
|
|
|
38097
38132
|
`**gdharness version**: ${SERVER_VERSION}`,
|
|
38098
38133
|
`**Godot version**: ${godotVersion ?? ""}`,
|
|
38099
38134
|
`**Bun version**: ${runtime()}`,
|
|
38100
|
-
`**OS**: ${
|
|
38135
|
+
`**OS**: ${process4.platform} ${process4.arch}`,
|
|
38101
38136
|
"**MCP client**:",
|
|
38102
38137
|
"",
|
|
38103
38138
|
"## What you did",
|
|
@@ -38159,10 +38194,10 @@ function defectReport(where, error, godotVersion) {
|
|
|
38159
38194
|
}
|
|
38160
38195
|
|
|
38161
38196
|
// src/prompt.ts
|
|
38162
|
-
import
|
|
38197
|
+
import process5 from "node:process";
|
|
38163
38198
|
import { createInterface } from "node:readline/promises";
|
|
38164
38199
|
function interactive() {
|
|
38165
|
-
return
|
|
38200
|
+
return process5.stdin.isTTY && process5.stdout.isTTY;
|
|
38166
38201
|
}
|
|
38167
38202
|
|
|
38168
38203
|
class Ask {
|
|
@@ -38171,7 +38206,7 @@ class Ask {
|
|
|
38171
38206
|
if (!interactive()) {
|
|
38172
38207
|
return fallback;
|
|
38173
38208
|
}
|
|
38174
|
-
this.line ??= createInterface({ input:
|
|
38209
|
+
this.line ??= createInterface({ input: process5.stdin, output: process5.stdout });
|
|
38175
38210
|
const answer = (await this.line.question(`${question} ${fallback ? "[Y/n]" : "[y/N]"} `)).trim();
|
|
38176
38211
|
return answer === "" ? fallback : answer.toLowerCase().startsWith("y");
|
|
38177
38212
|
}
|
|
@@ -38200,8 +38235,8 @@ init_class_cache();
|
|
|
38200
38235
|
init_headless();
|
|
38201
38236
|
init_resources();
|
|
38202
38237
|
init_server_version();
|
|
38203
|
-
import { cpSync, existsSync as
|
|
38204
|
-
import { dirname as
|
|
38238
|
+
import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync7, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
38239
|
+
import { dirname as dirname3, join as join8 } from "node:path";
|
|
38205
38240
|
import { fileURLToPath } from "node:url";
|
|
38206
38241
|
var ADDONS = ["gdharness_editor", "gdharness_runtime", "auto_reload"];
|
|
38207
38242
|
var EDITOR_PLUGINS = ["gdharness_editor", "auto_reload"];
|
|
@@ -38211,24 +38246,24 @@ var RUNTIME_AUTOLOAD = {
|
|
|
38211
38246
|
};
|
|
38212
38247
|
var VERSION_MARKER = ".gdharness-version";
|
|
38213
38248
|
function shippedAddonsDirectory() {
|
|
38214
|
-
return
|
|
38249
|
+
return join8(dirname3(fileURLToPath(import.meta.url)), "godot", "addons");
|
|
38215
38250
|
}
|
|
38216
38251
|
function shippedOperationsScript() {
|
|
38217
|
-
return
|
|
38252
|
+
return join8(dirname3(fileURLToPath(import.meta.url)), "godot", "operations", "godot_operations.gd");
|
|
38218
38253
|
}
|
|
38219
38254
|
function installAddons(projectPath, from = shippedAddonsDirectory()) {
|
|
38220
38255
|
const installed = [];
|
|
38221
38256
|
for (const name of ADDONS) {
|
|
38222
|
-
const source =
|
|
38223
|
-
if (!
|
|
38257
|
+
const source = join8(from, name);
|
|
38258
|
+
if (!existsSync7(join8(source, name === "gdharness_runtime" ? "runtime_autoload.gd" : "plugin.cfg"))) {
|
|
38224
38259
|
throw new Error(`The package holds no ${name} addon at ${source}.`);
|
|
38225
38260
|
}
|
|
38226
|
-
const target =
|
|
38227
|
-
const replaced =
|
|
38261
|
+
const target = join8(projectPath, "addons", name);
|
|
38262
|
+
const replaced = existsSync7(target);
|
|
38228
38263
|
rmSync4(target, { recursive: true, force: true });
|
|
38229
|
-
mkdirSync3(
|
|
38264
|
+
mkdirSync3(dirname3(target), { recursive: true });
|
|
38230
38265
|
cpSync(source, target, { recursive: true });
|
|
38231
|
-
writeFileSync5(
|
|
38266
|
+
writeFileSync5(join8(target, VERSION_MARKER), `${SERVER_VERSION}
|
|
38232
38267
|
`);
|
|
38233
38268
|
installed.push({ name, path: target, replaced });
|
|
38234
38269
|
}
|
|
@@ -38237,8 +38272,8 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
|
|
|
38237
38272
|
function removeAddons(projectPath) {
|
|
38238
38273
|
const removed = [];
|
|
38239
38274
|
for (const name of ADDONS) {
|
|
38240
|
-
const target =
|
|
38241
|
-
if (
|
|
38275
|
+
const target = join8(projectPath, "addons", name);
|
|
38276
|
+
if (existsSync7(target)) {
|
|
38242
38277
|
rmSync4(target, { recursive: true, force: true });
|
|
38243
38278
|
removed.push(target);
|
|
38244
38279
|
}
|
|
@@ -38272,10 +38307,10 @@ function enabledPlugins(settings) {
|
|
|
38272
38307
|
function inspectProject(projectPath) {
|
|
38273
38308
|
const problems = [];
|
|
38274
38309
|
const addons = ADDONS.map((name) => {
|
|
38275
|
-
const directory =
|
|
38276
|
-
const marker =
|
|
38277
|
-
const installed =
|
|
38278
|
-
const version =
|
|
38310
|
+
const directory = join8(projectPath, "addons", name);
|
|
38311
|
+
const marker = join8(directory, VERSION_MARKER);
|
|
38312
|
+
const installed = existsSync7(directory);
|
|
38313
|
+
const version = existsSync7(marker) ? readFileSync7(marker, "utf8").trim() : null;
|
|
38279
38314
|
const current = version === SERVER_VERSION;
|
|
38280
38315
|
if (!installed) {
|
|
38281
38316
|
problems.push(`addons/${name} is not installed; run gdharness setup`);
|
|
@@ -38284,7 +38319,7 @@ function inspectProject(projectPath) {
|
|
|
38284
38319
|
}
|
|
38285
38320
|
return { name, installed, version, current };
|
|
38286
38321
|
});
|
|
38287
|
-
const settings = parseProjectGodot(readFileSync7(
|
|
38322
|
+
const settings = parseProjectGodot(readFileSync7(join8(projectPath, "project.godot"), "utf8"));
|
|
38288
38323
|
const pluginsEnabled = enabledPlugins(settings);
|
|
38289
38324
|
for (const name of EDITOR_PLUGINS) {
|
|
38290
38325
|
if (!pluginsEnabled.includes(name)) {
|
|
@@ -38313,8 +38348,8 @@ function inspectProject(projectPath) {
|
|
|
38313
38348
|
|
|
38314
38349
|
// src/skill.ts
|
|
38315
38350
|
init_tool_definitions();
|
|
38316
|
-
import { existsSync as
|
|
38317
|
-
import { basename, dirname as
|
|
38351
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
38352
|
+
import { basename, dirname as dirname4, join as join9 } from "node:path";
|
|
38318
38353
|
|
|
38319
38354
|
// src/tool-reference.ts
|
|
38320
38355
|
init_tool_definitions();
|
|
@@ -38361,7 +38396,7 @@ function renderToolsMarkdown() {
|
|
|
38361
38396
|
|
|
38362
38397
|
// src/skill.ts
|
|
38363
38398
|
var SKILL_NAME = "gdharness";
|
|
38364
|
-
var SHARED_SKILLS =
|
|
38399
|
+
var SHARED_SKILLS = join9(".agents", "skills");
|
|
38365
38400
|
function skillMarkdown(version) {
|
|
38366
38401
|
return `---
|
|
38367
38402
|
name: ${SKILL_NAME}
|
|
@@ -38443,27 +38478,27 @@ whatever the engine said on stderr comes back under \`engine_messages\`.
|
|
|
38443
38478
|
function skillFiles(version) {
|
|
38444
38479
|
return new Map([
|
|
38445
38480
|
["SKILL.md", skillMarkdown(version)],
|
|
38446
|
-
[
|
|
38481
|
+
[join9("references", "tools.md"), renderToolsMarkdown()]
|
|
38447
38482
|
]);
|
|
38448
38483
|
}
|
|
38449
38484
|
function skillDirectories(harnesses, projectPath, exists) {
|
|
38450
|
-
const directories = [
|
|
38485
|
+
const directories = [join9(projectPath, SHARED_SKILLS, SKILL_NAME)];
|
|
38451
38486
|
for (const harness of harnesses) {
|
|
38452
38487
|
if (harness.skills === undefined) {
|
|
38453
38488
|
continue;
|
|
38454
38489
|
}
|
|
38455
|
-
const own =
|
|
38456
|
-
if ((!harness.skills.shared || exists(own)) && !directories.includes(
|
|
38457
|
-
directories.push(
|
|
38490
|
+
const own = join9(projectPath, harness.skills.dir);
|
|
38491
|
+
if ((!harness.skills.shared || exists(own)) && !directories.includes(join9(own, SKILL_NAME))) {
|
|
38492
|
+
directories.push(join9(own, SKILL_NAME));
|
|
38458
38493
|
}
|
|
38459
38494
|
}
|
|
38460
38495
|
return directories;
|
|
38461
38496
|
}
|
|
38462
38497
|
function everySkillDirectory(projectPath, harnesses) {
|
|
38463
|
-
const directories = new Set([
|
|
38498
|
+
const directories = new Set([join9(projectPath, SHARED_SKILLS, SKILL_NAME)]);
|
|
38464
38499
|
for (const harness of harnesses) {
|
|
38465
38500
|
if (harness.skills !== undefined) {
|
|
38466
|
-
directories.add(
|
|
38501
|
+
directories.add(join9(projectPath, harness.skills.dir, SKILL_NAME));
|
|
38467
38502
|
}
|
|
38468
38503
|
}
|
|
38469
38504
|
return [...directories];
|
|
@@ -38471,33 +38506,33 @@ function everySkillDirectory(projectPath, harnesses) {
|
|
|
38471
38506
|
function removeSkill(directories, projectPath) {
|
|
38472
38507
|
const removed = [];
|
|
38473
38508
|
for (const directory of directories) {
|
|
38474
|
-
if (
|
|
38509
|
+
if (existsSync8(directory)) {
|
|
38475
38510
|
rmSync5(directory, { recursive: true, force: true });
|
|
38476
|
-
pruneEmpty(
|
|
38511
|
+
pruneEmpty(dirname4(directory), projectPath);
|
|
38477
38512
|
removed.push(directory);
|
|
38478
38513
|
}
|
|
38479
38514
|
}
|
|
38480
38515
|
return removed;
|
|
38481
38516
|
}
|
|
38482
38517
|
function pruneEmpty(directory, projectPath) {
|
|
38483
|
-
const shared =
|
|
38518
|
+
const shared = join9(projectPath, ".agents");
|
|
38484
38519
|
let path = directory;
|
|
38485
38520
|
while (path !== projectPath && (basename(path) === "skills" || path === shared)) {
|
|
38486
38521
|
if (readdirSync3(path).length > 0) {
|
|
38487
38522
|
return;
|
|
38488
38523
|
}
|
|
38489
38524
|
rmSync5(path, { recursive: true, force: true });
|
|
38490
|
-
path =
|
|
38525
|
+
path = dirname4(path);
|
|
38491
38526
|
}
|
|
38492
38527
|
}
|
|
38493
38528
|
function writeSkill(directories, version) {
|
|
38494
38529
|
const files = skillFiles(version);
|
|
38495
38530
|
return directories.map((directory) => {
|
|
38496
|
-
const replaced =
|
|
38531
|
+
const replaced = existsSync8(directory);
|
|
38497
38532
|
rmSync5(directory, { recursive: true, force: true });
|
|
38498
38533
|
for (const [name, contents] of files) {
|
|
38499
|
-
const path =
|
|
38500
|
-
mkdirSync4(
|
|
38534
|
+
const path = join9(directory, name);
|
|
38535
|
+
mkdirSync4(dirname4(path), { recursive: true });
|
|
38501
38536
|
writeFileSync6(path, contents, "utf8");
|
|
38502
38537
|
}
|
|
38503
38538
|
return { path: directory, replaced };
|
|
@@ -38506,13 +38541,13 @@ function writeSkill(directories, version) {
|
|
|
38506
38541
|
|
|
38507
38542
|
// src/version.ts
|
|
38508
38543
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
38509
|
-
import { dirname as
|
|
38544
|
+
import { dirname as dirname5, join as join10 } from "node:path";
|
|
38510
38545
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
38511
38546
|
function getLocalVersion() {
|
|
38512
|
-
const currentDirectory =
|
|
38547
|
+
const currentDirectory = dirname5(fileURLToPath2(import.meta.url));
|
|
38513
38548
|
const packageCandidates = [
|
|
38514
|
-
|
|
38515
|
-
|
|
38549
|
+
join10(currentDirectory, "..", "package.json"),
|
|
38550
|
+
join10(currentDirectory, "..", "..", "package.json")
|
|
38516
38551
|
];
|
|
38517
38552
|
for (const packagePath of packageCandidates) {
|
|
38518
38553
|
try {
|
|
@@ -38534,7 +38569,7 @@ class UsageError extends Refusal {
|
|
|
38534
38569
|
function projectArgument(at) {
|
|
38535
38570
|
const named = args.slice(at).find((value) => !value.startsWith("--"));
|
|
38536
38571
|
const projectPath = resolve5(named ?? ".");
|
|
38537
|
-
if (!
|
|
38572
|
+
if (!existsSync12(join14(projectPath, "project.godot"))) {
|
|
38538
38573
|
throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
|
|
38539
38574
|
}
|
|
38540
38575
|
return projectPath;
|
|
@@ -38678,7 +38713,7 @@ async function setup() {
|
|
|
38678
38713
|
console.log("no harness configured; name one yourself, and gdharness harnesses lists them all");
|
|
38679
38714
|
}
|
|
38680
38715
|
if (!args.includes("--no-skill")) {
|
|
38681
|
-
const directories = skillDirectories(chosen.harnesses, projectPath,
|
|
38716
|
+
const directories = skillDirectories(chosen.harnesses, projectPath, existsSync12);
|
|
38682
38717
|
for (const written of writeSkill(directories, getLocalVersion())) {
|
|
38683
38718
|
console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
|
|
38684
38719
|
}
|
|
@@ -38763,7 +38798,7 @@ async function upgrade() {
|
|
|
38763
38798
|
if (already.length === 0) {
|
|
38764
38799
|
console.log("no harness config names gdharness, so none was re-pinned");
|
|
38765
38800
|
}
|
|
38766
|
-
for (const written of writeSkill(skillDirectories(already, projectPath,
|
|
38801
|
+
for (const written of writeSkill(skillDirectories(already, projectPath, existsSync12), version)) {
|
|
38767
38802
|
console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
|
|
38768
38803
|
}
|
|
38769
38804
|
console.log(`
|