gdharness 0.12.10 → 0.12.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/cli.js CHANGED
@@ -15324,7 +15324,7 @@ var init_tool_definitions = __esm(() => {
15324
15324
  },
15325
15325
  {
15326
15326
  name: "project_search",
15327
- description: "Searches text or a regular expression across project files and returns file paths with line numbers.",
15327
+ description: "Searches text or a regular expression across project files and returns file paths with line numbers. What the engine steps over is not searched: directories spelled with a dot, node_modules, and any directory holding a .gdignore. A vendored engine or an export directory is therefore absent from the results rather than matching the code you are looking for in a copy nobody runs.",
15328
15328
  parameters: {
15329
15329
  projectPath: PROJECT_PATH,
15330
15330
  query: { type: "string", description: "The text or pattern to find." },
@@ -35786,13 +35786,22 @@ var init_lsp_client = __esm(() => {
35786
35786
  });
35787
35787
 
35788
35788
  // src/project-scan.ts
35789
- import { readdirSync as readdirSync4, readFileSync as readFileSync10 } from "node:fs";
35789
+ import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync10 } from "node:fs";
35790
35790
  import { join as join12 } from "node:path";
35791
+ function skipped(name) {
35792
+ return name.startsWith(".") || SKIPPED.has(name);
35793
+ }
35794
+ function steppedOver(directory) {
35795
+ return existsSync10(join12(directory, ".gdignore"));
35796
+ }
35791
35797
  function projectStructure(projectPath) {
35792
35798
  const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
35793
35799
  const visit = (directory) => {
35800
+ if (steppedOver(directory)) {
35801
+ return;
35802
+ }
35794
35803
  for (const entry of readdirSync4(directory, { withFileTypes: true })) {
35795
- if (entry.name.startsWith(".")) {
35804
+ if (skipped(entry.name)) {
35796
35805
  continue;
35797
35806
  }
35798
35807
  if (entry.isDirectory()) {
@@ -35831,11 +35840,14 @@ function searchProject(projectPath, options) {
35831
35840
  return false;
35832
35841
  };
35833
35842
  const visit = (directory) => {
35843
+ if (steppedOver(directory)) {
35844
+ return;
35845
+ }
35834
35846
  for (const entry of readdirSync4(directory, { withFileTypes: true })) {
35835
35847
  if (full()) {
35836
35848
  return;
35837
35849
  }
35838
- if (SKIPPED.has(entry.name)) {
35850
+ if (skipped(entry.name)) {
35839
35851
  continue;
35840
35852
  }
35841
35853
  const entryPath = join12(directory, entry.name);
@@ -35872,12 +35884,12 @@ function searchProject(projectPath, options) {
35872
35884
  }
35873
35885
  var SKIPPED, ASSET_EXTENSIONS;
35874
35886
  var init_project_scan = __esm(() => {
35875
- SKIPPED = new Set([".git", ".godot", ".import", "node_modules"]);
35887
+ SKIPPED = new Set(["node_modules"]);
35876
35888
  ASSET_EXTENSIONS = new Set(["png", "jpg", "jpeg", "webp", "svg", "ttf", "otf", "wav", "mp3", "ogg"]);
35877
35889
  });
35878
35890
 
35879
35891
  // src/runtime-client.ts
35880
- import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync11, unlinkSync } from "node:fs";
35892
+ import { existsSync as existsSync11, readdirSync as readdirSync5, readFileSync as readFileSync11, unlinkSync } from "node:fs";
35881
35893
  import { createConnection as createConnection3 } from "node:net";
35882
35894
  import { tmpdir as tmpdir4 } from "node:os";
35883
35895
  import { join as join13, resolve as resolve4 } from "node:path";
@@ -35948,7 +35960,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
35948
35960
  return runtimesAnnounced(directories).running;
35949
35961
  }
35950
35962
  function announcedIn(directory) {
35951
- if (!existsSync10(directory)) {
35963
+ if (!existsSync11(directory)) {
35952
35964
  return [];
35953
35965
  }
35954
35966
  const found = [];
@@ -36285,11 +36297,11 @@ var init_run_record = __esm(() => {
36285
36297
  });
36286
36298
 
36287
36299
  // src/setup.ts
36288
- import { cpSync as cpSync2, existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync13, rmSync as rmSync8, writeFileSync as writeFileSync9 } from "node:fs";
36300
+ import { cpSync as cpSync2, existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync13, rmSync as rmSync8, writeFileSync as writeFileSync9 } from "node:fs";
36289
36301
  import { dirname as dirname8, join as join15 } from "node:path";
36290
36302
  function installedAddonVersion(projectPath) {
36291
36303
  const marker = join15(projectPath, "addons", ADDONS2[0], VERSION_MARKER2);
36292
- if (!existsSync11(marker)) {
36304
+ if (!existsSync12(marker)) {
36293
36305
  return null;
36294
36306
  }
36295
36307
  const said = readFileSync13(marker, "utf8").trim();
@@ -36312,7 +36324,7 @@ var init_setup = __esm(() => {
36312
36324
  import { execFile as execFile5, spawn } from "node:child_process";
36313
36325
  import {
36314
36326
  closeSync,
36315
- existsSync as existsSync12,
36327
+ existsSync as existsSync13,
36316
36328
  fstatSync,
36317
36329
  mkdirSync as mkdirSync8,
36318
36330
  mkdtempSync as mkdtempSync3,
@@ -36460,7 +36472,7 @@ function aboveTheRunner(entry) {
36460
36472
  }
36461
36473
  function elsewhereIn(projectPath, asked) {
36462
36474
  const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
36463
- if (wanted === "" || existsSync12(join16(projectPath, wanted))) {
36475
+ if (wanted === "" || existsSync13(join16(projectPath, wanted))) {
36464
36476
  return "";
36465
36477
  }
36466
36478
  const root = (wanted.split("/")[0] ?? "").toLowerCase();
@@ -37077,7 +37089,7 @@ class GodotServer {
37077
37089
  return { ok: false, response: this.createErrorResponse("projectPath is required.") };
37078
37090
  }
37079
37091
  const file = join16(path, "project.godot");
37080
- if (!existsSync12(file)) {
37092
+ if (!existsSync13(file)) {
37081
37093
  return {
37082
37094
  ok: false,
37083
37095
  response: this.createErrorResponse(`Not a Godot project: ${path}`, [
@@ -37341,7 +37353,7 @@ class GodotServer {
37341
37353
  log.finish();
37342
37354
  const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
37343
37355
  const verdict = {
37344
- exported: exitCode === 0 && log.count("error") === 0 && existsSync12(output.absolutePath),
37356
+ exported: exitCode === 0 && log.count("error") === 0 && existsSync13(output.absolutePath),
37345
37357
  preset,
37346
37358
  outputPath: output.relativePath,
37347
37359
  debug,
@@ -37371,7 +37383,7 @@ class GodotServer {
37371
37383
  return contained.response;
37372
37384
  }
37373
37385
  const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
37374
- if (!existsSync12(join16(project.value.path, runner))) {
37386
+ if (!existsSync13(join16(project.value.path, runner))) {
37375
37387
  return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
37376
37388
  "Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
37377
37389
  ]);
@@ -37425,7 +37437,7 @@ class GodotServer {
37425
37437
  let report = null;
37426
37438
  let reportProblem = null;
37427
37439
  try {
37428
- const written = existsSync12(reportsDir) ? readdirSync7(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
37440
+ const written = existsSync13(reportsDir) ? readdirSync7(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
37429
37441
  const newest = written.at(-1);
37430
37442
  if (newest !== undefined) {
37431
37443
  report = parseJUnit(readFileSync14(join16(reportsDir, newest, "results.xml"), "utf8"));
@@ -37845,7 +37857,7 @@ class GodotServer {
37845
37857
  return runIsUp(run, editorSays);
37846
37858
  }
37847
37859
  async runtimeUp(projectPath, before, budgetMs) {
37848
- if (!existsSync12(join16(projectPath, RUNTIME_AUTOLOAD2.path))) {
37860
+ if (!existsSync13(join16(projectPath, RUNTIME_AUTOLOAD2.path))) {
37849
37861
  return runtimeVerdict(null, { addon: false, budgetMs, heldAt: null, running: false });
37850
37862
  }
37851
37863
  const endpoint = await announcedSince(projectPath, before, {
@@ -38475,7 +38487,7 @@ var init_server3 = __esm(() => {
38475
38487
  });
38476
38488
 
38477
38489
  // src/cli.ts
38478
- import { existsSync as existsSync13 } from "fs";
38490
+ import { existsSync as existsSync14 } from "fs";
38479
38491
  import { join as join17, resolve as resolve5 } from "path";
38480
38492
 
38481
38493
  // src/errors.ts
@@ -39891,6 +39903,11 @@ formatting. \`script_diagnostics\` and \`script_info\` come from the editor's ow
39891
39903
  \`editor_classes\` need nothing open: they run a short headless engine and are gone before the
39892
39904
  answer is printed.
39893
39905
 
39906
+ Editing a file while a game is running does not change the running game. \`auto_reload\` is an
39907
+ editor plugin and reloads into the editor's own process; the game is a separate process holding
39908
+ its own copy. So a long run is not a reason to stop editing, and the new code arrives on the next
39909
+ \`editor_run start\`.
39910
+
39894
39911
  A wall of "Could not find type" on the project's own classes means the editor is not holding
39895
39912
  them. \`editor_rescan\` asks it to scan and names any class it still cannot resolve under
39896
39913
  \`unseenByEditor\`: its walk skips a file a headless engine has already imported, so the
@@ -40018,7 +40035,7 @@ class UsageError extends Refusal {
40018
40035
  function projectArgument(at) {
40019
40036
  const named = args.slice(at).find((value) => !value.startsWith("--"));
40020
40037
  const projectPath = resolve5(named ?? ".");
40021
- if (!existsSync13(join17(projectPath, "project.godot"))) {
40038
+ if (!existsSync14(join17(projectPath, "project.godot"))) {
40022
40039
  throw new UsageError(`Not a Godot project: ${projectPath} holds no project.godot.`);
40023
40040
  }
40024
40041
  return projectPath;
@@ -40052,7 +40069,7 @@ async function registerRuntime(godot, projectPath) {
40052
40069
  return;
40053
40070
  }
40054
40071
  console.log(`${RUNTIME_AUTOLOAD.name} autoload left at ${named}, which this project registers itself`);
40055
- if (!existsSync13(join17(projectPath, (named ?? "").replace(/^res:\/\//, "")))) {
40072
+ if (!existsSync14(join17(projectPath, (named ?? "").replace(/^res:\/\//, "")))) {
40056
40073
  console.log(` that file is not in this project, so it boots with a missing script: restore it, or point the entry at res://${RUNTIME_AUTOLOAD.path}`);
40057
40074
  }
40058
40075
  }
@@ -40184,7 +40201,7 @@ async function setup() {
40184
40201
  console.log("no harness configured; name one yourself, and gdharness harnesses lists them all");
40185
40202
  }
40186
40203
  if (!args.includes("--no-skill")) {
40187
- const directories = skillDirectories(chosen.harnesses, projectPath, existsSync13);
40204
+ const directories = skillDirectories(chosen.harnesses, projectPath, existsSync14);
40188
40205
  for (const written of writeSkill(directories, getLocalVersion())) {
40189
40206
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
40190
40207
  }
@@ -40273,7 +40290,7 @@ async function upgrade() {
40273
40290
  if (already.length === 0) {
40274
40291
  console.log("no harness config names gdharness, so none was re-pinned");
40275
40292
  }
40276
- for (const written of writeSkill(skillDirectories(already, projectPath, existsSync13), version)) {
40293
+ for (const written of writeSkill(skillDirectories(already, projectPath, existsSync14), version)) {
40277
40294
  console.log(`skill: ${written.replaced ? "replaced" : "written"} ${written.path}`);
40278
40295
  }
40279
40296
  console.log(`
package/build/index.js CHANGED
@@ -10134,7 +10134,7 @@ function defectReport(where, error, godotVersion) {
10134
10134
  import { execFile as execFile3, spawn } from "node:child_process";
10135
10135
  import {
10136
10136
  closeSync,
10137
- existsSync as existsSync7,
10137
+ existsSync as existsSync8,
10138
10138
  fstatSync,
10139
10139
  mkdirSync as mkdirSync5,
10140
10140
  mkdtempSync as mkdtempSync2,
@@ -27196,15 +27196,24 @@ async function handleLSPTool(client, toolName, args) {
27196
27196
  }
27197
27197
 
27198
27198
  // src/project-scan.ts
27199
- import { readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
27199
+ import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
27200
27200
  import { join as join6 } from "node:path";
27201
- var SKIPPED = new Set([".git", ".godot", ".import", "node_modules"]);
27201
+ var SKIPPED = new Set(["node_modules"]);
27202
+ function skipped(name) {
27203
+ return name.startsWith(".") || SKIPPED.has(name);
27204
+ }
27205
+ function steppedOver(directory) {
27206
+ return existsSync5(join6(directory, ".gdignore"));
27207
+ }
27202
27208
  var ASSET_EXTENSIONS = new Set(["png", "jpg", "jpeg", "webp", "svg", "ttf", "otf", "wav", "mp3", "ogg"]);
27203
27209
  function projectStructure(projectPath) {
27204
27210
  const structure = { scenes: 0, scripts: 0, assets: 0, other: 0 };
27205
27211
  const visit = (directory) => {
27212
+ if (steppedOver(directory)) {
27213
+ return;
27214
+ }
27206
27215
  for (const entry of readdirSync3(directory, { withFileTypes: true })) {
27207
- if (entry.name.startsWith(".")) {
27216
+ if (skipped(entry.name)) {
27208
27217
  continue;
27209
27218
  }
27210
27219
  if (entry.isDirectory()) {
@@ -27243,11 +27252,14 @@ function searchProject(projectPath, options) {
27243
27252
  return false;
27244
27253
  };
27245
27254
  const visit = (directory) => {
27255
+ if (steppedOver(directory)) {
27256
+ return;
27257
+ }
27246
27258
  for (const entry of readdirSync3(directory, { withFileTypes: true })) {
27247
27259
  if (full()) {
27248
27260
  return;
27249
27261
  }
27250
- if (SKIPPED.has(entry.name)) {
27262
+ if (skipped(entry.name)) {
27251
27263
  continue;
27252
27264
  }
27253
27265
  const entryPath = join6(directory, entry.name);
@@ -27506,7 +27518,7 @@ import { mkdirSync as mkdirSync3, openSync, readdirSync as readdirSync5, readFil
27506
27518
  import { basename, join as join8 } from "node:path";
27507
27519
 
27508
27520
  // src/runtime-client.ts
27509
- import { existsSync as existsSync5, readdirSync as readdirSync4, readFileSync as readFileSync7, unlinkSync } from "node:fs";
27521
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync7, unlinkSync } from "node:fs";
27510
27522
  import { createConnection as createConnection3 } from "node:net";
27511
27523
  import { tmpdir as tmpdir3 } from "node:os";
27512
27524
  import { join as join7, resolve as resolve4 } from "node:path";
@@ -27632,7 +27644,7 @@ function discoverRuntimes(directories = runtimeDirectories()) {
27632
27644
  return runtimesAnnounced(directories).running;
27633
27645
  }
27634
27646
  function announcedIn(directory) {
27635
- if (!existsSync5(directory)) {
27647
+ if (!existsSync6(directory)) {
27636
27648
  return [];
27637
27649
  }
27638
27650
  const found = [];
@@ -27962,7 +27974,7 @@ function sweepTranscripts(keepMs = 24 * 60 * 60 * 1000, now = Date.now()) {
27962
27974
  }
27963
27975
 
27964
27976
  // src/setup.ts
27965
- import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync9, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "node:fs";
27977
+ import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync9, rmSync as rmSync4, writeFileSync as writeFileSync5 } from "node:fs";
27966
27978
  import { dirname as dirname3, join as join9 } from "node:path";
27967
27979
  var ADDONS = ["gdharness_editor", "gdharness_runtime", "auto_reload"];
27968
27980
  var RUNTIME_AUTOLOAD = {
@@ -27972,7 +27984,7 @@ var RUNTIME_AUTOLOAD = {
27972
27984
  var VERSION_MARKER = ".gdharness-version";
27973
27985
  function installedAddonVersion(projectPath) {
27974
27986
  const marker = join9(projectPath, "addons", ADDONS[0], VERSION_MARKER);
27975
- if (!existsSync6(marker)) {
27987
+ if (!existsSync7(marker)) {
27976
27988
  return null;
27977
27989
  }
27978
27990
  const said = readFileSync9(marker, "utf8").trim();
@@ -28199,7 +28211,7 @@ var TOOL_SPECS = [
28199
28211
  },
28200
28212
  {
28201
28213
  name: "project_search",
28202
- description: "Searches text or a regular expression across project files and returns file paths with line numbers.",
28214
+ description: "Searches text or a regular expression across project files and returns file paths with line numbers. What the engine steps over is not searched: directories spelled with a dot, node_modules, and any directory holding a .gdignore. A vendored engine or an export directory is therefore absent from the results rather than matching the code you are looking for in a copy nobody runs.",
28203
28215
  parameters: {
28204
28216
  projectPath: PROJECT_PATH,
28205
28217
  query: { type: "string", description: "The text or pattern to find." },
@@ -29242,7 +29254,7 @@ function aboveTheRunner(entry) {
29242
29254
  }
29243
29255
  function elsewhereIn(projectPath, asked) {
29244
29256
  const wanted = asked.replace(/^res:\/\//, "").replace(/\/+$/, "");
29245
- if (wanted === "" || existsSync7(join10(projectPath, wanted))) {
29257
+ if (wanted === "" || existsSync8(join10(projectPath, wanted))) {
29246
29258
  return "";
29247
29259
  }
29248
29260
  const root = (wanted.split("/")[0] ?? "").toLowerCase();
@@ -29859,7 +29871,7 @@ class GodotServer {
29859
29871
  return { ok: false, response: this.createErrorResponse("projectPath is required.") };
29860
29872
  }
29861
29873
  const file = join10(path, "project.godot");
29862
- if (!existsSync7(file)) {
29874
+ if (!existsSync8(file)) {
29863
29875
  return {
29864
29876
  ok: false,
29865
29877
  response: this.createErrorResponse(`Not a Godot project: ${path}`, [
@@ -30123,7 +30135,7 @@ class GodotServer {
30123
30135
  log.finish();
30124
30136
  const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
30125
30137
  const verdict = {
30126
- exported: exitCode === 0 && log.count("error") === 0 && existsSync7(output.absolutePath),
30138
+ exported: exitCode === 0 && log.count("error") === 0 && existsSync8(output.absolutePath),
30127
30139
  preset,
30128
30140
  outputPath: output.relativePath,
30129
30141
  debug,
@@ -30153,7 +30165,7 @@ class GodotServer {
30153
30165
  return contained.response;
30154
30166
  }
30155
30167
  const runner = "addons/gdUnit4/bin/GdUnitCmdTool.gd";
30156
- if (!existsSync7(join10(project.value.path, runner))) {
30168
+ if (!existsSync8(join10(project.value.path, runner))) {
30157
30169
  return this.createErrorResponse(`gdUnit4 is not installed in this project: no ${runner}.`, [
30158
30170
  "Install gdUnit4 under addons/gdUnit4, from https://github.com/godot-gdunit-labs/gdUnit4"
30159
30171
  ]);
@@ -30207,7 +30219,7 @@ class GodotServer {
30207
30219
  let report = null;
30208
30220
  let reportProblem = null;
30209
30221
  try {
30210
- const written = existsSync7(reportsDir) ? readdirSync6(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
30222
+ const written = existsSync8(reportsDir) ? readdirSync6(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
30211
30223
  const newest = written.at(-1);
30212
30224
  if (newest !== undefined) {
30213
30225
  report = parseJUnit(readFileSync10(join10(reportsDir, newest, "results.xml"), "utf8"));
@@ -30627,7 +30639,7 @@ class GodotServer {
30627
30639
  return runIsUp(run, editorSays);
30628
30640
  }
30629
30641
  async runtimeUp(projectPath, before, budgetMs) {
30630
- if (!existsSync7(join10(projectPath, RUNTIME_AUTOLOAD.path))) {
30642
+ if (!existsSync8(join10(projectPath, RUNTIME_AUTOLOAD.path))) {
30631
30643
  return runtimeVerdict(null, { addon: false, budgetMs, heldAt: null, running: false });
30632
30644
  }
30633
30645
  const endpoint = await announcedSince(projectPath, before, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "0.12.10",
3
+ "version": "0.12.11",
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",