gdharness 0.5.3 → 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.
Files changed (3) hide show
  1. package/build/cli.js +189 -172
  2. package/build/index.js +14 -13
  3. 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 = process.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 existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
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 join4 } from "node:path";
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 join4(set("LOCALAPPDATA") ?? home, "gdharness");
7273
+ return join5(set("LOCALAPPDATA") ?? home, "gdharness");
7256
7274
  }
7257
7275
  if (process.platform === "darwin") {
7258
- return join4(home, "Library", "Caches", "gdharness");
7276
+ return join5(home, "Library", "Caches", "gdharness");
7259
7277
  }
7260
- return join4(set("XDG_CACHE_HOME") ?? join4(home, ".cache"), "gdharness");
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 join4(directory, "update-check.json");
7284
+ return join5(directory, "update-check.json");
7267
7285
  } catch {
7268
- return join4(tmpdir2(), "gdharness-update-check.json");
7286
+ return join5(tmpdir2(), "gdharness-update-check.json");
7269
7287
  }
7270
7288
  }
7271
7289
  function readCache(path) {
7272
7290
  try {
7273
- if (!existsSync4(path)) {
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 existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync5 } from "node:fs";
7443
- import { join as join5 } from "node:path";
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 = join5(directory, entry.name);
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 = join5(projectPath, ".godot", "global_script_class_cache.cfg");
7467
- if (!existsSync5(cache)) {
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 join6 } from "node:path";
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(join6(tmpdir3(), "gdharness-params-"));
7531
- const paramsFile = join6(paramsDir, `${operation}.json`);
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 process5 from "node:process";
30574
+ import process6 from "node:process";
30556
30575
 
30557
30576
  class StdioServerTransport {
30558
- constructor(_stdin = process5.stdin, _stdout = process5.stdout, options) {
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 existsSync8 } from "node:fs";
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" || existsSync8(path)) {
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 process6 from "node:process";
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 = process6.versions;
34581
+ const versions = process7.versions;
34563
34582
  const bun = versions["bun"];
34564
- return bun === undefined ? `node ${process6.versions.node}` : `bun ${bun}`;
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()}, ${process6.platform} ${process6.arch}`],
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**: ${process6.platform} ${process6.arch}`,
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 dirname5, resolve as resolve3 } from "node:path";
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 ?? dirname5(resolve3(filePath));
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 join10 } from "node:path";
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(join10(directory, entry.name));
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 = join10(directory, entry.name);
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 existsSync9, readdirSync as readdirSync5, readFileSync as readFileSync10, unlinkSync } from "node:fs";
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 join11, resolve as resolve4 } from "node:path";
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 join11(perUser ?? tmpdir4(), "gdharness");
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(join11(base, process.platform === "win32" ? "Temp" : "", "gdharness"));
35465
+ candidates.push(join12(base, process.platform === "win32" ? "Temp" : "", "gdharness"));
35447
35466
  }
35448
35467
  return [...new Set(candidates.map((path) => resolve4(path)))];
35449
35468
  }
@@ -35497,7 +35516,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
35497
35516
  return runtimesAnnounced(directories).running;
35498
35517
  }
