gdharness 0.12.14 → 0.12.16

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
@@ -15759,7 +15759,7 @@ var init_tool_definitions = __esm(() => {
15759
15759
  },
15760
15760
  {
15761
15761
  name: "editor_status",
15762
- description: 'Whether the editor addon is connected, which Godot answers, whether the editor is playing something, and whether a game with the runtime addon is reachable. When connected is false, mayYetConnect says whether that is final: the editor dials this server rather than the other way round and backs off between tries, so for the first half-minute after a server starts, false means "not reached yet" as often as it means "no editor". True is worth waiting out; false is an editor that is not there.',
15762
+ description: 'Whether the editor addon is connected, which Godot answers, whether the editor is playing something, and whether a game with the runtime addon is reachable. When connected is false, mayYetConnect says whether that is final: the editor dials this server rather than the other way round and backs off between tries, so for the first half-minute after a server starts, false means "not reached yet" as often as it means "no editor". True is worth waiting out; false is an editor that is not there. listeningSince is when this server took the bridge port, which is what that window is measured from and what a caller wanting its own window should read.',
15763
15763
  parameters: {},
15764
15764
  requires: []
15765
15765
  },
@@ -34406,7 +34406,7 @@ function servedPort(said) {
34406
34406
  return typeof said === "number" && Number.isInteger(said) && said > 0 && said <= 65535 ? said : undefined;
34407
34407
  }
34408
34408
  function mayYetConnect(listeningSince, now = Date.now()) {
34409
- return listeningSince === undefined || now - listeningSince < CONNECT_WINDOW_MS;
34409
+ return listeningSince === undefined || now - listeningSince.getTime() < CONNECT_WINDOW_MS;
34410
34410
  }
34411
34411
  function getDefaultBridge(ownProject = null) {
34412
34412
  defaultBridge ??= new GodotBridge(resolveDefaultBridgePort(), resolveDefaultBridgeHost(), DEFAULT_TIMEOUT_MS, ownProject);
@@ -34482,7 +34482,7 @@ var init_godot_bridge = __esm(() => {
34482
34482
  });
34483
34483
  server.once("listening", () => {
34484
34484
  settled = true;
34485
- this.listeningSince = Date.now();
34485
+ this.listeningSince = new Date;
34486
34486
  this.httpServer = server;
34487
34487
  this.godotWss = godotWss;
34488
34488
  const bound = server.address();
@@ -36159,6 +36159,16 @@ function writeRunRecord(record) {
36159
36159
  mkdirSync6(runsDirectory(), { recursive: true });
36160
36160
  writeFileSync8(recordPath(), JSON.stringify(record, null, 2), "utf8");
36161
36161
  }
36162
+ function recordRunEnded(pid, exitCode) {
36163
+ const path = recordPath();
36164
+ const record = recordAt(path);
36165
+ if (record === null || record.pid !== pid) {
36166
+ return;
36167
+ }
36168
+ try {
36169
+ writeFileSync8(path, JSON.stringify({ ...record, exitCode }, null, 2), "utf8");
36170
+ } catch {}
36171
+ }
36162
36172
  function readRunRecord() {
36163
36173
  for (const path of recordPaths()) {
36164
36174
  const record = recordAt(path);
@@ -36192,7 +36202,8 @@ function recordAt(path) {
36192
36202
  startedAt,
36193
36203
  projectPath: typeof fields["projectPath"] === "string" ? fields["projectPath"] : "",
36194
36204
  arguments: Array.isArray(args) ? args.filter((value) => typeof value === "string") : [],
36195
- ...typeof fields["command"] === "string" ? { command: fields["command"] } : {}
36205
+ ...typeof fields["command"] === "string" ? { command: fields["command"] } : {},
36206
+ ...typeof fields["exitCode"] === "number" ? { exitCode: fields["exitCode"] } : {}
36196
36207
  };
36197
36208
  }
36198
36209
  function runningAs(pid) {
@@ -37343,8 +37354,11 @@ class GodotServer {
37343
37354
  return this.createErrorResponse(`Cannot create ${dirname9(output.relativePath)} to export into: ${errorMessage(error)}`);
37344
37355
  }
37345
37356
  const debug = readBoolean(args, "debug") ?? false;
37357
+ const exportLogs = mkdtempSync3(join16(tmpdir5(), "gdharness-export-"));
37346
37358
  const exportArgs = [
37347
37359
  "--headless",
37360
+ "--log-file",
37361
+ join16(exportLogs, "engine.log"),
37348
37362
  "--path",
37349
37363
  project.value.path,
37350
37364
  debug ? "--export-debug" : "--export-release",
@@ -37366,6 +37380,8 @@ class GodotServer {
37366
37380
  log.append("stdout", failed.stdout);
37367
37381
  log.append("stderr", failed.stderr);
37368
37382
  exitCode = typeof failed.code === "number" ? failed.code : -1;
37383
+ } finally {
37384
+ rmSync9(exportLogs, { recursive: true, force: true });
37369
37385
  }
37370
37386
  log.finish();
37371
37387
  const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
@@ -38001,6 +38017,9 @@ class GodotServer {
38001
38017
  this.logDebug(`Godot process exited with code ${code ?? "none"}`);
38002
38018
  log.finish();
38003
38019
  started.exitCode = code ?? -1;
38020
+ if (started.pid !== null) {
38021
+ recordRunEnded(started.pid, started.exitCode);
38022
+ }
38004
38023
  });
38005
38024
  child.on("error", (err) => {
38006
38025
  console.error("Failed to start Godot process:", err);
@@ -38105,8 +38124,8 @@ class GodotServer {
38105
38124
  this.drainTranscript(adopted);
38106
38125
  if (!alive(record.pid) || !couldStillBeTheRecordedRun(record)) {
38107
38126
  adopted.log.finish();
38108
- adopted.exitCode = null;
38109
- adopted.endedUnwatched = true;
38127
+ adopted.exitCode = record.exitCode ?? null;
38128
+ adopted.endedUnwatched = record.exitCode === undefined;
38110
38129
  }
38111
38130
  this.activeProcess = adopted;
38112
38131
  return adopted;
package/build/index.js CHANGED
@@ -25613,7 +25613,7 @@ function servedPort(said) {
25613
25613
  }
25614
25614
  var CONNECT_WINDOW_MS = 35000;
25615
25615
  function mayYetConnect(listeningSince, now = Date.now()) {
25616
- return listeningSince === undefined || now - listeningSince < CONNECT_WINDOW_MS;
25616
+ return listeningSince === undefined || now - listeningSince.getTime() < CONNECT_WINDOW_MS;
25617
25617
  }
25618
25618
 
25619
25619
  class GodotBridge extends EventEmitter {
@@ -25680,7 +25680,7 @@ class GodotBridge extends EventEmitter {
25680
25680
  });
25681
25681
  server.once("listening", () => {
25682
25682
  settled = true;
25683
- this.listeningSince = Date.now();
25683
+ this.listeningSince = new Date;
25684
25684
  this.httpServer = server;
25685
25685
  this.godotWss = godotWss;
25686
25686
  const bound = server.address();
@@ -27841,6 +27841,16 @@ function writeRunRecord(record) {
27841
27841
  mkdirSync3(runsDirectory(), { recursive: true });
27842
27842
  writeFileSync4(recordPath(), JSON.stringify(record, null, 2), "utf8");
27843
27843
  }
27844
+ function recordRunEnded(pid, exitCode) {
27845
+ const path = recordPath();
27846
+ const record = recordAt(path);
27847
+ if (record === null || record.pid !== pid) {
27848
+ return;
27849
+ }
27850
+ try {
27851
+ writeFileSync4(path, JSON.stringify({ ...record, exitCode }, null, 2), "utf8");
27852
+ } catch {}
27853
+ }
27844
27854
  function readRunRecord() {
27845
27855
  for (const path of recordPaths()) {
27846
27856
  const record = recordAt(path);
@@ -27874,7 +27884,8 @@ function recordAt(path) {
27874
27884
  startedAt,
27875
27885
  projectPath: typeof fields["projectPath"] === "string" ? fields["projectPath"] : "",
27876
27886
  arguments: Array.isArray(args) ? args.filter((value) => typeof value === "string") : [],
27877
- ...typeof fields["command"] === "string" ? { command: fields["command"] } : {}
27887
+ ...typeof fields["command"] === "string" ? { command: fields["command"] } : {},
27888
+ ...typeof fields["exitCode"] === "number" ? { exitCode: fields["exitCode"] } : {}
27878
27889
  };
27879
27890
  }
27880
27891
  function runningAs(pid) {
@@ -28662,7 +28673,7 @@ var TOOL_SPECS = [
28662
28673
  },
28663
28674
  {
28664
28675
  name: "editor_status",
28665
- description: 'Whether the editor addon is connected, which Godot answers, whether the editor is playing something, and whether a game with the runtime addon is reachable. When connected is false, mayYetConnect says whether that is final: the editor dials this server rather than the other way round and backs off between tries, so for the first half-minute after a server starts, false means "not reached yet" as often as it means "no editor". True is worth waiting out; false is an editor that is not there.',
28676
+ description: 'Whether the editor addon is connected, which Godot answers, whether the editor is playing something, and whether a game with the runtime addon is reachable. When connected is false, mayYetConnect says whether that is final: the editor dials this server rather than the other way round and backs off between tries, so for the first half-minute after a server starts, false means "not reached yet" as often as it means "no editor". True is worth waiting out; false is an editor that is not there. listeningSince is when this server took the bridge port, which is what that window is measured from and what a caller wanting its own window should read.',
28666
28677
  parameters: {},
28667
28678
  requires: []
28668
28679
  },
@@ -30126,8 +30137,11 @@ class GodotServer {
30126
30137
  return this.createErrorResponse(`Cannot create ${dirname4(output.relativePath)} to export into: ${errorMessage(error)}`);
30127
30138
  }
30128
30139
  const debug = readBoolean(args, "debug") ?? false;
30140
+ const exportLogs = mkdtempSync2(join10(tmpdir4(), "gdharness-export-"));
30129
30141
  const exportArgs = [
30130
30142
  "--headless",
30143
+ "--log-file",
30144
+ join10(exportLogs, "engine.log"),
30131
30145
  "--path",
30132
30146
  project.value.path,
30133
30147
  debug ? "--export-debug" : "--export-release",
@@ -30149,6 +30163,8 @@ class GodotServer {
30149
30163
  log.append("stdout", failed.stdout);
30150
30164
  log.append("stderr", failed.stderr);
30151
30165
  exitCode = typeof failed.code === "number" ? failed.code : -1;
30166
+ } finally {
30167
+ rmSync5(exportLogs, { recursive: true, force: true });
30152
30168
  }
30153
30169
  log.finish();
30154
30170
  const problems = log.select({ severity: "warning", sinceLastCall: false, limit: 200 });
@@ -30784,6 +30800,9 @@ class GodotServer {
30784
30800
  this.logDebug(`Godot process exited with code ${code ?? "none"}`);
30785
30801
  log.finish();
30786
30802
  started.exitCode = code ?? -1;
30803
+ if (started.pid !== null) {
30804
+ recordRunEnded(started.pid, started.exitCode);
30805
+ }
30787
30806
  });
30788
30807
  child.on("error", (err) => {
30789
30808
  console.error("Failed to start Godot process:", err);
@@ -30888,8 +30907,8 @@ class GodotServer {
30888
30907
  this.drainTranscript(adopted);
30889
30908
  if (!alive(record.pid) || !couldStillBeTheRecordedRun(record)) {
30890
30909
  adopted.log.finish();
30891
- adopted.exitCode = null;
30892
- adopted.endedUnwatched = true;
30910
+ adopted.exitCode = record.exitCode ?? null;
30911
+ adopted.endedUnwatched = record.exitCode === undefined;
30893
30912
  }
30894
30913
  this.activeProcess = adopted;
30895
30914
  return adopted;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "0.12.14",
3
+ "version": "0.12.16",
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",