gdharness 0.13.6 → 0.13.7

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
@@ -26630,13 +26630,14 @@ var require_fast_uri = __commonJS(function(exports, module) {
26630
26630
  if (!malformedIPLiteral) {
26631
26631
  malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
26632
26632
  }
26633
- if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
26634
- if (uri.indexOf("%") !== -1) {
26635
- if (parsed.host !== undefined && !malformedIPLiteral) {
26636
- const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
26637
- parsed.host = reescapeHostDelimiters(host, isIP);
26638
- }
26633
+ if (uri.indexOf("%") !== -1 && parsed.host !== undefined && !malformedIPLiteral) {
26634
+ let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
26635
+ if (!isIP) {
26636
+ host = normalizePercentEncoding(host.toLowerCase());
26639
26637
  }
26638
+ parsed.host = reescapeHostDelimiters(host, isIP);
26639
+ }
26640
+ if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
26640
26641
  if (parsed.path) {
26641
26642
  parsed.path = normalizePathEncoding(parsed.path);
26642
26643
  }
@@ -37887,6 +37888,7 @@ class GodotServer {
37887
37888
  };
37888
37889
  }));
37889
37890
  const playing = await this.editorPlayingState();
37891
+ await this.pickUpWhatTheEditorIsPlaying();
37890
37892
  return this.jsonTextResponse({
37891
37893
  editor: {
37892
37894
  ...this.getEditorStatusPayload(),
@@ -38322,6 +38324,33 @@ class GodotServer {
38322
38324
  closeSync(handle);
38323
38325
  }
38324
38326
  }
38327
+ async pickUpWhatTheEditorIsPlaying() {
38328
+ if (this.activeProcess !== null || !this.godotBridge.isConnected()) {
38329
+ return;
38330
+ }
38331
+ const playing = await this.editorPlayingState();
38332
+ if (playing?.playing !== true) {
38333
+ return;
38334
+ }
38335
+ try {
38336
+ await this.dap().connect();
38337
+ } catch (error) {
38338
+ this.logDebug(`Picked up an editor-played run without its adapter: ${errorMessage(error)}`);
38339
+ }
38340
+ this.activeProcess = {
38341
+ process: null,
38342
+ pid: null,
38343
+ log: new GameLog,
38344
+ transcript: null,
38345
+ readOffset: 0,
38346
+ projectPath: this.godotBridge.getStatus().projectPath ?? null,
38347
+ startedAt: Date.now(),
38348
+ exitCode: null,
38349
+ throughEditor: true,
38350
+ brokeOn: null,
38351
+ pickedUpPlaying: true
38352
+ };
38353
+ }
38325
38354
  adoptRecordedRun() {
38326
38355
  const record = readRunRecord();
38327
38356
  if (record === null || !this.couldBeOurs(record.projectPath)) {
@@ -38403,6 +38432,7 @@ class GodotServer {
38403
38432
  });
38404
38433
  }
38405
38434
  async handleWaitForRun(args) {
38435
+ await this.pickUpWhatTheEditorIsPlaying();
38406
38436
  const run = this.currentRun();
38407
38437
  if (!run) {
38408
38438
  return this.createErrorResponse(this.nothingOfOursIsRunning());
@@ -38417,6 +38447,7 @@ class GodotServer {
38417
38447
  return await this.handleGetDebugOutput(args, stillRunning(run) ? budgetMs : undefined);
38418
38448
  }
38419
38449
  async handleGetDebugOutput(args, waitedMs) {
38450
+ await this.pickUpWhatTheEditorIsPlaying();
38420
38451
  const run = this.currentRun();
38421
38452
  if (!run) {
38422
38453
  return this.createErrorResponse(this.nothingOfOursIsRunning());
@@ -38444,6 +38475,9 @@ class GodotServer {
38444
38475
  if (run.endedUnwatched === true) {
38445
38476
  notes.push("This run outlived the server that started it and is over now, so its exit code was never collected. Everything it printed is below, read back from its transcript.");
38446
38477
  }
38478
+ if (run.pickedUpPlaying === true) {
38479
+ notes.push("The editor was already playing this when this server reached it, so this is not the run from its start: what it printed before that went with the server that was listening then. It is the run the editor is holding now, which is the one the debug_* tools answer for.");
38480
+ }
38447
38481
  if (typeof run.endedHere === "string") {
38448
38482
  notes.push(`This run was ended here, by ${run.endedHere}.`);
38449
38483
  } else if (!stillRunning(run) && !run.throughEditor && run.exitCode !== null) {
@@ -38474,6 +38508,7 @@ class GodotServer {
38474
38508
  });
38475
38509
  }
38476
38510
  async handleStopProject() {
38511
+ await this.pickUpWhatTheEditorIsPlaying();
38477
38512
  const stopped = this.currentRun();
38478
38513
  if (!stopped) {
38479
38514
  return this.createErrorResponse(this.nothingOfOursIsRunning());
package/build/index.js CHANGED
@@ -4060,13 +4060,14 @@ var require_fast_uri = __commonJS(function(exports, module) {
4060
4060
  if (!malformedIPLiteral) {
4061
4061
  malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4062
4062
  }
4063
- if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4064
- if (uri.indexOf("%") !== -1) {
4065
- if (parsed.host !== undefined && !malformedIPLiteral) {
4066
- const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4067
- parsed.host = reescapeHostDelimiters(host, isIP);
4068
- }
4063
+ if (uri.indexOf("%") !== -1 && parsed.host !== undefined && !malformedIPLiteral) {
4064
+ let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4065
+ if (!isIP) {
4066
+ host = normalizePercentEncoding(host.toLowerCase());
4069
4067
  }
4068
+ parsed.host = reescapeHostDelimiters(host, isIP);
4069
+ }
4070
+ if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4070
4071
  if (parsed.path) {
4071
4072
  parsed.path = normalizePathEncoding(parsed.path);
4072
4073
  }
@@ -30641,6 +30642,7 @@ class GodotServer {
30641
30642
  };
30642
30643
  }));
30643
30644
  const playing = await this.editorPlayingState();
30645
+ await this.pickUpWhatTheEditorIsPlaying();
30644
30646
  return this.jsonTextResponse({
30645
30647
  editor: {
30646
30648
  ...this.getEditorStatusPayload(),
@@ -31076,6 +31078,33 @@ class GodotServer {
31076
31078
  closeSync(handle);
31077
31079
  }
31078
31080
  }
31081
+ async pickUpWhatTheEditorIsPlaying() {
31082
+ if (this.activeProcess !== null || !this.godotBridge.isConnected()) {
31083
+ return;
31084
+ }
31085
+ const playing = await this.editorPlayingState();
31086
+ if (playing?.playing !== true) {
31087
+ return;
31088
+ }
31089
+ try {
31090
+ await this.dap().connect();
31091
+ } catch (error) {
31092
+ this.logDebug(`Picked up an editor-played run without its adapter: ${errorMessage(error)}`);
31093
+ }
31094
+ this.activeProcess = {
31095
+ process: null,
31096
+ pid: null,
31097
+ log: new GameLog,
31098
+ transcript: null,
31099
+ readOffset: 0,
31100
+ projectPath: this.godotBridge.getStatus().projectPath ?? null,
31101
+ startedAt: Date.now(),
31102
+ exitCode: null,
31103
+ throughEditor: true,
31104
+ brokeOn: null,
31105
+ pickedUpPlaying: true
31106
+ };
31107
+ }
31079
31108
  adoptRecordedRun() {
31080
31109
  const record = readRunRecord();
31081
31110
  if (record === null || !this.couldBeOurs(record.projectPath)) {
@@ -31157,6 +31186,7 @@ class GodotServer {
31157
31186
  });
31158
31187
  }
31159
31188
  async handleWaitForRun(args) {
31189
+ await this.pickUpWhatTheEditorIsPlaying();
31160
31190
  const run = this.currentRun();
31161
31191
  if (!run) {
31162
31192
  return this.createErrorResponse(this.nothingOfOursIsRunning());
@@ -31171,6 +31201,7 @@ class GodotServer {
31171
31201
  return await this.handleGetDebugOutput(args, stillRunning(run) ? budgetMs : undefined);
31172
31202
  }
31173
31203
  async handleGetDebugOutput(args, waitedMs) {
31204
+ await this.pickUpWhatTheEditorIsPlaying();
31174
31205
  const run = this.currentRun();
31175
31206
  if (!run) {
31176
31207
  return this.createErrorResponse(this.nothingOfOursIsRunning());
@@ -31198,6 +31229,9 @@ class GodotServer {
31198
31229
  if (run.endedUnwatched === true) {
31199
31230
  notes.push("This run outlived the server that started it and is over now, so its exit code was never collected. Everything it printed is below, read back from its transcript.");
31200
31231
  }
31232
+ if (run.pickedUpPlaying === true) {
31233
+ notes.push("The editor was already playing this when this server reached it, so this is not the run from its start: what it printed before that went with the server that was listening then. It is the run the editor is holding now, which is the one the debug_* tools answer for.");
31234
+ }
31201
31235
  if (typeof run.endedHere === "string") {
31202
31236
  notes.push(`This run was ended here, by ${run.endedHere}.`);
31203
31237
  } else if (!stillRunning(run) && !run.throughEditor && run.exitCode !== null) {
@@ -31228,6 +31262,7 @@ class GodotServer {
31228
31262
  });
31229
31263
  }
31230
31264
  async handleStopProject() {
31265
+ await this.pickUpWhatTheEditorIsPlaying();
31231
31266
  const stopped = this.currentRun();
31232
31267
  if (!stopped) {
31233
31268
  return this.createErrorResponse(this.nothingOfOursIsRunning());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "0.13.6",
3
+ "version": "0.13.7",
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",