35499
35518
  function announcedIn(directory) {
35500
- if (!existsSync9(directory)) {
35519
+ if (!existsSync10(directory)) {
35501
35520
  return [];
35502
35521
  }
35503
35522
  const found = [];
@@ -35506,7 +35525,7 @@ function announcedIn(directory) {
35506
35525
  if (!match) {
35507
35526
  continue;
35508
35527
  }
35509
- const file = join11(directory, entry);
35528
+ const file = join12(directory, entry);
35510
35529
  const pid = Number.parseInt(match[1] ?? "", 10);
35511
35530
  const announced = processAlive(pid) ? parseAnnouncement(file, pid) : { kind: "rubbish" };
35512
35531
  if (announced.kind === "rubbish") {
@@ -35652,9 +35671,9 @@ var init_runtime_client = __esm(() => {
35652
35671
 
35653
35672
  // src/server.ts
35654
35673
  import { execFile as execFile5, spawn } from "node:child_process";
35655
- import { existsSync as existsSync10, mkdtempSync as mkdtempSync3, readdirSync as readdirSync6, readFileSync as readFileSync11, realpathSync as realpathSync2, rmSync as rmSync6 } from "node:fs";
35674
+ import { existsSync as existsSync11, mkdtempSync as mkdtempSync3, readdirSync as readdirSync6, readFileSync as readFileSync11, realpathSync as realpathSync2, rmSync as rmSync6 } from "node:fs";
35656
35675
  import { tmpdir as tmpdir5 } from "node:os";
35657
- import { basename as basename2, dirname as dirname6, join as join12, normalize as normalize3 } from "node:path";
35676
+ import { basename as basename2, dirname as dirname7, join as join13, normalize as normalize3 } from "node:path";
35658
35677
  import { setTimeout as delay2 } from "node:timers/promises";
35659
35678
  import { fileURLToPath as fileURLToPath4 } from "node:url";
35660
35679
  import { promisify as promisify5 } from "node:util";
@@ -35700,7 +35719,7 @@ function camelCased(params) {
35700
35719
  class GodotServer {
35701
35720
  mcp;
35702
35721
  locator = new GodotLocator2;
35703
- operationsScript = join12(__dirname2, "godot", "operations", "godot_operations.gd");
35722
+ operationsScript = join13(__dirname2, "godot", "operations", "godot_operations.gd");
35704
35723
  godotBridge;
35705
35724
  tools = buildToolDefinitions();
35706
35725
  activeProcess = null;
@@ -36154,8 +36173,8 @@ class GodotServer {
36154
36173
  if (path === undefined) {
36155
36174
  return { ok: false, response: this.createErrorResponse("projectPath is required.") };
36156
36175
  }
36157
- const file = join12(path, "project.godot");
36158
- if (!existsSync10(file)) {
36176
+ const file = join13(path, "project.godot");
36177
+ if (!existsSync11(file)) {
36159
36178
  return {
36160
36179
  ok: false,
36161
36180
  response: this.createErrorResponse(`Not a Godot project: ${path}`, [
@@ -36389,7 +36408,7 @@ class GodotServer {
36389
36408
  log.finish();
36390
36409
  const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
36391
36410
  const verdict = {
36392
- exported: exitCode === 0 && log.count("error") === 0 && existsSync10(output.absolutePath),
36411
+ exported: exitCode === 0 && log.count("error") === 0 && existsSync11(output.absolutePath),
36393
36412
  preset,
36394
36413
  outputPath: output.relativePath,
36395
36414
  debug,
@@ -36419,7 +36438,7 @@ class GodotServer {
36419
36438
  return contained.response;
36420
36439
  }
36421
36440
  const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
36422
- if (!existsSync10(join12(project.value.path, runner))) {
36441
+ if (!existsSync11(join13(project.value.path, runner))) {
36423
36442
  return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
36424
36443
  "Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
36425
36444
  ]);
@@ -36452,7 +36471,7 @@ class GodotServer {
36452
36471
  ];
36453
36472
  const timeoutMs = readPositiveNumber(args, "timeoutMs") ?? 600000;
36454
36473
  this.logDebug(`Running tests: ${engine.value} ${cmdArgs.join(" ")}`);
36455
- const userData = mkdtempSync3(join12(tmpdir5(), "gdharness-tests-"));
36474
+ const userData = mkdtempSync3(join13(tmpdir5(), "gdharness-tests-"));
36456
36475
  const run = this.spawnGame(engine.value, cmdArgs, userDataIn(userData));
36457
36476
  const hung = await new Promise((resolve) => {
36458
36477
  const timer = setTimeout(() => {
@@ -36468,14 +36487,14 @@ class GodotServer {
36468
36487
  resolve(false);
36469
36488
  });
36470
36489
  });
36471
- const reportsDir = join12(project.value.path, ".godot", "gdharness-reports");
36490
+ const reportsDir = join13(project.value.path, ".godot", "gdharness-reports");
36472
36491
  let report = null;
36473
36492
  let reportProblem = null;
36474
36493
  try {
36475
- const written = existsSync10(reportsDir) ? readdirSync6(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
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))) : [];
36476
36495
  const newest = written.at(-1);
36477
36496
  if (newest !== undefined) {
36478
- report = parseJUnit(readFileSync11(join12(reportsDir, newest, "results.xml"), "utf8"));
36497
+ report = parseJUnit(readFileSync11(join13(reportsDir, newest, "results.xml"), "utf8"));
36479
36498
  }
36480
36499
  } catch (error) {
36481
36500
  reportProblem = errorMessage(error);
@@ -36988,8 +37007,8 @@ class GodotServer {
36988
37007
  return this.createErrorResponse(choice.problem);
36989
37008
  }
36990
37009
  const expectsScreenshot = command === "capture_screenshot" || command === "capture_viewport";
36991
- const screenshotDir = expectsScreenshot ? mkdtempSync3(join12(tmpdir5(), "gdharness-runtime-screenshot-")) : null;
36992
- const screenshotPath = screenshotDir ? join12(screenshotDir, "capture.png") : null;
37010
+ const screenshotDir = expectsScreenshot ? mkdtempSync3(join13(tmpdir5(), "gdharness-runtime-screenshot-")) : null;
37011
+ const screenshotPath = screenshotDir ? join13(screenshotDir, "capture.png") : null;
36993
37012
  try {
36994
37013
  const reply = await runtimeRequest(choice.endpoint, command, screenshotPath ? { ...params, output_path: screenshotPath } : params, timeoutMs);
36995
37014
  if (!reply.ok) {
@@ -37095,7 +37114,7 @@ var init_server3 = __esm(() => {
37095
37114
  init_tool_definitions();
37096
37115
  init_update_check();
37097
37116
  run5 = promisify5(execFile5);
37098
- __dirname2 = dirname6(fileURLToPath4(import.meta.url));
37117
+ __dirname2 = dirname7(fileURLToPath4(import.meta.url));
37099
37118
  PATH_SOLUTIONS = [
37100
37119
  'Give the path relative to the project, such as "scenes/main.tscn" or "res://scenes/main.tscn"',
37101
37120
  "Point projectPath at the project the file belongs to"
@@ -37152,8 +37171,8 @@ var init_server3 = __esm(() => {
37152
37171
  });
37153
37172
 
37154
37173
  // src/cli.ts
37155
- import { existsSync as existsSync11 } from "fs";
37156
- import { join as join13, resolve as resolve5 } from "path";
37174
+ import { existsSync as existsSync12 } from "fs";
37175
+ import { join as join14, resolve as resolve5 } from "path";
37157
37176
 
37158
37177
  // src/errors.ts
37159
37178
  class Refusal extends Error {
@@ -37216,10 +37235,10 @@ class GodotLocator {
37216
37235
  }
37217
37236
 
37218
37237
  // src/harnesses.ts
37219
- import { existsSync as existsSync3, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
37238
+ import { existsSync as existsSync4, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
37220
37239
  import { homedir as homedir2 } from "node:os";
37221
- import { dirname, join as join2 } from "node:path";
37222
- import process2 from "node:process";
37240
+ import { dirname as dirname2, join as join3 } from "node:path";
37241
+ import process3 from "node:process";
37223
37242
 
37224
37243
  // node_modules/yaml/dist/index.js
37225
37244
  var composer = require_composer();
@@ -37361,13 +37380,11 @@ function isEmptyCollection(node) {
37361
37380
 
37362
37381
  // src/harnesses.ts
37363
37382
  init_errors();
37383
+ init_runner();
37364
37384
  var SERVER_KEY = "gdharness";
37365
37385
  function launchFor(version, godotPath, runner = currentRunner()) {
37366
- return {
37367
- command: runner,
37368
- args: runner === "npx" ? ["-y", `gdharness@${version}`] : [`gdharness@${version}`],
37369
- env: { GODOT_PATH: godotPath }
37370
- };
37386
+ const spawn = spawnFor(runner, version);
37387
+ return { command: spawn.command, args: spawn.args, env: { GODOT_PATH: godotPath } };
37371
37388
  }
37372
37389
  function tomlArray(values) {
37373
37390
  return `[${values.map((value) => `"${value}"`).join(", ")}]`;
@@ -37389,7 +37406,7 @@ var HARNESSES = [
37389
37406
  shape: "plain",
37390
37407
  home: ".claude",
37391
37408
  marker: ".claude",
37392
- skills: { dir: join2(".claude", "skills"), shared: false }
37409
+ skills: { dir: join3(".claude", "skills"), shared: false }
37393
37410
  },
37394
37411
  {
37395
37412
  id: "copilot-cli",
@@ -37399,7 +37416,7 @@ var HARNESSES = [
37399
37416
  container: "mcpServers",
37400
37417
  shape: "plain",
37401
37418
  home: ".copilot",
37402
- skills: { dir: join2(".github", "skills"), shared: true },
37419
+ skills: { dir: join3(".github", "skills"), shared: true },
37403
37420
  manual: "Trust the folder when Copilot CLI first asks, or it reads no config here."
37404
37421
  },
37405
37422
  {
@@ -37425,22 +37442,22 @@ var HARNESSES = [
37425
37442
  id: "cursor",
37426
37443
  name: "Cursor",
37427
37444
  scope: "project",
37428
- file: join2(".cursor", "mcp.json"),
37445
+ file: join3(".cursor", "mcp.json"),
37429
37446
  container: "mcpServers",
37430
37447
  shape: "plain",
37431
37448
  home: ".cursor",
37432
- skills: { dir: join2(".cursor", "skills"), shared: true },
37449
+ skills: { dir: join3(".cursor", "skills"), shared: true },
37433
37450
  manual: "Cursor asks before each tool call by default, and the server can be toggled off."
37434
37451
  },
37435
37452
  {
37436
37453
  id: "vscode",
37437
37454
  name: "VS Code",
37438
37455
  scope: "project",
37439
- file: join2(".vscode", "mcp.json"),
37456
+ file: join3(".vscode", "mcp.json"),
37440
37457
  container: "servers",
37441
37458
  shape: "typed",
37442
37459
  home: ".vscode",
37443
- skills: { dir: join2(".github", "skills"), shared: true },
37460
+ skills: { dir: join3(".github", "skills"), shared: true },
37444
37461
  manual: "VS Code asks you to trust a server the first time it starts one."
37445
37462
  },
37446
37463
  {
@@ -37450,45 +37467,45 @@ var HARNESSES = [
37450
37467
  file: "opencode.json",
37451
37468
  container: "mcp",
37452
37469
  shape: "opencode",
37453
- home: join2(".config", "opencode"),
37470
+ home: join3(".config", "opencode"),
37454
37471
  marker: ".opencode",
37455
- skills: { dir: join2(".opencode", "skills"), shared: true }
37472
+ skills: { dir: join3(".opencode", "skills"), shared: true }
37456
37473
  },
37457
37474
  {
37458
37475
  id: "junie",
37459
37476
  name: "Junie",
37460
37477
  scope: "project",
37461
- file: join2(".junie", "mcp", "mcp.json"),
37478
+ file: join3(".junie", "mcp", "mcp.json"),
37462
37479
  container: "mcpServers",
37463
37480
  shape: "plain",
37464
37481
  home: ".junie",
37465
- skills: { dir: join2(".junie", "skills"), shared: true }
37482
+ skills: { dir: join3(".junie", "skills"), shared: true }
37466
37483
  },
37467
37484
  {
37468
37485
  id: "kiro",
37469
37486
  name: "Kiro",
37470
37487
  scope: "project",
37471
- file: join2(".kiro", "settings", "mcp.json"),
37488
+ file: join3(".kiro", "settings", "mcp.json"),
37472
37489
  container: "mcpServers",
37473
37490
  shape: "plain",
37474
37491
  home: ".kiro",
37475
- skills: { dir: join2(".kiro", "skills"), shared: false }
37492
+ skills: { dir: join3(".kiro", "skills"), shared: false }
37476
37493
  },
37477
37494
  {
37478
37495
  id: "gemini",
37479
37496
  name: "Gemini CLI",
37480
37497
  scope: "project",
37481
- file: join2(".gemini", "settings.json"),
37498
+ file: join3(".gemini", "settings.json"),
37482
37499
  container: "mcpServers",
37483
37500
  shape: "plain",
37484
37501
  home: ".gemini",
37485
- skills: { dir: join2(".gemini", "skills"), shared: true }
37502
+ skills: { dir: join3(".gemini", "skills"), shared: true }
37486
37503
  },
37487
37504
  {
37488
37505
  id: "roo",
37489
37506
  name: "Roo Code",
37490
37507
  scope: "project",
37491
- file: join2(".roo", "mcp.json"),
37508
+ file: join3(".roo", "mcp.json"),
37492
37509
  container: "mcpServers",
37493
37510
  shape: "plain"
37494
37511
  },
@@ -37496,7 +37513,7 @@ var HARNESSES = [
37496
37513
  id: "kilo",
37497
37514
  name: "Kilo Code",
37498
37515
  scope: "project",
37499
- file: join2(".kilocode", "mcp.json"),
37516
+ file: join3(".kilocode", "mcp.json"),
37500
37517
  container: "mcpServers",
37501
37518
  shape: "plain"
37502
37519
  },
@@ -37504,16 +37521,16 @@ var HARNESSES = [
37504
37521
  id: "amazon-q",
37505
37522
  name: "Amazon Q Developer CLI",
37506
37523
  scope: "project",
37507
- file: join2(".amazonq", "mcp.json"),
37524
+ file: join3(".amazonq", "mcp.json"),
37508
37525
  container: "mcpServers",
37509
37526
  shape: "plain",
37510
- home: join2(".aws", "amazonq")
37527
+ home: join3(".aws", "amazonq")
37511
37528
  },
37512
37529
  {
37513
37530
  id: "zed",
37514
37531
  name: "Zed",
37515
37532
  scope: "project",
37516
- file: join2(".zed", "settings.json"),
37533
+ file: join3(".zed", "settings.json"),
37517
37534
  container: "context_servers",
37518
37535
  shape: "plain"
37519
37536
  },
@@ -37521,16 +37538,16 @@ var HARNESSES = [
37521
37538
  id: "amp",
37522
37539
  name: "Amp",
37523
37540
  scope: "project",
37524
- file: join2(".amp", "settings.json"),
37541
+ file: join3(".amp", "settings.json"),
37525
37542
  container: "amp.mcpServers",
37526
37543
  shape: "plain",
37527
- home: join2(".config", "amp")
37544
+ home: join3(".config", "amp")
37528
37545
  },
37529
37546
  {
37530
37547
  id: "warp",
37531
37548
  name: "Warp",
37532
37549
  scope: "project",
37533
- file: join2(".warp", ".mcp.json"),
37550
+ file: join3(".warp", ".mcp.json"),
37534
37551
  container: "mcpServers",
37535
37552
  shape: "plain",
37536
37553
  home: ".warp",
@@ -37540,7 +37557,7 @@ var HARNESSES = [
37540
37557
  id: "trae",
37541
37558
  name: "Trae",
37542
37559
  scope: "project",
37543
- file: join2(".trae", "mcp.json"),
37560
+ file: join3(".trae", "mcp.json"),
37544
37561
  container: "mcpServers",
37545
37562
  shape: "plain",
37546
37563
  home: ".trae"
@@ -37549,7 +37566,7 @@ var HARNESSES = [
37549
37566
  id: "factory",
37550
37567
  name: "Factory Droid",
37551
37568
  scope: "project",
37552
- file: join2(".factory", "mcp.json"),
37569
+ file: join3(".factory", "mcp.json"),
37553
37570
  container: "mcpServers",
37554
37571
  shape: "typed",
37555
37572
  home: ".factory"
@@ -37558,7 +37575,7 @@ var HARNESSES = [
37558
37575
  id: "tabnine",
37559
37576
  name: "Tabnine",
37560
37577
  scope: "project",
37561
- file: join2(".tabnine", "mcp_servers.json"),
37578
+ file: join3(".tabnine", "mcp_servers.json"),
37562
37579
  container: "mcpServers",
37563
37580
  shape: "plain",
37564
37581
  home: ".tabnine"
@@ -37575,7 +37592,7 @@ var HARNESSES = [
37575
37592
  id: "pi",
37576
37593
  name: "pi",
37577
37594
  scope: "project",
37578
- file: join2(".pi", "mcp.json"),
37595
+ file: join3(".pi", "mcp.json"),
37579
37596
  container: "mcpServers",
37580
37597
  shape: "plain",
37581
37598
  home: ".pi"
@@ -37584,7 +37601,7 @@ var HARNESSES = [
37584
37601
  id: "mistral-vibe",
37585
37602
  name: "Mistral Vibe",
37586
37603
  scope: "project",
37587
- file: join2(".vibe", "config.toml"),
37604
+ file: join3(".vibe", "config.toml"),
37588
37605
  container: "mcp_servers",
37589
37606
  shape: "plain",
37590
37607
  toml: {
@@ -37640,7 +37657,7 @@ var HARNESSES = [
37640
37657
  id: "codex",
37641
37658
  name: "Codex CLI",
37642
37659
  scope: "home",
37643
- file: join2(".codex", "config.toml"),
37660
+ file: join3(".codex", "config.toml"),
37644
37661
  container: "mcp_servers",
37645
37662
  shape: "plain",
37646
37663
  manual: "Codex reads its config at startup, so restart it.",
@@ -37659,20 +37676,20 @@ var HARNESSES = [
37659
37676
  id: "cline",
37660
37677
  name: "Cline",
37661
37678
  scope: "home",
37662
- file: join2(".cline", "data", "settings", "cline_mcp_settings.json"),
37679
+ file: join3(".cline", "data", "settings", "cline_mcp_settings.json"),
37663
37680
  container: "mcpServers",
37664
37681
  shape: "plain",
37665
37682
  marker: ".cline",
37666
- skills: { dir: join2(".cline", "skills"), shared: false }
37683
+ skills: { dir: join3(".cline", "skills"), shared: false }
37667
37684
  },
37668
37685
  {
37669
37686
  id: "goose",
37670
37687
  name: "Goose",
37671
37688
  scope: "home",
37672
37689
  file: {
37673
- win32: { appData: join2("Block", "goose", "config", "config.yaml") },
37674
- darwin: join2(".config", "goose", "config.yaml"),
37675
- linux: join2(".config", "goose", "config.yaml")
37690
+ win32: { appData: join3("Block", "goose", "config", "config.yaml") },
37691
+ darwin: join3(".config", "goose", "config.yaml"),
37692
+ linux: join3(".config", "goose", "config.yaml")
37676
37693
  },
37677
37694
  container: "extensions",
37678
37695
  shape: "plain",
@@ -37693,19 +37710,19 @@ var HARNESSES = [
37693
37710
  id: "windsurf",
37694
37711
  name: "Windsurf",
37695
37712
  scope: "home",
37696
- file: join2(".codeium", "windsurf", "mcp_config.json"),
37713
+ file: join3(".codeium", "windsurf", "mcp_config.json"),
37697
37714
  container: "mcpServers",
37698
37715
  shape: "plain",
37699
- skills: { dir: join2(".windsurf", "skills"), shared: true }
37716
+ skills: { dir: join3(".windsurf", "skills"), shared: true }
37700
37717
  },
37701
37718
  {
37702
37719
  id: "hermes",
37703
37720
  name: "Hermes",
37704
37721
  scope: "home",
37705
- file: join2(".hermes", "config.yaml"),
37722
+ file: join3(".hermes", "config.yaml"),
37706
37723
  container: "mcp_servers",
37707
37724
  shape: "plain",
37708
- skills: { dir: join2(".hermes", "skills"), shared: true },
37725
+ skills: { dir: join3(".hermes", "skills"), shared: true },
37709
37726
  yaml: {
37710
37727
  path: ["mcp_servers", SERVER_KEY],
37711
37728
  entry: (launch) => ({
@@ -37720,7 +37737,7 @@ var HARNESSES = [
37720
37737
  id: "openclaw",
37721
37738
  name: "OpenClaw",
37722
37739
  scope: "home",
37723
- file: join2(".openclaw", "openclaw.json"),
37740
+ file: join3(".openclaw", "openclaw.json"),
37724
37741
  container: "mcpServers",
37725
37742
  shape: "plain"
37726
37743
  },
@@ -37729,9 +37746,9 @@ var HARNESSES = [
37729
37746
  name: "Claude Desktop",
37730
37747
  scope: "home",
37731
37748
  file: {
37732
- win32: { appData: join2("Claude", "claude_desktop_config.json") },
37733
- darwin: join2("Library", "Application Support", "Claude", "claude_desktop_config.json"),
37734
- linux: join2(".config", "Claude", "claude_desktop_config.json")
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")
37735
37752
  },
37736
37753
  container: "mcpServers",
37737
37754
  shape: "plain"
@@ -37740,7 +37757,7 @@ var HARNESSES = [
37740
37757
  id: "zeroclaw",
37741
37758
  name: "ZeroClaw",
37742
37759
  scope: "home",
37743
- file: join2(".zeroclaw", "config.toml"),
37760
+ file: join3(".zeroclaw", "config.toml"),
37744
37761
  container: "mcp.servers",
37745
37762
  shape: "plain",
37746
37763
  toml: {
@@ -37761,7 +37778,7 @@ var HARNESSES = [
37761
37778
  id: "deepcode",
37762
37779
  name: "Deep Code",
37763
37780
  scope: "home",
37764
- file: join2(".deepcode", "settings.json"),
37781
+ file: join3(".deepcode", "settings.json"),
37765
37782
  container: "mcpServers",
37766
37783
  shape: "plain"
37767
37784
  },
@@ -37769,7 +37786,7 @@ var HARNESSES = [
37769
37786
  id: "nanobot",
37770
37787
  name: "nanobot",
37771
37788
  scope: "home",
37772
- file: join2(".nanobot", "config.json"),
37789
+ file: join3(".nanobot", "config.json"),
37773
37790
  container: "mcpServers",
37774
37791
  shape: "plain",
37775
37792
  snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
@@ -37778,19 +37795,19 @@ var HARNESSES = [
37778
37795
  id: "autohand",
37779
37796
  name: "Autohand",
37780
37797
  scope: "home",
37781
- file: join2(".autohand", "config.json"),
37798
+ file: join3(".autohand", "config.json"),
37782
37799
  container: "mcpServers",
37783
37800
  shape: "plain",
37784
37801
  snippet: (launch) => jsonSnippet(launch, "mcpServers", "plain")
37785
37802
  }
37786
37803
  ];
37787
37804
  function appDataRoot() {
37788
- return process2.env["APPDATA"] ?? join2(homedir2(), "AppData", "Roaming");
37805
+ return process3.env["APPDATA"] ?? join3(homedir2(), "AppData", "Roaming");
37789
37806
  }
37790
37807
  function homePath(path) {
37791
- return typeof path === "string" ? join2(homedir2(), path) : join2(appDataRoot(), path.appData);
37808
+ return typeof path === "string" ? join3(homedir2(), path) : join3(appDataRoot(), path.appData);
37792
37809
  }
37793
- function fileFor(harness, platform = process2.platform) {
37810
+ function fileFor(harness, platform = process3.platform) {
37794
37811
  if (typeof harness.file === "string") {
37795
37812
  return harness.file;
37796
37813
  }
@@ -37799,11 +37816,11 @@ function fileFor(harness, platform = process2.platform) {
37799
37816
  function configPath(harness, projectPath) {
37800
37817
  const file = fileFor(harness);
37801
37818
  if (harness.scope === "project") {
37802
- return join2(projectPath, file);
37819
+ return join3(projectPath, file);
37803
37820
  }
37804
37821
  return homePath(file);
37805
37822
  }
37806
- function displayPath(harness, platform = process2.platform) {
37823
+ function displayPath(harness, platform = process3.platform) {
37807
37824
  const file = fileFor(harness, platform);
37808
37825
  if (typeof file !== "string") {
37809
37826
  return `%APPDATA%/${file.appData.replaceAll("\\", "/")}`;
@@ -37839,15 +37856,15 @@ function harnessById(id) {
37839
37856
  }
37840
37857
  function present(harness, projectPath) {
37841
37858
  const path = configPath(harness, projectPath);
37842
- if (existsSync3(path)) {
37859
+ if (existsSync4(path)) {
37843
37860
  return true;
37844
37861
  }
37845
37862
  const root = harness.scope === "project" ? projectPath : homedir2();
37846
- const own = dirname(path);
37847
- if (own !== root && existsSync3(own)) {
37863
+ const own = dirname2(path);
37864
+ if (own !== root && existsSync4(own)) {
37848
37865
  return true;
37849
37866
  }
37850
- return harness.marker !== undefined && existsSync3(join2(root, harness.marker));
37867
+ return harness.marker !== undefined && existsSync4(join3(root, harness.marker));
37851
37868
  }
37852
37869
  function candidates(projectPath) {
37853
37870
  const found = [];
@@ -37860,7 +37877,7 @@ function candidates(projectPath) {
37860
37877
  }
37861
37878
  if (present(harness, projectPath)) {
37862
37879
  found.push({ harness, reason: "configured" });
37863
- } else if (harness.home !== undefined && existsSync3(join2(homedir2(), harness.home))) {
37880
+ } else if (harness.home !== undefined && existsSync4(join3(homedir2(), harness.home))) {
37864
37881
  found.push({ harness, reason: "installed" });
37865
37882
  }
37866
37883
  }
@@ -37882,7 +37899,7 @@ function groupByFile(harnesses, projectPath) {
37882
37899
  }
37883
37900
  function registered(harness, projectPath) {
37884
37901
  const path = configPath(harness, projectPath);
37885
- if (harness.snippet !== undefined || !existsSync3(path)) {
37902
+ if (harness.snippet !== undefined || !existsSync4(path)) {
37886
37903
  return false;
37887
37904
  }
37888
37905
  const text = readFileSync(path, "utf8");
@@ -37906,7 +37923,7 @@ function registered(harness, projectPath) {
37906
37923
  }
37907
37924
  function disconnect(harness, projectPath) {
37908
37925
  const path = configPath(harness, projectPath);
37909
- if (!existsSync3(path)) {
37926
+ if (!existsSync4(path)) {
37910
37927
  return { harness, path, action: "absent" };
37911
37928
  }
37912
37929
  if (harness.snippet !== undefined) {
@@ -37953,7 +37970,7 @@ function connect(harness, projectPath, launch) {
37953
37970
  if (harness.snippet !== undefined) {
37954
37971
  return { harness, path, action: "snippet", snippet: harness.snippet(launch) };
37955
37972
  }
37956
- const held = existsSync3(path) ? readFileSync(path, "utf8") : "";
37973
+ const held = existsSync4(path) ? readFileSync(path, "utf8") : "";
37957
37974
  if (harness.toml !== undefined) {
37958
37975
  const already = held.includes(harness.toml.identity ?? harness.toml.header);
37959
37976
  return put(harness, path, writeToml(held, harness.toml, launch), already);
@@ -37976,7 +37993,7 @@ function connect(harness, projectPath, launch) {
37976
37993
  `, already);
37977
37994
  }
37978
37995
  function put(harness, path, contents, already) {
37979
- mkdirSync(dirname(path), { recursive: true });
37996
+ mkdirSync(dirname2(path), { recursive: true });
37980
37997
  writeFileSync(path, contents, "utf8");
37981
37998
  return { harness, path, action: already ? "replaced" : "written" };
37982
37999
  }
@@ -37997,7 +38014,7 @@ init_game_log();
37997
38014
  import { execFile as execFile2 } from "node:child_process";
37998
38015
  import { mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
37999
38016
  import { tmpdir } from "node:os";
38000
- import { join as join3 } from "node:path";
38017
+ import { join as join4 } from "node:path";
38001
38018
  import { promisify as promisify2 } from "node:util";
38002
38019
  var run2 = promisify2(execFile2);
38003
38020
  function snakeCased(params) {
@@ -38038,8 +38055,8 @@ function reason(stdout, stderr) {
38038
38055
  return stdout.trim().split(/\r?\n/).at(-1) ?? "no output at all";
38039
38056
  }
38040
38057
  async function runOperation(engine, operation, params, projectPath) {
38041
- const paramsDir = mkdtempSync(join3(tmpdir(), "gdharness-params-"));
38042
- const paramsFile = join3(paramsDir, `${operation}.json`);
38058
+ const paramsDir = mkdtempSync(join4(tmpdir(), "gdharness-params-"));
38059
+ const paramsFile = join4(paramsDir, `${operation}.json`);
38043
38060
  writeFileSync2(paramsFile, JSON.stringify(snakeCased(params)), "utf8");
38044
38061
  const args = [
38045
38062
  "--headless",
@@ -38087,13 +38104,13 @@ async function runOperation(engine, operation, params, projectPath) {
38087
38104
  init_errors();
38088
38105
  init_server_version();
38089
38106
  import { createHash } from "node:crypto";
38090
- import process3 from "node:process";
38107
+ import process4 from "node:process";
38091
38108
  var NEW_ISSUE = "https://github.com/Aureliolo/gdharness/issues/new";
38092
38109
  var ENHANCEMENT_URL = `${NEW_ISSUE}?template=feature_request.md`;
38093
38110
  function runtime() {
38094
- const versions = process3.versions;
38111
+ const versions = process4.versions;
38095
38112
  const bun = versions["bun"];
38096
- return bun === undefined ? `node ${process3.versions.node}` : `bun ${bun}`;
38113
+ return bun === undefined ? `node ${process4.versions.node}` : `bun ${bun}`;
38097
38114
  }
38098
38115
  function defectSignature(where, message) {
38099
38116
  const normalised = `${where}
@@ -38105,7 +38122,7 @@ function facts(where, message, godotVersion) {
38105
38122
  ["Where", where],
38106
38123
  ["Error", message],
38107
38124
  ["Version", `gdharness ${SERVER_VERSION}`],
38108
- ["Runtime", `${runtime()}, ${process3.platform} ${process3.arch}`],
38125
+ ["Runtime", `${runtime()}, ${process4.platform} ${process4.arch}`],
38109
38126
  ["Godot", godotVersion ?? "not known at the point this failed"],
38110
38127
  ["Signature", defectSignature(where, message)]
38111
38128
  ];
@@ -38115,7 +38132,7 @@ function filledTemplate(where, message, godotVersion) {
38115
38132
  `**gdharness version**: ${SERVER_VERSION}`,
38116
38133
  `**Godot version**: ${godotVersion ?? ""}`,
38117
38134
  `**Bun version**: ${runtime()}`,
38118
- `**OS**: ${process3.platform} ${process3.arch}`,
38135
+ `**OS**: ${process4.platform} ${process4.arch}`,
38119
38136
  "**MCP client**:",
38120
38137
  "",
38121
38138
  "## What you did",
@@ -38177,10 +38194,10 @@ function defectReport(where, error, godotVersion) {
38177
38194
  }
38178
38195
 
38179
38196
  // src/prompt.ts
38180
- import process4 from "node:process";
38197
+ import process5 from "node:process";
38181
38198
  import { createInterface } from "node:readline/promises";
38182
38199
  function interactive() {
38183
- return process4.stdin.isTTY && process4.stdout.isTTY;
38200
+ return process5.stdin.isTTY && process5.stdout.isTTY;
38184
38201
  }
38185
38202
 
38186
38203
  class Ask {
@@ -38189,7 +38206,7 @@ class Ask {
38189
38206
  if (!interactive()) {
38190
38207
  return fallback;
38191
38208
  }
38192
- this.line ??= createInterface({ input: process4.stdin, output: process4.stdout });
38209
+ this.line ??= createInterface({ input: process5.stdin, output: process5.stdout });
38193
38210
  const answer = (await this.line.question(`${question} ${fallback ? "[Y/n]" : "[y/N]"} `)).trim();
38194
38211
  return answer === "" ? fallback : answer.toLowerCase().startsWith("y");
38195
38212
  }
@@ -38218,8 +38235,8 @@ init_class_cache();
38218
38235
  init_headless();
38219
38236
  init_resources();
38220
38237
  init_server_version();
38221
- import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync7, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "node:fs";
38222
- import { dirname as dirname2, join as join7 } from "node:path";
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";
38223
38240
  import { fileURLToPath } from "node:url";
38224
38241
  var ADDONS = ["gdharness_editor", "gdharness_runtime", "auto_reload"];
38225
38242
  var EDITOR_PLUGINS = ["gdharness_editor", "auto_reload"];
@@ -38229,24 +38246,24 @@ var RUNTIME_AUTOLOAD = {
38229
38246
  };
38230
38247
  var VERSION_MARKER = ".gdharness-version";
38231
38248
  function shippedAddonsDirectory() {
38232
- return join7(dirname2(fileURLToPath(import.meta.url)), "godot", "addons");
38249
+ return join8(dirname3(fileURLToPath(import.meta.url)), "godot", "addons");
38233
38250
  }
38234
38251
  function shippedOperationsScript() {
38235
- return join7(dirname2(fileURLToPath(import.meta.url)), "godot", "operations", "godot_operations.gd");
38252
+ return join8(dirname3(fileURLToPath(import.meta.url)), "godot", "operations", "godot_operations.gd");
38236
38253
  }
38237
38254
  function installAddons(projectPath, from = shippedAddonsDirectory()) {
38238
38255
  const installed = [];
38239
38256
  for (const name of ADDONS) {
38240
- const source = join7(from, name);
38241
- if (!existsSync6(join7(source, name === "gdharness_runtime" ? "runtime_autoload.gd" : "plugin.cfg"))) {
38257
+ const source = join8(from, name);
38258
+ if (!existsSync7(join8(source, name === "gdharness_runtime" ? "runtime_autoload.gd" : "plugin.cfg"))) {
38242
38259
  throw new Error(`The package holds no ${name} addon at ${source}.`);
38243
38260
  }
38244
- const target = join7(projectPath, "addons", name);
38245
- const replaced = existsSync6(target);
38261
+ const target = join8(projectPath, "addons", name);
38262
+ const replaced = existsSync7(target);
38246
38263
  rmSync4(target, { recursive: true, force: true });
38247
- mkdirSync3(dirname2(target), { recursive: true });
38264
+ mkdirSync3(dirname3(target), { recursive: true });
38248
38265
  cpSync(source, target, { recursive: true });
38249
- writeFileSync5(join7(target, VERSION_MARKER), `${SERVER_VERSION}
38266
+ writeFileSync5(join8(target, VERSION_MARKER), `${SERVER_VERSION}
38250
38267
  `);
38251
38268
  installed.push({ name, path: target, replaced });
38252
38269
  }
@@ -38255,8 +38272,8 @@ function installAddons(projectPath, from = shippedAddonsDirectory()) {
38255
38272
  function removeAddons(projectPath) {
38256
38273
  const removed = [];
38257
38274
  for (const name of ADDONS) {
38258
- const target = join7(projectPath, "addons", name);
38259
- if (existsSync6(target)) {
38275
+ const target = join8(projectPath, "addons", name);
38276
+ if (existsSync7(target)) {
38260
38277
  rmSync4(target, { recursive: true, force: true });
38261
38278
  removed.push(target);
38262
38279
  }
@@ -38290,10 +38307,10 @@ function enabledPlugins(settings) {
38290
38307
  function inspectProject(projectPath) {
38291
38308
  const problems = [];
38292
38309
  const addons = ADDONS.map((name) => {
38293
- const directory = join7(projectPath, "addons", name);
38294
- const marker = join7(directory, VERSION_MARKER);
38295
- const installed = existsSync6(directory);
38296
- const version = existsSync6(marker) ? readFileSync7(marker, "utf8").trim() : null;
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;
38297
38314
  const current = version === SERVER_VERSION;
38298
38315
  if (!installed) {
38299
38316
  problems.push(`addons/${name} is not installed; run gdharness setup`);
@@ -38302,7 +38319,7 @@ function inspectProject(projectPath) {
38302
38319
  }
38303
38320
  return { name, installed, version, current };
38304
38321
  });
38305
- const settings = parseProjectGodot(readFileSync7(join7(projectPath, "project.godot"), "utf8"));
38322
+ const settings = parseProjectGodot(readFileSync7(join8(projectPath, "project.godot"), "utf8"));
38306
38323
  const pluginsEnabled = enabledPlugins(settings);
38307
38324
  for (const name of EDITOR_PLUGINS) {
38308
38325
  if (!pluginsEnabled.includes(name)) {
@@ -38331,8 +38348,8 @@ function inspectProject(projectPath) {
38331
38348
 
38332
38349
  // src/skill.ts
38333
38350
  init_tool_definitions();
38334
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
38335
- import { basename, dirname as dirname3, join as join8 } from "node:path";
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";
38336
38353
 
38337
38354
  // src/tool-reference.ts
38338
38355
  init_tool_definitions();
@@ -38379,7 +38396,7 @@ function renderToolsMarkdown() {
38379
38396
 
38380
38397
  // src/skill.ts
38381
38398
  var SKILL_NAME = "gdharness";
38382
- var SHARED_SKILLS = join8(".agents", "skills");
38399
+ var SHARED_SKILLS = join9(".agents", "skills");
38383
38400
  function skillMarkdown(version) {
38384
38401
  return `---
38385
38402
  name: ${SKILL_NAME}
@@ -38461,27 +38478,27 @@ whatever the engine said on stderr comes back under \`engine_messages\`.
38461
38478
  function skillFiles(version) {
38462
38479
  return new Map([
38463
38480
  ["SKILL.md", skillMarkdown(version)],
38464
- [join8("references", "tools.md"), renderToolsMarkdown()]
38481
+ [join9("references", "tools.md"), renderToolsMarkdown()]
38465
38482
  ]);
38466
38483
  }
38467
38484
  function skillDirectories(harnesses, projectPath, exists) {
38468
- const directories = [join8(projectPath, SHARED_SKILLS, SKILL_NAME)];
38485
+ const directories = [join9(projectPath, SHARED_SKILLS, SKILL_NAME)];
38469
38486
  for (const harness of harnesses) {
38470
38487
  if (harness.skills === undefined) {
38471
38488
  continue;
38472
38489
  }
38473
- const own = join8(projectPath, harness.skills.dir);
38474
- if ((!harness.skills.shared || exists(own)) && !directories.includes(join8(own, SKILL_NAME))) {
38475
- directories.push(join8(own, SKILL_NAME));
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));
38476
38493
  }
38477
38494
  }
38478
38495
  return directories;
38479
38496
  }
38480
38497
  function everySkillDirectory(projectPath, harnesses) {
38481
- const directories = new Set([join8(projectPath, SHARED_SKILLS, SKILL_NAME)]);
38498
+ const directories = new Set([join9(projectPath, SHARED_SKILLS, SKILL_NAME)]);
38482
38499
  for (const harness of harnesses) {
38483
38500
  if (harness.skills !== undefined) {
38484
- directories.add(join8(projectPath, harness.skills.dir, SKILL_NAME));
38501
+ directories.add(join9(projectPath, harness.skills.dir, SKILL_NAME));
38485
38502
  }
38486
38503
  }
38487
38504
  return [...directories];
@@ -38489,33 +38506,33 @@ function everySkillDirectory(projectPath, harnesses) {
38489
38506
  function removeSkill(directories, projectPath) {
38490
38507
  const removed = [];
38491
38508
  for (const directory of directories) {
38492
- if (existsSync7(directory)) {
38509
+ if (existsSync8(directory)) {
38493
38510
  rmSync5(directory, { recursive: true, force: true });
38494
- pruneEmpty(dirname3(directory), projectPath);
38511
+ pruneEmpty(dirname4(directory), projectPath);
38495
38512
  removed.push(directory);
38496
38513
  }
38497
38514
  }
38498
38515
  return removed;
38499
38516
  }
38500
38517
  function pruneEmpty(directory, projectPath) {
38501
- const shared = join8(projectPath, ".agents");
38518
+ const shared = join9(projectPath, ".agents");
38502
38519
  let path = directory;
38503
38520
  while (path !== projectPath && (basename(path) === "skills" || path === shared)) {
38504
38521
  if (readdirSync3(path).length > 0) {
38505
38522
  return;
38506
38523
  }
38507
38524
  rmSync5(path, { recursive: true, force: true });
38508
- path = dirname3(path);
38525
+ path = dirname4(path);
38509
38526
  }
38510
38527
  }
38511
38528
  function writeSkill(directories, version) {
38512
38529
  const files = skillFiles(version);
38513
38530
  return directories.map((directory) => {
38514
- const replaced = existsSync7(directory);
38531
+ const replaced = existsSync8(directory);
38515
38532
  rmSync5(directory, { recursive: true, force: true });
38516
38533
  for (const [name, contents] of files) {
38517
- const path = join8(directory, name);
38518
- mkdirSync4(dirname3(path), { recursive: true });
38534
+ const path = join9(directory, name);
38535
+ mkdirSync4(dirname4(path), { recursive: true });
38519
38536
  writeFileSync6(path, contents, "utf8");
38520
38537
  }
38521
38538
  return { path: directory, replaced };
@@ -38524,13 +38541,13 @@ function writeSkill(directories, version) {
38524
38541
 
38525
38542
  // src/version.ts
38526
38543
  import { readFileSync as readFileSync8 } from "node:fs";
38527
- import { dirname as dirname4, join as join9 } from "node:path";
38544
+ import { dirname as dirname5, join as join10 } from "node:path";
38528
38545
  import { fileURLToPath as fileURLToPath2 } from "node:url";
38529
38546
  function getLocalVersion() {
38530
- const currentDirectory = dirname4(fileURLToPath2(import.meta.url));
38547
+ const currentDirectory = dirname5(fileURLToPath2(import.meta.url));
38531
38548
  const packageCandidates = [
38532
- join9(currentDirectory, "..", "package.json"),
38533
- join9(currentDirectory, "..", "..", "package.json")
38549
+ join10(currentDirectory, "..", "package.json"),
38550
+ join10(currentDirectory, "..", "..", "package.json")
38534
38551
  ];
38535
38552
  for (const packagePath of packageCandidates) {
38536
38553
  try {
@@ -38552,7 +38569,7 @@ class UsageError extends Refusal {
38552
38569
  function projectArgument(at) {
38553
38570
  const named = args.slice(at).find((value) => !value.startsWith("--"));
38554
38571
  const projectPath = resolve5(named ?? ".");
38555
- if (!existsSync11(join13(projectPath, "project.godot"))) {
38572
+ if (!existsSync12(join14(projectPath, "project.godot"))) {
38556
38573
  throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
38557
38574
  }
38558
38575
  return projectPath;
@@ -38696,7 +38713,7 @@ async function setup() {
38696
38713
  console.log("no harness configured; name one yourself, and gdharness harnesses lists them all");
38697
38714
  }
38698
38715
  if (!args.includes("--no-skill")) {
38699
- const directories = skillDirectories(chosen.harnesses, projectPath, existsSync11);
38716
+ const directories = skillDirectories(chosen.harnesses, projectPath, existsSync12);
38700
38717
  for (const written of writeSkill(directories, getLocalVersion())) {
38701
38718
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
38702
38719
  }
@@ -38781,7 +38798,7 @@ async function upgrade() {
38781
38798
  if (already.length === 0) {
38782
38799
  console.log("no harness config names gdharness, so none was re-pinned");
38783
38800
  }
38784
- for (const written of writeSkill(skillDirectories(already, projectPath, existsSync11), version)) {
38801
+ for (const written of writeSkill(skillDirectories(already, projectPath, existsSync12), version)) {
38785
38802
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
38786
38803
  }
38787
38804
  console.log(`
package/build/index.js CHANGED
@@ -9804,7 +9804,7 @@ var require_websocket_server = __commonJS(function(exports, module) {
9804
9804
 
9805
9805
  // src/issues.ts
9806
9806
  import { createHash } from "node:crypto";
9807
- import process2 from "node:process";
9807
+ import process3 from "node:process";
9808
9808
 
9809
9809
  // src/errors.ts
9810
9810
  class Refusal extends Error {
@@ -9834,8 +9834,9 @@ import { homedir, tmpdir } from "node:os";
9834
9834
  import { join } from "node:path";
9835
9835
 
9836
9836
  // src/runner.ts
9837
+ import process2 from "node:process";
9837
9838
  function currentRunner() {
9838
- const versions = process.versions;
9839
+ const versions = process2.versions;
9839
9840
  return versions["bun"] === undefined ? "npx" : "bunx";
9840
9841
  }
9841
9842
  function runLine(runner, version, rest = "") {
@@ -10038,9 +10039,9 @@ function addonMismatch(addonVersion, serverVersion) {
10038
10039
  var NEW_ISSUE = "https://github.com/Aureliolo/gdharness/issues/new";
10039
10040
  var ENHANCEMENT_URL = `${NEW_ISSUE}?template=feature_request.md`;
10040
10041
  function runtime() {
10041
- const versions = process2.versions;
10042
+ const versions = process3.versions;
10042
10043
  const bun = versions["bun"];
10043
- return bun === undefined ? `node ${process2.versions.node}` : `bun ${bun}`;
10044
+ return bun === undefined ? `node ${process3.versions.node}` : `bun ${bun}`;
10044
10045
  }
10045
10046
  function defectSignature(where, message) {
10046
10047
  const normalised = `${where}
@@ -10052,7 +10053,7 @@ function facts(where, message, godotVersion) {
10052
10053
  ["Where", where],
10053
10054
  ["Error", message],
10054
10055
  ["Version", `gdharness ${SERVER_VERSION}`],
10055
- ["Runtime", `${runtime()}, ${process2.platform} ${process2.arch}`],
10056
+ ["Runtime", `${runtime()}, ${process3.platform} ${process3.arch}`],
10056
10057
  ["Godot", godotVersion ?? "not known at the point this failed"],
10057
10058
  ["Signature", defectSignature(where, message)]
10058
10059
  ];
@@ -10062,7 +10063,7 @@ function filledTemplate(where, message, godotVersion) {
10062
10063
  `**gdharness version**: ${SERVER_VERSION}`,
10063
10064
  `**Godot version**: ${godotVersion ?? ""}`,
10064
10065
  `**Bun version**: ${runtime()}`,
10065
- `**OS**: ${process2.platform} ${process2.arch}`,
10066
+ `**OS**: ${process3.platform} ${process3.arch}`,
10066
10067
  "**MCP client**:",
10067
10068
  "",
10068
10069
  "## What you did",
@@ -24590,7 +24591,7 @@ var EMPTY_COMPLETION_RESULT = {
24590
24591
  };
24591
24592
 
24592
24593
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
24593
- import process3 from "node:process";
24594
+ import process4 from "node:process";
24594
24595
 
24595
24596
  // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
24596
24597
  var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
@@ -24634,7 +24635,7 @@ function serializeMessage(message) {
24634
24635
 
24635
24636
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
24636
24637
  class StdioServerTransport {
24637
- constructor(_stdin = process3.stdin, _stdout = process3.stdout, options) {
24638
+ constructor(_stdin = process4.stdin, _stdout = process4.stdout, options) {
24638
24639
  this._stdin = _stdin;
24639
24640
  this._stdout = _stdout;
24640
24641
  this._started = false;
@@ -26090,7 +26091,7 @@ async function runOperation(engine, operation, params, projectPath) {
26090
26091
 
26091
26092
  // src/issues.ts
26092
26093
  import { createHash as createHash2 } from "node:crypto";
26093
- import process4 from "node:process";
26094
+ import process5 from "node:process";
26094
26095
  var NEW_ISSUE2 = "https://github.com/Aureliolo/gdharness/issues/new";
26095
26096
  var ENHANCEMENT_URL2 = `${NEW_ISSUE2}?template=feature_request.md`;
26096
26097
  function feedbackNotice() {
@@ -26102,9 +26103,9 @@ function feedbackNotice() {
26102
26103
  }, null, 2);
26103
26104
  }
26104
26105
  function runtime2() {
26105
- const versions = process4.versions;
26106
+ const versions = process5.versions;
26106
26107
  const bun = versions["bun"];
26107
- return bun === undefined ? `node ${process4.versions.node}` : `bun ${bun}`;
26108
+ return bun === undefined ? `node ${process5.versions.node}` : `bun ${bun}`;
26108
26109
  }
26109
26110
  function defectSignature2(where, message) {
26110
26111
  const normalised = `${where}
@@ -26116,7 +26117,7 @@ function facts2(where, message, godotVersion) {
26116
26117
  ["Where", where],
26117
26118
  ["Error", message],
26118
26119
  ["Version", `gdharness ${SERVER_VERSION}`],
26119
- ["Runtime", `${runtime2()}, ${process4.platform} ${process4.arch}`],
26120
+ ["Runtime", `${runtime2()}, ${process5.platform} ${process5.arch}`],
26120
26121
  ["Godot", godotVersion ?? "not known at the point this failed"],
26121
26122
  ["Signature", defectSignature2(where, message)]
26122
26123
  ];
@@ -26126,7 +26127,7 @@ function filledTemplate2(where, message, godotVersion) {
26126
26127
  `**gdharness version**: ${SERVER_VERSION}`,
26127
26128
  `**Godot version**: ${godotVersion ?? ""}`,
26128
26129
  `**Bun version**: ${runtime2()}`,
26129
- `**OS**: ${process4.platform} ${process4.arch}`,
26130
+ `**OS**: ${process5.platform} ${process5.arch}`,
26130
26131
  "**MCP client**:",
26131
26132
  "",
26132
26133
  "## What you did",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "mcpName": "io.github.Aureliolo/gdharness",
5
5
  "description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
6
6
  "type": "module",